Home | History | Annotate | Line # | Download | only in pwd_mkdb
pwd_mkdb.c revision 1.34.6.2
      1  1.34.6.2  christos /*	$NetBSD: pwd_mkdb.c,v 1.34.6.2 2008/12/28 01:21:23 christos Exp $	*/
      2  1.34.6.2  christos 
      3  1.34.6.2  christos /*
      4  1.34.6.2  christos  * Copyright (c) 1991, 1993, 1994
      5  1.34.6.2  christos  *	The Regents of the University of California.  All rights reserved.
      6  1.34.6.2  christos  *
      7  1.34.6.2  christos  * Redistribution and use in source and binary forms, with or without
      8  1.34.6.2  christos  * modification, are permitted provided that the following conditions
      9  1.34.6.2  christos  * are met:
     10  1.34.6.2  christos  * 1. Redistributions of source code must retain the above copyright
     11  1.34.6.2  christos  *    notice, this list of conditions and the following disclaimer.
     12  1.34.6.2  christos  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.34.6.2  christos  *    notice, this list of conditions and the following disclaimer in the
     14  1.34.6.2  christos  *    documentation and/or other materials provided with the distribution.
     15  1.34.6.2  christos  * 3. Neither the name of the University nor the names of its contributors
     16  1.34.6.2  christos  *    may be used to endorse or promote products derived from this software
     17  1.34.6.2  christos  *    without specific prior written permission.
     18  1.34.6.2  christos  *
     19  1.34.6.2  christos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  1.34.6.2  christos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  1.34.6.2  christos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  1.34.6.2  christos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  1.34.6.2  christos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  1.34.6.2  christos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  1.34.6.2  christos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  1.34.6.2  christos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  1.34.6.2  christos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  1.34.6.2  christos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  1.34.6.2  christos  * SUCH DAMAGE.
     30  1.34.6.2  christos  */
     31  1.34.6.2  christos 
     32  1.34.6.2  christos /*
     33  1.34.6.2  christos  * Portions Copyright(C) 1994, Jason Downs.  All rights reserved.
     34  1.34.6.2  christos  *
     35  1.34.6.2  christos  * Redistribution and use in source and binary forms, with or without
     36  1.34.6.2  christos  * modification, are permitted provided that the following conditions
     37  1.34.6.2  christos  * are met:
     38  1.34.6.2  christos  * 1. Redistributions of source code must retain the above copyright
     39  1.34.6.2  christos  *    notice, this list of conditions and the following disclaimer.
     40  1.34.6.2  christos  * 2. Redistributions in binary form must reproduce the above copyright
     41  1.34.6.2  christos  *    notice, this list of conditions and the following disclaimer in the
     42  1.34.6.2  christos  *    documentation and/or other materials provided with the distribution.
     43  1.34.6.2  christos  *
     44  1.34.6.2  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
     45  1.34.6.2  christos  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     46  1.34.6.2  christos  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     47  1.34.6.2  christos  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
     48  1.34.6.2  christos  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     49  1.34.6.2  christos  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     50  1.34.6.2  christos  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     51  1.34.6.2  christos  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     52  1.34.6.2  christos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     53  1.34.6.2  christos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     54  1.34.6.2  christos  * SUCH DAMAGE.
     55  1.34.6.2  christos  */
     56  1.34.6.2  christos 
     57  1.34.6.2  christos #if HAVE_NBTOOL_CONFIG_H
     58  1.34.6.2  christos #include "nbtool_config.h"
     59  1.34.6.2  christos #endif
     60  1.34.6.2  christos 
     61  1.34.6.2  christos #include <sys/cdefs.h>
     62  1.34.6.2  christos #if !defined(lint)
     63  1.34.6.2  christos __COPYRIGHT("@(#) Copyright (c) 2000\
     64  1.34.6.2  christos  The NetBSD Foundation, Inc.  All rights reserved.\
     65  1.34.6.2  christos   Copyright (c) 1991, 1993, 1994\
     66  1.34.6.2  christos  The Regents of the University of California.  All rights reserved.");
     67  1.34.6.2  christos __SCCSID("from: @(#)pwd_mkdb.c	8.5 (Berkeley) 4/20/94");
     68  1.34.6.2  christos __RCSID("$NetBSD: pwd_mkdb.c,v 1.34.6.2 2008/12/28 01:21:23 christos Exp $");
     69  1.34.6.2  christos #endif /* not lint */
     70  1.34.6.2  christos 
     71  1.34.6.2  christos #if HAVE_NBTOOL_CONFIG_H
     72  1.34.6.2  christos #include "compat_pwd.h"
     73  1.34.6.2  christos #else
     74  1.34.6.2  christos #include <pwd.h>
     75  1.34.6.2  christos #endif
     76  1.34.6.2  christos 
     77  1.34.6.2  christos #include <sys/param.h>
     78  1.34.6.2  christos #include <sys/stat.h>
     79  1.34.6.2  christos 
     80  1.34.6.2  christos #include <db.h>
     81  1.34.6.2  christos #include <err.h>
     82  1.34.6.2  christos #include <errno.h>
     83  1.34.6.2  christos #include <fcntl.h>
     84  1.34.6.2  christos #include <limits.h>
     85  1.34.6.2  christos #include <signal.h>
     86  1.34.6.2  christos #include <stdio.h>
     87  1.34.6.2  christos #include <stdlib.h>
     88  1.34.6.2  christos #include <string.h>
     89  1.34.6.2  christos #include <unistd.h>
     90  1.34.6.2  christos #include <util.h>
     91  1.34.6.2  christos 
     92  1.34.6.2  christos #define	MAX_CACHESIZE	8*1024*1024
     93  1.34.6.2  christos #define	MIN_CACHESIZE	2*1024*1024
     94  1.34.6.2  christos 
     95  1.34.6.2  christos #define	PERM_INSECURE	(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
     96  1.34.6.2  christos #define	PERM_SECURE	(S_IRUSR | S_IWUSR)
     97  1.34.6.2  christos 
     98  1.34.6.2  christos #if HAVE_NBTOOL_CONFIG_H
     99  1.34.6.2  christos static const char __yp_token[] = "__YP!";
    100  1.34.6.2  christos #else
    101  1.34.6.2  christos /* Pull this out of the C library. */
    102  1.34.6.2  christos extern const char __yp_token[];
    103  1.34.6.2  christos #endif
    104  1.34.6.2  christos 
    105  1.34.6.2  christos HASHINFO openinfo = {
    106  1.34.6.2  christos 	4096,		/* bsize */
    107  1.34.6.2  christos 	32,		/* ffactor */
    108  1.34.6.2  christos 	256,		/* nelem */
    109  1.34.6.2  christos 	0,		/* cachesize */
    110  1.34.6.2  christos 	NULL,		/* hash() */
    111  1.34.6.2  christos 	0		/* lorder */
    112  1.34.6.2  christos };
    113  1.34.6.2  christos 
    114  1.34.6.2  christos #define	FILE_INSECURE	0x01
    115  1.34.6.2  christos #define	FILE_SECURE	0x02
    116  1.34.6.2  christos #define	FILE_ORIG	0x04
    117  1.34.6.2  christos 
    118  1.34.6.2  christos static char	*pname;				/* password file name */
    119  1.34.6.2  christos static char	prefix[MAXPATHLEN];
    120  1.34.6.2  christos static char	oldpwdfile[MAX(MAXPATHLEN, LINE_MAX * 2)];
    121  1.34.6.2  christos static char	pwd_db_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)];
    122  1.34.6.2  christos static char	pwd_Sdb_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)];
    123  1.34.6.2  christos static int 	lorder = BYTE_ORDER;
    124  1.34.6.2  christos static int	clean;
    125  1.34.6.2  christos 
    126  1.34.6.2  christos void	bailout(void);
    127  1.34.6.2  christos void	cp(const char *, const char *, mode_t);
    128  1.34.6.2  christos int	deldbent(DB *, const char *, int, void *);
    129  1.34.6.2  christos void	error(const char *);
    130  1.34.6.2  christos int	getdbent(DB *, const char *, int, void *, struct passwd **);
    131  1.34.6.2  christos void	inconsistancy(void);
    132  1.34.6.2  christos void	install(const char *, const char *);
    133  1.34.6.2  christos int	main(int, char **);
    134  1.34.6.2  christos void	putdbents(DB *, struct passwd *, const char *, int, const char *, int,
    135  1.34.6.2  christos 		  int, int);
    136  1.34.6.2  christos void	putyptoken(DB *, const char *);
    137  1.34.6.2  christos void	rm(const char *);
    138  1.34.6.2  christos int	scan(FILE *, struct passwd *, int *, int *);
    139  1.34.6.2  christos void	usage(void);
    140  1.34.6.2  christos void	wr_error(const char *);
    141  1.34.6.2  christos void	setversion(DB *);
    142  1.34.6.2  christos 
    143  1.34.6.2  christos static __inline uint16_t swap16(uint16_t sw)
    144  1.34.6.2  christos {
    145  1.34.6.2  christos 	return ((sw & 0x00ff) << 8) |
    146  1.34.6.2  christos 	       ((sw & 0xff00) >> 8);
    147  1.34.6.2  christos }
    148  1.34.6.2  christos 
    149  1.34.6.2  christos static __inline uint32_t swap32(uint32_t sw) {
    150  1.34.6.2  christos 	return ((sw & 0x000000ff) << 24) |
    151  1.34.6.2  christos 	       ((sw & 0x0000ff00) << 8) |
    152  1.34.6.2  christos 	       ((sw & 0x00ff0000) >> 8) |
    153  1.34.6.2  christos 	       ((sw & 0xff000000) >> 24);
    154  1.34.6.2  christos }
    155  1.34.6.2  christos 
    156  1.34.6.2  christos static __inline uint64_t swap64(uint64_t sw) {
    157  1.34.6.2  christos 	return ((sw & 0x00000000000000ffULL) << 56) |
    158  1.34.6.2  christos 	       ((sw & 0x000000000000ff00ULL) << 40) |
    159  1.34.6.2  christos 	       ((sw & 0x0000000000ff0000ULL) >> 24) |
    160  1.34.6.2  christos 	       ((sw & 0x00000000ff000000ULL) << 8) |
    161  1.34.6.2  christos 	       ((sw & 0x000000ff00000000ULL) >> 8) |
    162  1.34.6.2  christos 	       ((sw & 0x0000ff0000000000ULL) >> 24) |
    163  1.34.6.2  christos 	       ((sw & 0x00ff000000000000ULL) >> 40) |
    164  1.34.6.2  christos 	       ((sw & 0xff00000000000000ULL) >> 56);
    165  1.34.6.2  christos }
    166  1.34.6.2  christos 
    167  1.34.6.2  christos #define SWAP(sw) \
    168  1.34.6.2  christos     ((sizeof(sw) == 2 ? (typeof(sw))swap16((uint16_t)sw) : \
    169  1.34.6.2  christos     (sizeof(sw) == 4 ? (typeof(sw))swap32((uint32_t)sw) : \
    170  1.34.6.2  christos     (sizeof(sw) == 8 ? (typeof(sw))swap64((uint64_t)sw) : abort(), 0))))
    171  1.34.6.2  christos 
    172  1.34.6.2  christos int
    173  1.34.6.2  christos main(int argc, char *argv[])
    174  1.34.6.2  christos {
    175  1.34.6.2  christos 	int ch, makeold, tfd, lineno, found, rv, hasyp, secureonly;
    176  1.34.6.2  christos 	struct passwd pwd, *tpwd;
    177  1.34.6.2  christos 	char *username;
    178  1.34.6.2  christos 	DB *dp, *edp;
    179  1.34.6.2  christos 	FILE *fp, *oldfp;
    180  1.34.6.2  christos 	sigset_t set;
    181  1.34.6.2  christos 	int dbflg, uid_dbflg, newuser, olduid, flags;
    182  1.34.6.2  christos 	char buf[MAXPATHLEN];
    183  1.34.6.2  christos 	struct stat st;
    184  1.34.6.2  christos 	u_int cachesize;
    185  1.34.6.2  christos 
    186  1.34.6.2  christos 	prefix[0] = '\0';
    187  1.34.6.2  christos 	makeold = 0;
    188  1.34.6.2  christos 	oldfp = NULL;
    189  1.34.6.2  christos 	username = NULL;
    190  1.34.6.2  christos 	hasyp = 0;
    191  1.34.6.2  christos 	secureonly = 0;
    192  1.34.6.2  christos 	found = 0;
    193  1.34.6.2  christos 	newuser = 0;
    194  1.34.6.2  christos 	dp = NULL;
    195  1.34.6.2  christos 	cachesize = 0;
    196  1.34.6.2  christos 
    197  1.34.6.2  christos 	while ((ch = getopt(argc, argv, "BLc:d:psu:v")) != -1)
    198  1.34.6.2  christos 		switch (ch) {
    199  1.34.6.2  christos 		case 'B':			/* big-endian output */
    200  1.34.6.2  christos 			lorder = BIG_ENDIAN;
    201  1.34.6.2  christos 			break;
    202  1.34.6.2  christos 		case 'L':			/* little-endian output */
    203  1.34.6.2  christos 			lorder = LITTLE_ENDIAN;
    204  1.34.6.2  christos 			break;
    205  1.34.6.2  christos 		case 'c':
    206  1.34.6.2  christos 			cachesize = atoi(optarg) * 1024 * 1024;
    207  1.34.6.2  christos 			break;
    208  1.34.6.2  christos 		case 'd':			/* set prefix */
    209  1.34.6.2  christos 			strlcpy(prefix, optarg, sizeof(prefix));
    210  1.34.6.2  christos 			break;
    211  1.34.6.2  christos 		case 'p':			/* create V7 "file.orig" */
    212  1.34.6.2  christos 			makeold = 1;
    213  1.34.6.2  christos 			break;
    214  1.34.6.2  christos 		case 's':			/* modify secure db only */
    215  1.34.6.2  christos 			secureonly = 1;
    216  1.34.6.2  christos 			break;
    217  1.34.6.2  christos 		case 'u':			/* modify one user only */
    218  1.34.6.2  christos 			username = optarg;
    219  1.34.6.2  christos 			break;
    220  1.34.6.2  christos 		case 'v':			/* backward compatible */
    221  1.34.6.2  christos 			break;
    222  1.34.6.2  christos 		case '?':
    223  1.34.6.2  christos 		default:
    224  1.34.6.2  christos 			usage();
    225  1.34.6.2  christos 		}
    226  1.34.6.2  christos 	argc -= optind;
    227  1.34.6.2  christos 	argv += optind;
    228  1.34.6.2  christos 
    229  1.34.6.2  christos 	if (argc != 1)
    230  1.34.6.2  christos 		usage();
    231  1.34.6.2  christos 	if (username != NULL)
    232  1.34.6.2  christos 		if (username[0] == '+' || username[0] == '-')
    233  1.34.6.2  christos 			usage();
    234  1.34.6.2  christos 	if (secureonly)
    235  1.34.6.2  christos 		makeold = 0;
    236  1.34.6.2  christos 
    237  1.34.6.2  christos 	/*
    238  1.34.6.2  christos 	 * This could be changed to allow the user to interrupt.
    239  1.34.6.2  christos 	 * Probably not worth the effort.
    240  1.34.6.2  christos 	 */
    241  1.34.6.2  christos 	sigemptyset(&set);
    242  1.34.6.2  christos 	sigaddset(&set, SIGTSTP);
    243  1.34.6.2  christos 	sigaddset(&set, SIGHUP);
    244  1.34.6.2  christos 	sigaddset(&set, SIGINT);
    245  1.34.6.2  christos 	sigaddset(&set, SIGQUIT);
    246  1.34.6.2  christos 	sigaddset(&set, SIGTERM);
    247  1.34.6.2  christos 	(void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
    248  1.34.6.2  christos 
    249  1.34.6.2  christos 	/* We don't care what the user wants. */
    250  1.34.6.2  christos 	(void)umask(0);
    251  1.34.6.2  christos 
    252  1.34.6.2  christos 	if (username == NULL)
    253  1.34.6.2  christos 		flags = O_RDWR | O_CREAT | O_EXCL;
    254  1.34.6.2  christos 	else
    255  1.34.6.2  christos 		flags = O_RDWR;
    256  1.34.6.2  christos 
    257  1.34.6.2  christos 	pname = *argv;
    258  1.34.6.2  christos 	/* Open the original password file */
    259  1.34.6.2  christos 	if ((fp = fopen(pname, "r")) == NULL)
    260  1.34.6.2  christos 		error(pname);
    261  1.34.6.2  christos 
    262  1.34.6.2  christos 	openinfo.lorder = lorder;
    263  1.34.6.2  christos 
    264  1.34.6.2  christos 	if (fstat(fileno(fp), &st) == -1)
    265  1.34.6.2  christos 		error(pname);
    266  1.34.6.2  christos 
    267  1.34.6.2  christos 	if (cachesize) {
    268  1.34.6.2  christos 		openinfo.cachesize = cachesize;
    269  1.34.6.2  christos 	} else {
    270  1.34.6.2  christos 		/* Tweak openinfo values for large passwd files. */
    271  1.34.6.2  christos 		cachesize = st.st_size * 20;
    272  1.34.6.2  christos 		if (cachesize > MAX_CACHESIZE)
    273  1.34.6.2  christos 			cachesize = MAX_CACHESIZE;
    274  1.34.6.2  christos 		else if (cachesize < MIN_CACHESIZE)
    275  1.34.6.2  christos 			cachesize = MIN_CACHESIZE;
    276  1.34.6.2  christos 		openinfo.cachesize = cachesize;
    277  1.34.6.2  christos 	}
    278  1.34.6.2  christos 
    279  1.34.6.2  christos 	/* Open the temporary insecure password database. */
    280  1.34.6.2  christos 	if (!secureonly) {
    281  1.34.6.2  christos 		(void)snprintf(pwd_db_tmp, sizeof(pwd_db_tmp), "%s%s.tmp",
    282  1.34.6.2  christos 		    prefix, _PATH_MP_DB);
    283  1.34.6.2  christos 		if (username != NULL) {
    284  1.34.6.2  christos 			snprintf(buf, sizeof(buf), "%s" _PATH_MP_DB, prefix);
    285  1.34.6.2  christos 			cp(buf, pwd_db_tmp, PERM_INSECURE);
    286  1.34.6.2  christos 		}
    287  1.34.6.2  christos 		dp = dbopen(pwd_db_tmp, flags, PERM_INSECURE, DB_HASH,
    288  1.34.6.2  christos 		    &openinfo);
    289  1.34.6.2  christos 		if (dp == NULL)
    290  1.34.6.2  christos 			error(pwd_db_tmp);
    291  1.34.6.2  christos 		setversion(dp);
    292  1.34.6.2  christos 		clean |= FILE_INSECURE;
    293  1.34.6.2  christos 	}
    294  1.34.6.2  christos 
    295  1.34.6.2  christos 	/* Open the temporary encrypted password database. */
    296  1.34.6.2  christos 	(void)snprintf(pwd_Sdb_tmp, sizeof(pwd_Sdb_tmp), "%s%s.tmp", prefix,
    297  1.34.6.2  christos 		_PATH_SMP_DB);
    298  1.34.6.2  christos 	if (username != NULL) {
    299  1.34.6.2  christos 		snprintf(buf, sizeof(buf), "%s" _PATH_SMP_DB, prefix);
    300  1.34.6.2  christos 		cp(buf, pwd_Sdb_tmp, PERM_SECURE);
    301  1.34.6.2  christos 	}
    302  1.34.6.2  christos 	edp = dbopen(pwd_Sdb_tmp, flags, PERM_SECURE, DB_HASH, &openinfo);
    303  1.34.6.2  christos 	if (!edp)
    304  1.34.6.2  christos 		error(pwd_Sdb_tmp);
    305  1.34.6.2  christos 	setversion(edp);
    306  1.34.6.2  christos 	clean |= FILE_SECURE;
    307  1.34.6.2  christos 
    308  1.34.6.2  christos 	/*
    309  1.34.6.2  christos 	 * Open file for old password file.  Minor trickiness -- don't want to
    310  1.34.6.2  christos 	 * chance the file already existing, since someone (stupidly) might
    311  1.34.6.2  christos 	 * still be using this for permission checking.  So, open it first and
    312  1.34.6.2  christos 	 * fdopen the resulting fd.  The resulting file should be readable by
    313  1.34.6.2  christos 	 * everyone.
    314  1.34.6.2  christos 	 */
    315  1.34.6.2  christos 	if (makeold) {
    316  1.34.6.2  christos 		(void)snprintf(oldpwdfile, sizeof(oldpwdfile), "%s.orig",
    317  1.34.6.2  christos 		    pname);
    318  1.34.6.2  christos 		if ((tfd = open(oldpwdfile, O_WRONLY | O_CREAT | O_EXCL,
    319  1.34.6.2  christos 		    PERM_INSECURE)) < 0)
    320  1.34.6.2  christos 			error(oldpwdfile);
    321  1.34.6.2  christos 		clean |= FILE_ORIG;
    322  1.34.6.2  christos 		if ((oldfp = fdopen(tfd, "w")) == NULL)
    323  1.34.6.2  christos 			error(oldpwdfile);
    324  1.34.6.2  christos 	}
    325  1.34.6.2  christos 
    326  1.34.6.2  christos 	if (username != NULL) {
    327  1.34.6.2  christos 		uid_dbflg = 0;
    328  1.34.6.2  christos 		dbflg = 0;
    329  1.34.6.2  christos 
    330  1.34.6.2  christos 		/*
    331  1.34.6.2  christos 		 * Determine if this is a new entry.
    332  1.34.6.2  christos 		 */
    333  1.34.6.2  christos 		if (getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYNAME, username, &tpwd))
    334  1.34.6.2  christos 			newuser = 1;
    335  1.34.6.2  christos 		else {
    336  1.34.6.2  christos 			newuser = 0;
    337  1.34.6.2  christos 			olduid = tpwd->pw_uid;
    338  1.34.6.2  christos 		}
    339  1.34.6.2  christos 
    340  1.34.6.2  christos 	} else {
    341  1.34.6.2  christos 		uid_dbflg = R_NOOVERWRITE;
    342  1.34.6.2  christos 		dbflg = R_NOOVERWRITE;
    343  1.34.6.2  christos 	}
    344  1.34.6.2  christos 
    345  1.34.6.2  christos 	/*
    346  1.34.6.2  christos 	 * If we see something go by that looks like YP, we save a special
    347  1.34.6.2  christos 	 * pointer record, which if YP is enabled in the C lib, will speed
    348  1.34.6.2  christos 	 * things up.
    349  1.34.6.2  christos 	 */
    350  1.34.6.2  christos 	for (lineno = 0; scan(fp, &pwd, &flags, &lineno);) {
    351  1.34.6.2  christos 		/*
    352  1.34.6.2  christos 		 * Create original format password file entry.
    353  1.34.6.2  christos 		 */
    354  1.34.6.2  christos 		if (makeold) {
    355  1.34.6.2  christos 			(void)fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n",
    356  1.34.6.2  christos 			    pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos,
    357  1.34.6.2  christos 			    pwd.pw_dir, pwd.pw_shell);
    358  1.34.6.2  christos 			if (ferror(oldfp))
    359  1.34.6.2  christos 				wr_error(oldpwdfile);
    360  1.34.6.2  christos 		}
    361  1.34.6.2  christos 
    362  1.34.6.2  christos 		if (username == NULL) {
    363  1.34.6.2  christos 			/* Look like YP? */
    364  1.34.6.2  christos 			if (pwd.pw_name[0] == '+' || pwd.pw_name[0] == '-')
    365  1.34.6.2  christos 				hasyp++;
    366  1.34.6.2  christos 
    367  1.34.6.2  christos 			/* Warn about potentially unsafe uid/gid overrides. */
    368  1.34.6.2  christos 			if (pwd.pw_name[0] == '+') {
    369  1.34.6.2  christos 				if ((flags & _PASSWORD_NOUID) == 0 &&
    370  1.34.6.2  christos 				    pwd.pw_uid == 0)
    371  1.34.6.2  christos 					warnx("line %d: superuser override "
    372  1.34.6.2  christos 					    "in YP inclusion", lineno);
    373  1.34.6.2  christos 				if ((flags & _PASSWORD_NOGID) == 0 &&
    374  1.34.6.2  christos 				    pwd.pw_gid == 0)
    375  1.34.6.2  christos 					warnx("line %d: wheel override "
    376  1.34.6.2  christos 					    "in YP inclusion", lineno);
    377  1.34.6.2  christos 			}
    378  1.34.6.2  christos 
    379  1.34.6.2  christos 			/* Write the database entry out. */
    380  1.34.6.2  christos 			if (!secureonly)
    381  1.34.6.2  christos 				putdbents(dp, &pwd, "*", flags, pwd_db_tmp,
    382  1.34.6.2  christos 				    lineno, dbflg, uid_dbflg);
    383  1.34.6.2  christos 			continue;
    384  1.34.6.2  christos 		} else if (strcmp(username, pwd.pw_name) != 0)
    385  1.34.6.2  christos 			continue;
    386  1.34.6.2  christos 
    387  1.34.6.2  christos 		if (found) {
    388  1.34.6.2  christos 			warnx("user `%s' listed twice in password file",
    389  1.34.6.2  christos 			    username);
    390  1.34.6.2  christos 			bailout();
    391  1.34.6.2  christos 		}
    392  1.34.6.2  christos 
    393  1.34.6.2  christos 		/*
    394  1.34.6.2  christos 		 * Ensure that the text file and database agree on
    395  1.34.6.2  christos 		 * which line the record is from.
    396  1.34.6.2  christos 		 */
    397  1.34.6.2  christos 		rv = getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYNUM, &lineno, &tpwd);
    398  1.34.6.2  christos 		if (newuser) {
    399  1.34.6.2  christos 			if (rv == 0)
    400  1.34.6.2  christos 				inconsistancy();
    401  1.34.6.2  christos 		} else if (rv == -1 ||
    402  1.34.6.2  christos 			strcmp(username, tpwd->pw_name) != 0)
    403  1.34.6.2  christos 			inconsistancy();
    404  1.34.6.2  christos 		else if (olduid != pwd.pw_uid) {
    405  1.34.6.2  christos 			/*
    406  1.34.6.2  christos 			 * If we're changing UID, remove the BYUID
    407  1.34.6.2  christos 			 * record for the old UID only if it has the
    408  1.34.6.2  christos 			 * same username.
    409  1.34.6.2  christos 			 */
    410  1.34.6.2  christos 			if (!getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYUID, &olduid,
    411  1.34.6.2  christos 			    &tpwd)) {
    412  1.34.6.2  christos 				if (strcmp(username, tpwd->pw_name) == 0) {
    413  1.34.6.2  christos 					if (!secureonly)
    414  1.34.6.2  christos 						deldbent(dp, pwd_db_tmp,
    415  1.34.6.2  christos 						    _PW_KEYBYUID, &olduid);
    416  1.34.6.2  christos 					deldbent(edp, pwd_Sdb_tmp,
    417  1.34.6.2  christos 					    _PW_KEYBYUID, &olduid);
    418  1.34.6.2  christos 				}
    419  1.34.6.2  christos 			} else
    420  1.34.6.2  christos 				inconsistancy();
    421  1.34.6.2  christos 		}
    422  1.34.6.2  christos 
    423  1.34.6.2  christos 		/*
    424  1.34.6.2  christos 		 * If there's an existing BYUID record for the new UID and
    425  1.34.6.2  christos 		 * the username doesn't match then be sure not to overwrite
    426  1.34.6.2  christos 		 * it.
    427  1.34.6.2  christos 		 */
    428  1.34.6.2  christos 		if (!getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYUID, &pwd.pw_uid,
    429  1.34.6.2  christos 		    &tpwd))
    430  1.34.6.2  christos 			if (strcmp(username, tpwd->pw_name) != 0)
    431  1.34.6.2  christos 				uid_dbflg = R_NOOVERWRITE;
    432  1.34.6.2  christos 
    433  1.34.6.2  christos 		/* Write the database entries out */
    434  1.34.6.2  christos 		if (!secureonly)
    435  1.34.6.2  christos 			putdbents(dp, &pwd, "*", flags, pwd_db_tmp, lineno,
    436  1.34.6.2  christos 			    dbflg, uid_dbflg);
    437  1.34.6.2  christos 		putdbents(edp, &pwd, pwd.pw_passwd, flags, pwd_Sdb_tmp,
    438  1.34.6.2  christos 		    lineno, dbflg, uid_dbflg);
    439  1.34.6.2  christos 
    440  1.34.6.2  christos 		found = 1;
    441  1.34.6.2  christos 		if (!makeold)
    442  1.34.6.2  christos 			break;
    443  1.34.6.2  christos 	}
    444  1.34.6.2  christos 
    445  1.34.6.2  christos 	if (!secureonly) {
    446  1.34.6.2  christos 		/* Store YP token if needed. */
    447  1.34.6.2  christos 		if (hasyp)
    448  1.34.6.2  christos 			putyptoken(dp, pwd_db_tmp);
    449  1.34.6.2  christos 
    450  1.34.6.2  christos 		/* Close the insecure database. */
    451  1.34.6.2  christos 		if ((*dp->close)(dp) < 0)
    452  1.34.6.2  christos 			wr_error(pwd_db_tmp);
    453  1.34.6.2  christos 	}
    454  1.34.6.2  christos 
    455  1.34.6.2  christos 	/*
    456  1.34.6.2  christos 	 * If rebuilding the databases, we re-parse the text file and write
    457  1.34.6.2  christos 	 * the secure entries out in a separate pass.
    458  1.34.6.2  christos 	 */
    459  1.34.6.2  christos 	if (username == NULL) {
    460  1.34.6.2  christos 		rewind(fp);
    461  1.34.6.2  christos 		for (lineno = 0; scan(fp, &pwd, &flags, &lineno);)
    462  1.34.6.2  christos 			putdbents(edp, &pwd, pwd.pw_passwd, flags, pwd_Sdb_tmp,
    463  1.34.6.2  christos 			    lineno, dbflg, uid_dbflg);
    464  1.34.6.2  christos 
    465  1.34.6.2  christos 		/* Store YP token if needed. */
    466  1.34.6.2  christos 		if (hasyp)
    467  1.34.6.2  christos 			putyptoken(edp, pwd_Sdb_tmp);
    468  1.34.6.2  christos 	} else if (!found) {
    469  1.34.6.2  christos 		warnx("user `%s' not found in password file", username);
    470  1.34.6.2  christos 		bailout();
    471  1.34.6.2  christos 	}
    472  1.34.6.2  christos 
    473  1.34.6.2  christos 	/* Close the secure database. */
    474  1.34.6.2  christos 	if ((*edp->close)(edp) < 0)
    475  1.34.6.2  christos 		wr_error(pwd_Sdb_tmp);
    476  1.34.6.2  christos 
    477  1.34.6.2  christos 	/* Install as the real password files. */
    478  1.34.6.2  christos 	if (!secureonly)
    479  1.34.6.2  christos 		install(pwd_db_tmp, _PATH_MP_DB);
    480  1.34.6.2  christos 	install(pwd_Sdb_tmp, _PATH_SMP_DB);
    481  1.34.6.2  christos 
    482  1.34.6.2  christos 	/* Install the V7 password file. */
    483  1.34.6.2  christos 	if (makeold) {
    484  1.34.6.2  christos 		if (fflush(oldfp) == EOF)
    485  1.34.6.2  christos 			wr_error(oldpwdfile);
    486  1.34.6.2  christos 		if (fclose(oldfp) == EOF)
    487  1.34.6.2  christos 			wr_error(oldpwdfile);
    488  1.34.6.2  christos 		install(oldpwdfile, _PATH_PASSWD);
    489  1.34.6.2  christos 	}
    490  1.34.6.2  christos 
    491  1.34.6.2  christos 	/* Set master.passwd permissions, in case caller forgot. */
    492  1.34.6.2  christos 	(void)fchmod(fileno(fp), S_IRUSR|S_IWUSR);
    493  1.34.6.2  christos 	if (fclose(fp) == EOF)
    494  1.34.6.2  christos 		wr_error(pname);
    495  1.34.6.2  christos 
    496  1.34.6.2  christos 	/*
    497  1.34.6.2  christos 	 * Move the temporary master password file LAST -- chpass(1),
    498  1.34.6.2  christos 	 * passwd(1), vipw(8) and friends all use its existence to block
    499  1.34.6.2  christos 	 * other incarnations of themselves.  The rename means that
    500  1.34.6.2  christos 	 * everything is unlocked, as the original file can no longer be
    501  1.34.6.2  christos 	 * accessed.
    502  1.34.6.2  christos 	 */
    503  1.34.6.2  christos 	install(pname, _PATH_MASTERPASSWD);
    504  1.34.6.2  christos 	exit(EXIT_SUCCESS);
    505  1.34.6.2  christos 	/* NOTREACHED */
    506  1.34.6.2  christos }
    507  1.34.6.2  christos 
    508  1.34.6.2  christos int
    509  1.34.6.2  christos scan(FILE *fp, struct passwd *pw, int *flags, int *lineno)
    510  1.34.6.2  christos {
    511  1.34.6.2  christos 	static char line[LINE_MAX];
    512  1.34.6.2  christos 	char *p;
    513  1.34.6.2  christos 	int oflags;
    514  1.34.6.2  christos 
    515  1.34.6.2  christos 	if (fgets(line, sizeof(line), fp) == NULL)
    516  1.34.6.2  christos 		return (0);
    517  1.34.6.2  christos 	(*lineno)++;
    518  1.34.6.2  christos 
    519  1.34.6.2  christos 	/*
    520  1.34.6.2  christos 	 * ``... if I swallow anything evil, put your fingers down my
    521  1.34.6.2  christos 	 * throat...''
    522  1.34.6.2  christos 	 *	-- The Who
    523  1.34.6.2  christos 	 */
    524  1.34.6.2  christos 	if ((p = strchr(line, '\n')) == NULL) {
    525  1.34.6.2  christos 		warnx("line too long");
    526  1.34.6.2  christos 		errno = EFTYPE;	/* XXX */
    527  1.34.6.2  christos 		error(pname);
    528  1.34.6.2  christos 	}
    529  1.34.6.2  christos 	*p = '\0';
    530  1.34.6.2  christos 	if (strcmp(line, "+") == 0)
    531  1.34.6.2  christos 		strcpy(line, "+:::::::::");	/* pw_scan() can't handle "+" */
    532  1.34.6.2  christos 	oflags = 0;
    533  1.34.6.2  christos 	if (!pw_scan(line, pw, &oflags)) {
    534  1.34.6.2  christos 		warnx("at line #%d", *lineno);
    535  1.34.6.2  christos 		errno = EFTYPE;	/* XXX */
    536  1.34.6.2  christos 		error(pname);
    537  1.34.6.2  christos 	}
    538  1.34.6.2  christos 	*flags = oflags;
    539  1.34.6.2  christos 
    540  1.34.6.2  christos 	return (1);
    541  1.34.6.2  christos }
    542  1.34.6.2  christos 
    543  1.34.6.2  christos void
    544  1.34.6.2  christos install(const char *from, const char *to)
    545  1.34.6.2  christos {
    546  1.34.6.2  christos 	char buf[MAXPATHLEN];
    547  1.34.6.2  christos 	char errbuf[BUFSIZ];
    548  1.34.6.2  christos 	int sverrno;
    549  1.34.6.2  christos 
    550  1.34.6.2  christos 	snprintf(buf, sizeof(buf), "%s%s", prefix, to);
    551  1.34.6.2  christos 	if (rename(from, buf)) {
    552  1.34.6.2  christos 		sverrno = errno;
    553  1.34.6.2  christos 		(void)snprintf(errbuf, sizeof(errbuf), "%s to %s", from, buf);
    554  1.34.6.2  christos 		errno = sverrno;
    555  1.34.6.2  christos 		error(errbuf);
    556  1.34.6.2  christos 	}
    557  1.34.6.2  christos }
    558  1.34.6.2  christos 
    559  1.34.6.2  christos void
    560  1.34.6.2  christos rm(const char *victim)
    561  1.34.6.2  christos {
    562  1.34.6.2  christos 
    563  1.34.6.2  christos 	if (unlink(victim) < 0)
    564  1.34.6.2  christos 		warn("unlink(%s)", victim);
    565  1.34.6.2  christos }
    566  1.34.6.2  christos 
    567  1.34.6.2  christos void
    568  1.34.6.2  christos cp(const char *from, const char *to, mode_t mode)
    569  1.34.6.2  christos {
    570  1.34.6.2  christos 	static char buf[MAXBSIZE];
    571  1.34.6.2  christos 	int from_fd, rcount, to_fd, wcount, sverrno;
    572  1.34.6.2  christos 
    573  1.34.6.2  christos 	if ((from_fd = open(from, O_RDONLY, 0)) < 0)
    574  1.34.6.2  christos 		error(from);
    575  1.34.6.2  christos 	if ((to_fd = open(to, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0)
    576  1.34.6.2  christos 		error(to);
    577  1.34.6.2  christos 	while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
    578  1.34.6.2  christos 		wcount = write(to_fd, buf, rcount);
    579  1.34.6.2  christos 		if (rcount != wcount || wcount == -1) {
    580  1.34.6.2  christos 			sverrno = errno;
    581  1.34.6.2  christos 			(void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
    582  1.34.6.2  christos 			errno = sverrno;
    583  1.34.6.2  christos 			error(buf);
    584  1.34.6.2  christos 		}
    585  1.34.6.2  christos 	}
    586  1.34.6.2  christos 
    587  1.34.6.2  christos 	if (rcount < 0) {
    588  1.34.6.2  christos 		sverrno = errno;
    589  1.34.6.2  christos 		(void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
    590  1.34.6.2  christos 		errno = sverrno;
    591  1.34.6.2  christos 		error(buf);
    592  1.34.6.2  christos 	}
    593  1.34.6.2  christos }
    594  1.34.6.2  christos 
    595  1.34.6.2  christos void
    596  1.34.6.2  christos wr_error(const char *str)
    597  1.34.6.2  christos {
    598  1.34.6.2  christos 	char errbuf[BUFSIZ];
    599  1.34.6.2  christos 	int sverrno;
    600  1.34.6.2  christos 
    601  1.34.6.2  christos 	sverrno = errno;
    602  1.34.6.2  christos 
    603  1.34.6.2  christos 	(void)snprintf(errbuf, sizeof(errbuf),
    604  1.34.6.2  christos 		"attempt to write %s failed", str);
    605  1.34.6.2  christos 
    606  1.34.6.2  christos 	errno = sverrno;
    607  1.34.6.2  christos 	error(errbuf);
    608  1.34.6.2  christos }
    609  1.34.6.2  christos 
    610  1.34.6.2  christos void
    611  1.34.6.2  christos error(const char *str)
    612  1.34.6.2  christos {
    613  1.34.6.2  christos 
    614  1.34.6.2  christos 	warn("%s", str);
    615  1.34.6.2  christos 	bailout();
    616  1.34.6.2  christos }
    617  1.34.6.2  christos 
    618  1.34.6.2  christos void
    619  1.34.6.2  christos inconsistancy(void)
    620  1.34.6.2  christos {
    621  1.34.6.2  christos 
    622  1.34.6.2  christos 	warnx("text files and databases are inconsistent");
    623  1.34.6.2  christos 	warnx("re-build the databases without -u");
    624  1.34.6.2  christos 	bailout();
    625  1.34.6.2  christos }
    626  1.34.6.2  christos 
    627  1.34.6.2  christos void
    628  1.34.6.2  christos bailout(void)
    629  1.34.6.2  christos {
    630  1.34.6.2  christos 
    631  1.34.6.2  christos 	if ((clean & FILE_ORIG) != 0)
    632  1.34.6.2  christos 		rm(oldpwdfile);
    633  1.34.6.2  christos 	if ((clean & FILE_SECURE) != 0)
    634  1.34.6.2  christos 		rm(pwd_Sdb_tmp);
    635  1.34.6.2  christos 	if ((clean & FILE_INSECURE) != 0)
    636  1.34.6.2  christos 		rm(pwd_db_tmp);
    637  1.34.6.2  christos 
    638  1.34.6.2  christos 	exit(EXIT_FAILURE);
    639  1.34.6.2  christos }
    640  1.34.6.2  christos 
    641  1.34.6.2  christos void
    642  1.34.6.2  christos setversion(DB *dp)
    643  1.34.6.2  christos {
    644  1.34.6.2  christos 	DBT data, key;
    645  1.34.6.2  christos 	uint32_t version = sizeof(time_t) != sizeof(int32_t);
    646  1.34.6.2  christos 
    647  1.34.6.2  christos 	key.data = __UNCONST("VERSION");
    648  1.34.6.2  christos 	key.size = strlen((const char *)key.data) + 1;
    649  1.34.6.2  christos 
    650  1.34.6.2  christos 	if (lorder != BYTE_ORDER)
    651  1.34.6.2  christos 		version = SWAP(version);
    652  1.34.6.2  christos 	data.data = &version;
    653  1.34.6.2  christos 	data.size = sizeof(uint32_t);
    654  1.34.6.2  christos 
    655  1.34.6.2  christos 	if ((*dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
    656  1.34.6.2  christos 		wr_error("setversion");
    657  1.34.6.2  christos }
    658  1.34.6.2  christos 
    659  1.34.6.2  christos /*
    660  1.34.6.2  christos  * Write entries to a database for a single user.
    661  1.34.6.2  christos  *
    662  1.34.6.2  christos  * The databases actually contain three copies of the original data.  Each
    663  1.34.6.2  christos  * password file entry is converted into a rough approximation of a ``struct
    664  1.34.6.2  christos  * passwd'', with the strings placed inline.  This object is then stored as
    665  1.34.6.2  christos  * the data for three separate keys.  The first key * is the pw_name field
    666  1.34.6.2  christos  * prepended by the _PW_KEYBYNAME character.  The second key is the pw_uid
    667  1.34.6.2  christos  * field prepended by the _PW_KEYBYUID character.  The third key is the line
    668  1.34.6.2  christos  * number in the original file prepended by the _PW_KEYBYNUM character.
    669  1.34.6.2  christos  * (The special characters are prepended to ensure that the keys do not
    670  1.34.6.2  christos  * collide.)
    671  1.34.6.2  christos  */
    672  1.34.6.2  christos #define	COMPACT(e)	for (t = e; (*p++ = *t++) != '\0';)
    673  1.34.6.2  christos 
    674  1.34.6.2  christos void
    675  1.34.6.2  christos putdbents(DB *dp, struct passwd *pw, const char *passwd, int flags,
    676  1.34.6.2  christos 	  const char *fn, int lineno, int dbflg, int uid_dbflg)
    677  1.34.6.2  christos {
    678  1.34.6.2  christos 	struct passwd pwd;
    679  1.34.6.2  christos 	char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024], *p;
    680  1.34.6.2  christos 	DBT data, key;
    681  1.34.6.2  christos 	const char *t;
    682  1.34.6.2  christos 	u_int32_t x;
    683  1.34.6.2  christos 	int len;
    684  1.34.6.2  christos 
    685  1.34.6.2  christos 	memcpy(&pwd, pw, sizeof(pwd));
    686  1.34.6.2  christos 	data.data = (u_char *)buf;
    687  1.34.6.2  christos 	key.data = (u_char *)tbuf;
    688  1.34.6.2  christos 
    689  1.34.6.2  christos 	if (lorder != BYTE_ORDER) {
    690  1.34.6.2  christos 		pwd.pw_uid = SWAP(pwd.pw_uid);
    691  1.34.6.2  christos 		pwd.pw_gid = SWAP(pwd.pw_gid);
    692  1.34.6.2  christos 		pwd.pw_change = SWAP(pwd.pw_change);
    693  1.34.6.2  christos 		pwd.pw_expire = SWAP(pwd.pw_expire);
    694  1.34.6.2  christos 	}
    695  1.34.6.2  christos 
    696  1.34.6.2  christos 	/* Create insecure data. */
    697  1.34.6.2  christos 	p = buf;
    698  1.34.6.2  christos 	COMPACT(pwd.pw_name);
    699  1.34.6.2  christos 	COMPACT(passwd);
    700  1.34.6.2  christos 	memmove(p, &pwd.pw_uid, sizeof(pwd.pw_uid));
    701  1.34.6.2  christos 	p += sizeof(pwd.pw_uid);
    702  1.34.6.2  christos 	memmove(p, &pwd.pw_gid, sizeof(pwd.pw_gid));
    703  1.34.6.2  christos 	p += sizeof(pwd.pw_gid);
    704  1.34.6.2  christos 	memmove(p, &pwd.pw_change, sizeof(pwd.pw_change));
    705  1.34.6.2  christos 	p += sizeof(pwd.pw_change);
    706  1.34.6.2  christos 	COMPACT(pwd.pw_class);
    707  1.34.6.2  christos 	COMPACT(pwd.pw_gecos);
    708  1.34.6.2  christos 	COMPACT(pwd.pw_dir);
    709  1.34.6.2  christos 	COMPACT(pwd.pw_shell);
    710  1.34.6.2  christos 	memmove(p, &pwd.pw_expire, sizeof(pwd.pw_expire));
    711  1.34.6.2  christos 	p += sizeof(pwd.pw_expire);
    712  1.34.6.2  christos 	x = flags;
    713  1.34.6.2  christos 	if (lorder != BYTE_ORDER)
    714  1.34.6.2  christos 		x = SWAP(x);
    715  1.34.6.2  christos 	memmove(p, &x, sizeof(x));
    716  1.34.6.2  christos 	p += sizeof(flags);
    717  1.34.6.2  christos 	data.size = p - buf;
    718  1.34.6.2  christos 
    719  1.34.6.2  christos 	/* Store insecure by name. */
    720  1.34.6.2  christos 	tbuf[0] = _PW_KEYBYNAME;
    721  1.34.6.2  christos 	len = strlen(pwd.pw_name);
    722  1.34.6.2  christos 	memmove(tbuf + 1, pwd.pw_name, len);
    723  1.34.6.2  christos 	key.size = len + 1;
    724  1.34.6.2  christos 	if ((*dp->put)(dp, &key, &data, dbflg) == -1)
    725  1.34.6.2  christos 		wr_error(fn);
    726  1.34.6.2  christos 
    727  1.34.6.2  christos 	/* Store insecure by number. */
    728  1.34.6.2  christos 	tbuf[0] = _PW_KEYBYNUM;
    729  1.34.6.2  christos 	x = lineno;
    730  1.34.6.2  christos 	if (lorder != BYTE_ORDER)
    731  1.34.6.2  christos 		x = SWAP(x);
    732  1.34.6.2  christos 	memmove(tbuf + 1, &x, sizeof(x));
    733  1.34.6.2  christos 	key.size = sizeof(x) + 1;
    734  1.34.6.2  christos 	if ((*dp->put)(dp, &key, &data, dbflg) == -1)
    735  1.34.6.2  christos 		wr_error(fn);
    736  1.34.6.2  christos 
    737  1.34.6.2  christos 	/* Store insecure by uid. */
    738  1.34.6.2  christos 	tbuf[0] = _PW_KEYBYUID;
    739  1.34.6.2  christos 	memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
    740  1.34.6.2  christos 	key.size = sizeof(pwd.pw_uid) + 1;
    741  1.34.6.2  christos 	if ((*dp->put)(dp, &key, &data, uid_dbflg) == -1)
    742  1.34.6.2  christos 		wr_error(fn);
    743  1.34.6.2  christos }
    744  1.34.6.2  christos 
    745  1.34.6.2  christos int
    746  1.34.6.2  christos deldbent(DB *dp, const char *fn, int type, void *keyp)
    747  1.34.6.2  christos {
    748  1.34.6.2  christos 	char tbuf[1024];
    749  1.34.6.2  christos 	DBT key;
    750  1.34.6.2  christos 	u_int32_t x;
    751  1.34.6.2  christos 	int len, rv;
    752  1.34.6.2  christos 
    753  1.34.6.2  christos 	key.data = (u_char *)tbuf;
    754  1.34.6.2  christos 
    755  1.34.6.2  christos 	switch (tbuf[0] = type) {
    756  1.34.6.2  christos 	case _PW_KEYBYNAME:
    757  1.34.6.2  christos 		len = strlen((char *)keyp);
    758  1.34.6.2  christos 		memcpy(tbuf + 1, keyp, len);
    759  1.34.6.2  christos 		key.size = len + 1;
    760  1.34.6.2  christos 		break;
    761  1.34.6.2  christos 
    762  1.34.6.2  christos 	case _PW_KEYBYNUM:
    763  1.34.6.2  christos 	case _PW_KEYBYUID:
    764  1.34.6.2  christos 		x = *(int *)keyp;
    765  1.34.6.2  christos 		if (lorder != BYTE_ORDER)
    766  1.34.6.2  christos 			x = SWAP(x);
    767  1.34.6.2  christos 		memmove(tbuf + 1, &x, sizeof(x));
    768  1.34.6.2  christos 		key.size = sizeof(x) + 1;
    769  1.34.6.2  christos 		break;
    770  1.34.6.2  christos 	}
    771  1.34.6.2  christos 
    772  1.34.6.2  christos 	if ((rv = (*dp->del)(dp, &key, 0)) == -1)
    773  1.34.6.2  christos 		wr_error(fn);
    774  1.34.6.2  christos 	return (rv);
    775  1.34.6.2  christos }
    776  1.34.6.2  christos 
    777  1.34.6.2  christos int
    778  1.34.6.2  christos getdbent(DB *dp, const char *fn, int type, void *keyp, struct passwd **tpwd)
    779  1.34.6.2  christos {
    780  1.34.6.2  christos 	static char buf[MAX(MAXPATHLEN, LINE_MAX * 2)];
    781  1.34.6.2  christos 	static struct passwd pwd;
    782  1.34.6.2  christos 	char tbuf[1024], *p;
    783  1.34.6.2  christos 	DBT key, data;
    784  1.34.6.2  christos 	u_int32_t x;
    785  1.34.6.2  christos 	int len, rv;
    786  1.34.6.2  christos 
    787  1.34.6.2  christos 	data.data = (u_char *)buf;
    788  1.34.6.2  christos 	data.size = sizeof(buf);
    789  1.34.6.2  christos 	key.data = (u_char *)tbuf;
    790  1.34.6.2  christos 
    791  1.34.6.2  christos 	switch (tbuf[0] = type) {
    792  1.34.6.2  christos 	case _PW_KEYBYNAME:
    793  1.34.6.2  christos 		len = strlen((char *)keyp);
    794  1.34.6.2  christos 		memcpy(tbuf + 1, keyp, len);
    795  1.34.6.2  christos 		key.size = len + 1;
    796  1.34.6.2  christos 		break;
    797  1.34.6.2  christos 
    798  1.34.6.2  christos 	case _PW_KEYBYNUM:
    799  1.34.6.2  christos 	case _PW_KEYBYUID:
    800  1.34.6.2  christos 		x = *(int *)keyp;
    801  1.34.6.2  christos 		if (lorder != BYTE_ORDER)
    802  1.34.6.2  christos 			x = SWAP(x);
    803  1.34.6.2  christos 		memmove(tbuf + 1, &x, sizeof(x));
    804  1.34.6.2  christos 		key.size = sizeof(x) + 1;
    805  1.34.6.2  christos 		break;
    806  1.34.6.2  christos 	}
    807  1.34.6.2  christos 
    808  1.34.6.2  christos 	if ((rv = (*dp->get)(dp, &key, &data, 0)) == 1)
    809  1.34.6.2  christos 		return (rv);
    810  1.34.6.2  christos 	if (rv == -1)
    811  1.34.6.2  christos 		error(pwd_Sdb_tmp);
    812  1.34.6.2  christos 
    813  1.34.6.2  christos 	p = (char *)data.data;
    814  1.34.6.2  christos 
    815  1.34.6.2  christos 	pwd.pw_name = p;
    816  1.34.6.2  christos 	while (*p++ != '\0')
    817  1.34.6.2  christos 		;
    818  1.34.6.2  christos 	pwd.pw_passwd = p;
    819  1.34.6.2  christos 	while (*p++ != '\0')
    820  1.34.6.2  christos 		;
    821  1.34.6.2  christos 
    822  1.34.6.2  christos 	memcpy(&pwd.pw_uid, p, sizeof(pwd.pw_uid));
    823  1.34.6.2  christos 	p += sizeof(pwd.pw_uid);
    824  1.34.6.2  christos 	memcpy(&pwd.pw_gid, p, sizeof(pwd.pw_gid));
    825  1.34.6.2  christos 	p += sizeof(pwd.pw_gid);
    826  1.34.6.2  christos 	memcpy(&pwd.pw_change, p, sizeof(pwd.pw_change));
    827  1.34.6.2  christos 	p += sizeof(pwd.pw_change);
    828  1.34.6.2  christos 
    829  1.34.6.2  christos 	pwd.pw_class = p;
    830  1.34.6.2  christos 	while (*p++ != '\0')
    831  1.34.6.2  christos 		;
    832  1.34.6.2  christos 	pwd.pw_gecos = p;
    833  1.34.6.2  christos 	while (*p++ != '\0')
    834  1.34.6.2  christos 		;
    835  1.34.6.2  christos 	pwd.pw_dir = p;
    836  1.34.6.2  christos 	while (*p++ != '\0')
    837  1.34.6.2  christos 		;
    838  1.34.6.2  christos 	pwd.pw_shell = p;
    839  1.34.6.2  christos 	while (*p++ != '\0')
    840  1.34.6.2  christos 		;
    841  1.34.6.2  christos 
    842  1.34.6.2  christos 	memcpy(&pwd.pw_expire, p, sizeof(pwd.pw_expire));
    843  1.34.6.2  christos 	p += sizeof(pwd.pw_expire);
    844  1.34.6.2  christos 
    845  1.34.6.2  christos 	if (lorder != BYTE_ORDER) {
    846  1.34.6.2  christos 		pwd.pw_uid = SWAP(pwd.pw_uid);
    847  1.34.6.2  christos 		pwd.pw_gid = SWAP(pwd.pw_gid);
    848  1.34.6.2  christos 		pwd.pw_change = SWAP(pwd.pw_change);
    849  1.34.6.2  christos 		pwd.pw_expire = SWAP(pwd.pw_expire);
    850  1.34.6.2  christos 	}
    851  1.34.6.2  christos 
    852  1.34.6.2  christos 	*tpwd = &pwd;
    853  1.34.6.2  christos 	return (0);
    854  1.34.6.2  christos }
    855  1.34.6.2  christos 
    856  1.34.6.2  christos void
    857  1.34.6.2  christos putyptoken(DB *dp, const char *fn)
    858  1.34.6.2  christos {
    859  1.34.6.2  christos 	DBT data, key;
    860  1.34.6.2  christos 
    861  1.34.6.2  christos 	key.data = (u_char *)__yp_token;
    862  1.34.6.2  christos 	key.size = strlen(__yp_token);
    863  1.34.6.2  christos 	data.data = (u_char *)NULL;
    864  1.34.6.2  christos 	data.size = 0;
    865  1.34.6.2  christos 
    866  1.34.6.2  christos 	if ((*dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
    867  1.34.6.2  christos 		wr_error(fn);
    868  1.34.6.2  christos }
    869  1.34.6.2  christos 
    870  1.34.6.2  christos void
    871  1.34.6.2  christos usage(void)
    872  1.34.6.2  christos {
    873  1.34.6.2  christos 
    874  1.34.6.2  christos 	(void)fprintf(stderr,
    875  1.34.6.2  christos 	    "usage: pwd_mkdb [-BLps] [-c cachesize] [-d directory] [-u user] file\n");
    876  1.34.6.2  christos 	exit(EXIT_FAILURE);
    877  1.34.6.2  christos }
    878