X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=loginutils%2Fchpasswd.c;h=4b3602e7a315545231751f700e8d2b4fed874648;hb=3a4d5a73a876b0922afed095bc9f83dbdf07148e;hp=1f823179f82613ba2c46233fd42bb8ab53c28a85;hpb=e8feca085dbcd0fb97aa5af1a8e751affb88df48;p=oweals%2Fbusybox.git diff --git a/loginutils/chpasswd.c b/loginutils/chpasswd.c index 1f823179f..4b3602e7a 100644 --- a/loginutils/chpasswd.c +++ b/loginutils/chpasswd.c @@ -3,40 +3,82 @@ * chpasswd.c * * Written for SLIND (from passwd.c) by Alexander Shishkin - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +//config:config CHPASSWD +//config: bool "chpasswd (18 kb)" +//config: default y +//config: help +//config: Reads a file of user name and password pairs from standard input +//config: and uses this information to update a group of existing users. +//config: +//config:config FEATURE_DEFAULT_PASSWD_ALGO +//config: string "Default encryption method (passwd -a, cryptpw -m, chpasswd -c ALG)" +//config: default "des" +//config: depends on PASSWD || CRYPTPW || CHPASSWD +//config: help +//config: Possible choices are "d[es]", "m[d5]", "s[ha256]" or "sha512". -#include "libbb.h" +//applet:IF_CHPASSWD(APPLET(chpasswd, BB_DIR_USR_SBIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_CHPASSWD) += chpasswd.o -#if ENABLE_GETOPT_LONG -#include +//usage:#define chpasswd_trivial_usage +//usage: IF_LONG_OPTS("[--md5|--encrypted|--crypt-method|--root]") IF_NOT_LONG_OPTS("[-m|-e|-c|-R]") +//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 Encrypt using md5, not des" +//usage: "\n -c,--crypt-method ALG "CRYPT_METHODS_HELP_STR +//usage: "\n -R,--root DIR Directory to chroot into" +//usage: ) +//usage: IF_NOT_LONG_OPTS( +//usage: "\n -e Supplied passwords are in encrypted form" +//usage: "\n -m Encrypt using md5, not des" +//usage: "\n -c ALG "CRYPT_METHODS_HELP_STR +//usage: "\n -R DIR Directory to chroot into" +//usage: ) -static const struct option chpasswd_opts[] = { - { "encrypted", no_argument, NULL, 'e' }, - { "md5", no_argument, NULL, 'm' }, - { NULL, 0, NULL, 0 } -}; +#include "libbb.h" + +#if ENABLE_LONG_OPTS +static const char chpasswd_longopts[] ALIGN1 = + "encrypted\0" No_argument "e" + "md5\0" No_argument "m" + "crypt-method\0" Required_argument "c" + "root\0" Required_argument "R" + ; #endif -#define OPT_ENC 1 -#define OPT_MD5 2 +#define OPT_ENC 1 +#define OPT_MD5 2 -int chpasswd_main(int argc, char **argv); -int chpasswd_main(int argc, char **argv) +int chpasswd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int chpasswd_main(int argc UNUSED_PARAM, char **argv) { - char *name, *pass; - char salt[sizeof("$N$XXXXXXXX")]; - int opt, rc; - int rnd = rnd; /* we *want* it to be non-initialized! */ + char *name; + const char *algo = CONFIG_FEATURE_DEFAULT_PASSWD_ALGO; + const char *root = NULL; + int opt; - if (getuid()) + if (getuid() != 0) bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); - opt_complementary = "m--e:e--m"; - USE_GETOPT_LONG(applet_long_options = chpasswd_opts;) - opt = getopt32(argc, argv, "em"); + opt = getopt32long(argv, "^" "emc:R:" "\0" "m--ec:e--mc:c--em", + chpasswd_longopts, + &algo, &root + ); + + if (root) { + xchroot(root); + } + + while ((name = xmalloc_fgetline(stdin)) != NULL) { + char *free_me; + char *pass; + int rc; - while ((name = xmalloc_getline(stdin)) != NULL) { pass = strchr(name, ':'); if (!pass) bb_error_msg_and_die("missing new password"); @@ -44,31 +86,38 @@ int chpasswd_main(int argc, char **argv) xuname2uid(name); /* dies if there is no such user */ + free_me = NULL; if (!(opt & OPT_ENC)) { - rnd = crypt_make_salt(salt, 1, rnd); + char salt[MAX_PW_SALT_LEN]; + if (opt & OPT_MD5) { - strcpy(salt, "$1$"); - rnd = crypt_make_salt(salt + 3, 4, rnd); + /* Force MD5 if the -m flag is set */ + algo = "md5"; } - pass = pw_encrypt(pass, salt); + + crypt_make_pw_salt(salt, algo); + free_me = pass = pw_encrypt(pass, salt, 0); } /* This is rather complex: if user is not found in /etc/shadow, * we try to find & change his passwd in /etc/passwd */ #if ENABLE_FEATURE_SHADOWPASSWDS - rc = update_passwd(bb_path_shadow_file, name, pass); - if (rc == 0) /* no lines updated, no errors detected */ + rc = update_passwd(bb_path_shadow_file, name, pass, NULL); + if (rc > 0) /* password in /etc/shadow was updated */ + pass = (char*)"x"; + if (rc >= 0) + /* 0 = /etc/shadow missing (not an error), >0 = passwd changed in /etc/shadow */ #endif - rc = update_passwd(bb_path_passwd_file, name, pass); + rc = update_passwd(bb_path_passwd_file, name, pass, NULL); /* LOGMODE_BOTH logs to syslog also */ logmode = LOGMODE_BOTH; if (rc < 0) bb_error_msg_and_die("an error occurred updating password for %s", name); if (rc) - bb_info_msg("Password for '%s' changed", name); + bb_error_msg("password for '%s' changed", name); logmode = LOGMODE_STDIO; free(name); + free(free_me); } - - return 0; + return EXIT_SUCCESS; }