2009-06-19 20:46:52 +04:00
|
|
|
/* $NetBSD: pwd_mkdb.c,v 1.45 2009/06/19 16:46:52 christos Exp $ */
|
2009-01-16 13:42:36 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2000, 2009 The NetBSD Foundation, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
2000-08-07 17:19:27 +04:00
|
|
|
|
1998-04-14 03:12:45 +04:00
|
|
|
/*
|
1994-08-29 03:32:47 +04:00
|
|
|
* Copyright (c) 1991, 1993, 1994
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
2003-08-07 15:25:11 +04:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
1995-07-28 11:13:04 +04:00
|
|
|
* Portions Copyright(C) 1994, Jason Downs. All rights reserved.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
2003-10-13 19:36:33 +04:00
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
|
|
|
|
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
|
|
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
1993-03-21 12:45:37 +03:00
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2003-10-27 03:12:41 +03:00
|
|
|
#if HAVE_NBTOOL_CONFIG_H
|
|
|
|
#include "nbtool_config.h"
|
2002-01-29 13:20:28 +03:00
|
|
|
#endif
|
|
|
|
|
1997-10-17 16:18:16 +04:00
|
|
|
#include <sys/cdefs.h>
|
2003-10-27 03:12:41 +03:00
|
|
|
#if !defined(lint)
|
2009-01-16 13:42:36 +03:00
|
|
|
__COPYRIGHT("@(#) Copyright (c) 2000, 2009\
|
2008-07-21 17:36:57 +04:00
|
|
|
The NetBSD Foundation, Inc. All rights reserved.\
|
|
|
|
Copyright (c) 1991, 1993, 1994\
|
|
|
|
The Regents of the University of California. All rights reserved.");
|
2000-01-23 22:59:32 +03:00
|
|
|
__SCCSID("from: @(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94");
|
2009-06-19 20:46:52 +04:00
|
|
|
__RCSID("$NetBSD: pwd_mkdb.c,v 1.45 2009/06/19 16:46:52 christos Exp $");
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif /* not lint */
|
|
|
|
|
2004-06-21 02:20:14 +04:00
|
|
|
#if HAVE_NBTOOL_CONFIG_H
|
|
|
|
#include "compat_pwd.h"
|
|
|
|
#else
|
|
|
|
#include <pwd.h>
|
|
|
|
#endif
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/stat.h>
|
Replace local swap16, swap32, and swap64 inline functions with the
NetBSD conventional bswap16, bswap32, and bswap64 functions or macros.
In a non-tools build, include <sys/types.h> and <machine/bswap.h> to
get definitions of these functions. In a tools build, rely on the
functions or macros being provided by nbtool_config.h, but don't incluce
<machine/bswap.h> (which might not exist in a cross build).
This should address a problem building on OpenBSD, which has swap16,
swap32, and swap64 macros that conflicted with the local definitions.
The problem was reported by Alexander Bluhm, but this patch is quite
different from the one he suggested.
2009-03-06 22:05:11 +03:00
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#ifndef HAVE_NBTOOL_CONFIG_H
|
|
|
|
#include <machine/bswap.h>
|
|
|
|
#endif
|
1994-08-29 03:32:47 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <db.h>
|
2002-02-01 01:43:33 +03:00
|
|
|
#include <err.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <errno.h>
|
1994-08-29 03:32:47 +04:00
|
|
|
#include <fcntl.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <limits.h>
|
1994-08-29 03:32:47 +04:00
|
|
|
#include <signal.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <stdio.h>
|
1994-08-29 03:32:47 +04:00
|
|
|
#include <stdlib.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <string.h>
|
1994-08-29 03:32:47 +04:00
|
|
|
#include <unistd.h>
|
2002-02-01 01:43:33 +03:00
|
|
|
#include <util.h>
|
2002-01-29 13:20:28 +03:00
|
|
|
|
2001-08-18 23:29:31 +04:00
|
|
|
#define MAX_CACHESIZE 8*1024*1024
|
|
|
|
#define MIN_CACHESIZE 2*1024*1024
|
|
|
|
|
2000-08-07 17:19:27 +04:00
|
|
|
#define PERM_INSECURE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
|
|
|
|
#define PERM_SECURE (S_IRUSR | S_IWUSR)
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2003-10-27 03:12:41 +03:00
|
|
|
#if HAVE_NBTOOL_CONFIG_H
|
2002-01-29 13:20:28 +03:00
|
|
|
static const char __yp_token[] = "__YP!";
|
|
|
|
#else
|
2001-08-18 23:29:31 +04:00
|
|
|
/* Pull this out of the C library. */
|
1995-07-28 11:13:04 +04:00
|
|
|
extern const char __yp_token[];
|
2002-01-29 13:20:28 +03:00
|
|
|
#endif
|
1995-07-28 11:13:04 +04:00
|
|
|
|
2009-06-18 21:46:24 +04:00
|
|
|
static HASHINFO openinfo = {
|
1994-08-29 03:32:47 +04:00
|
|
|
4096, /* bsize */
|
|
|
|
32, /* ffactor */
|
|
|
|
256, /* nelem */
|
2001-08-18 23:29:31 +04:00
|
|
|
0, /* cachesize */
|
1994-08-29 03:32:47 +04:00
|
|
|
NULL, /* hash() */
|
|
|
|
0 /* lorder */
|
|
|
|
};
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2001-08-18 23:29:31 +04:00
|
|
|
#define FILE_INSECURE 0x01
|
|
|
|
#define FILE_SECURE 0x02
|
|
|
|
#define FILE_ORIG 0x04
|
|
|
|
|
2009-06-19 01:59:24 +04:00
|
|
|
|
|
|
|
struct pwddb {
|
|
|
|
DB *db;
|
|
|
|
char dbname[MAX(MAXPATHLEN, LINE_MAX * 2)];
|
|
|
|
const char *fname;
|
|
|
|
uint32_t rversion;
|
|
|
|
uint32_t wversion;
|
|
|
|
};
|
|
|
|
|
2001-08-18 23:29:31 +04:00
|
|
|
static char *pname; /* password file name */
|
|
|
|
static char prefix[MAXPATHLEN];
|
|
|
|
static char oldpwdfile[MAX(MAXPATHLEN, LINE_MAX * 2)];
|
|
|
|
static int lorder = BYTE_ORDER;
|
|
|
|
static int clean;
|
2009-06-19 01:59:24 +04:00
|
|
|
static int verbose;
|
|
|
|
static int warning;
|
|
|
|
static struct pwddb sdb, idb;
|
|
|
|
|
2001-08-18 23:29:31 +04:00
|
|
|
|
2009-06-18 21:46:24 +04:00
|
|
|
void bailout(void) __attribute__((__noreturn__));
|
2001-08-18 23:29:31 +04:00
|
|
|
void cp(const char *, const char *, mode_t);
|
2009-06-19 19:23:26 +04:00
|
|
|
void deldbent(struct pwddb *, int, void *);
|
2000-08-07 17:19:27 +04:00
|
|
|
void error(const char *);
|
2009-06-19 01:59:24 +04:00
|
|
|
int getdbent(struct pwddb *, int, void *, struct passwd **);
|
2009-06-19 19:23:26 +04:00
|
|
|
void inconsistency(void);
|
2000-08-07 17:19:27 +04:00
|
|
|
void install(const char *, const char *);
|
2001-08-18 23:29:31 +04:00
|
|
|
int main(int, char **);
|
2009-06-19 19:23:26 +04:00
|
|
|
void putdbents(struct pwddb *, struct passwd *, const char *, int, int,
|
|
|
|
u_int, u_int);
|
2009-06-19 01:59:24 +04:00
|
|
|
void putyptoken(struct pwddb *);
|
2000-08-07 17:19:27 +04:00
|
|
|
void rm(const char *);
|
|
|
|
int scan(FILE *, struct passwd *, int *, int *);
|
2009-06-18 21:46:24 +04:00
|
|
|
void usage(void) __attribute__((__noreturn__));
|
2001-08-18 23:29:31 +04:00
|
|
|
void wr_error(const char *);
|
2009-06-18 21:46:24 +04:00
|
|
|
uint32_t getversion(const char *);
|
2009-06-19 01:59:24 +04:00
|
|
|
void setversion(struct pwddb *);
|
2009-01-15 02:18:57 +03:00
|
|
|
|
2009-06-19 19:23:26 +04:00
|
|
|
#ifndef __lint__
|
2009-01-15 02:18:57 +03:00
|
|
|
#define SWAP(sw) \
|
Replace local swap16, swap32, and swap64 inline functions with the
NetBSD conventional bswap16, bswap32, and bswap64 functions or macros.
In a non-tools build, include <sys/types.h> and <machine/bswap.h> to
get definitions of these functions. In a tools build, rely on the
functions or macros being provided by nbtool_config.h, but don't incluce
<machine/bswap.h> (which might not exist in a cross build).
This should address a problem building on OpenBSD, which has swap16,
swap32, and swap64 macros that conflicted with the local definitions.
The problem was reported by Alexander Bluhm, but this patch is quite
different from the one he suggested.
2009-03-06 22:05:11 +03:00
|
|
|
((sizeof(sw) == 2 ? (typeof(sw))bswap16((uint16_t)sw) : \
|
|
|
|
(sizeof(sw) == 4 ? (typeof(sw))bswap32((uint32_t)sw) : \
|
|
|
|
(sizeof(sw) == 8 ? (typeof(sw))bswap64((uint64_t)sw) : (abort(), 0)))))
|
2009-06-19 19:23:26 +04:00
|
|
|
#else
|
|
|
|
#define SWAP(sw) sw
|
|
|
|
#endif
|
1994-08-29 03:32:47 +04:00
|
|
|
|
2009-06-19 01:59:24 +04:00
|
|
|
static void
|
|
|
|
closedb(struct pwddb *db)
|
|
|
|
{
|
|
|
|
if ((*db->db->close)(db->db) < 0)
|
|
|
|
wr_error(db->dbname);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
opendb(struct pwddb *db, const char *dbname, const char *username,
|
2009-06-19 19:23:26 +04:00
|
|
|
uint32_t req_version, int flags, mode_t perm)
|
2009-06-19 01:59:24 +04:00
|
|
|
{
|
|
|
|
char buf[MAXPATHLEN];
|
|
|
|
|
|
|
|
(void)snprintf(db->dbname, sizeof(db->dbname), "%s%s.tmp", prefix,
|
|
|
|
dbname);
|
|
|
|
|
|
|
|
if (username != NULL) {
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)snprintf(buf, sizeof(buf), "%s%s", prefix, dbname);
|
2009-06-19 01:59:24 +04:00
|
|
|
cp(buf, db->dbname, perm);
|
|
|
|
}
|
|
|
|
|
|
|
|
db->db = dbopen(db->dbname, flags, perm, DB_HASH, &openinfo);
|
|
|
|
if (db->db == NULL)
|
|
|
|
error(db->dbname);
|
|
|
|
|
|
|
|
db->fname = dbname;
|
|
|
|
db->rversion = getversion(dbname);
|
|
|
|
if (req_version == ~0U)
|
|
|
|
db->wversion = db->rversion;
|
|
|
|
else
|
|
|
|
db->wversion = req_version;
|
|
|
|
|
|
|
|
if (warning && db->rversion == 0 && db->wversion == 0) {
|
|
|
|
warnx("Database %s is a version %u database.",
|
|
|
|
db->fname, db->rversion);
|
|
|
|
warnx("Use %s -V 1 to upgrade once you've recompiled "
|
|
|
|
"all your binaries.", getprogname());
|
|
|
|
}
|
|
|
|
if (db->wversion != db->rversion) {
|
2009-06-19 19:23:26 +04:00
|
|
|
if (username != NULL) {
|
|
|
|
(void)fprintf(stderr, "%s: you cannot change a single "
|
|
|
|
"record from version %u to version %u\n",
|
|
|
|
getprogname(), db->rversion, db->wversion);
|
|
|
|
bailout();
|
|
|
|
} else if (verbose) {
|
|
|
|
(void)fprintf(stderr, "%s: changing %s from version "
|
2009-06-19 01:59:24 +04:00
|
|
|
"%u to version %u\n",
|
|
|
|
getprogname(), db->fname,
|
|
|
|
db->rversion, db->wversion);
|
|
|
|
}
|
2009-06-19 19:23:26 +04:00
|
|
|
} else {
|
|
|
|
if (verbose)
|
|
|
|
(void)fprintf(stderr, "%s: %s version %u "
|
|
|
|
"requested %u\n", getprogname(), db->fname,
|
|
|
|
db->rversion, db->wversion);
|
2009-06-19 01:59:24 +04:00
|
|
|
}
|
2009-06-19 19:23:26 +04:00
|
|
|
|
2009-06-19 01:59:24 +04:00
|
|
|
setversion(db);
|
|
|
|
}
|
|
|
|
|
1994-08-29 03:32:47 +04:00
|
|
|
int
|
2000-08-07 17:19:27 +04:00
|
|
|
main(int argc, char *argv[])
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2009-06-19 01:59:24 +04:00
|
|
|
int ch, makeold, tfd, lineno, found, rv, hasyp, secureonly;
|
2001-08-18 23:29:31 +04:00
|
|
|
struct passwd pwd, *tpwd;
|
|
|
|
char *username;
|
1994-08-29 03:32:47 +04:00
|
|
|
FILE *fp, *oldfp;
|
|
|
|
sigset_t set;
|
2009-06-19 19:23:26 +04:00
|
|
|
u_int dbflg, uid_dbflg;
|
|
|
|
int newuser, olduid, flags;
|
2001-08-18 23:29:31 +04:00
|
|
|
struct stat st;
|
|
|
|
u_int cachesize;
|
2009-06-19 01:59:24 +04:00
|
|
|
uint32_t req_version;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2000-11-20 17:09:36 +03:00
|
|
|
prefix[0] = '\0';
|
1993-03-21 12:45:37 +03:00
|
|
|
makeold = 0;
|
2001-08-18 23:29:31 +04:00
|
|
|
oldfp = NULL;
|
|
|
|
username = NULL;
|
|
|
|
hasyp = 0;
|
|
|
|
secureonly = 0;
|
2005-06-02 13:18:14 +04:00
|
|
|
found = 0;
|
|
|
|
newuser = 0;
|
2006-09-23 21:17:04 +04:00
|
|
|
cachesize = 0;
|
2009-06-18 21:46:24 +04:00
|
|
|
verbose = 0;
|
2009-06-19 01:59:24 +04:00
|
|
|
warning = 0;
|
|
|
|
req_version = ~0U;
|
2001-08-18 23:29:31 +04:00
|
|
|
|
2009-06-19 01:59:24 +04:00
|
|
|
while ((ch = getopt(argc, argv, "BLc:d:psu:V:vw")) != -1)
|
2001-08-18 23:29:31 +04:00
|
|
|
switch (ch) {
|
|
|
|
case 'B': /* big-endian output */
|
|
|
|
lorder = BIG_ENDIAN;
|
|
|
|
break;
|
|
|
|
case 'L': /* little-endian output */
|
|
|
|
lorder = LITTLE_ENDIAN;
|
|
|
|
break;
|
2006-09-23 21:17:04 +04:00
|
|
|
case 'c':
|
|
|
|
cachesize = atoi(optarg) * 1024 * 1024;
|
|
|
|
break;
|
2000-08-07 17:19:27 +04:00
|
|
|
case 'd': /* set prefix */
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)strlcpy(prefix, optarg, sizeof(prefix));
|
1996-11-22 08:37:29 +03:00
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
case 'p': /* create V7 "file.orig" */
|
|
|
|
makeold = 1;
|
|
|
|
break;
|
2001-08-18 23:29:31 +04:00
|
|
|
case 's': /* modify secure db only */
|
|
|
|
secureonly = 1;
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
2001-08-18 23:29:31 +04:00
|
|
|
case 'u': /* modify one user only */
|
|
|
|
username = optarg;
|
2000-01-23 22:59:32 +03:00
|
|
|
break;
|
2009-06-18 21:46:24 +04:00
|
|
|
case 'V':
|
2009-06-19 01:59:24 +04:00
|
|
|
req_version = (uint32_t)atoi(optarg);
|
2009-06-18 21:46:24 +04:00
|
|
|
if (req_version > 1)
|
|
|
|
err(1, "Unknown version %u\n", req_version);
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
verbose++;
|
2000-01-23 22:59:32 +03:00
|
|
|
break;
|
2009-06-19 01:59:24 +04:00
|
|
|
case 'w':
|
|
|
|
warning++;
|
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
case '?':
|
|
|
|
default:
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
argc -= optind;
|
|
|
|
argv += optind;
|
|
|
|
|
|
|
|
if (argc != 1)
|
|
|
|
usage();
|
2001-08-18 23:29:31 +04:00
|
|
|
if (username != NULL)
|
|
|
|
if (username[0] == '+' || username[0] == '-')
|
|
|
|
usage();
|
|
|
|
if (secureonly)
|
|
|
|
makeold = 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*
|
1994-08-29 03:32:47 +04:00
|
|
|
* This could be changed to allow the user to interrupt.
|
|
|
|
* Probably not worth the effort.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)sigemptyset(&set);
|
|
|
|
(void)sigaddset(&set, SIGTSTP);
|
|
|
|
(void)sigaddset(&set, SIGHUP);
|
|
|
|
(void)sigaddset(&set, SIGINT);
|
|
|
|
(void)sigaddset(&set, SIGQUIT);
|
|
|
|
(void)sigaddset(&set, SIGTERM);
|
1993-03-21 12:45:37 +03:00
|
|
|
(void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
|
|
|
|
|
1994-08-29 03:32:47 +04:00
|
|
|
/* We don't care what the user wants. */
|
|
|
|
(void)umask(0);
|
|
|
|
|
2001-08-18 23:29:31 +04:00
|
|
|
if (username == NULL)
|
|
|
|
flags = O_RDWR | O_CREAT | O_EXCL;
|
|
|
|
else
|
|
|
|
flags = O_RDWR;
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
pname = *argv;
|
|
|
|
/* Open the original password file */
|
2000-08-07 17:19:27 +04:00
|
|
|
if ((fp = fopen(pname, "r")) == NULL)
|
1993-03-21 12:45:37 +03:00
|
|
|
error(pname);
|
|
|
|
|
2000-01-23 22:59:32 +03:00
|
|
|
openinfo.lorder = lorder;
|
|
|
|
|
2001-08-18 23:29:31 +04:00
|
|
|
if (fstat(fileno(fp), &st) == -1)
|
|
|
|
error(pname);
|
|
|
|
|
2006-09-23 21:17:04 +04:00
|
|
|
if (cachesize) {
|
|
|
|
openinfo.cachesize = cachesize;
|
|
|
|
} else {
|
|
|
|
/* Tweak openinfo values for large passwd files. */
|
2009-06-19 19:23:26 +04:00
|
|
|
cachesize = (u_int)(st.st_size * 20);
|
2006-09-23 21:17:04 +04:00
|
|
|
if (cachesize > MAX_CACHESIZE)
|
|
|
|
cachesize = MAX_CACHESIZE;
|
|
|
|
else if (cachesize < MIN_CACHESIZE)
|
|
|
|
cachesize = MIN_CACHESIZE;
|
|
|
|
openinfo.cachesize = cachesize;
|
|
|
|
}
|
2001-08-18 23:29:31 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/* Open the temporary insecure password database. */
|
2001-08-18 23:29:31 +04:00
|
|
|
if (!secureonly) {
|
2009-06-19 01:59:24 +04:00
|
|
|
opendb(&idb, _PATH_MP_DB, username, req_version,
|
|
|
|
flags, PERM_INSECURE);
|
2001-08-18 23:29:31 +04:00
|
|
|
clean |= FILE_INSECURE;
|
|
|
|
}
|
2009-06-19 01:59:24 +04:00
|
|
|
|
2001-08-18 23:29:31 +04:00
|
|
|
|
|
|
|
/* Open the temporary encrypted password database. */
|
2009-06-19 01:59:24 +04:00
|
|
|
opendb(&sdb, _PATH_SMP_DB, username, req_version, flags, PERM_SECURE);
|
2001-08-18 23:29:31 +04:00
|
|
|
clean |= FILE_SECURE;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Open file for old password file. Minor trickiness -- don't want to
|
|
|
|
* chance the file already existing, since someone (stupidly) might
|
|
|
|
* still be using this for permission checking. So, open it first and
|
1994-08-29 03:32:47 +04:00
|
|
|
* fdopen the resulting fd. The resulting file should be readable by
|
|
|
|
* everyone.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
|
|
|
if (makeold) {
|
1998-04-14 03:12:45 +04:00
|
|
|
(void)snprintf(oldpwdfile, sizeof(oldpwdfile), "%s.orig",
|
2000-08-07 17:19:27 +04:00
|
|
|
pname);
|
|
|
|
if ((tfd = open(oldpwdfile, O_WRONLY | O_CREAT | O_EXCL,
|
|
|
|
PERM_INSECURE)) < 0)
|
1998-04-14 03:12:45 +04:00
|
|
|
error(oldpwdfile);
|
2001-08-18 23:29:31 +04:00
|
|
|
clean |= FILE_ORIG;
|
1994-08-29 03:32:47 +04:00
|
|
|
if ((oldfp = fdopen(tfd, "w")) == NULL)
|
1998-04-14 03:12:45 +04:00
|
|
|
error(oldpwdfile);
|
2001-08-18 23:29:31 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (username != NULL) {
|
|
|
|
uid_dbflg = 0;
|
|
|
|
dbflg = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine if this is a new entry.
|
|
|
|
*/
|
2009-06-19 01:59:24 +04:00
|
|
|
if (getdbent(&sdb, _PW_KEYBYNAME, username, &tpwd))
|
2001-08-18 23:29:31 +04:00
|
|
|
newuser = 1;
|
|
|
|
else {
|
|
|
|
newuser = 0;
|
|
|
|
olduid = tpwd->pw_uid;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
uid_dbflg = R_NOOVERWRITE;
|
|
|
|
dbflg = R_NOOVERWRITE;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1995-07-28 11:13:04 +04:00
|
|
|
* If we see something go by that looks like YP, we save a special
|
|
|
|
* pointer record, which if YP is enabled in the C lib, will speed
|
|
|
|
* things up.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2000-08-07 17:19:27 +04:00
|
|
|
for (lineno = 0; scan(fp, &pwd, &flags, &lineno);) {
|
1996-11-25 00:13:27 +03:00
|
|
|
/*
|
2001-08-18 23:29:31 +04:00
|
|
|
* Create original format password file entry.
|
1996-11-25 00:13:27 +03:00
|
|
|
*/
|
1998-04-14 03:12:45 +04:00
|
|
|
if (makeold) {
|
1994-08-29 03:32:47 +04:00
|
|
|
(void)fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n",
|
|
|
|
pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos,
|
|
|
|
pwd.pw_dir, pwd.pw_shell);
|
2000-08-07 17:19:27 +04:00
|
|
|
if (ferror(oldfp))
|
1998-04-14 03:12:45 +04:00
|
|
|
wr_error(oldpwdfile);
|
|
|
|
}
|
2001-08-18 23:29:31 +04:00
|
|
|
|
|
|
|
if (username == NULL) {
|
|
|
|
/* Look like YP? */
|
|
|
|
if (pwd.pw_name[0] == '+' || pwd.pw_name[0] == '-')
|
|
|
|
hasyp++;
|
|
|
|
|
|
|
|
/* Warn about potentially unsafe uid/gid overrides. */
|
|
|
|
if (pwd.pw_name[0] == '+') {
|
|
|
|
if ((flags & _PASSWORD_NOUID) == 0 &&
|
|
|
|
pwd.pw_uid == 0)
|
|
|
|
warnx("line %d: superuser override "
|
|
|
|
"in YP inclusion", lineno);
|
|
|
|
if ((flags & _PASSWORD_NOGID) == 0 &&
|
|
|
|
pwd.pw_gid == 0)
|
|
|
|
warnx("line %d: wheel override "
|
|
|
|
"in YP inclusion", lineno);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write the database entry out. */
|
|
|
|
if (!secureonly)
|
2009-06-19 01:59:24 +04:00
|
|
|
putdbents(&idb, &pwd, "*", flags, lineno, dbflg,
|
|
|
|
uid_dbflg);
|
2001-08-18 23:29:31 +04:00
|
|
|
continue;
|
|
|
|
} else if (strcmp(username, pwd.pw_name) != 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (found) {
|
|
|
|
warnx("user `%s' listed twice in password file",
|
|
|
|
username);
|
|
|
|
bailout();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ensure that the text file and database agree on
|
|
|
|
* which line the record is from.
|
|
|
|
*/
|
2009-06-19 01:59:24 +04:00
|
|
|
rv = getdbent(&sdb, _PW_KEYBYNUM, &lineno, &tpwd);
|
2001-08-18 23:29:31 +04:00
|
|
|
if (newuser) {
|
|
|
|
if (rv == 0)
|
2009-06-19 19:23:26 +04:00
|
|
|
inconsistency();
|
2001-08-18 23:29:31 +04:00
|
|
|
} else if (rv == -1 ||
|
|
|
|
strcmp(username, tpwd->pw_name) != 0)
|
2009-06-19 19:23:26 +04:00
|
|
|
inconsistency();
|
2009-04-18 12:08:36 +04:00
|
|
|
else if ((uid_t)olduid != pwd.pw_uid) {
|
2001-08-18 23:29:31 +04:00
|
|
|
/*
|
|
|
|
* If we're changing UID, remove the BYUID
|
|
|
|
* record for the old UID only if it has the
|
|
|
|
* same username.
|
|
|
|
*/
|
2009-06-19 01:59:24 +04:00
|
|
|
if (!getdbent(&sdb, _PW_KEYBYUID, &olduid, &tpwd)) {
|
2001-08-18 23:29:31 +04:00
|
|
|
if (strcmp(username, tpwd->pw_name) == 0) {
|
|
|
|
if (!secureonly)
|
2009-06-19 01:59:24 +04:00
|
|
|
deldbent(&idb, _PW_KEYBYUID,
|
|
|
|
&olduid);
|
|
|
|
deldbent(&sdb, _PW_KEYBYUID, &olduid);
|
2001-08-18 23:29:31 +04:00
|
|
|
}
|
|
|
|
} else
|
2009-06-19 19:23:26 +04:00
|
|
|
inconsistency();
|
2001-08-18 23:29:31 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If there's an existing BYUID record for the new UID and
|
|
|
|
* the username doesn't match then be sure not to overwrite
|
|
|
|
* it.
|
|
|
|
*/
|
2009-06-19 01:59:24 +04:00
|
|
|
if (!getdbent(&sdb, _PW_KEYBYUID, &pwd.pw_uid, &tpwd))
|
2001-08-18 23:29:31 +04:00
|
|
|
if (strcmp(username, tpwd->pw_name) != 0)
|
|
|
|
uid_dbflg = R_NOOVERWRITE;
|
|
|
|
|
|
|
|
/* Write the database entries out */
|
|
|
|
if (!secureonly)
|
2009-06-19 01:59:24 +04:00
|
|
|
putdbents(&idb, &pwd, "*", flags, lineno, dbflg,
|
|
|
|
uid_dbflg);
|
|
|
|
putdbents(&sdb, &pwd, pwd.pw_passwd, flags, lineno, dbflg,
|
|
|
|
uid_dbflg);
|
2001-08-18 23:29:31 +04:00
|
|
|
|
|
|
|
found = 1;
|
|
|
|
if (!makeold)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!secureonly) {
|
|
|
|
/* Store YP token if needed. */
|
|
|
|
if (hasyp)
|
2009-06-19 01:59:24 +04:00
|
|
|
putyptoken(&idb);
|
2001-08-18 23:29:31 +04:00
|
|
|
|
|
|
|
/* Close the insecure database. */
|
2009-06-19 01:59:24 +04:00
|
|
|
closedb(&idb);
|
2001-08-18 23:29:31 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If rebuilding the databases, we re-parse the text file and write
|
|
|
|
* the secure entries out in a separate pass.
|
|
|
|
*/
|
|
|
|
if (username == NULL) {
|
|
|
|
rewind(fp);
|
|
|
|
for (lineno = 0; scan(fp, &pwd, &flags, &lineno);)
|
2009-06-19 01:59:24 +04:00
|
|
|
putdbents(&sdb, &pwd, pwd.pw_passwd, flags,
|
|
|
|
lineno, dbflg, uid_dbflg);
|
2001-08-18 23:29:31 +04:00
|
|
|
|
|
|
|
/* Store YP token if needed. */
|
|
|
|
if (hasyp)
|
2009-06-19 01:59:24 +04:00
|
|
|
putyptoken(&sdb);
|
2001-08-18 23:29:31 +04:00
|
|
|
} else if (!found) {
|
|
|
|
warnx("user `%s' not found in password file", username);
|
|
|
|
bailout();
|
1994-08-29 03:32:47 +04:00
|
|
|
}
|
1995-07-28 11:13:04 +04:00
|
|
|
|
2001-08-18 23:29:31 +04:00
|
|
|
/* Close the secure database. */
|
2009-06-19 01:59:24 +04:00
|
|
|
closedb(&sdb);
|
2001-08-18 23:29:31 +04:00
|
|
|
|
|
|
|
/* Install as the real password files. */
|
|
|
|
if (!secureonly)
|
2009-06-19 01:59:24 +04:00
|
|
|
install(idb.dbname, idb.fname);
|
|
|
|
install(sdb.dbname, sdb.fname);
|
1995-07-28 11:13:04 +04:00
|
|
|
|
2001-08-18 23:29:31 +04:00
|
|
|
/* Install the V7 password file. */
|
1994-08-29 03:32:47 +04:00
|
|
|
if (makeold) {
|
2000-08-07 17:19:27 +04:00
|
|
|
if (fflush(oldfp) == EOF)
|
1998-04-14 03:12:45 +04:00
|
|
|
wr_error(oldpwdfile);
|
2000-08-07 17:19:27 +04:00
|
|
|
if (fclose(oldfp) == EOF)
|
1998-04-14 03:12:45 +04:00
|
|
|
wr_error(oldpwdfile);
|
2001-08-18 23:29:31 +04:00
|
|
|
install(oldpwdfile, _PATH_PASSWD);
|
1994-08-29 03:32:47 +04:00
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/* Set master.passwd permissions, in case caller forgot. */
|
|
|
|
(void)fchmod(fileno(fp), S_IRUSR|S_IWUSR);
|
2000-08-07 17:19:27 +04:00
|
|
|
if (fclose(fp) == EOF)
|
1998-04-14 03:12:45 +04:00
|
|
|
wr_error(pname);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2000-08-07 17:19:27 +04:00
|
|
|
/*
|
2001-08-18 23:29:31 +04:00
|
|
|
* Move the temporary master password file LAST -- chpass(1),
|
2006-11-25 01:52:16 +03:00
|
|
|
* passwd(1), vipw(8) and friends all use its existence to block
|
2001-08-18 23:29:31 +04:00
|
|
|
* other incarnations of themselves. The rename means that
|
|
|
|
* everything is unlocked, as the original file can no longer be
|
|
|
|
* accessed.
|
2000-08-07 17:19:27 +04:00
|
|
|
*/
|
|
|
|
install(pname, _PATH_MASTERPASSWD);
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
/* NOTREACHED */
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-08-29 03:32:47 +04:00
|
|
|
int
|
2000-08-07 17:19:27 +04:00
|
|
|
scan(FILE *fp, struct passwd *pw, int *flags, int *lineno)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
static char line[LINE_MAX];
|
|
|
|
char *p;
|
2000-01-23 22:59:32 +03:00
|
|
|
int oflags;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2009-06-19 19:23:26 +04:00
|
|
|
if (fgets(line, (int)sizeof(line), fp) == NULL)
|
1994-08-29 03:32:47 +04:00
|
|
|
return (0);
|
2000-08-07 17:19:27 +04:00
|
|
|
(*lineno)++;
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* ``... if I swallow anything evil, put your fingers down my
|
|
|
|
* throat...''
|
|
|
|
* -- The Who
|
|
|
|
*/
|
2000-08-07 17:19:27 +04:00
|
|
|
if ((p = strchr(line, '\n')) == NULL) {
|
1994-08-29 03:32:47 +04:00
|
|
|
warnx("line too long");
|
2000-08-07 17:19:27 +04:00
|
|
|
errno = EFTYPE; /* XXX */
|
|
|
|
error(pname);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
*p = '\0';
|
2009-06-19 19:23:26 +04:00
|
|
|
if (strcmp(line, "+") == 0) {
|
|
|
|
/* pw_scan() can't handle "+" */
|
|
|
|
(void)strcpy(line, "+:::::::::");
|
|
|
|
}
|
2000-01-23 22:59:32 +03:00
|
|
|
oflags = 0;
|
|
|
|
if (!pw_scan(line, pw, &oflags)) {
|
2000-08-07 17:19:27 +04:00
|
|
|
warnx("at line #%d", *lineno);
|
|
|
|
errno = EFTYPE; /* XXX */
|
1993-03-21 12:45:37 +03:00
|
|
|
error(pname);
|
|
|
|
}
|
2000-01-23 22:59:32 +03:00
|
|
|
*flags = oflags;
|
1994-08-29 03:32:47 +04:00
|
|
|
|
|
|
|
return (1);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-08-29 03:32:47 +04:00
|
|
|
void
|
2000-08-07 17:19:27 +04:00
|
|
|
install(const char *from, const char *to)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
char buf[MAXPATHLEN];
|
2006-09-23 21:38:42 +04:00
|
|
|
char errbuf[BUFSIZ];
|
2000-08-07 17:19:27 +04:00
|
|
|
int sverrno;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)snprintf(buf, sizeof(buf), "%s%s", prefix, to);
|
2000-08-07 17:19:27 +04:00
|
|
|
if (rename(from, buf)) {
|
|
|
|
sverrno = errno;
|
2006-09-23 21:38:42 +04:00
|
|
|
(void)snprintf(errbuf, sizeof(errbuf), "%s to %s", from, buf);
|
1993-03-21 12:45:37 +03:00
|
|
|
errno = sverrno;
|
2006-09-23 21:38:42 +04:00
|
|
|
error(errbuf);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-08-18 23:29:31 +04:00
|
|
|
void
|
|
|
|
rm(const char *victim)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (unlink(victim) < 0)
|
|
|
|
warn("unlink(%s)", victim);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
cp(const char *from, const char *to, mode_t mode)
|
|
|
|
{
|
|
|
|
static char buf[MAXBSIZE];
|
2009-06-19 19:23:26 +04:00
|
|
|
int from_fd, to_fd, sverrno;
|
|
|
|
ssize_t rcount, wcount;
|
2001-08-18 23:29:31 +04:00
|
|
|
|
|
|
|
if ((from_fd = open(from, O_RDONLY, 0)) < 0)
|
|
|
|
error(from);
|
|
|
|
if ((to_fd = open(to, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0)
|
|
|
|
error(to);
|
|
|
|
while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
|
2009-06-19 19:23:26 +04:00
|
|
|
wcount = write(to_fd, buf, (size_t)rcount);
|
2001-08-18 23:29:31 +04:00
|
|
|
if (rcount != wcount || wcount == -1) {
|
|
|
|
sverrno = errno;
|
|
|
|
(void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
|
|
|
|
errno = sverrno;
|
|
|
|
error(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rcount < 0) {
|
|
|
|
sverrno = errno;
|
|
|
|
(void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
|
|
|
|
errno = sverrno;
|
|
|
|
error(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-04-14 03:12:45 +04:00
|
|
|
void
|
2000-08-07 17:19:27 +04:00
|
|
|
wr_error(const char *str)
|
1998-04-14 03:12:45 +04:00
|
|
|
{
|
2000-08-07 17:19:27 +04:00
|
|
|
char errbuf[BUFSIZ];
|
|
|
|
int sverrno;
|
|
|
|
|
|
|
|
sverrno = errno;
|
1998-04-14 03:12:45 +04:00
|
|
|
|
|
|
|
(void)snprintf(errbuf, sizeof(errbuf),
|
2000-08-07 17:19:27 +04:00
|
|
|
"attempt to write %s failed", str);
|
1998-04-14 03:12:45 +04:00
|
|
|
|
|
|
|
errno = sverrno;
|
|
|
|
error(errbuf);
|
|
|
|
}
|
|
|
|
|
1994-08-29 03:32:47 +04:00
|
|
|
void
|
2000-08-07 17:19:27 +04:00
|
|
|
error(const char *str)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-29 03:32:47 +04:00
|
|
|
|
2000-08-07 17:19:27 +04:00
|
|
|
warn("%s", str);
|
2001-08-18 23:29:31 +04:00
|
|
|
bailout();
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1998-04-14 03:12:45 +04:00
|
|
|
void
|
2009-06-19 19:23:26 +04:00
|
|
|
inconsistency(void)
|
1998-04-14 03:12:45 +04:00
|
|
|
{
|
2000-08-07 17:19:27 +04:00
|
|
|
|
2001-08-18 23:29:31 +04:00
|
|
|
warnx("text files and databases are inconsistent");
|
|
|
|
warnx("re-build the databases without -u");
|
|
|
|
bailout();
|
1998-04-14 03:12:45 +04:00
|
|
|
}
|
|
|
|
|
1994-08-29 03:32:47 +04:00
|
|
|
void
|
2001-08-18 23:29:31 +04:00
|
|
|
bailout(void)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2000-08-07 17:19:27 +04:00
|
|
|
|
2001-08-18 23:29:31 +04:00
|
|
|
if ((clean & FILE_ORIG) != 0)
|
1998-04-14 03:12:45 +04:00
|
|
|
rm(oldpwdfile);
|
2001-08-18 23:29:31 +04:00
|
|
|
if ((clean & FILE_SECURE) != 0)
|
2009-06-19 01:59:24 +04:00
|
|
|
rm(sdb.dbname);
|
2001-08-18 23:29:31 +04:00
|
|
|
if ((clean & FILE_INSECURE) != 0)
|
2009-06-19 01:59:24 +04:00
|
|
|
rm(idb.dbname);
|
2001-08-18 23:29:31 +04:00
|
|
|
|
|
|
|
exit(EXIT_FAILURE);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2009-06-18 21:46:24 +04:00
|
|
|
uint32_t
|
|
|
|
getversion(const char *fname)
|
2009-01-15 02:18:57 +03:00
|
|
|
{
|
|
|
|
DBT data, key;
|
2009-01-16 13:42:36 +03:00
|
|
|
int ret;
|
2009-06-18 21:46:24 +04:00
|
|
|
uint32_t version = 0;
|
2009-06-19 01:59:24 +04:00
|
|
|
DB *db;
|
2009-01-15 02:18:57 +03:00
|
|
|
|
2009-06-19 01:59:24 +04:00
|
|
|
db = dbopen(fname, O_RDONLY, PERM_INSECURE, DB_HASH, NULL);
|
|
|
|
if (db == NULL) {
|
2009-06-19 20:46:52 +04:00
|
|
|
/* If we are building on a separate root, assume version 1 */
|
|
|
|
if (errno == EACCES && prefix[0])
|
|
|
|
return 1;
|
2009-06-18 21:46:24 +04:00
|
|
|
warn("Cannot open database %s", fname);
|
2009-01-16 13:42:36 +03:00
|
|
|
bailout();
|
|
|
|
}
|
2009-06-18 21:46:24 +04:00
|
|
|
key.data = __UNCONST("VERSION");
|
|
|
|
key.size = strlen((const char *)key.data) + 1;
|
2009-01-16 13:42:36 +03:00
|
|
|
|
2009-06-19 01:59:24 +04:00
|
|
|
switch (ret = (*db->get)(db, &key, &data, 0)) {
|
2009-06-18 21:46:24 +04:00
|
|
|
case -1: /* Error */
|
|
|
|
warn("Cannot get VERSION record from database");
|
|
|
|
goto out;
|
|
|
|
case 0:
|
|
|
|
if (data.size != sizeof(version)) {
|
|
|
|
warnx("Bad VERSION record in database");
|
|
|
|
goto out;
|
|
|
|
}
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memcpy(&version, data.data, sizeof(version));
|
2009-06-18 21:46:24 +04:00
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case 1:
|
2009-06-19 01:59:24 +04:00
|
|
|
if (ret == 1)
|
|
|
|
warnx("Database %s has no version info", fname);
|
|
|
|
(*db->close)(db);
|
2009-06-18 21:46:24 +04:00
|
|
|
return version;
|
|
|
|
default:
|
|
|
|
warnx("internal error db->get returns %d", ret);
|
|
|
|
goto out;
|
2009-01-16 13:42:36 +03:00
|
|
|
}
|
2009-06-18 21:46:24 +04:00
|
|
|
out:
|
2009-06-19 01:59:24 +04:00
|
|
|
(*db->close)(db);
|
2009-06-18 21:46:24 +04:00
|
|
|
bailout();
|
2009-06-19 19:23:26 +04:00
|
|
|
/*NOTREACHED*/
|
2009-01-16 13:42:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-06-19 01:59:24 +04:00
|
|
|
setversion(struct pwddb *db)
|
2009-01-16 13:42:36 +03:00
|
|
|
{
|
|
|
|
DBT data, key;
|
|
|
|
key.data = __UNCONST("VERSION");
|
|
|
|
key.size = strlen((const char *)key.data) + 1;
|
|
|
|
|
2009-06-19 01:59:24 +04:00
|
|
|
data.data = &db->wversion;
|
2009-01-15 02:18:57 +03:00
|
|
|
data.size = sizeof(uint32_t);
|
|
|
|
|
2009-06-19 02:13:56 +04:00
|
|
|
if ((*db->db->put)(db->db, &key, &data, 0) != 0) {
|
2009-06-19 01:59:24 +04:00
|
|
|
warn("Can't write VERSION record to %s", db->dbname);
|
|
|
|
bailout();
|
|
|
|
}
|
2009-01-15 02:18:57 +03:00
|
|
|
}
|
|
|
|
|
2009-06-18 21:46:24 +04:00
|
|
|
|
2000-08-07 17:19:27 +04:00
|
|
|
/*
|
|
|
|
* Write entries to a database for a single user.
|
|
|
|
*
|
|
|
|
* The databases actually contain three copies of the original data. Each
|
|
|
|
* password file entry is converted into a rough approximation of a ``struct
|
|
|
|
* passwd'', with the strings placed inline. This object is then stored as
|
|
|
|
* the data for three separate keys. The first key * is the pw_name field
|
|
|
|
* prepended by the _PW_KEYBYNAME character. The second key is the pw_uid
|
|
|
|
* field prepended by the _PW_KEYBYUID character. The third key is the line
|
|
|
|
* number in the original file prepended by the _PW_KEYBYNUM character.
|
|
|
|
* (The special characters are prepended to ensure that the keys do not
|
|
|
|
* collide.)
|
|
|
|
*/
|
|
|
|
#define COMPACT(e) for (t = e; (*p++ = *t++) != '\0';)
|
|
|
|
|
|
|
|
void
|
2009-06-19 01:59:24 +04:00
|
|
|
putdbents(struct pwddb *db, struct passwd *pw, const char *passwd, int flags,
|
2009-06-19 19:23:26 +04:00
|
|
|
int lineno, u_int dbflg, u_int uid_dbflg)
|
2000-08-07 17:19:27 +04:00
|
|
|
{
|
|
|
|
struct passwd pwd;
|
|
|
|
char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024], *p;
|
|
|
|
DBT data, key;
|
|
|
|
const char *t;
|
|
|
|
u_int32_t x;
|
2009-06-19 19:23:26 +04:00
|
|
|
size_t len;
|
2000-08-07 17:19:27 +04:00
|
|
|
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memcpy(&pwd, pw, sizeof(pwd));
|
2000-08-07 17:19:27 +04:00
|
|
|
data.data = (u_char *)buf;
|
|
|
|
key.data = (u_char *)tbuf;
|
|
|
|
|
|
|
|
if (lorder != BYTE_ORDER) {
|
2009-01-15 02:18:57 +03:00
|
|
|
pwd.pw_uid = SWAP(pwd.pw_uid);
|
|
|
|
pwd.pw_gid = SWAP(pwd.pw_gid);
|
2000-08-07 17:19:27 +04:00
|
|
|
}
|
|
|
|
|
2009-06-18 21:46:24 +04:00
|
|
|
#define WRITEPWTIMEVAR(pwvar) \
|
|
|
|
do { \
|
2009-06-19 01:59:24 +04:00
|
|
|
if (db->wversion == 0 && \
|
2009-06-19 19:23:26 +04:00
|
|
|
/*CONSTCOND*/sizeof(pwvar) == sizeof(uint64_t)) { \
|
2009-06-18 21:46:24 +04:00
|
|
|
uint32_t tmp = (uint32_t)pwvar; \
|
|
|
|
if (lorder != BYTE_ORDER) \
|
|
|
|
tmp = SWAP(tmp); \
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memmove(p, &tmp, sizeof(tmp)); \
|
2009-06-18 21:46:24 +04:00
|
|
|
p += sizeof(tmp); \
|
2009-06-19 01:59:24 +04:00
|
|
|
} else if (db->wversion == 1 && \
|
2009-06-19 19:23:26 +04:00
|
|
|
/*CONSTCOND*/sizeof(pwvar) == sizeof(uint32_t)) { \
|
2009-06-18 21:46:24 +04:00
|
|
|
uint64_t tmp = pwvar; \
|
|
|
|
if (lorder != BYTE_ORDER) \
|
|
|
|
tmp = SWAP(tmp); \
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memmove(p, &tmp, sizeof(tmp)); \
|
2009-06-18 21:46:24 +04:00
|
|
|
p += sizeof(tmp); \
|
|
|
|
} else { \
|
|
|
|
if (lorder != BYTE_ORDER) \
|
|
|
|
pwvar = SWAP(pwvar); \
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memmove(p, &pwvar, sizeof(pwvar)); \
|
2009-06-18 21:46:24 +04:00
|
|
|
p += sizeof(pwvar); \
|
|
|
|
} \
|
|
|
|
} while (/*CONSTCOND*/0)
|
|
|
|
|
2000-08-07 17:19:27 +04:00
|
|
|
/* Create insecure data. */
|
|
|
|
p = buf;
|
|
|
|
COMPACT(pwd.pw_name);
|
|
|
|
COMPACT(passwd);
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memmove(p, &pwd.pw_uid, sizeof(pwd.pw_uid));
|
2000-08-07 17:19:27 +04:00
|
|
|
p += sizeof(pwd.pw_uid);
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memmove(p, &pwd.pw_gid, sizeof(pwd.pw_gid));
|
2000-08-07 17:19:27 +04:00
|
|
|
p += sizeof(pwd.pw_gid);
|
2009-06-18 21:46:24 +04:00
|
|
|
WRITEPWTIMEVAR(pwd.pw_change);
|
2000-08-07 17:19:27 +04:00
|
|
|
COMPACT(pwd.pw_class);
|
|
|
|
COMPACT(pwd.pw_gecos);
|
|
|
|
COMPACT(pwd.pw_dir);
|
|
|
|
COMPACT(pwd.pw_shell);
|
2009-06-18 21:46:24 +04:00
|
|
|
WRITEPWTIMEVAR(pwd.pw_expire);
|
2000-08-07 17:19:27 +04:00
|
|
|
x = flags;
|
|
|
|
if (lorder != BYTE_ORDER)
|
2009-01-15 02:18:57 +03:00
|
|
|
x = SWAP(x);
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memmove(p, &x, sizeof(x));
|
2000-08-07 17:19:27 +04:00
|
|
|
p += sizeof(flags);
|
|
|
|
data.size = p - buf;
|
|
|
|
|
|
|
|
/* Store insecure by name. */
|
|
|
|
tbuf[0] = _PW_KEYBYNAME;
|
|
|
|
len = strlen(pwd.pw_name);
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memmove(tbuf + 1, pwd.pw_name, len);
|
2000-08-07 17:19:27 +04:00
|
|
|
key.size = len + 1;
|
2009-06-19 01:59:24 +04:00
|
|
|
if ((*db->db->put)(db->db, &key, &data, dbflg) == -1)
|
|
|
|
wr_error(db->dbname);
|
2001-08-18 23:29:31 +04:00
|
|
|
|
2000-08-07 17:19:27 +04:00
|
|
|
/* Store insecure by number. */
|
|
|
|
tbuf[0] = _PW_KEYBYNUM;
|
|
|
|
x = lineno;
|
|
|
|
if (lorder != BYTE_ORDER)
|
2009-01-15 02:18:57 +03:00
|
|
|
x = SWAP(x);
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memmove(tbuf + 1, &x, sizeof(x));
|
2000-08-07 17:19:27 +04:00
|
|
|
key.size = sizeof(x) + 1;
|
2009-06-19 01:59:24 +04:00
|
|
|
if ((*db->db->put)(db->db, &key, &data, dbflg) == -1)
|
|
|
|
wr_error(db->dbname);
|
2000-08-07 17:19:27 +04:00
|
|
|
|
|
|
|
/* Store insecure by uid. */
|
|
|
|
tbuf[0] = _PW_KEYBYUID;
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
|
2000-08-07 17:19:27 +04:00
|
|
|
key.size = sizeof(pwd.pw_uid) + 1;
|
2009-06-19 01:59:24 +04:00
|
|
|
if ((*db->db->put)(db->db, &key, &data, uid_dbflg) == -1)
|
|
|
|
wr_error(db->dbname);
|
2001-08-18 23:29:31 +04:00
|
|
|
}
|
|
|
|
|
2009-06-19 19:23:26 +04:00
|
|
|
void
|
2009-06-19 01:59:24 +04:00
|
|
|
deldbent(struct pwddb *db, int type, void *keyp)
|
2001-08-18 23:29:31 +04:00
|
|
|
{
|
|
|
|
char tbuf[1024];
|
|
|
|
DBT key;
|
|
|
|
u_int32_t x;
|
2009-06-19 19:23:26 +04:00
|
|
|
size_t len;
|
2001-08-18 23:29:31 +04:00
|
|
|
|
|
|
|
key.data = (u_char *)tbuf;
|
|
|
|
|
|
|
|
switch (tbuf[0] = type) {
|
|
|
|
case _PW_KEYBYNAME:
|
|
|
|
len = strlen((char *)keyp);
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memcpy(tbuf + 1, keyp, len);
|
2001-08-18 23:29:31 +04:00
|
|
|
key.size = len + 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case _PW_KEYBYNUM:
|
|
|
|
case _PW_KEYBYUID:
|
|
|
|
x = *(int *)keyp;
|
|
|
|
if (lorder != BYTE_ORDER)
|
2009-01-15 02:18:57 +03:00
|
|
|
x = SWAP(x);
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memmove(tbuf + 1, &x, sizeof(x));
|
2001-08-18 23:29:31 +04:00
|
|
|
key.size = sizeof(x) + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-06-19 19:23:26 +04:00
|
|
|
if ((*db->db->del)(db->db, &key, 0) == -1)
|
2009-06-19 01:59:24 +04:00
|
|
|
wr_error(db->dbname);
|
2001-08-18 23:29:31 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2009-06-19 01:59:24 +04:00
|
|
|
getdbent(struct pwddb *db, int type, void *keyp, struct passwd **tpwd)
|
2001-08-18 23:29:31 +04:00
|
|
|
{
|
|
|
|
static char buf[MAX(MAXPATHLEN, LINE_MAX * 2)];
|
|
|
|
static struct passwd pwd;
|
|
|
|
char tbuf[1024], *p;
|
|
|
|
DBT key, data;
|
|
|
|
u_int32_t x;
|
2009-06-19 19:23:26 +04:00
|
|
|
size_t len;
|
|
|
|
int rv;
|
2001-08-18 23:29:31 +04:00
|
|
|
|
|
|
|
data.data = (u_char *)buf;
|
|
|
|
data.size = sizeof(buf);
|
|
|
|
key.data = (u_char *)tbuf;
|
|
|
|
|
|
|
|
switch (tbuf[0] = type) {
|
|
|
|
case _PW_KEYBYNAME:
|
|
|
|
len = strlen((char *)keyp);
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memcpy(tbuf + 1, keyp, len);
|
2001-08-18 23:29:31 +04:00
|
|
|
key.size = len + 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case _PW_KEYBYNUM:
|
|
|
|
case _PW_KEYBYUID:
|
|
|
|
x = *(int *)keyp;
|
|
|
|
if (lorder != BYTE_ORDER)
|
2009-01-15 02:18:57 +03:00
|
|
|
x = SWAP(x);
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memmove(tbuf + 1, &x, sizeof(x));
|
2001-08-18 23:29:31 +04:00
|
|
|
key.size = sizeof(x) + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-06-19 01:59:24 +04:00
|
|
|
if ((rv = (*db->db->get)(db->db, &key, &data, 0)) == 1)
|
2001-08-18 23:29:31 +04:00
|
|
|
return (rv);
|
|
|
|
if (rv == -1)
|
2009-06-19 01:59:24 +04:00
|
|
|
error(db->dbname);
|
2001-08-18 23:29:31 +04:00
|
|
|
|
|
|
|
p = (char *)data.data;
|
|
|
|
|
|
|
|
pwd.pw_name = p;
|
|
|
|
while (*p++ != '\0')
|
2009-06-18 21:46:24 +04:00
|
|
|
continue;
|
2001-08-18 23:29:31 +04:00
|
|
|
pwd.pw_passwd = p;
|
|
|
|
while (*p++ != '\0')
|
2009-06-18 21:46:24 +04:00
|
|
|
continue;
|
2001-08-18 23:29:31 +04:00
|
|
|
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memcpy(&pwd.pw_uid, p, sizeof(pwd.pw_uid));
|
2001-08-18 23:29:31 +04:00
|
|
|
p += sizeof(pwd.pw_uid);
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memcpy(&pwd.pw_gid, p, sizeof(pwd.pw_gid));
|
2001-08-18 23:29:31 +04:00
|
|
|
p += sizeof(pwd.pw_gid);
|
2009-06-18 21:46:24 +04:00
|
|
|
|
|
|
|
#define READPWTIMEVAR(pwvar) \
|
|
|
|
do { \
|
2009-06-19 01:59:24 +04:00
|
|
|
if (db->rversion == 0 && \
|
2009-06-19 19:23:26 +04:00
|
|
|
/*CONSTCOND*/sizeof(pwvar) == sizeof(uint64_t)) { \
|
2009-06-18 21:46:24 +04:00
|
|
|
uint32_t tmp; \
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memcpy(&tmp, p, sizeof(tmp)); \
|
2009-06-18 21:46:24 +04:00
|
|
|
p += sizeof(tmp); \
|
|
|
|
if (lorder != BYTE_ORDER) \
|
|
|
|
pwvar = SWAP(tmp); \
|
|
|
|
else \
|
|
|
|
pwvar = tmp; \
|
2009-06-19 01:59:24 +04:00
|
|
|
} else if (db->rversion == 1 && \
|
2009-06-19 19:23:26 +04:00
|
|
|
/*CONSTCOND*/sizeof(pwvar) == sizeof(uint32_t)) { \
|
2009-06-18 21:46:24 +04:00
|
|
|
uint64_t tmp; \
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memcpy(&tmp, p, sizeof(tmp)); \
|
2009-06-18 21:46:24 +04:00
|
|
|
p += sizeof(tmp); \
|
|
|
|
if (lorder != BYTE_ORDER) \
|
|
|
|
pwvar = (uint32_t)SWAP(tmp); \
|
|
|
|
else \
|
|
|
|
pwvar = (uint32_t)tmp; \
|
|
|
|
} else { \
|
2009-06-19 19:23:26 +04:00
|
|
|
(void)memcpy(&pwvar, p, sizeof(pwvar)); \
|
2009-06-18 21:46:24 +04:00
|
|
|
p += sizeof(pwvar); \
|
|
|
|
if (lorder != BYTE_ORDER) \
|
|
|
|
pwvar = SWAP(pwvar); \
|
|
|
|
} \
|
|
|
|
} while (/*CONSTCOND*/0)
|
|
|
|
|
|
|
|
READPWTIMEVAR(pwd.pw_change);
|
2001-08-18 23:29:31 +04:00
|
|
|
|
|
|
|
pwd.pw_class = p;
|
|
|
|
while (*p++ != '\0')
|
2009-06-18 21:46:24 +04:00
|
|
|
continue;
|
2001-08-18 23:29:31 +04:00
|
|
|
pwd.pw_gecos = p;
|
|
|
|
while (*p++ != '\0')
|
2009-06-18 21:46:24 +04:00
|
|
|
continue;
|
2001-08-18 23:29:31 +04:00
|
|
|
pwd.pw_dir = p;
|
|
|
|
while (*p++ != '\0')
|
2009-06-18 21:46:24 +04:00
|
|
|
continue;
|
2001-08-18 23:29:31 +04:00
|
|
|
pwd.pw_shell = p;
|
|
|
|
while (*p++ != '\0')
|
2009-06-18 21:46:24 +04:00
|
|
|
continue;
|
2001-08-18 23:29:31 +04:00
|
|
|
|
2009-06-18 21:46:24 +04:00
|
|
|
READPWTIMEVAR(pwd.pw_expire);
|
2001-08-18 23:29:31 +04:00
|
|
|
|
|
|
|
if (lorder != BYTE_ORDER) {
|
2009-01-15 02:18:57 +03:00
|
|
|
pwd.pw_uid = SWAP(pwd.pw_uid);
|
|
|
|
pwd.pw_gid = SWAP(pwd.pw_gid);
|
2001-08-18 23:29:31 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
*tpwd = &pwd;
|
|
|
|
return (0);
|
2000-08-07 17:19:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-06-19 01:59:24 +04:00
|
|
|
putyptoken(struct pwddb *db)
|
2000-08-07 17:19:27 +04:00
|
|
|
{
|
|
|
|
DBT data, key;
|
|
|
|
|
2009-04-18 12:08:36 +04:00
|
|
|
key.data = __UNCONST(__yp_token);
|
2000-08-07 17:19:27 +04:00
|
|
|
key.size = strlen(__yp_token);
|
|
|
|
data.data = (u_char *)NULL;
|
|
|
|
data.size = 0;
|
|
|
|
|
2009-06-19 01:59:24 +04:00
|
|
|
if ((*db->db->put)(db->db, &key, &data, R_NOOVERWRITE) == -1)
|
|
|
|
wr_error(db->dbname);
|
2000-08-07 17:19:27 +04:00
|
|
|
}
|
|
|
|
|
1994-08-29 03:32:47 +04:00
|
|
|
void
|
2000-08-07 17:19:27 +04:00
|
|
|
usage(void)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-29 03:32:47 +04:00
|
|
|
|
2001-08-18 23:29:31 +04:00
|
|
|
(void)fprintf(stderr,
|
2009-06-19 01:59:24 +04:00
|
|
|
"Usage: %s [-BLpsvw] [-c cachesize] [-d directory] [-u user] "
|
2009-06-18 21:46:24 +04:00
|
|
|
"[-V version] file\n",
|
|
|
|
getprogname());
|
2000-08-07 17:19:27 +04:00
|
|
|
exit(EXIT_FAILURE);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|