1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-08 21:18:16 +03:00

util: add a crypt wrapper, derived from dsdb:password_hash

This is going to be used by the dsdb password_hash module, and exposed
to Python via pyglue.

We're doing this because Python 3.13 has dropped crypt from the Python
standard library.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15756

Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
Douglas Bagnall 2024-12-05 16:35:51 +13:00 committed by Andreas Schneider
parent 5ad1a93107
commit 833455c7f9
3 changed files with 101 additions and 0 deletions

90
lib/util/util_crypt.c Normal file
View File

@ -0,0 +1,90 @@
#include <replace.h>
#include "data_blob.h"
#include <talloc.h>
#include <crypt.h>
#include "util_crypt.h"
static int crypt_as_best_we_can(const char *phrase,
const char *setting,
const char **hashp)
{
int ret = 0;
const char *hash = NULL;
#if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT_RN)
struct crypt_data crypt_data = {
.initialized = 0 /* working storage used by crypt */
};
#endif
/*
* 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(phrase, setting,
&crypt_data,
sizeof(crypt_data));
#elif HAVE_CRYPT_R
hash = crypt_r(phrase, setting, &crypt_data);
#else
/*
* No crypt_r falling back to crypt, which is NOT thread safe
* Thread safety MT-Unsafe race:crypt
*/
hash = crypt(phrase, setting);
#endif
/*
* On error, crypt() and crypt_r() may return a null pointer,
* or a pointer to an invalid hash beginning with a '*'.
*/
ret = errno;
errno = 0;
if (hash == NULL || hash[0] == '*') {
if (ret == 0) {
/* this is annoying */
ret = ENOTRECOVERABLE;
}
}
*hashp = hash;
return ret;
}
int talloc_crypt_blob(TALLOC_CTX *mem_ctx,
const char *phrase,
const char *setting,
DATA_BLOB *blob)
{
const char *hash = NULL;
int ret = crypt_as_best_we_can(phrase, setting, &hash);
if (ret != 0) {
blob->data = NULL;
blob->length = 0;
return ret;
}
blob->length = strlen(hash);
blob->data = talloc_memdup(mem_ctx, hash, blob->length);
if (blob->data == NULL) {
return ENOMEM;
}
return 0;
}

5
lib/util/util_crypt.h Normal file
View File

@ -0,0 +1,5 @@
int talloc_crypt_blob(TALLOC_CTX *mem_ctx,
const char *phrase,
const char *cmd,
DATA_BLOB *blob);

View File

@ -253,6 +253,12 @@ else:
private_library=True,
local_include=False)
bld.SAMBA_LIBRARY('util_crypt',
source='util_crypt.c',
deps='talloc crypt',
private_library=True,
local_include=False)
bld.SAMBA_SUBSYSTEM('UNIX_PRIVS',
source='unix_privs.c',