| |
@@ -43,6 +43,21 @@
|
| |
#define HASH_ROUNDS_MIN 1000
|
| |
#define HASH_ROUNDS_MAX 999999999
|
| |
|
| |
+ #if (defined CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY && \
|
| |
+ CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY)
|
| |
+ #define USE_XCRYPT_GENSALT 1
|
| |
+ #else
|
| |
+ #define USE_XCRYPT_GENSALT 0
|
| |
+ #endif
|
| |
+
|
| |
+ #if ((defined XCRYPT_VERSION_NUM && \
|
| |
+ XCRYPT_VERSION_NUM >= ((4 << 16) | 3)) && \
|
| |
+ USE_XCRYPT_GENSALT)
|
| |
+ #define HAVE_YESCRYPT 1
|
| |
+ #else
|
| |
+ #define HAVE_YESCRYPT 0
|
| |
+ #endif
|
| |
+
|
| |
struct lu_lock {
|
| |
int fd;
|
| |
struct flock lock;
|
| |
@@ -66,6 +81,7 @@
|
| |
return strcmp((char *) v1, (char *) v2);
|
| |
}
|
| |
|
| |
+ #if !USE_XCRYPT_GENSALT
|
| |
/* A list of allowed salt characters, according to SUSv2. */
|
| |
#define ACCEPTABLE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
|
| |
"abcdefghijklmnopqrstuvwxyz" \
|
| |
@@ -115,6 +131,7 @@
|
| |
close(fd);
|
| |
return TRUE;
|
| |
}
|
| |
+ #endif
|
| |
|
| |
static const struct {
|
| |
const char initial[5];
|
| |
@@ -124,9 +141,12 @@
|
| |
} salt_type_info[] = {
|
| |
{"$1$", "$", 8, FALSE },
|
| |
/* FIXME: number of rounds, base64 of 128 bits */
|
| |
- {"$2a$", "$", 8, FALSE },
|
| |
+ {"$2b$", "$", 8, FALSE },
|
| |
{"$5$", "$", 16, TRUE },
|
| |
{"$6$", "$", 16, TRUE },
|
| |
+ #if HAVE_YESCRYPT
|
| |
+ {"$y$", "$", 24, FALSE },
|
| |
+ #endif
|
| |
{ "", "", 2 },
|
| |
};
|
| |
|
| |
@@ -135,6 +155,9 @@
|
| |
{
|
| |
char salt[2048];
|
| |
size_t i, len = 0;
|
| |
+ #if USE_XCRYPT_GENSALT
|
| |
+ unsigned long rounds = 0;
|
| |
+ #endif
|
| |
|
| |
if (previous == NULL) {
|
| |
previous = LU_DEFAULT_SALT_TYPE;
|
| |
@@ -151,6 +174,23 @@
|
| |
|
| |
if (salt_type_info[i].sha_rounds != FALSE
|
| |
&& strncmp(previous + len, "rounds=", strlen("rounds=")) == 0) {
|
| |
+ #if USE_XCRYPT_GENSALT
|
| |
+ const char *start;
|
| |
+ char *end;
|
| |
+
|
| |
+ start = previous + len + strlen("rounds=");
|
| |
+ rounds = strtoul (start, &end, 10);
|
| |
+
|
| |
+ if (rounds < HASH_ROUNDS_MIN)
|
| |
+ rounds = HASH_ROUNDS_MIN;
|
| |
+ else if (rounds > HASH_ROUNDS_MAX)
|
| |
+ rounds = HASH_ROUNDS_MAX;
|
| |
+ }
|
| |
+
|
| |
+ g_assert(CRYPT_GENSALT_OUTPUT_SIZE <= sizeof(salt));
|
| |
+
|
| |
+ crypt_gensalt_rn(previous, rounds, NULL, 0, salt, sizeof(salt));
|
| |
+ #else
|
| |
const char *start, *end;
|
| |
|
| |
start = previous + len + strlen("rounds=");
|
| |
@@ -168,6 +208,7 @@
|
| |
return NULL;
|
| |
strcpy(salt + len + salt_type_info[i].salt_length,
|
| |
salt_type_info[i].separator);
|
| |
+ #endif
|
| |
|
| |
return crypt(plain, salt);
|
| |
}
|
| |
@@ -231,9 +272,12 @@
|
| |
} salt_types[] = {
|
| |
{ "des", "", FALSE },
|
| |
{ "md5", "$1$", FALSE },
|
| |
- { "blowfish", "$2a$", FALSE },
|
| |
+ { "blowfish", "$2b$", FALSE },
|
| |
{ "sha256", "$5$", TRUE },
|
| |
{ "sha512", "$6$", TRUE },
|
| |
+ #if HAVE_YESCRYPT
|
| |
+ { "yescrypt", "$y$", FALSE },
|
| |
+ #endif
|
| |
};
|
| |
|
| |
const char *salt_type;
|
| |
@@ -251,13 +295,18 @@
|
| |
|
| |
found:
|
| |
if (salt_types[i].sha_rounds != FALSE) {
|
| |
- unsigned long rounds;
|
| |
+ unsigned long rounds = 0;
|
| |
|
| |
rounds = select_hash_rounds(context);
|
| |
+ #if USE_XCRYPT_GENSALT
|
| |
+ return g_strdup(crypt_gensalt(salt_types[i].initializer,
|
| |
+ rounds, NULL, 0));
|
| |
+ #else
|
| |
if (rounds != 0)
|
| |
return g_strdup_printf("%srounds=%lu$",
|
| |
salt_types[i].initializer,
|
| |
rounds);
|
| |
+ #endif
|
| |
}
|
| |
return g_strdup(salt_types[i].initializer);
|
| |
}
|
| |
The yescrypt hashing method is considered to be much stronger than sha512crypt and fully supported by libxcrypt. It is based on NIST-approved primitives and on par with argon2 in strength.
Fresh installed systems, as well as newly computed hashes for the UNIX shadow file should prefer this method.
See: https://fedoraproject.org/wiki/Changes/yescrypt_as_default_hashing_method_for_shadow