1*0a6a1f1dSLionel Sambuc /* $NetBSD: pwd_mkdb.c,v 1.57 2014/01/26 01:57:04 christos Exp $ */
25c007436SBen Gras
35c007436SBen Gras /*
45c007436SBen Gras * Copyright (c) 2000, 2009 The NetBSD Foundation, Inc.
55c007436SBen Gras * All rights reserved.
65c007436SBen Gras *
75c007436SBen Gras * Redistribution and use in source and binary forms, with or without
85c007436SBen Gras * modification, are permitted provided that the following conditions
95c007436SBen Gras * are met:
105c007436SBen Gras * 1. Redistributions of source code must retain the above copyright
115c007436SBen Gras * notice, this list of conditions and the following disclaimer.
125c007436SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
135c007436SBen Gras * notice, this list of conditions and the following disclaimer in the
145c007436SBen Gras * documentation and/or other materials provided with the distribution.
155c007436SBen Gras *
165c007436SBen Gras * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
175c007436SBen Gras * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
185c007436SBen Gras * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
195c007436SBen Gras * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
205c007436SBen Gras * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
215c007436SBen Gras * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
225c007436SBen Gras * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
235c007436SBen Gras * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
245c007436SBen Gras * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
255c007436SBen Gras * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
265c007436SBen Gras * POSSIBILITY OF SUCH DAMAGE.
275c007436SBen Gras */
285c007436SBen Gras
295c007436SBen Gras /*
305c007436SBen Gras * Copyright (c) 1991, 1993, 1994
315c007436SBen Gras * The Regents of the University of California. All rights reserved.
325c007436SBen Gras *
335c007436SBen Gras * Redistribution and use in source and binary forms, with or without
345c007436SBen Gras * modification, are permitted provided that the following conditions
355c007436SBen Gras * are met:
365c007436SBen Gras * 1. Redistributions of source code must retain the above copyright
375c007436SBen Gras * notice, this list of conditions and the following disclaimer.
385c007436SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
395c007436SBen Gras * notice, this list of conditions and the following disclaimer in the
405c007436SBen Gras * documentation and/or other materials provided with the distribution.
415c007436SBen Gras * 3. Neither the name of the University nor the names of its contributors
425c007436SBen Gras * may be used to endorse or promote products derived from this software
435c007436SBen Gras * without specific prior written permission.
445c007436SBen Gras *
455c007436SBen Gras * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
465c007436SBen Gras * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
475c007436SBen Gras * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
485c007436SBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
495c007436SBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
505c007436SBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
515c007436SBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
525c007436SBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
535c007436SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
545c007436SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
555c007436SBen Gras * SUCH DAMAGE.
565c007436SBen Gras */
575c007436SBen Gras
585c007436SBen Gras /*
595c007436SBen Gras * Portions Copyright(C) 1994, Jason Downs. All rights reserved.
605c007436SBen Gras *
615c007436SBen Gras * Redistribution and use in source and binary forms, with or without
625c007436SBen Gras * modification, are permitted provided that the following conditions
635c007436SBen Gras * are met:
645c007436SBen Gras * 1. Redistributions of source code must retain the above copyright
655c007436SBen Gras * notice, this list of conditions and the following disclaimer.
665c007436SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
675c007436SBen Gras * notice, this list of conditions and the following disclaimer in the
685c007436SBen Gras * documentation and/or other materials provided with the distribution.
695c007436SBen Gras *
705c007436SBen Gras * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
715c007436SBen Gras * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
725c007436SBen Gras * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
735c007436SBen Gras * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
745c007436SBen Gras * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
755c007436SBen Gras * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
765c007436SBen Gras * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
775c007436SBen Gras * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
785c007436SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
795c007436SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
805c007436SBen Gras * SUCH DAMAGE.
815c007436SBen Gras */
825c007436SBen Gras
835c007436SBen Gras #if HAVE_NBTOOL_CONFIG_H
845c007436SBen Gras #include "nbtool_config.h"
855c007436SBen Gras #endif
865c007436SBen Gras
875c007436SBen Gras #include <sys/cdefs.h>
885c007436SBen Gras #if !defined(lint)
895c007436SBen Gras __COPYRIGHT("@(#) Copyright (c) 2000, 2009\
905c007436SBen Gras The NetBSD Foundation, Inc. All rights reserved.\
915c007436SBen Gras Copyright (c) 1991, 1993, 1994\
925c007436SBen Gras The Regents of the University of California. All rights reserved.");
93*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: pwd_mkdb.c,v 1.57 2014/01/26 01:57:04 christos Exp $");
945c007436SBen Gras #endif /* not lint */
955c007436SBen Gras
965c007436SBen Gras #if HAVE_NBTOOL_CONFIG_H
975c007436SBen Gras #include "compat_pwd.h"
985c007436SBen Gras #else
995c007436SBen Gras #include <pwd.h>
1005c007436SBen Gras #endif
1015c007436SBen Gras
1025c007436SBen Gras #include <sys/param.h>
1035c007436SBen Gras #include <sys/stat.h>
1045c007436SBen Gras #include <sys/types.h>
1055c007436SBen Gras
1065c007436SBen Gras #ifndef HAVE_NBTOOL_CONFIG_H
1075c007436SBen Gras #include <machine/bswap.h>
1085c007436SBen Gras #endif
1095c007436SBen Gras
1105c007436SBen Gras #include <db.h>
1115c007436SBen Gras #include <err.h>
1125c007436SBen Gras #include <errno.h>
1135c007436SBen Gras #include <fcntl.h>
1145c007436SBen Gras #include <syslog.h>
1155c007436SBen Gras #include <limits.h>
1165c007436SBen Gras #include <signal.h>
1175c007436SBen Gras #include <stdio.h>
1185c007436SBen Gras #include <stdlib.h>
1195c007436SBen Gras #include <stdarg.h>
1205c007436SBen Gras #include <string.h>
1215c007436SBen Gras #include <unistd.h>
12284d9c625SLionel Sambuc
12384d9c625SLionel Sambuc #ifndef HAVE_NBTOOL_CONFIG_H
1245c007436SBen Gras #include <util.h>
12584d9c625SLionel Sambuc #endif
1265c007436SBen Gras
1275c007436SBen Gras #define MAX_CACHESIZE 8*1024*1024
1285c007436SBen Gras #define MIN_CACHESIZE 2*1024*1024
1295c007436SBen Gras
1305c007436SBen Gras #define PERM_INSECURE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
1315c007436SBen Gras #define PERM_SECURE (S_IRUSR | S_IWUSR)
1325c007436SBen Gras
1335c007436SBen Gras #if HAVE_NBTOOL_CONFIG_H
1345c007436SBen Gras static const char __yp_token[] = "__YP!";
1355c007436SBen Gras #else
1365c007436SBen Gras /* Pull this out of the C library. */
1375c007436SBen Gras extern const char __yp_token[];
1385c007436SBen Gras #endif
1395c007436SBen Gras
1405c007436SBen Gras static HASHINFO openinfo = {
1415c007436SBen Gras 4096, /* bsize */
1425c007436SBen Gras 32, /* ffactor */
1435c007436SBen Gras 256, /* nelem */
1445c007436SBen Gras 0, /* cachesize */
1455c007436SBen Gras NULL, /* hash() */
1465c007436SBen Gras 0 /* lorder */
1475c007436SBen Gras };
1485c007436SBen Gras
1495c007436SBen Gras #define FILE_INSECURE 0x01
1505c007436SBen Gras #define FILE_SECURE 0x02
1515c007436SBen Gras #define FILE_ORIG 0x04
1525c007436SBen Gras
1535c007436SBen Gras
1545c007436SBen Gras struct pwddb {
1555c007436SBen Gras DB *db;
1565c007436SBen Gras char dbname[MAX(MAXPATHLEN, LINE_MAX * 2)];
1575c007436SBen Gras const char *fname;
1585c007436SBen Gras uint32_t rversion;
1595c007436SBen Gras uint32_t wversion;
1605c007436SBen Gras };
1615c007436SBen Gras
1625c007436SBen Gras static char *pname; /* password file name */
1635c007436SBen Gras static char prefix[MAXPATHLEN];
1645c007436SBen Gras static char oldpwdfile[MAX(MAXPATHLEN, LINE_MAX * 2)];
1655c007436SBen Gras static int lorder = BYTE_ORDER;
1665c007436SBen Gras static int logsyslog;
1675c007436SBen Gras static int clean;
1685c007436SBen Gras static int verbose;
1695c007436SBen Gras static int warning;
1705c007436SBen Gras static struct pwddb sdb, idb;
1715c007436SBen Gras
1725c007436SBen Gras
17384d9c625SLionel Sambuc void bailout(void) __dead;
1745c007436SBen Gras void cp(const char *, const char *, mode_t);
1755c007436SBen Gras void deldbent(struct pwddb *, int, void *);
17684d9c625SLionel Sambuc void mkpw_error(const char *, ...) __dead;
1775c007436SBen Gras void mkpw_warning(const char *, ...);
1785c007436SBen Gras int getdbent(struct pwddb *, int, void *, struct passwd **);
17984d9c625SLionel Sambuc void inconsistency(void) __dead;
1805c007436SBen Gras void install(const char *, const char *);
1815c007436SBen Gras int main(int, char **);
1825c007436SBen Gras void putdbents(struct pwddb *, struct passwd *, const char *, int, int,
1835c007436SBen Gras u_int, u_int);
1845c007436SBen Gras void putyptoken(struct pwddb *);
1855c007436SBen Gras void rm(const char *);
1865c007436SBen Gras int scan(FILE *, struct passwd *, int *, int *);
18784d9c625SLionel Sambuc void usage(void) __dead;
18884d9c625SLionel Sambuc void wr_error(const char *) __dead;
1895c007436SBen Gras uint32_t getversion(const char *);
1905c007436SBen Gras void setversion(struct pwddb *);
1915c007436SBen Gras
1925c007436SBen Gras #ifndef __lint__
1935c007436SBen Gras #define SWAP(sw) \
1945c007436SBen Gras ((sizeof(sw) == 2 ? (typeof(sw))bswap16((uint16_t)sw) : \
1955c007436SBen Gras (sizeof(sw) == 4 ? (typeof(sw))bswap32((uint32_t)sw) : \
1965c007436SBen Gras (sizeof(sw) == 8 ? (typeof(sw))bswap64((uint64_t)sw) : (abort(), 0)))))
1975c007436SBen Gras #else
1985c007436SBen Gras #define SWAP(sw) sw
1995c007436SBen Gras #endif
2005c007436SBen Gras
2015c007436SBen Gras static void
closedb(struct pwddb * db)2025c007436SBen Gras closedb(struct pwddb *db)
2035c007436SBen Gras {
2045c007436SBen Gras if ((*db->db->close)(db->db) < 0)
2055c007436SBen Gras wr_error(db->dbname);
2065c007436SBen Gras }
2075c007436SBen Gras
2085c007436SBen Gras static void
opendb(struct pwddb * db,const char * dbname,const char * username,uint32_t req_version,int flags,mode_t perm)2095c007436SBen Gras opendb(struct pwddb *db, const char *dbname, const char *username,
2105c007436SBen Gras uint32_t req_version, int flags, mode_t perm)
2115c007436SBen Gras {
2125c007436SBen Gras char buf[MAXPATHLEN];
2135c007436SBen Gras
2145c007436SBen Gras (void)snprintf(db->dbname, sizeof(db->dbname), "%s%s.tmp", prefix,
2155c007436SBen Gras dbname);
2165c007436SBen Gras
2175c007436SBen Gras if (username != NULL) {
2185c007436SBen Gras (void)snprintf(buf, sizeof(buf), "%s%s", prefix, dbname);
2195c007436SBen Gras cp(buf, db->dbname, perm);
2205c007436SBen Gras }
2215c007436SBen Gras
2225c007436SBen Gras db->db = dbopen(db->dbname, flags, perm, DB_HASH, &openinfo);
2235c007436SBen Gras if (db->db == NULL)
2245c007436SBen Gras mkpw_error("Cannot open `%s'", db->dbname);
2255c007436SBen Gras
2265c007436SBen Gras db->fname = dbname;
2275c007436SBen Gras db->rversion = getversion(dbname);
2285c007436SBen Gras if (req_version == ~0U)
2295c007436SBen Gras db->wversion = db->rversion;
2305c007436SBen Gras else
2315c007436SBen Gras db->wversion = req_version;
2325c007436SBen Gras
2335c007436SBen Gras if (warning && db->rversion == 0 && db->wversion == 0) {
2345c007436SBen Gras mkpw_warning("Database %s is a version %u database.",
2355c007436SBen Gras db->fname, db->rversion);
2365c007436SBen Gras mkpw_warning("Use %s -V 1 to upgrade once you've recompiled "
2375c007436SBen Gras "all your binaries.", getprogname());
2385c007436SBen Gras }
2395c007436SBen Gras if (db->wversion != db->rversion) {
2405c007436SBen Gras if (username != NULL) {
2415c007436SBen Gras mkpw_warning("You cannot change a single "
2425c007436SBen Gras "record from version %u to version %u\n",
2435c007436SBen Gras db->rversion, db->wversion);
2445c007436SBen Gras bailout();
2455c007436SBen Gras } else if (verbose) {
2465c007436SBen Gras mkpw_warning("Changing %s from version %u to version %u",
2475c007436SBen Gras db->fname, db->rversion, db->wversion);
2485c007436SBen Gras }
2495c007436SBen Gras } else {
2505c007436SBen Gras if (verbose)
2515c007436SBen Gras mkpw_warning("File `%s' version %u requested %u",
2525c007436SBen Gras db->fname, db->rversion, db->wversion);
2535c007436SBen Gras }
2545c007436SBen Gras
2555c007436SBen Gras setversion(db);
2565c007436SBen Gras }
2575c007436SBen Gras
2585c007436SBen Gras int
main(int argc,char * argv[])2595c007436SBen Gras main(int argc, char *argv[])
2605c007436SBen Gras {
2615c007436SBen Gras int ch, makeold, tfd, lineno, found, rv, hasyp, secureonly;
2625c007436SBen Gras struct passwd pwd, *tpwd;
2635c007436SBen Gras char *username;
2645c007436SBen Gras FILE *fp, *oldfp;
2655c007436SBen Gras sigset_t set;
2665c007436SBen Gras u_int dbflg, uid_dbflg;
2675c007436SBen Gras int newuser, olduid, flags;
2685c007436SBen Gras struct stat st;
2695c007436SBen Gras u_int cachesize;
2705c007436SBen Gras uint32_t req_version;
2715c007436SBen Gras
2725c007436SBen Gras prefix[0] = '\0';
2735c007436SBen Gras makeold = 0;
2745c007436SBen Gras oldfp = NULL;
2755c007436SBen Gras username = NULL;
2765c007436SBen Gras hasyp = 0;
2775c007436SBen Gras secureonly = 0;
2785c007436SBen Gras found = 0;
2795c007436SBen Gras newuser = 0;
2805c007436SBen Gras cachesize = 0;
2815c007436SBen Gras verbose = 0;
2825c007436SBen Gras warning = 0;
2835c007436SBen Gras logsyslog = 0;
2845c007436SBen Gras req_version = ~0U;
2855c007436SBen Gras
2865c007436SBen Gras while ((ch = getopt(argc, argv, "BLc:d:lpsu:V:vw")) != -1)
2875c007436SBen Gras switch (ch) {
2885c007436SBen Gras case 'B': /* big-endian output */
2895c007436SBen Gras lorder = BIG_ENDIAN;
2905c007436SBen Gras break;
2915c007436SBen Gras case 'L': /* little-endian output */
2925c007436SBen Gras lorder = LITTLE_ENDIAN;
2935c007436SBen Gras break;
2945c007436SBen Gras case 'c':
2955c007436SBen Gras cachesize = atoi(optarg) * 1024 * 1024;
2965c007436SBen Gras break;
2975c007436SBen Gras case 'd': /* set prefix */
2985c007436SBen Gras (void)strlcpy(prefix, optarg, sizeof(prefix));
2995c007436SBen Gras break;
3005c007436SBen Gras case 'l':
3015c007436SBen Gras openlog(getprogname(), LOG_PID, LOG_AUTH);
3025c007436SBen Gras logsyslog = 1;
3035c007436SBen Gras break;
3045c007436SBen Gras case 'p': /* create V7 "file.orig" */
3055c007436SBen Gras makeold = 1;
3065c007436SBen Gras break;
3075c007436SBen Gras case 's': /* modify secure db only */
3085c007436SBen Gras secureonly = 1;
3095c007436SBen Gras break;
3105c007436SBen Gras case 'u': /* modify one user only */
3115c007436SBen Gras username = optarg;
3125c007436SBen Gras break;
3135c007436SBen Gras case 'V':
3145c007436SBen Gras req_version = (uint32_t)atoi(optarg);
3155c007436SBen Gras if (req_version > 1) {
3165c007436SBen Gras mkpw_warning("Unknown version %u", req_version);
3175c007436SBen Gras return EXIT_FAILURE;
3185c007436SBen Gras }
3195c007436SBen Gras break;
3205c007436SBen Gras case 'v':
3215c007436SBen Gras verbose++;
3225c007436SBen Gras break;
3235c007436SBen Gras case 'w':
3245c007436SBen Gras warning++;
3255c007436SBen Gras break;
3265c007436SBen Gras case '?':
3275c007436SBen Gras default:
3285c007436SBen Gras usage();
3295c007436SBen Gras }
3305c007436SBen Gras argc -= optind;
3315c007436SBen Gras argv += optind;
3325c007436SBen Gras
3335c007436SBen Gras if (argc != 1)
3345c007436SBen Gras usage();
3355c007436SBen Gras if (username != NULL)
3365c007436SBen Gras if (username[0] == '+' || username[0] == '-')
3375c007436SBen Gras usage();
3385c007436SBen Gras if (secureonly)
3395c007436SBen Gras makeold = 0;
3405c007436SBen Gras
3415c007436SBen Gras /*
3425c007436SBen Gras * This could be changed to allow the user to interrupt.
3435c007436SBen Gras * Probably not worth the effort.
3445c007436SBen Gras */
3455c007436SBen Gras (void)sigemptyset(&set);
3465c007436SBen Gras (void)sigaddset(&set, SIGTSTP);
3475c007436SBen Gras (void)sigaddset(&set, SIGHUP);
3485c007436SBen Gras (void)sigaddset(&set, SIGINT);
3495c007436SBen Gras (void)sigaddset(&set, SIGQUIT);
3505c007436SBen Gras (void)sigaddset(&set, SIGTERM);
35184d9c625SLionel Sambuc (void)sigprocmask(SIG_BLOCK, &set, NULL);
3525c007436SBen Gras
3535c007436SBen Gras /* We don't care what the user wants. */
3545c007436SBen Gras (void)umask(0);
3555c007436SBen Gras
3565c007436SBen Gras if (username == NULL)
3575c007436SBen Gras flags = O_RDWR | O_CREAT | O_EXCL;
3585c007436SBen Gras else
3595c007436SBen Gras flags = O_RDWR;
3605c007436SBen Gras
3615c007436SBen Gras pname = *argv;
3625c007436SBen Gras /* Open the original password file */
3635c007436SBen Gras if ((fp = fopen(pname, "r")) == NULL)
3645c007436SBen Gras mkpw_error("Cannot open `%s'", pname);
3655c007436SBen Gras
3665c007436SBen Gras openinfo.lorder = lorder;
3675c007436SBen Gras
3685c007436SBen Gras if (fstat(fileno(fp), &st) == -1)
3695c007436SBen Gras mkpw_error("Cannot stat `%s'", pname);
3705c007436SBen Gras
3715c007436SBen Gras if (cachesize) {
3725c007436SBen Gras openinfo.cachesize = cachesize;
3735c007436SBen Gras } else {
3745c007436SBen Gras /* Tweak openinfo values for large passwd files. */
3755c007436SBen Gras cachesize = (u_int)(st.st_size * 20);
3765c007436SBen Gras if (cachesize > MAX_CACHESIZE)
3775c007436SBen Gras cachesize = MAX_CACHESIZE;
3785c007436SBen Gras else if (cachesize < MIN_CACHESIZE)
3795c007436SBen Gras cachesize = MIN_CACHESIZE;
3805c007436SBen Gras openinfo.cachesize = cachesize;
3815c007436SBen Gras }
3825c007436SBen Gras
3835c007436SBen Gras /* Open the temporary insecure password database. */
3845c007436SBen Gras if (!secureonly) {
3855c007436SBen Gras opendb(&idb, _PATH_MP_DB, username, req_version,
3865c007436SBen Gras flags, PERM_INSECURE);
3875c007436SBen Gras clean |= FILE_INSECURE;
3885c007436SBen Gras }
3895c007436SBen Gras
3905c007436SBen Gras
3915c007436SBen Gras /* Open the temporary encrypted password database. */
3925c007436SBen Gras opendb(&sdb, _PATH_SMP_DB, username, req_version, flags, PERM_SECURE);
3935c007436SBen Gras clean |= FILE_SECURE;
3945c007436SBen Gras
3955c007436SBen Gras /*
3965c007436SBen Gras * Open file for old password file. Minor trickiness -- don't want to
3975c007436SBen Gras * chance the file already existing, since someone (stupidly) might
3985c007436SBen Gras * still be using this for permission checking. So, open it first and
3995c007436SBen Gras * fdopen the resulting fd. The resulting file should be readable by
4005c007436SBen Gras * everyone.
4015c007436SBen Gras */
4025c007436SBen Gras if (makeold) {
4035c007436SBen Gras (void)snprintf(oldpwdfile, sizeof(oldpwdfile), "%s.orig",
4045c007436SBen Gras pname);
4055c007436SBen Gras if ((tfd = open(oldpwdfile, O_WRONLY | O_CREAT | O_EXCL,
4065c007436SBen Gras PERM_INSECURE)) < 0)
4075c007436SBen Gras mkpw_error("Cannot create `%s'", oldpwdfile);
4085c007436SBen Gras clean |= FILE_ORIG;
4095c007436SBen Gras if ((oldfp = fdopen(tfd, "w")) == NULL)
4105c007436SBen Gras mkpw_error("Cannot fdopen `%s'", oldpwdfile);
4115c007436SBen Gras }
4125c007436SBen Gras
4135c007436SBen Gras if (username != NULL) {
4145c007436SBen Gras uid_dbflg = 0;
4155c007436SBen Gras dbflg = 0;
4165c007436SBen Gras
4175c007436SBen Gras /*
4185c007436SBen Gras * Determine if this is a new entry.
4195c007436SBen Gras */
4205c007436SBen Gras if (getdbent(&sdb, _PW_KEYBYNAME, username, &tpwd))
4215c007436SBen Gras newuser = 1;
4225c007436SBen Gras else {
4235c007436SBen Gras newuser = 0;
4245c007436SBen Gras olduid = tpwd->pw_uid;
4255c007436SBen Gras }
4265c007436SBen Gras
4275c007436SBen Gras } else {
4285c007436SBen Gras uid_dbflg = R_NOOVERWRITE;
4295c007436SBen Gras dbflg = R_NOOVERWRITE;
4305c007436SBen Gras }
4315c007436SBen Gras
4325c007436SBen Gras /*
4335c007436SBen Gras * If we see something go by that looks like YP, we save a special
4345c007436SBen Gras * pointer record, which if YP is enabled in the C lib, will speed
4355c007436SBen Gras * things up.
4365c007436SBen Gras */
4375c007436SBen Gras for (lineno = 0; scan(fp, &pwd, &flags, &lineno);) {
4385c007436SBen Gras /*
4395c007436SBen Gras * Create original format password file entry.
4405c007436SBen Gras */
4415c007436SBen Gras if (makeold) {
4425c007436SBen Gras (void)fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n",
4435c007436SBen Gras pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos,
4445c007436SBen Gras pwd.pw_dir, pwd.pw_shell);
4455c007436SBen Gras if (ferror(oldfp))
4465c007436SBen Gras wr_error(oldpwdfile);
4475c007436SBen Gras }
4485c007436SBen Gras
4495c007436SBen Gras if (username == NULL) {
4505c007436SBen Gras /* Look like YP? */
4515c007436SBen Gras if (pwd.pw_name[0] == '+' || pwd.pw_name[0] == '-')
4525c007436SBen Gras hasyp++;
4535c007436SBen Gras
4545c007436SBen Gras /* Warn about potentially unsafe uid/gid overrides. */
4555c007436SBen Gras if (pwd.pw_name[0] == '+') {
4565c007436SBen Gras if ((flags & _PASSWORD_NOUID) == 0 &&
4575c007436SBen Gras pwd.pw_uid == 0)
4585c007436SBen Gras mkpw_warning("line %d: superuser "
4595c007436SBen Gras "override in YP inclusion", lineno);
4605c007436SBen Gras if ((flags & _PASSWORD_NOGID) == 0 &&
4615c007436SBen Gras pwd.pw_gid == 0)
4625c007436SBen Gras mkpw_warning("line %d: wheel override "
4635c007436SBen Gras "in YP inclusion", lineno);
4645c007436SBen Gras }
4655c007436SBen Gras
4665c007436SBen Gras /* Write the database entry out. */
4675c007436SBen Gras if (!secureonly)
4685c007436SBen Gras putdbents(&idb, &pwd, "*", flags, lineno, dbflg,
4695c007436SBen Gras uid_dbflg);
4705c007436SBen Gras continue;
4715c007436SBen Gras } else if (strcmp(username, pwd.pw_name) != 0)
4725c007436SBen Gras continue;
4735c007436SBen Gras
4745c007436SBen Gras if (found) {
4755c007436SBen Gras mkpw_warning("user `%s' listed twice in password file",
4765c007436SBen Gras username);
4775c007436SBen Gras bailout();
4785c007436SBen Gras }
4795c007436SBen Gras
4805c007436SBen Gras /*
4815c007436SBen Gras * Ensure that the text file and database agree on
4825c007436SBen Gras * which line the record is from.
4835c007436SBen Gras */
4845c007436SBen Gras rv = getdbent(&sdb, _PW_KEYBYNUM, &lineno, &tpwd);
4855c007436SBen Gras if (newuser) {
4865c007436SBen Gras if (rv == 0)
4875c007436SBen Gras inconsistency();
4885c007436SBen Gras } else if (rv == 1 || strcmp(username, tpwd->pw_name) != 0)
4895c007436SBen Gras inconsistency();
4905c007436SBen Gras else if ((uid_t)olduid != pwd.pw_uid) {
4915c007436SBen Gras /*
4925c007436SBen Gras * If we're changing UID, remove the BYUID
4935c007436SBen Gras * record for the old UID only if it has the
4945c007436SBen Gras * same username.
4955c007436SBen Gras */
4965c007436SBen Gras if (!getdbent(&sdb, _PW_KEYBYUID, &olduid, &tpwd)) {
4975c007436SBen Gras if (strcmp(username, tpwd->pw_name) == 0) {
4985c007436SBen Gras if (!secureonly)
4995c007436SBen Gras deldbent(&idb, _PW_KEYBYUID,
5005c007436SBen Gras &olduid);
5015c007436SBen Gras deldbent(&sdb, _PW_KEYBYUID, &olduid);
5025c007436SBen Gras }
5035c007436SBen Gras } else
5045c007436SBen Gras inconsistency();
5055c007436SBen Gras }
5065c007436SBen Gras
5075c007436SBen Gras /*
5085c007436SBen Gras * If there's an existing BYUID record for the new UID and
5095c007436SBen Gras * the username doesn't match then be sure not to overwrite
5105c007436SBen Gras * it.
5115c007436SBen Gras */
5125c007436SBen Gras if (!getdbent(&sdb, _PW_KEYBYUID, &pwd.pw_uid, &tpwd))
5135c007436SBen Gras if (strcmp(username, tpwd->pw_name) != 0)
5145c007436SBen Gras uid_dbflg = R_NOOVERWRITE;
5155c007436SBen Gras
5165c007436SBen Gras /* Write the database entries out */
5175c007436SBen Gras if (!secureonly)
5185c007436SBen Gras putdbents(&idb, &pwd, "*", flags, lineno, dbflg,
5195c007436SBen Gras uid_dbflg);
5205c007436SBen Gras putdbents(&sdb, &pwd, pwd.pw_passwd, flags, lineno, dbflg,
5215c007436SBen Gras uid_dbflg);
5225c007436SBen Gras
5235c007436SBen Gras found = 1;
5245c007436SBen Gras if (!makeold)
5255c007436SBen Gras break;
5265c007436SBen Gras }
5275c007436SBen Gras
5285c007436SBen Gras if (!secureonly) {
5295c007436SBen Gras /* Store YP token if needed. */
5305c007436SBen Gras if (hasyp)
5315c007436SBen Gras putyptoken(&idb);
5325c007436SBen Gras
5335c007436SBen Gras /* Close the insecure database. */
5345c007436SBen Gras closedb(&idb);
5355c007436SBen Gras }
5365c007436SBen Gras
5375c007436SBen Gras /*
5385c007436SBen Gras * If rebuilding the databases, we re-parse the text file and write
5395c007436SBen Gras * the secure entries out in a separate pass.
5405c007436SBen Gras */
5415c007436SBen Gras if (username == NULL) {
5425c007436SBen Gras rewind(fp);
5435c007436SBen Gras for (lineno = 0; scan(fp, &pwd, &flags, &lineno);)
5445c007436SBen Gras putdbents(&sdb, &pwd, pwd.pw_passwd, flags,
5455c007436SBen Gras lineno, dbflg, uid_dbflg);
5465c007436SBen Gras
5475c007436SBen Gras /* Store YP token if needed. */
5485c007436SBen Gras if (hasyp)
5495c007436SBen Gras putyptoken(&sdb);
5505c007436SBen Gras } else if (!found) {
5515c007436SBen Gras mkpw_warning("user `%s' not found in password file", username);
5525c007436SBen Gras bailout();
5535c007436SBen Gras }
5545c007436SBen Gras
5555c007436SBen Gras /* Close the secure database. */
5565c007436SBen Gras closedb(&sdb);
5575c007436SBen Gras
5585c007436SBen Gras /* Install as the real password files. */
5595c007436SBen Gras if (!secureonly)
5605c007436SBen Gras install(idb.dbname, idb.fname);
5615c007436SBen Gras install(sdb.dbname, sdb.fname);
5625c007436SBen Gras
5635c007436SBen Gras /* Install the V7 password file. */
5645c007436SBen Gras if (makeold) {
5655c007436SBen Gras if (fflush(oldfp) == EOF)
5665c007436SBen Gras wr_error(oldpwdfile);
5675c007436SBen Gras if (fclose(oldfp) == EOF)
5685c007436SBen Gras wr_error(oldpwdfile);
5695c007436SBen Gras install(oldpwdfile, _PATH_PASSWD);
5705c007436SBen Gras }
5715c007436SBen Gras
5725c007436SBen Gras /* Set master.passwd permissions, in case caller forgot. */
5735c007436SBen Gras (void)fchmod(fileno(fp), S_IRUSR|S_IWUSR);
5745c007436SBen Gras if (fclose(fp) == EOF)
5755c007436SBen Gras wr_error(pname);
5765c007436SBen Gras
5775c007436SBen Gras /*
5785c007436SBen Gras * Move the temporary master password file LAST -- chpass(1),
5795c007436SBen Gras * passwd(1), vipw(8) and friends all use its existence to block
5805c007436SBen Gras * other incarnations of themselves. The rename means that
5815c007436SBen Gras * everything is unlocked, as the original file can no longer be
5825c007436SBen Gras * accessed.
5835c007436SBen Gras */
5845c007436SBen Gras install(pname, _PATH_MASTERPASSWD);
5855c007436SBen Gras exit(EXIT_SUCCESS);
5865c007436SBen Gras /* NOTREACHED */
5875c007436SBen Gras }
5885c007436SBen Gras
5895c007436SBen Gras int
scan(FILE * fp,struct passwd * pw,int * flags,int * lineno)5905c007436SBen Gras scan(FILE *fp, struct passwd *pw, int *flags, int *lineno)
5915c007436SBen Gras {
5925c007436SBen Gras static char line[LINE_MAX];
5935c007436SBen Gras char *p;
5945c007436SBen Gras int oflags;
5955c007436SBen Gras
5965c007436SBen Gras if (fgets(line, (int)sizeof(line), fp) == NULL)
5975c007436SBen Gras return (0);
5985c007436SBen Gras (*lineno)++;
5995c007436SBen Gras
6005c007436SBen Gras /*
6015c007436SBen Gras * ``... if I swallow anything evil, put your fingers down my
6025c007436SBen Gras * throat...''
6035c007436SBen Gras * -- The Who
6045c007436SBen Gras */
6055c007436SBen Gras if ((p = strchr(line, '\n')) == NULL) {
6065c007436SBen Gras errno = EFTYPE; /* XXX */
6075c007436SBen Gras mkpw_error("%s, %d: line too long", pname, *lineno);
6085c007436SBen Gras }
6095c007436SBen Gras *p = '\0';
6105c007436SBen Gras if (strcmp(line, "+") == 0) {
6115c007436SBen Gras /* pw_scan() can't handle "+" */
6125c007436SBen Gras (void)strcpy(line, "+:::::::::");
6135c007436SBen Gras }
6145c007436SBen Gras oflags = 0;
6155c007436SBen Gras if (!pw_scan(line, pw, &oflags)) {
6165c007436SBen Gras errno = EFTYPE; /* XXX */
6175c007436SBen Gras mkpw_error("%s, %d: Syntax mkpw_error", pname, *lineno);
6185c007436SBen Gras }
6195c007436SBen Gras *flags = oflags;
6205c007436SBen Gras
6215c007436SBen Gras return (1);
6225c007436SBen Gras }
6235c007436SBen Gras
6245c007436SBen Gras void
install(const char * from,const char * to)6255c007436SBen Gras install(const char *from, const char *to)
6265c007436SBen Gras {
6275c007436SBen Gras char buf[MAXPATHLEN];
6285c007436SBen Gras
6295c007436SBen Gras (void)snprintf(buf, sizeof(buf), "%s%s", prefix, to);
6305c007436SBen Gras if (rename(from, buf))
6315c007436SBen Gras mkpw_error("Cannot rename `%s' to `%s'", from, buf);
6325c007436SBen Gras }
6335c007436SBen Gras
6345c007436SBen Gras void
rm(const char * victim)6355c007436SBen Gras rm(const char *victim)
6365c007436SBen Gras {
6375c007436SBen Gras
6385c007436SBen Gras if (unlink(victim) < 0)
6395c007436SBen Gras warn("unlink(%s)", victim);
6405c007436SBen Gras }
6415c007436SBen Gras
6425c007436SBen Gras void
cp(const char * from,const char * to,mode_t mode)6435c007436SBen Gras cp(const char *from, const char *to, mode_t mode)
6445c007436SBen Gras {
6455c007436SBen Gras static char buf[MAXBSIZE];
6465c007436SBen Gras int from_fd, to_fd;
6475c007436SBen Gras ssize_t rcount, wcount;
6485c007436SBen Gras
6495c007436SBen Gras if ((from_fd = open(from, O_RDONLY, 0)) < 0)
6505c007436SBen Gras mkpw_error("Cannot open `%s'", from);
6515c007436SBen Gras if ((to_fd = open(to, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) {
6525c007436SBen Gras (void)close(from_fd);
6535c007436SBen Gras mkpw_error("Cannot open `%s'", to);
6545c007436SBen Gras }
6555c007436SBen Gras while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
6565c007436SBen Gras wcount = write(to_fd, buf, (size_t)rcount);
6575c007436SBen Gras if (rcount != wcount || wcount == -1) {
6585c007436SBen Gras (void)close(from_fd);
6595c007436SBen Gras (void)close(to_fd);
6605c007436SBen Gras goto on_error;
6615c007436SBen Gras }
6625c007436SBen Gras }
6635c007436SBen Gras
6645c007436SBen Gras close(from_fd);
6655c007436SBen Gras if (close(to_fd))
6665c007436SBen Gras goto on_error;
6675c007436SBen Gras if (rcount < 0)
6685c007436SBen Gras goto on_error;
6695c007436SBen Gras return;
6705c007436SBen Gras
6715c007436SBen Gras on_error:
6725c007436SBen Gras mkpw_error("Cannot copy `%s' to `%s'", from, to);
6735c007436SBen Gras }
6745c007436SBen Gras
6755c007436SBen Gras void
wr_error(const char * str)6765c007436SBen Gras wr_error(const char *str)
6775c007436SBen Gras {
6785c007436SBen Gras mkpw_error("Cannot write `%s'", str);
6795c007436SBen Gras }
6805c007436SBen Gras
6815c007436SBen Gras void
mkpw_error(const char * fmt,...)6825c007436SBen Gras mkpw_error(const char *fmt, ...)
6835c007436SBen Gras {
6845c007436SBen Gras va_list ap;
6855c007436SBen Gras va_start(ap, fmt);
6865c007436SBen Gras if (logsyslog) {
6875c007436SBen Gras int sverrno = errno;
6885c007436SBen Gras char efmt[BUFSIZ];
6895c007436SBen Gras snprintf(efmt, sizeof(efmt), "%s (%%m)", fmt);
6905c007436SBen Gras errno = sverrno;
6915c007436SBen Gras vsyslog(LOG_ERR, efmt, ap);
6925c007436SBen Gras } else
6935c007436SBen Gras vwarn(fmt, ap);
6945c007436SBen Gras va_end(ap);
6955c007436SBen Gras bailout();
6965c007436SBen Gras }
6975c007436SBen Gras
6985c007436SBen Gras void
mkpw_warning(const char * fmt,...)6995c007436SBen Gras mkpw_warning(const char *fmt, ...)
7005c007436SBen Gras {
7015c007436SBen Gras va_list ap;
7025c007436SBen Gras va_start(ap, fmt);
7035c007436SBen Gras if (logsyslog)
7045c007436SBen Gras vsyslog(LOG_WARNING, fmt, ap);
7055c007436SBen Gras else
7065c007436SBen Gras vwarnx(fmt, ap);
7075c007436SBen Gras va_end(ap);
7085c007436SBen Gras }
7095c007436SBen Gras
7105c007436SBen Gras void
inconsistency(void)7115c007436SBen Gras inconsistency(void)
7125c007436SBen Gras {
7135c007436SBen Gras
7145c007436SBen Gras mkpw_warning("text files and databases are inconsistent");
7155c007436SBen Gras mkpw_warning("re-build the databases without -u");
7165c007436SBen Gras bailout();
7175c007436SBen Gras }
7185c007436SBen Gras
7195c007436SBen Gras void
bailout(void)7205c007436SBen Gras bailout(void)
7215c007436SBen Gras {
7225c007436SBen Gras
7235c007436SBen Gras if ((clean & FILE_ORIG) != 0)
7245c007436SBen Gras rm(oldpwdfile);
7255c007436SBen Gras if ((clean & FILE_SECURE) != 0)
7265c007436SBen Gras rm(sdb.dbname);
7275c007436SBen Gras if ((clean & FILE_INSECURE) != 0)
7285c007436SBen Gras rm(idb.dbname);
7295c007436SBen Gras
7305c007436SBen Gras exit(EXIT_FAILURE);
7315c007436SBen Gras }
7325c007436SBen Gras
7335c007436SBen Gras uint32_t
getversion(const char * fname)7345c007436SBen Gras getversion(const char *fname)
7355c007436SBen Gras {
7365c007436SBen Gras DBT data, key;
7375c007436SBen Gras int ret;
7385c007436SBen Gras uint32_t version = 0;
7395c007436SBen Gras DB *db;
7405c007436SBen Gras
7415c007436SBen Gras db = dbopen(fname, O_RDONLY, PERM_INSECURE, DB_HASH, NULL);
7425c007436SBen Gras if (db == NULL) {
7435c007436SBen Gras /* If we are building on a separate root, assume version 1 */
744*0a6a1f1dSLionel Sambuc if ((errno == EACCES && prefix[0]) || errno == ENOENT)
7455c007436SBen Gras return 1;
7465c007436SBen Gras mkpw_warning("Cannot open database `%s'", fname);
7475c007436SBen Gras bailout();
7485c007436SBen Gras }
7495c007436SBen Gras key.data = __UNCONST("VERSION");
7505c007436SBen Gras key.size = strlen((const char *)key.data) + 1;
7515c007436SBen Gras
7525c007436SBen Gras switch (ret = (*db->get)(db, &key, &data, 0)) {
7535c007436SBen Gras case -1: /* Error */
7545c007436SBen Gras mkpw_warning("Cannot get VERSION record from database `%s'",
7555c007436SBen Gras fname);
7565c007436SBen Gras goto out;
7575c007436SBen Gras case 0:
7585c007436SBen Gras if (data.size != sizeof(version)) {
7595c007436SBen Gras mkpw_warning("Bad VERSION record in database `%s'", fname);
7605c007436SBen Gras goto out;
7615c007436SBen Gras }
7625c007436SBen Gras (void)memcpy(&version, data.data, sizeof(version));
7635c007436SBen Gras /*FALLTHROUGH*/
7645c007436SBen Gras case 1:
7655c007436SBen Gras if (ret == 1)
7665c007436SBen Gras mkpw_warning("Database `%s' has no version info",
7675c007436SBen Gras fname);
7685c007436SBen Gras (*db->close)(db);
7695c007436SBen Gras return version;
7705c007436SBen Gras default:
7715c007436SBen Gras mkpw_warning("internal mkpw_error db->get returns %d", ret);
7725c007436SBen Gras goto out;
7735c007436SBen Gras }
7745c007436SBen Gras out:
7755c007436SBen Gras (*db->close)(db);
7765c007436SBen Gras bailout();
7775c007436SBen Gras /*NOTREACHED*/
7785c007436SBen Gras }
7795c007436SBen Gras
7805c007436SBen Gras void
setversion(struct pwddb * db)7815c007436SBen Gras setversion(struct pwddb *db)
7825c007436SBen Gras {
7835c007436SBen Gras DBT data, key;
7845c007436SBen Gras key.data = __UNCONST("VERSION");
7855c007436SBen Gras key.size = strlen((const char *)key.data) + 1;
7865c007436SBen Gras
7875c007436SBen Gras data.data = &db->wversion;
7885c007436SBen Gras data.size = sizeof(uint32_t);
7895c007436SBen Gras
7905c007436SBen Gras if ((*db->db->put)(db->db, &key, &data, 0) != 0) {
7915c007436SBen Gras mkpw_warning("Can't write VERSION record to `%s'", db->dbname);
7925c007436SBen Gras bailout();
7935c007436SBen Gras }
7945c007436SBen Gras }
7955c007436SBen Gras
7965c007436SBen Gras
7975c007436SBen Gras /*
7985c007436SBen Gras * Write entries to a database for a single user.
7995c007436SBen Gras *
8005c007436SBen Gras * The databases actually contain three copies of the original data. Each
8015c007436SBen Gras * password file entry is converted into a rough approximation of a ``struct
8025c007436SBen Gras * passwd'', with the strings placed inline. This object is then stored as
8035c007436SBen Gras * the data for three separate keys. The first key * is the pw_name field
8045c007436SBen Gras * prepended by the _PW_KEYBYNAME character. The second key is the pw_uid
8055c007436SBen Gras * field prepended by the _PW_KEYBYUID character. The third key is the line
8065c007436SBen Gras * number in the original file prepended by the _PW_KEYBYNUM character.
8075c007436SBen Gras * (The special characters are prepended to ensure that the keys do not
8085c007436SBen Gras * collide.)
8095c007436SBen Gras */
8105c007436SBen Gras #define COMPACT(e) for (t = e; (*p++ = *t++) != '\0';)
8115c007436SBen Gras
8125c007436SBen Gras void
putdbents(struct pwddb * db,struct passwd * pw,const char * passwd,int flags,int lineno,u_int dbflg,u_int uid_dbflg)8135c007436SBen Gras putdbents(struct pwddb *db, struct passwd *pw, const char *passwd, int flags,
8145c007436SBen Gras int lineno, u_int dbflg, u_int uid_dbflg)
8155c007436SBen Gras {
8165c007436SBen Gras struct passwd pwd;
8175c007436SBen Gras char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024], *p;
8185c007436SBen Gras DBT data, key;
8195c007436SBen Gras const char *t;
8205c007436SBen Gras u_int32_t x;
8215c007436SBen Gras size_t len;
8225c007436SBen Gras
8235c007436SBen Gras (void)memcpy(&pwd, pw, sizeof(pwd));
8245c007436SBen Gras data.data = (u_char *)buf;
8255c007436SBen Gras key.data = (u_char *)tbuf;
8265c007436SBen Gras
8275c007436SBen Gras if (lorder != BYTE_ORDER) {
8285c007436SBen Gras pwd.pw_uid = SWAP(pwd.pw_uid);
8295c007436SBen Gras pwd.pw_gid = SWAP(pwd.pw_gid);
8305c007436SBen Gras }
8315c007436SBen Gras
8325c007436SBen Gras #define WRITEPWTIMEVAR(pwvar) \
8335c007436SBen Gras do { \
8345c007436SBen Gras if (db->wversion == 0 && \
8355c007436SBen Gras /*CONSTCOND*/sizeof(pwvar) == sizeof(uint64_t)) { \
8365c007436SBen Gras uint32_t tmp = (uint32_t)pwvar; \
8375c007436SBen Gras if (lorder != BYTE_ORDER) \
8385c007436SBen Gras tmp = SWAP(tmp); \
8395c007436SBen Gras (void)memmove(p, &tmp, sizeof(tmp)); \
8405c007436SBen Gras p += sizeof(tmp); \
8415c007436SBen Gras } else if (db->wversion == 1 && \
8425c007436SBen Gras /*CONSTCOND*/sizeof(pwvar) == sizeof(uint32_t)) { \
8435c007436SBen Gras uint64_t tmp = pwvar; \
8445c007436SBen Gras if (lorder != BYTE_ORDER) \
8455c007436SBen Gras tmp = SWAP(tmp); \
8465c007436SBen Gras (void)memmove(p, &tmp, sizeof(tmp)); \
8475c007436SBen Gras p += sizeof(tmp); \
8485c007436SBen Gras } else { \
8495c007436SBen Gras if (lorder != BYTE_ORDER) \
8505c007436SBen Gras pwvar = SWAP(pwvar); \
8515c007436SBen Gras (void)memmove(p, &pwvar, sizeof(pwvar)); \
8525c007436SBen Gras p += sizeof(pwvar); \
8535c007436SBen Gras } \
8545c007436SBen Gras } while (/*CONSTCOND*/0)
8555c007436SBen Gras
8565c007436SBen Gras /* Create insecure data. */
8575c007436SBen Gras p = buf;
8585c007436SBen Gras COMPACT(pwd.pw_name);
8595c007436SBen Gras COMPACT(passwd);
8605c007436SBen Gras (void)memmove(p, &pwd.pw_uid, sizeof(pwd.pw_uid));
8615c007436SBen Gras p += sizeof(pwd.pw_uid);
8625c007436SBen Gras (void)memmove(p, &pwd.pw_gid, sizeof(pwd.pw_gid));
8635c007436SBen Gras p += sizeof(pwd.pw_gid);
8645c007436SBen Gras WRITEPWTIMEVAR(pwd.pw_change);
8655c007436SBen Gras COMPACT(pwd.pw_class);
8665c007436SBen Gras COMPACT(pwd.pw_gecos);
8675c007436SBen Gras COMPACT(pwd.pw_dir);
8685c007436SBen Gras COMPACT(pwd.pw_shell);
8695c007436SBen Gras WRITEPWTIMEVAR(pwd.pw_expire);
8705c007436SBen Gras x = flags;
8715c007436SBen Gras if (lorder != BYTE_ORDER)
8725c007436SBen Gras x = SWAP(x);
8735c007436SBen Gras (void)memmove(p, &x, sizeof(x));
8745c007436SBen Gras p += sizeof(x);
8755c007436SBen Gras data.size = p - buf;
8765c007436SBen Gras
8775c007436SBen Gras /* Store insecure by name. */
8785c007436SBen Gras tbuf[0] = _PW_KEYBYNAME;
8795c007436SBen Gras len = strlen(pwd.pw_name);
8805c007436SBen Gras (void)memmove(tbuf + 1, pwd.pw_name, len);
8815c007436SBen Gras key.size = len + 1;
8825c007436SBen Gras if ((*db->db->put)(db->db, &key, &data, dbflg) == -1)
8835c007436SBen Gras wr_error(db->dbname);
8845c007436SBen Gras
8855c007436SBen Gras /* Store insecure by number. */
8865c007436SBen Gras tbuf[0] = _PW_KEYBYNUM;
8875c007436SBen Gras x = lineno;
8885c007436SBen Gras if (lorder != BYTE_ORDER)
8895c007436SBen Gras x = SWAP(x);
8905c007436SBen Gras (void)memmove(tbuf + 1, &x, sizeof(x));
8915c007436SBen Gras key.size = sizeof(x) + 1;
8925c007436SBen Gras if ((*db->db->put)(db->db, &key, &data, dbflg) == -1)
8935c007436SBen Gras wr_error(db->dbname);
8945c007436SBen Gras
8955c007436SBen Gras /* Store insecure by uid. */
8965c007436SBen Gras tbuf[0] = _PW_KEYBYUID;
8975c007436SBen Gras (void)memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
8985c007436SBen Gras key.size = sizeof(pwd.pw_uid) + 1;
8995c007436SBen Gras if ((*db->db->put)(db->db, &key, &data, uid_dbflg) == -1)
9005c007436SBen Gras wr_error(db->dbname);
9015c007436SBen Gras }
9025c007436SBen Gras
9035c007436SBen Gras void
deldbent(struct pwddb * db,int type,void * keyp)9045c007436SBen Gras deldbent(struct pwddb *db, int type, void *keyp)
9055c007436SBen Gras {
9065c007436SBen Gras char tbuf[1024];
9075c007436SBen Gras DBT key;
9085c007436SBen Gras u_int32_t x;
9095c007436SBen Gras size_t len;
9105c007436SBen Gras
9115c007436SBen Gras key.data = (u_char *)tbuf;
9125c007436SBen Gras
9135c007436SBen Gras switch (tbuf[0] = type) {
9145c007436SBen Gras case _PW_KEYBYNAME:
9155c007436SBen Gras len = strlen((char *)keyp);
9165c007436SBen Gras (void)memcpy(tbuf + 1, keyp, len);
9175c007436SBen Gras key.size = len + 1;
9185c007436SBen Gras break;
9195c007436SBen Gras
9205c007436SBen Gras case _PW_KEYBYNUM:
9215c007436SBen Gras case _PW_KEYBYUID:
9225c007436SBen Gras x = *(int *)keyp;
9235c007436SBen Gras if (lorder != BYTE_ORDER)
9245c007436SBen Gras x = SWAP(x);
9255c007436SBen Gras (void)memmove(tbuf + 1, &x, sizeof(x));
9265c007436SBen Gras key.size = sizeof(x) + 1;
9275c007436SBen Gras break;
9285c007436SBen Gras }
9295c007436SBen Gras
9305c007436SBen Gras if ((*db->db->del)(db->db, &key, 0) == -1)
9315c007436SBen Gras wr_error(db->dbname);
9325c007436SBen Gras }
9335c007436SBen Gras
9345c007436SBen Gras int
getdbent(struct pwddb * db,int type,void * keyp,struct passwd ** tpwd)9355c007436SBen Gras getdbent(struct pwddb *db, int type, void *keyp, struct passwd **tpwd)
9365c007436SBen Gras {
9375c007436SBen Gras static char buf[MAX(MAXPATHLEN, LINE_MAX * 2)];
9385c007436SBen Gras static struct passwd pwd;
9395c007436SBen Gras char tbuf[1024], *p;
9405c007436SBen Gras DBT key, data;
9415c007436SBen Gras u_int32_t x;
9425c007436SBen Gras size_t len;
9435c007436SBen Gras int rv;
9445c007436SBen Gras
9455c007436SBen Gras data.data = (u_char *)buf;
9465c007436SBen Gras data.size = sizeof(buf);
9475c007436SBen Gras key.data = (u_char *)tbuf;
9485c007436SBen Gras
9495c007436SBen Gras switch (tbuf[0] = type) {
9505c007436SBen Gras case _PW_KEYBYNAME:
9515c007436SBen Gras len = strlen((char *)keyp);
9525c007436SBen Gras (void)memcpy(tbuf + 1, keyp, len);
9535c007436SBen Gras key.size = len + 1;
9545c007436SBen Gras break;
9555c007436SBen Gras
9565c007436SBen Gras case _PW_KEYBYNUM:
9575c007436SBen Gras case _PW_KEYBYUID:
9585c007436SBen Gras x = *(int *)keyp;
9595c007436SBen Gras if (lorder != BYTE_ORDER)
9605c007436SBen Gras x = SWAP(x);
9615c007436SBen Gras (void)memmove(tbuf + 1, &x, sizeof(x));
9625c007436SBen Gras key.size = sizeof(x) + 1;
9635c007436SBen Gras break;
9645c007436SBen Gras }
9655c007436SBen Gras
9665c007436SBen Gras if ((rv = (*db->db->get)(db->db, &key, &data, 0)) == 1)
9675c007436SBen Gras return (rv);
9685c007436SBen Gras if (rv == -1)
9695c007436SBen Gras mkpw_error("Error getting record from `%s'", db->dbname);
9705c007436SBen Gras
9715c007436SBen Gras p = (char *)data.data;
9725c007436SBen Gras
9735c007436SBen Gras pwd.pw_name = p;
9745c007436SBen Gras while (*p++ != '\0')
9755c007436SBen Gras continue;
9765c007436SBen Gras pwd.pw_passwd = p;
9775c007436SBen Gras while (*p++ != '\0')
9785c007436SBen Gras continue;
9795c007436SBen Gras
9805c007436SBen Gras (void)memcpy(&pwd.pw_uid, p, sizeof(pwd.pw_uid));
9815c007436SBen Gras p += sizeof(pwd.pw_uid);
9825c007436SBen Gras (void)memcpy(&pwd.pw_gid, p, sizeof(pwd.pw_gid));
9835c007436SBen Gras p += sizeof(pwd.pw_gid);
9845c007436SBen Gras
9855c007436SBen Gras #define READPWTIMEVAR(pwvar) \
9865c007436SBen Gras do { \
9875c007436SBen Gras if (db->rversion == 0 && \
9885c007436SBen Gras /*CONSTCOND*/sizeof(pwvar) == sizeof(uint64_t)) { \
9895c007436SBen Gras uint32_t tmp; \
9905c007436SBen Gras (void)memcpy(&tmp, p, sizeof(tmp)); \
9915c007436SBen Gras p += sizeof(tmp); \
9925c007436SBen Gras if (lorder != BYTE_ORDER) \
9935c007436SBen Gras pwvar = SWAP(tmp); \
9945c007436SBen Gras else \
9955c007436SBen Gras pwvar = tmp; \
9965c007436SBen Gras } else if (db->rversion == 1 && \
9975c007436SBen Gras /*CONSTCOND*/sizeof(pwvar) == sizeof(uint32_t)) { \
9985c007436SBen Gras uint64_t tmp; \
9995c007436SBen Gras (void)memcpy(&tmp, p, sizeof(tmp)); \
10005c007436SBen Gras p += sizeof(tmp); \
10015c007436SBen Gras if (lorder != BYTE_ORDER) \
10025c007436SBen Gras pwvar = (uint32_t)SWAP(tmp); \
10035c007436SBen Gras else \
10045c007436SBen Gras pwvar = (uint32_t)tmp; \
10055c007436SBen Gras } else { \
10065c007436SBen Gras (void)memcpy(&pwvar, p, sizeof(pwvar)); \
10075c007436SBen Gras p += sizeof(pwvar); \
10085c007436SBen Gras if (lorder != BYTE_ORDER) \
10095c007436SBen Gras pwvar = SWAP(pwvar); \
10105c007436SBen Gras } \
10115c007436SBen Gras } while (/*CONSTCOND*/0)
10125c007436SBen Gras
10135c007436SBen Gras READPWTIMEVAR(pwd.pw_change);
10145c007436SBen Gras
10155c007436SBen Gras pwd.pw_class = p;
10165c007436SBen Gras while (*p++ != '\0')
10175c007436SBen Gras continue;
10185c007436SBen Gras pwd.pw_gecos = p;
10195c007436SBen Gras while (*p++ != '\0')
10205c007436SBen Gras continue;
10215c007436SBen Gras pwd.pw_dir = p;
10225c007436SBen Gras while (*p++ != '\0')
10235c007436SBen Gras continue;
10245c007436SBen Gras pwd.pw_shell = p;
10255c007436SBen Gras while (*p++ != '\0')
10265c007436SBen Gras continue;
10275c007436SBen Gras
10285c007436SBen Gras READPWTIMEVAR(pwd.pw_expire);
10295c007436SBen Gras
10305c007436SBen Gras if (lorder != BYTE_ORDER) {
10315c007436SBen Gras pwd.pw_uid = SWAP(pwd.pw_uid);
10325c007436SBen Gras pwd.pw_gid = SWAP(pwd.pw_gid);
10335c007436SBen Gras }
10345c007436SBen Gras
10355c007436SBen Gras *tpwd = &pwd;
10365c007436SBen Gras return (0);
10375c007436SBen Gras }
10385c007436SBen Gras
10395c007436SBen Gras void
putyptoken(struct pwddb * db)10405c007436SBen Gras putyptoken(struct pwddb *db)
10415c007436SBen Gras {
10425c007436SBen Gras DBT data, key;
10435c007436SBen Gras
10445c007436SBen Gras key.data = __UNCONST(__yp_token);
10455c007436SBen Gras key.size = strlen(__yp_token);
104684d9c625SLionel Sambuc data.data = NULL;
10475c007436SBen Gras data.size = 0;
10485c007436SBen Gras
10495c007436SBen Gras if ((*db->db->put)(db->db, &key, &data, R_NOOVERWRITE) == -1)
10505c007436SBen Gras wr_error(db->dbname);
10515c007436SBen Gras }
10525c007436SBen Gras
10535c007436SBen Gras void
usage(void)10545c007436SBen Gras usage(void)
10555c007436SBen Gras {
10565c007436SBen Gras
10575c007436SBen Gras (void)fprintf(stderr,
10585c007436SBen Gras "Usage: %s [-BLlpsvw] [-c cachesize] [-d directory] [-u user] "
10595c007436SBen Gras "[-V version] file\n",
10605c007436SBen Gras getprogname());
10615c007436SBen Gras exit(EXIT_FAILURE);
10625c007436SBen Gras }
1063