6 #include "util_crypt.h"
9 static int crypt_as_best_we_can(TALLOC_CTX
*mem_ctx
,
15 const char *hash
= NULL
;
17 #if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT_RN)
18 struct crypt_data crypt_data
= {
19 .initialized
= 0 /* working storage used by crypt */
24 * crypt_r() and crypt() may return a null pointer upon error
25 * depending on how libcrypt was configured, so we prefer
26 * crypt_rn() from libcrypt / libxcrypt which always returns
29 * POSIX specifies returning a null pointer and setting
32 * RHEL 7 (which does not use libcrypt / libxcrypt) returns a
33 * non-NULL pointer from crypt_r() on success but (always?)
34 * sets errno during internal processing in the NSS crypto
37 * By preferring crypt_rn we avoid the 'return non-NULL but
38 * set-errno' that we otherwise cannot tell apart from the
44 hash
= crypt_rn(phrase
, setting
,
48 hash
= crypt_r(phrase
, setting
, &crypt_data
);
51 * No crypt_r falling back to crypt, which is NOT thread safe
52 * Thread safety MT-Unsafe race:crypt
54 hash
= crypt(phrase
, setting
);
57 * On error, crypt() and crypt_r() may return a null pointer,
58 * or a pointer to an invalid hash beginning with a '*'.
62 if (hash
== NULL
|| hash
[0] == '*') {
64 /* this is annoying */
65 ret
= ENOTRECOVERABLE
;
72 *hashp
= talloc_strdup(mem_ctx
, hash
);
80 int talloc_crypt_blob(TALLOC_CTX
*mem_ctx
,
85 const char *hash
= NULL
;
86 int ret
= crypt_as_best_we_can(mem_ctx
, phrase
, setting
, &hash
);
92 blob
->length
= strlen(hash
);
93 blob
->data
= discard_const_p(uint8_t, hash
);
94 if (blob
->data
== NULL
) {
101 char *talloc_crypt_errstring(TALLOC_CTX
*mem_ctx
, int error
)
105 if (error
== ERANGE
) {
106 return talloc_strdup(
108 "Password exceeds maximum length allowed for crypt() hashing");
110 if (error
== ENOTRECOVERABLE
) {
111 /* probably weird RHEL7 crypt, see crypt_as_best_we_can() */
115 err
= strerror_r(error
, buf
, sizeof(buf
));
119 return talloc_strndup(mem_ctx
, buf
, sizeof(buf
));
121 return talloc_strdup(mem_ctx
, "Unknown error");