]> granicus.if.org Git - shadow/commitdiff
* lib/prototypes.h, libmisc/salt.c: Add parameters to
authornekral-guest <nekral-guest@5a98b0ae-9ef6-0310-add3-de5d479b70d7>
Tue, 20 Nov 2007 09:33:52 +0000 (09:33 +0000)
committernekral-guest <nekral-guest@5a98b0ae-9ef6-0310-add3-de5d479b70d7>
Tue, 20 Nov 2007 09:33:52 +0000 (09:33 +0000)
  crypt_make_salt to force the crypt method and number of rounds.
* libmisc/salt.c: Add parameter to SHA_salt_rounds to force the
  number of rounds.
* libmisc/salt.c, lib/getdef.c: ENCRYPT_METHOD and MD5_CRYPT_ENAB
  are needed also when USE_PAM (e.g. for chpasswd).
* src/newusers.c, src/gpasswd.c: Use the new crypt_make_salt prototype.
* src/chpasswd.c, src/chgpasswd.c: Add option -c, --crypt-method
  and -s, --sha-rounds to specify the crypt method and number of
  rounds in case of one of the SHA methods. The new prototype of
  crypt_make_salt simplifies the handling of -m, --md5.

ChangeLog
lib/getdef.c
lib/prototypes.h
libmisc/salt.c
src/chgpasswd.c
src/chpasswd.c
src/gpasswd.c
src/newusers.c

index 82e1a769b37e4ed8d0b373690133b628c85170c0..cba2b88aeb5d30dabff6846ab636ace66bbc5b50 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2007-11-20  Nicolas François  <nicolas.francois@centraliens.net>
+
+       * lib/prototypes.h, libmisc/salt.c: Add parameters to
+       crypt_make_salt to force the crypt method and number of rounds.
+       * libmisc/salt.c: Add parameter to SHA_salt_rounds to force the
+       number of rounds.
+       * libmisc/salt.c, lib/getdef.c: ENCRYPT_METHOD and MD5_CRYPT_ENAB
+       are needed also when USE_PAM (e.g. for chpasswd).
+       * src/newusers.c, src/gpasswd.c: Use the new crypt_make_salt prototype
+       * src/chpasswd.c, src/chgpasswd.c: Add option -c, --crypt-method
+       and -s, --sha-rounds to specify the crypt method and number of
+       rounds in case of one of the SHA methods. The new prototype of
+       crypt_make_salt simplifies the handling of -m, --md5.
+
 2007-11-19  Nicolas François  <nicolas.francois@centraliens.net>
 
        * libmisc/salt.c: The salt has a random size (between 8 and 16
index 7b8a798a048e5978402b65c3785e7371a0957d39..df474c81a883dbfbb49dade58b6f3551b36f0710 100644 (file)
@@ -52,6 +52,7 @@ static struct itemdef def_table[] = {
        {"CONSOLE", NULL},
        {"CREATE_HOME", NULL},
        {"DEFAULT_HOME", NULL},
+       {"ENCRYPT_METHOD", NULL},
        {"ENV_PATH", NULL},
        {"ENV_SUPATH", NULL},
        {"ERASECHAR", NULL},
@@ -67,9 +68,12 @@ static struct itemdef def_table[] = {
        {"LOG_UNKFAIL_ENAB", NULL},
        {"MAIL_DIR", NULL},
        {"MAIL_FILE", NULL},
+       {"MD5_CRYPT_ENAB", NULL},
        {"PASS_MAX_DAYS", NULL},
        {"PASS_MIN_DAYS", NULL},
        {"PASS_WARN_AGE", NULL},
+       {"SHA_CRYPT_MAX_ROUNDS", NULL},
+       {"SHA_CRYPT_MIN_ROUNDS", NULL},
        {"SULOG_FILE", NULL},
        {"SU_NAME", NULL},
        {"TTYGROUP", NULL},
@@ -84,7 +88,6 @@ static struct itemdef def_table[] = {
        {"CHFN_AUTH", NULL},
        {"CHSH_AUTH", NULL},
        {"CRACKLIB_DICTPATH", NULL},
-       {"ENCRYPT_METHOD", NULL},
        {"ENV_HZ", NULL},
        {"ENVIRON_FILE", NULL},
        {"ENV_TZ", NULL},
@@ -94,7 +97,6 @@ static struct itemdef def_table[] = {
        {"LASTLOG_ENAB", NULL},
        {"LOGIN_STRING", NULL},
        {"MAIL_CHECK_ENAB", NULL},
-       {"MD5_CRYPT_ENAB", NULL},
        {"MOTD_FILE", NULL},
        {"NOLOGINS_FILE", NULL},
        {"OBSCURE_CHECKS_ENAB", NULL},
@@ -104,8 +106,6 @@ static struct itemdef def_table[] = {
        {"PASS_MIN_LEN", NULL},
        {"PORTTIME_CHECKS_ENAB", NULL},
        {"QUOTAS_ENAB", NULL},
-       {"SHA_CRYPT_MAX_ROUNDS", NULL},
-       {"SHA_CRYPT_MIN_ROUNDS", NULL},
        {"SU_WHEEL_ONLY", NULL},
        {"ULIMIT", NULL},
 #endif
index e18d71e87a9bd9be078b681f8b54e28b7f843504..86c4a7c82ffa81948bd9387f7568d943c6a8812c 100644 (file)
@@ -132,7 +132,7 @@ extern void pwd_init (void);
 extern int do_rlogin (const char *, char *, int, char *, int);
 
 /* salt.c */
-extern char *crypt_make_salt (void);
+extern char *crypt_make_salt (char *meth, void *arg);
 
 /* setugid.c */
 extern int setup_groups (const struct passwd *);
index ec3de46c54df35900c08a581b07106d2ef45f583..8ee0dcbb6cf1691693daf69f1a39c1b9a06c1387 100644 (file)
@@ -85,28 +85,32 @@ static unsigned int SHA_salt_size (void)
 /*
  * Return a salt prefix specifying the rounds number for the SHA crypt methods.
  */
-static char *SHA_salt_rounds (void)
+static char *SHA_salt_rounds (int *prefered_rounds)
 {
-       static char *rounds_prefix[18];
-       long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1);
-       long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1);
+       static char rounds_prefix[18];
        long rounds;
 
-       if (-1 == min_rounds && -1 == max_rounds)
-               return "";
+       if (NULL == prefered_rounds) {
+               long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1);
+               long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1);
 
-       if (-1 == min_rounds)
-               min_rounds = max_rounds;
+               if (-1 == min_rounds && -1 == max_rounds)
+                       return "";
 
-       if (-1 == max_rounds)
-               max_rounds = min_rounds;
+               if (-1 == min_rounds)
+                       min_rounds = max_rounds;
 
-       if (min_rounds > max_rounds)
-               max_rounds = min_rounds;
+               if (-1 == max_rounds)
+                       max_rounds = min_rounds;
 
-       srand (time (NULL));
-       rounds = min_rounds +
-                (double)rand () * (max_rounds-min_rounds+1)/RAND_MAX;
+               if (min_rounds > max_rounds)
+                       max_rounds = min_rounds;
+
+               srand (time (NULL));
+               rounds = min_rounds +
+                        (double)rand () * (max_rounds-min_rounds+1)/RAND_MAX;
+       } else if (0 == *prefered_rounds)
+               return "";
 
        /* Sanity checks. The libc should also check this, but this
         * protects against a rounds_prefix overflow. */
@@ -133,8 +137,16 @@ static char *SHA_salt_rounds (void)
  * (magic) and pw_encrypt() will execute the MD5-based FreeBSD-compatible
  * version of crypt() instead of the standard one.
  * Other methods can be set with ENCRYPT_METHOD
+ *
+ * The method can be forced with the meth parameter.
+ * If NULL, the method will be defined according to the MD5_CRYPT_ENAB and
+ * ENCRYPT_METHOD login.defs variables.
+ *
+ * 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).
  */
-char *crypt_make_salt (void)
+char *crypt_make_salt (char *meth, void *arg)
 {
        struct timeval tv;
        /* Max result size for the SHA methods:
@@ -145,41 +157,39 @@ char *crypt_make_salt (void)
         */
        static char result[40];
        int max_salt_len = 8;
-       char *method;
+       char *method = "DES";
 
        result[0] = '\0';
 
-#ifndef USE_PAM
+       if (NULL != meth)
+               method = meth;
+       else
 #ifdef ENCRYPTMETHOD_SELECT
-       if ((method = getdef_str ("ENCRYPT_METHOD")) == NULL) {
+       if ((method = getdef_str ("ENCRYPT_METHOD")) == NULL)
 #endif
-               if (getdef_bool ("MD5_CRYPT_ENAB")) {
-                       MAGNUM(result,'1');
-                       max_salt_len = 11;
-               }
+               if (getdef_bool ("MD5_CRYPT_ENAB"))
+                       method = "MD5";
+
+       if (!strncmp (method, "MD5", 3)) {
+               MAGNUM(result, '1');
+               max_salt_len = 11;
 #ifdef ENCRYPTMETHOD_SELECT
-       } else {
-               if (!strncmp (method, "MD5", 3)) {
-                       MAGNUM(result, '1');
-                       max_salt_len = 11;
-               } else if (!strncmp (method, "SHA256", 6)) {
-                       MAGNUM(result, '5');
-                       strcat(result, SHA_salt_rounds());
-                       max_salt_len = strlen(result) + SHA_salt_size();
-               } else if (!strncmp (method, "SHA512", 6)) {
-                       MAGNUM(result, '6');
-                       strcat(result, SHA_salt_rounds());
-                       max_salt_len = strlen(result) + SHA_salt_size();
-               } else if (0 != strncmp (method, "DES", 3)) {
-                       fprintf (stderr,
-                                _("Invalid ENCRYPT_METHOD value: '%s'.\n"
-                                  "Defaulting to DES.\n"),
-                                method);
-                       result[0] = '\0';
-               }
+       } else if (!strncmp (method, "SHA256", 6)) {
+               MAGNUM(result, '5');
+               strcat(result, SHA_salt_rounds((int *)arg));
+               max_salt_len = strlen(result) + SHA_salt_size();
+       } else if (!strncmp (method, "SHA512", 6)) {
+               MAGNUM(result, '6');
+               strcat(result, SHA_salt_rounds((int *)arg));
+               max_salt_len = strlen(result) + SHA_salt_size();
+#endif
+       } else if (0 != strncmp (method, "DES", 3)) {
+               fprintf (stderr,
+                        _("Invalid ENCRYPT_METHOD value: '%s'.\n"
+                          "Defaulting to DES.\n"),
+                        method);
+               result[0] = '\0';
        }
-#endif                         /* ENCRYPTMETHOD_SELECT */
-#endif                         /* USE_PAM */
 
        /*
         * Concatenate a pseudo random salt.
index 185d7ad032bc9b69e5d842108d812fd7379b231c..e1f95db183fc9ccc12b3218bafa2f887427832fa 100644 (file)
  * Global variables
  */
 static char *Prog;
+static int cflg = 0;
 static int eflg = 0;
 static int md5flg = 0;
+static int sflg = 0;
+
+static char *crypt_method = NULL;
+static int sha_rounds = 5000;
 
 #ifdef SHADOWGRP
 static int is_shadow_grp;
@@ -68,14 +73,36 @@ static void usage (void)
        fprintf (stderr, _("Usage: chgpasswd [options]\n"
                           "\n"
                           "Options:\n"
+                          "  -c, --crypt-method        the crypt method (one of %s)\n"
                           "  -e, --encrypted   supplied passwords are encrypted\n"
                           "  -h, --help                display this help message and exit\n"
                           "  -m, --md5         use MD5 encryption instead DES when the supplied\n"
                           "                    passwords are not encrypted\n"
-                          "\n"));
+                          "\n"),
+#ifndef ENCRYPTMETHOD_SELECT
+                        "DES MD5"
+#else
+                        "DES MD5 SHA256 SHA512"
+#endif
+                        );
        exit (1);
 }
 
+static long getnumber (const char *numstr)
+{
+       long val;
+       char *errptr;
+
+       val = strtol (numstr, &errptr, 10);
+       if (*errptr || errno == ERANGE) {
+               fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog,
+                        numstr);
+               exit (1);
+       }
+
+       return val;
+}
+
 int main (int argc, char **argv)
 {
        char buf[BUFSIZ];
@@ -111,16 +138,22 @@ int main (int argc, char **argv)
                int option_index = 0;
                int c;
                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'},
+                       {"sha-rounds", required_argument, NULL, 's'},
                        {NULL, 0, NULL, '\0'}
                };
 
                while ((c =
-                       getopt_long (argc, argv, "ehm", long_options,
+                       getopt_long (argc, argv, "c:ehms:", long_options,
                                     &option_index)) != -1) {
                        switch (c) {
+                       case 'c':
+                               cflg = 1;
+                               crypt_method = optarg;
+                               break;
                        case 'e':
                                eflg = 1;
                                break;
@@ -130,6 +163,10 @@ int main (int argc, char **argv)
                        case 'm':
                                md5flg = 1;
                                break;
+                       case 's':
+                               sflg = 1;
+                               sha_rounds = getnumber(optarg);
+                               break;
                        case 0:
                                /* long option */
                                break;
@@ -140,6 +177,34 @@ int main (int argc, char **argv)
                }
        }
 
+       /* validate options */
+       if (sflg && !cflg) {
+               fprintf (stderr,
+                        _("%s: %s flag is ONLY allowed with the %s flag\n"),
+                        Prog, "-s", "-c");
+               usage ();
+       }
+       if (md5flg && cflg) {
+               fprintf (stderr,
+                        _("%s: the -m and -c flags are exclusive\n"),
+                        Prog);
+               usage ();
+       }
+       if (cflg) {
+               if (0 != strcmp (method, "DES") &&
+                   0 != strcmp (method, "MD5") &&
+#ifdef ENCRYPTMETHOD_SELECT
+                   0 != strcmp (method, "SHA256") &&
+                   0 != strcmp (method, "SHA512")
+#endif
+                   ) {
+                       fprintf (stderr,
+                        _("%s: unsupported crypt method: %s\n"),
+                        Prog, method);
+                       usage ();
+               }
+       }
+
 #ifdef USE_PAM
        retval = PAM_SUCCESS;
 
@@ -245,18 +310,16 @@ int main (int argc, char **argv)
                }
                newpwd = cp;
                if (!eflg) {
-                       if (md5flg) {
-                               char md5salt[12] = "$1$";
-                               char *salt = crypt_make_salt ();
-
-                               if (strncmp (salt, "$1$", 3) == 0) {
-                                       strncpy (md5salt, salt, 11);
-                               } else {
-                                       strncat (md5salt, salt, 8);
-                               }
-                               cp = pw_encrypt (newpwd, md5salt);
+                       void *arg = NULL;
+                       if (md5flg)
+                               crypt_method = "MD5";
+                       else if (crypt_method != NULL) {
+                               if (sflg)
+                                       arg = &sha_rounds;
                        } else
-                               cp = pw_encrypt (newpwd, crypt_make_salt ());
+                               crypt_method = "DES";
+                       cp = pw_encrypt (newpwd,
+                                        crypt_make_salt(crypt_method, arg));
                }
 
                /*
index c8b006078d983e2285ad142f229ead132908e14f..f4fe606788f673a7c52b1acbdbf39556845f9053 100644 (file)
  * Global variables
  */
 static char *Prog;
+static int cflg = 0;
 static int eflg = 0;
 static int md5flg = 0;
+static int sflg = 0;
+
+static char *crypt_method = NULL;
+static int sha_rounds = 5000;
 
 static int is_shadow_pwd;
 
@@ -65,14 +70,36 @@ static void usage (void)
        fprintf (stderr, _("Usage: chpasswd [options]\n"
                           "\n"
                           "Options:\n"
+                          "  -c, --crypt-method        the crypt method (one of %s)\n"
                           "  -e, --encrypted   supplied passwords are encrypted\n"
                           "  -h, --help                display this help message and exit\n"
                           "  -m, --md5         use MD5 encryption instead DES when the supplied\n"
                           "                    passwords are not encrypted\n"
-                          "\n"));
+                          "\n"),
+#ifndef ENCRYPTMETHOD_SELECT
+                        "DES MD5"
+#else
+                        "DES MD5 SHA256 SHA512"
+#endif
+                        );
        exit (E_USAGE);
 }
 
+static long getnumber (const char *numstr)
+{
+       long val;
+       char *errptr;
+
+       val = strtol (numstr, &errptr, 10);
+       if (*errptr || errno == ERANGE) {
+               fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog,
+                        numstr);
+               exit (1);
+       }
+
+       return val;
+}
+
 int main (int argc, char **argv)
 {
        char buf[BUFSIZ];
@@ -105,16 +132,22 @@ int main (int argc, char **argv)
                int option_index = 0;
                int c;
                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'},
+                       {"sha-rounds", required_argument, NULL, 's'},
                        {NULL, 0, NULL, '\0'}
                };
 
                while ((c =
-                       getopt_long (argc, argv, "ehm", long_options,
+                       getopt_long (argc, argv, "c:ehms:", long_options,
                                     &option_index)) != -1) {
                        switch (c) {
+                       case 'c':
+                               cflg = 1;
+                               crypt_method = optarg;
+                               break;
                        case 'e':
                                eflg = 1;
                                break;
@@ -124,6 +157,10 @@ int main (int argc, char **argv)
                        case 'm':
                                md5flg = 1;
                                break;
+                       case 's':
+                               sflg = 1;
+                               sha_rounds = getnumber(optarg);
+                               break;
                        case 0:
                                /* long option */
                                break;
@@ -134,6 +171,34 @@ int main (int argc, char **argv)
                }
        }
 
+       /* validate options */
+       if (sflg && !cflg) {
+               fprintf (stderr,
+                        _("%s: %s flag is ONLY allowed with the %s flag\n"),
+                        Prog, "-s", "-c");
+               usage ();
+       }
+       if (md5flg && cflg) {
+               fprintf (stderr,
+                        _("%s: the -m and -c flags are exclusive\n"),
+                        Prog);
+               usage ();
+       }
+       if (cflg) {
+               if (0 != strcmp (method, "DES") &&
+                   0 != strcmp (method, "MD5") &&
+#ifdef ENCRYPTMETHOD_SELECT
+                   0 != strcmp (method, "SHA256") &&
+                   0 != strcmp (method, "SHA512")
+#endif
+                   ) {
+                       fprintf (stderr,
+                        _("%s: unsupported crypt method: %s\n"),
+                        Prog, method);
+                       usage ();
+               }
+       }
+
 #ifdef USE_PAM
        retval = PAM_SUCCESS;
 
@@ -241,18 +306,16 @@ int main (int argc, char **argv)
                }
                newpwd = cp;
                if (!eflg) {
-                       if (md5flg) {
-                               char md5salt[12] = "$1$";
-                               char *salt = crypt_make_salt ();
-
-                               if (strncmp (salt, "$1$", 3) == 0) {
-                                       strncpy (md5salt, salt, 11);
-                               } else {
-                                       strncat (md5salt, salt, 8);
-                               }
-                               cp = pw_encrypt (newpwd, salt);
+                       void *arg = NULL;
+                       if (md5flg)
+                               crypt_method = "MD5";
+                       else if (crypt_method != NULL) {
+                               if (sflg)
+                                       arg = &sha_rounds;
                        } else
-                               cp = pw_encrypt (newpwd, crypt_make_salt ());
+                               crypt_method = "DES";
+                       cp = pw_encrypt (newpwd,
+                                        crypt_make_salt(crypt_method, arg));
                }
 
                /*
index f8f6832de1b0aa4365a98dd387d9ed08cdd421b3..67a656ee2e5ba62d9b46e41608556e869a61095f 100644 (file)
@@ -607,7 +607,7 @@ int main (int argc, char **argv)
                exit (1);
        }
 
-       cp = pw_encrypt (pass, crypt_make_salt ());
+       cp = pw_encrypt (pass, crypt_make_salt (NULL, NULL));
        memzero (pass, sizeof pass);
 #ifdef SHADOWGRP
        if (is_shadowgrp)
index ce27fb9cc03775a4d6920546ba197fa9fb618615..15af7c9106cf5c17596fdb1788f9360660d71b2c 100644 (file)
@@ -214,7 +214,7 @@ static int add_user (const char *name, const char *uid, uid_t * nuid, gid_t gid)
 
 static void update_passwd (struct passwd *pwd, const char *passwd)
 {
-       pwd->pw_passwd = pw_encrypt (passwd, crypt_make_salt ());
+       pwd->pw_passwd = pw_encrypt (passwd, crypt_make_salt (NULL, NULL));
 }
 
 /*
@@ -241,7 +241,8 @@ static int add_passwd (struct passwd *pwd, const char *passwd)
         */
        if ((sp = spw_locate (pwd->pw_name))) {
                spent = *sp;
-               spent.sp_pwdp = pw_encrypt (passwd, crypt_make_salt ());
+               spent.sp_pwdp = pw_encrypt (passwd,
+                                           crypt_make_salt (NULL, NULL));
                return !spw_update (&spent);
        }
 
@@ -261,7 +262,7 @@ static int add_passwd (struct passwd *pwd, const char *passwd)
         * shadow password file entry.
         */
        spent.sp_namp = pwd->pw_name;
-       spent.sp_pwdp = pw_encrypt (passwd, crypt_make_salt ());
+       spent.sp_pwdp = pw_encrypt (passwd, crypt_make_salt (NULL, NULL));
        spent.sp_lstchg = time ((time_t *) 0) / SCALE;
        spent.sp_min = getdef_num ("PASS_MIN_DAYS", 0);
        /* 10000 is infinity this week */