diff options
author | rgrimes <rgrimes@FreeBSD.org> | 1994-05-26 05:23:31 +0000 |
---|---|---|
committer | rgrimes <rgrimes@FreeBSD.org> | 1994-05-26 05:23:31 +0000 |
commit | 862fdf11a2ede45dec0da01ed575525d79468981 (patch) | |
tree | 7a1c88ccb8006476bd4b4a548a6ad48fbfc33a01 /usr.sbin/pwd_mkdb | |
parent | 8e1a19ddde0df113b0b26b0ea621afd61dbaf91f (diff) | |
download | FreeBSD-src-862fdf11a2ede45dec0da01ed575525d79468981.zip FreeBSD-src-862fdf11a2ede45dec0da01ed575525d79468981.tar.gz |
BSD 4.4 Lite usr.sbin Sources
Diffstat (limited to 'usr.sbin/pwd_mkdb')
-rw-r--r-- | usr.sbin/pwd_mkdb/Makefile | 7 | ||||
-rw-r--r-- | usr.sbin/pwd_mkdb/pw_scan.c | 122 | ||||
-rw-r--r-- | usr.sbin/pwd_mkdb/pw_scan.h | 36 | ||||
-rw-r--r-- | usr.sbin/pwd_mkdb/pwd_mkdb.8 | 128 | ||||
-rw-r--r-- | usr.sbin/pwd_mkdb/pwd_mkdb.c | 387 |
5 files changed, 680 insertions, 0 deletions
diff --git a/usr.sbin/pwd_mkdb/Makefile b/usr.sbin/pwd_mkdb/Makefile new file mode 100644 index 0000000..f1e9020 --- /dev/null +++ b/usr.sbin/pwd_mkdb/Makefile @@ -0,0 +1,7 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= pwd_mkdb +SRCS= pw_scan.c pwd_mkdb.c +MAN8= pwd_mkdb.0 + +.include <bsd.prog.mk> diff --git a/usr.sbin/pwd_mkdb/pw_scan.c b/usr.sbin/pwd_mkdb/pw_scan.c new file mode 100644 index 0000000..3093ac2 --- /dev/null +++ b/usr.sbin/pwd_mkdb/pw_scan.c @@ -0,0 +1,122 @@ +/*- + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)pw_scan.c 8.3 (Berkeley) 4/2/94"; +#endif /* not lint */ + +/* + * This module is used to "verify" password entries by chpass(1) and + * pwd_mkdb(8). + */ + +#include <sys/param.h> + +#include <err.h> +#include <fcntl.h> +#include <pwd.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +#include "pw_scan.h" + +int +pw_scan(bp, pw) + char *bp; + struct passwd *pw; +{ + long id; + int root; + char *p, *sh; + + if (!(pw->pw_name = strsep(&bp, ":"))) /* login */ + goto fmt; + root = !strcmp(pw->pw_name, "root"); + + if (!(pw->pw_passwd = strsep(&bp, ":"))) /* passwd */ + goto fmt; + + if (!(p = strsep(&bp, ":"))) /* uid */ + goto fmt; + id = atol(p); + if (root && id) { + warnx("root uid should be 0"); + return (0); + } + if (id > USHRT_MAX) { + warnx("%s > max uid value (%d)", p, USHRT_MAX); + return (0); + } + pw->pw_uid = id; + + if (!(p = strsep(&bp, ":"))) /* gid */ + goto fmt; + id = atol(p); + if (id > USHRT_MAX) { + warnx("%s > max gid value (%d)", p, USHRT_MAX); + return (0); + } + pw->pw_gid = id; + + pw->pw_class = strsep(&bp, ":"); /* class */ + if (!(p = strsep(&bp, ":"))) /* change */ + goto fmt; + pw->pw_change = atol(p); + if (!(p = strsep(&bp, ":"))) /* expire */ + goto fmt; + pw->pw_expire = atol(p); + pw->pw_gecos = strsep(&bp, ":"); /* gecos */ + pw->pw_dir = strsep(&bp, ":"); /* directory */ + if (!(pw->pw_shell = strsep(&bp, ":"))) /* shell */ + goto fmt; + + p = pw->pw_shell; + if (root && *p) /* empty == /bin/sh */ + for (setusershell();;) { + if (!(sh = getusershell())) { + warnx("warning, unknown root shell"); + break; + } + if (!strcmp(p, sh)) + break; + } + + if (p = strsep(&bp, ":")) { /* too many */ +fmt: warnx("corrupted entry"); + return (0); + } + return (1); +} diff --git a/usr.sbin/pwd_mkdb/pw_scan.h b/usr.sbin/pwd_mkdb/pw_scan.h new file mode 100644 index 0000000..d1d4bc1 --- /dev/null +++ b/usr.sbin/pwd_mkdb/pw_scan.h @@ -0,0 +1,36 @@ +/*- + * 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_scan.h 8.1 (Berkeley) 4/1/94 + */ + +extern int pw_scan __P((char *, struct passwd *)); diff --git a/usr.sbin/pwd_mkdb/pwd_mkdb.8 b/usr.sbin/pwd_mkdb/pwd_mkdb.8 new file mode 100644 index 0000000..01bc1c2 --- /dev/null +++ b/usr.sbin/pwd_mkdb/pwd_mkdb.8 @@ -0,0 +1,128 @@ +.\" Copyright (c) 1991, 1993 +.\" 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. +.\" +.\" @(#)pwd_mkdb.8 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt PWD_MKDB 8 +.Os +.Sh NAME +.Nm pwd_mkdb +.Nd "generate the password databases" +.Sh SYNOPSIS +.Nm pwd_mkdb +.Op Fl p +.Ar file +.Sh DESCRIPTION +.Nm Pwd_mkdb +creates +.Xr db 3 +style secure and insecure databases for the specified file. +These databases are then installed into +.Dq Pa /etc/spwd.db +and +.Dq Pa /etc/pwd.db +respectively. +The file is installed into +.Dq Pa /etc/master.passwd . +The file must be in the correct format (see +.Xr passwd 5 ) . +It is important to note that the format used in this system is +different from the historic Version 7 style format. +.Pp +The options are as follows: +.Bl -tag -width flag +.It Fl p +Create a Version 7 style password file and install it into +.Dq Pa /etc/passwd . +.El +.Pp +The two databases differ in that the secure version contains the user's +encrypted password and the insecure version has an asterisk (``*'') +.Pp +The databases are used by the C library password routines (see +.Xr getpwent 3 ) . +.Pp +.Nm Pwd_mkdb +exits zero on success, non-zero on failure. +.Sh FILES +.Bl -tag -width Pa -compact +.It Pa /var/db/pwd.db +The insecure password database file. +.It Pa /var/db/pwd.db.tmp +A temporary file. +.It Pa /var/db/spwd.db +The secure password database file. +.It Pa /var/db/spwd.db.tmp +A temporary file. +.It Pa /etc/master.passwd +The current password file. +.It Pa /etc/passwd +A Version 7 format password file. +.El +.Sh BUGS +Because of the necessity for atomic update of the password files, +.Nm pwd_mkdb +uses +.Xr rename 2 +to install them. +This, however, requires that the file specified on the command line live +on the same file system as the +.Dq Pa /etc +directory. +.Pp +There are the obvious races with multiple people running +.Nm pwd_mkdb +on different password files at the same time. +The front-ends to +.Nm pwd_mkdb , +.Xr chpass 1 , +.Xr passwd 1 +and +.Xr vipw 8 , +handle the locking necessary to avoid this problem. +.Sh COMPATIBILITY +Previous versions of the system had a program similar to +.Nm pwd_mkdb , +.Xr mkpasswd 8 , +which built +.Xr dbm 3 +style databases for the password file but depended on the calling programs +to install them. +The program was renamed in order that previous users of the program +not be surprised by the changes in functionality. +.Sh SEE ALSO +.Xr chpass 1 , +.Xr passwd 1 , +.Xr db 3 , +.Xr getpwent 3 , +.Xr passwd 5 , +.Xr vipw 8 diff --git a/usr.sbin/pwd_mkdb/pwd_mkdb.c b/usr.sbin/pwd_mkdb/pwd_mkdb.c new file mode 100644 index 0000000..7ccc91f --- /dev/null +++ b/usr.sbin/pwd_mkdb/pwd_mkdb.c @@ -0,0 +1,387 @@ +/*- + * Copyright (c) 1991, 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/stat.h> + +#include <db.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <pwd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "pw_scan.h" + +#define INSECURE 1 +#define SECURE 2 +#define PERM_INSECURE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) +#define PERM_SECURE (S_IRUSR|S_IWUSR) + +HASHINFO openinfo = { + 4096, /* bsize */ + 32, /* ffactor */ + 256, /* nelem */ + 2048 * 1024, /* cachesize */ + NULL, /* hash() */ + 0 /* lorder */ +}; + +static enum state { FILE_INSECURE, FILE_SECURE, FILE_ORIG } clean; +static struct passwd pwd; /* password structure */ +static char *pname; /* password file name */ + +void cleanup __P((void)); +void error __P((char *)); +void mv __P((char *, char *)); +int scan __P((FILE *, struct passwd *)); +void usage __P((void)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + DB *dp, *edp; + DBT data, key; + FILE *fp, *oldfp; + sigset_t set; + int ch, cnt, len, makeold, tfd; + char *p, *t; + char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024]; + + makeold = 0; + while ((ch = getopt(argc, argv, "pv")) != EOF) + switch(ch) { + case 'p': /* create V7 "file.orig" */ + makeold = 1; + break; + case 'v': /* backward compatible */ + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc != 1) + usage(); + + /* + * This could be changed to allow the user to interrupt. + * Probably not worth the effort. + */ + sigemptyset(&set); + sigaddset(&set, SIGTSTP); + sigaddset(&set, SIGHUP); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGQUIT); + sigaddset(&set, SIGTERM); + (void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL); + + /* We don't care what the user wants. */ + (void)umask(0); + + pname = *argv; + /* Open the original password file */ + if (!(fp = fopen(pname, "r"))) + error(pname); + + /* Open the temporary insecure password database. */ + (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_MP_DB); + dp = dbopen(buf, + O_RDWR|O_CREAT|O_EXCL, PERM_INSECURE, DB_HASH, &openinfo); + if (dp == NULL) + error(buf); + clean = FILE_INSECURE; + + /* + * Open file for old password file. Minor trickiness -- don't want to + * chance the file already existing, since someone (stupidly) might + * still be using this for permission checking. So, open it first and + * fdopen the resulting fd. The resulting file should be readable by + * everyone. + */ + if (makeold) { + (void)snprintf(buf, sizeof(buf), "%s.orig", pname); + if ((tfd = open(buf, + O_WRONLY|O_CREAT|O_EXCL, PERM_INSECURE)) < 0) + error(buf); + if ((oldfp = fdopen(tfd, "w")) == NULL) + error(buf); + clean = FILE_ORIG; + } + + /* + * The databases actually contain three copies of the original data. + * Each password file entry is converted into a rough approximation + * of a ``struct passwd'', with the strings placed inline. This + * object is then stored as the data for three separate keys. The + * first key * is the pw_name field prepended by the _PW_KEYBYNAME + * character. The second key is the pw_uid field prepended by the + * _PW_KEYBYUID character. The third key is the line number in the + * original file prepended by the _PW_KEYBYNUM character. (The special + * characters are prepended to ensure that the keys do not collide.) + */ + data.data = (u_char *)buf; + key.data = (u_char *)tbuf; + for (cnt = 1; scan(fp, &pwd); ++cnt) { +#define COMPACT(e) t = e; while (*p++ = *t++); + /* Create insecure data. */ + p = buf; + COMPACT(pwd.pw_name); + COMPACT("*"); + memmove(p, &pwd.pw_uid, sizeof(int)); + p += sizeof(int); + memmove(p, &pwd.pw_gid, sizeof(int)); + p += sizeof(int); + memmove(p, &pwd.pw_change, sizeof(time_t)); + p += sizeof(time_t); + COMPACT(pwd.pw_class); + COMPACT(pwd.pw_gecos); + COMPACT(pwd.pw_dir); + COMPACT(pwd.pw_shell); + memmove(p, &pwd.pw_expire, sizeof(time_t)); + p += sizeof(time_t); + data.size = p - buf; + + /* Store insecure by name. */ + tbuf[0] = _PW_KEYBYNAME; + len = strlen(pwd.pw_name); + memmove(tbuf + 1, pwd.pw_name, len); + key.size = len + 1; + if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1) + error("put"); + + /* Store insecure by number. */ + tbuf[0] = _PW_KEYBYNUM; + memmove(tbuf + 1, &cnt, sizeof(cnt)); + key.size = sizeof(cnt) + 1; + if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1) + error("put"); + + /* Store insecure by uid. */ + tbuf[0] = _PW_KEYBYUID; + memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid)); + key.size = sizeof(pwd.pw_uid) + 1; + if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1) + error("put"); + + /* Create original format password file entry */ + if (makeold) + (void)fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n", + pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos, + pwd.pw_dir, pwd.pw_shell); + } + (void)(dp->close)(dp); + if (makeold) { + (void)fflush(oldfp); + (void)fclose(oldfp); + } + + /* Open the temporary encrypted password database. */ + (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_SMP_DB); + edp = dbopen(buf, + O_RDWR|O_CREAT|O_EXCL, PERM_SECURE, DB_HASH, &openinfo); + if (!edp) + error(buf); + clean = FILE_SECURE; + + rewind(fp); + for (cnt = 1; scan(fp, &pwd); ++cnt) { + + /* Create secure data. */ + p = buf; + COMPACT(pwd.pw_name); + COMPACT(pwd.pw_passwd); + memmove(p, &pwd.pw_uid, sizeof(int)); + p += sizeof(int); + memmove(p, &pwd.pw_gid, sizeof(int)); + p += sizeof(int); + memmove(p, &pwd.pw_change, sizeof(time_t)); + p += sizeof(time_t); + COMPACT(pwd.pw_class); + COMPACT(pwd.pw_gecos); + COMPACT(pwd.pw_dir); + COMPACT(pwd.pw_shell); + memmove(p, &pwd.pw_expire, sizeof(time_t)); + p += sizeof(time_t); + data.size = p - buf; + + /* Store secure by name. */ + tbuf[0] = _PW_KEYBYNAME; + len = strlen(pwd.pw_name); + memmove(tbuf + 1, pwd.pw_name, len); + key.size = len + 1; + if ((dp->put)(edp, &key, &data, R_NOOVERWRITE) == -1) + error("put"); + + /* Store secure by number. */ + tbuf[0] = _PW_KEYBYNUM; + memmove(tbuf + 1, &cnt, sizeof(cnt)); + key.size = sizeof(cnt) + 1; + if ((dp->put)(edp, &key, &data, R_NOOVERWRITE) == -1) + error("put"); + + /* Store secure by uid. */ + tbuf[0] = _PW_KEYBYUID; + memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid)); + key.size = sizeof(pwd.pw_uid) + 1; + if ((dp->put)(edp, &key, &data, R_NOOVERWRITE) == -1) + error("put"); + } + + (void)(edp->close)(edp); + + /* Set master.passwd permissions, in case caller forgot. */ + (void)fchmod(fileno(fp), S_IRUSR|S_IWUSR); + (void)fclose(fp); + + /* Install as the real password files. */ + (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_MP_DB); + mv(buf, _PATH_MP_DB); + (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_SMP_DB); + mv(buf, _PATH_SMP_DB); + if (makeold) { + (void)snprintf(buf, sizeof(buf), "%s.orig", pname); + mv(buf, _PATH_PASSWD); + } + /* + * Move the master password LAST -- chpass(1), passwd(1) and vipw(8) + * all use flock(2) on it to block other incarnations of themselves. + * The rename means that everything is unlocked, as the original file + * can no longer be accessed. + */ + mv(pname, _PATH_MASTERPASSWD); + exit(0); +} + +int +scan(fp, pw) + FILE *fp; + struct passwd *pw; +{ + static int lcnt; + static char line[LINE_MAX]; + char *p; + + if (!fgets(line, sizeof(line), fp)) + return (0); + ++lcnt; + /* + * ``... if I swallow anything evil, put your fingers down my + * throat...'' + * -- The Who + */ + if (!(p = strchr(line, '\n'))) { + warnx("line too long"); + goto fmt; + + } + *p = '\0'; + if (!pw_scan(line, pw)) { + warnx("at line #%d", lcnt); +fmt: errno = EFTYPE; /* XXX */ + error(pname); + } + + return (1); +} + +void +mv(from, to) + char *from, *to; +{ + char buf[MAXPATHLEN]; + + if (rename(from, to)) { + int sverrno = errno; + (void)snprintf(buf, sizeof(buf), "%s to %s", from, to); + errno = sverrno; + error(buf); + } +} + +void +error(name) + char *name; +{ + + warn(name); + cleanup(); + exit(1); +} + +void +cleanup() +{ + char buf[MAXPATHLEN]; + + switch(clean) { + case FILE_ORIG: + (void)snprintf(buf, sizeof(buf), "%s.orig", pname); + (void)unlink(buf); + /* FALLTHROUGH */ + case FILE_SECURE: + (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_SMP_DB); + (void)unlink(buf); + /* FALLTHROUGH */ + case FILE_INSECURE: + (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_MP_DB); + (void)unlink(buf); + } +} + +void +usage() +{ + + (void)fprintf(stderr, "usage: pwd_mkdb [-p] file\n"); + exit(1); +} |