From ba9722180241b4a97e611f1e52c1fd53c86b1f5b Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Wed, 26 Apr 2017 10:09:26 -0400 Subject: [PATCH] Issue 49225 - Add additional CRYPT password storage schemes Description: Add the crypt md5, sha256, and sha512 hashing algorithms. We only need a special encoding function for each type, as the current crypt compare function works for all formats. https://pagure.io/389-ds-base/issue/49225 Reviewed by: firstyear(Thanks!) --- dirsrvtests/tests/suites/password/pwd_algo_test.py | 5 +- ldap/ldif/template-dse.ldif.in | 27 ++++++++ ldap/servers/plugins/pwdstorage/crypt_pwd.c | 65 +++++++++++++++--- ldap/servers/plugins/pwdstorage/pwd_init.c | 78 ++++++++++++++++++++++ ldap/servers/plugins/pwdstorage/pwdstorage.h | 3 + 5 files changed, 167 insertions(+), 11 deletions(-) diff --git a/dirsrvtests/tests/suites/password/pwd_algo_test.py b/dirsrvtests/tests/suites/password/pwd_algo_test.py index b3f03fe..d997728 100644 --- a/dirsrvtests/tests/suites/password/pwd_algo_test.py +++ b/dirsrvtests/tests/suites/password/pwd_algo_test.py @@ -54,7 +54,7 @@ def _test_algo(inst, algo_name): assert (not _test_bind(inst, 'Alsowrong')) # Bind with a subset password, should fail assert (not _test_bind(inst, 'Secret')) - if algo_name != 'CRYPT': + if not algo_name.startswith('CRYPT'): # Bind with a subset password that is 1 char shorter, to detect off by 1 in clear assert (not _test_bind(inst, 'Secret12')) # Bind with a superset password, should fail @@ -71,6 +71,9 @@ def test_pwd_algo_test(topology_st): for algo in ('CLEAR', 'CRYPT', + 'CRYPT-MD5', + 'CRYPT-SHA256', + 'CRYPT-SHA512', 'MD5', 'SHA', 'SHA256', diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in index c78f3b9..cf3ed1b 100644 --- a/ldap/ldif/template-dse.ldif.in +++ b/ldap/ldif/template-dse.ldif.in @@ -131,6 +131,33 @@ nsslapd-plugininitfunc: crypt_pwd_storage_scheme_init nsslapd-plugintype: pwdstoragescheme nsslapd-pluginenabled: on +dn: cn=CRYPT-MD5,cn=Password Storage Schemes,cn=plugins,cn=config +objectclass: top +objectclass: nsSlapdPlugin +cn: CRYPT-MD5 +nsslapd-pluginpath: libpwdstorage-plugin +nsslapd-plugininitfunc: crypt_md5_pwd_storage_scheme_init +nsslapd-plugintype: pwdstoragescheme +nsslapd-pluginenabled: on + +dn: cn=CRYPT-SHA256,cn=Password Storage Schemes,cn=plugins,cn=config +objectclass: top +objectclass: nsSlapdPlugin +cn: CRYPT-SHA256 +nsslapd-pluginpath: libpwdstorage-plugin +nsslapd-plugininitfunc: crypt_sha256_pwd_storage_scheme_init +nsslapd-plugintype: pwdstoragescheme +nsslapd-pluginenabled: on + +dn: cn=CRYPT-SHA512,cn=Password Storage Schemes,cn=plugins,cn=config +objectclass: top +objectclass: nsSlapdPlugin +cn: CRYPT-SHA512 +nsslapd-pluginpath: libpwdstorage-plugin +nsslapd-plugininitfunc: crypt_sha512_pwd_storage_scheme_init +nsslapd-plugintype: pwdstoragescheme +nsslapd-pluginenabled: on + dn: cn=MD5,cn=Password Storage Schemes,cn=plugins,cn=config objectclass: top objectclass: nsSlapdPlugin diff --git a/ldap/servers/plugins/pwdstorage/crypt_pwd.c b/ldap/servers/plugins/pwdstorage/crypt_pwd.c index dfd5af9..03b442a 100644 --- a/ldap/servers/plugins/pwdstorage/crypt_pwd.c +++ b/ldap/servers/plugins/pwdstorage/crypt_pwd.c @@ -31,25 +31,34 @@ #include "pwdstorage.h" -static PRLock *cryptlock; /* Some implementations of crypt are not thread safe. ie. ours & Irix */ +static PRLock *cryptlock = NULL; /* Some implementations of crypt are not thread safe. ie. ours & Irix */ /* characters used in crypt encoding */ static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +#define CRYPT_UNIX 0 +#define CRYPT_MD5 1 +#define CRYPT_SHA256 2 +#define CRYPT_SHA512 3 int crypt_start(Slapi_PBlock *pb __attribute__((unused))) { - cryptlock = PR_NewLock(); + if (!cryptlock) { + cryptlock = PR_NewLock(); + } return 0; } int crypt_close(Slapi_PBlock *pb __attribute__((unused))) { - PR_DestroyLock(cryptlock); + if (cryptlock) { + PR_DestroyLock(cryptlock); + cryptlock = NULL; + } return 0; } @@ -70,11 +79,12 @@ crypt_pw_cmp( const char *userpwd, const char *dbpwd ) return rc; } -char * -crypt_pw_enc( const char *pwd ) -{ - char *cry, salt[3]; - char *enc= NULL; +static char* +crypt_pw_enc_by_hash( const char *pwd, int hash_algo){ + char salt[3]; + char *algo_salt = NULL; + char *cry; + char *enc = NULL; long v; static unsigned int seed = 0; @@ -89,13 +99,48 @@ crypt_pw_enc( const char *pwd ) salt[1] = itoa64[v & 0x3f]; salt[2] = '\0'; + /* Prepare our salt based on the hashing algorithm */ + if (hash_algo == CRYPT_UNIX) { + algo_salt = strdup(salt); + } else if (hash_algo == CRYPT_MD5) { + algo_salt = slapi_ch_smprintf("$1$%s", salt); + } else if (hash_algo == CRYPT_SHA256) { + algo_salt = slapi_ch_smprintf("$5$%s", salt); + } else if (hash_algo == CRYPT_SHA512) { + algo_salt = slapi_ch_smprintf("$6$%s", salt); + } + PR_Lock(cryptlock); - cry = crypt( pwd, salt ); + cry = crypt( pwd, algo_salt ); if ( cry != NULL ) { enc = slapi_ch_smprintf("%c%s%c%s", PWD_HASH_PREFIX_START, CRYPT_SCHEME_NAME, PWD_HASH_PREFIX_END, cry ); - } + } PR_Unlock(cryptlock); + slapi_ch_free_string(&algo_salt); + return( enc ); + +} + +char * +crypt_pw_enc( const char *pwd ) +{ + return crypt_pw_enc_by_hash(pwd, CRYPT_UNIX); } +char * +crypt_pw_md5_enc( const char *pwd ) +{ + return crypt_pw_enc_by_hash(pwd, CRYPT_MD5); +} +char * +crypt_pw_sha256_enc( const char *pwd ) +{ + return crypt_pw_enc_by_hash(pwd, CRYPT_SHA256); +} +char * +crypt_pw_sha512_enc( const char *pwd ) +{ + return crypt_pw_enc_by_hash(pwd, CRYPT_SHA512); +} diff --git a/ldap/servers/plugins/pwdstorage/pwd_init.c b/ldap/servers/plugins/pwdstorage/pwd_init.c index 16d2f32..ff839f7 100644 --- a/ldap/servers/plugins/pwdstorage/pwd_init.c +++ b/ldap/servers/plugins/pwdstorage/pwd_init.c @@ -36,6 +36,12 @@ static Slapi_PluginDesc ssha512_pdesc = { "ssha512-password-storage-scheme", VEN static Slapi_PluginDesc crypt_pdesc = { "crypt-password-storage-scheme", VENDOR, DS_PACKAGE_VERSION, "Unix crypt algorithm (CRYPT)" }; +static Slapi_PluginDesc crypt_md5_pdesc = { "crypt-md5-password-storage-scheme", VENDOR, DS_PACKAGE_VERSION, "Unix crypt algorithm (CRYPT-MD5)" }; + +static Slapi_PluginDesc crypt_sha256_pdesc = { "crypt-sha256-password-storage-scheme", VENDOR, DS_PACKAGE_VERSION, "Unix crypt algorithm (CRYPT-SHA256)" }; + +static Slapi_PluginDesc crypt_sha512_pdesc = { "crypt-sha512-password-storage-scheme", VENDOR, DS_PACKAGE_VERSION, "Unix crypt algorithm (CRYPT-SHA512)" }; + static Slapi_PluginDesc clear_pdesc = { "clear-password-storage-scheme", VENDOR, DS_PACKAGE_VERSION, "No encryption (CLEAR)" }; static Slapi_PluginDesc ns_mta_md5_pdesc = { "NS-MTA-MD5-password-storage-scheme", VENDOR, DS_PACKAGE_VERSION, "Netscape MD5 (NS-MTA-MD5)" }; @@ -253,6 +259,78 @@ crypt_pwd_storage_scheme_init( Slapi_PBlock *pb ) } int +crypt_md5_pwd_storage_scheme_init( Slapi_PBlock *pb ) +{ + int rc; + + slapi_log_err(SLAPI_LOG_PLUGIN, plugin_name, "=> crypt_md5_pwd_storage_scheme_init\n" ); + + rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, + (void *) SLAPI_PLUGIN_VERSION_01 ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, + (void *)&crypt_md5_pdesc ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN, (void*)&crypt_start); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN, (void*)&crypt_close); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_ENC_FN, + (void *) crypt_pw_md5_enc ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_CMP_FN, + (void *) crypt_pw_cmp ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_NAME, + "CRYPT-MD5" ); + + slapi_log_err(SLAPI_LOG_PLUGIN, plugin_name, "<= crypt_md5_pwd_storage_scheme_init %d\n\n", rc ); + return( rc ); +} + +int +crypt_sha256_pwd_storage_scheme_init( Slapi_PBlock *pb ) +{ + int rc; + + slapi_log_err(SLAPI_LOG_PLUGIN, plugin_name, "=> crypt_sha256_pwd_storage_scheme_init\n" ); + + rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, + (void *) SLAPI_PLUGIN_VERSION_01 ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, + (void *)&crypt_sha256_pdesc ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN, (void*)&crypt_start); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN, (void*)&crypt_close); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_ENC_FN, + (void *) crypt_pw_sha256_enc ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_CMP_FN, + (void *) crypt_pw_cmp ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_NAME, + "CRYPT-SHA256" ); + + slapi_log_err(SLAPI_LOG_PLUGIN, plugin_name, "<= crypt_sha256_pwd_storage_scheme_init %d\n\n", rc ); + return( rc ); +} + +int +crypt_sha512_pwd_storage_scheme_init( Slapi_PBlock *pb ) +{ + int rc; + + slapi_log_err(SLAPI_LOG_PLUGIN, plugin_name, "=> crypt_sha512_pwd_storage_scheme_init\n" ); + + rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, + (void *) SLAPI_PLUGIN_VERSION_01 ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, + (void *)&crypt_sha512_pdesc ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN, (void*)&crypt_start); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN, (void*)&crypt_close); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_ENC_FN, + (void *) crypt_pw_sha512_enc ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_CMP_FN, + (void *) crypt_pw_cmp ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_NAME, + "CRYPT-SHA512" ); + + slapi_log_err(SLAPI_LOG_PLUGIN, plugin_name, "<= crypt_sha512_pwd_storage_scheme_init %d\n\n", rc ); + return( rc ); +} + +int clear_pwd_storage_scheme_init( Slapi_PBlock *pb ) { int rc; diff --git a/ldap/servers/plugins/pwdstorage/pwdstorage.h b/ldap/servers/plugins/pwdstorage/pwdstorage.h index 2909998..b41bb47 100644 --- a/ldap/servers/plugins/pwdstorage/pwdstorage.h +++ b/ldap/servers/plugins/pwdstorage/pwdstorage.h @@ -78,6 +78,9 @@ int crypt_start(Slapi_PBlock *pb); int crypt_close(Slapi_PBlock *pb); int crypt_pw_cmp( const char *userpwd, const char *dbpwd ); char *crypt_pw_enc( const char *pwd ); +char *crypt_pw_md5_enc( const char *pwd ); +char *crypt_pw_sha256_enc( const char *pwd ); +char *crypt_pw_sha512_enc( const char *pwd ); int ns_mta_md5_pw_cmp( const char *userpwd, const char *dbpwd ); int md5_pw_cmp( const char *userpwd, const char *dbpwd ); char *md5_pw_enc( const char *pwd ); -- 2.9.3