diff -ru openldap-2.4.23.orig/configure openldap-2.4.23/configure
--- openldap-2.4.23.orig/configure 2010-04-19 15:22:25.000000000 -0400
+++ openldap-2.4.23/configure 2011-02-04 03:32:32.851466637 -0500
@@ -1559,6 +1559,7 @@
--enable-aci enable per-object ACIs (experimental) no|yes|mod [no]
--enable-cleartext enable cleartext passwords [yes]
--enable-crypt enable crypt(3) passwords [no]
+ --enable-apr1 enable Apache MD5 passwords [no]
--enable-lmpasswd enable LAN Manager passwords [no]
--enable-spasswd enable (Cyrus) SASL password verification [no]
--enable-modules enable dynamic module support [no]
@@ -3191,6 +3192,29 @@
fi
# end --enable-crypt
+# OpenLDAP --enable-apr1
+
+ # Check whether --enable-apr1 was given.
+if test "${enable_apr1+set}" = set; then
+ enableval=$enable_apr1;
+ ol_arg=invalid
+ for ol_val in auto yes no ; do
+ if test "$enableval" = "$ol_val" ; then
+ ol_arg="$ol_val"
+ fi
+ done
+ if test "$ol_arg" = "invalid" ; then
+ { { echo "$as_me:$LINENO: error: bad value $enableval for --enable-apr1" >&5
+echo "$as_me: error: bad value $enableval for --enable-apr1" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ ol_enable_apr1="$ol_arg"
+
+else
+ ol_enable_apr1=no
+fi
+
+# end --enable-apr1
# OpenLDAP --enable-lmpasswd
# Check whether --enable-lmpasswd was given.
@@ -37943,6 +37967,13 @@
_ACEOF
fi
+if test "$ol_enable_apr1" != no ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define SLAPD_APR1 1
+_ACEOF
+
+fi
if test "$ol_link_spasswd" != no ; then
cat >>confdefs.h <<\_ACEOF
diff -ru openldap-2.4.23.orig/include/portable.hin openldap-2.4.23/include/portable.hin
--- openldap-2.4.23.orig/include/portable.hin 2010-04-19 15:22:30.000000000 -0400
+++ openldap-2.4.23/include/portable.hin 2011-02-04 03:32:32.851466637 -0500
@@ -927,6 +927,9 @@
/* define to support crypt(3) passwords */
#undef SLAPD_CRYPT
+/* define to support Apache MD5 passwords */
+#undef SLAPD_APR1
+
/* define to support DNS SRV backend */
#undef SLAPD_DNSSRV
diff -ru openldap-2.4.23.orig/libraries/liblutil/passwd.c openldap-2.4.23/libraries/liblutil/passwd.c
--- openldap-2.4.23.orig/libraries/liblutil/passwd.c 2010-04-13 16:23:06.000000000 -0400
+++ openldap-2.4.23/libraries/liblutil/passwd.c 2011-02-04 03:32:43.354767827 -0500
@@ -11,6 +11,15 @@
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
+ *
+ * A portion of the code is derived from code by Poul-Henning Kamp
+ * which is released under the following license:
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
*/
/*
@@ -92,6 +101,12 @@
static const unsigned char crypt64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
+#ifdef SLAPD_APR1
+static const unsigned char apr64[] =
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+static const unsigned char apr1magic[] = "$apr1$";
+#endif
+
#ifdef SLAPD_CRYPT
static char *salt_format = NULL;
static lutil_cryptfunc lutil_crypt;
@@ -122,6 +137,11 @@
static LUTIL_PASSWD_HASH_FUNC hash_smd5;
static LUTIL_PASSWD_HASH_FUNC hash_md5;
+#ifdef SLAPD_APR1
+#define APR1_SALT_SIZE 8
+static LUTIL_PASSWD_CHK_FUNC chk_apr1;
+static LUTIL_PASSWD_HASH_FUNC hash_apr1;
+#endif
#ifdef LUTIL_SHA1_BYTES
static LUTIL_PASSWD_CHK_FUNC chk_ssha1;
@@ -163,6 +183,10 @@
{ BER_BVC("{SMD5}"), chk_smd5, hash_smd5 },
{ BER_BVC("{MD5}"), chk_md5, hash_md5 },
+#ifdef SLAPD_APR1
+ { BER_BVC("{APR1}"), chk_apr1, hash_apr1 },
+#endif
+
#ifdef SLAPD_LMHASH
{ BER_BVC("{LANMAN}"), chk_lanman, hash_lanman },
#endif /* SLAPD_LMHASH */
@@ -656,6 +680,102 @@
return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
}
+#ifdef SLAPD_APR1
+static int chk_apr1(
+ const struct berval *sc,
+ const struct berval * passwd,
+ const struct berval * cred,
+ const char **text )
+{
+ lutil_MD5_CTX MD5context, MD5context1;
+ unsigned char MD5digest[LUTIL_MD5_BYTES];
+ int rc, sl, n;
+ unsigned char *orig_pass = NULL;
+
+ /* safety check */
+ if (LUTIL_BASE64_DECODE_LEN(passwd->bv_len) <= sizeof(MD5digest)) {
+ return LUTIL_PASSWD_ERR;
+ }
+
+ /* base64 un-encode password */
+ orig_pass = (unsigned char *) ber_memalloc( (size_t) (
+ LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
+
+ if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
+
+ rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
+
+ if (rc <= (int)(sizeof(MD5digest))) {
+ ber_memfree(orig_pass);
+ return LUTIL_PASSWD_ERR;
+ }
+
+ sl = rc - sizeof(MD5digest);
+
+ /* hash credentials using PHK MD5 and special magic */
+ lutil_MD5Init( &MD5context );
+ lutil_MD5Update( &MD5context,
+ (const unsigned char *) cred->bv_val, cred->bv_len );
+ lutil_MD5Update( &MD5context,
+ apr1magic, sizeof(apr1magic) - 1);
+ lutil_MD5Update( &MD5context,
+ &orig_pass[sizeof(MD5digest)], sl );
+ /* Inner hash */
+ lutil_MD5Init( &MD5context1 );
+ lutil_MD5Update( &MD5context1,
+ (const unsigned char *) cred->bv_val, cred->bv_len );
+ lutil_MD5Update( &MD5context1,
+ &orig_pass[sizeof(MD5digest)], sl );
+ lutil_MD5Update( &MD5context1,
+ (const unsigned char *) cred->bv_val, cred->bv_len );
+ lutil_MD5Final( MD5digest, &MD5context1 );
+ for( n = cred->bv_len; n > 0; n -= sizeof(MD5digest) ) {
+ lutil_MD5Update( &MD5context, MD5digest,
+ (n > sizeof(MD5digest) ? sizeof(MD5digest) : n) );
+ }
+ memset( MD5digest, 0, sizeof(MD5digest) );
+ for( n = cred->bv_len; n; n >>= 1 ) {
+ if( n & 1 ) {
+ lutil_MD5Update( &MD5context, MD5digest, 1 );
+ } else {
+ lutil_MD5Update( &MD5context, cred->bv_val, 1);
+ }
+ }
+ lutil_MD5Final( MD5digest, &MD5context );
+ for( n = 0; n < 1000; n++ ) {
+ lutil_MD5Init( &MD5context1 );
+ if( n & 1 ) {
+ lutil_MD5Update( &MD5context1,
+ (const unsigned char *) cred->bv_val, cred->bv_len );
+ } else {
+ lutil_MD5Update( &MD5context1,
+ MD5digest, sizeof(MD5digest) );
+ }
+ if( n % 3 ) {
+ lutil_MD5Update( &MD5context1,
+ &orig_pass[sizeof(MD5digest)], sl );
+ }
+ if( n % 7 ) {
+ lutil_MD5Update( &MD5context1,
+ (const unsigned char *) cred->bv_val, cred->bv_len );
+ }
+ if( n & 1 ) {
+ lutil_MD5Update( &MD5context1,
+ MD5digest, sizeof(MD5digest) );
+ } else {
+ lutil_MD5Update( &MD5context1,
+ (const unsigned char *) cred->bv_val, cred->bv_len );
+ }
+ lutil_MD5Final( MD5digest, &MD5context1 );
+ }
+
+ /* compare */
+ rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
+ ber_memfree(orig_pass);
+ return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
+}
+#endif
+
#ifdef SLAPD_LMHASH
#if defined(HAVE_OPENSSL)
@@ -1129,6 +1249,93 @@
;
}
+#ifdef SLAPD_APR1
+static int hash_apr1(
+ const struct berval *scheme,
+ const struct berval *passwd,
+ struct berval *hash,
+ const char **text )
+{
+ lutil_MD5_CTX MD5context, MD5context1;
+ unsigned char MD5digest[LUTIL_MD5_BYTES];
+ char saltdata[APR1_SALT_SIZE];
+ struct berval digest;
+ struct berval salt;
+ int n;
+
+ digest.bv_val = (char *) MD5digest;
+ digest.bv_len = sizeof(MD5digest);
+ salt.bv_val = saltdata;
+ salt.bv_len = sizeof(saltdata);
+
+ if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) {
+ return LUTIL_PASSWD_ERR;
+ }
+ for( n = 0; n < salt.bv_len; n++ ) {
+ salt.bv_val[n] = apr64[salt.bv_val[n] % (sizeof(apr64) - 1)];
+ }
+
+ /* hash credentials using PHK MD5 and special magic */
+ lutil_MD5Init( &MD5context );
+ lutil_MD5Update( &MD5context,
+ (const unsigned char *) passwd->bv_val, passwd->bv_len );
+ lutil_MD5Update( &MD5context,
+ apr1magic, sizeof(apr1magic) - 1);
+ lutil_MD5Update( &MD5context,
+ (const unsigned char *) salt.bv_val, salt.bv_len );
+ /* Inner hash */
+ lutil_MD5Init( &MD5context1 );
+ lutil_MD5Update( &MD5context1,
+ (const unsigned char *) passwd->bv_val, passwd->bv_len );
+ lutil_MD5Update( &MD5context1,
+ (const unsigned char *) salt.bv_val, salt.bv_len );
+ lutil_MD5Update( &MD5context1,
+ (const unsigned char *) passwd->bv_val, passwd->bv_len );
+ lutil_MD5Final( MD5digest, &MD5context1 );
+ for( n = passwd->bv_len; n > 0; n -= sizeof(MD5digest) ) {
+ lutil_MD5Update( &MD5context, MD5digest,
+ (n > sizeof(MD5digest) ? sizeof(MD5digest) : n) );
+ }
+ memset( MD5digest, 0, sizeof(MD5digest) );
+ for( n = passwd->bv_len; n; n >>= 1 ) {
+ if( n & 1 ) {
+ lutil_MD5Update( &MD5context, MD5digest, 1 );
+ } else {
+ lutil_MD5Update( &MD5context, passwd->bv_val, 1);
+ }
+ }
+ lutil_MD5Final( MD5digest, &MD5context );
+ for( n = 0; n < 1000; n++ ) {
+ lutil_MD5Init( &MD5context1 );
+ if( n & 1 ) {
+ lutil_MD5Update( &MD5context1,
+ (const unsigned char *) passwd->bv_val, passwd->bv_len );
+ } else {
+ lutil_MD5Update( &MD5context1,
+ MD5digest, sizeof(MD5digest) );
+ }
+ if( n % 3 ) {
+ lutil_MD5Update( &MD5context1,
+ (const unsigned char *) salt.bv_val, salt.bv_len );
+ }
+ if( n % 7 ) {
+ lutil_MD5Update( &MD5context1,
+ (const unsigned char *) passwd->bv_val, passwd->bv_len );
+ }
+ if( n & 1 ) {
+ lutil_MD5Update( &MD5context1,
+ MD5digest, sizeof(MD5digest) );
+ } else {
+ lutil_MD5Update( &MD5context1,
+ (const unsigned char *) passwd->bv_val, passwd->bv_len );
+ }
+ lutil_MD5Final( MD5digest, &MD5context1 );
+ }
+
+ return pw_string64( scheme, &digest, hash, &salt );
+}
+#endif
+
#ifdef SLAPD_LMHASH
static int hash_lanman(
const struct berval *scheme,