diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-07-20 21:28:41 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-07-20 21:28:41 +0000 |
commit | 21d1014b5b91d1a1319273945291b7a9f4717827 (patch) | |
tree | b84eadba35d31f923ef62579652e4e5d76678c38 /loginutils | |
parent | 2f6ae43b9c74d393a139007377895e8c50b8af9a (diff) | |
download | busybox-w32-21d1014b5b91d1a1319273945291b7a9f4717827.tar.gz busybox-w32-21d1014b5b91d1a1319273945291b7a9f4717827.tar.bz2 busybox-w32-21d1014b5b91d1a1319273945291b7a9f4717827.zip |
chpasswd: new applet by Alexander Shishkin <virtuoso@slind.org>
Diffstat (limited to 'loginutils')
-rw-r--r-- | loginutils/Config.in | 8 | ||||
-rw-r--r-- | loginutils/Kbuild | 1 | ||||
-rw-r--r-- | loginutils/cryptpw.c | 4 | ||||
-rw-r--r-- | loginutils/passwd.c | 121 |
4 files changed, 17 insertions, 117 deletions
diff --git a/loginutils/Config.in b/loginutils/Config.in index f9ae122e4..63ae9b4db 100644 --- a/loginutils/Config.in +++ b/loginutils/Config.in | |||
@@ -180,6 +180,14 @@ config CRYPTPW | |||
180 | help | 180 | help |
181 | Applet for crypting a string. | 181 | Applet for crypting a string. |
182 | 182 | ||
183 | config CHPASSWD | ||
184 | bool "chpasswd" | ||
185 | default n | ||
186 | help | ||
187 | chpasswd reads a file of user name and password pairs from | ||
188 | standard input and uses this information to update a group of | ||
189 | existing users. | ||
190 | |||
183 | config SU | 191 | config SU |
184 | bool "su" | 192 | bool "su" |
185 | default n | 193 | default n |
diff --git a/loginutils/Kbuild b/loginutils/Kbuild index 1b1165a6e..3d0d777e8 100644 --- a/loginutils/Kbuild +++ b/loginutils/Kbuild | |||
@@ -8,6 +8,7 @@ lib-y:= | |||
8 | lib-$(CONFIG_ADDGROUP) += addgroup.o | 8 | lib-$(CONFIG_ADDGROUP) += addgroup.o |
9 | lib-$(CONFIG_ADDUSER) += adduser.o | 9 | lib-$(CONFIG_ADDUSER) += adduser.o |
10 | lib-$(CONFIG_CRYPTPW) += cryptpw.o | 10 | lib-$(CONFIG_CRYPTPW) += cryptpw.o |
11 | lib-$(CONFIG_CHPASSWD) += chpasswd.o | ||
11 | lib-$(CONFIG_GETTY) += getty.o | 12 | lib-$(CONFIG_GETTY) += getty.o |
12 | lib-$(CONFIG_LOGIN) += login.o | 13 | lib-$(CONFIG_LOGIN) += login.o |
13 | lib-$(CONFIG_PASSWD) += passwd.o | 14 | lib-$(CONFIG_PASSWD) += passwd.o |
diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c index dd7304613..1c3059198 100644 --- a/loginutils/cryptpw.c +++ b/loginutils/cryptpw.c | |||
@@ -17,9 +17,9 @@ int cryptpw_main(int argc, char **argv) | |||
17 | /* Too ugly, and needs even more magic to handle endianness: */ | 17 | /* Too ugly, and needs even more magic to handle endianness: */ |
18 | //((uint32_t*)&salt)[0] = '$' + '1'*0x100 + '$'*0x10000; | 18 | //((uint32_t*)&salt)[0] = '$' + '1'*0x100 + '$'*0x10000; |
19 | /* Hope one day gcc will do it itself (inlining strcpy) */ | 19 | /* Hope one day gcc will do it itself (inlining strcpy) */ |
20 | crypt_make_salt(salt + 3, 4); /* md5 */ | 20 | crypt_make_salt(salt + 3, 4, 0); /* md5 */ |
21 | } else { | 21 | } else { |
22 | crypt_make_salt(salt, 1); /* des */ | 22 | crypt_make_salt(salt, 1, 0); /* des */ |
23 | } | 23 | } |
24 | 24 | ||
25 | puts(pw_encrypt(argv[optind] ? argv[optind] : xmalloc_getline(stdin), salt)); | 25 | puts(pw_encrypt(argv[optind] ? argv[optind] : xmalloc_getline(stdin), salt)); |
diff --git a/loginutils/passwd.c b/loginutils/passwd.c index 8f65c3d0b..cd98d4101 100644 --- a/loginutils/passwd.c +++ b/loginutils/passwd.c | |||
@@ -52,10 +52,10 @@ static char* new_password(const struct passwd *pw, uid_t myuid, int algo) | |||
52 | } | 52 | } |
53 | 53 | ||
54 | /*memset(salt, 0, sizeof(salt)); - why?*/ | 54 | /*memset(salt, 0, sizeof(salt)); - why?*/ |
55 | crypt_make_salt(salt, 1); /* des */ | 55 | crypt_make_salt(salt, 1, 0); /* des */ |
56 | if (algo) { /* MD5 */ | 56 | if (algo) { /* MD5 */ |
57 | strcpy(salt, "$1$"); | 57 | strcpy(salt, "$1$"); |
58 | crypt_make_salt(salt + 3, 4); | 58 | crypt_make_salt(salt + 3, 4, 0); |
59 | } | 59 | } |
60 | ret = xstrdup(pw_encrypt(newp, salt)); /* returns ptr to static */ | 60 | ret = xstrdup(pw_encrypt(newp, salt)); /* returns ptr to static */ |
61 | /* whee, success! */ | 61 | /* whee, success! */ |
@@ -70,115 +70,6 @@ static char* new_password(const struct passwd *pw, uid_t myuid, int algo) | |||
70 | return ret; | 70 | return ret; |
71 | } | 71 | } |
72 | 72 | ||
73 | |||
74 | static int update_passwd(const char *filename, const char *username, | ||
75 | const char *new_pw) | ||
76 | { | ||
77 | struct stat sb; | ||
78 | struct flock lock; | ||
79 | FILE *old_fp; | ||
80 | FILE *new_fp; | ||
81 | char *new_name; | ||
82 | char *last_char; | ||
83 | unsigned user_len; | ||
84 | int old_fd; | ||
85 | int new_fd; | ||
86 | int i; | ||
87 | int ret = 1; /* failure */ | ||
88 | |||
89 | logmode = LOGMODE_STDIO; | ||
90 | /* New passwd file, "/etc/passwd+" for now */ | ||
91 | new_name = xasprintf("%s+", filename); | ||
92 | last_char = &new_name[strlen(new_name)-1]; | ||
93 | username = xasprintf("%s:", username); | ||
94 | user_len = strlen(username); | ||
95 | |||
96 | old_fp = fopen(filename, "r+"); | ||
97 | if (!old_fp) | ||
98 | goto free_mem; | ||
99 | old_fd = fileno(old_fp); | ||
100 | |||
101 | /* Try to create "/etc/passwd+". Wait if it exists. */ | ||
102 | i = 30; | ||
103 | do { | ||
104 | // FIXME: on last iteration try w/o O_EXCL but with O_TRUNC? | ||
105 | new_fd = open(new_name, O_WRONLY|O_CREAT|O_EXCL,0600); | ||
106 | if (new_fd >= 0) goto created; | ||
107 | if (errno != EEXIST) break; | ||
108 | usleep(100000); /* 0.1 sec */ | ||
109 | } while (--i); | ||
110 | bb_perror_msg("cannot create '%s'", new_name); | ||
111 | goto close_old_fp; | ||
112 | created: | ||
113 | if (!fstat(old_fd, &sb)) { | ||
114 | fchmod(new_fd, sb.st_mode & 0777); /* ignore errors */ | ||
115 | fchown(new_fd, sb.st_uid, sb.st_gid); | ||
116 | } | ||
117 | new_fp = fdopen(new_fd, "w"); | ||
118 | if (!new_fp) { | ||
119 | close(new_fd); | ||
120 | goto unlink_new; | ||
121 | } | ||
122 | |||
123 | /* Backup file is "/etc/passwd-" */ | ||
124 | last_char[0] = '-'; | ||
125 | /* Delete old one, create new as a hardlink to current */ | ||
126 | i = (unlink(new_name) && errno != ENOENT); | ||
127 | if (i || link(filename, new_name)) | ||
128 | bb_perror_msg("warning: cannot create backup copy '%s'", new_name); | ||
129 | last_char[0] = '+'; | ||
130 | |||
131 | /* Lock the password file before updating */ | ||
132 | lock.l_type = F_WRLCK; | ||
133 | lock.l_whence = SEEK_SET; | ||
134 | lock.l_start = 0; | ||
135 | lock.l_len = 0; | ||
136 | if (fcntl(old_fd, F_SETLK, &lock) < 0) | ||
137 | bb_perror_msg("warning: cannot lock '%s'", filename); | ||
138 | lock.l_type = F_UNLCK; | ||
139 | |||
140 | /* Read current password file, write updated one */ | ||
141 | while (1) { | ||
142 | char *line = xmalloc_fgets(old_fp); | ||
143 | if (!line) break; /* EOF/error */ | ||
144 | if (strncmp(username, line, user_len) == 0) { | ||
145 | /* we have a match with "username:"... */ | ||
146 | const char *cp = line + user_len; | ||
147 | /* now cp -> old passwd, skip it: */ | ||
148 | cp = strchr(cp, ':'); | ||
149 | if (!cp) cp = ""; | ||
150 | /* now cp -> ':' after old passwd or -> "" */ | ||
151 | fprintf(new_fp, "%s%s%s", username, new_pw, cp); | ||
152 | /* Erase password in memory */ | ||
153 | } else | ||
154 | fputs(line, new_fp); | ||
155 | free(line); | ||
156 | } | ||
157 | fcntl(old_fd, F_SETLK, &lock); | ||
158 | |||
159 | /* We do want all of them to execute, thus | instead of || */ | ||
160 | if ((ferror(old_fp) | fflush(new_fp) | fsync(new_fd) | fclose(new_fp)) | ||
161 | || rename(new_name, filename) | ||
162 | ) { | ||
163 | /* At least one of those failed */ | ||
164 | goto unlink_new; | ||
165 | } | ||
166 | ret = 0; /* whee, success! */ | ||
167 | |||
168 | unlink_new: | ||
169 | if (ret) unlink(new_name); | ||
170 | |||
171 | close_old_fp: | ||
172 | fclose(old_fp); | ||
173 | |||
174 | free_mem: | ||
175 | if (ENABLE_FEATURE_CLEAN_UP) free(new_name); | ||
176 | if (ENABLE_FEATURE_CLEAN_UP) free((char*)username); | ||
177 | logmode = LOGMODE_BOTH; | ||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | |||
182 | int passwd_main(int argc, char **argv); | 73 | int passwd_main(int argc, char **argv); |
183 | int passwd_main(int argc, char **argv) | 74 | int passwd_main(int argc, char **argv) |
184 | { | 75 | { |
@@ -192,6 +83,7 @@ int passwd_main(int argc, char **argv) | |||
192 | /*STATE_ALGO_des = 0x20, not needed yet */ | 83 | /*STATE_ALGO_des = 0x20, not needed yet */ |
193 | }; | 84 | }; |
194 | unsigned opt; | 85 | unsigned opt; |
86 | int rc; | ||
195 | const char *opt_a = ""; | 87 | const char *opt_a = ""; |
196 | const char *filename; | 88 | const char *filename; |
197 | char *myname; | 89 | char *myname; |
@@ -278,12 +170,11 @@ int passwd_main(int argc, char **argv) | |||
278 | signal(SIGQUIT, SIG_IGN); | 170 | signal(SIGQUIT, SIG_IGN); |
279 | umask(077); | 171 | umask(077); |
280 | xsetuid(0); | 172 | xsetuid(0); |
281 | if (update_passwd(filename, name, newp) != 0) { | 173 | rc = update_passwd(filename, name, newp); |
282 | /* LOGMODE_BOTH */ | 174 | logmode = LOGMODE_BOTH; |
175 | if (rc < 0) | ||
283 | bb_error_msg_and_die("cannot update password file %s", | 176 | bb_error_msg_and_die("cannot update password file %s", |
284 | filename); | 177 | filename); |
285 | } | ||
286 | /* LOGMODE_BOTH */ | ||
287 | bb_info_msg("Password for %s changed by %s", name, myname); | 178 | bb_info_msg("Password for %s changed by %s", name, myname); |
288 | 179 | ||
289 | if (ENABLE_FEATURE_CLEAN_UP) free(newp); | 180 | if (ENABLE_FEATURE_CLEAN_UP) free(newp); |