From 83602cd31ed43c6afafacf903fbec03e74cdbfb3 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Sun, 20 Sep 2009 16:18:37 +0200 Subject: [PATCH] Sync vipw(8) with FreeBSD. Mainly, use libutil for passwd manipulation. --- usr.sbin/vipw/Makefile | 7 +- usr.sbin/vipw/pw_util.c | 255 ------------------------------------------------ usr.sbin/vipw/pw_util.h | 43 -------- usr.sbin/vipw/vipw.c | 99 +++++++++---------- 4 files changed, 49 insertions(+), 355 deletions(-) delete mode 100644 usr.sbin/vipw/pw_util.c delete mode 100644 usr.sbin/vipw/pw_util.h diff --git a/usr.sbin/vipw/Makefile b/usr.sbin/vipw/Makefile index 11f8164414..05d42995e0 100644 --- a/usr.sbin/vipw/Makefile +++ b/usr.sbin/vipw/Makefile @@ -1,10 +1,11 @@ # @(#)Makefile 8.1 (Berkeley) 6/6/93 -# $FreeBSD: src/usr.sbin/vipw/Makefile,v 1.2.14.1 2001/04/25 12:11:09 ru Exp $ +# $FreeBSD: src/usr.sbin/vipw/Makefile,v 1.8 2003/04/04 17:49:20 obrien Exp $ # $DragonFly: src/usr.sbin/vipw/Makefile,v 1.2 2003/06/17 04:30:03 dillon Exp $ PROG= vipw -SRCS= pw_util.c vipw.c MAN= vipw.8 -WARNS?= 2 + +DPADD= ${LIBUTIL} +LDADD= -lutil .include diff --git a/usr.sbin/vipw/pw_util.c b/usr.sbin/vipw/pw_util.c deleted file mode 100644 index d34002bb02..0000000000 --- a/usr.sbin/vipw/pw_util.c +++ /dev/null @@ -1,255 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pw_util.c 8.3 (Berkeley) 4/2/94 - * $FreeBSD: src/usr.sbin/vipw/pw_util.c,v 1.17.2.4 2002/09/04 15:28:10 des Exp $ - * $DragonFly: src/usr.sbin/vipw/pw_util.c,v 1.5 2005/12/26 20:18:56 dillon Exp $ - */ - -/* - * This file is used by all the "password" programs; vipw(8), chpass(1), - * and passwd(1). - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pw_util.h" - -extern char *tempname; -static pid_t editpid = -1; -static int lockfd; -char *mppath = _PATH_PWD; -char *masterpasswd = _PATH_MASTERPASSWD; - -void -pw_cont(int sig) -{ - if (editpid != -1) { - kill(editpid, sig); - } -} - -void -pw_init(void) -{ - struct rlimit rlim; - - /* Unlimited resource limits. */ - rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; - setrlimit(RLIMIT_CPU, &rlim); - setrlimit(RLIMIT_FSIZE, &rlim); - setrlimit(RLIMIT_STACK, &rlim); - setrlimit(RLIMIT_DATA, &rlim); - setrlimit(RLIMIT_RSS, &rlim); - - /* Don't drop core (not really necessary, but GP's). */ - rlim.rlim_cur = rlim.rlim_max = 0; - setrlimit(RLIMIT_CORE, &rlim); - - /* Turn off signals. */ - signal(SIGALRM, SIG_IGN); - signal(SIGHUP, SIG_IGN); - signal(SIGINT, SIG_IGN); - signal(SIGPIPE, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - signal(SIGTERM, SIG_IGN); - signal(SIGCONT, pw_cont); - - /* Create with exact permissions. */ - umask(0); -} - -int -pw_lock(void) -{ - /* - * If the master password file doesn't exist, the system is hosed. - * Might as well try to build one. Set the close-on-exec bit so - * that users can't get at the encrypted passwords while editing. - * Open should allow flock'ing the file; see 4.4BSD. XXX - */ - for (;;) { - struct stat st; - - lockfd = open(masterpasswd, O_RDONLY, 0); - if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) - err(1, "%s", masterpasswd); - if (flock(lockfd, LOCK_EX|LOCK_NB)) - errx(1, "the password db file is busy"); - - /* - * If the password file was replaced while we were trying to - * get the lock, our hardlink count will be 0 and we have to - * close and retry. - */ - if (fstat(lockfd, &st) < 0) - errx(1, "fstat() failed"); - if (st.st_nlink != 0) - break; - close(lockfd); - lockfd = -1; - } - return (lockfd); -} - -int -pw_tmp(void) -{ - static char path[MAXPATHLEN]; - int fd; - char *p; - - if ((p = strrchr(masterpasswd, '/')) == NULL) - strcpy(path, "pw.XXXXXX"); - else - if (snprintf(path, sizeof path, "%.*s/pw.XXXXXX", - (int)(p - masterpasswd), masterpasswd) >= sizeof path) - errx(1, "%s: path too long", masterpasswd); - if ((fd = mkstemp(path)) == -1) - err(1, "%s", path); - tempname = path; - return (fd); -} - -int -pw_mkdb(char *username) -{ - int pstat; - pid_t pid; - - fflush(stderr); - if (!(pid = fork())) { - if(!username) { - warnx("rebuilding the database..."); - execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-d", mppath, - tempname, NULL); - } else { - warnx("updating the database..."); - execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-d", mppath, - "-u", username, tempname, NULL); - } - pw_error(_PATH_PWD_MKDB, 1, 1); - } - pid = waitpid(pid, &pstat, 0); - if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) - return (0); - warnx("done"); - return (1); -} - -void -pw_edit(int notsetuid) -{ - int pstat; - char *p, *editor; - - if (!(editor = getenv("EDITOR"))) - editor = _PATH_VI; - if ((p = strrchr(editor, '/'))) - ++p; - else - p = editor; - - if (!(editpid = fork())) { - if (notsetuid) { - setgid(getgid()); - setuid(getuid()); - } - errno = 0; - execlp(editor, p, tempname, NULL); - _exit(errno); - } - for (;;) { - editpid = waitpid(editpid, (int *)&pstat, 0); - errno = WEXITSTATUS(pstat); - if (editpid == -1) - pw_error(editor, 1, 1); - else if (WIFSTOPPED(pstat)) - ; /*raise(WSTOPSIG(pstat));*/ - else if (WIFEXITED(pstat) && errno == 0) - break; - else - pw_error(editor, 1, 1); - } - editpid = -1; -} - -void -pw_prompt(void) -{ - int c, first; - - printf("re-edit the password file? [y]: "); - fflush(stdout); - first = c = getchar(); - while (c != '\n' && c != EOF) - c = getchar(); - if (first == 'n') - pw_error(NULL, 0, 0); -} - -void -pw_error(char *name, int err, int eval) -{ -#ifdef YP - extern int _use_yp; -#endif /* YP */ - if (err) { - if (name != NULL) - warn("%s", name); - else - warn(NULL); - } -#ifdef YP - if (_use_yp) - warnx("NIS information unchanged"); - else -#endif /* YP */ - warnx("%s: unchanged", masterpasswd); - unlink(tempname); - exit(eval); -} diff --git a/usr.sbin/vipw/pw_util.h b/usr.sbin/vipw/pw_util.h deleted file mode 100644 index 7b51979e95..0000000000 --- a/usr.sbin/vipw/pw_util.h +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * Copyright (c) 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pw_util.h 8.2 (Berkeley) 4/1/94 - * $DragonFly: src/usr.sbin/vipw/pw_util.h,v 1.3 2003/11/03 19:31:44 eirikn Exp $ - */ - -void pw_edit(int); -void pw_error(char *, int, int); -void pw_init(void); -int pw_lock(void); -int pw_mkdb(char *); -void pw_prompt(void); -int pw_tmp(void); diff --git a/usr.sbin/vipw/vipw.c b/usr.sbin/vipw/vipw.c index 2b69dfbe96..3b88483b14 100644 --- a/usr.sbin/vipw/vipw.c +++ b/usr.sbin/vipw/vipw.c @@ -1,6 +1,13 @@ /* * Copyright (c) 1987, 1993, 1994 * The Regents of the University of California. All rights reserved. + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * Portions of this software were developed for the FreeBSD Project by + * ThinkSec AS and NAI Labs, the Security Research Division of Network + * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 + * ("CBOSS"), as part of the DARPA CHATS research program. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +17,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -32,7 +35,7 @@ * * @(#) Copyright (c) 1987, 1993, 1994 The Regents of the University of California. All rights reserved. * @(#)vipw.c 8.3 (Berkeley) 4/2/94 - * $FreeBSD: src/usr.sbin/vipw/vipw.c,v 1.11 1999/10/25 09:46:57 sheldonh Exp $ + * $FreeBSD: src/usr.sbin/vipw/vipw.c,v 1.16 2004/08/07 04:28:56 imp Exp $ * $DragonFly: src/usr.sbin/vipw/vipw.c,v 1.5 2005/12/05 01:23:23 swildner Exp $ */ @@ -46,37 +49,22 @@ #include #include -#include "pw_util.h" - -extern char *mppath; -extern char *masterpasswd; -char *tempname; +#include /* must be after pwd.h */ -void copyfile(int, int); static void usage(void); int main(int argc, char *argv[]) { - int pfd, tfd; - struct stat begin, end; - int ch; + const char *passwd_dir = NULL; + int ch, pfd, tfd; + char *line; + size_t len; while ((ch = getopt(argc, argv, "d:")) != -1) switch (ch) { case 'd': - if ((masterpasswd = malloc(strlen(optarg) + - strlen(_MASTERPASSWD) + 2)) == NULL) - err(1, NULL); - strcpy(masterpasswd, optarg); - if (masterpasswd[strlen(masterpasswd) - 1] != '/') - strcat(masterpasswd, "/" _MASTERPASSWD); - else - strcat(masterpasswd, _MASTERPASSWD); - if ((mppath = strdup(optarg)) == NULL) - err(1, NULL); - if (mppath[strlen(mppath) - 1] == '/') - mppath[strlen(mppath) - 1] = '\0'; + passwd_dir = optarg; break; case '?': default: @@ -89,45 +77,48 @@ main(int argc, char *argv[]) if (argc != 0) usage(); - pw_init(); - pfd = pw_lock(); - tfd = pw_tmp(); - copyfile(pfd, tfd); + if (pw_init(passwd_dir, NULL) == -1) + err(1, "pw_init()"); + if ((pfd = pw_lock()) == -1) { + pw_fini(); + err(1, "pw_lock()"); + } + if ((tfd = pw_tmp(pfd)) == -1) { + pw_fini(); + err(1, "pw_tmp()"); + } close(tfd); /* Force umask for partial writes made in the edit phase */ umask(077); for (;;) { - if (stat(tempname, &begin)) - pw_error(tempname, 1, 1); - pw_edit(0); - if (stat(tempname, &end)) - pw_error(tempname, 1, 1); - if (begin.st_mtime == end.st_mtime) { - warnx("no changes made"); - pw_error(NULL, 0, 0); + switch (pw_edit(0)) { + case -1: + pw_fini(); + err(1, "pw_edit()"); + case 0: + pw_fini(); + errx(0, "no changes made"); + default: + break; } - if (pw_mkdb(NULL)) + if (pw_mkdb(NULL) == 0) { + pw_fini(); + errx(0, "password list updated"); + } + printf("re-edit the password file? "); + fflush(stdout); + if ((line = fgetln(stdin, &len)) == NULL) { + pw_fini(); + err(1, "fgetln()"); + } + if (len > 0 && (*line == 'N' || *line == 'n')) break; - pw_prompt(); } + pw_fini(); exit(0); } -void -copyfile(int from, int to) -{ - int nr, nw, off; - char buf[8*1024]; - - while ((nr = read(from, buf, sizeof(buf))) > 0) - for (off = 0; off < nr; nr -= nw, off += nw) - if ((nw = write(to, buf + off, nr)) < 0) - pw_error(tempname, 1, 1); - if (nr < 0) - pw_error(masterpasswd, 1, 1); -} - static void usage(void) { -- 2.11.4.GIT