1 /* $NetBSD: pwd_mkdb.c,v 1.56 2012/11/26 20:13:54 pooka Exp $ */
4 * Copyright (c) 2000, 2009 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
30 * Copyright (c) 1991, 1993, 1994
31 * The Regents of the University of California. All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * Portions Copyright(C) 1994, Jason Downs. All rights reserved.
61 * Redistribution and use in source and binary forms, with or without
62 * modification, are permitted provided that the following conditions
64 * 1. Redistributions of source code must retain the above copyright
65 * notice, this list of conditions and the following disclaimer.
66 * 2. Redistributions in binary form must reproduce the above copyright
67 * notice, this list of conditions and the following disclaimer in the
68 * documentation and/or other materials provided with the distribution.
70 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
71 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
72 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
73 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
74 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
75 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
76 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
77 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
78 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
79 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
83 #if HAVE_NBTOOL_CONFIG_H
84 #include "nbtool_config.h"
87 #include <sys/cdefs.h>
89 __COPYRIGHT("@(#) Copyright (c) 2000, 2009\
90 The NetBSD Foundation, Inc. All rights reserved.\
91 Copyright (c) 1991, 1993, 1994\
92 The Regents of the University of California. All rights reserved.");
93 __RCSID("$NetBSD: pwd_mkdb.c,v 1.56 2012/11/26 20:13:54 pooka Exp $");
96 #if HAVE_NBTOOL_CONFIG_H
97 #include "compat_pwd.h"
102 #include <sys/param.h>
103 #include <sys/stat.h>
104 #include <sys/types.h>
106 #ifndef HAVE_NBTOOL_CONFIG_H
107 #include <machine/bswap.h>
123 #ifndef HAVE_NBTOOL_CONFIG_H
127 #define MAX_CACHESIZE 8*1024*1024
128 #define MIN_CACHESIZE 2*1024*1024
130 #define PERM_INSECURE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
131 #define PERM_SECURE (S_IRUSR | S_IWUSR)
133 #if HAVE_NBTOOL_CONFIG_H
134 static const char __yp_token
[] = "__YP!";
136 /* Pull this out of the C library. */
137 extern const char __yp_token
[];
140 static HASHINFO openinfo
= {
149 #define FILE_INSECURE 0x01
150 #define FILE_SECURE 0x02
151 #define FILE_ORIG 0x04
156 char dbname
[MAX(MAXPATHLEN
, LINE_MAX
* 2)];
162 static char *pname
; /* password file name */
163 static char prefix
[MAXPATHLEN
];
164 static char oldpwdfile
[MAX(MAXPATHLEN
, LINE_MAX
* 2)];
165 static int lorder
= BYTE_ORDER
;
166 static int logsyslog
;
170 static struct pwddb sdb
, idb
;
173 void bailout(void) __dead
;
174 void cp(const char *, const char *, mode_t
);
175 void deldbent(struct pwddb
*, int, void *);
176 void mkpw_error(const char *, ...) __dead
;
177 void mkpw_warning(const char *, ...);
178 int getdbent(struct pwddb
*, int, void *, struct passwd
**);
179 void inconsistency(void) __dead
;
180 void install(const char *, const char *);
181 int main(int, char **);
182 void putdbents(struct pwddb
*, struct passwd
*, const char *, int, int,
184 void putyptoken(struct pwddb
*);
185 void rm(const char *);
186 int scan(FILE *, struct passwd
*, int *, int *);
187 void usage(void) __dead
;
188 void wr_error(const char *) __dead
;
189 uint32_t getversion(const char *);
190 void setversion(struct pwddb
*);
194 ((sizeof(sw) == 2 ? (typeof(sw))bswap16((uint16_t)sw) : \
195 (sizeof(sw) == 4 ? (typeof(sw))bswap32((uint32_t)sw) : \
196 (sizeof(sw) == 8 ? (typeof(sw))bswap64((uint64_t)sw) : (abort(), 0)))))
202 closedb(struct pwddb
*db
)
204 if ((*db
->db
->close
)(db
->db
) < 0)
205 wr_error(db
->dbname
);
209 opendb(struct pwddb
*db
, const char *dbname
, const char *username
,
210 uint32_t req_version
, int flags
, mode_t perm
)
212 char buf
[MAXPATHLEN
];
214 (void)snprintf(db
->dbname
, sizeof(db
->dbname
), "%s%s.tmp", prefix
,
217 if (username
!= NULL
) {
218 (void)snprintf(buf
, sizeof(buf
), "%s%s", prefix
, dbname
);
219 cp(buf
, db
->dbname
, perm
);
222 db
->db
= dbopen(db
->dbname
, flags
, perm
, DB_HASH
, &openinfo
);
224 mkpw_error("Cannot open `%s'", db
->dbname
);
227 db
->rversion
= getversion(dbname
);
228 if (req_version
== ~0U)
229 db
->wversion
= db
->rversion
;
231 db
->wversion
= req_version
;
233 if (warning
&& db
->rversion
== 0 && db
->wversion
== 0) {
234 mkpw_warning("Database %s is a version %u database.",
235 db
->fname
, db
->rversion
);
236 mkpw_warning("Use %s -V 1 to upgrade once you've recompiled "
237 "all your binaries.", getprogname());
239 if (db
->wversion
!= db
->rversion
) {
240 if (username
!= NULL
) {
241 mkpw_warning("You cannot change a single "
242 "record from version %u to version %u\n",
243 db
->rversion
, db
->wversion
);
245 } else if (verbose
) {
246 mkpw_warning("Changing %s from version %u to version %u",
247 db
->fname
, db
->rversion
, db
->wversion
);
251 mkpw_warning("File `%s' version %u requested %u",
252 db
->fname
, db
->rversion
, db
->wversion
);
259 main(int argc
, char *argv
[])
261 int ch
, makeold
, tfd
, lineno
, found
, rv
, hasyp
, secureonly
;
262 struct passwd pwd
, *tpwd
;
266 u_int dbflg
, uid_dbflg
;
267 int newuser
, olduid
, flags
;
270 uint32_t req_version
;
286 while ((ch
= getopt(argc
, argv
, "BLc:d:lpsu:V:vw")) != -1)
288 case 'B': /* big-endian output */
291 case 'L': /* little-endian output */
292 lorder
= LITTLE_ENDIAN
;
295 cachesize
= atoi(optarg
) * 1024 * 1024;
297 case 'd': /* set prefix */
298 (void)strlcpy(prefix
, optarg
, sizeof(prefix
));
301 openlog(getprogname(), LOG_PID
, LOG_AUTH
);
304 case 'p': /* create V7 "file.orig" */
307 case 's': /* modify secure db only */
310 case 'u': /* modify one user only */
314 req_version
= (uint32_t)atoi(optarg
);
315 if (req_version
> 1) {
316 mkpw_warning("Unknown version %u", req_version
);
335 if (username
!= NULL
)
336 if (username
[0] == '+' || username
[0] == '-')
342 * This could be changed to allow the user to interrupt.
343 * Probably not worth the effort.
345 (void)sigemptyset(&set
);
346 (void)sigaddset(&set
, SIGTSTP
);
347 (void)sigaddset(&set
, SIGHUP
);
348 (void)sigaddset(&set
, SIGINT
);
349 (void)sigaddset(&set
, SIGQUIT
);
350 (void)sigaddset(&set
, SIGTERM
);
351 (void)sigprocmask(SIG_BLOCK
, &set
, NULL
);
353 /* We don't care what the user wants. */
356 if (username
== NULL
)
357 flags
= O_RDWR
| O_CREAT
| O_EXCL
;
362 /* Open the original password file */
363 if ((fp
= fopen(pname
, "r")) == NULL
)
364 mkpw_error("Cannot open `%s'", pname
);
366 openinfo
.lorder
= lorder
;
368 if (fstat(fileno(fp
), &st
) == -1)
369 mkpw_error("Cannot stat `%s'", pname
);
372 openinfo
.cachesize
= cachesize
;
374 /* Tweak openinfo values for large passwd files. */
375 cachesize
= (u_int
)(st
.st_size
* 20);
376 if (cachesize
> MAX_CACHESIZE
)
377 cachesize
= MAX_CACHESIZE
;
378 else if (cachesize
< MIN_CACHESIZE
)
379 cachesize
= MIN_CACHESIZE
;
380 openinfo
.cachesize
= cachesize
;
383 /* Open the temporary insecure password database. */
385 opendb(&idb
, _PATH_MP_DB
, username
, req_version
,
386 flags
, PERM_INSECURE
);
387 clean
|= FILE_INSECURE
;
391 /* Open the temporary encrypted password database. */
392 opendb(&sdb
, _PATH_SMP_DB
, username
, req_version
, flags
, PERM_SECURE
);
393 clean
|= FILE_SECURE
;
396 * Open file for old password file. Minor trickiness -- don't want to
397 * chance the file already existing, since someone (stupidly) might
398 * still be using this for permission checking. So, open it first and
399 * fdopen the resulting fd. The resulting file should be readable by
403 (void)snprintf(oldpwdfile
, sizeof(oldpwdfile
), "%s.orig",
405 if ((tfd
= open(oldpwdfile
, O_WRONLY
| O_CREAT
| O_EXCL
,
407 mkpw_error("Cannot create `%s'", oldpwdfile
);
409 if ((oldfp
= fdopen(tfd
, "w")) == NULL
)
410 mkpw_error("Cannot fdopen `%s'", oldpwdfile
);
413 if (username
!= NULL
) {
418 * Determine if this is a new entry.
420 if (getdbent(&sdb
, _PW_KEYBYNAME
, username
, &tpwd
))
424 olduid
= tpwd
->pw_uid
;
428 uid_dbflg
= R_NOOVERWRITE
;
429 dbflg
= R_NOOVERWRITE
;
433 * If we see something go by that looks like YP, we save a special
434 * pointer record, which if YP is enabled in the C lib, will speed
437 for (lineno
= 0; scan(fp
, &pwd
, &flags
, &lineno
);) {
439 * Create original format password file entry.
442 (void)fprintf(oldfp
, "%s:*:%d:%d:%s:%s:%s\n",
443 pwd
.pw_name
, pwd
.pw_uid
, pwd
.pw_gid
, pwd
.pw_gecos
,
444 pwd
.pw_dir
, pwd
.pw_shell
);
446 wr_error(oldpwdfile
);
449 if (username
== NULL
) {
451 if (pwd
.pw_name
[0] == '+' || pwd
.pw_name
[0] == '-')
454 /* Warn about potentially unsafe uid/gid overrides. */
455 if (pwd
.pw_name
[0] == '+') {
456 if ((flags
& _PASSWORD_NOUID
) == 0 &&
458 mkpw_warning("line %d: superuser "
459 "override in YP inclusion", lineno
);
460 if ((flags
& _PASSWORD_NOGID
) == 0 &&
462 mkpw_warning("line %d: wheel override "
463 "in YP inclusion", lineno
);
466 /* Write the database entry out. */
468 putdbents(&idb
, &pwd
, "*", flags
, lineno
, dbflg
,
471 } else if (strcmp(username
, pwd
.pw_name
) != 0)
475 mkpw_warning("user `%s' listed twice in password file",
481 * Ensure that the text file and database agree on
482 * which line the record is from.
484 rv
= getdbent(&sdb
, _PW_KEYBYNUM
, &lineno
, &tpwd
);
488 } else if (rv
== 1 || strcmp(username
, tpwd
->pw_name
) != 0)
490 else if ((uid_t
)olduid
!= pwd
.pw_uid
) {
492 * If we're changing UID, remove the BYUID
493 * record for the old UID only if it has the
496 if (!getdbent(&sdb
, _PW_KEYBYUID
, &olduid
, &tpwd
)) {
497 if (strcmp(username
, tpwd
->pw_name
) == 0) {
499 deldbent(&idb
, _PW_KEYBYUID
,
501 deldbent(&sdb
, _PW_KEYBYUID
, &olduid
);
508 * If there's an existing BYUID record for the new UID and
509 * the username doesn't match then be sure not to overwrite
512 if (!getdbent(&sdb
, _PW_KEYBYUID
, &pwd
.pw_uid
, &tpwd
))
513 if (strcmp(username
, tpwd
->pw_name
) != 0)
514 uid_dbflg
= R_NOOVERWRITE
;
516 /* Write the database entries out */
518 putdbents(&idb
, &pwd
, "*", flags
, lineno
, dbflg
,
520 putdbents(&sdb
, &pwd
, pwd
.pw_passwd
, flags
, lineno
, dbflg
,
529 /* Store YP token if needed. */
533 /* Close the insecure database. */
538 * If rebuilding the databases, we re-parse the text file and write
539 * the secure entries out in a separate pass.
541 if (username
== NULL
) {
543 for (lineno
= 0; scan(fp
, &pwd
, &flags
, &lineno
);)
544 putdbents(&sdb
, &pwd
, pwd
.pw_passwd
, flags
,
545 lineno
, dbflg
, uid_dbflg
);
547 /* Store YP token if needed. */
551 mkpw_warning("user `%s' not found in password file", username
);
555 /* Close the secure database. */
558 /* Install as the real password files. */
560 install(idb
.dbname
, idb
.fname
);
561 install(sdb
.dbname
, sdb
.fname
);
563 /* Install the V7 password file. */
565 if (fflush(oldfp
) == EOF
)
566 wr_error(oldpwdfile
);
567 if (fclose(oldfp
) == EOF
)
568 wr_error(oldpwdfile
);
569 install(oldpwdfile
, _PATH_PASSWD
);
572 /* Set master.passwd permissions, in case caller forgot. */
573 (void)fchmod(fileno(fp
), S_IRUSR
|S_IWUSR
);
574 if (fclose(fp
) == EOF
)
578 * Move the temporary master password file LAST -- chpass(1),
579 * passwd(1), vipw(8) and friends all use its existence to block
580 * other incarnations of themselves. The rename means that
581 * everything is unlocked, as the original file can no longer be
584 install(pname
, _PATH_MASTERPASSWD
);
590 scan(FILE *fp
, struct passwd
*pw
, int *flags
, int *lineno
)
592 static char line
[LINE_MAX
];
596 if (fgets(line
, (int)sizeof(line
), fp
) == NULL
)
601 * ``... if I swallow anything evil, put your fingers down my
605 if ((p
= strchr(line
, '\n')) == NULL
) {
606 errno
= EFTYPE
; /* XXX */
607 mkpw_error("%s, %d: line too long", pname
, *lineno
);
610 if (strcmp(line
, "+") == 0) {
611 /* pw_scan() can't handle "+" */
612 (void)strcpy(line
, "+:::::::::");
615 if (!pw_scan(line
, pw
, &oflags
)) {
616 errno
= EFTYPE
; /* XXX */
617 mkpw_error("%s, %d: Syntax mkpw_error", pname
, *lineno
);
625 install(const char *from
, const char *to
)
627 char buf
[MAXPATHLEN
];
629 (void)snprintf(buf
, sizeof(buf
), "%s%s", prefix
, to
);
630 if (rename(from
, buf
))
631 mkpw_error("Cannot rename `%s' to `%s'", from
, buf
);
635 rm(const char *victim
)
638 if (unlink(victim
) < 0)
639 warn("unlink(%s)", victim
);
643 cp(const char *from
, const char *to
, mode_t mode
)
645 static char buf
[MAXBSIZE
];
647 ssize_t rcount
, wcount
;
649 if ((from_fd
= open(from
, O_RDONLY
, 0)) < 0)
650 mkpw_error("Cannot open `%s'", from
);
651 if ((to_fd
= open(to
, O_WRONLY
| O_CREAT
| O_EXCL
, mode
)) < 0) {
652 (void)close(from_fd
);
653 mkpw_error("Cannot open `%s'", to
);
655 while ((rcount
= read(from_fd
, buf
, MAXBSIZE
)) > 0) {
656 wcount
= write(to_fd
, buf
, (size_t)rcount
);
657 if (rcount
!= wcount
|| wcount
== -1) {
658 (void)close(from_fd
);
672 mkpw_error("Cannot copy `%s' to `%s'", from
, to
);
676 wr_error(const char *str
)
678 mkpw_error("Cannot write `%s'", str
);
682 mkpw_error(const char *fmt
, ...)
689 snprintf(efmt
, sizeof(efmt
), "%s (%%m)", fmt
);
691 vsyslog(LOG_ERR
, efmt
, ap
);
699 mkpw_warning(const char *fmt
, ...)
704 vsyslog(LOG_WARNING
, fmt
, ap
);
714 mkpw_warning("text files and databases are inconsistent");
715 mkpw_warning("re-build the databases without -u");
723 if ((clean
& FILE_ORIG
) != 0)
725 if ((clean
& FILE_SECURE
) != 0)
727 if ((clean
& FILE_INSECURE
) != 0)
734 getversion(const char *fname
)
738 uint32_t version
= 0;
741 db
= dbopen(fname
, O_RDONLY
, PERM_INSECURE
, DB_HASH
, NULL
);
743 /* If we are building on a separate root, assume version 1 */
744 if ((errno
== EACCES
|| errno
== ENOENT
) && prefix
[0])
746 mkpw_warning("Cannot open database `%s'", fname
);
749 key
.data
= __UNCONST("VERSION");
750 key
.size
= strlen((const char *)key
.data
) + 1;
752 switch (ret
= (*db
->get
)(db
, &key
, &data
, 0)) {
754 mkpw_warning("Cannot get VERSION record from database `%s'",
758 if (data
.size
!= sizeof(version
)) {
759 mkpw_warning("Bad VERSION record in database `%s'", fname
);
762 (void)memcpy(&version
, data
.data
, sizeof(version
));
766 mkpw_warning("Database `%s' has no version info",
771 mkpw_warning("internal mkpw_error db->get returns %d", ret
);
781 setversion(struct pwddb
*db
)
784 key
.data
= __UNCONST("VERSION");
785 key
.size
= strlen((const char *)key
.data
) + 1;
787 data
.data
= &db
->wversion
;
788 data
.size
= sizeof(uint32_t);
790 if ((*db
->db
->put
)(db
->db
, &key
, &data
, 0) != 0) {
791 mkpw_warning("Can't write VERSION record to `%s'", db
->dbname
);
798 * Write entries to a database for a single user.
800 * The databases actually contain three copies of the original data. Each
801 * password file entry is converted into a rough approximation of a ``struct
802 * passwd'', with the strings placed inline. This object is then stored as
803 * the data for three separate keys. The first key * is the pw_name field
804 * prepended by the _PW_KEYBYNAME character. The second key is the pw_uid
805 * field prepended by the _PW_KEYBYUID character. The third key is the line
806 * number in the original file prepended by the _PW_KEYBYNUM character.
807 * (The special characters are prepended to ensure that the keys do not
810 #define COMPACT(e) for (t = e; (*p++ = *t++) != '\0';)
813 putdbents(struct pwddb
*db
, struct passwd
*pw
, const char *passwd
, int flags
,
814 int lineno
, u_int dbflg
, u_int uid_dbflg
)
817 char buf
[MAX(MAXPATHLEN
, LINE_MAX
* 2)], tbuf
[1024], *p
;
823 (void)memcpy(&pwd
, pw
, sizeof(pwd
));
824 data
.data
= (u_char
*)buf
;
825 key
.data
= (u_char
*)tbuf
;
827 if (lorder
!= BYTE_ORDER
) {
828 pwd
.pw_uid
= SWAP(pwd
.pw_uid
);
829 pwd
.pw_gid
= SWAP(pwd
.pw_gid
);
832 #define WRITEPWTIMEVAR(pwvar) \
834 if (db->wversion == 0 && \
835 /*CONSTCOND*/sizeof(pwvar) == sizeof(uint64_t)) { \
836 uint32_t tmp = (uint32_t)pwvar; \
837 if (lorder != BYTE_ORDER) \
839 (void)memmove(p, &tmp, sizeof(tmp)); \
841 } else if (db->wversion == 1 && \
842 /*CONSTCOND*/sizeof(pwvar) == sizeof(uint32_t)) { \
843 uint64_t tmp = pwvar; \
844 if (lorder != BYTE_ORDER) \
846 (void)memmove(p, &tmp, sizeof(tmp)); \
849 if (lorder != BYTE_ORDER) \
850 pwvar = SWAP(pwvar); \
851 (void)memmove(p, &pwvar, sizeof(pwvar)); \
852 p += sizeof(pwvar); \
854 } while (/*CONSTCOND*/0)
856 /* Create insecure data. */
858 COMPACT(pwd
.pw_name
);
860 (void)memmove(p
, &pwd
.pw_uid
, sizeof(pwd
.pw_uid
));
861 p
+= sizeof(pwd
.pw_uid
);
862 (void)memmove(p
, &pwd
.pw_gid
, sizeof(pwd
.pw_gid
));
863 p
+= sizeof(pwd
.pw_gid
);
864 WRITEPWTIMEVAR(pwd
.pw_change
);
865 COMPACT(pwd
.pw_class
);
866 COMPACT(pwd
.pw_gecos
);
868 COMPACT(pwd
.pw_shell
);
869 WRITEPWTIMEVAR(pwd
.pw_expire
);
871 if (lorder
!= BYTE_ORDER
)
873 (void)memmove(p
, &x
, sizeof(x
));
877 /* Store insecure by name. */
878 tbuf
[0] = _PW_KEYBYNAME
;
879 len
= strlen(pwd
.pw_name
);
880 (void)memmove(tbuf
+ 1, pwd
.pw_name
, len
);
882 if ((*db
->db
->put
)(db
->db
, &key
, &data
, dbflg
) == -1)
883 wr_error(db
->dbname
);
885 /* Store insecure by number. */
886 tbuf
[0] = _PW_KEYBYNUM
;
888 if (lorder
!= BYTE_ORDER
)
890 (void)memmove(tbuf
+ 1, &x
, sizeof(x
));
891 key
.size
= sizeof(x
) + 1;
892 if ((*db
->db
->put
)(db
->db
, &key
, &data
, dbflg
) == -1)
893 wr_error(db
->dbname
);
895 /* Store insecure by uid. */
896 tbuf
[0] = _PW_KEYBYUID
;
897 (void)memmove(tbuf
+ 1, &pwd
.pw_uid
, sizeof(pwd
.pw_uid
));
898 key
.size
= sizeof(pwd
.pw_uid
) + 1;
899 if ((*db
->db
->put
)(db
->db
, &key
, &data
, uid_dbflg
) == -1)
900 wr_error(db
->dbname
);
904 deldbent(struct pwddb
*db
, int type
, void *keyp
)
911 key
.data
= (u_char
*)tbuf
;
913 switch (tbuf
[0] = type
) {
915 len
= strlen((char *)keyp
);
916 (void)memcpy(tbuf
+ 1, keyp
, len
);
923 if (lorder
!= BYTE_ORDER
)
925 (void)memmove(tbuf
+ 1, &x
, sizeof(x
));
926 key
.size
= sizeof(x
) + 1;
930 if ((*db
->db
->del
)(db
->db
, &key
, 0) == -1)
931 wr_error(db
->dbname
);
935 getdbent(struct pwddb
*db
, int type
, void *keyp
, struct passwd
**tpwd
)
937 static char buf
[MAX(MAXPATHLEN
, LINE_MAX
* 2)];
938 static struct passwd pwd
;
945 data
.data
= (u_char
*)buf
;
946 data
.size
= sizeof(buf
);
947 key
.data
= (u_char
*)tbuf
;
949 switch (tbuf
[0] = type
) {
951 len
= strlen((char *)keyp
);
952 (void)memcpy(tbuf
+ 1, keyp
, len
);
959 if (lorder
!= BYTE_ORDER
)
961 (void)memmove(tbuf
+ 1, &x
, sizeof(x
));
962 key
.size
= sizeof(x
) + 1;
966 if ((rv
= (*db
->db
->get
)(db
->db
, &key
, &data
, 0)) == 1)
969 mkpw_error("Error getting record from `%s'", db
->dbname
);
971 p
= (char *)data
.data
;
980 (void)memcpy(&pwd
.pw_uid
, p
, sizeof(pwd
.pw_uid
));
981 p
+= sizeof(pwd
.pw_uid
);
982 (void)memcpy(&pwd
.pw_gid
, p
, sizeof(pwd
.pw_gid
));
983 p
+= sizeof(pwd
.pw_gid
);
985 #define READPWTIMEVAR(pwvar) \
987 if (db->rversion == 0 && \
988 /*CONSTCOND*/sizeof(pwvar) == sizeof(uint64_t)) { \
990 (void)memcpy(&tmp, p, sizeof(tmp)); \
992 if (lorder != BYTE_ORDER) \
996 } else if (db->rversion == 1 && \
997 /*CONSTCOND*/sizeof(pwvar) == sizeof(uint32_t)) { \
999 (void)memcpy(&tmp, p, sizeof(tmp)); \
1001 if (lorder != BYTE_ORDER) \
1002 pwvar = (uint32_t)SWAP(tmp); \
1004 pwvar = (uint32_t)tmp; \
1006 (void)memcpy(&pwvar, p, sizeof(pwvar)); \
1007 p += sizeof(pwvar); \
1008 if (lorder != BYTE_ORDER) \
1009 pwvar = SWAP(pwvar); \
1011 } while (/*CONSTCOND*/0)
1013 READPWTIMEVAR(pwd
.pw_change
);
1016 while (*p
++ != '\0')
1019 while (*p
++ != '\0')
1022 while (*p
++ != '\0')
1025 while (*p
++ != '\0')
1028 READPWTIMEVAR(pwd
.pw_expire
);
1030 if (lorder
!= BYTE_ORDER
) {
1031 pwd
.pw_uid
= SWAP(pwd
.pw_uid
);
1032 pwd
.pw_gid
= SWAP(pwd
.pw_gid
);
1040 putyptoken(struct pwddb
*db
)
1044 key
.data
= __UNCONST(__yp_token
);
1045 key
.size
= strlen(__yp_token
);
1049 if ((*db
->db
->put
)(db
->db
, &key
, &data
, R_NOOVERWRITE
) == -1)
1050 wr_error(db
->dbname
);
1057 (void)fprintf(stderr
,
1058 "Usage: %s [-BLlpsvw] [-c cachesize] [-d directory] [-u user] "
1059 "[-V version] file\n",