diff options
author | Ricardo Mestre <mestre@cvs.openbsd.org> | 2016-05-03 21:05:15 +0000 |
---|---|---|
committer | Ricardo Mestre <mestre@cvs.openbsd.org> | 2016-05-03 21:05:15 +0000 |
commit | 574e25e5346a072323ee6caae33aa7e17663a910 (patch) | |
tree | 0bfdd3a8b6d58dc827ddf947f9393cb4338f809e | |
parent | 038c1503d1e9350cd20c8a09443719bfcda1f66d (diff) |
Fix regression on usermod/userdel by calling getpwnam_shadow(3) and saving
passwd hash early, instead of getpwnam(3), then close fds by calling
endpwent(3) and finally only call pledge(2) after it, otherwise on any
modification to the user it would destroy the passwd hash and therefore
forbidding him/her to login again to the machine.
Reported and tested by Edgar Pettijohn <edgar ! pettijohn-web at com>
According to deraadt@ "that looks better then"
-rw-r--r-- | usr.sbin/user/user.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/usr.sbin/user/user.c b/usr.sbin/user/user.c index 95deb93f9b5..27344a768b8 100644 --- a/usr.sbin/user/user.c +++ b/usr.sbin/user/user.c @@ -1,4 +1,4 @@ -/* $OpenBSD: user.c,v 1.110 2016/05/02 15:25:03 millert Exp $ */ +/* $OpenBSD: user.c,v 1.111 2016/05/03 21:05:14 mestre Exp $ */ /* $NetBSD: user.c,v 1.69 2003/04/14 17:40:07 agc Exp $ */ /* @@ -1377,7 +1377,7 @@ is_local(char *name, const char *file) static int moduser(char *login_name, char *newlogin, user_t *up) { - struct passwd *pwp; + struct passwd *pwp = NULL; struct group *grp; const char *homedir; char buf[LINE_MAX]; @@ -1405,9 +1405,23 @@ moduser(char *login_name, char *newlogin, user_t *up) if (!valid_login(newlogin)) { errx(EXIT_FAILURE, "`%s' is not a valid login name", login_name); } - if ((pwp = getpwnam(login_name)) == NULL) { + if ((pwp = getpwnam_shadow(login_name)) == NULL) { errx(EXIT_FAILURE, "No such user `%s'", login_name); } + if (up != NULL) { + if ((*pwp->pw_passwd != '\0') && (up->u_flags &~ F_PASSWORD)) { + up->u_flags |= F_PASSWORD; + memsave(&up->u_password, pwp->pw_passwd, + strlen(pwp->pw_passwd)); + memset(pwp->pw_passwd, 'X', strlen(pwp->pw_passwd)); + } + } + endpwent(); + + if (pledge("stdio rpath wpath cpath fattr flock proc exec getpw id", + NULL) == -1) + err(1, "pledge"); + if (!is_local(login_name, _PATH_MASTERPASSWD)) { errx(EXIT_FAILURE, "User `%s' must be a local user", login_name); } @@ -1987,10 +2001,6 @@ usermod(int argc, char **argv) } } - if (pledge("stdio rpath wpath cpath fattr flock proc exec getpw id", - NULL) == -1) - err(1, "pledge"); - if ((u.u_flags & F_MKDIR) && !(u.u_flags & F_HOMEDIR) && !(u.u_flags & F_USERNAME)) { warnx("option 'm' useless without 'd' or 'l' -- ignored"); |