Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/loginutils/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 984 - (hide annotations) (download)
Sun May 30 11:32:42 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 5758 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
4     */
5 niro 816 #include "libbb.h"
6 niro 532 #include <syslog.h>
7    
8     static void nuke_str(char *str)
9     {
10     if (str) memset(str, 0, strlen(str));
11     }
12    
13     static char* new_password(const struct passwd *pw, uid_t myuid, int algo)
14     {
15     char salt[sizeof("$N$XXXXXXXX")]; /* "$N$XXXXXXXX" or "XX" */
16 niro 816 char *orig = (char*)"";
17 niro 532 char *newp = NULL;
18     char *cp = NULL;
19     char *ret = NULL; /* failure so far */
20    
21     if (myuid && pw->pw_passwd[0]) {
22 niro 816 char *encrypted;
23    
24 niro 984 orig = bb_ask_stdin("Old password: "); /* returns ptr to static */
25 niro 532 if (!orig)
26     goto err_ret;
27 niro 816 encrypted = pw_encrypt(orig, pw->pw_passwd, 1); /* returns malloced str */
28     if (strcmp(encrypted, pw->pw_passwd) != 0) {
29     syslog(LOG_WARNING, "incorrect password for %s",
30 niro 532 pw->pw_name);
31     bb_do_delay(FAIL_DELAY);
32     puts("Incorrect password");
33     goto err_ret;
34     }
35 niro 816 if (ENABLE_FEATURE_CLEAN_UP) free(encrypted);
36 niro 532 }
37 niro 984 orig = xstrdup(orig); /* or else bb_ask_stdin() will destroy it */
38     newp = bb_ask_stdin("New password: "); /* returns ptr to static */
39 niro 532 if (!newp)
40     goto err_ret;
41 niro 984 newp = xstrdup(newp); /* we are going to bb_ask_stdin() again, so save it */
42 niro 532 if (ENABLE_FEATURE_PASSWD_WEAK_CHECK
43     && obscure(orig, newp, pw) && myuid)
44     goto err_ret; /* non-root is not allowed to have weak passwd */
45    
46 niro 984 cp = bb_ask_stdin("Retype password: ");
47 niro 532 if (!cp)
48     goto err_ret;
49     if (strcmp(cp, newp)) {
50     puts("Passwords don't match");
51     goto err_ret;
52     }
53    
54 niro 816 crypt_make_salt(salt, 1, 0); /* des */
55 niro 532 if (algo) { /* MD5 */
56     strcpy(salt, "$1$");
57 niro 816 crypt_make_salt(salt + 3, 4, 0);
58 niro 532 }
59 niro 816 /* pw_encrypt returns malloced str */
60     ret = pw_encrypt(newp, salt, 1);
61 niro 532 /* whee, success! */
62    
63     err_ret:
64     nuke_str(orig);
65     if (ENABLE_FEATURE_CLEAN_UP) free(orig);
66     nuke_str(newp);
67     if (ENABLE_FEATURE_CLEAN_UP) free(newp);
68     nuke_str(cp);
69     return ret;
70     }
71    
72 niro 816 int passwd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
73     int passwd_main(int argc UNUSED_PARAM, char **argv)
74 niro 532 {
75     enum {
76     OPT_algo = 0x1, /* -a - password algorithm */
77     OPT_lock = 0x2, /* -l - lock account */
78     OPT_unlock = 0x4, /* -u - unlock account */
79     OPT_delete = 0x8, /* -d - delete password */
80     OPT_lud = 0xe,
81     STATE_ALGO_md5 = 0x10,
82 niro 816 //STATE_ALGO_des = 0x20, not needed yet
83 niro 532 };
84     unsigned opt;
85 niro 816 int rc;
86     const char *opt_a = "";
87 niro 532 const char *filename;
88     char *myname;
89     char *name;
90     char *newp;
91     struct passwd *pw;
92     uid_t myuid;
93     struct rlimit rlimit_fsize;
94     char c;
95 niro 816 #if ENABLE_FEATURE_SHADOWPASSWDS
96     /* Using _r function to avoid pulling in static buffers */
97     struct spwd spw;
98     char buffer[256];
99     #endif
100 niro 532
101     logmode = LOGMODE_BOTH;
102 niro 984 openlog(applet_name, 0, LOG_AUTH);
103 niro 816 opt = getopt32(argv, "a:lud", &opt_a);
104     //argc -= optind;
105 niro 532 argv += optind;
106    
107     if (strcasecmp(opt_a, "des") != 0) /* -a */
108     opt |= STATE_ALGO_md5;
109     //else
110     // opt |= STATE_ALGO_des;
111     myuid = getuid();
112 niro 816 /* -l, -u, -d require root priv and username argument */
113     if ((opt & OPT_lud) && (myuid || !argv[0]))
114 niro 532 bb_show_usage();
115    
116 niro 816 /* Will complain and die if username not found */
117 niro 984 myname = xstrdup(xuid2uname(myuid));
118 niro 816 name = argv[0] ? argv[0] : myname;
119 niro 532
120 niro 984 pw = xgetpwnam(name);
121 niro 532 if (myuid && pw->pw_uid != myuid) {
122     /* LOGMODE_BOTH */
123     bb_error_msg_and_die("%s can't change password for %s", myname, name);
124     }
125    
126     #if ENABLE_FEATURE_SHADOWPASSWDS
127     {
128 niro 816 /* getspnam_r may return 0 yet set result to NULL.
129     * At least glibc 2.4 does this. Be extra paranoid here. */
130     struct spwd *result = NULL;
131 niro 984 errno = 0;
132     if (getspnam_r(pw->pw_name, &spw, buffer, sizeof(buffer), &result) != 0
133     || !result /* no error, but no record found either */
134     || strcmp(result->sp_namp, pw->pw_name) != 0 /* paranoia */
135     ) {
136     if (errno != ENOENT) {
137     /* LOGMODE_BOTH */
138     bb_perror_msg("no record of %s in %s, using %s",
139 niro 532 name, bb_path_shadow_file,
140     bb_path_passwd_file);
141 niro 984 }
142     /* else: /etc/shadow does not exist,
143     * apparently we are on a shadow-less system,
144     * no surprise there */
145 niro 532 } else {
146 niro 816 pw->pw_passwd = result->sp_pwdp;
147 niro 532 }
148     }
149     #endif
150    
151     /* Decide what the new password will be */
152     newp = NULL;
153     c = pw->pw_passwd[0] - '!';
154     if (!(opt & OPT_lud)) {
155     if (myuid && !c) { /* passwd starts with '!' */
156     /* LOGMODE_BOTH */
157 niro 984 bb_error_msg_and_die("can't change "
158 niro 532 "locked password for %s", name);
159     }
160     printf("Changing password for %s\n", name);
161     newp = new_password(pw, myuid, opt & STATE_ALGO_md5);
162     if (!newp) {
163     logmode = LOGMODE_STDIO;
164     bb_error_msg_and_die("password for %s is unchanged", name);
165     }
166     } else if (opt & OPT_lock) {
167     if (!c) goto skip; /* passwd starts with '!' */
168     newp = xasprintf("!%s", pw->pw_passwd);
169     } else if (opt & OPT_unlock) {
170     if (c) goto skip; /* not '!' */
171 niro 816 /* pw->pw_passwd points to static storage,
172     * strdup'ing to avoid nasty surprizes */
173 niro 532 newp = xstrdup(&pw->pw_passwd[1]);
174     } else if (opt & OPT_delete) {
175 niro 816 //newp = xstrdup("");
176     newp = (char*)"";
177 niro 532 }
178    
179     rlimit_fsize.rlim_cur = rlimit_fsize.rlim_max = 512L * 30000;
180     setrlimit(RLIMIT_FSIZE, &rlimit_fsize);
181 niro 816 bb_signals(0
182     + (1 << SIGHUP)
183     + (1 << SIGINT)
184     + (1 << SIGQUIT)
185     , SIG_IGN);
186 niro 532 umask(077);
187     xsetuid(0);
188 niro 816
189     #if ENABLE_FEATURE_SHADOWPASSWDS
190     filename = bb_path_shadow_file;
191 niro 984 rc = update_passwd(bb_path_shadow_file, name, newp, NULL);
192 niro 816 if (rc == 0) /* no lines updated, no errors detected */
193     #endif
194     {
195     filename = bb_path_passwd_file;
196 niro 984 rc = update_passwd(bb_path_passwd_file, name, newp, NULL);
197 niro 816 }
198     /* LOGMODE_BOTH */
199     if (rc < 0)
200 niro 984 bb_error_msg_and_die("can't update password file %s",
201 niro 532 filename);
202     bb_info_msg("Password for %s changed by %s", name, myname);
203    
204 niro 816 //if (ENABLE_FEATURE_CLEAN_UP) free(newp);
205     skip:
206 niro 532 if (!newp) {
207     bb_error_msg_and_die("password for %s is already %slocked",
208     name, (opt & OPT_unlock) ? "un" : "");
209     }
210     if (ENABLE_FEATURE_CLEAN_UP) free(myname);
211     return 0;
212     }