aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-07-27 11:22:34 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-07-27 11:22:34 +0000
commit1d10aaf11617558592b0215fe85bc42fa444e384 (patch)
tree033e1b9896e651a3ab1d94b255a534ff39a91845
parent3734b946bfef55c8f63d367422da5c7aa7b972db (diff)
downloadbusybox-1d10aaf11617558592b0215fe85bc42fa444e384.tar.gz
passwd: fix bug: we are trying to update shadow even if user's record is in passwd!
getspnam is guilty, it lies that user record exists in shadow.
-rw-r--r--include/libbb.h8
-rw-r--r--loginutils/passwd.c20
2 files changed, 19 insertions, 9 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 82cee380b..b438ec25f 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -482,10 +482,10 @@ int get_uidgid(struct bb_uidgid_t*, const char*, int numeric_ok);
/* chown-like handling of "user[:[group]" */
void parse_chown_usergroup_or_die(struct bb_uidgid_t *u, char *user_group);
/* bb_getpwuid, bb_getgrgid:
-bb_getXXXid(buf, bufsz, id) - copy user/group name or id
- as a string to buf, return user/group name or NULL
-bb_getXXXid(NULL, 0, id) - return user/group name or NULL
-bb_getXXXid(NULL, -1, id) - return user/group name or exit
+ * bb_getXXXid(buf, bufsz, id) - copy user/group name or id
+ * as a string to buf, return user/group name or NULL
+ * bb_getXXXid(NULL, 0, id) - return user/group name or NULL
+ * bb_getXXXid(NULL, -1, id) - return user/group name or exit
*/
char *bb_getpwuid(char *name, int bufsize, long uid);
char *bb_getgrgid(char *group, int bufsize, long gid);
diff --git a/loginutils/passwd.c b/loginutils/passwd.c
index a293ee926..4f7094aec 100644
--- a/loginutils/passwd.c
+++ b/loginutils/passwd.c
@@ -127,15 +127,16 @@ int passwd_main(int argc, char **argv)
bb_error_msg_and_die("%s can't change password for %s", myname, name);
}
- filename = bb_path_passwd_file;
#if ENABLE_FEATURE_SHADOWPASSWDS
- if (getspnam_r(pw->pw_name, &spw, buffer, sizeof(buffer), &result)) {
+ /* getspnam_r() can lie! Even if user isn't in shadow, it can
+ * return success (pwd field was seen set to "!" in this case) */
+ if (getspnam_r(pw->pw_name, &spw, buffer, sizeof(buffer), &result)
+ || LONE_CHAR(spw.sp_pwdp, '!')) {
/* LOGMODE_BOTH */
bb_error_msg("no record of %s in %s, using %s",
name, bb_path_shadow_file,
bb_path_passwd_file);
} else {
- filename = bb_path_shadow_file;
pw->pw_passwd = spw.sp_pwdp;
}
#endif
@@ -175,8 +176,17 @@ int passwd_main(int argc, char **argv)
signal(SIGQUIT, SIG_IGN);
umask(077);
xsetuid(0);
- rc = update_passwd(filename, name, newp);
- logmode = LOGMODE_BOTH;
+
+#if ENABLE_FEATURE_SHADOWPASSWDS
+ filename = bb_path_shadow_file;
+ rc = update_passwd(bb_path_shadow_file, name, newp);
+ if (rc == 0) /* no lines updated, no errors detected */
+#endif
+ {
+ filename = bb_path_passwd_file;
+ rc = update_passwd(bb_path_passwd_file, name, newp);
+ }
+ /* LOGMODE_BOTH */
if (rc < 0)
bb_error_msg_and_die("cannot update password file %s",
filename);