From 8031d13eb7d0633f522cfae4fd52d4ef24ce437d Mon Sep 17 00:00:00 2001
From: Quanah Gibson-Mount <quanah@openldap.org>
Date: Thu, 15 Apr 2010 20:40:14 +0000
Subject: [PATCH] ITS#6433

---
 CHANGES                                       |   3 +-
 contrib/slapd-modules/passwd/sha2/README      |  13 +-
 .../slapd-modules/passwd/sha2/slapd-sha2.c    | 128 +++++++++++++++++-
 3 files changed, 139 insertions(+), 5 deletions(-)

diff --git a/CHANGES b/CHANGES
index dc387d7c06..ab09f147bb 100644
--- a/CHANGES
+++ b/CHANGES
@@ -19,7 +19,8 @@ OpenLDAP 2.4.22 Engineering
 	Fixed slapo-rwm olcRwmMap handling (ITS#6436)
 	Fixed slapo-rwm REP_ENTRY flag handling (ITS#5340,ITS#6423)
 	Fixed slapo-syncprov memory leak (ITS#6459)
-	Fixed slapo-valsort REP_ENTRY flag handling (ITS#5340,ITS#6423)
+	Fixed slapo-valsort REP_ENTRY flag handling (ITS#5340,ITS#6423)	
+	Fixed contrib/sha2 adds mechs for more hashes (ITS#6433)
 	Documentation
 		admin24 avoid explicity moduleload statements (ITS#6486)
 
diff --git a/contrib/slapd-modules/passwd/sha2/README b/contrib/slapd-modules/passwd/sha2/README
index 7d1ef3cca0..d6eebfb4ba 100644
--- a/contrib/slapd-modules/passwd/sha2/README
+++ b/contrib/slapd-modules/passwd/sha2/README
@@ -37,7 +37,18 @@ moduleload ...path/to/slapd-sha2.so
 
 5) Restart slapd.
 
-The {SHA512} scheme should now be recognised.
+
+Configuring
+-----------
+
+The {SHA256}, {SHA384} and {SHA512} password schemes should now be recognised.
+
+You can also tell OpenLDAP to use one of these new schemes when processing LDAP
+Password Modify Extended Operations, thanks to the password-hash option in
+slapd.conf. For example:
+
+password-hash	{SHA256}
+
 
 Testing
 -------
diff --git a/contrib/slapd-modules/passwd/sha2/slapd-sha2.c b/contrib/slapd-modules/passwd/sha2/slapd-sha2.c
index b06a301b29..4d49b3c718 100644
--- a/contrib/slapd-modules/passwd/sha2/slapd-sha2.c
+++ b/contrib/slapd-modules/passwd/sha2/slapd-sha2.c
@@ -15,6 +15,8 @@
 /* ACKNOWLEDGEMENT:
  * This work was initially developed by Jeff Turner for inclusion
  * in OpenLDAP Software.
+ *
+ * Hash methods for passwords generation added by Cédric Delfosse.
  */
 
 #include <lber.h>
@@ -30,6 +32,63 @@
 #include <stdio.h>
 #endif
 
+/* pw_string64 function taken from libraries/liblutil/passwd.c */
+static int pw_string64(
+	const struct berval *sc,
+	const struct berval *hash,
+	struct berval *b64,
+	const struct berval *salt )
+{
+	int rc;
+	struct berval string;
+	size_t b64len;
+
+	if( salt ) {
+		/* need to base64 combined string */
+		string.bv_len = hash->bv_len + salt->bv_len;
+		string.bv_val = ber_memalloc( string.bv_len + 1 );
+
+		if( string.bv_val == NULL ) {
+			return LUTIL_PASSWD_ERR;
+		}
+
+		AC_MEMCPY( string.bv_val, hash->bv_val,
+			hash->bv_len );
+		AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val,
+			salt->bv_len );
+		string.bv_val[string.bv_len] = '\0';
+
+	} else {
+		string = *hash;
+	}
+
+	b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1;
+	b64->bv_len = b64len + sc->bv_len;
+	b64->bv_val = ber_memalloc( b64->bv_len + 1 );
+
+	if( b64->bv_val == NULL ) {
+		if( salt ) ber_memfree( string.bv_val );
+		return LUTIL_PASSWD_ERR;
+	}
+
+	AC_MEMCPY(b64->bv_val, sc->bv_val, sc->bv_len);
+
+	rc = lutil_b64_ntop(
+		(unsigned char *) string.bv_val, string.bv_len,
+		&b64->bv_val[sc->bv_len], b64len );
+
+	if( salt ) ber_memfree( string.bv_val );
+	
+	if( rc < 0 ) {
+		return LUTIL_PASSWD_ERR;
+	}
+
+	/* recompute length */
+	b64->bv_len = sc->bv_len + rc;
+	assert( strlen(b64->bv_val) == b64->bv_len );
+	return LUTIL_PASSWD_OK;
+}
+
 char * sha256_hex_hash(const char * passwd) {
 
 	SHA256_CTX ct;
@@ -94,6 +153,69 @@ char * sha512_hex_hash(const char * passwd) {
 	return real_hash;
 }
 
+static int hash_sha256(
+	const struct berval *scheme,
+	const struct berval *passwd,
+	struct berval *hash,
+	const char **text )
+{
+	SHA256_CTX ct;
+	unsigned char hash256[SHA256_DIGEST_LENGTH];
+
+	SHA256_Init(&ct);
+	SHA256_Update(&ct, (const uint8_t*)passwd->bv_val, passwd->bv_len);
+	SHA256_Final(hash256, &ct);
+
+	struct berval digest;
+	digest.bv_val = (char *) hash256;
+	digest.bv_len = sizeof(hash256);
+
+	return pw_string64(scheme, &digest, hash, NULL);
+}
+
+static int hash_sha384(
+	const struct berval *scheme,
+	const struct berval *passwd,
+	struct berval *hash,
+	const char **text )
+{
+	SHA384_CTX ct;
+	unsigned char hash384[SHA384_DIGEST_LENGTH];
+
+#ifdef SLAPD_SHA2_DEBUG
+	fprintf(stderr, "hashing password\n");
+#endif
+	SHA384_Init(&ct);
+	SHA384_Update(&ct, (const uint8_t*)passwd->bv_val, passwd->bv_len);
+	SHA384_Final(hash384, &ct);
+
+	struct berval digest;
+	digest.bv_val = (char *) hash384;
+	digest.bv_len = sizeof(hash384);
+
+	return pw_string64(scheme, &digest, hash, NULL);
+}
+
+static int hash_sha512(
+	const struct berval *scheme,
+	const struct berval *passwd,
+	struct berval *hash,
+	const char **text )
+{
+	SHA512_CTX ct;
+	unsigned char hash512[SHA512_DIGEST_LENGTH];
+
+	SHA512_Init(&ct);
+	SHA512_Update(&ct, (const uint8_t*)passwd->bv_val, passwd->bv_len);
+	SHA512_Final(hash512, &ct);
+
+	struct berval digest;
+	digest.bv_val = (char *) hash512;
+	digest.bv_len = sizeof(hash512);
+
+	return pw_string64(scheme, &digest, hash, NULL);
+}
+
 static int chk_sha256(
 	const struct berval *scheme, // Scheme of hashed reference password
 	const struct berval *passwd, // Hashed reference password to check against
@@ -150,10 +272,10 @@ const struct berval sha512scheme = BER_BVC("{SHA512}");
 
 int init_module(int argc, char *argv[]) {
 	int result = 0;
-	result = lutil_passwd_add( (struct berval *)&sha256scheme, chk_sha256, NULL );
+	result = lutil_passwd_add( (struct berval *)&sha256scheme, chk_sha256, hash_sha256 );
 	if (result != 0) return result;
-	result = lutil_passwd_add( (struct berval *)&sha384scheme, chk_sha384, NULL );
+	result = lutil_passwd_add( (struct berval *)&sha384scheme, chk_sha384, hash_sha384 );
 	if (result != 0) return result;
-	result = lutil_passwd_add( (struct berval *)&sha512scheme, chk_sha512, NULL );
+	result = lutil_passwd_add( (struct berval *)&sha512scheme, chk_sha512, hash_sha512 );
 	return result;
 }
-- 
GitLab