|
@@ -50,7 +50,7 @@
|
|
|
#include <sechash.h>
|
|
#include <sechash.h>
|
|
|
#endif /* NET_SSL */
|
|
#endif /* NET_SSL */
|
|
|
|
|
|
|
|
-#define SHA1_SALT_LENGTH 8 /* number of bytes of data in salt */
|
|
|
|
|
|
|
+#define SHA_SALT_LENGTH 8 /* number of bytes of data in salt */
|
|
|
#define NOT_FIRST_TIME (time_t)1 /* not the first logon */
|
|
#define NOT_FIRST_TIME (time_t)1 /* not the first logon */
|
|
|
|
|
|
|
|
static char *hasherrmsg = "pw_cmp: %s userPassword \"%s\" is the wrong length or is not properly encoded BASE64\n";
|
|
static char *hasherrmsg = "pw_cmp: %s userPassword \"%s\" is the wrong length or is not properly encoded BASE64\n";
|
|
@@ -62,21 +62,46 @@ static char *plugin_name = "NSPwdStoragePlugin";
|
|
|
* 8 bytes of salt plus the first 10 bytes of the SHA-1 digest.
|
|
* 8 bytes of salt plus the first 10 bytes of the SHA-1 digest.
|
|
|
* It's obsolescent now, but we still handle such stored values.
|
|
* It's obsolescent now, but we still handle such stored values.
|
|
|
*/
|
|
*/
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
int
|
|
int
|
|
|
-sha1_pw_cmp (char *userpwd, char *dbpwd )
|
|
|
|
|
|
|
+sha_pw_cmp (char *userpwd, char *dbpwd, unsigned int shaLen )
|
|
|
{
|
|
{
|
|
|
/*
|
|
/*
|
|
|
- * SHA1 passwords are stored in the database as SHA1_LENGTH bytes of
|
|
|
|
|
|
|
+ * SHA passwords are stored in the database as shaLen bytes of
|
|
|
* hash, followed by zero or more bytes of salt, all BASE64 encoded.
|
|
* hash, followed by zero or more bytes of salt, all BASE64 encoded.
|
|
|
*/
|
|
*/
|
|
|
int result = 1; /* failure */
|
|
int result = 1; /* failure */
|
|
|
- unsigned char userhash[SHA1_LENGTH];
|
|
|
|
|
- unsigned char quick_dbhash[SHA1_LENGTH + SHA1_SALT_LENGTH + 3];
|
|
|
|
|
|
|
+ unsigned char userhash[MAX_SHA_HASH_SIZE];
|
|
|
|
|
+ unsigned char quick_dbhash[MAX_SHA_HASH_SIZE + SHA_SALT_LENGTH + 3];
|
|
|
unsigned char *dbhash = quick_dbhash;
|
|
unsigned char *dbhash = quick_dbhash;
|
|
|
struct berval salt;
|
|
struct berval salt;
|
|
|
int hash_len; /* must be a signed valued -- see below */
|
|
int hash_len; /* must be a signed valued -- see below */
|
|
|
-
|
|
|
|
|
|
|
+ unsigned int secOID;
|
|
|
|
|
+ char *schemeName;
|
|
|
|
|
+
|
|
|
|
|
+ /* Determine which algorithm we're using */
|
|
|
|
|
+ switch (shaLen) {
|
|
|
|
|
+ case SHA1_LENGTH:
|
|
|
|
|
+ schemeName = SHA1_SCHEME_NAME;
|
|
|
|
|
+ secOID = SEC_OID_SHA1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case SHA256_LENGTH:
|
|
|
|
|
+ schemeName = SHA256_SCHEME_NAME;
|
|
|
|
|
+ secOID = SEC_OID_SHA256;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case SHA384_LENGTH:
|
|
|
|
|
+ schemeName = SHA384_SCHEME_NAME;
|
|
|
|
|
+ secOID = SEC_OID_SHA384;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case SHA512_LENGTH:
|
|
|
|
|
+ schemeName = SHA512_SCHEME_NAME;
|
|
|
|
|
+ secOID = SEC_OID_SHA512;
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ /* An unknown shaLen was passed in. We shouldn't get here. */
|
|
|
|
|
+ goto loser;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* Decode hash stored in database.
|
|
* Decode hash stored in database.
|
|
|
*
|
|
*
|
|
@@ -90,54 +115,137 @@ sha1_pw_cmp (char *userpwd, char *dbpwd )
|
|
|
if ( dbhash == NULL ) goto loser;
|
|
if ( dbhash == NULL ) goto loser;
|
|
|
}
|
|
}
|
|
|
hash_len = ldif_base64_decode( dbpwd, dbhash );
|
|
hash_len = ldif_base64_decode( dbpwd, dbhash );
|
|
|
- if ( hash_len >= SHA1_LENGTH ) {
|
|
|
|
|
- salt.bv_val = (void*)(dbhash + SHA1_LENGTH);
|
|
|
|
|
- salt.bv_len = hash_len - SHA1_LENGTH;
|
|
|
|
|
|
|
+ if ( hash_len >= shaLen ) {
|
|
|
|
|
+ salt.bv_val = (void*)(dbhash + shaLen);
|
|
|
|
|
+ salt.bv_len = hash_len - shaLen;
|
|
|
} else if ( hash_len == DS40B1_SALTED_SHA_LENGTH ) {
|
|
} else if ( hash_len == DS40B1_SALTED_SHA_LENGTH ) {
|
|
|
salt.bv_val = (void*)dbhash;
|
|
salt.bv_val = (void*)dbhash;
|
|
|
salt.bv_len = 8;
|
|
salt.bv_len = 8;
|
|
|
} else { /* unsupported, invalid BASE64 (hash_len < 0), or similar */
|
|
} else { /* unsupported, invalid BASE64 (hash_len < 0), or similar */
|
|
|
- slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, hasherrmsg, SHA1_SCHEME_NAME, dbpwd );
|
|
|
|
|
|
|
+ slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, hasherrmsg, schemeName, dbpwd );
|
|
|
goto loser;
|
|
goto loser;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- /* SHA1 hash the user's key */
|
|
|
|
|
- if ( sha1_salted_hash( userhash, userpwd, &salt ) != SECSuccess ) {
|
|
|
|
|
- slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "sha1_pw_cmp: SHA1_Hash() failed\n");
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /* hash the user's key */
|
|
|
|
|
+ if ( sha_salted_hash( userhash, userpwd, &salt, secOID ) != SECSuccess ) {
|
|
|
|
|
+ slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "sha_pw_cmp: sha_salted_hash() failed\n");
|
|
|
goto loser;
|
|
goto loser;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/* the proof is in the comparison... */
|
|
/* the proof is in the comparison... */
|
|
|
result = ( hash_len == DS40B1_SALTED_SHA_LENGTH ) ?
|
|
result = ( hash_len == DS40B1_SALTED_SHA_LENGTH ) ?
|
|
|
( memcmp( userhash, dbhash + 8, hash_len - 8 )) :
|
|
( memcmp( userhash, dbhash + 8, hash_len - 8 )) :
|
|
|
- ( memcmp( userhash, dbhash, SHA1_LENGTH ));
|
|
|
|
|
-
|
|
|
|
|
|
|
+ ( memcmp( userhash, dbhash, shaLen ));
|
|
|
|
|
+
|
|
|
loser:
|
|
loser:
|
|
|
if ( dbhash && dbhash != quick_dbhash ) slapi_ch_free( (void**)&dbhash );
|
|
if ( dbhash && dbhash != quick_dbhash ) slapi_ch_free( (void**)&dbhash );
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
char *
|
|
char *
|
|
|
-sha1_pw_enc( char *pwd )
|
|
|
|
|
|
|
+sha_pw_enc( char *pwd, unsigned int shaLen )
|
|
|
{
|
|
{
|
|
|
- unsigned char hash[ SHA1_LENGTH ];
|
|
|
|
|
|
|
+ unsigned char hash[MAX_SHA_HASH_SIZE];
|
|
|
char *enc;
|
|
char *enc;
|
|
|
-
|
|
|
|
|
- /* SHA1 hash the user's key */
|
|
|
|
|
- if ( sha1_salted_hash( hash, pwd, NULL ) != SECSuccess ) {
|
|
|
|
|
|
|
+ char *schemeName;
|
|
|
|
|
+ unsigned int schemeNameLen;
|
|
|
|
|
+ unsigned int secOID;
|
|
|
|
|
+
|
|
|
|
|
+ /* Determine which algorithm we're using */
|
|
|
|
|
+ switch (shaLen) {
|
|
|
|
|
+ case SHA1_LENGTH:
|
|
|
|
|
+ schemeName = SHA1_SCHEME_NAME;
|
|
|
|
|
+ schemeNameLen = SHA1_NAME_LEN;
|
|
|
|
|
+ secOID = SEC_OID_SHA1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case SHA256_LENGTH:
|
|
|
|
|
+ schemeName = SHA256_SCHEME_NAME;
|
|
|
|
|
+ schemeNameLen = SHA256_NAME_LEN;
|
|
|
|
|
+ secOID = SEC_OID_SHA256;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case SHA384_LENGTH:
|
|
|
|
|
+ schemeName = SHA384_SCHEME_NAME;
|
|
|
|
|
+ schemeNameLen = SHA384_NAME_LEN;
|
|
|
|
|
+ secOID = SEC_OID_SHA384;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case SHA512_LENGTH:
|
|
|
|
|
+ schemeName = SHA512_SCHEME_NAME;
|
|
|
|
|
+ schemeNameLen = SHA512_NAME_LEN;
|
|
|
|
|
+ secOID = SEC_OID_SHA512;
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ /* An unknown shaLen was passed in. We shouldn't get here. */
|
|
|
|
|
+ return( NULL );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* hash the user's key */
|
|
|
|
|
+ if ( sha_salted_hash( hash, pwd, NULL, secOID ) != SECSuccess ) {
|
|
|
return( NULL );
|
|
return( NULL );
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- if (( enc = slapi_ch_malloc( 3 + SHA1_NAME_LEN +
|
|
|
|
|
- LDIF_BASE64_LEN( SHA1_LENGTH ))) == NULL ) {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if (( enc = slapi_ch_malloc( 3 + schemeNameLen +
|
|
|
|
|
+ LDIF_BASE64_LEN( shaLen ))) == NULL ) {
|
|
|
return( NULL );
|
|
return( NULL );
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- sprintf( enc, "%c%s%c", PWD_HASH_PREFIX_START, SHA1_SCHEME_NAME,
|
|
|
|
|
|
|
+
|
|
|
|
|
+ sprintf( enc, "%c%s%c", PWD_HASH_PREFIX_START, schemeName,
|
|
|
PWD_HASH_PREFIX_END );
|
|
PWD_HASH_PREFIX_END );
|
|
|
- (void)ldif_base64_encode( hash, enc + 2 + SHA1_NAME_LEN,
|
|
|
|
|
- SHA1_LENGTH, -1 );
|
|
|
|
|
-
|
|
|
|
|
|
|
+ (void)ldif_base64_encode( hash, enc + 2 + schemeNameLen,
|
|
|
|
|
+ shaLen, -1 );
|
|
|
|
|
+
|
|
|
return( enc );
|
|
return( enc );
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+ * Wrapper password comparison functions
|
|
|
|
|
+ */
|
|
|
|
|
+int
|
|
|
|
|
+sha1_pw_cmp (char *userpwd, char *dbpwd )
|
|
|
|
|
+{
|
|
|
|
|
+ return sha_pw_cmp( userpwd, dbpwd, SHA1_LENGTH );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int
|
|
|
|
|
+sha256_pw_cmp (char *userpwd, char *dbpwd )
|
|
|
|
|
+{
|
|
|
|
|
+ return sha_pw_cmp( userpwd, dbpwd, SHA256_LENGTH );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int
|
|
|
|
|
+sha384_pw_cmp (char *userpwd, char *dbpwd )
|
|
|
|
|
+{
|
|
|
|
|
+ return sha_pw_cmp( userpwd, dbpwd, SHA384_LENGTH );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int
|
|
|
|
|
+sha512_pw_cmp (char *userpwd, char *dbpwd )
|
|
|
|
|
+{
|
|
|
|
|
+ return sha_pw_cmp( userpwd, dbpwd, SHA512_LENGTH );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+ * Wrapper password encryption functions
|
|
|
|
|
+ */
|
|
|
|
|
+char *
|
|
|
|
|
+sha1_pw_enc( char *pwd )
|
|
|
|
|
+{
|
|
|
|
|
+ return sha_pw_enc( pwd, SHA1_LENGTH );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+char *
|
|
|
|
|
+sha256_pw_enc( char *pwd )
|
|
|
|
|
+{
|
|
|
|
|
+ return sha_pw_enc( pwd, SHA256_LENGTH );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+char *
|
|
|
|
|
+sha384_pw_enc( char *pwd )
|
|
|
|
|
+{
|
|
|
|
|
+ return sha_pw_enc( pwd, SHA384_LENGTH );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+char *
|
|
|
|
|
+sha512_pw_enc( char *pwd )
|
|
|
|
|
+{
|
|
|
|
|
+ return sha_pw_enc( pwd, SHA512_LENGTH );
|
|
|
|
|
+}
|