Magellan Linux

Annotation of /tags/mkinitrd-6_2_0/loginutils/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


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