]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
Initial bcrypt support 179/head
authorprez <prez@national.shitposting.agency>
Mon, 16 Sep 2019 18:54:56 +0000 (20:54 +0200)
committerSerge Hallyn <shallyn@cisco.com>
Sun, 1 Dec 2019 17:00:57 +0000 (11:00 -0600)
configure.ac
etc/login.defs
lib/encrypt.c
lib/getdef.c
libmisc/obscure.c
libmisc/salt.c
src/chgpasswd.c
src/chpasswd.c
src/newusers.c
src/passwd.c

index a97d39172e25b25eddef40e70f9342ec5a486239..d0443460e1c015551926896dfee3ba9e0f8a88c1 100644 (file)
@@ -277,6 +277,9 @@ AC_ARG_WITH(libcrack,
 AC_ARG_WITH(sha-crypt,
        [AC_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=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_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=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])
 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
        AC_CHECK_FUNC(posix_spawn,
                      [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 " S/Key support:                  $with_skey"
 echo " SHA passwords encryption:       $with_sha_crypt"
+echo " bcrypt passwords encryption:    $with_bcrypt"
 echo " nscd support:                   $with_nscd"
 echo " sssd support:                   $with_sssd"
 echo " subordinate IDs support:        $enable_subids"
index f235e1b4bf3242da1853303e1fcbfba93fe86266..cd2597dc28859f5841df3144dc7f86ddfc480295 100644 (file)
@@ -320,6 +320,7 @@ CHFN_RESTRICT               rwh
 # 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 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)
 # Overrides the MD5_CRYPT_ENAB option
 #
@@ -344,6 +345,21 @@ CHFN_RESTRICT              rwh
 #SHA_CRYPT_MIN_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
 # when logging in from the console (as determined by the CONSOLE
index 53c99c94806f24fd1a2490625c6617de6c0ccd8e..4247f2412031c0fdb5a4e3869b357001f7103b47 100644 (file)
@@ -65,6 +65,9 @@
                        case '1':
                                method = "MD5";
                                break;
+                       case '2':
+                               method = "BCRYPT";
+                               break;
                        case '5':
                                method = "SHA256";
                                break;
index 939aea29908346f7c102cdceeb07a4b90771f4fb..bbb273f417756845072a922363494c4078dbce1b 100644 (file)
@@ -110,6 +110,10 @@ static struct itemdef def_table[] = {
 #ifdef USE_SHA_CRYPT
        {"SHA_CRYPT_MAX_ROUNDS", NULL},
        {"SHA_CRYPT_MIN_ROUNDS", NULL},
+#endif
+#ifdef USE_BCRYPT
+       {"BCRYPT_MAX_ROUNDS", NULL},
+       {"BCRYPT_MIN_ROUNDS", NULL},
 #endif
        {"SUB_GID_COUNT", NULL},
        {"SUB_GID_MAX", NULL},
index a075123703052cbd56c716e18564a7c0ba409aab..15da760304d1da6d454f71d9f487e914422a77ea 100644 (file)
@@ -268,6 +268,9 @@ static /*@observer@*//*@null@*/const char *obscure_msg (
 #ifdef USE_SHA_CRYPT
                    || (strcmp (result, "SHA256") == 0)
                    || (strcmp (result, "SHA512") == 0)
+#endif
+#ifdef USE_BCRYPT
+                   || (strcmp (result, "BCRYPT") == 0)
 #endif
                    ) {
                        return NULL;
index c72447ea78bc9cb8c30ebb7ad94e5226d2d6299a..e1a7ac8075d8550154c3d9360be2f1fcc1ea14b8 100644 (file)
 /* local function prototypes */
 static void seedRNG (void);
 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);
+#endif /* USE_SHA_CRYPT || USE_BCRYPT */
+#ifdef USE_SHA_CRYPT
 static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds);
 #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
 static /*@observer@*/char *l64a(long value)
@@ -79,8 +85,16 @@ static void seedRNG (void)
  * Add the salt prefix.
  */
 #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().
  * We assume 2^31-1.*/
 #define RANDOM_MAX 0x7FFFFFFF
@@ -105,14 +119,15 @@ static long shadow_random (long min, long max)
        }
        return ret;
 }
+#endif /* USE_SHA_CRYPT || USE_BCRYPT */
 
+#ifdef USE_SHA_CRYPT
 /* Default number of rounds if not explicitly specified.  */
 #define ROUNDS_DEFAULT 5000
 /* Minimum number of rounds.  */
 #define ROUNDS_MIN 1000
 /* Maximum number of rounds.  */
 #define ROUNDS_MAX 999999999
-
 /*
  * 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 */
 
+#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.
  */
@@ -230,6 +328,11 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
 
        if (0 == strcmp (method, "MD5")) {
                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
        } else if (0 == strcmp (method, "SHA256")) {
                MAGNUM(result, '5');
@@ -252,8 +355,18 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
         * Concatenate a pseudo random salt.
         */
        assert (sizeof (result) > strlen (result) + salt_len);
-       strncat (result, gensalt (salt_len),
-                sizeof (result) - strlen (result) - 1);
+#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),
+                        sizeof (result) - strlen (result) - 1);
+#ifdef USE_BCRYPT
+       }
+#endif /* USE_BCRYPT */        
 
        return result;
 }
index e5f2eb7e86077931772cb5a07d1a77e1077427d2..4013abb38a847ebbb6d1025f5c6365f7a114ac66 100644 (file)
 const char *Prog;
 static bool eflg   = false;
 static bool md5flg = false;
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
 static bool sflg   = false;
-#endif
+#endif /* USE_SHA_CRYPT || USE_BCRYPT */
 
 static /*@null@*//*@observer@*/const char *crypt_method = NULL;
 #define cflg (NULL != crypt_method)
 #ifdef USE_SHA_CRYPT
 static long sha_rounds = 5000;
 #endif
+#ifdef USE_BCRYPT
+static long bcrypt_rounds = 13;
+#endif
 
 #ifdef SHADOWGRP
 static bool is_shadow_grp;
@@ -125,11 +128,15 @@ static /*@noreturn@*/void usage (int status)
                        Prog);
        (void) fprintf (usageout,
                        _("  -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"
-#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"
-#endif                         /* USE_SHA_CRYPT */
+#else
+                       "NONE DES MD5 BCRYPT"
+#endif
                       );
        (void) fputs (_("  -e, --encrypted               supplied passwords are encrypted\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"),
                      usageout);
        (void) fputs (_("  -R, --root CHROOT_DIR         directory to chroot into\n"), usageout);
-#ifdef USE_SHA_CRYPT
-       (void) fputs (_("  -s, --sha-rounds              number of SHA rounds for the SHA*\n"
+#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"),
                      usageout);
-#endif                         /* USE_SHA_CRYPT */
+#endif                         /* USE_SHA_CRYPT || USE_BCRYPT */
        (void) fputs ("\n", usageout);
 
        exit (status);
@@ -161,14 +168,13 @@ static void process_flags (int argc, char **argv)
                {"help",         no_argument,       NULL, 'h'},
                {"md5",          no_argument,       NULL, 'm'},
                {"root",         required_argument, NULL, 'R'},
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
                {"sha-rounds",   required_argument, NULL, 's'},
-#endif
+#endif                         /* USE_SHA_CRYPT || USE_BCRYPT */
                {NULL, 0, NULL, '\0'}
        };
-
        while ((c = getopt_long (argc, argv,
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
                                 "c:ehmR:s:",
 #else
                                 "c:ehmR:",
@@ -189,10 +195,33 @@ static void process_flags (int argc, char **argv)
                        break;
                case 'R': /* no-op, handled in process_root_flag () */
                        break;
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
                case 's':
                        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,
                                         _("%s: invalid numeric argument '%s'\n"),
                                         Prog, optarg);
@@ -200,6 +229,7 @@ static void process_flags (int argc, char **argv)
                        }
                        break;
 #endif
+
                default:
                        usage (E_USAGE);
                        /*@notreached@*/break;
@@ -217,7 +247,7 @@ static void process_flags (int argc, char **argv)
  */
 static void check_flags (void)
 {
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
        if (sflg && !cflg) {
                fprintf (stderr,
                         _("%s: %s flag is only allowed with the %s flag\n"),
@@ -241,6 +271,9 @@ static void check_flags (void)
 #ifdef USE_SHA_CRYPT
                    && (0 != strcmp (crypt_method, "SHA256"))
                    && (0 != strcmp (crypt_method, "SHA512"))
+#endif
+#ifdef USE_BCRYPT
+                   && (0 != strcmp (crypt_method, "BCRYPT"))
 #endif
                    ) {
                        fprintf (stderr,
@@ -464,10 +497,24 @@ int main (int argc, char **argv)
                        if (md5flg) {
                                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) {
                                arg = &sha_rounds;
                        }
+#elif defined(USE_BCRYPT)
+                       if (sflg) {
+                               arg = &bcrypt_rounds;
+                       }
 #endif
                        salt = crypt_make_salt (crypt_method, arg);
                        cp = pw_encrypt (newpwd, salt);
index d1c1043aaec2018e13c93d988a695f6763197c20..be61e0388970c635c54eb8f5e4c8e53489b5edb9 100644 (file)
 const char *Prog;
 static bool eflg   = false;
 static bool md5flg = false;
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
 static bool sflg   = false;
-#endif                         /* USE_SHA_CRYPT */
+#endif
 
 static /*@null@*//*@observer@*/const char *crypt_method = NULL;
 #define cflg (NULL != crypt_method)
 #ifdef USE_SHA_CRYPT
 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 pw_locked = false;
@@ -118,11 +121,15 @@ static /*@noreturn@*/void usage (int status)
                        Prog);
        (void) fprintf (usageout,
                        _("  -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"
-#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"
-#endif                         /* USE_SHA_CRYPT */
+#else
+                       "NONE DES MD5 BCRYPT"
+#endif
                       );
        (void) fputs (_("  -e, --encrypted               supplied passwords are encrypted\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"),
                      usageout);
        (void) fputs (_("  -R, --root CHROOT_DIR         directory to chroot into\n"), usageout);
-#ifdef USE_SHA_CRYPT
-       (void) fputs (_("  -s, --sha-rounds              number of SHA rounds for the SHA*\n"
+#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"),
                      usageout);
-#endif                         /* USE_SHA_CRYPT */
+#endif                         /* USE_SHA_CRYPT || USE_BCRYPT */
        (void) fputs ("\n", usageout);
 
        exit (status);
@@ -154,18 +161,18 @@ static void process_flags (int argc, char **argv)
                {"help",         no_argument,       NULL, 'h'},
                {"md5",          no_argument,       NULL, 'm'},
                {"root",         required_argument, NULL, 'R'},
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
                {"sha-rounds",   required_argument, NULL, 's'},
-#endif                         /* USE_SHA_CRYPT */
+#endif                         /* USE_SHA_CRYPT || USE_BCRYPT */
                {NULL, 0, NULL, '\0'}
        };
 
        while ((c = getopt_long (argc, argv,
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
                                 "c:ehmR:s:",
-#else                          /* !USE_SHA_CRYPT */
+#else
                                 "c:ehmR:",
-#endif                         /* !USE_SHA_CRYPT */
+#endif
                                 long_options, NULL)) != -1) {
                switch (c) {
                case 'c':
@@ -182,17 +189,41 @@ static void process_flags (int argc, char **argv)
                        break;
                case 'R': /* no-op, handled in process_root_flag () */
                        break;
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
                case 's':
                        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;
-#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:
                        usage (E_USAGE);
                        /*@notreached@*/break;
@@ -210,7 +241,7 @@ static void process_flags (int argc, char **argv)
  */
 static void check_flags (void)
 {
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
        if (sflg && !cflg) {
                fprintf (stderr,
                         _("%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, "SHA512"))
 #endif                         /* USE_SHA_CRYPT */
+#ifdef USE_BCRYPT
+                   && (0 != strcmp (crypt_method, "BCRYPT"))
+#endif                         /* USE_BCRYPT */
                    ) {
                        fprintf (stderr,
                                 _("%s: unsupported crypt method: %s\n"),
@@ -496,10 +530,24 @@ int main (int argc, char **argv)
                        if (md5flg) {
                                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) {
                                arg = &sha_rounds;
                        }
+#elif defined(USE_BCRYPT)
+                       if (sflg) {
+                               arg = &bcrypt_rounds;
+                       }
 #endif
                        salt = crypt_make_salt (crypt_method, arg);
                        cp = pw_encrypt (newpwd, salt);
index bf63f4b56629585c2d070a971ba4bc1a21535bda..99c69f780c9e4a1b426243ebb459e108b32654d0 100644 (file)
@@ -80,10 +80,15 @@ static bool rflg = false;   /* create a system account */
 #ifndef USE_PAM
 static /*@null@*//*@observer@*/char *crypt_method = NULL;
 #define cflg (NULL != crypt_method)
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
 static bool sflg = false;
+#endif
+#ifdef USE_SHA_CRYPT
 static long sha_rounds = 5000;
 #endif                         /* USE_SHA_CRYPT */
+#ifdef USE_BCRYPT
+static long bcrypt_rounds = 13;
+#endif                         /* USE_BCRYPT */
 #endif                         /* !USE_PAM */
 
 static bool is_shadow;
@@ -134,22 +139,26 @@ static void usage (int status)
 #ifndef USE_PAM
        (void) fprintf (usageout,
                        _("  -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"
-#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"
-#endif                         /* USE_SHA_CRYPT */
+#else
+                       "NONE DES MD5 BCRYPT"
+#endif
                       );
 #endif                         /* !USE_PAM */
        (void) fputs (_("  -h, --help                    display this help message and exit\n"), usageout);
        (void) fputs (_("  -r, --system                  create system accounts\n"), usageout);
        (void) fputs (_("  -R, --root CHROOT_DIR         directory to chroot into\n"), usageout);
 #ifndef USE_PAM
-#ifdef USE_SHA_CRYPT
-       (void) fputs (_("  -s, --sha-rounds              number of SHA rounds for the SHA*\n"
+#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"),
                      usageout);
-#endif                         /* USE_SHA_CRYPT */
+#endif                         /* USE_SHA_CRYPT || USE_BCRYPT */
 #endif                         /* !USE_PAM */
        (void) fputs ("\n", usageout);
 
@@ -423,15 +432,29 @@ static int update_passwd (struct passwd *pwd, const char *password)
 {
        void *crypt_arg = NULL;
        char *cp;
-       if (crypt_method != NULL) {
-#ifdef USE_SHA_CRYPT
+       if (NULL != crypt_method) {
+#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) {
                        crypt_arg = &sha_rounds;
                }
+#elif defined(USE_BCRYPT)
+               if (sflg) {
+                       crypt_arg = &bcrypt_rounds;
+               }
 #endif
        }
 
-       if ((crypt_method != NULL) && (0 == strcmp(crypt_method, "NONE"))) {
+       if ((NULL != crypt_method) && (0 == strcmp(crypt_method, "NONE"))) {
                pwd->pw_passwd = (char *)password;
        } else {
                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
        void *crypt_arg = NULL;
-       if (crypt_method != NULL) {
-#ifdef USE_SHA_CRYPT
+       if (NULL != crypt_method) {
+#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) {
                        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'},
                {"root",         required_argument, NULL, 'R'},
 #ifndef USE_PAM
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
                {"sha-rounds",   required_argument, NULL, 's'},
-#endif                         /* USE_SHA_CRYPT */
+#endif                         /* USE_SHA_CRYPT || USE_BCRYPT */
 #endif                         /* !USE_PAM */
                {NULL, 0, NULL, '\0'}
        };
 
        while ((c = getopt_long (argc, argv,
 #ifndef USE_PAM
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
                                 "c:bhrs:",
-#else                          /* !USE_SHA_CRYPT */
+#else                          /* !USE_SHA_CRYPT && !USE_BCRYPT */
                                 "c:bhr",
-#endif                         /* !USE_SHA_CRYPT */
+#endif                         /* USE_SHA_CRYPT || USE_BCRYPT */
 #else                          /* USE_PAM */
                                 "bhr",
 #endif
@@ -627,17 +664,40 @@ static void process_flags (int argc, char **argv)
                case 'R': /* no-op, handled in process_root_flag () */
                        break;
 #ifndef USE_PAM
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT)
                case 's':
                        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 (EXIT_FAILURE);
                        }
                        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 */
                default:
                        usage (EXIT_FAILURE);
@@ -671,14 +731,14 @@ static void process_flags (int argc, char **argv)
 static void check_flags (void)
 {
 #ifndef USE_PAM
-#ifdef USE_SHA_CRYPT
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
        if (sflg && !cflg) {
                fprintf (stderr,
                         _("%s: %s flag is only allowed with the %s flag\n"),
                         Prog, "-s", "-c");
                usage (EXIT_FAILURE);
        }
-#endif                         /* USE_SHA_CRYPT */
+#endif
 
        if (cflg) {
                if (   (0 != strcmp (crypt_method, "DES"))
@@ -688,6 +748,9 @@ static void check_flags (void)
                    && (0 != strcmp (crypt_method, "SHA256"))
                    && (0 != strcmp (crypt_method, "SHA512"))
 #endif                         /* USE_SHA_CRYPT */
+#ifdef USE_BCRYPT
+                   && (0 != strcmp (crypt_method, "BCRYPT"))
+#endif                         /* USE_BCRYPT */
                    ) {
                        fprintf (stderr,
                                 _("%s: unsupported crypt method: %s\n"),
index 8dca4455f9bf479e6c236a1244b985f8103fa207..13619b164cb11009830271ac7061b014a9f93b72 100644 (file)
@@ -279,7 +279,11 @@ static int new_password (const struct passwd *pw)
 #ifdef USE_SHA_CRYPT
                    || (strcmp (method, "SHA256") == 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;
                } else {