Yhteiset alihakemistot: a/debian ja b/debian
diff --unified a/DIRECTIVES b/DIRECTIVES
--- a/DIRECTIVES	2013-01-12 15:20:27.123647765 +0200
+++ b/DIRECTIVES	2013-01-12 15:18:19.131648782 +0200
@@ -210,7 +210,21 @@
 	Apache
 		The hashing scheme used by htpasswd utility. Compatible to
 		authuserfile.
-		
+               
+    PHPass
+        Portable PHP password hashing framework
+        http://www.openwall.com/phpass/
+        
+        PHPass is a public domain password hashing scheme used 
+        by some PHP-based software (eg. Wordpress 3, phpBB3).
+        It is similar in spirit to a more common bcrypt for C
+        applications, but PHPass can be implemented in pure PHP using
+        only primitives that are available in all PHP versions.
+
+        The basic idea is that the number of iterations of
+        the cryptographic primitive can scale to match
+        the increases in computing power.
+
 Auth_MySQL_Encrypted_Passwords <on/off> (DEPRECATED)
 	Equivalent to: Auth_MySQL_Encryption_Types Crypt_DES
 	Only used if ...Encryption_Types is not set.  Defaults to 'on'.  If
diff --unified a/mod_auth_mysql.c b/mod_auth_mysql.c
--- a/mod_auth_mysql.c	2013-01-12 15:20:26.000000000 +0200
+++ b/mod_auth_mysql.c	2013-01-12 15:18:19.135648782 +0200
@@ -105,6 +105,7 @@
 #endif
 #define SHA1SUM_ENCRYPTION_FLAG		1<<6
 #define APACHE_ENCRYPTION_FLAG		1<<7
+#define PHPASS_ENCRYPTION_FLAG		1<<8
 
 /* from include/sha1.h from the mysql-server source distribution */
 #define SHA1_HASH_SIZE 20 /* Hash size in bytes */
@@ -250,6 +251,150 @@
 #endif
 }
 
+#ifdef APACHE2
+static int phpass_iteration(char *prefix, int prefix_length, const char *passwd, int escape_html_chars, char* hash_out)
+#else
+static int phpass_iteration(char *prefix, int prefix_length, const char *passwd, int escape_html_chars, char* hash_out)
+#endif
+{
+	int char_index;
+	int piece_length;
+	const char *piece;
+
+	/* Initialize and feed prefix. */
+#ifdef APACHE2
+	apr_md5_ctx_t ct;
+	apr_md5_init(&ct);
+	apr_md5_update(&ct, prefix, prefix_length);
+#else
+	AP_MD5_CTX ct;
+	ap_MD5Init(&ct);
+	ap_MD5Update(&ct, prefix, prefix_length);
+#endif
+
+	if (escape_html_chars) {
+		/* PhpBB3 hash has some special characters escaped.
+		Feed the password to MD5 character by characer
+		and escape as we go. */
+		for (char_index = 0; passwd[char_index] != '\0'; char_index++)
+		{
+
+			switch(passwd[char_index])
+			{
+			case '<':
+				piece = "&lt;";
+				piece_length = 4;
+				break;
+			case '>':
+				piece = "&gt;";
+				piece_length = 4;
+				break;
+			case '"':
+				piece = "&quot;";
+				piece_length = 6;
+				break;
+			case '&':
+				piece = "&amp;";
+				piece_length = 5;
+				break;
+			default:
+				piece = &passwd[char_index];
+				piece_length = 1;
+				break;
+			}
+#ifdef APACHE2
+				apr_md5_update(&ct, piece, piece_length);
+#else
+				ap_MD5Update(&ct, piece, piece_length);
+#endif
+		}
+	} else {
+#ifdef APACHE2
+		apr_md5_update(&ct, passwd, strlen(passwd));
+#else
+		ap_MD5Update(&ct, passwd, strlen(passwd));
+#endif
+	}
+
+#ifdef APACHE2
+	apr_md5_final(hash_out, &ct);
+#else
+	ap_MD5Final(hash_out, &ct);
+#endif
+}
+
+static int check_phpass_encryption(const char *passwd, char *enc_passwd)
+{
+#ifdef APACHE2
+	char hash[APR_MD5_DIGESTSIZE];
+#else
+	char hash[AP_MD5_DIGESTSIZE];
+#endif
+	int iterations;
+	int iteration;
+	int escape_html_chars = 0;
+
+	char encoded_hash[22];
+	int i;
+	char *base64_digits =
+		"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+	int high_index;
+	unsigned char high, low;
+	int value;
+
+	if (strlen(enc_passwd) < 4 + 8 + 22) {
+		return 0; /* too short for PHPass. */
+	}
+
+	if (!strncmp(enc_passwd, "*0", 2)) {
+		return 0; /* disabled password */
+	}
+
+	/* Check hash type. Standard PHPass uses "$P$" as identifier. */
+	if (strncmp(enc_passwd, "$P$", 3)) {
+		if (strncmp(enc_passwd, "$H$", 3)) {
+			return 0; /* Unknown identifier. */
+		} else {
+			/* PhpBB3 version uses $H$ as identifier
+			and HTML escapes the password before hashing. */
+			escape_html_chars = 1;
+		}
+	}
+
+	if (enc_passwd[3] >= '5' && enc_passwd[3] <= '9') {
+		iterations = 1 << ((enc_passwd[3] - '5') + 7);
+	} else if (enc_passwd[3] >= 'A' && enc_passwd[3] <= 'S') {
+		iterations = 1 << ((enc_passwd[3] - 'A') + 12);
+	} else {
+		return 0; /* invalid iteration count */
+	}
+
+	/* Initialize iteration. Salt is the first prefix. */
+	phpass_iteration(&enc_passwd[4], 8, passwd, escape_html_chars, hash);
+
+	for (iteration = 0; iteration < iterations; iteration++)
+	{
+		/* Each iteration takes the previous hash as prefix. */
+		phpass_iteration(hash, sizeof(hash), passwd, escape_html_chars, hash);
+	}
+
+	/* PHPass uses a variant of base64 encoding where the input bits
+	   are processed in different order and no padding is used. */
+	for (i = 0; i < sizeof(encoded_hash); i++)
+	{
+		high_index = (i / 4) * 3 + (i % 4);
+		low = (i % 4 != 0) ? (unsigned char) hash[high_index - 1] : 0;
+		high = (i % 4 != 3 && high_index < sizeof(hash))
+			? (unsigned char) hash[high_index] : 0;
+
+		value = ( (high << (2 * (i % 4))) | (low >> (8 - 2 * (i % 4))) ) & 0x3f;
+
+		encoded_hash[i] = base64_digits[value];
+	}
+
+	return (!strncmp(encoded_hash, &enc_passwd[4 + 8], sizeof(encoded_hash)));
+}
+
 typedef struct {
 	char *name;
 	int (*check_function)(const char *passwd, char *enc_passwd);
@@ -269,6 +414,7 @@
 	{ "PHP_MD5",		check_PHP_MD5_encryption,		PHP_MD5_ENCRYPTION_FLAG	},
 	{ "SHA1Sum",	check_SHA1Sum_encryption, SHA1SUM_ENCRYPTION_FLAG},
 	{ "Apache",		check_apache_encryption,		APACHE_ENCRYPTION_FLAG  },
+	{ "PHPass",		check_phpass_encryption,		PHPASS_ENCRYPTION_FLAG  },
 	/* add additional encryption types below */
 	{ NULL,			NULL,					0 }
 };
