blob: 9eab99e446ebd7cf9703816502828ef31bd0e386
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 source tree. |
7 | */ |
8 | #include "libbb.h" |
9 | |
10 | //usage:#define chpasswd_trivial_usage |
11 | //usage: IF_LONG_OPTS("[--md5|--encrypted]") IF_NOT_LONG_OPTS("[-m|-e]") |
12 | //usage:#define chpasswd_full_usage "\n\n" |
13 | //usage: "Read user:password from stdin and update /etc/passwd\n" |
14 | //usage: IF_LONG_OPTS( |
15 | //usage: "\n -e,--encrypted Supplied passwords are in encrypted form" |
16 | //usage: "\n -m,--md5 Use MD5 encryption instead of DES" |
17 | //usage: ) |
18 | //usage: IF_NOT_LONG_OPTS( |
19 | //usage: "\n -e Supplied passwords are in encrypted form" |
20 | //usage: "\n -m Use MD5 encryption instead of DES" |
21 | //usage: ) |
22 | |
23 | //TODO: implement -c ALGO |
24 | |
25 | #if ENABLE_LONG_OPTS |
26 | static const char chpasswd_longopts[] ALIGN1 = |
27 | "encrypted\0" No_argument "e" |
28 | "md5\0" No_argument "m" |
29 | ; |
30 | #endif |
31 | |
32 | #define OPT_ENC 1 |
33 | #define OPT_MD5 2 |
34 | |
35 | int chpasswd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
36 | int chpasswd_main(int argc UNUSED_PARAM, char **argv) |
37 | { |
38 | char *name; |
39 | int opt; |
40 | |
41 | if (getuid() != 0) |
42 | bb_error_msg_and_die("%s", bb_msg_perm_denied_are_you_root); |
43 | |
44 | opt_complementary = "m--e:e--m"; |
45 | IF_LONG_OPTS(applet_long_options = chpasswd_longopts;) |
46 | opt = getopt32(argv, "em"); |
47 | |
48 | while ((name = xmalloc_fgetline(stdin)) != NULL) { |
49 | char *free_me; |
50 | char *pass; |
51 | int rc; |
52 | |
53 | pass = strchr(name, ':'); |
54 | if (!pass) |
55 | bb_error_msg_and_die("missing new password"); |
56 | *pass++ = '\0'; |
57 | |
58 | xuname2uid(name); /* dies if there is no such user */ |
59 | |
60 | free_me = NULL; |
61 | if (!(opt & OPT_ENC)) { |
62 | char salt[sizeof("$N$XXXXXXXX")]; |
63 | |
64 | crypt_make_salt(salt, 1); |
65 | if (opt & OPT_MD5) { |
66 | salt[0] = '$'; |
67 | salt[1] = '1'; |
68 | salt[2] = '$'; |
69 | crypt_make_salt(salt + 3, 4); |
70 | } |
71 | free_me = pass = pw_encrypt(pass, salt, 0); |
72 | } |
73 | |
74 | /* This is rather complex: if user is not found in /etc/shadow, |
75 | * we try to find & change his passwd in /etc/passwd */ |
76 | #if ENABLE_FEATURE_SHADOWPASSWDS |
77 | rc = update_passwd(bb_path_shadow_file, name, pass, NULL); |
78 | if (rc > 0) /* password in /etc/shadow was updated */ |
79 | pass = (char*)"x"; |
80 | if (rc >= 0) |
81 | /* 0 = /etc/shadow missing (not an error), >0 = passwd changed in /etc/shadow */ |
82 | #endif |
83 | rc = update_passwd(bb_path_passwd_file, name, pass, NULL); |
84 | /* LOGMODE_BOTH logs to syslog also */ |
85 | logmode = LOGMODE_BOTH; |
86 | if (rc < 0) |
87 | bb_error_msg_and_die("an error occurred updating password for %s", name); |
88 | if (rc) |
89 | bb_info_msg("Password for '%s' changed", name); |
90 | logmode = LOGMODE_STDIO; |
91 | free(name); |
92 | free(free_me); |
93 | } |
94 | return EXIT_SUCCESS; |
95 | } |
96 |