diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2001-07-04 17:20:25 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2001-07-04 17:20:25 +0000 |
commit | 8c8deb8c36aab4146522f000e24bb82b567d524d (patch) | |
tree | bcb2768eb274f0b496208c7c39512e4d9718a4f8 /usr.bin/passwd | |
parent | 56fd4f374bd7cb084a2393ebdbdc535e9a085a44 (diff) |
Move locking of the passwd file *after* we have gotten a new password
from the user. Set real/effective/saved uids to 0 and block all signals
so the lock cannot be kept longer than necessary. If we cannot lock,
try again every 1/4 second for 2 seconds and then ask the user what
they wish to do (keep trying, quit).
Diffstat (limited to 'usr.bin/passwd')
-rw-r--r-- | usr.bin/passwd/local_passwd.c | 79 |
1 files changed, 64 insertions, 15 deletions
diff --git a/usr.bin/passwd/local_passwd.c b/usr.bin/passwd/local_passwd.c index 80c576c3662..a1b3f4e71a7 100644 --- a/usr.bin/passwd/local_passwd.c +++ b/usr.bin/passwd/local_passwd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local_passwd.c,v 1.14 2001/06/18 21:09:23 millert Exp $ */ +/* $OpenBSD: local_passwd.c,v 1.15 2001/07/04 17:20:24 millert Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -35,7 +35,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)local_passwd.c 5.5 (Berkeley) 5/6/91";*/ -static char rcsid[] = "$OpenBSD: local_passwd.c,v 1.14 2001/06/18 21:09:23 millert Exp $"; +static char rcsid[] = "$OpenBSD: local_passwd.c,v 1.15 2001/07/04 17:20:24 millert Exp $"; #endif /* not lint */ #include <sys/types.h> @@ -48,6 +48,7 @@ static char rcsid[] = "$OpenBSD: local_passwd.c,v 1.14 2001/06/18 21:09:23 mille #include <unistd.h> #include <ctype.h> #include <fcntl.h> +#include <signal.h> #include <util.h> #include <login_cap.h> @@ -57,6 +58,7 @@ extern int pwd_check __P((struct passwd *, login_cap_t *, char *)); extern int pwd_gettries __P((struct passwd *, login_cap_t *)); char *getnewpasswd __P((struct passwd *, login_cap_t *, int)); +void kbintr __P((int)); int local_passwd(uname, authenticated) @@ -65,8 +67,10 @@ local_passwd(uname, authenticated) { struct passwd *pw; login_cap_t *lc; - int pfd, tfd; + sigset_t fullset; time_t period; + int pfd, tfd; + char *s = NULL; if (!(pw = getpwnam(uname))) { #ifdef YP @@ -87,18 +91,6 @@ local_passwd(uname, authenticated) return(1); } - pw_init(); - tfd = pw_lock(0); - if (tfd < 0) { - if (errno == EEXIST) - errx(1, "the passwd file is busy."); - else - err(1, "can't open passwd temp file"); - } - pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0); - if (pfd < 0 || fcntl(pfd, F_SETFD, 1) == -1) - pw_error(_PATH_MASTERPASSWD, 1, 1); - /* Get the new password. */ pw->pw_passwd = getnewpasswd(pw, lc, authenticated); @@ -109,6 +101,53 @@ local_passwd(uname, authenticated) else pw->pw_change = 0; + /* Drop user's real uid and block all signals to avoid a DoS. */ + setuid(0); + sigfillset(&fullset); + sigdelset(&fullset, SIGINT); + sigprocmask(SIG_BLOCK, &fullset, NULL); + + /* Get a lock on the passwd file and open it. */ + pw_init(); + for (;;) { + int i, c, d; + + (void)fputs("Please wait", stderr); + for (i = 0; i < (s ? 64 : 8) && (tfd = pw_lock(0)) == -1; i++) { + (void)signal(SIGINT, kbintr); + fputc('.', stderr); + usleep(250000); + (void)signal(SIGINT, SIG_IGN); + } + fputc('\n', stderr); + if (tfd != -1) + break; + + /* Unable to lock passwd file, let the user decide. */ + if (errno == EEXIST) { + if (s == NULL) + s = "The passwd file is busy,"; + else + s = "The passwd file is still busy,"; + } else + s = "Unable to open passwd temp file,"; + (void)fprintf(stderr, + "%s do you want to wait until it is available? [y/n] ", s); + (void)signal(SIGINT, kbintr); + c = getchar(); + (void)signal(SIGINT, SIG_IGN); + if (c != '\n') + while ((d = getchar()) != '\n' && d != EOF) + ; + if (tolower(c) != 'y') { + printf("Password unchanged\n"); + exit(1); + } + } + pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0); + if (pfd < 0 || fcntl(pfd, F_SETFD, 1) == -1) + pw_error(_PATH_MASTERPASSWD, 1, 1); + /* Update master.passwd file and build .db version. */ pw_copy(pfd, tfd, pw); if (pw_mkdb(uname) < 0) @@ -164,3 +203,13 @@ getnewpasswd(pw, lc, authenticated) } return(crypt(buf, salt)); } + +void +kbintr(signo) + int signo; +{ + char msg[] = "\nPassword unchanged\n"; + + write(STDOUT_FILENO, msg, sizeof(msg) - 1); + _exit(1); +} |