From f51ea5a6dc09ca726b14a65d08ee2496cb81c117 Mon Sep 17 00:00:00 2001 From: "Crist J. Clark" Date: Mon, 18 Mar 2002 02:22:53 +0000 Subject: It was possible for an unprivileged user to tie up the password information (no one else can vipw(8), chpass(1), or even passwd(1)), either on purpose or by accident, until an administrator manually intervened. Instead, do not lock the master.passwd file while a user is editing his information. But once we go to write the new information, check that the modified user's information has not changed in the password database since we started. Abort the changes if it has. Add a $FreeBSD$ to pw_copy.h. PR: i386/35816 Obtained from: NetBSD MFC after: 1 week --- chpass/pw_copy.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) (limited to 'chpass/pw_copy.c') diff --git a/chpass/pw_copy.c b/chpass/pw_copy.c index d475757..2e86dc3 100644 --- a/chpass/pw_copy.c +++ b/chpass/pw_copy.c @@ -48,15 +48,41 @@ static const char sccsid[] = "@(#)pw_copy.c 8.4 (Berkeley) 4/2/94"; #include #include +#include #include + #include "pw_copy.h" extern char *tempname; +/* for use in pw_copy(). Compare a pw entry to a pw struct. */ +static int +pw_equal(char *buf, struct passwd *pw) +{ + struct passwd buf_pw; + int len; + + len = strlen (buf); + if (buf[len-1] == '\n') + buf[len-1] = '\0'; + if (!__pw_scan(buf, &buf_pw, _PWSCAN_MASTER)) + return 0; + return (strcmp(pw->pw_name, buf_pw.pw_name) == 0 + && pw->pw_uid == buf_pw.pw_uid + && pw->pw_gid == buf_pw.pw_gid + && strcmp(pw->pw_class, buf_pw.pw_class) == 0 + && (long)pw->pw_change == (long)buf_pw.pw_change + && (long)pw->pw_expire == (long)buf_pw.pw_expire + && strcmp(pw->pw_gecos, buf_pw.pw_gecos) == 0 + && strcmp(pw->pw_dir, buf_pw.pw_dir) == 0 + && strcmp(pw->pw_shell, buf_pw.pw_shell) == 0); +} + + void -pw_copy(ffd, tfd, pw) +pw_copy(ffd, tfd, pw, old_pw) int ffd, tfd; - struct passwd *pw; + struct passwd *pw, *old_pw; { FILE *from, *to; int done; @@ -108,6 +134,12 @@ pw_copy(ffd, tfd, pw) goto err; continue; } + *p = ':'; + if (old_pw && !pw_equal(buf, old_pw)) { + warnx("%s: entry for %s has changed", + _PATH_MASTERPASSWD, pw->pw_name); + pw_error(NULL, 0, 1); + } (void)fprintf(to, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n", pw->pw_name, pw->pw_passwd, pw->pw_fields & _PWF_UID ? uidstr : "", -- cgit v1.2.3