Merge pull request #179 from seitokaichou/master

WIP: Initial bcrypt support
This commit is contained in:
Serge Hallyn 2019-12-01 11:02:23 -06:00 committed by GitHub
commit 681b66b13c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 374 additions and 64 deletions

View File

@ -277,6 +277,9 @@ AC_ARG_WITH(libcrack,
AC_ARG_WITH(sha-crypt, AC_ARG_WITH(sha-crypt,
[AC_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])], [AC_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])],
[with_sha_crypt=$withval], [with_sha_crypt=yes]) [with_sha_crypt=$withval], [with_sha_crypt=yes])
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(nscd, AC_ARG_WITH(nscd,
[AC_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=yes@:>@])], [AC_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=yes@:>@])],
[with_nscd=$withval], [with_nscd=yes]) [with_nscd=$withval], [with_nscd=yes])
@ -304,6 +307,11 @@ if test "$with_sha_crypt" = "yes"; then
AC_DEFINE(USE_SHA_CRYPT, 1, [Define to allow the SHA256 and SHA512 password encryption algorithms]) AC_DEFINE(USE_SHA_CRYPT, 1, [Define to allow the SHA256 and SHA512 password encryption algorithms])
fi fi
AM_CONDITIONAL(USE_BCRYPT, test "x$with_bcrypt" = "xyes")
if test "$with_bcrypt" = "yes"; then
AC_DEFINE(USE_BCRYPT, 1, [Define to allow the bcrypt password encryption algorithm])
fi
if test "$with_nscd" = "yes"; then if test "$with_nscd" = "yes"; then
AC_CHECK_FUNC(posix_spawn, AC_CHECK_FUNC(posix_spawn,
[AC_DEFINE(USE_NSCD, 1, [Define to support flushing of nscd caches])], [AC_DEFINE(USE_NSCD, 1, [Define to support flushing of nscd caches])],
@ -732,6 +740,7 @@ echo " tcb support (incomplete): $with_tcb"
echo " shadow group support: $enable_shadowgrp" echo " shadow group support: $enable_shadowgrp"
echo " S/Key support: $with_skey" echo " S/Key support: $with_skey"
echo " SHA passwords encryption: $with_sha_crypt" echo " SHA passwords encryption: $with_sha_crypt"
echo " bcrypt passwords encryption: $with_bcrypt"
echo " nscd support: $with_nscd" echo " nscd support: $with_nscd"
echo " sssd support: $with_sssd" echo " sssd support: $with_sssd"
echo " subordinate IDs support: $enable_subids" echo " subordinate IDs support: $enable_subids"

View File

@ -320,6 +320,7 @@ CHFN_RESTRICT rwh
# If set to MD5, MD5-based algorithm will be used for encrypting password # If set to MD5, MD5-based algorithm will be used for encrypting password
# If set to SHA256, SHA256-based algorithm will be used for encrypting password # 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 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 DES, DES-based algorithm will be used for encrypting password (default) # If set to DES, DES-based algorithm will be used for encrypting password (default)
# Overrides the MD5_CRYPT_ENAB option # Overrides the MD5_CRYPT_ENAB option
# #
@ -344,6 +345,21 @@ CHFN_RESTRICT rwh
#SHA_CRYPT_MIN_ROUNDS 5000 #SHA_CRYPT_MIN_ROUNDS 5000
#SHA_CRYPT_MAX_ROUNDS 5000 #SHA_CRYPT_MAX_ROUNDS 5000
#
# Only works if ENCRYPT_METHOD is set to BCRYPT.
#
# Define the number of BCRYPT rounds.
# With a lot of rounds, it is more difficult to brute-force the password.
# However, more CPU resources will be needed to authenticate users if
# this value is increased.
#
# If not specified, 13 rounds will be attempted.
# If only one of the MIN or MAX values is set, then this value will be used.
# If MIN > MAX, the highest value will be used.
#
#BCRYPT_MIN_ROUNDS 13
#BCRYPT_MAX_ROUNDS 13
# #
# List of groups to add to the user's supplementary group set # List of groups to add to the user's supplementary group set
# when logging in from the console (as determined by the CONSOLE # when logging in from the console (as determined by the CONSOLE

View File

@ -65,6 +65,9 @@
case '1': case '1':
method = "MD5"; method = "MD5";
break; break;
case '2':
method = "BCRYPT";
break;
case '5': case '5':
method = "SHA256"; method = "SHA256";
break; break;

View File

@ -110,6 +110,10 @@ static struct itemdef def_table[] = {
#ifdef USE_SHA_CRYPT #ifdef USE_SHA_CRYPT
{"SHA_CRYPT_MAX_ROUNDS", NULL}, {"SHA_CRYPT_MAX_ROUNDS", NULL},
{"SHA_CRYPT_MIN_ROUNDS", NULL}, {"SHA_CRYPT_MIN_ROUNDS", NULL},
#endif
#ifdef USE_BCRYPT
{"BCRYPT_MAX_ROUNDS", NULL},
{"BCRYPT_MIN_ROUNDS", NULL},
#endif #endif
{"SUB_GID_COUNT", NULL}, {"SUB_GID_COUNT", NULL},
{"SUB_GID_MAX", NULL}, {"SUB_GID_MAX", NULL},

View File

@ -268,6 +268,9 @@ static /*@observer@*//*@null@*/const char *obscure_msg (
#ifdef USE_SHA_CRYPT #ifdef USE_SHA_CRYPT
|| (strcmp (result, "SHA256") == 0) || (strcmp (result, "SHA256") == 0)
|| (strcmp (result, "SHA512") == 0) || (strcmp (result, "SHA512") == 0)
#endif
#ifdef USE_BCRYPT
|| (strcmp (result, "BCRYPT") == 0)
#endif #endif
) { ) {
return NULL; return NULL;

View File

@ -22,10 +22,16 @@
/* local function prototypes */ /* local function prototypes */
static void seedRNG (void); static void seedRNG (void);
static /*@observer@*/const char *gensalt (size_t salt_size); static /*@observer@*/const char *gensalt (size_t salt_size);
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
static long shadow_random (long min, long max); static long shadow_random (long min, long max);
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
#ifdef USE_SHA_CRYPT
static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds); static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds);
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT */
#ifdef USE_BCRYPT
static /*@observer@*/const char *gensalt_bcrypt (void);
static /*@observer@*/const char *BCRYPT_salt_rounds (/*@null@*/int *prefered_rounds);
#endif /* USE_BCRYPT */
#ifndef HAVE_L64A #ifndef HAVE_L64A
static /*@observer@*/char *l64a(long value) static /*@observer@*/char *l64a(long value)
@ -79,8 +85,16 @@ static void seedRNG (void)
* Add the salt prefix. * Add the salt prefix.
*/ */
#define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0' #define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0'
#ifdef USE_BCRYPT
/*
* Using the Prefix $2a$ to enable an anti-collision safety measure in musl libc.
* Negatively affects a subset of passwords containing the '\xff' character,
* which is not valid UTF-8 (so "unlikely to cause much annoyance").
*/
#define BCRYPTMAGNUM(array) (array)[0]=(array)[3]='$',(array)[1]='2',(array)[2]='a',(array)[4]='\0'
#endif /* USE_BCRYPT */
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
/* It is not clear what is the maximum value of random(). /* It is not clear what is the maximum value of random().
* We assume 2^31-1.*/ * We assume 2^31-1.*/
#define RANDOM_MAX 0x7FFFFFFF #define RANDOM_MAX 0x7FFFFFFF
@ -105,14 +119,15 @@ static long shadow_random (long min, long max)
} }
return ret; return ret;
} }
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
#ifdef USE_SHA_CRYPT
/* Default number of rounds if not explicitly specified. */ /* Default number of rounds if not explicitly specified. */
#define ROUNDS_DEFAULT 5000 #define ROUNDS_DEFAULT 5000
/* Minimum number of rounds. */ /* Minimum number of rounds. */
#define ROUNDS_MIN 1000 #define ROUNDS_MIN 1000
/* Maximum number of rounds. */ /* Maximum number of rounds. */
#define ROUNDS_MAX 999999999 #define ROUNDS_MAX 999999999
/* /*
* Return a salt prefix specifying the rounds number for the SHA crypt methods. * Return a salt prefix specifying the rounds number for the SHA crypt methods.
*/ */
@ -165,6 +180,89 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds
} }
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT */
#ifdef USE_BCRYPT
/* Default number of rounds if not explicitly specified. */
#define B_ROUNDS_DEFAULT 13
/* Minimum number of rounds. */
#define B_ROUNDS_MIN 4
/* Maximum number of rounds. */
#define B_ROUNDS_MAX 31
/*
* Return a salt prefix specifying the rounds number for the BCRYPT method.
*/
static /*@observer@*/const char *BCRYPT_salt_rounds (/*@null@*/int *prefered_rounds)
{
static char rounds_prefix[4]; /* Max size: 31$ */
long rounds;
if (NULL == prefered_rounds) {
long min_rounds = getdef_long ("BCRYPT_MIN_ROUNDS", -1);
long max_rounds = getdef_long ("BCRYPT_MAX_ROUNDS", -1);
if (((-1 == min_rounds) && (-1 == max_rounds)) || (0 == *prefered_rounds)) {
rounds = B_ROUNDS_DEFAULT;
}
else {
if (-1 == min_rounds) {
min_rounds = max_rounds;
}
if (-1 == max_rounds) {
max_rounds = min_rounds;
}
if (min_rounds > max_rounds) {
max_rounds = min_rounds;
}
rounds = shadow_random (min_rounds, max_rounds);
}
} else {
rounds = *prefered_rounds;
}
/*
* Sanity checks.
* Use 19 as an upper bound for now,
* because musl doesn't allow rounds >= 20.
*/
if (rounds < B_ROUNDS_MIN) {
rounds = B_ROUNDS_MIN;
}
if (rounds > 19) {
/* rounds = B_ROUNDS_MAX; */
rounds = 19;
}
(void) snprintf (rounds_prefix, sizeof rounds_prefix,
"%2.2ld$", rounds);
return rounds_prefix;
}
#define BCRYPT_SALT_SIZE 22
/*
* Generate a 22 character salt string for bcrypt.
*/
static /*@observer@*/const char *gensalt_bcrypt (void)
{
static char salt[32];
salt[0] = '\0';
seedRNG ();
strcat (salt, l64a (random()));
do {
strcat (salt, l64a (random()));
} while (strlen (salt) < BCRYPT_SALT_SIZE);
salt[BCRYPT_SALT_SIZE] = '\0';
return salt;
}
#endif /* USE_BCRYPT */
/* /*
* Generate salt of size salt_size. * Generate salt of size salt_size.
*/ */
@ -230,6 +328,11 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
if (0 == strcmp (method, "MD5")) { if (0 == strcmp (method, "MD5")) {
MAGNUM(result, '1'); MAGNUM(result, '1');
#ifdef USE_BCRYPT
} else if (0 == strcmp (method, "BCRYPT")) {
BCRYPTMAGNUM(result);
strcat(result, BCRYPT_salt_rounds((int *)arg));
#endif /* USE_BCRYPT */
#ifdef USE_SHA_CRYPT #ifdef USE_SHA_CRYPT
} else if (0 == strcmp (method, "SHA256")) { } else if (0 == strcmp (method, "SHA256")) {
MAGNUM(result, '5'); MAGNUM(result, '5');
@ -252,8 +355,18 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
* Concatenate a pseudo random salt. * Concatenate a pseudo random salt.
*/ */
assert (sizeof (result) > strlen (result) + salt_len); assert (sizeof (result) > strlen (result) + salt_len);
#ifdef USE_BCRYPT
if (0 == strcmp (method, "BCRYPT")) {
strncat (result, gensalt_bcrypt (),
sizeof (result) - strlen (result) - 1);
return result;
} else {
#endif /* USE_BCRYPT */
strncat (result, gensalt (salt_len), strncat (result, gensalt (salt_len),
sizeof (result) - strlen (result) - 1); sizeof (result) - strlen (result) - 1);
#ifdef USE_BCRYPT
}
#endif /* USE_BCRYPT */
return result; return result;
} }

View File

@ -61,15 +61,18 @@
const char *Prog; const char *Prog;
static bool eflg = false; static bool eflg = false;
static bool md5flg = false; static bool md5flg = false;
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
static bool sflg = false; static bool sflg = false;
#endif #endif /* USE_SHA_CRYPT || USE_BCRYPT */
static /*@null@*//*@observer@*/const char *crypt_method = NULL; static /*@null@*//*@observer@*/const char *crypt_method = NULL;
#define cflg (NULL != crypt_method) #define cflg (NULL != crypt_method)
#ifdef USE_SHA_CRYPT #ifdef USE_SHA_CRYPT
static long sha_rounds = 5000; static long sha_rounds = 5000;
#endif #endif
#ifdef USE_BCRYPT
static long bcrypt_rounds = 13;
#endif
#ifdef SHADOWGRP #ifdef SHADOWGRP
static bool is_shadow_grp; static bool is_shadow_grp;
@ -125,11 +128,15 @@ static /*@noreturn@*/void usage (int status)
Prog); Prog);
(void) fprintf (usageout, (void) fprintf (usageout,
_(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"),
#ifndef USE_SHA_CRYPT #if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT)
"NONE DES MD5" "NONE DES MD5"
#else /* USE_SHA_CRYPT */ #elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
"NONE DES MD5 SHA256 SHA512 BCRYPT"
#elif defined(USE_SHA_CRYPT)
"NONE DES MD5 SHA256 SHA512" "NONE DES MD5 SHA256 SHA512"
#endif /* USE_SHA_CRYPT */ #else
"NONE DES MD5 BCRYPT"
#endif
); );
(void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout); (void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout);
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout); (void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
@ -137,11 +144,11 @@ static /*@noreturn@*/void usage (int status)
" the MD5 algorithm\n"), " the MD5 algorithm\n"),
usageout); usageout);
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
(void) fputs (_(" -s, --sha-rounds number of SHA rounds for the SHA*\n" (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n"
" crypt algorithms\n"), " crypt algorithms\n"),
usageout); usageout);
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT || USE_BCRYPT */
(void) fputs ("\n", usageout); (void) fputs ("\n", usageout);
exit (status); exit (status);
@ -161,14 +168,13 @@ static void process_flags (int argc, char **argv)
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"md5", no_argument, NULL, 'm'}, {"md5", no_argument, NULL, 'm'},
{"root", required_argument, NULL, 'R'}, {"root", required_argument, NULL, 'R'},
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
{"sha-rounds", required_argument, NULL, 's'}, {"sha-rounds", required_argument, NULL, 's'},
#endif #endif /* USE_SHA_CRYPT || USE_BCRYPT */
{NULL, 0, NULL, '\0'} {NULL, 0, NULL, '\0'}
}; };
while ((c = getopt_long (argc, argv, while ((c = getopt_long (argc, argv,
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
"c:ehmR:s:", "c:ehmR:s:",
#else #else
"c:ehmR:", "c:ehmR:",
@ -189,10 +195,33 @@ static void process_flags (int argc, char **argv)
break; break;
case 'R': /* no-op, handled in process_root_flag () */ case 'R': /* no-op, handled in process_root_flag () */
break; break;
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
case 's': case 's':
sflg = true; sflg = true;
if (getlong(optarg, &sha_rounds) == 0) { if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
&& (0 == getlong(optarg, &sha_rounds)))
|| ( (0 == strcmp (crypt_method, "BCRYPT"))
&& (0 == getlong(optarg, &bcrypt_rounds)))) {
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, fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"), _("%s: invalid numeric argument '%s'\n"),
Prog, optarg); Prog, optarg);
@ -200,6 +229,7 @@ static void process_flags (int argc, char **argv)
} }
break; break;
#endif #endif
default: default:
usage (E_USAGE); usage (E_USAGE);
/*@notreached@*/break; /*@notreached@*/break;
@ -217,7 +247,7 @@ static void process_flags (int argc, char **argv)
*/ */
static void check_flags (void) static void check_flags (void)
{ {
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
if (sflg && !cflg) { if (sflg && !cflg) {
fprintf (stderr, fprintf (stderr,
_("%s: %s flag is only allowed with the %s flag\n"), _("%s: %s flag is only allowed with the %s flag\n"),
@ -241,6 +271,9 @@ static void check_flags (void)
#ifdef USE_SHA_CRYPT #ifdef USE_SHA_CRYPT
&& (0 != strcmp (crypt_method, "SHA256")) && (0 != strcmp (crypt_method, "SHA256"))
&& (0 != strcmp (crypt_method, "SHA512")) && (0 != strcmp (crypt_method, "SHA512"))
#endif
#ifdef USE_BCRYPT
&& (0 != strcmp (crypt_method, "BCRYPT"))
#endif #endif
) { ) {
fprintf (stderr, fprintf (stderr,
@ -464,10 +497,24 @@ int main (int argc, char **argv)
if (md5flg) { if (md5flg) {
crypt_method = "MD5"; crypt_method = "MD5";
} }
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
if (sflg) {
if ( (0 == strcmp (crypt_method, "SHA256"))
|| (0 == strcmp (crypt_method, "SHA512"))) {
arg = &sha_rounds;
}
else if (0 == strcmp (crypt_method, "BCRYPT")) {
arg = &bcrypt_rounds;
}
}
#elif defined(USE_SHA_CRYPT)
if (sflg) { if (sflg) {
arg = &sha_rounds; arg = &sha_rounds;
} }
#elif defined(USE_BCRYPT)
if (sflg) {
arg = &bcrypt_rounds;
}
#endif #endif
salt = crypt_make_salt (crypt_method, arg); salt = crypt_make_salt (crypt_method, arg);
cp = pw_encrypt (newpwd, salt); cp = pw_encrypt (newpwd, salt);

View File

@ -58,15 +58,18 @@
const char *Prog; const char *Prog;
static bool eflg = false; static bool eflg = false;
static bool md5flg = false; static bool md5flg = false;
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
static bool sflg = false; static bool sflg = false;
#endif /* USE_SHA_CRYPT */ #endif
static /*@null@*//*@observer@*/const char *crypt_method = NULL; static /*@null@*//*@observer@*/const char *crypt_method = NULL;
#define cflg (NULL != crypt_method) #define cflg (NULL != crypt_method)
#ifdef USE_SHA_CRYPT #ifdef USE_SHA_CRYPT
static long sha_rounds = 5000; static long sha_rounds = 5000;
#endif /* USE_SHA_CRYPT */ #endif
#ifdef USE_BCRYPT
static long bcrypt_rounds = 13;
#endif
static bool is_shadow_pwd; static bool is_shadow_pwd;
static bool pw_locked = false; static bool pw_locked = false;
@ -118,11 +121,15 @@ static /*@noreturn@*/void usage (int status)
Prog); Prog);
(void) fprintf (usageout, (void) fprintf (usageout,
_(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"),
#ifndef USE_SHA_CRYPT #if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT)
"NONE DES MD5" "NONE DES MD5"
#else /* USE_SHA_CRYPT */ #elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
"NONE DES MD5 SHA256 SHA512 BCRYPT"
#elif defined(USE_SHA_CRYPT)
"NONE DES MD5 SHA256 SHA512" "NONE DES MD5 SHA256 SHA512"
#endif /* USE_SHA_CRYPT */ #else
"NONE DES MD5 BCRYPT"
#endif
); );
(void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout); (void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout);
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout); (void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
@ -130,11 +137,11 @@ static /*@noreturn@*/void usage (int status)
" the MD5 algorithm\n"), " the MD5 algorithm\n"),
usageout); usageout);
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
(void) fputs (_(" -s, --sha-rounds number of SHA rounds for the SHA*\n" (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n"
" crypt algorithms\n"), " crypt algorithms\n"),
usageout); usageout);
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT || USE_BCRYPT */
(void) fputs ("\n", usageout); (void) fputs ("\n", usageout);
exit (status); exit (status);
@ -154,18 +161,18 @@ static void process_flags (int argc, char **argv)
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"md5", no_argument, NULL, 'm'}, {"md5", no_argument, NULL, 'm'},
{"root", required_argument, NULL, 'R'}, {"root", required_argument, NULL, 'R'},
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
{"sha-rounds", required_argument, NULL, 's'}, {"sha-rounds", required_argument, NULL, 's'},
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT || USE_BCRYPT */
{NULL, 0, NULL, '\0'} {NULL, 0, NULL, '\0'}
}; };
while ((c = getopt_long (argc, argv, while ((c = getopt_long (argc, argv,
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
"c:ehmR:s:", "c:ehmR:s:",
#else /* !USE_SHA_CRYPT */ #else
"c:ehmR:", "c:ehmR:",
#endif /* !USE_SHA_CRYPT */ #endif
long_options, NULL)) != -1) { long_options, NULL)) != -1) {
switch (c) { switch (c) {
case 'c': case 'c':
@ -182,17 +189,41 @@ static void process_flags (int argc, char **argv)
break; break;
case 'R': /* no-op, handled in process_root_flag () */ case 'R': /* no-op, handled in process_root_flag () */
break; break;
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
case 's': case 's':
sflg = true; sflg = true;
if (getlong(optarg, &sha_rounds) == 0) { if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
&& (0 == getlong(optarg, &sha_rounds)))
|| ( (0 == strcmp (crypt_method, "BCRYPT"))
&& (0 == getlong(optarg, &bcrypt_rounds)))) {
fprintf (stderr, fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"), _("%s: invalid numeric argument '%s'\n"),
Prog, optarg); Prog, optarg);
usage (E_USAGE); usage (E_USAGE);
} }
break; break;
#endif /* USE_SHA_CRYPT */ #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
default: default:
usage (E_USAGE); usage (E_USAGE);
/*@notreached@*/break; /*@notreached@*/break;
@ -210,7 +241,7 @@ static void process_flags (int argc, char **argv)
*/ */
static void check_flags (void) static void check_flags (void)
{ {
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
if (sflg && !cflg) { if (sflg && !cflg) {
fprintf (stderr, fprintf (stderr,
_("%s: %s flag is only allowed with the %s flag\n"), _("%s: %s flag is only allowed with the %s flag\n"),
@ -235,6 +266,9 @@ static void check_flags (void)
&& (0 != strcmp (crypt_method, "SHA256")) && (0 != strcmp (crypt_method, "SHA256"))
&& (0 != strcmp (crypt_method, "SHA512")) && (0 != strcmp (crypt_method, "SHA512"))
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT */
#ifdef USE_BCRYPT
&& (0 != strcmp (crypt_method, "BCRYPT"))
#endif /* USE_BCRYPT */
) { ) {
fprintf (stderr, fprintf (stderr,
_("%s: unsupported crypt method: %s\n"), _("%s: unsupported crypt method: %s\n"),
@ -496,10 +530,24 @@ int main (int argc, char **argv)
if (md5flg) { if (md5flg) {
crypt_method = "MD5"; crypt_method = "MD5";
} }
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
if (sflg) {
if ( (0 == strcmp (crypt_method, "SHA256"))
|| (0 == strcmp (crypt_method, "SHA512"))) {
arg = &sha_rounds;
}
else if (0 == strcmp (crypt_method, "BCRYPT")) {
arg = &bcrypt_rounds;
}
}
#elif defined(USE_SHA_CRYPT)
if (sflg) { if (sflg) {
arg = &sha_rounds; arg = &sha_rounds;
} }
#elif defined(USE_BCRYPT)
if (sflg) {
arg = &bcrypt_rounds;
}
#endif #endif
salt = crypt_make_salt (crypt_method, arg); salt = crypt_make_salt (crypt_method, arg);
cp = pw_encrypt (newpwd, salt); cp = pw_encrypt (newpwd, salt);

View File

@ -80,10 +80,15 @@ static bool rflg = false; /* create a system account */
#ifndef USE_PAM #ifndef USE_PAM
static /*@null@*//*@observer@*/char *crypt_method = NULL; static /*@null@*//*@observer@*/char *crypt_method = NULL;
#define cflg (NULL != crypt_method) #define cflg (NULL != crypt_method)
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
static bool sflg = false; static bool sflg = false;
#endif
#ifdef USE_SHA_CRYPT
static long sha_rounds = 5000; static long sha_rounds = 5000;
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT */
#ifdef USE_BCRYPT
static long bcrypt_rounds = 13;
#endif /* USE_BCRYPT */
#endif /* !USE_PAM */ #endif /* !USE_PAM */
static bool is_shadow; static bool is_shadow;
@ -134,22 +139,26 @@ static void usage (int status)
#ifndef USE_PAM #ifndef USE_PAM
(void) fprintf (usageout, (void) fprintf (usageout,
_(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"),
#ifndef USE_SHA_CRYPT #if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT)
"NONE DES MD5" "NONE DES MD5"
#else /* USE_SHA_CRYPT */ #elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
"NONE DES MD5 SHA256 SHA512 BCRYPT"
#elif defined(USE_SHA_CRYPT)
"NONE DES MD5 SHA256 SHA512" "NONE DES MD5 SHA256 SHA512"
#endif /* USE_SHA_CRYPT */ #else
"NONE DES MD5 BCRYPT"
#endif
); );
#endif /* !USE_PAM */ #endif /* !USE_PAM */
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout); (void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
(void) fputs (_(" -r, --system create system accounts\n"), usageout); (void) fputs (_(" -r, --system create system accounts\n"), usageout);
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
#ifndef USE_PAM #ifndef USE_PAM
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
(void) fputs (_(" -s, --sha-rounds number of SHA rounds for the SHA*\n" (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n"
" crypt algorithms\n"), " crypt algorithms\n"),
usageout); usageout);
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT || USE_BCRYPT */
#endif /* !USE_PAM */ #endif /* !USE_PAM */
(void) fputs ("\n", usageout); (void) fputs ("\n", usageout);
@ -423,15 +432,29 @@ static int update_passwd (struct passwd *pwd, const char *password)
{ {
void *crypt_arg = NULL; void *crypt_arg = NULL;
char *cp; char *cp;
if (crypt_method != NULL) { if (NULL != crypt_method) {
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
if (sflg) {
if ( (0 == strcmp (crypt_method, "SHA256"))
|| (0 == strcmp (crypt_method, "SHA512"))) {
crypt_arg = &sha_rounds;
}
else if (0 == strcmp (crypt_method, "BCRYPT")) {
crypt_arg = &bcrypt_rounds;
}
}
#elif defined(USE_SHA_CRYPT)
if (sflg) { if (sflg) {
crypt_arg = &sha_rounds; crypt_arg = &sha_rounds;
} }
#elif defined(USE_BCRYPT)
if (sflg) {
crypt_arg = &bcrypt_rounds;
}
#endif #endif
} }
if ((crypt_method != NULL) && (0 == strcmp(crypt_method, "NONE"))) { if ((NULL != crypt_method) && (0 == strcmp(crypt_method, "NONE"))) {
pwd->pw_passwd = (char *)password; pwd->pw_passwd = (char *)password;
} else { } else {
const char *salt = crypt_make_salt (crypt_method, crypt_arg); const char *salt = crypt_make_salt (crypt_method, crypt_arg);
@ -460,12 +483,26 @@ static int add_passwd (struct passwd *pwd, const char *password)
#ifndef USE_PAM #ifndef USE_PAM
void *crypt_arg = NULL; void *crypt_arg = NULL;
if (crypt_method != NULL) { if (NULL != crypt_method) {
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
if (sflg) {
if ( (0 == strcmp (crypt_method, "SHA256"))
|| (0 == strcmp (crypt_method, "SHA512"))) {
crypt_arg = &sha_rounds;
}
else if (0 == strcmp (crypt_method, "BCRYPT")) {
crypt_arg = &bcrypt_rounds;
}
}
#elif defined(USE_SHA_CRYPT)
if (sflg) { if (sflg) {
crypt_arg = &sha_rounds; crypt_arg = &sha_rounds;
} }
#endif /* USE_SHA_CRYPT */ #elif defined(USE_BCRYPT)
if (sflg) {
crypt_arg = &bcrypt_rounds;
}
#endif
} }
/* /*
@ -591,20 +628,20 @@ static void process_flags (int argc, char **argv)
{"system", no_argument, NULL, 'r'}, {"system", no_argument, NULL, 'r'},
{"root", required_argument, NULL, 'R'}, {"root", required_argument, NULL, 'R'},
#ifndef USE_PAM #ifndef USE_PAM
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
{"sha-rounds", required_argument, NULL, 's'}, {"sha-rounds", required_argument, NULL, 's'},
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT || USE_BCRYPT */
#endif /* !USE_PAM */ #endif /* !USE_PAM */
{NULL, 0, NULL, '\0'} {NULL, 0, NULL, '\0'}
}; };
while ((c = getopt_long (argc, argv, while ((c = getopt_long (argc, argv,
#ifndef USE_PAM #ifndef USE_PAM
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
"c:bhrs:", "c:bhrs:",
#else /* !USE_SHA_CRYPT */ #else /* !USE_SHA_CRYPT && !USE_BCRYPT */
"c:bhr", "c:bhr",
#endif /* !USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT || USE_BCRYPT */
#else /* USE_PAM */ #else /* USE_PAM */
"bhr", "bhr",
#endif #endif
@ -627,17 +664,40 @@ static void process_flags (int argc, char **argv)
case 'R': /* no-op, handled in process_root_flag () */ case 'R': /* no-op, handled in process_root_flag () */
break; break;
#ifndef USE_PAM #ifndef USE_PAM
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
case 's': case 's':
sflg = true; sflg = true;
if (getlong(optarg, &sha_rounds) == 0) { if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
&& (0 == getlong(optarg, &sha_rounds)))
|| ( (0 == strcmp (crypt_method, "BCRYPT"))
&& (0 == getlong(optarg, &bcrypt_rounds)))) {
fprintf (stderr, fprintf (stderr,
_("%s: invalid numeric argument '%s'\n"), _("%s: invalid numeric argument '%s'\n"),
Prog, optarg); Prog, optarg);
usage (EXIT_FAILURE); usage (EXIT_FAILURE);
} }
break; break;
#endif /* USE_SHA_CRYPT */ #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_PAM */ #endif /* !USE_PAM */
default: default:
usage (EXIT_FAILURE); usage (EXIT_FAILURE);
@ -671,14 +731,14 @@ static void process_flags (int argc, char **argv)
static void check_flags (void) static void check_flags (void)
{ {
#ifndef USE_PAM #ifndef USE_PAM
#ifdef USE_SHA_CRYPT #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
if (sflg && !cflg) { if (sflg && !cflg) {
fprintf (stderr, fprintf (stderr,
_("%s: %s flag is only allowed with the %s flag\n"), _("%s: %s flag is only allowed with the %s flag\n"),
Prog, "-s", "-c"); Prog, "-s", "-c");
usage (EXIT_FAILURE); usage (EXIT_FAILURE);
} }
#endif /* USE_SHA_CRYPT */ #endif
if (cflg) { if (cflg) {
if ( (0 != strcmp (crypt_method, "DES")) if ( (0 != strcmp (crypt_method, "DES"))
@ -688,6 +748,9 @@ static void check_flags (void)
&& (0 != strcmp (crypt_method, "SHA256")) && (0 != strcmp (crypt_method, "SHA256"))
&& (0 != strcmp (crypt_method, "SHA512")) && (0 != strcmp (crypt_method, "SHA512"))
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT */
#ifdef USE_BCRYPT
&& (0 != strcmp (crypt_method, "BCRYPT"))
#endif /* USE_BCRYPT */
) { ) {
fprintf (stderr, fprintf (stderr,
_("%s: unsupported crypt method: %s\n"), _("%s: unsupported crypt method: %s\n"),

View File

@ -280,6 +280,10 @@ static int new_password (const struct passwd *pw)
|| (strcmp (method, "SHA256") == 0) || (strcmp (method, "SHA256") == 0)
|| (strcmp (method, "SHA512") == 0) || (strcmp (method, "SHA512") == 0)
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT */
#ifdef USE_BCRYPT
|| (strcmp (method, "BCRYPT") == 0)
#endif /* USE_SHA_CRYPT */
) { ) {
pass_max_len = -1; pass_max_len = -1;
} else { } else {