]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
dsdb:password_hash: use talloc_crypt_blob()
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Wed, 11 Dec 2024 22:16:22 +0000 (11:16 +1300)
committerAndreas Schneider <asn@cryptomilk.org>
Fri, 20 Dec 2024 07:04:31 +0000 (07:04 +0000)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15756

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
source4/dsdb/samdb/ldb_modules/password_hash.c
source4/dsdb/samdb/ldb_modules/wscript_build_server

index c1902126a720317d03cd77763322a057b017a223..7a7114c1caab064ab7015f66e23f99e5eaf94c2e 100644 (file)
@@ -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 <gnutls/crypto.h>
@@ -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;
index 9c1eb12a7c2e212bd6af212d89eaab60ee3070ba..16d9b31a9825e5c6d5e07d255a922b69baab1b05 100644 (file)
@@ -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'
        )