Home | History | Annotate | Line # | Download | only in pwd_mkdb
pwd_mkdb.c revision 1.17
      1  1.11     fair /*
      2   1.5  mycroft  * Copyright (c) 1991, 1993, 1994
      3   1.5  mycroft  *	The Regents of the University of California.  All rights reserved.
      4   1.6     phil  * Portions Copyright(C) 1994, Jason Downs.  All rights reserved.
      5   1.1      cgd  *
      6   1.1      cgd  * Redistribution and use in source and binary forms, with or without
      7   1.1      cgd  * modification, are permitted provided that the following conditions
      8   1.1      cgd  * are met:
      9   1.1      cgd  * 1. Redistributions of source code must retain the above copyright
     10   1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     11   1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     12   1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     13   1.1      cgd  *    documentation and/or other materials provided with the distribution.
     14   1.1      cgd  * 3. All advertising materials mentioning features or use of this software
     15   1.1      cgd  *    must display the following acknowledgement:
     16   1.1      cgd  *	This product includes software developed by the University of
     17   1.1      cgd  *	California, Berkeley and its contributors.
     18   1.1      cgd  * 4. Neither the name of the University nor the names of its contributors
     19   1.1      cgd  *    may be used to endorse or promote products derived from this software
     20   1.1      cgd  *    without specific prior written permission.
     21   1.1      cgd  *
     22   1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23   1.1      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24   1.1      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25   1.1      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26   1.1      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27   1.1      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28   1.1      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29   1.1      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30   1.1      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31   1.1      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32   1.1      cgd  * SUCH DAMAGE.
     33   1.1      cgd  */
     34   1.1      cgd 
     35  1.10    lukem #include <sys/cdefs.h>
     36   1.1      cgd #ifndef lint
     37  1.17  mycroft __COPYRIGHT("@(#) Copyright (c) 2000\n\
     38  1.17  mycroft 	The NetBSD Foundation, Inc.  All rights reserved.\n\
     39  1.17  mycroft Copyright (c) 1991, 1993, 1994\n\
     40  1.10    lukem 	The Regents of the University of California.  All rights reserved.\n");
     41  1.17  mycroft __SCCSID("from: @(#)pwd_mkdb.c	8.5 (Berkeley) 4/20/94");
     42  1.17  mycroft __RCSID("$NetBSD: pwd_mkdb.c,v 1.17 2000/01/23 19:59:33 mycroft Exp $");
     43   1.1      cgd #endif /* not lint */
     44   1.1      cgd 
     45   1.1      cgd #include <sys/param.h>
     46   1.1      cgd #include <sys/stat.h>
     47   1.5  mycroft 
     48   1.1      cgd #include <db.h>
     49   1.5  mycroft #include <err.h>
     50   1.1      cgd #include <errno.h>
     51   1.5  mycroft #include <fcntl.h>
     52   1.1      cgd #include <limits.h>
     53   1.5  mycroft #include <pwd.h>
     54   1.5  mycroft #include <signal.h>
     55   1.1      cgd #include <stdio.h>
     56   1.5  mycroft #include <stdlib.h>
     57   1.1      cgd #include <string.h>
     58   1.5  mycroft #include <unistd.h>
     59   1.7      jtc #include <util.h>
     60   1.1      cgd 
     61   1.1      cgd #define	INSECURE	1
     62   1.1      cgd #define	SECURE		2
     63   1.1      cgd #define	PERM_INSECURE	(S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
     64   1.1      cgd #define	PERM_SECURE	(S_IRUSR|S_IWUSR)
     65   1.1      cgd 
     66   1.6     phil /* pull this out of the C library. */
     67   1.6     phil extern const char __yp_token[];
     68   1.6     phil 
     69   1.5  mycroft HASHINFO openinfo = {
     70   1.5  mycroft 	4096,		/* bsize */
     71   1.5  mycroft 	32,		/* ffactor */
     72   1.5  mycroft 	256,		/* nelem */
     73   1.5  mycroft 	2048 * 1024,	/* cachesize */
     74   1.5  mycroft 	NULL,		/* hash() */
     75   1.5  mycroft 	0		/* lorder */
     76   1.5  mycroft };
     77   1.1      cgd 
     78   1.1      cgd static enum state { FILE_INSECURE, FILE_SECURE, FILE_ORIG } clean;
     79   1.1      cgd static struct passwd pwd;			/* password structure */
     80   1.1      cgd static char *pname;				/* password file name */
     81   1.8    lukem static char prefix[MAXPATHLEN];
     82  1.11     fair static char oldpwdfile[MAX(MAXPATHLEN, LINE_MAX * 2)];
     83  1.11     fair static char pwd_db_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)];
     84  1.11     fair static char pwd_Sdb_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)];
     85   1.1      cgd 
     86   1.5  mycroft void	cleanup __P((void));
     87   1.5  mycroft void	error __P((char *));
     88  1.11     fair void	wr_error __P((char *));
     89  1.10    lukem int	main __P((int, char **));
     90   1.5  mycroft void	mv __P((char *, char *));
     91  1.11     fair void	rm __P((char *));
     92  1.17  mycroft int	scan __P((FILE *, struct passwd *, u_int32_t *));
     93   1.5  mycroft void	usage __P((void));
     94   1.5  mycroft 
     95   1.5  mycroft int
     96   1.1      cgd main(argc, argv)
     97   1.1      cgd 	int argc;
     98   1.5  mycroft 	char *argv[];
     99   1.1      cgd {
    100   1.5  mycroft 	DB *dp, *edp;
    101   1.5  mycroft 	DBT data, key;
    102   1.1      cgd 	FILE *fp, *oldfp;
    103   1.1      cgd 	sigset_t set;
    104  1.17  mycroft 	int ch, len, makeold, tfd;
    105  1.17  mycroft 	u_int32_t x, cnt, flags;
    106  1.16  mycroft 	char *p;
    107  1.16  mycroft 	const char *t;
    108  1.11     fair 	char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024];
    109   1.6     phil 	int hasyp = 0;
    110   1.6     phil 	DBT ypdata, ypkey;
    111  1.17  mycroft 	int lorder = BYTE_ORDER;
    112   1.1      cgd 
    113  1.10    lukem 	oldfp = NULL;
    114   1.8    lukem 	strcpy(prefix, "/");
    115   1.1      cgd 	makeold = 0;
    116  1.17  mycroft 	while ((ch = getopt(argc, argv, "d:pvBL")) != -1)
    117   1.1      cgd 		switch(ch) {
    118   1.8    lukem 		case 'd':
    119   1.8    lukem 			strncpy(prefix, optarg, sizeof(prefix));
    120   1.8    lukem 			prefix[sizeof(prefix)-1] = '\0';
    121   1.8    lukem 			break;
    122   1.1      cgd 		case 'p':			/* create V7 "file.orig" */
    123   1.1      cgd 			makeold = 1;
    124   1.1      cgd 			break;
    125   1.1      cgd 		case 'v':			/* backward compatible */
    126   1.1      cgd 			break;
    127  1.17  mycroft 		case 'B':
    128  1.17  mycroft 			lorder = BIG_ENDIAN;
    129  1.17  mycroft 			break;
    130  1.17  mycroft 		case 'L':
    131  1.17  mycroft 			lorder = LITTLE_ENDIAN;
    132  1.17  mycroft 			break;
    133   1.1      cgd 		case '?':
    134   1.1      cgd 		default:
    135   1.1      cgd 			usage();
    136   1.1      cgd 		}
    137   1.1      cgd 	argc -= optind;
    138   1.1      cgd 	argv += optind;
    139   1.1      cgd 
    140   1.1      cgd 	if (argc != 1)
    141   1.1      cgd 		usage();
    142   1.4      cgd 
    143   1.1      cgd 	/*
    144   1.5  mycroft 	 * This could be changed to allow the user to interrupt.
    145   1.5  mycroft 	 * Probably not worth the effort.
    146   1.1      cgd 	 */
    147   1.1      cgd 	sigemptyset(&set);
    148   1.1      cgd 	sigaddset(&set, SIGTSTP);
    149   1.1      cgd 	sigaddset(&set, SIGHUP);
    150   1.1      cgd 	sigaddset(&set, SIGINT);
    151   1.1      cgd 	sigaddset(&set, SIGQUIT);
    152   1.1      cgd 	sigaddset(&set, SIGTERM);
    153   1.1      cgd 	(void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
    154   1.1      cgd 
    155   1.5  mycroft 	/* We don't care what the user wants. */
    156   1.5  mycroft 	(void)umask(0);
    157   1.5  mycroft 
    158   1.1      cgd 	pname = *argv;
    159   1.1      cgd 	/* Open the original password file */
    160   1.1      cgd 	if (!(fp = fopen(pname, "r")))
    161   1.1      cgd 		error(pname);
    162   1.1      cgd 
    163  1.17  mycroft 	openinfo.lorder = lorder;
    164  1.17  mycroft 
    165   1.1      cgd 	/* Open the temporary insecure password database. */
    166  1.11     fair 	(void)snprintf(pwd_db_tmp, sizeof(pwd_db_tmp), "%s%s.tmp", prefix,
    167  1.11     fair 		_PATH_MP_DB);
    168  1.11     fair 	dp = dbopen(pwd_db_tmp,
    169   1.5  mycroft 	    O_RDWR|O_CREAT|O_EXCL, PERM_INSECURE, DB_HASH, &openinfo);
    170   1.5  mycroft 	if (dp == NULL)
    171  1.11     fair 		error(pwd_db_tmp);
    172   1.1      cgd 	clean = FILE_INSECURE;
    173   1.1      cgd 
    174   1.1      cgd 	/*
    175   1.1      cgd 	 * Open file for old password file.  Minor trickiness -- don't want to
    176   1.1      cgd 	 * chance the file already existing, since someone (stupidly) might
    177   1.1      cgd 	 * still be using this for permission checking.  So, open it first and
    178   1.5  mycroft 	 * fdopen the resulting fd.  The resulting file should be readable by
    179   1.5  mycroft 	 * everyone.
    180   1.1      cgd 	 */
    181   1.1      cgd 	if (makeold) {
    182  1.11     fair 		(void)snprintf(oldpwdfile, sizeof(oldpwdfile), "%s.orig",
    183  1.11     fair 			pname);
    184  1.11     fair 		if ((tfd = open(oldpwdfile,
    185   1.1      cgd 		    O_WRONLY|O_CREAT|O_EXCL, PERM_INSECURE)) < 0)
    186  1.11     fair 			error(oldpwdfile);
    187   1.5  mycroft 		if ((oldfp = fdopen(tfd, "w")) == NULL)
    188  1.11     fair 			error(oldpwdfile);
    189   1.1      cgd 		clean = FILE_ORIG;
    190   1.1      cgd 	}
    191   1.1      cgd 
    192   1.1      cgd 	/*
    193   1.1      cgd 	 * The databases actually contain three copies of the original data.
    194   1.1      cgd 	 * Each password file entry is converted into a rough approximation
    195   1.1      cgd 	 * of a ``struct passwd'', with the strings placed inline.  This
    196   1.1      cgd 	 * object is then stored as the data for three separate keys.  The
    197   1.1      cgd 	 * first key * is the pw_name field prepended by the _PW_KEYBYNAME
    198   1.1      cgd 	 * character.  The second key is the pw_uid field prepended by the
    199   1.1      cgd 	 * _PW_KEYBYUID character.  The third key is the line number in the
    200   1.1      cgd 	 * original file prepended by the _PW_KEYBYNUM character.  (The special
    201   1.1      cgd 	 * characters are prepended to ensure that the keys do not collide.)
    202   1.6     phil 	 *
    203   1.6     phil 	 * If we see something go by that looks like YP, we save a special
    204   1.6     phil 	 * pointer record, which if YP is enabled in the C lib, will speed
    205   1.6     phil 	 * things up.
    206   1.1      cgd 	 */
    207   1.1      cgd 	data.data = (u_char *)buf;
    208   1.1      cgd 	key.data = (u_char *)tbuf;
    209   1.6     phil 	for (cnt = 1; scan(fp, &pwd, &flags); ++cnt) {
    210   1.8    lukem #define	COMPACT(e)	t = e; while ((*p++ = *t++));
    211   1.6     phil 
    212   1.6     phil 		/* look like YP? */
    213   1.6     phil 		if((pwd.pw_name[0] == '+') || (pwd.pw_name[0] == '-'))
    214   1.6     phil 			hasyp++;
    215   1.9  thorpej 
    216   1.9  thorpej 		/*
    217   1.9  thorpej 		 * Warn about potentially unsafe uid/gid overrides.
    218   1.9  thorpej 		 */
    219   1.9  thorpej 		if (pwd.pw_name[0] == '+') {
    220   1.9  thorpej 			if ((flags & _PASSWORD_NOUID) == 0 && pwd.pw_uid == 0)
    221  1.15    lukem 				warnx(
    222  1.15    lukem 				"line %d: superuser override in YP inclusion",
    223  1.15    lukem 				    cnt);
    224   1.9  thorpej 			if ((flags & _PASSWORD_NOGID) == 0 && pwd.pw_gid == 0)
    225  1.15    lukem 				warnx("line %d: wheel override in YP inclusion",
    226  1.15    lukem 				    cnt);
    227   1.9  thorpej 		}
    228   1.6     phil 
    229  1.17  mycroft 		if (lorder != BYTE_ORDER) {
    230  1.17  mycroft 			M_32_SWAP(pwd.pw_uid);
    231  1.17  mycroft 			M_32_SWAP(pwd.pw_gid);
    232  1.17  mycroft 			M_32_SWAP(pwd.pw_change);
    233  1.17  mycroft 			M_32_SWAP(pwd.pw_expire);
    234  1.17  mycroft 			M_32_SWAP(flags);
    235  1.17  mycroft 		}
    236  1.17  mycroft 
    237   1.1      cgd 		/* Create insecure data. */
    238   1.1      cgd 		p = buf;
    239   1.1      cgd 		COMPACT(pwd.pw_name);
    240   1.1      cgd 		COMPACT("*");
    241  1.17  mycroft 		memmove(p, &pwd.pw_uid, sizeof(pwd.pw_uid));
    242  1.17  mycroft 		p += sizeof(pwd.pw_uid);
    243  1.17  mycroft 		memmove(p, &pwd.pw_gid, sizeof(pwd.pw_gid));
    244  1.17  mycroft 		p += sizeof(pwd.pw_gid);
    245  1.17  mycroft 		memmove(p, &pwd.pw_change, sizeof(pwd.pw_change));
    246  1.17  mycroft 		p += sizeof(pwd.pw_change);
    247   1.1      cgd 		COMPACT(pwd.pw_class);
    248   1.1      cgd 		COMPACT(pwd.pw_gecos);
    249   1.1      cgd 		COMPACT(pwd.pw_dir);
    250   1.1      cgd 		COMPACT(pwd.pw_shell);
    251  1.17  mycroft 		memmove(p, &pwd.pw_expire, sizeof(pwd.pw_expire));
    252  1.17  mycroft 		p += sizeof(pwd.pw_expire);
    253  1.17  mycroft 		memmove(p, &flags, sizeof(flags));
    254  1.17  mycroft 		p += sizeof(flags);
    255   1.1      cgd 		data.size = p - buf;
    256   1.1      cgd 
    257   1.1      cgd 		/* Store insecure by name. */
    258   1.1      cgd 		tbuf[0] = _PW_KEYBYNAME;
    259   1.1      cgd 		len = strlen(pwd.pw_name);
    260   1.5  mycroft 		memmove(tbuf + 1, pwd.pw_name, len);
    261   1.1      cgd 		key.size = len + 1;
    262   1.1      cgd 		if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
    263  1.11     fair 			wr_error(pwd_db_tmp);
    264   1.1      cgd 
    265   1.1      cgd 		/* Store insecure by number. */
    266   1.1      cgd 		tbuf[0] = _PW_KEYBYNUM;
    267  1.17  mycroft 		x = cnt;
    268  1.17  mycroft 		if (lorder != BYTE_ORDER)
    269  1.17  mycroft 			M_32_SWAP(x);
    270  1.17  mycroft 		memmove(tbuf + 1, &x, sizeof(x));
    271  1.17  mycroft 		key.size = sizeof(x) + 1;
    272   1.1      cgd 		if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
    273  1.11     fair 			wr_error(pwd_db_tmp);
    274   1.1      cgd 
    275   1.1      cgd 		/* Store insecure by uid. */
    276   1.1      cgd 		tbuf[0] = _PW_KEYBYUID;
    277   1.5  mycroft 		memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
    278   1.1      cgd 		key.size = sizeof(pwd.pw_uid) + 1;
    279   1.1      cgd 		if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
    280  1.11     fair 			wr_error(pwd_db_tmp);
    281   1.1      cgd 
    282   1.5  mycroft 		/* Create original format password file entry */
    283  1.11     fair 		if (makeold) {
    284   1.5  mycroft 			(void)fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n",
    285   1.5  mycroft 			    pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos,
    286   1.5  mycroft 			    pwd.pw_dir, pwd.pw_shell);
    287  1.11     fair 			if (ferror(oldfp)) {
    288  1.11     fair 				wr_error(oldpwdfile);
    289  1.11     fair 			}
    290  1.11     fair 		}
    291   1.5  mycroft 	}
    292   1.6     phil 
    293   1.6     phil 	/* Store YP token, if needed. */
    294   1.6     phil 	if(hasyp) {
    295   1.6     phil 		ypkey.data = (u_char *)__yp_token;
    296   1.6     phil 		ypkey.size = strlen(__yp_token);
    297   1.6     phil 		ypdata.data = (u_char *)NULL;
    298   1.6     phil 		ypdata.size = 0;
    299   1.6     phil 
    300   1.6     phil 		if ((dp->put)(dp, &ypkey, &ypdata, R_NOOVERWRITE) == -1)
    301  1.11     fair 			wr_error(pwd_db_tmp);
    302   1.6     phil 	}
    303   1.6     phil 
    304  1.11     fair 	if ((dp->close)(dp) < 0) {
    305  1.11     fair 		wr_error(pwd_db_tmp);
    306  1.11     fair 	}
    307   1.5  mycroft 	if (makeold) {
    308  1.11     fair 		if (fflush(oldfp) == EOF) {
    309  1.11     fair 			wr_error(oldpwdfile);
    310  1.11     fair 		}
    311  1.11     fair 		if (fclose(oldfp) == EOF) {
    312  1.11     fair 			wr_error(oldpwdfile);
    313  1.11     fair 		}
    314   1.5  mycroft 	}
    315   1.5  mycroft 
    316   1.5  mycroft 	/* Open the temporary encrypted password database. */
    317  1.11     fair 	(void)snprintf(pwd_Sdb_tmp, sizeof(pwd_Sdb_tmp), "%s%s.tmp", prefix,
    318  1.11     fair 		_PATH_SMP_DB);
    319  1.11     fair 	edp = dbopen(pwd_Sdb_tmp,
    320   1.5  mycroft 	    O_RDWR|O_CREAT|O_EXCL, PERM_SECURE, DB_HASH, &openinfo);
    321   1.5  mycroft 	if (!edp)
    322  1.11     fair 		error(pwd_Sdb_tmp);
    323   1.5  mycroft 	clean = FILE_SECURE;
    324   1.5  mycroft 
    325   1.5  mycroft 	rewind(fp);
    326   1.6     phil 	for (cnt = 1; scan(fp, &pwd, &flags); ++cnt) {
    327   1.5  mycroft 
    328  1.17  mycroft 		if (lorder != BYTE_ORDER) {
    329  1.17  mycroft 			M_32_SWAP(pwd.pw_uid);
    330  1.17  mycroft 			M_32_SWAP(pwd.pw_gid);
    331  1.17  mycroft 			M_32_SWAP(pwd.pw_change);
    332  1.17  mycroft 			M_32_SWAP(pwd.pw_expire);
    333  1.17  mycroft 			M_32_SWAP(flags);
    334  1.17  mycroft 		}
    335  1.17  mycroft 
    336   1.1      cgd 		/* Create secure data. */
    337   1.1      cgd 		p = buf;
    338   1.1      cgd 		COMPACT(pwd.pw_name);
    339   1.1      cgd 		COMPACT(pwd.pw_passwd);
    340  1.17  mycroft 		memmove(p, &pwd.pw_uid, sizeof(pwd.pw_uid));
    341  1.17  mycroft 		p += sizeof(pwd.pw_uid);
    342  1.17  mycroft 		memmove(p, &pwd.pw_gid, sizeof(pwd.pw_gid));
    343  1.17  mycroft 		p += sizeof(pwd.pw_gid);
    344  1.17  mycroft 		memmove(p, &pwd.pw_change, sizeof(pwd.pw_change));
    345  1.17  mycroft 		p += sizeof(pwd.pw_change);
    346   1.1      cgd 		COMPACT(pwd.pw_class);
    347   1.1      cgd 		COMPACT(pwd.pw_gecos);
    348   1.1      cgd 		COMPACT(pwd.pw_dir);
    349   1.1      cgd 		COMPACT(pwd.pw_shell);
    350  1.17  mycroft 		memmove(p, &pwd.pw_expire, sizeof(pwd.pw_expire));
    351  1.17  mycroft 		p += sizeof(pwd.pw_expire);
    352  1.17  mycroft 		memmove(p, &flags, sizeof(flags));
    353  1.17  mycroft 		p += sizeof(flags);
    354   1.1      cgd 		data.size = p - buf;
    355   1.1      cgd 
    356   1.1      cgd 		/* Store secure by name. */
    357   1.1      cgd 		tbuf[0] = _PW_KEYBYNAME;
    358   1.1      cgd 		len = strlen(pwd.pw_name);
    359   1.5  mycroft 		memmove(tbuf + 1, pwd.pw_name, len);
    360   1.1      cgd 		key.size = len + 1;
    361  1.11     fair 		if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
    362  1.12     fair 			wr_error(pwd_Sdb_tmp);
    363   1.1      cgd 
    364   1.1      cgd 		/* Store secure by number. */
    365   1.1      cgd 		tbuf[0] = _PW_KEYBYNUM;
    366  1.17  mycroft 		x = cnt;
    367  1.17  mycroft 		if (lorder != BYTE_ORDER)
    368  1.17  mycroft 			M_32_SWAP(x);
    369  1.17  mycroft 		memmove(tbuf + 1, &x, sizeof(x));
    370  1.17  mycroft 		key.size = sizeof(x) + 1;
    371  1.11     fair 		if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
    372  1.12     fair 			wr_error(pwd_Sdb_tmp);
    373   1.1      cgd 
    374   1.1      cgd 		/* Store secure by uid. */
    375   1.1      cgd 		tbuf[0] = _PW_KEYBYUID;
    376   1.5  mycroft 		memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
    377   1.1      cgd 		key.size = sizeof(pwd.pw_uid) + 1;
    378  1.11     fair 		if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
    379  1.12     fair 			wr_error(pwd_Sdb_tmp);
    380   1.5  mycroft 	}
    381   1.1      cgd 
    382   1.6     phil 	/* Store YP token, if needed. */
    383   1.6     phil 	if(hasyp) {
    384   1.6     phil 		ypkey.data = (u_char *)__yp_token;
    385   1.6     phil 		ypkey.size = strlen(__yp_token);
    386   1.6     phil 		ypdata.data = (u_char *)NULL;
    387   1.6     phil 		ypdata.size = 0;
    388   1.6     phil 
    389  1.11     fair 		if((edp->put)(edp, &ypkey, &ypdata, R_NOOVERWRITE) == -1)
    390  1.12     fair 			wr_error(pwd_Sdb_tmp);
    391   1.6     phil 	}
    392   1.6     phil 
    393  1.11     fair 	if ((edp->close)(edp) < 0) {
    394  1.11     fair 		wr_error(_PATH_SMP_DB);
    395  1.11     fair 	}
    396   1.1      cgd 
    397   1.1      cgd 	/* Set master.passwd permissions, in case caller forgot. */
    398   1.1      cgd 	(void)fchmod(fileno(fp), S_IRUSR|S_IWUSR);
    399  1.11     fair 	if (fclose(fp) == EOF) {
    400  1.11     fair 		wr_error(pname);
    401  1.11     fair 	}
    402   1.1      cgd 
    403   1.1      cgd 	/* Install as the real password files. */
    404  1.11     fair 	{
    405  1.11     fair 		char	destination[MAXPATHLEN];
    406  1.11     fair 
    407  1.11     fair 		(void)snprintf(destination, sizeof(destination),
    408  1.11     fair 			"%s%s", prefix, _PATH_MP_DB);
    409  1.11     fair 		mv(pwd_db_tmp, destination);
    410  1.11     fair 
    411  1.11     fair 		(void)snprintf(destination, sizeof(destination),
    412  1.11     fair 			"%s%s", prefix, _PATH_SMP_DB);
    413  1.11     fair 		mv(pwd_Sdb_tmp, destination);
    414  1.11     fair 
    415  1.11     fair 		if (makeold) {
    416  1.11     fair 			(void)snprintf(destination, sizeof(destination),
    417  1.11     fair 				"%s%s", prefix, _PATH_PASSWD);
    418  1.11     fair 			mv(oldpwdfile, destination);
    419  1.11     fair 		}
    420  1.11     fair 
    421  1.11     fair 		/*
    422  1.11     fair 		 * Move the master password LAST -- chpass(1),
    423  1.11     fair 		 * passwd(1) and vipw(8) all use flock(2) on it to
    424  1.11     fair 		 * block other incarnations of themselves. The rename
    425  1.11     fair 		 * means that everything is unlocked, as the original
    426  1.11     fair 		 * file can no longer be accessed.
    427  1.11     fair 		 */
    428  1.11     fair 		(void)snprintf(destination, sizeof(destination),
    429  1.11     fair 			"%s%s", prefix, _PATH_MASTERPASSWD);
    430  1.11     fair 		mv(pname, destination);
    431   1.1      cgd 	}
    432   1.1      cgd 	exit(0);
    433   1.1      cgd }
    434   1.1      cgd 
    435   1.5  mycroft int
    436   1.6     phil scan(fp, pw, flags)
    437   1.1      cgd 	FILE *fp;
    438   1.1      cgd 	struct passwd *pw;
    439  1.17  mycroft 	u_int32_t *flags;
    440   1.1      cgd {
    441   1.1      cgd 	static int lcnt;
    442   1.1      cgd 	static char line[LINE_MAX];
    443   1.1      cgd 	char *p;
    444  1.17  mycroft 	int oflags;
    445   1.1      cgd 
    446   1.1      cgd 	if (!fgets(line, sizeof(line), fp))
    447   1.5  mycroft 		return (0);
    448   1.1      cgd 	++lcnt;
    449   1.1      cgd 	/*
    450   1.1      cgd 	 * ``... if I swallow anything evil, put your fingers down my
    451   1.1      cgd 	 * throat...''
    452   1.1      cgd 	 *	-- The Who
    453   1.1      cgd 	 */
    454   1.5  mycroft 	if (!(p = strchr(line, '\n'))) {
    455   1.5  mycroft 		warnx("line too long");
    456   1.1      cgd 		goto fmt;
    457   1.1      cgd 
    458   1.1      cgd 	}
    459   1.1      cgd 	*p = '\0';
    460  1.15    lukem 	if (strcmp(line, "+") == 0)
    461  1.15    lukem 		strcpy(line, "+:::::::::");	/* pw_scan() can't handle "+" */
    462  1.17  mycroft 	oflags = 0;
    463  1.17  mycroft 	if (!pw_scan(line, pw, &oflags)) {
    464   1.5  mycroft 		warnx("at line #%d", lcnt);
    465   1.5  mycroft fmt:		errno = EFTYPE;	/* XXX */
    466   1.1      cgd 		error(pname);
    467   1.1      cgd 	}
    468  1.17  mycroft 	*flags = oflags;
    469   1.5  mycroft 
    470   1.5  mycroft 	return (1);
    471   1.1      cgd }
    472   1.1      cgd 
    473   1.5  mycroft void
    474   1.1      cgd mv(from, to)
    475   1.1      cgd 	char *from, *to;
    476   1.1      cgd {
    477   1.1      cgd 	char buf[MAXPATHLEN];
    478   1.1      cgd 
    479   1.1      cgd 	if (rename(from, to)) {
    480   1.5  mycroft 		int sverrno = errno;
    481   1.5  mycroft 		(void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
    482   1.1      cgd 		errno = sverrno;
    483   1.1      cgd 		error(buf);
    484   1.1      cgd 	}
    485   1.1      cgd }
    486   1.1      cgd 
    487   1.5  mycroft void
    488  1.11     fair wr_error(name)
    489  1.11     fair 	char *name;
    490  1.11     fair {
    491  1.11     fair 	char	errbuf[BUFSIZ];
    492  1.11     fair 	int	sverrno = errno;
    493  1.11     fair 
    494  1.11     fair 	(void)snprintf(errbuf, sizeof(errbuf),
    495  1.11     fair 		"attempt to write %s failed", name);
    496  1.11     fair 
    497  1.11     fair 	errno = sverrno;
    498  1.11     fair 	error(errbuf);
    499  1.11     fair }
    500  1.11     fair 
    501  1.11     fair void
    502   1.1      cgd error(name)
    503   1.1      cgd 	char *name;
    504   1.1      cgd {
    505   1.5  mycroft 
    506   1.5  mycroft 	warn(name);
    507   1.1      cgd 	cleanup();
    508  1.11     fair #ifdef think_about_this_a_while_longer
    509  1.11     fair 	fputs("NOTE: possible inconsistencies between text files and databases\n", stderr);
    510  1.11     fair 	fputs("re-run pwd_mkdb when you have fixed the problem.\n", stderr);
    511  1.11     fair #endif
    512   1.1      cgd 	exit(1);
    513   1.1      cgd }
    514   1.1      cgd 
    515   1.5  mycroft void
    516  1.11     fair rm(victim)
    517  1.11     fair 	char *victim;
    518  1.11     fair {
    519  1.11     fair 	if (unlink(victim) < 0) {
    520  1.11     fair 		warn("unlink(%s)", victim);
    521  1.11     fair 	}
    522  1.11     fair }
    523  1.11     fair 
    524  1.11     fair void
    525   1.1      cgd cleanup()
    526   1.1      cgd {
    527   1.1      cgd 	switch(clean) {
    528   1.1      cgd 	case FILE_ORIG:
    529  1.11     fair 		rm(oldpwdfile);
    530   1.1      cgd 		/* FALLTHROUGH */
    531   1.1      cgd 	case FILE_SECURE:
    532  1.11     fair 		rm(pwd_Sdb_tmp);
    533   1.1      cgd 		/* FALLTHROUGH */
    534   1.1      cgd 	case FILE_INSECURE:
    535  1.11     fair 		rm(pwd_db_tmp);
    536   1.1      cgd 	}
    537   1.1      cgd }
    538   1.1      cgd 
    539   1.5  mycroft void
    540   1.1      cgd usage()
    541   1.1      cgd {
    542   1.5  mycroft 
    543  1.17  mycroft 	(void)fprintf(stderr, "usage: pwd_mkdb [-pBL] [-d directory] file\n");
    544   1.1      cgd 	exit(1);
    545   1.1      cgd }
    546