#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>
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,
* 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 {
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;