1 /* $NetBSD: pwd_mkdb.c,v 1.48 2009/08/25 09:27:25 enami 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.48 2009/08/25 09:27:25 enami 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>
122 #define MAX_CACHESIZE 8*1024*1024
123 #define MIN_CACHESIZE 2*1024*1024
125 #define PERM_INSECURE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
126 #define PERM_SECURE (S_IRUSR | S_IWUSR)
128 #if HAVE_NBTOOL_CONFIG_H
129 static const char __yp_token
[] = "__YP!";
131 /* Pull this out of the C library. */
132 extern const char __yp_token
[];
135 static HASHINFO openinfo
= {
144 #define FILE_INSECURE 0x01
145 #define FILE_SECURE 0x02
146 #define FILE_ORIG 0x04
151 char dbname
[MAX(MAXPATHLEN
, LINE_MAX
* 2)];
157 static char *pname
; /* password file name */
158 static char prefix
[MAXPATHLEN
];
159 static char oldpwdfile
[MAX(MAXPATHLEN
, LINE_MAX
* 2)];
160 static int lorder
= BYTE_ORDER
;
164 static struct pwddb sdb
, idb
;
167 void bailout(void) __attribute__((__noreturn__
));
168 void cp(const char *, const char *, mode_t
);
169 void deldbent(struct pwddb
*, int, void *);
170 void error(const char *);
171 int getdbent(struct pwddb
*, int, void *, struct passwd
**);
172 void inconsistency(void);
173 void install(const char *, const char *);
174 int main(int, char **);
175 void putdbents(struct pwddb
*, struct passwd
*, const char *, int, int,
177 void putyptoken(struct pwddb
*);
178 void rm(const char *);
179 int scan(FILE *, struct passwd
*, int *, int *);
180 void usage(void) __attribute__((__noreturn__
));
181 void wr_error(const char *);
182 uint32_t getversion(const char *);
183 void setversion(struct pwddb
*);
187 ((sizeof(sw) == 2 ? (typeof(sw))bswap16((uint16_t)sw) : \
188 (sizeof(sw) == 4 ? (typeof(sw))bswap32((uint32_t)sw) : \
189 (sizeof(sw) == 8 ? (typeof(sw))bswap64((uint64_t)sw) : (abort(), 0)))))
195 closedb(struct pwddb
*db
)
197 if ((*db
->db
->close
)(db
->db
) < 0)
198 wr_error(db
->dbname
);
202 opendb(struct pwddb
*db
, const char *dbname
, const char *username
,
203 uint32_t req_version
, int flags
, mode_t perm
)
205 char buf
[MAXPATHLEN
];
207 (void)snprintf(db
->dbname
, sizeof(db
->dbname
), "%s%s.tmp", prefix
,
210 if (username
!= NULL
) {
211 (void)snprintf(buf
, sizeof(buf
), "%s%s", prefix
, dbname
);
212 cp(buf
, db
->dbname
, perm
);
215 db
->db
= dbopen(db
->dbname
, flags
, perm
, DB_HASH
, &openinfo
);
220 db
->rversion
= getversion(dbname
);
221 if (req_version
== ~0U)
222 db
->wversion
= db
->rversion
;
224 db
->wversion
= req_version
;
226 if (warning
&& db
->rversion
== 0 && db
->wversion
== 0) {
227 warnx("Database %s is a version %u database.",
228 db
->fname
, db
->rversion
);
229 warnx("Use %s -V 1 to upgrade once you've recompiled "
230 "all your binaries.", getprogname());
232 if (db
->wversion
!= db
->rversion
) {
233 if (username
!= NULL
) {
234 (void)fprintf(stderr
, "%s: you cannot change a single "
235 "record from version %u to version %u\n",
236 getprogname(), db
->rversion
, db
->wversion
);
238 } else if (verbose
) {
239 (void)fprintf(stderr
, "%s: changing %s from version "
240 "%u to version %u\n",
241 getprogname(), db
->fname
,
242 db
->rversion
, db
->wversion
);
246 (void)fprintf(stderr
, "%s: %s version %u "
247 "requested %u\n", getprogname(), db
->fname
,
248 db
->rversion
, db
->wversion
);
255 main(int argc
, char *argv
[])
257 int ch
, makeold
, tfd
, lineno
, found
, rv
, hasyp
, secureonly
;
258 struct passwd pwd
, *tpwd
;
262 u_int dbflg
, uid_dbflg
;
263 int newuser
, olduid
, flags
;
266 uint32_t req_version
;
281 while ((ch
= getopt(argc
, argv
, "BLc:d:psu:V:vw")) != -1)
283 case 'B': /* big-endian output */
286 case 'L': /* little-endian output */
287 lorder
= LITTLE_ENDIAN
;
290 cachesize
= atoi(optarg
) * 1024 * 1024;
292 case 'd': /* set prefix */
293 (void)strlcpy(prefix
, optarg
, sizeof(prefix
));
295 case 'p': /* create V7 "file.orig" */
298 case 's': /* modify secure db only */
301 case 'u': /* modify one user only */
305 req_version
= (uint32_t)atoi(optarg
);
307 err(1, "Unknown version %u\n", req_version
);
324 if (username
!= NULL
)
325 if (username
[0] == '+' || username
[0] == '-')
331 * This could be changed to allow the user to interrupt.
332 * Probably not worth the effort.
334 (void)sigemptyset(&set
);
335 (void)sigaddset(&set
, SIGTSTP
);
336 (void)sigaddset(&set
, SIGHUP
);
337 (void)sigaddset(&set
, SIGINT
);
338 (void)sigaddset(&set
, SIGQUIT
);
339 (void)sigaddset(&set
, SIGTERM
);
340 (void)sigprocmask(SIG_BLOCK
, &set
, (sigset_t
*)NULL
);
342 /* We don't care what the user wants. */
345 if (username
== NULL
)
346 flags
= O_RDWR
| O_CREAT
| O_EXCL
;
351 /* Open the original password file */
352 if ((fp
= fopen(pname
, "r")) == NULL
)
355 openinfo
.lorder
= lorder
;
357 if (fstat(fileno(fp
), &st
) == -1)
361 openinfo
.cachesize
= cachesize
;
363 /* Tweak openinfo values for large passwd files. */
364 cachesize
= (u_int
)(st
.st_size
* 20);
365 if (cachesize
> MAX_CACHESIZE
)
366 cachesize
= MAX_CACHESIZE
;
367 else if (cachesize
< MIN_CACHESIZE
)
368 cachesize
= MIN_CACHESIZE
;
369 openinfo
.cachesize
= cachesize
;
372 /* Open the temporary insecure password database. */
374 opendb(&idb
, _PATH_MP_DB
, username
, req_version
,
375 flags
, PERM_INSECURE
);
376 clean
|= FILE_INSECURE
;
380 /* Open the temporary encrypted password database. */
381 opendb(&sdb
, _PATH_SMP_DB
, username
, req_version
, flags
, PERM_SECURE
);
382 clean
|= FILE_SECURE
;
385 * Open file for old password file. Minor trickiness -- don't want to
386 * chance the file already existing, since someone (stupidly) might
387 * still be using this for permission checking. So, open it first and
388 * fdopen the resulting fd. The resulting file should be readable by
392 (void)snprintf(oldpwdfile
, sizeof(oldpwdfile
), "%s.orig",
394 if ((tfd
= open(oldpwdfile
, O_WRONLY
| O_CREAT
| O_EXCL
,
398 if ((oldfp
= fdopen(tfd
, "w")) == NULL
)
402 if (username
!= NULL
) {
407 * Determine if this is a new entry.
409 if (getdbent(&sdb
, _PW_KEYBYNAME
, username
, &tpwd
))
413 olduid
= tpwd
->pw_uid
;
417 uid_dbflg
= R_NOOVERWRITE
;
418 dbflg
= R_NOOVERWRITE
;
422 * If we see something go by that looks like YP, we save a special
423 * pointer record, which if YP is enabled in the C lib, will speed
426 for (lineno
= 0; scan(fp
, &pwd
, &flags
, &lineno
);) {
428 * Create original format password file entry.
431 (void)fprintf(oldfp
, "%s:*:%d:%d:%s:%s:%s\n",
432 pwd
.pw_name
, pwd
.pw_uid
, pwd
.pw_gid
, pwd
.pw_gecos
,
433 pwd
.pw_dir
, pwd
.pw_shell
);
435 wr_error(oldpwdfile
);
438 if (username
== NULL
) {
440 if (pwd
.pw_name
[0] == '+' || pwd
.pw_name
[0] == '-')
443 /* Warn about potentially unsafe uid/gid overrides. */
444 if (pwd
.pw_name
[0] == '+') {
445 if ((flags
& _PASSWORD_NOUID
) == 0 &&
447 warnx("line %d: superuser override "
448 "in YP inclusion", lineno
);
449 if ((flags
& _PASSWORD_NOGID
) == 0 &&
451 warnx("line %d: wheel override "
452 "in YP inclusion", lineno
);
455 /* Write the database entry out. */
457 putdbents(&idb
, &pwd
, "*", flags
, lineno
, dbflg
,
460 } else if (strcmp(username
, pwd
.pw_name
) != 0)
464 warnx("user `%s' listed twice in password file",
470 * Ensure that the text file and database agree on
471 * which line the record is from.
473 rv
= getdbent(&sdb
, _PW_KEYBYNUM
, &lineno
, &tpwd
);
477 } else if (rv
== 1 || strcmp(username
, tpwd
->pw_name
) != 0)
479 else if ((uid_t
)olduid
!= pwd
.pw_uid
) {
481 * If we're changing UID, remove the BYUID
482 * record for the old UID only if it has the
485 if (!getdbent(&sdb
, _PW_KEYBYUID
, &olduid
, &tpwd
)) {
486 if (strcmp(username
, tpwd
->pw_name
) == 0) {
488 deldbent(&idb
, _PW_KEYBYUID
,
490 deldbent(&sdb
, _PW_KEYBYUID
, &olduid
);
497 * If there's an existing BYUID record for the new UID and
498 * the username doesn't match then be sure not to overwrite
501 if (!getdbent(&sdb
, _PW_KEYBYUID
, &pwd
.pw_uid
, &tpwd
))
502 if (strcmp(username
, tpwd
->pw_name
) != 0)
503 uid_dbflg
= R_NOOVERWRITE
;
505 /* Write the database entries out */
507 putdbents(&idb
, &pwd
, "*", flags
, lineno
, dbflg
,
509 putdbents(&sdb
, &pwd
, pwd
.pw_passwd
, flags
, lineno
, dbflg
,
518 /* Store YP token if needed. */
522 /* Close the insecure database. */
527 * If rebuilding the databases, we re-parse the text file and write
528 * the secure entries out in a separate pass.
530 if (username
== NULL
) {
532 for (lineno
= 0; scan(fp
, &pwd
, &flags
, &lineno
);)
533 putdbents(&sdb
, &pwd
, pwd
.pw_passwd
, flags
,
534 lineno
, dbflg
, uid_dbflg
);
536 /* Store YP token if needed. */
540 warnx("user `%s' not found in password file", username
);
544 /* Close the secure database. */
547 /* Install as the real password files. */
549 install(idb
.dbname
, idb
.fname
);
550 install(sdb
.dbname
, sdb
.fname
);
552 /* Install the V7 password file. */
554 if (fflush(oldfp
) == EOF
)
555 wr_error(oldpwdfile
);
556 if (fclose(oldfp
) == EOF
)
557 wr_error(oldpwdfile
);
558 install(oldpwdfile
, _PATH_PASSWD
);
561 /* Set master.passwd permissions, in case caller forgot. */
562 (void)fchmod(fileno(fp
), S_IRUSR
|S_IWUSR
);
563 if (fclose(fp
) == EOF
)
567 * Move the temporary master password file LAST -- chpass(1),
568 * passwd(1), vipw(8) and friends all use its existence to block
569 * other incarnations of themselves. The rename means that
570 * everything is unlocked, as the original file can no longer be
573 install(pname
, _PATH_MASTERPASSWD
);
579 scan(FILE *fp
, struct passwd
*pw
, int *flags
, int *lineno
)
581 static char line
[LINE_MAX
];
585 if (fgets(line
, (int)sizeof(line
), fp
) == NULL
)
590 * ``... if I swallow anything evil, put your fingers down my
594 if ((p
= strchr(line
, '\n')) == NULL
) {
595 warnx("line too long");
596 errno
= EFTYPE
; /* XXX */
600 if (strcmp(line
, "+") == 0) {
601 /* pw_scan() can't handle "+" */
602 (void)strcpy(line
, "+:::::::::");
605 if (!pw_scan(line
, pw
, &oflags
)) {
606 warnx("at line #%d", *lineno
);
607 errno
= EFTYPE
; /* XXX */
616 install(const char *from
, const char *to
)
618 char buf
[MAXPATHLEN
];
622 (void)snprintf(buf
, sizeof(buf
), "%s%s", prefix
, to
);
623 if (rename(from
, buf
)) {
625 (void)snprintf(errbuf
, sizeof(errbuf
), "%s to %s", from
, buf
);
632 rm(const char *victim
)
635 if (unlink(victim
) < 0)
636 warn("unlink(%s)", victim
);
640 cp(const char *from
, const char *to
, mode_t mode
)
642 static char buf
[MAXBSIZE
];
643 int from_fd
, to_fd
, sverrno
;
644 ssize_t rcount
, wcount
;
646 if ((from_fd
= open(from
, O_RDONLY
, 0)) < 0)
648 if ((to_fd
= open(to
, O_WRONLY
| O_CREAT
| O_EXCL
, mode
)) < 0)
650 while ((rcount
= read(from_fd
, buf
, MAXBSIZE
)) > 0) {
651 wcount
= write(to_fd
, buf
, (size_t)rcount
);
652 if (rcount
!= wcount
|| wcount
== -1) {
654 (void)snprintf(buf
, sizeof(buf
), "%s to %s", from
, to
);
662 (void)snprintf(buf
, sizeof(buf
), "%s to %s", from
, to
);
669 wr_error(const char *str
)
676 (void)snprintf(errbuf
, sizeof(errbuf
),
677 "attempt to write %s failed", str
);
684 error(const char *str
)
695 warnx("text files and databases are inconsistent");
696 warnx("re-build the databases without -u");
704 if ((clean
& FILE_ORIG
) != 0)
706 if ((clean
& FILE_SECURE
) != 0)
708 if ((clean
& FILE_INSECURE
) != 0)
715 getversion(const char *fname
)
719 uint32_t version
= 0;
722 db
= dbopen(fname
, O_RDONLY
, PERM_INSECURE
, DB_HASH
, NULL
);
724 /* If we are building on a separate root, assume version 1 */
725 if ((errno
== EACCES
|| errno
== ENOENT
) && prefix
[0])
727 warn("Cannot open database %s", fname
);
730 key
.data
= __UNCONST("VERSION");
731 key
.size
= strlen((const char *)key
.data
) + 1;
733 switch (ret
= (*db
->get
)(db
, &key
, &data
, 0)) {
735 warn("Cannot get VERSION record from database");
738 if (data
.size
!= sizeof(version
)) {
739 warnx("Bad VERSION record in database");
742 (void)memcpy(&version
, data
.data
, sizeof(version
));
746 warnx("Database %s has no version info", fname
);
750 warnx("internal error db->get returns %d", ret
);
760 setversion(struct pwddb
*db
)
763 key
.data
= __UNCONST("VERSION");
764 key
.size
= strlen((const char *)key
.data
) + 1;
766 data
.data
= &db
->wversion
;
767 data
.size
= sizeof(uint32_t);
769 if ((*db
->db
->put
)(db
->db
, &key
, &data
, 0) != 0) {
770 warn("Can't write VERSION record to %s", db
->dbname
);
777 * Write entries to a database for a single user.
779 * The databases actually contain three copies of the original data. Each
780 * password file entry is converted into a rough approximation of a ``struct
781 * passwd'', with the strings placed inline. This object is then stored as
782 * the data for three separate keys. The first key * is the pw_name field
783 * prepended by the _PW_KEYBYNAME character. The second key is the pw_uid
784 * field prepended by the _PW_KEYBYUID character. The third key is the line
785 * number in the original file prepended by the _PW_KEYBYNUM character.
786 * (The special characters are prepended to ensure that the keys do not
789 #define COMPACT(e) for (t = e; (*p++ = *t++) != '\0';)
792 putdbents(struct pwddb
*db
, struct passwd
*pw
, const char *passwd
, int flags
,
793 int lineno
, u_int dbflg
, u_int uid_dbflg
)
796 char buf
[MAX(MAXPATHLEN
, LINE_MAX
* 2)], tbuf
[1024], *p
;
802 (void)memcpy(&pwd
, pw
, sizeof(pwd
));
803 data
.data
= (u_char
*)buf
;
804 key
.data
= (u_char
*)tbuf
;
806 if (lorder
!= BYTE_ORDER
) {
807 pwd
.pw_uid
= SWAP(pwd
.pw_uid
);
808 pwd
.pw_gid
= SWAP(pwd
.pw_gid
);
811 #define WRITEPWTIMEVAR(pwvar) \
813 if (db->wversion == 0 && \
814 /*CONSTCOND*/sizeof(pwvar) == sizeof(uint64_t)) { \
815 uint32_t tmp = (uint32_t)pwvar; \
816 if (lorder != BYTE_ORDER) \
818 (void)memmove(p, &tmp, sizeof(tmp)); \
820 } else if (db->wversion == 1 && \
821 /*CONSTCOND*/sizeof(pwvar) == sizeof(uint32_t)) { \
822 uint64_t tmp = pwvar; \
823 if (lorder != BYTE_ORDER) \
825 (void)memmove(p, &tmp, sizeof(tmp)); \
828 if (lorder != BYTE_ORDER) \
829 pwvar = SWAP(pwvar); \
830 (void)memmove(p, &pwvar, sizeof(pwvar)); \
831 p += sizeof(pwvar); \
833 } while (/*CONSTCOND*/0)
835 /* Create insecure data. */
837 COMPACT(pwd
.pw_name
);
839 (void)memmove(p
, &pwd
.pw_uid
, sizeof(pwd
.pw_uid
));
840 p
+= sizeof(pwd
.pw_uid
);
841 (void)memmove(p
, &pwd
.pw_gid
, sizeof(pwd
.pw_gid
));
842 p
+= sizeof(pwd
.pw_gid
);
843 WRITEPWTIMEVAR(pwd
.pw_change
);
844 COMPACT(pwd
.pw_class
);
845 COMPACT(pwd
.pw_gecos
);
847 COMPACT(pwd
.pw_shell
);
848 WRITEPWTIMEVAR(pwd
.pw_expire
);
850 if (lorder
!= BYTE_ORDER
)
852 (void)memmove(p
, &x
, sizeof(x
));
856 /* Store insecure by name. */
857 tbuf
[0] = _PW_KEYBYNAME
;
858 len
= strlen(pwd
.pw_name
);
859 (void)memmove(tbuf
+ 1, pwd
.pw_name
, len
);
861 if ((*db
->db
->put
)(db
->db
, &key
, &data
, dbflg
) == -1)
862 wr_error(db
->dbname
);
864 /* Store insecure by number. */
865 tbuf
[0] = _PW_KEYBYNUM
;
867 if (lorder
!= BYTE_ORDER
)
869 (void)memmove(tbuf
+ 1, &x
, sizeof(x
));
870 key
.size
= sizeof(x
) + 1;
871 if ((*db
->db
->put
)(db
->db
, &key
, &data
, dbflg
) == -1)
872 wr_error(db
->dbname
);
874 /* Store insecure by uid. */
875 tbuf
[0] = _PW_KEYBYUID
;
876 (void)memmove(tbuf
+ 1, &pwd
.pw_uid
, sizeof(pwd
.pw_uid
));
877 key
.size
= sizeof(pwd
.pw_uid
) + 1;
878 if ((*db
->db
->put
)(db
->db
, &key
, &data
, uid_dbflg
) == -1)
879 wr_error(db
->dbname
);
883 deldbent(struct pwddb
*db
, int type
, void *keyp
)
890 key
.data
= (u_char
*)tbuf
;
892 switch (tbuf
[0] = type
) {
894 len
= strlen((char *)keyp
);
895 (void)memcpy(tbuf
+ 1, keyp
, len
);
902 if (lorder
!= BYTE_ORDER
)
904 (void)memmove(tbuf
+ 1, &x
, sizeof(x
));
905 key
.size
= sizeof(x
) + 1;
909 if ((*db
->db
->del
)(db
->db
, &key
, 0) == -1)
910 wr_error(db
->dbname
);
914 getdbent(struct pwddb
*db
, int type
, void *keyp
, struct passwd
**tpwd
)
916 static char buf
[MAX(MAXPATHLEN
, LINE_MAX
* 2)];
917 static struct passwd pwd
;
924 data
.data
= (u_char
*)buf
;
925 data
.size
= sizeof(buf
);
926 key
.data
= (u_char
*)tbuf
;
928 switch (tbuf
[0] = type
) {
930 len
= strlen((char *)keyp
);
931 (void)memcpy(tbuf
+ 1, keyp
, len
);
938 if (lorder
!= BYTE_ORDER
)
940 (void)memmove(tbuf
+ 1, &x
, sizeof(x
));
941 key
.size
= sizeof(x
) + 1;
945 if ((rv
= (*db
->db
->get
)(db
->db
, &key
, &data
, 0)) == 1)
950 p
= (char *)data
.data
;
959 (void)memcpy(&pwd
.pw_uid
, p
, sizeof(pwd
.pw_uid
));
960 p
+= sizeof(pwd
.pw_uid
);
961 (void)memcpy(&pwd
.pw_gid
, p
, sizeof(pwd
.pw_gid
));
962 p
+= sizeof(pwd
.pw_gid
);
964 #define READPWTIMEVAR(pwvar) \
966 if (db->rversion == 0 && \
967 /*CONSTCOND*/sizeof(pwvar) == sizeof(uint64_t)) { \
969 (void)memcpy(&tmp, p, sizeof(tmp)); \
971 if (lorder != BYTE_ORDER) \
975 } else if (db->rversion == 1 && \
976 /*CONSTCOND*/sizeof(pwvar) == sizeof(uint32_t)) { \
978 (void)memcpy(&tmp, p, sizeof(tmp)); \
980 if (lorder != BYTE_ORDER) \
981 pwvar = (uint32_t)SWAP(tmp); \
983 pwvar = (uint32_t)tmp; \
985 (void)memcpy(&pwvar, p, sizeof(pwvar)); \
986 p += sizeof(pwvar); \
987 if (lorder != BYTE_ORDER) \
988 pwvar = SWAP(pwvar); \
990 } while (/*CONSTCOND*/0)
992 READPWTIMEVAR(pwd
.pw_change
);
1001 while (*p
++ != '\0')
1004 while (*p
++ != '\0')
1007 READPWTIMEVAR(pwd
.pw_expire
);
1009 if (lorder
!= BYTE_ORDER
) {
1010 pwd
.pw_uid
= SWAP(pwd
.pw_uid
);
1011 pwd
.pw_gid
= SWAP(pwd
.pw_gid
);
1019 putyptoken(struct pwddb
*db
)
1023 key
.data
= __UNCONST(__yp_token
);
1024 key
.size
= strlen(__yp_token
);
1025 data
.data
= (u_char
*)NULL
;
1028 if ((*db
->db
->put
)(db
->db
, &key
, &data
, R_NOOVERWRITE
) == -1)
1029 wr_error(db
->dbname
);
1036 (void)fprintf(stderr
,
1037 "Usage: %s [-BLpsvw] [-c cachesize] [-d directory] [-u user] "
1038 "[-V version] file\n",