aboutsummaryrefslogtreecommitdiff
path: root/loginutils
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-07-20 21:28:41 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-07-20 21:28:41 +0000
commit21d1014b5b91d1a1319273945291b7a9f4717827 (patch)
treeb84eadba35d31f923ef62579652e4e5d76678c38 /loginutils
parent2f6ae43b9c74d393a139007377895e8c50b8af9a (diff)
downloadbusybox-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.in8
-rw-r--r--loginutils/Kbuild1
-rw-r--r--loginutils/cryptpw.c4
-rw-r--r--loginutils/passwd.c121
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
183config 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
183config SU 191config 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:=
8lib-$(CONFIG_ADDGROUP) += addgroup.o 8lib-$(CONFIG_ADDGROUP) += addgroup.o
9lib-$(CONFIG_ADDUSER) += adduser.o 9lib-$(CONFIG_ADDUSER) += adduser.o
10lib-$(CONFIG_CRYPTPW) += cryptpw.o 10lib-$(CONFIG_CRYPTPW) += cryptpw.o
11lib-$(CONFIG_CHPASSWD) += chpasswd.o
11lib-$(CONFIG_GETTY) += getty.o 12lib-$(CONFIG_GETTY) += getty.o
12lib-$(CONFIG_LOGIN) += login.o 13lib-$(CONFIG_LOGIN) += login.o
13lib-$(CONFIG_PASSWD) += passwd.o 14lib-$(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
74static 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
182int passwd_main(int argc, char **argv); 73int passwd_main(int argc, char **argv);
183int passwd_main(int argc, char **argv) 74int 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);