shared/libcrypt-util: add fallback for crypt_ra()

Following the style in missing_syscall.h, we use a non-conflicting name
for the function and use a macro to map to the real name to the replacement.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2020-09-10 18:30:22 +02:00
parent 2b49f0ca83
commit 9de324c3c9
1 changed files with 44 additions and 1 deletions

View File

@ -69,6 +69,8 @@ int make_salt(char **ret) {
assert_cc(sizeof(table) == 64U + 1U);
log_debug("Generating fallback salt for hash prefix: $6$");
/* Insist on the best randomness by setting RANDOM_BLOCK, this is about keeping passwords secret after all. */
r = genuine_random_bytes(raw, sizeof(raw), RANDOM_BLOCK);
if (r < 0)
@ -90,6 +92,47 @@ int make_salt(char **ret) {
#endif
}
#if HAVE_CRYPT_RA
# define CRYPT_RA_NAME "crypt_ra"
#else
# define CRYPT_RA_NAME "crypt_r"
/* Provide a poor man's fallback that uses a fixed size buffer. */
static char* systemd_crypt_ra(const char *phrase, const char *setting, void **data, int *size) {
assert(data);
assert(size);
/* We allocate the buffer because crypt(3) says: struct crypt_data may be quite large (32kB in this
* implementation of libcrypt; over 128kB in some other implementations). This is large enough that
* it may be unwise to allocate it on the stack. */
if (!*data) {
*data = new0(struct crypt_data, 1);
if (!*data) {
errno = -ENOMEM;
return NULL;
}
*size = (int) (sizeof(struct crypt_data));
}
char *t = crypt_r(phrase, setting, *data);
if (!t)
return NULL;
/* crypt_r may return a pointer to an invalid hashed password on error. Our callers expect NULL on
* error, so let's just return that. */
if (t[0] == '*')
return NULL;
return t;
}
#define crypt_ra systemd_crypt_ra
#endif
int hash_password_full(const char *password, void **cd_data, int *cd_size, char **ret) {
_cleanup_free_ char *salt = NULL;
_cleanup_(erase_and_freep) void *_cd_data = NULL;
@ -106,7 +149,7 @@ int hash_password_full(const char *password, void **cd_data, int *cd_size, char
p = crypt_ra(password, salt, cd_data ?: &_cd_data, cd_size ?: &_cd_size);
if (!p)
return log_debug_errno(errno_or_else(SYNTHETIC_ERRNO(EINVAL)),
"crypt_ra() failed: %m");
CRYPT_RA_NAME "() failed: %m");
p = strdup(p);
if (!p)