diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index c1902126a72..7a7114c1caa 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -51,6 +51,7 @@ #include "auth/common_auth.h" #include "lib/messaging/messaging.h" #include "lib/param/loadparm.h" +#include "lib/util/util_crypt.h" #include "lib/crypto/gnutls_helpers.h" #include @@ -1592,16 +1593,11 @@ static int setup_primary_userPassword_hash( struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module); const char *salt = NULL; /* Randomly generated salt */ const char *cmd = NULL; /* command passed to crypt */ - const char *hash = NULL; /* password hash generated by crypt */ int algorithm = 0; /* crypt hash algorithm number */ int rounds = 0; /* The number of hash rounds */ + int ret; DATA_BLOB *hash_blob = NULL; TALLOC_CTX *frame = talloc_stackframe(); -#if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT_RN) - struct crypt_data crypt_data = { - .initialized = 0 /* working storage used by crypt */ - }; -#endif /* Generate a random password salt */ salt = generate_random_str_list(frame, @@ -1660,52 +1656,20 @@ static int setup_primary_userPassword_hash( * Relies on the assertion that cleartext_utf8->data is a zero * terminated UTF-8 string */ - - /* - * crypt_r() and crypt() may return a null pointer upon error - * depending on how libcrypt was configured, so we prefer - * crypt_rn() from libcrypt / libxcrypt which always returns - * NULL on error. - * - * POSIX specifies returning a null pointer and setting - * errno. - * - * RHEL 7 (which does not use libcrypt / libxcrypt) returns a - * non-NULL pointer from crypt_r() on success but (always?) - * sets errno during internal processing in the NSS crypto - * subsystem. - * - * By preferring crypt_rn we avoid the 'return non-NULL but - * set-errno' that we otherwise cannot tell apart from the - * RHEL 7 behaviour. - */ - errno = 0; - -#ifdef HAVE_CRYPT_RN - hash = crypt_rn((char *)io->n.cleartext_utf8->data, - cmd, - &crypt_data, - sizeof(crypt_data)); -#elif HAVE_CRYPT_R - hash = crypt_r((char *)io->n.cleartext_utf8->data, cmd, &crypt_data); -#else - /* - * No crypt_r falling back to crypt, which is NOT thread safe - * Thread safety MT-Unsafe race:crypt - */ - hash = crypt((char *)io->n.cleartext_utf8->data, cmd); -#endif - /* - * On error, crypt() and crypt_r() may return a null pointer, - * or a pointer to an invalid hash beginning with a '*'. - */ - if (hash == NULL || hash[0] == '*') { + ret = talloc_crypt_blob(hash_blob, + (char *)io->n.cleartext_utf8->data, + cmd, + hash_blob); + if (ret != 0) { char buf[1024]; const char *reason = NULL; - if (errno == ERANGE) { + if (ret == ERANGE) { reason = "Password exceeds maximum length allowed for crypt() hashing"; + } else if (ret == ENOTRECOVERABLE) { + /* probably weird RHEL7 crypt, see talloc_crypt_blob() */ + reason = "Unknown error"; } else { - int err = strerror_r(errno, buf, sizeof(buf)); + int err = strerror_r(ret, buf, sizeof(buf)); if (err == 0) { reason = buf; } else { @@ -1723,14 +1687,6 @@ static int setup_primary_userPassword_hash( return LDB_ERR_OPERATIONS_ERROR; } - - *hash_blob = data_blob_talloc(hash_blob, - (const uint8_t *)hash, - strlen(hash)); - if (hash_blob->data == NULL) { - TALLOC_FREE(frame); - return ldb_oom(ldb); - } hash_value->value = hash_blob; TALLOC_FREE(frame); return LDB_SUCCESS; diff --git a/source4/dsdb/samdb/ldb_modules/wscript_build_server b/source4/dsdb/samdb/ldb_modules/wscript_build_server index 9c1eb12a7c2..16d9b31a982 100644 --- a/source4/dsdb/samdb/ldb_modules/wscript_build_server +++ b/source4/dsdb/samdb/ldb_modules/wscript_build_server @@ -195,7 +195,7 @@ bld.SAMBA_MODULE('ldb_password_hash', init_function='ldb_password_hash_module_init', module_init_name='ldb_init_module', internal_module=False, - deps='talloc samdb LIBCLI_AUTH NDR_DRSBLOBS authkrb5 krb5 gpgme DSDB_MODULE_HELPERS crypt db-glue' + deps='talloc samdb LIBCLI_AUTH NDR_DRSBLOBS authkrb5 krb5 gpgme DSDB_MODULE_HELPERS util_crypt db-glue' )