diff --git a/configure.ac b/configure.ac index b766eff0..6aaae6b7 100644 --- a/configure.ac +++ b/configure.ac @@ -290,6 +290,9 @@ AC_ARG_WITH(sha-crypt, AC_ARG_WITH(bcrypt, [AC_HELP_STRING([--with-bcrypt], [allow the bcrypt password encryption algorithm @<:@default=no@:>@])], [with_bcrypt=$withval], [with_bcrypt=no]) +AC_ARG_WITH(yescrypt, + [AC_HELP_STRING([--with-yescrypt], [allow the yescrypt password encryption algorithm @<:@default=no@:>@])], + [with_yescrypt=$withval], [with_yescrypt=no]) AC_ARG_WITH(nscd, [AC_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=yes@:>@])], [with_nscd=$withval], [with_nscd=yes]) @@ -322,6 +325,11 @@ if test "$with_bcrypt" = "yes"; then AC_DEFINE(USE_BCRYPT, 1, [Define to allow the bcrypt password encryption algorithm]) fi +AM_CONDITIONAL(USE_YESCRYPT, test "x$with_yescrypt" = "xyes") +if test "$with_yescrypt" = "yes"; then + AC_DEFINE(USE_YESCRYPT, 1, [Define to allow the yescrypt password encryption algorithm]) +fi + if test "$with_nscd" = "yes"; then AC_CHECK_FUNC(posix_spawn, [AC_DEFINE(USE_NSCD, 1, [Define to support flushing of nscd caches])], @@ -402,6 +410,10 @@ AC_SUBST(LIBCRYPT) AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt], [AC_MSG_ERROR([crypt() not found])]) +AC_SUBST(LIYESCRYPT) +AC_CHECK_LIB(crypt, crypt, [LIYESCRYPT=-lcrypt], + [AC_MSG_ERROR([crypt() not found])]) + AC_SUBST(LIBACL) if test "$with_acl" != "no"; then AC_CHECK_HEADERS(acl/libacl.h attr/error_context.h, [acl_header="yes"], [acl_header="no"]) @@ -752,6 +764,7 @@ echo " shadow group support: $enable_shadowgrp" echo " S/Key support: $with_skey" echo " SHA passwords encryption: $with_sha_crypt" echo " bcrypt passwords encryption: $with_bcrypt" +echo " yescrypt passwords encryption: $with_yescrypt" echo " nscd support: $with_nscd" echo " sssd support: $with_sssd" echo " subordinate IDs support: $enable_subids" diff --git a/etc/login.defs b/etc/login.defs index b9409185..fe206812 100644 --- a/etc/login.defs +++ b/etc/login.defs @@ -326,6 +326,7 @@ CHFN_RESTRICT rwh # If set to SHA256, SHA256-based algorithm will be used for encrypting password # If set to SHA512, SHA512-based algorithm will be used for encrypting password # If set to BCRYPT, BCRYPT-based algorithm will be used for encrypting password +# If set to YESCRYPT, YESCRYPT-based algorithm will be used for encrypting password # If set to DES, DES-based algorithm will be used for encrypting password (default) # MD5 and DES should not be used for new hashes, see crypt(5) for recommendations. # Overrides the MD5_CRYPT_ENAB option @@ -367,6 +368,19 @@ CHFN_RESTRICT rwh #BCRYPT_MIN_ROUNDS 13 #BCRYPT_MAX_ROUNDS 13 +# +# Only works if ENCRYPT_METHOD is set to YESCRYPT. +# +# Define the YESCRYPT cost factor. +# With a higher cost factor, it is more difficult to brute-force the password. +# However, more CPU time and more memory will be needed to authenticate users +# if this value is increased. +# +# If not specified, a cost factor of 5 will be used. +# The value must be within the 1-11 range. +# +#YESCRYPT_COST_FACTOR 5 + # # List of groups to add to the user's supplementary group set # when logging in from the console (as determined by the CONSOLE diff --git a/lib/encrypt.c b/lib/encrypt.c index 4247f241..4ab0a1d7 100644 --- a/lib/encrypt.c +++ b/lib/encrypt.c @@ -74,6 +74,9 @@ case '6': method = "SHA512"; break; + case 'y': + method = "YESCRYPT"; + break; default: { static char nummethod[4] = "$x$"; diff --git a/lib/getdef.c b/lib/getdef.c index c3506473..909ee45f 100644 --- a/lib/getdef.c +++ b/lib/getdef.c @@ -126,6 +126,9 @@ static struct itemdef def_table[] = { #ifdef USE_BCRYPT {"BCRYPT_MAX_ROUNDS", NULL}, {"BCRYPT_MIN_ROUNDS", NULL}, +#endif +#ifdef USE_YESCRYPT + {"YESCRYPT_COST_FACTOR", NULL}, #endif {"SUB_GID_COUNT", NULL}, {"SUB_GID_MAX", NULL}, diff --git a/libmisc/obscure.c b/libmisc/obscure.c index 15da7603..dc69f768 100644 --- a/libmisc/obscure.c +++ b/libmisc/obscure.c @@ -271,6 +271,9 @@ static /*@observer@*//*@null@*/const char *obscure_msg ( #endif #ifdef USE_BCRYPT || (strcmp (result, "BCRYPT") == 0) +#endif +#ifdef USE_YESCRYPT + || (strcmp (result, "YESCRYPT") == 0) #endif ) { return NULL; diff --git a/libmisc/salt.c b/libmisc/salt.c index e1a7ac80..46555dc4 100644 --- a/libmisc/salt.c +++ b/libmisc/salt.c @@ -32,6 +32,10 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds static /*@observer@*/const char *gensalt_bcrypt (void); static /*@observer@*/const char *BCRYPT_salt_rounds (/*@null@*/int *prefered_rounds); #endif /* USE_BCRYPT */ +#ifdef USE_YESCRYPT +static /*@observer@*/const char *gensalt_yescrypt (void); +static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/long *prefered_rounds); +#endif /* USE_YESCRYPT */ #ifndef HAVE_L64A static /*@observer@*/char *l64a(long value) @@ -263,6 +267,78 @@ static /*@observer@*/const char *gensalt_bcrypt (void) } #endif /* USE_BCRYPT */ +#ifdef USE_YESCRYPT +/* Default cost if not explicitly specified. */ +#define Y_COST_DEFAULT 5 +/* Minimum cost. */ +#define Y_COST_MIN 1 +/* Maximum cost. */ +#define Y_COST_MAX 11 +/* + * Return a salt prefix specifying the cost for the YESCRYPT method. + */ +static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/long *prefered_cost) +{ + static char cost_prefix[5]; + long cost; + + if (NULL == prefered_cost) { + cost = getdef_num ("YESCRYPT_COST_FACTOR", Y_COST_DEFAULT); + } else { + cost = *prefered_cost; + } + + if (cost < Y_COST_MIN) { + cost = Y_COST_MIN; + } + if (cost > Y_COST_MAX) { + cost = Y_COST_MAX; + } + + cost_prefix[0] = 'j'; + if (cost < 3) { + cost_prefix[1] = 0x36 + cost; + } else if (cost < 6) { + cost_prefix[1] = 0x34 + cost; + } else { + cost_prefix[1] = 0x3b + cost; + } + cost_prefix[2] = cost >= 3 ? 'T' : '5'; + cost_prefix[3] = '$'; + cost_prefix[4] = 0; + + return cost_prefix; +} + +/* + * Default number of base64 characters used for the salt. + * 24 characters gives a 144 bits (18 bytes) salt. Unlike the more + * traditional 128 bits (16 bytes) salt, this 144 bits salt is always + * represented by the same number of base64 characters without padding + * issue, even with a non-standard base64 encoding scheme. + */ +#define YESCRYPT_SALT_SIZE 24 +/* + * Generate a 22 character salt string for yescrypt. + */ +static /*@observer@*/const char *gensalt_yescrypt (void) +{ + static char salt[32]; + + salt[0] = '\0'; + + seedRNG (); + strcat (salt, l64a (random())); + do { + strcat (salt, l64a (random())); + } while (strlen (salt) < YESCRYPT_SALT_SIZE); + + salt[YESCRYPT_SALT_SIZE] = '\0'; + + return salt; +} +#endif /* USE_YESCRYPT */ + /* * Generate salt of size salt_size. */ @@ -302,6 +378,7 @@ static /*@observer@*/const char *gensalt (size_t salt_size) * If meth is specified, an additional parameter can be provided. * * For the SHA256 and SHA512 method, this specifies the number of rounds * (if not NULL). + * * For the YESCRYPT method, this specifies the cost factor (if not NULL). */ /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const char *meth, /*@null@*/void *arg) { @@ -333,6 +410,11 @@ static /*@observer@*/const char *gensalt (size_t salt_size) BCRYPTMAGNUM(result); strcat(result, BCRYPT_salt_rounds((int *)arg)); #endif /* USE_BCRYPT */ +#ifdef USE_YESCRYPT + } else if (0 == strcmp (method, "YESCRYPT")) { + MAGNUM(result, 'y'); + strcat(result, YESCRYPT_salt_cost((int *)arg)); +#endif /* USE_YESCRYPT */ #ifdef USE_SHA_CRYPT } else if (0 == strcmp (method, "SHA256")) { MAGNUM(result, '5'); @@ -362,11 +444,21 @@ static /*@observer@*/const char *gensalt (size_t salt_size) return result; } else { #endif /* USE_BCRYPT */ +#ifdef USE_YESCRYPT + if (0 == strcmp (method, "YESCRYPT")) { + strncat (result, gensalt_yescrypt (), + sizeof (result) - strlen (result) - 1); + return result; + } else { +#endif /* USE_YESCRYPT */ strncat (result, gensalt (salt_len), sizeof (result) - strlen (result) - 1); +#ifdef USE_YESCRYPT + } +#endif /* USE_YESCRYPT */ #ifdef USE_BCRYPT } -#endif /* USE_BCRYPT */ +#endif /* USE_BCRYPT */ return result; } diff --git a/src/chgpasswd.c b/src/chgpasswd.c index 4013abb3..ed5f75a6 100644 --- a/src/chgpasswd.c +++ b/src/chgpasswd.c @@ -61,9 +61,9 @@ const char *Prog; static bool eflg = false; static bool md5flg = false; -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) static bool sflg = false; -#endif /* USE_SHA_CRYPT || USE_BCRYPT */ +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ static /*@null@*//*@observer@*/const char *crypt_method = NULL; #define cflg (NULL != crypt_method) @@ -73,6 +73,9 @@ static long sha_rounds = 5000; #ifdef USE_BCRYPT static long bcrypt_rounds = 13; #endif +#ifdef USE_YESCRYPT +static long yescrypt_cost = 5; +#endif #ifdef SHADOWGRP static bool is_shadow_grp; @@ -128,14 +131,15 @@ static /*@noreturn@*/void usage (int status) Prog); (void) fprintf (usageout, _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), -#if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT) "NONE DES MD5" -#elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) - "NONE DES MD5 SHA256 SHA512 BCRYPT" -#elif defined(USE_SHA_CRYPT) - "NONE DES MD5 SHA256 SHA512" -#else - "NONE DES MD5 BCRYPT" +#if defined(USE_SHA_CRYPT) + " SHA256 SHA512" +#endif +#if defined(USE_BCRYPT) + " BCRYPT" +#endif +#if defined(USE_YESCRYPT) + " YESCRYPT" #endif ); (void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout); @@ -144,11 +148,11 @@ static /*@noreturn@*/void usage (int status) " the MD5 algorithm\n"), usageout); (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) - (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n" - " crypt algorithms\n"), +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" + " or YESCRYPT crypt algorithms\n"), usageout); -#endif /* USE_SHA_CRYPT || USE_BCRYPT */ +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ (void) fputs ("\n", usageout); exit (status); @@ -162,19 +166,22 @@ static /*@noreturn@*/void usage (int status) static void process_flags (int argc, char **argv) { int c; +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + int bad_s; +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ static struct option long_options[] = { {"crypt-method", required_argument, NULL, 'c'}, {"encrypted", no_argument, NULL, 'e'}, {"help", no_argument, NULL, 'h'}, {"md5", no_argument, NULL, 'm'}, {"root", required_argument, NULL, 'R'}, -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) {"sha-rounds", required_argument, NULL, 's'}, -#endif /* USE_SHA_CRYPT || USE_BCRYPT */ +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ {NULL, 0, NULL, '\0'} }; while ((c = getopt_long (argc, argv, -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) "c:ehmR:s:", #else "c:ehmR:", @@ -195,40 +202,36 @@ static void process_flags (int argc, char **argv) break; case 'R': /* no-op, handled in process_root_flag () */ break; -#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) case 's': sflg = true; + bad_s = 0; +#if defined(USE_SHA_CRYPT) if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) - && (0 == getlong(optarg, &sha_rounds))) - || ( (0 == strcmp (crypt_method, "BCRYPT")) + && (0 == getlong(optarg, &sha_rounds)))) { + bad_s = 1; + } +#endif /* USE_SHA_CRYPT */ +#if defined(USE_BCRYPT) + if (( (0 == strcmp (crypt_method, "BCRYPT")) && (0 == getlong(optarg, &bcrypt_rounds)))) { + bad_s = 1; + } +#endif /* USE_BCRYPT */ +#if defined(USE_YESCRYPT) + if (( (0 == strcmp (crypt_method, "YESCRYPT")) + && (0 == getlong(optarg, &yescrypt_cost)))) { + bad_s = 1; + } +#endif /* USE_YESCRYPT */ + if (bad_s != 0) { fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog, optarg); usage (E_USAGE); } break; -#elif defined(USE_SHA_CRYPT) - case 's': - sflg = true; - if (0 == getlong(optarg, &sha_rounds)) { - fprintf (stderr, - _("%s: invalid numeric argument '%s'\n"), - Prog, optarg); - usage (E_USAGE); - } - break; -#elif defined(USE_BCRYPT) - case 's': - sflg = true; - if (0 == getlong(optarg, &bcrypt_rounds)) { - fprintf (stderr, - _("%s: invalid numeric argument '%s'\n"), - Prog, optarg); - usage (E_USAGE); - } - break; -#endif +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ default: usage (E_USAGE); @@ -247,7 +250,7 @@ static void process_flags (int argc, char **argv) */ static void check_flags (void) { -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) if (sflg && !cflg) { fprintf (stderr, _("%s: %s flag is only allowed with the %s flag\n"), @@ -271,10 +274,13 @@ static void check_flags (void) #ifdef USE_SHA_CRYPT && (0 != strcmp (crypt_method, "SHA256")) && (0 != strcmp (crypt_method, "SHA512")) -#endif +#endif /* USE_SHA_CRYPT */ #ifdef USE_BCRYPT && (0 != strcmp (crypt_method, "BCRYPT")) -#endif +#endif /* USE_BCRYPT */ +#ifdef USE_YESCRYPT + && (0 != strcmp (crypt_method, "YESCRYPT")) +#endif /* USE_YESCRYPT */ ) { fprintf (stderr, _("%s: unsupported crypt method: %s\n"), @@ -497,23 +503,24 @@ int main (int argc, char **argv) if (md5flg) { crypt_method = "MD5"; } -#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) if (sflg) { +#if defined(USE_SHA_CRYPT) if ( (0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) { arg = &sha_rounds; } - else if (0 == strcmp (crypt_method, "BCRYPT")) { +#endif /* USE_SHA_CRYPT */ +#if defined(USE_BCRYPT) + if (0 == strcmp (crypt_method, "BCRYPT")) { arg = &bcrypt_rounds; } - } -#elif defined(USE_SHA_CRYPT) - if (sflg) { - arg = &sha_rounds; - } -#elif defined(USE_BCRYPT) - if (sflg) { - arg = &bcrypt_rounds; +#endif /* USE_BCRYPT */ +#if defined(USE_YESCRYPT) + if (0 == strcmp (crypt_method, "YESCRYPT")) { + arg = &yescrypt_cost; + } +#endif /* USE_YESCRYPT */ } #endif salt = crypt_make_salt (crypt_method, arg); diff --git a/src/chpasswd.c b/src/chpasswd.c index be61e038..420342fd 100644 --- a/src/chpasswd.c +++ b/src/chpasswd.c @@ -58,7 +58,7 @@ const char *Prog; static bool eflg = false; static bool md5flg = false; -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) static bool sflg = false; #endif @@ -70,6 +70,9 @@ static long sha_rounds = 5000; #ifdef USE_BCRYPT static long bcrypt_rounds = 13; #endif +#ifdef USE_YESCRYPT +static long yescrypt_cost = 5; +#endif static bool is_shadow_pwd; static bool pw_locked = false; @@ -121,14 +124,15 @@ static /*@noreturn@*/void usage (int status) Prog); (void) fprintf (usageout, _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), -#if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT) "NONE DES MD5" -#elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) - "NONE DES MD5 SHA256 SHA512 BCRYPT" -#elif defined(USE_SHA_CRYPT) - "NONE DES MD5 SHA256 SHA512" -#else - "NONE DES MD5 BCRYPT" +#if defined(USE_SHA_CRYPT) + " SHA256 SHA512" +#endif +#if defined(USE_BCRYPT) + " BCRYPT" +#endif +#if defined(USE_YESCRYPT) + " YESCRYPT" #endif ); (void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout); @@ -137,11 +141,11 @@ static /*@noreturn@*/void usage (int status) " the MD5 algorithm\n"), usageout); (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) - (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n" - " crypt algorithms\n"), +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" + " or YESCRYPT crypt algorithms\n"), usageout); -#endif /* USE_SHA_CRYPT || USE_BCRYPT */ +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ (void) fputs ("\n", usageout); exit (status); @@ -155,20 +159,23 @@ static /*@noreturn@*/void usage (int status) static void process_flags (int argc, char **argv) { int c; +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + int bad_s; +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ static struct option long_options[] = { {"crypt-method", required_argument, NULL, 'c'}, {"encrypted", no_argument, NULL, 'e'}, {"help", no_argument, NULL, 'h'}, {"md5", no_argument, NULL, 'm'}, {"root", required_argument, NULL, 'R'}, -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) {"sha-rounds", required_argument, NULL, 's'}, -#endif /* USE_SHA_CRYPT || USE_BCRYPT */ +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ {NULL, 0, NULL, '\0'} }; while ((c = getopt_long (argc, argv, -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) "c:ehmR:s:", #else "c:ehmR:", @@ -189,40 +196,36 @@ static void process_flags (int argc, char **argv) break; case 'R': /* no-op, handled in process_root_flag () */ break; -#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) case 's': sflg = true; + bad_s = 0; +#if defined(USE_SHA_CRYPT) if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) - && (0 == getlong(optarg, &sha_rounds))) - || ( (0 == strcmp (crypt_method, "BCRYPT")) + && (0 == getlong(optarg, &sha_rounds)))) { + bad_s = 1; + } +#endif /* USE_SHA_CRYPT */ +#if defined(USE_BCRYPT) + if (( (0 == strcmp (crypt_method, "BCRYPT")) && (0 == getlong(optarg, &bcrypt_rounds)))) { + bad_s = 1; + } +#endif /* USE_BCRYPT */ +#if defined(USE_YESCRYPT) + if (( (0 == strcmp (crypt_method, "YESCRYPT")) + && (0 == getlong(optarg, &yescrypt_cost)))) { + bad_s = 1; + } +#endif /* USE_YESCRYPT */ + if (bad_s != 0) { fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog, optarg); usage (E_USAGE); } break; -#elif defined(USE_SHA_CRYPT) - case 's': - sflg = true; - if (0 == getlong(optarg, &sha_rounds)) { - fprintf (stderr, - _("%s: invalid numeric argument '%s'\n"), - Prog, optarg); - usage (E_USAGE); - } - break; -#elif defined(USE_BCRYPT) - case 's': - sflg = true; - if (0 == getlong(optarg, &bcrypt_rounds)) { - fprintf (stderr, - _("%s: invalid numeric argument '%s'\n"), - Prog, optarg); - usage (E_USAGE); - } - break; -#endif +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ default: usage (E_USAGE); @@ -241,7 +244,7 @@ static void process_flags (int argc, char **argv) */ static void check_flags (void) { -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) if (sflg && !cflg) { fprintf (stderr, _("%s: %s flag is only allowed with the %s flag\n"), @@ -269,6 +272,9 @@ static void check_flags (void) #ifdef USE_BCRYPT && (0 != strcmp (crypt_method, "BCRYPT")) #endif /* USE_BCRYPT */ +#ifdef USE_YESCRYPT + && (0 != strcmp (crypt_method, "YESCRYPT")) +#endif /* USE_YESCRYPT */ ) { fprintf (stderr, _("%s: unsupported crypt method: %s\n"), @@ -530,23 +536,24 @@ int main (int argc, char **argv) if (md5flg) { crypt_method = "MD5"; } -#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) if (sflg) { +#if defined(USE_SHA_CRYPT) if ( (0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) { arg = &sha_rounds; } - else if (0 == strcmp (crypt_method, "BCRYPT")) { +#endif /* USE_SHA_CRYPT */ +#if defined(USE_BCRYPT) + if (0 == strcmp (crypt_method, "BCRYPT")) { arg = &bcrypt_rounds; } - } -#elif defined(USE_SHA_CRYPT) - if (sflg) { - arg = &sha_rounds; - } -#elif defined(USE_BCRYPT) - if (sflg) { - arg = &bcrypt_rounds; +#endif /* USE_BCRYPT */ +#if defined(USE_YESCRYPT) + if (0 == strcmp (crypt_method, "YESCRYPT")) { + arg = &yescrypt_cost; + } +#endif /* USE_YESCRYPT */ } #endif salt = crypt_make_salt (crypt_method, arg); diff --git a/src/newusers.c b/src/newusers.c index 3104d6fd..ec0fe828 100644 --- a/src/newusers.c +++ b/src/newusers.c @@ -89,6 +89,9 @@ static long sha_rounds = 5000; #ifdef USE_BCRYPT static long bcrypt_rounds = 13; #endif /* USE_BCRYPT */ +#ifdef USE_YESCRYPT +static long yescrypt_cost = 5; +#endif /* USE_YESCRYPT */ #endif /* !USE_PAM */ static bool is_shadow; @@ -139,14 +142,15 @@ static void usage (int status) #ifndef USE_PAM (void) fprintf (usageout, _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), -#if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT) - "NONE DES MD5" -#elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) - "NONE DES MD5 SHA256 SHA512 BCRYPT" -#elif defined(USE_SHA_CRYPT) - "NONE DES MD5 SHA256 SHA512" -#else - "NONE DES MD5 BCRYPT" + "NONE DES MD5" +#if defined(USE_SHA_CRYPT) + " SHA256 SHA512" +#endif +#if defined(USE_BCRYPT) + " BCRYPT" +#endif +#if defined(USE_YESCRYPT) + " YESCRYPT" #endif ); #endif /* !USE_PAM */ @@ -154,11 +158,11 @@ static void usage (int status) (void) fputs (_(" -r, --system create system accounts\n"), usageout); (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); #ifndef USE_PAM -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) - (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n" - " crypt algorithms\n"), +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" + " or YESCRYPT crypt algorithms\n"), usageout); -#endif /* USE_SHA_CRYPT || USE_BCRYPT */ +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ #endif /* !USE_PAM */ (void) fputs ("\n", usageout); @@ -433,25 +437,28 @@ static int update_passwd (struct passwd *pwd, const char *password) void *crypt_arg = NULL; char *cp; if (NULL != crypt_method) { -#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) if (sflg) { if ( (0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) { crypt_arg = &sha_rounds; } - else if (0 == strcmp (crypt_method, "BCRYPT")) { + } +#endif /* USE_SHA_CRYPT */ +#if defined(USE_BCRYPT) + if (sflg) { + if (0 == strcmp (crypt_method, "BCRYPT")) { crypt_arg = &bcrypt_rounds; } } -#elif defined(USE_SHA_CRYPT) +#endif /* USE_BCRYPT */ +#if defined(USE_YESCRYPT) if (sflg) { - crypt_arg = &sha_rounds; + if (0 == strcmp (crypt_method, "YESCRYPT")) { + crypt_arg = &yescrypt_cost; + } } -#elif defined(USE_BCRYPT) - if (sflg) { - crypt_arg = &bcrypt_rounds; - } -#endif +#endif /* USE_YESCRYPT */ } if ((NULL != crypt_method) && (0 == strcmp(crypt_method, "NONE"))) { @@ -484,25 +491,28 @@ static int add_passwd (struct passwd *pwd, const char *password) #ifndef USE_PAM void *crypt_arg = NULL; if (NULL != crypt_method) { -#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) if (sflg) { if ( (0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) { crypt_arg = &sha_rounds; } - else if (0 == strcmp (crypt_method, "BCRYPT")) { + } +#endif /* USE_SHA_CRYPT */ +#if defined(USE_BCRYPT) + if (sflg) { + if (0 == strcmp (crypt_method, "BCRYPT")) { crypt_arg = &bcrypt_rounds; } } -#elif defined(USE_SHA_CRYPT) +#endif /* USE_BCRYPT */ +#if defined(USE_YESCRYPT) if (sflg) { - crypt_arg = &sha_rounds; + if (0 == strcmp (crypt_method, "YESCRYPT")) { + crypt_arg = &yescrypt_cost; + } } -#elif defined(USE_BCRYPT) - if (sflg) { - crypt_arg = &bcrypt_rounds; - } -#endif +#endif /* USE_PAM */ } /* @@ -619,6 +629,9 @@ static int add_passwd (struct passwd *pwd, const char *password) static void process_flags (int argc, char **argv) { int c; +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + int bad_s; +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ static struct option long_options[] = { {"badnames", no_argument, NULL, 'b'}, #ifndef USE_PAM @@ -628,20 +641,20 @@ static void process_flags (int argc, char **argv) {"system", no_argument, NULL, 'r'}, {"root", required_argument, NULL, 'R'}, #ifndef USE_PAM -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) {"sha-rounds", required_argument, NULL, 's'}, -#endif /* USE_SHA_CRYPT || USE_BCRYPT */ +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ #endif /* !USE_PAM */ {NULL, 0, NULL, '\0'} }; while ((c = getopt_long (argc, argv, #ifndef USE_PAM -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) "c:bhrs:", -#else /* !USE_SHA_CRYPT && !USE_BCRYPT */ +#else /* !USE_SHA_CRYPT && !USE_BCRYPT && !USE_YESCRYPT */ "c:bhr", -#endif /* USE_SHA_CRYPT || USE_BCRYPT */ +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ #else /* USE_PAM */ "bhr", #endif @@ -664,40 +677,36 @@ static void process_flags (int argc, char **argv) case 'R': /* no-op, handled in process_root_flag () */ break; #ifndef USE_PAM -#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) case 's': sflg = true; + bad_s = 0; +#if defined(USE_SHA_CRYPT) if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) - && (0 == getlong(optarg, &sha_rounds))) - || ( (0 == strcmp (crypt_method, "BCRYPT")) + && (0 == getlong(optarg, &sha_rounds)))) { + bad_s = 1; + } +#endif /* USE_SHA_CRYPT */ +#if defined(USE_BCRYPT) + if (( (0 == strcmp (crypt_method, "BCRYPT")) && (0 == getlong(optarg, &bcrypt_rounds)))) { + bad_s = 1; + } +#endif /* USE_BCRYPT */ +#if defined(USE_YESCRYPT) + if (( (0 == strcmp (crypt_method, "YESCRYPT")) + && (0 == getlong(optarg, &yescrypt_cost)))) { + bad_s = 1; + } +#endif /* USE_YESCRYPT */ + if (bad_s != 0) { fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog, optarg); usage (EXIT_FAILURE); } break; -#elif defined(USE_SHA_CRYPT) - case 's': - sflg = true; - if (0 == getlong(optarg, &sha_rounds)) { - fprintf (stderr, - _("%s: invalid numeric argument '%s'\n"), - Prog, optarg); - usage (EXIT_FAILURE); - } - break; -#elif defined(USE_BCRYPT) - case 's': - sflg = true; - if (0 == getlong(optarg, &bcrypt_rounds)) { - fprintf (stderr, - _("%s: invalid numeric argument '%s'\n"), - Prog, optarg); - usage (EXIT_FAILURE); - } - break; -#endif +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ #endif /* !USE_PAM */ default: usage (EXIT_FAILURE); @@ -731,14 +740,14 @@ static void process_flags (int argc, char **argv) static void check_flags (void) { #ifndef USE_PAM -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) if (sflg && !cflg) { fprintf (stderr, _("%s: %s flag is only allowed with the %s flag\n"), Prog, "-s", "-c"); usage (EXIT_FAILURE); } -#endif +#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ if (cflg) { if ( (0 != strcmp (crypt_method, "DES")) @@ -751,6 +760,9 @@ static void check_flags (void) #ifdef USE_BCRYPT && (0 != strcmp (crypt_method, "BCRYPT")) #endif /* USE_BCRYPT */ +#ifdef USE_YESCRYPT + && (0 != strcmp (crypt_method, "YESCRYPT")) +#endif /* USE_YESCRYPT */ ) { fprintf (stderr, _("%s: unsupported crypt method: %s\n"), diff --git a/src/passwd.c b/src/passwd.c index 504ab047..b056ee08 100644 --- a/src/passwd.c +++ b/src/passwd.c @@ -283,6 +283,9 @@ static int new_password (const struct passwd *pw) #ifdef USE_BCRYPT || (strcmp (method, "BCRYPT") == 0) #endif /* USE_BCRYPT*/ +#ifdef USE_YESCRYPT + || (strcmp (method, "YESCRYPT") == 0) +#endif /* USE_YESCRYPT*/ ) { pass_max_len = -1;