d5de424f047a8b7a419a73d4bfa6bbf0bf80ebe0
[oweals/busybox.git] / loginutils / chpasswd.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * chpasswd.c
4  *
5  * Written for SLIND (from passwd.c) by Alexander Shishkin <virtuoso@slind.org>
6  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
7  */
8
9 #include "libbb.h"
10
11 #if ENABLE_GETOPT_LONG
12 #include <getopt.h>
13
14 static const struct option chpasswd_opts[] = {
15         { "encrypted", no_argument, NULL, 'e' },
16         { "md5", no_argument, NULL, 'm' },
17         { NULL, 0, NULL, 0 }
18 };
19 #endif
20
21 #define OPT_ENC         1
22 #define OPT_MD5         2
23
24 int chpasswd_main(int argc, char **argv);
25 int chpasswd_main(int argc, char **argv)
26 {
27         char *name, *pass;
28         char salt[sizeof("$N$XXXXXXXX")];
29         int opt;
30         int rnd = rnd; /* we *want* it to be non-initialized! */
31
32         if (getuid())
33                 bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
34
35         opt_complementary = "?m--e:e--m";
36         USE_GETOPT_LONG(applet_long_options = chpasswd_opts;)
37         opt = getopt32(argc, argv, "em");
38
39         while ((name = xmalloc_getline(stdin)) != NULL) {
40                 pass = strchr(name, ':');
41                 if (!pass)
42                         bb_error_msg_and_die("missing new password");
43                 *pass++ = '\0';
44
45                 xuname2uid(name); /* dies if there is no such user */
46
47                 if (!(opt & OPT_ENC)) {
48                         rnd = crypt_make_salt(salt, 1, rnd);
49                         if (opt & OPT_MD5) {
50                                 strcpy(salt, "$1$");
51                                 rnd = crypt_make_salt(salt + 3, 4, rnd);
52                         }
53                         pass = pw_encrypt(pass, salt);
54                 }
55
56                 /* LOGMODE_BOTH logs to syslog */
57                 logmode = LOGMODE_BOTH;
58
59                 if ((ENABLE_FEATURE_SHADOWPASSWDS 
60                         && !update_passwd(bb_path_shadow_file, name, pass))
61                         || !update_passwd(bb_path_passwd_file, name, pass)
62                 ) {
63                         bb_error_msg_and_die("an error occurred updating password for %s", name);
64                 } else {
65                         bb_info_msg("Password for '%s' changed", name);
66                 }
67                 logmode = LOGMODE_STDIO;
68                 free(name);
69         }
70
71         return 0;
72 }