1 /* $NetBSD: pwd_mkdb.c,v 1.53 2011/01/04 10:01:51 wiz 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.53 2011/01/04 10:01:51 wiz 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>
124 #define MAX_CACHESIZE 8*1024*1024
125 #define MIN_CACHESIZE 2*1024*1024
127 #define PERM_INSECURE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
128 #define PERM_SECURE (S_IRUSR | S_IWUSR)
130 #if HAVE_NBTOOL_CONFIG_H
131 static const char __yp_token
[] = "__YP!";
133 /* Pull this out of the C library. */
134 extern const char __yp_token
[];
137 static HASHINFO openinfo
= {
146 #define FILE_INSECURE 0x01
147 #define FILE_SECURE 0x02
148 #define FILE_ORIG 0x04
153 char dbname
[MAX(MAXPATHLEN
, LINE_MAX
* 2)];
159 static char *pname
; /* password file name */
160 static char prefix
[MAXPATHLEN
];
161 static char oldpwdfile
[MAX(MAXPATHLEN
, LINE_MAX
* 2)];
162 static int lorder
= BYTE_ORDER
;
163 static int logsyslog
;
167 static struct pwddb sdb
, idb
;
170 void bailout(void) __attribute__((__noreturn__
));
171 void cp(const char *, const char *, mode_t
);
172 void deldbent(struct pwddb
*, int, void *);
173 void mkpw_error(const char *, ...);
174 void mkpw_warning(const char *, ...);
175 int getdbent(struct pwddb
*, int, void *, struct passwd
**);
176 void inconsistency(void);
177 void install(const char *, const char *);
178 int main(int, char **);
179 void putdbents(struct pwddb
*, struct passwd
*, const char *, int, int,
181 void putyptoken(struct pwddb
*);
182 void rm(const char *);
183 int scan(FILE *, struct passwd
*, int *, int *);
184 void usage(void) __attribute__((__noreturn__
));
185 void wr_error(const char *);
186 uint32_t getversion(const char *);
187 void setversion(struct pwddb
*);
191 ((sizeof(sw) == 2 ? (typeof(sw))bswap16((uint16_t)sw) : \
192 (sizeof(sw) == 4 ? (typeof(sw))bswap32((uint32_t)sw) : \
193 (sizeof(sw) == 8 ? (typeof(sw))bswap64((uint64_t)sw) : (abort(), 0)))))
199 closedb(struct pwddb
*db
)
201 if ((*db
->db
->close
)(db
->db
) < 0)
202 wr_error(db
->dbname
);
206 opendb(struct pwddb
*db
, const char *dbname
, const char *username
,
207 uint32_t req_version
, int flags
, mode_t perm
)
209 char buf
[MAXPATHLEN
];
211 (void)snprintf(db
->dbname
, sizeof(db
->dbname
), "%s%s.tmp", prefix
,
214 if (username
!= NULL
) {
215 (void)snprintf(buf
, sizeof(buf
), "%s%s", prefix
, dbname
);
216 cp(buf
, db
->dbname
, perm
);
219 db
->db
= dbopen(db
->dbname
, flags
, perm
, DB_HASH
, &openinfo
);
221 mkpw_error("Cannot open `%s'", db
->dbname
);
224 db
->rversion
= getversion(dbname
);
225 if (req_version
== ~0U)
226 db
->wversion
= db
->rversion
;
228 db
->wversion
= req_version
;
230 if (warning
&& db
->rversion
== 0 && db
->wversion
== 0) {
231 mkpw_warning("Database %s is a version %u database.",
232 db
->fname
, db
->rversion
);
233 mkpw_warning("Use %s -V 1 to upgrade once you've recompiled "
234 "all your binaries.", getprogname());
236 if (db
->wversion
!= db
->rversion
) {
237 if (username
!= NULL
) {
238 mkpw_warning("You cannot change a single "
239 "record from version %u to version %u\n",
240 db
->rversion
, db
->wversion
);
242 } else if (verbose
) {
243 mkpw_warning("Changing %s from version %u to version %u",
244 db
->fname
, db
->rversion
, db
->wversion
);
248 mkpw_warning("File `%s' version %u requested %u",
249 db
->fname
, db
->rversion
, db
->wversion
);
256 main(int argc
, char *argv
[])
258 int ch
, makeold
, tfd
, lineno
, found
, rv
, hasyp
, secureonly
;
259 struct passwd pwd
, *tpwd
;
263 u_int dbflg
, uid_dbflg
;
264 int newuser
, olduid
, flags
;
267 uint32_t req_version
;
283 while ((ch
= getopt(argc
, argv
, "BLc:d:lpsu:V:vw")) != -1)
285 case 'B': /* big-endian output */
288 case 'L': /* little-endian output */
289 lorder
= LITTLE_ENDIAN
;
292 cachesize
= atoi(optarg
) * 1024 * 1024;
294 case 'd': /* set prefix */
295 (void)strlcpy(prefix
, optarg
, sizeof(prefix
));
298 openlog(getprogname(), LOG_PID
, LOG_AUTH
);
301 case 'p': /* create V7 "file.orig" */
304 case 's': /* modify secure db only */
307 case 'u': /* modify one user only */
311 req_version
= (uint32_t)atoi(optarg
);
312 if (req_version
> 1) {
313 mkpw_warning("Unknown version %u", req_version
);
332 if (username
!= NULL
)
333 if (username
[0] == '+' || username
[0] == '-')
339 * This could be changed to allow the user to interrupt.
340 * Probably not worth the effort.
342 (void)sigemptyset(&set
);
343 (void)sigaddset(&set
, SIGTSTP
);
344 (void)sigaddset(&set
, SIGHUP
);
345 (void)sigaddset(&set
, SIGINT
);
346 (void)sigaddset(&set
, SIGQUIT
);
347 (void)sigaddset(&set
, SIGTERM
);
348 (void)sigprocmask(SIG_BLOCK
, &set
, (sigset_t
*)NULL
);
350 /* We don't care what the user wants. */
353 if (username
== NULL
)
354 flags
= O_RDWR
| O_CREAT
| O_EXCL
;
359 /* Open the original password file */
360 if ((fp
= fopen(pname
, "r")) == NULL
)
361 mkpw_error("Cannot open `%s'", pname
);
363 openinfo
.lorder
= lorder
;
365 if (fstat(fileno(fp
), &st
) == -1)
366 mkpw_error("Cannot stat `%s'", pname
);
369 openinfo
.cachesize
= cachesize
;
371 /* Tweak openinfo values for large passwd files. */
372 cachesize
= (u_int
)(st
.st_size
* 20);
373 if (cachesize
> MAX_CACHESIZE
)
374 cachesize
= MAX_CACHESIZE
;
375 else if (cachesize
< MIN_CACHESIZE
)
376 cachesize
= MIN_CACHESIZE
;
377 openinfo
.cachesize
= cachesize
;
380 /* Open the temporary insecure password database. */
382 opendb(&idb
, _PATH_MP_DB
, username
, req_version
,
383 flags
, PERM_INSECURE
);
384 clean
|= FILE_INSECURE
;
388 /* Open the temporary encrypted password database. */
389 opendb(&sdb
, _PATH_SMP_DB
, username
, req_version
, flags
, PERM_SECURE
);
390 clean
|= FILE_SECURE
;
393 * Open file for old password file. Minor trickiness -- don't want to
394 * chance the file already existing, since someone (stupidly) might
395 * still be using this for permission checking. So, open it first and
396 * fdopen the resulting fd. The resulting file should be readable by
400 (void)snprintf(oldpwdfile
, sizeof(oldpwdfile
), "%s.orig",
402 if ((tfd
= open(oldpwdfile
, O_WRONLY
| O_CREAT
| O_EXCL
,
404 mkpw_error("Cannot create `%s'", oldpwdfile
);
406 if ((oldfp
= fdopen(tfd
, "w")) == NULL
)
407 mkpw_error("Cannot fdopen `%s'", oldpwdfile
);
410 if (username
!= NULL
) {
415 * Determine if this is a new entry.
417 if (getdbent(&sdb
, _PW_KEYBYNAME
, username
, &tpwd
))
421 olduid
= tpwd
->pw_uid
;
425 uid_dbflg
= R_NOOVERWRITE
;
426 dbflg
= R_NOOVERWRITE
;
430 * If we see something go by that looks like YP, we save a special
431 * pointer record, which if YP is enabled in the C lib, will speed
434 for (lineno
= 0; scan(fp
, &pwd
, &flags
, &lineno
);) {
436 * Create original format password file entry.
440 (void)fprintf(oldfp
, "%s:##%s:%d:%d:%s:%s:%s\n",
441 pwd
.pw_name
, pwd
.pw_name
, pwd
.pw_uid
, pwd
.pw_gid
,
442 pwd
.pw_gecos
, pwd
.pw_dir
, pwd
.pw_shell
);
444 (void)fprintf(oldfp
, "%s:*:%d:%d:%s:%s:%s\n",
445 pwd
.pw_name
, pwd
.pw_uid
, pwd
.pw_gid
, pwd
.pw_gecos
,
446 pwd
.pw_dir
, pwd
.pw_shell
);
449 wr_error(oldpwdfile
);
452 if (username
== NULL
) {
454 if (pwd
.pw_name
[0] == '+' || pwd
.pw_name
[0] == '-')
457 /* Warn about potentially unsafe uid/gid overrides. */
458 if (pwd
.pw_name
[0] == '+') {
459 if ((flags
& _PASSWORD_NOUID
) == 0 &&
461 mkpw_warning("line %d: superuser "
462 "override in YP inclusion", lineno
);
463 if ((flags
& _PASSWORD_NOGID
) == 0 &&
465 mkpw_warning("line %d: wheel override "
466 "in YP inclusion", lineno
);
469 /* Write the database entry out. */
471 putdbents(&idb
, &pwd
, "*", flags
, lineno
, dbflg
,
474 } else if (strcmp(username
, pwd
.pw_name
) != 0)
478 mkpw_warning("user `%s' listed twice in password file",
484 * Ensure that the text file and database agree on
485 * which line the record is from.
487 rv
= getdbent(&sdb
, _PW_KEYBYNUM
, &lineno
, &tpwd
);
491 } else if (rv
== 1 || strcmp(username
, tpwd
->pw_name
) != 0)
493 else if ((uid_t
)olduid
!= pwd
.pw_uid
) {
495 * If we're changing UID, remove the BYUID
496 * record for the old UID only if it has the
499 if (!getdbent(&sdb
, _PW_KEYBYUID
, &olduid
, &tpwd
)) {
500 if (strcmp(username
, tpwd
->pw_name
) == 0) {
502 deldbent(&idb
, _PW_KEYBYUID
,
504 deldbent(&sdb
, _PW_KEYBYUID
, &olduid
);
511 * If there's an existing BYUID record for the new UID and
512 * the username doesn't match then be sure not to overwrite
515 if (!getdbent(&sdb
, _PW_KEYBYUID
, &pwd
.pw_uid
, &tpwd
))
516 if (strcmp(username
, tpwd
->pw_name
) != 0)
517 uid_dbflg
= R_NOOVERWRITE
;
519 /* Write the database entries out */
521 putdbents(&idb
, &pwd
, "*", flags
, lineno
, dbflg
,
523 putdbents(&sdb
, &pwd
, pwd
.pw_passwd
, flags
, lineno
, dbflg
,
532 /* Store YP token if needed. */
536 /* Close the insecure database. */
541 * If rebuilding the databases, we re-parse the text file and write
542 * the secure entries out in a separate pass.
544 if (username
== NULL
) {
546 for (lineno
= 0; scan(fp
, &pwd
, &flags
, &lineno
);)
547 putdbents(&sdb
, &pwd
, pwd
.pw_passwd
, flags
,
548 lineno
, dbflg
, uid_dbflg
);
550 /* Store YP token if needed. */
554 mkpw_warning("user `%s' not found in password file", username
);
558 /* Close the secure database. */
561 /* Install as the real password files. */
563 install(idb
.dbname
, idb
.fname
);
564 install(sdb
.dbname
, sdb
.fname
);
566 /* Install the V7 password file. */
568 if (fflush(oldfp
) == EOF
)
569 wr_error(oldpwdfile
);
570 if (fclose(oldfp
) == EOF
)
571 wr_error(oldpwdfile
);
572 install(oldpwdfile
, _PATH_PASSWD
);
575 /* Set master.passwd permissions, in case caller forgot. */
576 (void)fchmod(fileno(fp
), S_IRUSR
|S_IWUSR
);
577 if (fclose(fp
) == EOF
)
581 * Move the temporary master password file LAST -- chpass(1),
582 * passwd(1), vipw(8) and friends all use its existence to block
583 * other incarnations of themselves. The rename means that
584 * everything is unlocked, as the original file can no longer be
587 install(pname
, _PATH_MASTERPASSWD
);
593 scan(FILE *fp
, struct passwd
*pw
, int *flags
, int *lineno
)
595 static char line
[LINE_MAX
];
599 if (fgets(line
, (int)sizeof(line
), fp
) == NULL
)
604 * ``... if I swallow anything evil, put your fingers down my
608 if ((p
= strchr(line
, '\n')) == NULL
) {
609 errno
= EFTYPE
; /* XXX */
610 mkpw_error("%s, %d: line too long", pname
, *lineno
);
613 if (strcmp(line
, "+") == 0) {
614 /* pw_scan() can't handle "+" */
615 (void)strcpy(line
, "+:::::::::");
618 if (!pw_scan(line
, pw
, &oflags
)) {
619 errno
= EFTYPE
; /* XXX */
620 mkpw_error("%s, %d: Syntax mkpw_error", pname
, *lineno
);
628 install(const char *from
, const char *to
)
630 char buf
[MAXPATHLEN
];
632 (void)snprintf(buf
, sizeof(buf
), "%s%s", prefix
, to
);
633 if (rename(from
, buf
))
634 mkpw_error("Cannot rename `%s' to `%s'", from
, buf
);
638 rm(const char *victim
)
641 if (unlink(victim
) < 0)
642 warn("unlink(%s)", victim
);
646 cp(const char *from
, const char *to
, mode_t mode
)
648 static char buf
[MAXBSIZE
];
650 ssize_t rcount
, wcount
;
652 if ((from_fd
= open(from
, O_RDONLY
, 0)) < 0)
653 mkpw_error("Cannot open `%s'", from
);
654 if ((to_fd
= open(to
, O_WRONLY
| O_CREAT
| O_EXCL
, mode
)) < 0) {
655 (void)close(from_fd
);
656 mkpw_error("Cannot open `%s'", to
);
658 while ((rcount
= read(from_fd
, buf
, MAXBSIZE
)) > 0) {
659 wcount
= write(to_fd
, buf
, (size_t)rcount
);
660 if (rcount
!= wcount
|| wcount
== -1) {
661 (void)close(from_fd
);
675 mkpw_error("Cannot copy `%s' to `%s'", from
, to
);
679 wr_error(const char *str
)
681 mkpw_error("Cannot write `%s'", str
);
685 mkpw_error(const char *fmt
, ...)
692 snprintf(efmt
, sizeof(efmt
), "%s (%%m)", fmt
);
694 vsyslog(LOG_ERR
, efmt
, ap
);
702 mkpw_warning(const char *fmt
, ...)
707 vsyslog(LOG_WARNING
, fmt
, ap
);
717 mkpw_warning("text files and databases are inconsistent");
718 mkpw_warning("re-build the databases without -u");
726 if ((clean
& FILE_ORIG
) != 0)
728 if ((clean
& FILE_SECURE
) != 0)
730 if ((clean
& FILE_INSECURE
) != 0)
737 getversion(const char *fname
)
741 uint32_t version
= 0;
744 db
= dbopen(fname
, O_RDONLY
, PERM_INSECURE
, DB_HASH
, NULL
);
746 /* If we are building on a separate root, assume version 1 */
747 if ((errno
== EACCES
|| errno
== ENOENT
) && prefix
[0])
749 mkpw_warning("Cannot open database `%s'", fname
);
752 key
.data
= __UNCONST("VERSION");
753 key
.size
= strlen((const char *)key
.data
) + 1;
755 switch (ret
= (*db
->get
)(db
, &key
, &data
, 0)) {
757 mkpw_warning("Cannot get VERSION record from database `%s'",
761 if (data
.size
!= sizeof(version
)) {
762 mkpw_warning("Bad VERSION record in database `%s'", fname
);
765 (void)memcpy(&version
, data
.data
, sizeof(version
));
769 mkpw_warning("Database `%s' has no version info",
774 mkpw_warning("internal mkpw_error db->get returns %d", ret
);
784 setversion(struct pwddb
*db
)
787 key
.data
= __UNCONST("VERSION");
788 key
.size
= strlen((const char *)key
.data
) + 1;
790 data
.data
= &db
->wversion
;
791 data
.size
= sizeof(uint32_t);
793 if ((*db
->db
->put
)(db
->db
, &key
, &data
, 0) != 0) {
794 mkpw_warning("Can't write VERSION record to `%s'", db
->dbname
);
801 * Write entries to a database for a single user.
803 * The databases actually contain three copies of the original data. Each
804 * password file entry is converted into a rough approximation of a ``struct
805 * passwd'', with the strings placed inline. This object is then stored as
806 * the data for three separate keys. The first key * is the pw_name field
807 * prepended by the _PW_KEYBYNAME character. The second key is the pw_uid
808 * field prepended by the _PW_KEYBYUID character. The third key is the line
809 * number in the original file prepended by the _PW_KEYBYNUM character.
810 * (The special characters are prepended to ensure that the keys do not
813 #define COMPACT(e) for (t = e; (*p++ = *t++) != '\0';)
816 putdbents(struct pwddb
*db
, struct passwd
*pw
, const char *passwd
, int flags
,
817 int lineno
, u_int dbflg
, u_int uid_dbflg
)
820 char buf
[MAX(MAXPATHLEN
, LINE_MAX
* 2)], tbuf
[1024], *p
;
826 (void)memcpy(&pwd
, pw
, sizeof(pwd
));
827 data
.data
= (u_char
*)buf
;
828 key
.data
= (u_char
*)tbuf
;
830 if (lorder
!= BYTE_ORDER
) {
831 pwd
.pw_uid
= SWAP(pwd
.pw_uid
);
832 pwd
.pw_gid
= SWAP(pwd
.pw_gid
);
835 #define WRITEPWTIMEVAR(pwvar) \
837 if (db->wversion == 0 && \
838 /*CONSTCOND*/sizeof(pwvar) == sizeof(uint64_t)) { \
839 uint32_t tmp = (uint32_t)pwvar; \
840 if (lorder != BYTE_ORDER) \
842 (void)memmove(p, &tmp, sizeof(tmp)); \
844 } else if (db->wversion == 1 && \
845 /*CONSTCOND*/sizeof(pwvar) == sizeof(uint32_t)) { \
846 uint64_t tmp = pwvar; \
847 if (lorder != BYTE_ORDER) \
849 (void)memmove(p, &tmp, sizeof(tmp)); \
852 if (lorder != BYTE_ORDER) \
853 pwvar = SWAP(pwvar); \
854 (void)memmove(p, &pwvar, sizeof(pwvar)); \
855 p += sizeof(pwvar); \
857 } while (/*CONSTCOND*/0)
859 /* Create insecure data. */
861 COMPACT(pwd
.pw_name
);
863 (void)memmove(p
, &pwd
.pw_uid
, sizeof(pwd
.pw_uid
));
864 p
+= sizeof(pwd
.pw_uid
);
865 (void)memmove(p
, &pwd
.pw_gid
, sizeof(pwd
.pw_gid
));
866 p
+= sizeof(pwd
.pw_gid
);
867 WRITEPWTIMEVAR(pwd
.pw_change
);
868 COMPACT(pwd
.pw_class
);
869 COMPACT(pwd
.pw_gecos
);
871 COMPACT(pwd
.pw_shell
);
872 WRITEPWTIMEVAR(pwd
.pw_expire
);
874 if (lorder
!= BYTE_ORDER
)
876 (void)memmove(p
, &x
, sizeof(x
));
880 /* Store insecure by name. */
881 tbuf
[0] = _PW_KEYBYNAME
;
882 len
= strlen(pwd
.pw_name
);
883 (void)memmove(tbuf
+ 1, pwd
.pw_name
, len
);
885 if ((*db
->db
->put
)(db
->db
, &key
, &data
, dbflg
) == -1)
886 wr_error(db
->dbname
);
888 /* Store insecure by number. */
889 tbuf
[0] = _PW_KEYBYNUM
;
891 if (lorder
!= BYTE_ORDER
)
893 (void)memmove(tbuf
+ 1, &x
, sizeof(x
));
894 key
.size
= sizeof(x
) + 1;
895 if ((*db
->db
->put
)(db
->db
, &key
, &data
, dbflg
) == -1)
896 wr_error(db
->dbname
);
898 /* Store insecure by uid. */
899 tbuf
[0] = _PW_KEYBYUID
;
900 (void)memmove(tbuf
+ 1, &pwd
.pw_uid
, sizeof(pwd
.pw_uid
));
901 key
.size
= sizeof(pwd
.pw_uid
) + 1;
902 if ((*db
->db
->put
)(db
->db
, &key
, &data
, uid_dbflg
) == -1)
903 wr_error(db
->dbname
);
907 deldbent(struct pwddb
*db
, int type
, void *keyp
)
914 key
.data
= (u_char
*)tbuf
;
916 switch (tbuf
[0] = type
) {
918 len
= strlen((char *)keyp
);
919 (void)memcpy(tbuf
+ 1, keyp
, len
);
926 if (lorder
!= BYTE_ORDER
)
928 (void)memmove(tbuf
+ 1, &x
, sizeof(x
));
929 key
.size
= sizeof(x
) + 1;
933 if ((*db
->db
->del
)(db
->db
, &key
, 0) == -1)
934 wr_error(db
->dbname
);
938 getdbent(struct pwddb
*db
, int type
, void *keyp
, struct passwd
**tpwd
)
940 static char buf
[MAX(MAXPATHLEN
, LINE_MAX
* 2)];
941 static struct passwd pwd
;
948 data
.data
= (u_char
*)buf
;
949 data
.size
= sizeof(buf
);
950 key
.data
= (u_char
*)tbuf
;
952 switch (tbuf
[0] = type
) {
954 len
= strlen((char *)keyp
);
955 (void)memcpy(tbuf
+ 1, keyp
, len
);
962 if (lorder
!= BYTE_ORDER
)
964 (void)memmove(tbuf
+ 1, &x
, sizeof(x
));
965 key
.size
= sizeof(x
) + 1;
969 if ((rv
= (*db
->db
->get
)(db
->db
, &key
, &data
, 0)) == 1)
972 mkpw_error("Error getting record from `%s'", db
->dbname
);
974 p
= (char *)data
.data
;
983 (void)memcpy(&pwd
.pw_uid
, p
, sizeof(pwd
.pw_uid
));
984 p
+= sizeof(pwd
.pw_uid
);
985 (void)memcpy(&pwd
.pw_gid
, p
, sizeof(pwd
.pw_gid
));
986 p
+= sizeof(pwd
.pw_gid
);
988 #define READPWTIMEVAR(pwvar) \
990 if (db->rversion == 0 && \
991 /*CONSTCOND*/sizeof(pwvar) == sizeof(uint64_t)) { \
993 (void)memcpy(&tmp, p, sizeof(tmp)); \
995 if (lorder != BYTE_ORDER) \
999 } else if (db->rversion == 1 && \
1000 /*CONSTCOND*/sizeof(pwvar) == sizeof(uint32_t)) { \
1002 (void)memcpy(&tmp, p, sizeof(tmp)); \
1004 if (lorder != BYTE_ORDER) \
1005 pwvar = (uint32_t)SWAP(tmp); \
1007 pwvar = (uint32_t)tmp; \
1009 (void)memcpy(&pwvar, p, sizeof(pwvar)); \
1010 p += sizeof(pwvar); \
1011 if (lorder != BYTE_ORDER) \
1012 pwvar = SWAP(pwvar); \
1014 } while (/*CONSTCOND*/0)
1016 READPWTIMEVAR(pwd
.pw_change
);
1019 while (*p
++ != '\0')
1022 while (*p
++ != '\0')
1025 while (*p
++ != '\0')
1028 while (*p
++ != '\0')
1031 READPWTIMEVAR(pwd
.pw_expire
);
1033 if (lorder
!= BYTE_ORDER
) {
1034 pwd
.pw_uid
= SWAP(pwd
.pw_uid
);
1035 pwd
.pw_gid
= SWAP(pwd
.pw_gid
);
1043 putyptoken(struct pwddb
*db
)
1047 key
.data
= __UNCONST(__yp_token
);
1048 key
.size
= strlen(__yp_token
);
1049 data
.data
= (u_char
*)NULL
;
1052 if ((*db
->db
->put
)(db
->db
, &key
, &data
, R_NOOVERWRITE
) == -1)
1053 wr_error(db
->dbname
);
1060 (void)fprintf(stderr
,
1061 "Usage: %s [-BLlpsvw] [-c cachesize] [-d directory] [-u user] "
1062 "[-V version] file\n",