chpasswd: support -c argument and respect DEFAULT_PASSWD_ALGO
authorPascal Bach <pascal.bach@siemens.com>
Fri, 18 Dec 2015 18:01:14 +0000 (19:01 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 18 Dec 2015 18:01:14 +0000 (19:01 +0100)
Signed-off-by: Pascal Bach <pascal.bach@siemens.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
libbb/pw_encrypt.c
loginutils/chpasswd.c

index bfc7030a8387f81daa44ce8f1ccc6f50e3380233..dbc15e5fc589300a2d2e86b54260df5c968fcad8 100644 (file)
@@ -52,14 +52,18 @@ char* FAST_FUNC crypt_make_pw_salt(char salt[MAX_PW_SALT_LEN], const char *algo)
 {
        int len = 2/2;
        char *salt_ptr = salt;
-       if (algo[0] != 'd') { /* not des */
+
+       /* Standard chpasswd uses uppercase algos ("MD5", not "md5").
+        * Need to be case-insensitive in the code below.
+        */
+       if ((algo[0]|0x20) != 'd') { /* not des */
                len = 8/2; /* so far assuming md5 */
                *salt_ptr++ = '$';
                *salt_ptr++ = '1';
                *salt_ptr++ = '$';
 #if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA
-               if (algo[0] == 's') { /* sha */
-                       salt[1] = '5' + (strcmp(algo, "sha512") == 0);
+               if ((algo[0]|0x20) == 's') { /* sha */
+                       salt[1] = '5' + (strcasecmp(algo, "sha512") == 0);
                        len = 16/2;
                }
 #endif
index 6c41d17beb5b6454a62ba57d75bb102bb39a3f49..a022a42d6f1724d93785e1d3cb5ea0b04de6a8e2 100644 (file)
 //kbuild:lib-$(CONFIG_CHPASSWD) += chpasswd.o
 
 //usage:#define chpasswd_trivial_usage
-//usage:       IF_LONG_OPTS("[--md5|--encrypted]") IF_NOT_LONG_OPTS("[-m|-e]")
+//usage:       IF_LONG_OPTS("[--md5|--encrypted|--crypt-method]") IF_NOT_LONG_OPTS("[-m|-e|-c]")
 //usage:#define chpasswd_full_usage "\n\n"
 //usage:       "Read user:password from stdin and update /etc/passwd\n"
 //usage:       IF_LONG_OPTS(
-//usage:     "\n       -e,--encrypted  Supplied passwords are in encrypted form"
-//usage:     "\n       -m,--md5        Use MD5 encryption instead of DES"
+//usage:     "\n       -e,--encrypted          Supplied passwords are in encrypted form"
+//usage:     "\n       -m,--md5                Use MD5 encryption instead of DES"
+//usage:     "\n       -c,--crypt-method       Use the specified method to encrypt the passwords"
 //usage:       )
 //usage:       IF_NOT_LONG_OPTS(
 //usage:     "\n       -e      Supplied passwords are in encrypted form"
 //usage:     "\n       -m      Use MD5 encryption instead of DES"
+//usage:     "\n       -c      Use the specified method to encrypt the passwords"
 //usage:       )
 
-//TODO: implement -c ALGO
-
 #include "libbb.h"
 
 #if ENABLE_LONG_OPTS
 static const char chpasswd_longopts[] ALIGN1 =
-       "encrypted\0" No_argument "e"
-       "md5\0"       No_argument "m"
+       "encrypted\0"    No_argument       "e"
+       "md5\0"          No_argument       "m"
+       "crypt-method\0" Required_argument "c"
        ;
 #endif
 
@@ -54,14 +55,15 @@ int chpasswd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int chpasswd_main(int argc UNUSED_PARAM, char **argv)
 {
        char *name;
+       const char *algo = CONFIG_FEATURE_DEFAULT_PASSWD_ALGO;
        int opt;
 
        if (getuid() != 0)
                bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
 
-       opt_complementary = "m--e:e--m";
+       opt_complementary = "m--ec:e--mc:c--em";
        IF_LONG_OPTS(applet_long_options = chpasswd_longopts;)
-       opt = getopt32(argv, "em");
+       opt = getopt32(argv, "emc:", &algo);
 
        while ((name = xmalloc_fgetline(stdin)) != NULL) {
                char *free_me;
@@ -77,15 +79,14 @@ int chpasswd_main(int argc UNUSED_PARAM, char **argv)
 
                free_me = NULL;
                if (!(opt & OPT_ENC)) {
-                       char salt[sizeof("$N$XXXXXXXX")];
+                       char salt[MAX_PW_SALT_LEN];
 
-                       crypt_make_salt(salt, 1);
                        if (opt & OPT_MD5) {
-                               salt[0] = '$';
-                               salt[1] = '1';
-                               salt[2] = '$';
-                               crypt_make_salt(salt + 3, 4);
+                               /* Force MD5 if the -m flag is set */
+                               algo = "md5";
                        }
+
+                       crypt_make_pw_salt(salt, algo);
                        free_me = pass = pw_encrypt(pass, salt, 0);
                }