Thu Jun 18 21:59:24 2009 UTC ()
remove duplicated code by merging the insecure and secure database handling.
add warning flag.


(christos)
diff -r1.24 -r1.25 src/usr.sbin/pwd_mkdb/pwd_mkdb.8
diff -r1.41 -r1.42 src/usr.sbin/pwd_mkdb/pwd_mkdb.c

cvs diff -r1.24 -r1.25 src/usr.sbin/pwd_mkdb/pwd_mkdb.8 (switch to unified diff)

--- src/usr.sbin/pwd_mkdb/pwd_mkdb.8 2009/06/18 17:46:24 1.24
+++ src/usr.sbin/pwd_mkdb/pwd_mkdb.8 2009/06/18 21:59:24 1.25
@@ -1,211 +1,213 @@ @@ -1,211 +1,213 @@
1.\" $NetBSD: pwd_mkdb.8,v 1.24 2009/06/18 17:46:24 christos Exp $ 1.\" $NetBSD: pwd_mkdb.8,v 1.25 2009/06/18 21:59:24 christos Exp $
2.\" 2.\"
3.\" Copyright (c) 1991, 1993 3.\" Copyright (c) 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
5.\" 5.\"
6.\" Redistribution and use in source and binary forms, with or without 6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions 7.\" modification, are permitted provided that the following conditions
8.\" are met: 8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright 9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer. 10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the 12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution. 13.\" documentation and/or other materials provided with the distribution.
14.\" 3. Neither the name of the University nor the names of its contributors 14.\" 3. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software 15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission. 16.\" without specific prior written permission.
17.\" 17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE. 28.\" SUCH DAMAGE.
29.\" 29.\"
30.\" from: @(#)pwd_mkdb.8 8.2 (Berkeley) 4/27/95 30.\" from: @(#)pwd_mkdb.8 8.2 (Berkeley) 4/27/95
31.\" 31.\"
32.Dd June 18, 2009 32.Dd June 18, 2009
33.Dt PWD_MKDB 8 33.Dt PWD_MKDB 8
34.Os 34.Os
35.Sh NAME 35.Sh NAME
36.Nm pwd_mkdb 36.Nm pwd_mkdb
37.Nd generate the password databases 37.Nd generate the password databases
38.Sh SYNOPSIS 38.Sh SYNOPSIS
39.Nm 39.Nm
40.Op Fl BLpsv 40.Op Fl BLpsvw
41.Op Fl c Ar cachesize 41.Op Fl c Ar cachesize
42.Op Fl d Ar directory 42.Op Fl d Ar directory
43.Op Fl u Ar username 43.Op Fl u Ar username
44.Op Fl V Ar version 44.Op Fl V Ar version
45.Ar file 45.Ar file
46.Sh DESCRIPTION 46.Sh DESCRIPTION
47.Nm 47.Nm
48creates 48creates
49.Xr db 3 49.Xr db 3
50style secure and insecure databases for the specified file. 50style secure and insecure databases for the specified file.
51These databases are then installed into 51These databases are then installed into
52.Dq Pa /etc/spwd.db 52.Dq Pa /etc/spwd.db
53and 53and
54.Dq Pa /etc/pwd.db 54.Dq Pa /etc/pwd.db
55respectively. 55respectively.
56The file is installed into 56The file is installed into
57.Dq Pa /etc/master.passwd . 57.Dq Pa /etc/master.passwd .
58The file must be in the correct format (see 58The file must be in the correct format (see
59.Xr passwd 5 ) . 59.Xr passwd 5 ) .
60It is important to note that the format used in this system is 60It is important to note that the format used in this system is
61different from the historic Version 7 style format. 61different from the historic Version 7 style format.
62.Pp 62.Pp
63The options are as follows: 63The options are as follows:
64.Bl -tag -width flag 64.Bl -tag -width flag
65.It Fl B 65.It Fl B
66Store data in big-endian format (see also 66Store data in big-endian format (see also
67.Fl L ) . 67.Fl L ) .
68.It Fl c Ar cachesize 68.It Fl c Ar cachesize
69Specify the size of the memory cache in megabytes used by the 69Specify the size of the memory cache in megabytes used by the
70hashing library. 70hashing library.
71On systems with a large user base, a small cache size can lead to 71On systems with a large user base, a small cache size can lead to
72prohibitively long database file rebuild times. 72prohibitively long database file rebuild times.
73As a rough guide, the memory usage of 73As a rough guide, the memory usage of
74.Nm 74.Nm
75in megabytes will be a little bit more than twice the figure 75in megabytes will be a little bit more than twice the figure
76specified here. 76specified here.
77If unspecified, this value will be calculated based on the size of 77If unspecified, this value will be calculated based on the size of
78the input file up to a maximum of 8 megabytes. 78the input file up to a maximum of 8 megabytes.
79.It Fl d Ar directory 79.It Fl d Ar directory
80Change the root directory of the generated files from 80Change the root directory of the generated files from
81.Dq Pa / 81.Dq Pa /
82to 82to
83.Ar directory . 83.Ar directory .
84.It Fl L 84.It Fl L
85Store data in little-endian format (see also 85Store data in little-endian format (see also
86.Fl B ) . 86.Fl B ) .
87.It Fl p 87.It Fl p
88Create a Version 7 style password file and install it into 88Create a Version 7 style password file and install it into
89.Dq Pa /etc/passwd . 89.Dq Pa /etc/passwd .
90.It Fl s 90.It Fl s
91Update the secure database only. 91Update the secure database only.
92This is useful when only encrypted passwords have changed. 92This is useful when only encrypted passwords have changed.
93This option negates the effect of any 93This option negates the effect of any
94.Fl p 94.Fl p
95option. 95option.
96.It Fl u Ar name 96.It Fl u Ar name
97Don't re-build the database files, but instead modify or add entries 97Don't re-build the database files, but instead modify or add entries
98for the specified user only. 98for the specified user only.
99This option may only be used when the line number and user name in 99This option may only be used when the line number and user name in
100the password file have not changed, or when adding a new user from 100the password file have not changed, or when adding a new user from
101the last line in the password file. 101the last line in the password file.
102.It Fl V Ar version 102.It Fl V Ar version
103Upgrade or downgrade databases to the numbered version. Version 103Upgrade or downgrade databases to the numbered version. Version
104.Dv 0 104.Dv 0
105is the old format (up to and including 105is the old format (up to and including
106.Nx 5.0 ) 106.Nx 5.0 )
107with the 4 byte time fields and version 107with the 4 byte time fields and version
108.Dv 1 108.Dv 1
109is the new format with the 8 byte time fields (greater than 109is the new format with the 8 byte time fields (greater than
110.Nx 5.0 ). 110.Nx 5.0 ).
111.Nx 5.0 111.Nx 5.0
112cannot read version 112cannot read version
113.Dv 1 113.Dv 1
114databases. 114databases.
115All versions above 115All versions above
116.Nx 5.0 116.Nx 5.0
117can read and write both version 117can read and write both version
118.Dv 0 118.Dv 0
119and version 119and version
120.Dv 1 120.Dv 1
121databases. 121databases.
122By default the databases stay in the version they were before the command 122By default the databases stay in the version they were before the command
123was run. 123was run.
124.It Fl v 124.It Fl v
125Mention when a version change occurs. 125Mention when a version change occurs.
 126.It Fl w
 127Print a warning if the system is using old style databases.
126.El 128.El
127.Pp 129.Pp
128The two databases differ in that the secure version contains the user's 130The two databases differ in that the secure version contains the user's
129encrypted password and the insecure version has an asterisk 131encrypted password and the insecure version has an asterisk
130.Pq Dq * . 132.Pq Dq * .
131.Pp 133.Pp
132The databases are used by the C library password routines (see 134The databases are used by the C library password routines (see
133.Xr getpwent 3 ) . 135.Xr getpwent 3 ) .
134.Sh EXIT STATUS 136.Sh EXIT STATUS
135.Nm 137.Nm
136exits zero on success, non-zero on failure. 138exits zero on success, non-zero on failure.
137.Sh FILES 139.Sh FILES
138.Bl -tag -width Pa -compact 140.Bl -tag -width Pa -compact
139.It Pa /etc/master.passwd 141.It Pa /etc/master.passwd
140The current password file. 142The current password file.
141.It Pa /etc/passwd 143.It Pa /etc/passwd
142A Version 7 format password file. 144A Version 7 format password file.
143.It Pa /etc/pwd.db 145.It Pa /etc/pwd.db
144The insecure password database file. 146The insecure password database file.
145.It Pa /etc/pwd.db.tmp 147.It Pa /etc/pwd.db.tmp
146A temporary file. 148A temporary file.
147.It Pa /etc/spwd.db 149.It Pa /etc/spwd.db
148The secure password database file. 150The secure password database file.
149.It Pa /etc/spwd.db.tmp 151.It Pa /etc/spwd.db.tmp
150A temporary file. 152A temporary file.
151.El 153.El
152.Sh BUGS 154.Sh BUGS
153Because of the necessity for atomic update of the password files, 155Because of the necessity for atomic update of the password files,
154.Nm 156.Nm
155uses 157uses
156.Xr rename 2 158.Xr rename 2
157to install them. 159to install them.
158This, however, requires that the file specified on the command line live 160This, however, requires that the file specified on the command line live
159on the same file system as the 161on the same file system as the
160.Dq Pa /etc 162.Dq Pa /etc
161directory. 163directory.
162.Pp 164.Pp
163There are the obvious races with multiple people running 165There are the obvious races with multiple people running
164.Nm 166.Nm
165on different password files at the same time. 167on different password files at the same time.
166The front-ends to 168The front-ends to
167.Xr chpass 1 , 169.Xr chpass 1 ,
168.Xr passwd 1 , 170.Xr passwd 1 ,
169.Xr useradd 8 , 171.Xr useradd 8 ,
170.Xr userdel 8 , 172.Xr userdel 8 ,
171.Xr usermod 8 , 173.Xr usermod 8 ,
172and 174and
173.Xr vipw 8 175.Xr vipw 8
174handle the locking necessary to avoid this problem. 176handle the locking necessary to avoid this problem.
175.Pp 177.Pp
176The database files are copied when the 178The database files are copied when the
177.Fl u 179.Fl u
178option is used. 180option is used.
179Real locking would make this unnecessary. 181Real locking would make this unnecessary.
180.Pp 182.Pp
181Although the DB format is endian-transparent, the data stored in 183Although the DB format is endian-transparent, the data stored in
182the DB is not. 184the DB is not.
183Also, the format doesn't lend itself to insertion or removal of 185Also, the format doesn't lend itself to insertion or removal of
184records from arbitrary locations in the password file. 186records from arbitrary locations in the password file.
185This is difficult to fix without breaking compatibility. 187This is difficult to fix without breaking compatibility.
186.Pp 188.Pp
187Using the 189Using the
188.Fl u 190.Fl u
189option on a system where multiple users share the same UID can have 191option on a system where multiple users share the same UID can have
190unexpected results. 192unexpected results.
191.Sh COMPATIBILITY 193.Sh COMPATIBILITY
192Previous versions of the system had a program similar to 194Previous versions of the system had a program similar to
193.Nm 195.Nm
194which built 196which built
195.Em dbm 197.Em dbm
196style databases for the password file but depended on the calling programs 198style databases for the password file but depended on the calling programs
197to install them. 199to install them.
198The program was renamed in order that previous users of the program 200The program was renamed in order that previous users of the program
199not be surprised by the changes in functionality. 201not be surprised by the changes in functionality.
200.Sh SEE ALSO 202.Sh SEE ALSO
201.Xr chpass 1 , 203.Xr chpass 1 ,
202.Xr passwd 1 , 204.Xr passwd 1 ,
203.Xr pwhash 1 , 205.Xr pwhash 1 ,
204.Xr db 3 , 206.Xr db 3 ,
205.Xr getpwent 3 , 207.Xr getpwent 3 ,
206.Xr pw_mkdb 3 , 208.Xr pw_mkdb 3 ,
207.Xr passwd 5 , 209.Xr passwd 5 ,
208.Xr useradd 8 , 210.Xr useradd 8 ,
209.Xr userdel 8 , 211.Xr userdel 8 ,
210.Xr usermod 8 , 212.Xr usermod 8 ,
211.Xr vipw 8 213.Xr vipw 8

cvs diff -r1.41 -r1.42 src/usr.sbin/pwd_mkdb/pwd_mkdb.c (switch to unified diff)

--- src/usr.sbin/pwd_mkdb/pwd_mkdb.c 2009/06/18 17:46:24 1.41
+++ src/usr.sbin/pwd_mkdb/pwd_mkdb.c 2009/06/18 21:59:24 1.42
@@ -1,1020 +1,1035 @@ @@ -1,1020 +1,1035 @@
1/* $NetBSD: pwd_mkdb.c,v 1.41 2009/06/18 17:46:24 christos Exp $ */ 1/* $NetBSD: pwd_mkdb.c,v 1.42 2009/06/18 21:59:24 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2000, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 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 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 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * Copyright (c) 1991, 1993, 1994 30 * Copyright (c) 1991, 1993, 1994
31 * The Regents of the University of California. All rights reserved. 31 * The Regents of the University of California. All rights reserved.
32 * 32 *
33 * Redistribution and use in source and binary forms, with or without 33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions 34 * modification, are permitted provided that the following conditions
35 * are met: 35 * are met:
36 * 1. Redistributions of source code must retain the above copyright 36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer. 37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright 38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the 39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution. 40 * documentation and/or other materials provided with the distribution.
41 * 3. Neither the name of the University nor the names of its contributors 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 42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission. 43 * without specific prior written permission.
44 * 44 *
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE. 55 * SUCH DAMAGE.
56 */ 56 */
57 57
58/* 58/*
59 * Portions Copyright(C) 1994, Jason Downs. All rights reserved. 59 * Portions Copyright(C) 1994, Jason Downs. All rights reserved.
60 * 60 *
61 * Redistribution and use in source and binary forms, with or without 61 * Redistribution and use in source and binary forms, with or without
62 * modification, are permitted provided that the following conditions 62 * modification, are permitted provided that the following conditions
63 * are met: 63 * are met:
64 * 1. Redistributions of source code must retain the above copyright 64 * 1. Redistributions of source code must retain the above copyright
65 * notice, this list of conditions and the following disclaimer. 65 * notice, this list of conditions and the following disclaimer.
66 * 2. Redistributions in binary form must reproduce the above copyright 66 * 2. Redistributions in binary form must reproduce the above copyright
67 * notice, this list of conditions and the following disclaimer in the 67 * notice, this list of conditions and the following disclaimer in the
68 * documentation and/or other materials provided with the distribution. 68 * documentation and/or other materials provided with the distribution.
69 * 69 *
70 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS 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 71 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
72 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 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, 73 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
74 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 74 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
75 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 75 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
76 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 76 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
77 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 77 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
78 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 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 79 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
80 * SUCH DAMAGE. 80 * SUCH DAMAGE.
81 */ 81 */
82 82
83#if HAVE_NBTOOL_CONFIG_H 83#if HAVE_NBTOOL_CONFIG_H
84#include "nbtool_config.h" 84#include "nbtool_config.h"
85#endif 85#endif
86 86
87#include <sys/cdefs.h> 87#include <sys/cdefs.h>
88#if !defined(lint) 88#if !defined(lint)
89__COPYRIGHT("@(#) Copyright (c) 2000, 2009\ 89__COPYRIGHT("@(#) Copyright (c) 2000, 2009\
90 The NetBSD Foundation, Inc. All rights reserved.\ 90 The NetBSD Foundation, Inc. All rights reserved.\
91 Copyright (c) 1991, 1993, 1994\ 91 Copyright (c) 1991, 1993, 1994\
92 The Regents of the University of California. All rights reserved."); 92 The Regents of the University of California. All rights reserved.");
93__SCCSID("from: @(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94"); 93__SCCSID("from: @(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94");
94__RCSID("$NetBSD: pwd_mkdb.c,v 1.41 2009/06/18 17:46:24 christos Exp $"); 94__RCSID("$NetBSD: pwd_mkdb.c,v 1.42 2009/06/18 21:59:24 christos Exp $");
95#endif /* not lint */ 95#endif /* not lint */
96 96
97#if HAVE_NBTOOL_CONFIG_H 97#if HAVE_NBTOOL_CONFIG_H
98#include "compat_pwd.h" 98#include "compat_pwd.h"
99#else 99#else
100#include <pwd.h> 100#include <pwd.h>
101#endif 101#endif
102 102
103#include <sys/param.h> 103#include <sys/param.h>
104#include <sys/stat.h> 104#include <sys/stat.h>
105#include <sys/types.h> 105#include <sys/types.h>
106 106
107#ifndef HAVE_NBTOOL_CONFIG_H 107#ifndef HAVE_NBTOOL_CONFIG_H
108#include <machine/bswap.h> 108#include <machine/bswap.h>
109#endif 109#endif
110 110
111#include <db.h> 111#include <db.h>
112#include <err.h> 112#include <err.h>
113#include <errno.h> 113#include <errno.h>
114#include <fcntl.h> 114#include <fcntl.h>
115#include <limits.h> 115#include <limits.h>
116#include <signal.h> 116#include <signal.h>
117#include <stdio.h> 117#include <stdio.h>
118#include <stdlib.h> 118#include <stdlib.h>
119#include <string.h> 119#include <string.h>
120#include <unistd.h> 120#include <unistd.h>
121#include <util.h> 121#include <util.h>
122 122
123#define MAX_CACHESIZE 8*1024*1024 123#define MAX_CACHESIZE 8*1024*1024
124#define MIN_CACHESIZE 2*1024*1024 124#define MIN_CACHESIZE 2*1024*1024
125 125
126#define PERM_INSECURE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) 126#define PERM_INSECURE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
127#define PERM_SECURE (S_IRUSR | S_IWUSR) 127#define PERM_SECURE (S_IRUSR | S_IWUSR)
128 128
129#if HAVE_NBTOOL_CONFIG_H 129#if HAVE_NBTOOL_CONFIG_H
130static const char __yp_token[] = "__YP!"; 130static const char __yp_token[] = "__YP!";
131#else 131#else
132/* Pull this out of the C library. */ 132/* Pull this out of the C library. */
133extern const char __yp_token[]; 133extern const char __yp_token[];
134#endif 134#endif
135 135
136static HASHINFO openinfo = { 136static HASHINFO openinfo = {
137 4096, /* bsize */ 137 4096, /* bsize */
138 32, /* ffactor */ 138 32, /* ffactor */
139 256, /* nelem */ 139 256, /* nelem */
140 0, /* cachesize */ 140 0, /* cachesize */
141 NULL, /* hash() */ 141 NULL, /* hash() */
142 0 /* lorder */ 142 0 /* lorder */
143}; 143};
144 144
145#define FILE_INSECURE 0x01 145#define FILE_INSECURE 0x01
146#define FILE_SECURE 0x02 146#define FILE_SECURE 0x02
147#define FILE_ORIG 0x04 147#define FILE_ORIG 0x04
148 148
 149
 150struct pwddb {
 151 DB *db;
 152 char dbname[MAX(MAXPATHLEN, LINE_MAX * 2)];
 153 const char *fname;
 154 uint32_t rversion;
 155 uint32_t wversion;
 156};
 157
149static char *pname; /* password file name */ 158static char *pname; /* password file name */
150static char prefix[MAXPATHLEN]; 159static char prefix[MAXPATHLEN];
151static char oldpwdfile[MAX(MAXPATHLEN, LINE_MAX * 2)]; 160static char oldpwdfile[MAX(MAXPATHLEN, LINE_MAX * 2)];
152static char pwd_db_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)]; 
153static char pwd_Sdb_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)]; 
154static int lorder = BYTE_ORDER; 161static int lorder = BYTE_ORDER;
155static int clean; 162static int clean;
 163static int verbose;
 164static int warning;
 165static struct pwddb sdb, idb;
 166
156 167
157void bailout(void) __attribute__((__noreturn__)); 168void bailout(void) __attribute__((__noreturn__));
158void cp(const char *, const char *, mode_t); 169void cp(const char *, const char *, mode_t);
159int deldbent(DB *, const char *, int, void *); 170int deldbent(struct pwddb *, int, void *);
160void error(const char *); 171void error(const char *);
161int getdbent(DB *, const char *, int, void *, struct passwd **, uint32_t); 172int getdbent(struct pwddb *, int, void *, struct passwd **);
162void inconsistancy(void); 173void inconsistancy(void);
163void install(const char *, const char *); 174void install(const char *, const char *);
164int main(int, char **); 175int main(int, char **);
165void putdbents(DB *, struct passwd *, const char *, int, const char *, int, 176void putdbents(struct pwddb *, struct passwd *, const char *, int, int, int,
166 int, int, uint32_t); 177 int);
167void putyptoken(DB *, const char *); 178void putyptoken(struct pwddb *);
168void rm(const char *); 179void rm(const char *);
169int scan(FILE *, struct passwd *, int *, int *); 180int scan(FILE *, struct passwd *, int *, int *);
170void usage(void) __attribute__((__noreturn__)); 181void usage(void) __attribute__((__noreturn__));
171void wr_error(const char *); 182void wr_error(const char *);
172void checkversion(uint32_t, uint32_t); 183void checkversion(struct pwddb *);
173uint32_t getversion(const char *); 184uint32_t getversion(const char *);
174void setversion(DB *, uint32_t); 185void setversion(struct pwddb *);
175 186
176#define SWAP(sw) \ 187#define SWAP(sw) \
177 ((sizeof(sw) == 2 ? (typeof(sw))bswap16((uint16_t)sw) : \ 188 ((sizeof(sw) == 2 ? (typeof(sw))bswap16((uint16_t)sw) : \
178 (sizeof(sw) == 4 ? (typeof(sw))bswap32((uint32_t)sw) : \ 189 (sizeof(sw) == 4 ? (typeof(sw))bswap32((uint32_t)sw) : \
179 (sizeof(sw) == 8 ? (typeof(sw))bswap64((uint64_t)sw) : (abort(), 0))))) 190 (sizeof(sw) == 8 ? (typeof(sw))bswap64((uint64_t)sw) : (abort(), 0)))))
180 191
 192static void
 193closedb(struct pwddb *db)
 194{
 195 if ((*db->db->close)(db->db) < 0)
 196 wr_error(db->dbname);
 197}
 198
 199static void
 200opendb(struct pwddb *db, const char *dbname, const char *username,
 201 uint32_t req_version, int flags, int perm)
 202{
 203 char buf[MAXPATHLEN];
 204
 205 (void)snprintf(db->dbname, sizeof(db->dbname), "%s%s.tmp", prefix,
 206 dbname);
 207
 208 if (username != NULL) {
 209 snprintf(buf, sizeof(buf), "%s%s", prefix, dbname);
 210 cp(buf, db->dbname, perm);
 211 }
 212
 213 db->db = dbopen(db->dbname, flags, perm, DB_HASH, &openinfo);
 214 if (db->db == NULL)
 215 error(db->dbname);
 216
 217 db->fname = dbname;
 218 db->rversion = getversion(dbname);
 219 if (req_version == ~0U)
 220 db->wversion = db->rversion;
 221 else
 222 db->wversion = req_version;
 223
 224 if (warning && db->rversion == 0 && db->wversion == 0) {
 225 warnx("Database %s is a version %u database.",
 226 db->fname, db->rversion);
 227 warnx("Use %s -V 1 to upgrade once you've recompiled "
 228 "all your binaries.", getprogname());
 229 }
 230 if (verbose)
 231 fprintf(stderr, "%s: %s version %u requested %u\n",
 232 getprogname(), db->fname, db->rversion, db->wversion);
 233
 234 if (db->wversion != db->rversion) {
 235 if (username != NULL)
 236 checkversion(db);
 237 else if (verbose) {
 238 fprintf(stderr, "%s: changing %s from version "
 239 "%u to version %u\n",
 240 getprogname(), db->fname,
 241 db->rversion, db->wversion);
 242 }
 243 }
 244 setversion(db);
 245}
 246
181int 247int
182main(int argc, char *argv[]) 248main(int argc, char *argv[])
183{ 249{
184 int ch, makeold, tfd, lineno, found, rv, hasyp, secureonly, verbose; 250 int ch, makeold, tfd, lineno, found, rv, hasyp, secureonly;
185 struct passwd pwd, *tpwd; 251 struct passwd pwd, *tpwd;
186 char *username; 252 char *username;
187 DB *dp, *edp; 
188 FILE *fp, *oldfp; 253 FILE *fp, *oldfp;
189 sigset_t set; 254 sigset_t set;
190 int dbflg, uid_dbflg, newuser, olduid, flags; 255 int dbflg, uid_dbflg, newuser, olduid, flags;
191 char buf[MAXPATHLEN]; 
192 struct stat st; 256 struct stat st;
193 u_int cachesize; 257 u_int cachesize;
194 uint32_t version, req_version; 258 uint32_t req_version;
195 uint32_t sversion, req_sversion; 
196 259
197 prefix[0] = '\0'; 260 prefix[0] = '\0';
198 makeold = 0; 261 makeold = 0;
199 oldfp = NULL; 262 oldfp = NULL;
200 username = NULL; 263 username = NULL;
201 hasyp = 0; 264 hasyp = 0;
202 secureonly = 0; 265 secureonly = 0;
203 found = 0; 266 found = 0;
204 newuser = 0; 267 newuser = 0;
205 dp = NULL; 
206 cachesize = 0; 268 cachesize = 0;
207 verbose = 0; 269 verbose = 0;
208 req_version = req_sversion = ~0U; 270 warning = 0;
 271 req_version = ~0U;
209 272
210 while ((ch = getopt(argc, argv, "BLc:d:psu:V:v")) != -1) 273 while ((ch = getopt(argc, argv, "BLc:d:psu:V:vw")) != -1)
211 switch (ch) { 274 switch (ch) {
212 case 'B': /* big-endian output */ 275 case 'B': /* big-endian output */
213 lorder = BIG_ENDIAN; 276 lorder = BIG_ENDIAN;
214 break; 277 break;
215 case 'L': /* little-endian output */ 278 case 'L': /* little-endian output */
216 lorder = LITTLE_ENDIAN; 279 lorder = LITTLE_ENDIAN;
217 break; 280 break;
218 case 'c': 281 case 'c':
219 cachesize = atoi(optarg) * 1024 * 1024; 282 cachesize = atoi(optarg) * 1024 * 1024;
220 break; 283 break;
221 case 'd': /* set prefix */ 284 case 'd': /* set prefix */
222 strlcpy(prefix, optarg, sizeof(prefix)); 285 strlcpy(prefix, optarg, sizeof(prefix));
223 break; 286 break;
224 case 'p': /* create V7 "file.orig" */ 287 case 'p': /* create V7 "file.orig" */
225 makeold = 1; 288 makeold = 1;
226 break; 289 break;
227 case 's': /* modify secure db only */ 290 case 's': /* modify secure db only */
228 secureonly = 1; 291 secureonly = 1;
229 break; 292 break;
230 case 'u': /* modify one user only */ 293 case 'u': /* modify one user only */
231 username = optarg; 294 username = optarg;
232 break; 295 break;
233 case 'V': 296 case 'V':
234 req_sversion = req_version = (uint32_t)atoi(optarg); 297 req_version = (uint32_t)atoi(optarg);
235 if (req_version > 1) 298 if (req_version > 1)
236 err(1, "Unknown version %u\n", req_version); 299 err(1, "Unknown version %u\n", req_version);
237 break; 300 break;
238 case 'v': 301 case 'v':
239 verbose++; 302 verbose++;
240 break; 303 break;
 304 case 'w':
 305 warning++;
 306 break;
241 case '?': 307 case '?':
242 default: 308 default:
243 usage(); 309 usage();
244 } 310 }
245 argc -= optind; 311 argc -= optind;
246 argv += optind; 312 argv += optind;
247 313
248 if (argc != 1) 314 if (argc != 1)
249 usage(); 315 usage();
250 if (username != NULL) 316 if (username != NULL)
251 if (username[0] == '+' || username[0] == '-') 317 if (username[0] == '+' || username[0] == '-')
252 usage(); 318 usage();
253 if (secureonly) 319 if (secureonly)
254 makeold = 0; 320 makeold = 0;
255 321
256 /* 322 /*
257 * This could be changed to allow the user to interrupt. 323 * This could be changed to allow the user to interrupt.
258 * Probably not worth the effort. 324 * Probably not worth the effort.
259 */ 325 */
260 sigemptyset(&set); 326 sigemptyset(&set);
261 sigaddset(&set, SIGTSTP); 327 sigaddset(&set, SIGTSTP);
262 sigaddset(&set, SIGHUP); 328 sigaddset(&set, SIGHUP);
263 sigaddset(&set, SIGINT); 329 sigaddset(&set, SIGINT);
264 sigaddset(&set, SIGQUIT); 330 sigaddset(&set, SIGQUIT);
265 sigaddset(&set, SIGTERM); 331 sigaddset(&set, SIGTERM);
266 (void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL); 332 (void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
267 333
268 /* We don't care what the user wants. */ 334 /* We don't care what the user wants. */
269 (void)umask(0); 335 (void)umask(0);
270 336
271 if (username == NULL) 337 if (username == NULL)
272 flags = O_RDWR | O_CREAT | O_EXCL; 338 flags = O_RDWR | O_CREAT | O_EXCL;
273 else 339 else
274 flags = O_RDWR; 340 flags = O_RDWR;
275 341
276 pname = *argv; 342 pname = *argv;
277 /* Open the original password file */ 343 /* Open the original password file */
278 if ((fp = fopen(pname, "r")) == NULL) 344 if ((fp = fopen(pname, "r")) == NULL)
279 error(pname); 345 error(pname);
280 346
281 openinfo.lorder = lorder; 347 openinfo.lorder = lorder;
282 348
283 if (fstat(fileno(fp), &st) == -1) 349 if (fstat(fileno(fp), &st) == -1)
284 error(pname); 350 error(pname);
285 351
286 if (cachesize) { 352 if (cachesize) {
287 openinfo.cachesize = cachesize; 353 openinfo.cachesize = cachesize;
288 } else { 354 } else {
289 /* Tweak openinfo values for large passwd files. */ 355 /* Tweak openinfo values for large passwd files. */
290 cachesize = st.st_size * 20; 356 cachesize = st.st_size * 20;
291 if (cachesize > MAX_CACHESIZE) 357 if (cachesize > MAX_CACHESIZE)
292 cachesize = MAX_CACHESIZE; 358 cachesize = MAX_CACHESIZE;
293 else if (cachesize < MIN_CACHESIZE) 359 else if (cachesize < MIN_CACHESIZE)
294 cachesize = MIN_CACHESIZE; 360 cachesize = MIN_CACHESIZE;
295 openinfo.cachesize = cachesize; 361 openinfo.cachesize = cachesize;
296 } 362 }
297 363
298 /* Open the temporary insecure password database. */ 364 /* Open the temporary insecure password database. */
299 if (!secureonly) { 365 if (!secureonly) {
300 (void)snprintf(pwd_db_tmp, sizeof(pwd_db_tmp), "%s%s.tmp", 366 opendb(&idb, _PATH_MP_DB, username, req_version,
301 prefix, _PATH_MP_DB); 367 flags, PERM_INSECURE);
302 if (username != NULL) { 
303 snprintf(buf, sizeof(buf), "%s" _PATH_MP_DB, prefix); 
304 cp(buf, pwd_db_tmp, PERM_INSECURE); 
305 } 
306 dp = dbopen(pwd_db_tmp, flags, PERM_INSECURE, DB_HASH, 
307 &openinfo); 
308 if (dp == NULL) 
309 error(pwd_db_tmp); 
310 clean |= FILE_INSECURE; 368 clean |= FILE_INSECURE;
311 version = getversion(_PATH_MP_DB); 
312 if (req_version == ~0U) 
313 req_version = version; 
314 if (verbose) 
315 fprintf(stderr, "%s: " _PATH_MP_DB 
316 " version %u requested %u\n", 
317 getprogname(), version, req_version); 
318 if (username != NULL && req_version != version) 
319 checkversion(req_version, version); 
320 else if (req_version != version) { 
321 if (verbose) 
322 fprintf(stderr, "%s: changing " _PATH_MP_DB 
323 " from version %u to version %u\n", 
324 getprogname(), version, req_version); 
325 setversion(dp, req_version); 
326 } 
327 } 369 }
 370
328 371
329 /* Open the temporary encrypted password database. */ 372 /* Open the temporary encrypted password database. */
330 (void)snprintf(pwd_Sdb_tmp, sizeof(pwd_Sdb_tmp), "%s%s.tmp", prefix, 373 opendb(&sdb, _PATH_SMP_DB, username, req_version, flags, PERM_SECURE);
331 _PATH_SMP_DB); 
332 if (username != NULL) { 
333 snprintf(buf, sizeof(buf), "%s" _PATH_SMP_DB, prefix); 
334 cp(buf, pwd_Sdb_tmp, PERM_SECURE); 
335 } 
336 edp = dbopen(pwd_Sdb_tmp, flags, PERM_SECURE, DB_HASH, &openinfo); 
337 if (!edp) 
338 error(pwd_Sdb_tmp); 
339 clean |= FILE_SECURE; 374 clean |= FILE_SECURE;
340 sversion = getversion(_PATH_SMP_DB); 
341 if (verbose) 
342 fprintf(stderr, "%s: " _PATH_SMP_DB 
343 " version %u requested %u\n", 
344 getprogname(), sversion, req_version); 
345 if (req_sversion == ~0U) 
346 req_sversion = sversion; 
347 if (username != NULL) 
348 checkversion(req_sversion, sversion); 
349 else if (req_sversion != sversion) { 
350 if (verbose) 
351 fprintf(stderr, "%s: changing " _PATH_SMP_DB 
352 " from version %u to version %u\n", 
353 getprogname(), sversion, req_sversion); 
354 setversion(edp, req_sversion); 
355 } 
356 375
357 /* 376 /*
358 * Open file for old password file. Minor trickiness -- don't want to 377 * Open file for old password file. Minor trickiness -- don't want to
359 * chance the file already existing, since someone (stupidly) might 378 * chance the file already existing, since someone (stupidly) might
360 * still be using this for permission checking. So, open it first and 379 * still be using this for permission checking. So, open it first and
361 * fdopen the resulting fd. The resulting file should be readable by 380 * fdopen the resulting fd. The resulting file should be readable by
362 * everyone. 381 * everyone.
363 */ 382 */
364 if (makeold) { 383 if (makeold) {
365 (void)snprintf(oldpwdfile, sizeof(oldpwdfile), "%s.orig", 384 (void)snprintf(oldpwdfile, sizeof(oldpwdfile), "%s.orig",
366 pname); 385 pname);
367 if ((tfd = open(oldpwdfile, O_WRONLY | O_CREAT | O_EXCL, 386 if ((tfd = open(oldpwdfile, O_WRONLY | O_CREAT | O_EXCL,
368 PERM_INSECURE)) < 0) 387 PERM_INSECURE)) < 0)
369 error(oldpwdfile); 388 error(oldpwdfile);
370 clean |= FILE_ORIG; 389 clean |= FILE_ORIG;
371 if ((oldfp = fdopen(tfd, "w")) == NULL) 390 if ((oldfp = fdopen(tfd, "w")) == NULL)
372 error(oldpwdfile); 391 error(oldpwdfile);
373 } 392 }
374 393
375 if (username != NULL) { 394 if (username != NULL) {
376 uid_dbflg = 0; 395 uid_dbflg = 0;
377 dbflg = 0; 396 dbflg = 0;
378 397
379 /* 398 /*
380 * Determine if this is a new entry. 399 * Determine if this is a new entry.
381 */ 400 */
382 if (getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYNAME, username, &tpwd, 401 if (getdbent(&sdb, _PW_KEYBYNAME, username, &tpwd))
383 sversion)) 
384 newuser = 1; 402 newuser = 1;
385 else { 403 else {
386 newuser = 0; 404 newuser = 0;
387 olduid = tpwd->pw_uid; 405 olduid = tpwd->pw_uid;
388 } 406 }
389 407
390 } else { 408 } else {
391 uid_dbflg = R_NOOVERWRITE; 409 uid_dbflg = R_NOOVERWRITE;
392 dbflg = R_NOOVERWRITE; 410 dbflg = R_NOOVERWRITE;
393 } 411 }
394 412
395 /* 413 /*
396 * If we see something go by that looks like YP, we save a special 414 * If we see something go by that looks like YP, we save a special
397 * pointer record, which if YP is enabled in the C lib, will speed 415 * pointer record, which if YP is enabled in the C lib, will speed
398 * things up. 416 * things up.
399 */ 417 */
400 for (lineno = 0; scan(fp, &pwd, &flags, &lineno);) { 418 for (lineno = 0; scan(fp, &pwd, &flags, &lineno);) {
401 /* 419 /*
402 * Create original format password file entry. 420 * Create original format password file entry.
403 */ 421 */
404 if (makeold) { 422 if (makeold) {
405 (void)fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n", 423 (void)fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n",
406 pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos, 424 pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos,
407 pwd.pw_dir, pwd.pw_shell); 425 pwd.pw_dir, pwd.pw_shell);
408 if (ferror(oldfp)) 426 if (ferror(oldfp))
409 wr_error(oldpwdfile); 427 wr_error(oldpwdfile);
410 } 428 }
411 429
412 if (username == NULL) { 430 if (username == NULL) {
413 /* Look like YP? */ 431 /* Look like YP? */
414 if (pwd.pw_name[0] == '+' || pwd.pw_name[0] == '-') 432 if (pwd.pw_name[0] == '+' || pwd.pw_name[0] == '-')
415 hasyp++; 433 hasyp++;
416 434
417 /* Warn about potentially unsafe uid/gid overrides. */ 435 /* Warn about potentially unsafe uid/gid overrides. */
418 if (pwd.pw_name[0] == '+') { 436 if (pwd.pw_name[0] == '+') {
419 if ((flags & _PASSWORD_NOUID) == 0 && 437 if ((flags & _PASSWORD_NOUID) == 0 &&
420 pwd.pw_uid == 0) 438 pwd.pw_uid == 0)
421 warnx("line %d: superuser override " 439 warnx("line %d: superuser override "
422 "in YP inclusion", lineno); 440 "in YP inclusion", lineno);
423 if ((flags & _PASSWORD_NOGID) == 0 && 441 if ((flags & _PASSWORD_NOGID) == 0 &&
424 pwd.pw_gid == 0) 442 pwd.pw_gid == 0)
425 warnx("line %d: wheel override " 443 warnx("line %d: wheel override "
426 "in YP inclusion", lineno); 444 "in YP inclusion", lineno);
427 } 445 }
428 446
429 /* Write the database entry out. */ 447 /* Write the database entry out. */
430 if (!secureonly) 448 if (!secureonly)
431 putdbents(dp, &pwd, "*", flags, pwd_db_tmp, 449 putdbents(&idb, &pwd, "*", flags, lineno, dbflg,
432 lineno, dbflg, uid_dbflg, req_version); 450 uid_dbflg);
433 continue; 451 continue;
434 } else if (strcmp(username, pwd.pw_name) != 0) 452 } else if (strcmp(username, pwd.pw_name) != 0)
435 continue; 453 continue;
436 454
437 if (found) { 455 if (found) {
438 warnx("user `%s' listed twice in password file", 456 warnx("user `%s' listed twice in password file",
439 username); 457 username);
440 bailout(); 458 bailout();
441 } 459 }
442 460
443 /* 461 /*
444 * Ensure that the text file and database agree on 462 * Ensure that the text file and database agree on
445 * which line the record is from. 463 * which line the record is from.
446 */ 464 */
447 rv = getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYNUM, &lineno, &tpwd, 465 rv = getdbent(&sdb, _PW_KEYBYNUM, &lineno, &tpwd);
448 sversion); 
449 if (newuser) { 466 if (newuser) {
450 if (rv == 0) 467 if (rv == 0)
451 inconsistancy(); 468 inconsistancy();
452 } else if (rv == -1 || 469 } else if (rv == -1 ||
453 strcmp(username, tpwd->pw_name) != 0) 470 strcmp(username, tpwd->pw_name) != 0)
454 inconsistancy(); 471 inconsistancy();
455 else if ((uid_t)olduid != pwd.pw_uid) { 472 else if ((uid_t)olduid != pwd.pw_uid) {
456 /* 473 /*
457 * If we're changing UID, remove the BYUID 474 * If we're changing UID, remove the BYUID
458 * record for the old UID only if it has the 475 * record for the old UID only if it has the
459 * same username. 476 * same username.
460 */ 477 */
461 if (!getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYUID, &olduid, 478 if (!getdbent(&sdb, _PW_KEYBYUID, &olduid, &tpwd)) {
462 &tpwd, sversion)) { 
463 if (strcmp(username, tpwd->pw_name) == 0) { 479 if (strcmp(username, tpwd->pw_name) == 0) {
464 if (!secureonly) 480 if (!secureonly)
465 deldbent(dp, pwd_db_tmp, 481 deldbent(&idb, _PW_KEYBYUID,
466 _PW_KEYBYUID, &olduid); 482 &olduid);
467 deldbent(edp, pwd_Sdb_tmp, 483 deldbent(&sdb, _PW_KEYBYUID, &olduid);
468 _PW_KEYBYUID, &olduid); 
469 } 484 }
470 } else 485 } else
471 inconsistancy(); 486 inconsistancy();
472 } 487 }
473 488
474 /* 489 /*
475 * If there's an existing BYUID record for the new UID and 490 * If there's an existing BYUID record for the new UID and
476 * the username doesn't match then be sure not to overwrite 491 * the username doesn't match then be sure not to overwrite
477 * it. 492 * it.
478 */ 493 */
479 if (!getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYUID, &pwd.pw_uid, 494 if (!getdbent(&sdb, _PW_KEYBYUID, &pwd.pw_uid, &tpwd))
480 &tpwd, sversion)) 
481 if (strcmp(username, tpwd->pw_name) != 0) 495 if (strcmp(username, tpwd->pw_name) != 0)
482 uid_dbflg = R_NOOVERWRITE; 496 uid_dbflg = R_NOOVERWRITE;
483 497
484 /* Write the database entries out */ 498 /* Write the database entries out */
485 if (!secureonly) 499 if (!secureonly)
486 putdbents(dp, &pwd, "*", flags, pwd_db_tmp, lineno, 500 putdbents(&idb, &pwd, "*", flags, lineno, dbflg,
487 dbflg, uid_dbflg, req_version); 501 uid_dbflg);
488 putdbents(edp, &pwd, pwd.pw_passwd, flags, pwd_Sdb_tmp, 502 putdbents(&sdb, &pwd, pwd.pw_passwd, flags, lineno, dbflg,
489 lineno, dbflg, uid_dbflg, req_sversion); 503 uid_dbflg);
490 504
491 found = 1; 505 found = 1;
492 if (!makeold) 506 if (!makeold)
493 break; 507 break;
494 } 508 }
495 509
496 if (!secureonly) { 510 if (!secureonly) {
497 /* Store YP token if needed. */ 511 /* Store YP token if needed. */
498 if (hasyp) 512 if (hasyp)
499 putyptoken(dp, pwd_db_tmp); 513 putyptoken(&idb);
500 514
501 /* Close the insecure database. */ 515 /* Close the insecure database. */
502 if ((*dp->close)(dp) < 0) 516 closedb(&idb);
503 wr_error(pwd_db_tmp); 
504 } 517 }
505 518
506 /* 519 /*
507 * If rebuilding the databases, we re-parse the text file and write 520 * If rebuilding the databases, we re-parse the text file and write
508 * the secure entries out in a separate pass. 521 * the secure entries out in a separate pass.
509 */ 522 */
510 if (username == NULL) { 523 if (username == NULL) {
511 rewind(fp); 524 rewind(fp);
512 for (lineno = 0; scan(fp, &pwd, &flags, &lineno);) 525 for (lineno = 0; scan(fp, &pwd, &flags, &lineno);)
513 putdbents(edp, &pwd, pwd.pw_passwd, flags, pwd_Sdb_tmp, 526 putdbents(&sdb, &pwd, pwd.pw_passwd, flags,
514 lineno, dbflg, uid_dbflg, req_sversion); 527 lineno, dbflg, uid_dbflg);
515 528
516 /* Store YP token if needed. */ 529 /* Store YP token if needed. */
517 if (hasyp) 530 if (hasyp)
518 putyptoken(edp, pwd_Sdb_tmp); 531 putyptoken(&sdb);
519 } else if (!found) { 532 } else if (!found) {
520 warnx("user `%s' not found in password file", username); 533 warnx("user `%s' not found in password file", username);
521 bailout(); 534 bailout();
522 } 535 }
523 536
524 /* Close the secure database. */ 537 /* Close the secure database. */
525 if ((*edp->close)(edp) < 0) 538 closedb(&sdb);
526 wr_error(pwd_Sdb_tmp); 
527 539
528 /* Install as the real password files. */ 540 /* Install as the real password files. */
529 if (!secureonly) 541 if (!secureonly)
530 install(pwd_db_tmp, _PATH_MP_DB); 542 install(idb.dbname, idb.fname);
531 install(pwd_Sdb_tmp, _PATH_SMP_DB); 543 install(sdb.dbname, sdb.fname);
532 544
533 /* Install the V7 password file. */ 545 /* Install the V7 password file. */
534 if (makeold) { 546 if (makeold) {
535 if (fflush(oldfp) == EOF) 547 if (fflush(oldfp) == EOF)
536 wr_error(oldpwdfile); 548 wr_error(oldpwdfile);
537 if (fclose(oldfp) == EOF) 549 if (fclose(oldfp) == EOF)
538 wr_error(oldpwdfile); 550 wr_error(oldpwdfile);
539 install(oldpwdfile, _PATH_PASSWD); 551 install(oldpwdfile, _PATH_PASSWD);
540 } 552 }
541 553
542 /* Set master.passwd permissions, in case caller forgot. */ 554 /* Set master.passwd permissions, in case caller forgot. */
543 (void)fchmod(fileno(fp), S_IRUSR|S_IWUSR); 555 (void)fchmod(fileno(fp), S_IRUSR|S_IWUSR);
544 if (fclose(fp) == EOF) 556 if (fclose(fp) == EOF)
545 wr_error(pname); 557 wr_error(pname);
546 558
547 /* 559 /*
548 * Move the temporary master password file LAST -- chpass(1), 560 * Move the temporary master password file LAST -- chpass(1),
549 * passwd(1), vipw(8) and friends all use its existence to block 561 * passwd(1), vipw(8) and friends all use its existence to block
550 * other incarnations of themselves. The rename means that 562 * other incarnations of themselves. The rename means that
551 * everything is unlocked, as the original file can no longer be 563 * everything is unlocked, as the original file can no longer be
552 * accessed. 564 * accessed.
553 */ 565 */
554 install(pname, _PATH_MASTERPASSWD); 566 install(pname, _PATH_MASTERPASSWD);
555 exit(EXIT_SUCCESS); 567 exit(EXIT_SUCCESS);
556 /* NOTREACHED */ 568 /* NOTREACHED */
557} 569}
558 570
559int 571int
560scan(FILE *fp, struct passwd *pw, int *flags, int *lineno) 572scan(FILE *fp, struct passwd *pw, int *flags, int *lineno)
561{ 573{
562 static char line[LINE_MAX]; 574 static char line[LINE_MAX];
563 char *p; 575 char *p;
564 int oflags; 576 int oflags;
565 577
566 if (fgets(line, sizeof(line), fp) == NULL) 578 if (fgets(line, sizeof(line), fp) == NULL)
567 return (0); 579 return (0);
568 (*lineno)++; 580 (*lineno)++;
569 581
570 /* 582 /*
571 * ``... if I swallow anything evil, put your fingers down my 583 * ``... if I swallow anything evil, put your fingers down my
572 * throat...'' 584 * throat...''
573 * -- The Who 585 * -- The Who
574 */ 586 */
575 if ((p = strchr(line, '\n')) == NULL) { 587 if ((p = strchr(line, '\n')) == NULL) {
576 warnx("line too long"); 588 warnx("line too long");
577 errno = EFTYPE; /* XXX */ 589 errno = EFTYPE; /* XXX */
578 error(pname); 590 error(pname);
579 } 591 }
580 *p = '\0'; 592 *p = '\0';
581 if (strcmp(line, "+") == 0) 593 if (strcmp(line, "+") == 0)
582 strcpy(line, "+:::::::::"); /* pw_scan() can't handle "+" */ 594 strcpy(line, "+:::::::::"); /* pw_scan() can't handle "+" */
583 oflags = 0; 595 oflags = 0;
584 if (!pw_scan(line, pw, &oflags)) { 596 if (!pw_scan(line, pw, &oflags)) {
585 warnx("at line #%d", *lineno); 597 warnx("at line #%d", *lineno);
586 errno = EFTYPE; /* XXX */ 598 errno = EFTYPE; /* XXX */
587 error(pname); 599 error(pname);
588 } 600 }
589 *flags = oflags; 601 *flags = oflags;
590 602
591 return (1); 603 return (1);
592} 604}
593 605
594void 606void
595install(const char *from, const char *to) 607install(const char *from, const char *to)
596{ 608{
597 char buf[MAXPATHLEN]; 609 char buf[MAXPATHLEN];
598 char errbuf[BUFSIZ]; 610 char errbuf[BUFSIZ];
599 int sverrno; 611 int sverrno;
600 612
601 snprintf(buf, sizeof(buf), "%s%s", prefix, to); 613 snprintf(buf, sizeof(buf), "%s%s", prefix, to);
602 if (rename(from, buf)) { 614 if (rename(from, buf)) {
603 sverrno = errno; 615 sverrno = errno;
604 (void)snprintf(errbuf, sizeof(errbuf), "%s to %s", from, buf); 616 (void)snprintf(errbuf, sizeof(errbuf), "%s to %s", from, buf);
605 errno = sverrno; 617 errno = sverrno;
606 error(errbuf); 618 error(errbuf);
607 } 619 }
608} 620}
609 621
610void 622void
611rm(const char *victim) 623rm(const char *victim)
612{ 624{
613 625
614 if (unlink(victim) < 0) 626 if (unlink(victim) < 0)
615 warn("unlink(%s)", victim); 627 warn("unlink(%s)", victim);
616} 628}
617 629
618void  630void
619cp(const char *from, const char *to, mode_t mode)  631cp(const char *from, const char *to, mode_t mode)
620{  632{
621 static char buf[MAXBSIZE]; 633 static char buf[MAXBSIZE];
622 int from_fd, rcount, to_fd, wcount, sverrno; 634 int from_fd, rcount, to_fd, wcount, sverrno;
623 635
624 if ((from_fd = open(from, O_RDONLY, 0)) < 0) 636 if ((from_fd = open(from, O_RDONLY, 0)) < 0)
625 error(from); 637 error(from);
626 if ((to_fd = open(to, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) 638 if ((to_fd = open(to, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0)
627 error(to); 639 error(to);
628 while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) { 640 while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
629 wcount = write(to_fd, buf, rcount); 641 wcount = write(to_fd, buf, rcount);
630 if (rcount != wcount || wcount == -1) { 642 if (rcount != wcount || wcount == -1) {
631 sverrno = errno; 643 sverrno = errno;
632 (void)snprintf(buf, sizeof(buf), "%s to %s", from, to); 644 (void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
633 errno = sverrno; 645 errno = sverrno;
634 error(buf); 646 error(buf);
635 } 647 }
636 } 648 }
637 649
638 if (rcount < 0) { 650 if (rcount < 0) {
639 sverrno = errno; 651 sverrno = errno;
640 (void)snprintf(buf, sizeof(buf), "%s to %s", from, to); 652 (void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
641 errno = sverrno; 653 errno = sverrno;
642 error(buf); 654 error(buf);
643 } 655 }
644} 656}
645 657
646void 658void
647wr_error(const char *str) 659wr_error(const char *str)
648{ 660{
649 char errbuf[BUFSIZ]; 661 char errbuf[BUFSIZ];
650 int sverrno; 662 int sverrno;
651 663
652 sverrno = errno; 664 sverrno = errno;
653 665
654 (void)snprintf(errbuf, sizeof(errbuf), 666 (void)snprintf(errbuf, sizeof(errbuf),
655 "attempt to write %s failed", str); 667 "attempt to write %s failed", str);
656 668
657 errno = sverrno; 669 errno = sverrno;
658 error(errbuf); 670 error(errbuf);
659} 671}
660 672
661void 673void
662error(const char *str) 674error(const char *str)
663{ 675{
664 676
665 warn("%s", str); 677 warn("%s", str);
666 bailout(); 678 bailout();
667} 679}
668 680
669void 681void
670inconsistancy(void) 682inconsistancy(void)
671{ 683{
672 684
673 warnx("text files and databases are inconsistent"); 685 warnx("text files and databases are inconsistent");
674 warnx("re-build the databases without -u"); 686 warnx("re-build the databases without -u");
675 bailout(); 687 bailout();
676} 688}
677 689
678void 690void
679bailout(void) 691bailout(void)
680{ 692{
681 693
682 if ((clean & FILE_ORIG) != 0) 694 if ((clean & FILE_ORIG) != 0)
683 rm(oldpwdfile); 695 rm(oldpwdfile);
684 if ((clean & FILE_SECURE) != 0) 696 if ((clean & FILE_SECURE) != 0)
685 rm(pwd_Sdb_tmp); 697 rm(sdb.dbname);
686 if ((clean & FILE_INSECURE) != 0) 698 if ((clean & FILE_INSECURE) != 0)
687 rm(pwd_db_tmp); 699 rm(idb.dbname);
688 700
689 exit(EXIT_FAILURE); 701 exit(EXIT_FAILURE);
690} 702}
691 703
692uint32_t 704uint32_t
693getversion(const char *fname) 705getversion(const char *fname)
694{ 706{
695 DBT data, key; 707 DBT data, key;
696 int ret; 708 int ret;
697 uint32_t version = 0; 709 uint32_t version = 0;
698 DB *dp; 710 DB *db;
699 711
700 dp = dbopen(fname, O_RDONLY, PERM_INSECURE, DB_HASH, NULL); 712 db = dbopen(fname, O_RDONLY, PERM_INSECURE, DB_HASH, NULL);
701 if (dp == NULL) { 713 if (db == NULL) {
702 warn("Cannot open database %s", fname); 714 warn("Cannot open database %s", fname);
703 bailout(); 715 bailout();
704 } 716 }
705 key.data = __UNCONST("VERSION"); 717 key.data = __UNCONST("VERSION");
706 key.size = strlen((const char *)key.data) + 1; 718 key.size = strlen((const char *)key.data) + 1;
707 719
708 switch (ret = (*dp->get)(dp, &key, &data, 0)) { 720 switch (ret = (*db->get)(db, &key, &data, 0)) {
709 case -1: /* Error */ 721 case -1: /* Error */
710 warn("Cannot get VERSION record from database"); 722 warn("Cannot get VERSION record from database");
711 goto out; 723 goto out;
712 case 0: 724 case 0:
713 if (data.size != sizeof(version)) { 725 if (data.size != sizeof(version)) {
714 warnx("Bad VERSION record in database"); 726 warnx("Bad VERSION record in database");
715 goto out; 727 goto out;
716 } 728 }
717 memcpy(&version, data.data, sizeof(version)); 729 memcpy(&version, data.data, sizeof(version));
718 /*FALLTHROUGH*/ 730 /*FALLTHROUGH*/
719 case 1: 731 case 1:
720 (*dp->close)(dp); 732 if (ret == 1)
 733 warnx("Database %s has no version info", fname);
 734 (*db->close)(db);
721 return version; 735 return version;
722 default: 736 default:
723 warnx("internal error db->get returns %d", ret); 737 warnx("internal error db->get returns %d", ret);
724 goto out; 738 goto out;
725 } 739 }
726out: 740out:
727 (*dp->close)(dp); 741 (*db->close)(db);
728 bailout(); 742 bailout();
729} 743}
730 744
731void 745void
732setversion(DB *dp, uint32_t version) 746setversion(struct pwddb *db)
733{ 747{
734 DBT data, key; 748 DBT data, key;
735 key.data = __UNCONST("VERSION"); 749 key.data = __UNCONST("VERSION");
736 key.size = strlen((const char *)key.data) + 1; 750 key.size = strlen((const char *)key.data) + 1;
737 751
738 data.data = &version; 752 data.data = &db->wversion;
739 data.size = sizeof(uint32_t); 753 data.size = sizeof(uint32_t);
740 754
741 if ((*dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1) 755 if ((*db->db->put)(db->db, &key, &data, R_NOOVERWRITE) != 0) {
742 wr_error("setversion"); 756 warn("Can't write VERSION record to %s", db->dbname);
 757 bailout();
 758 }
743} 759}
744 760
745void 761void
746checkversion(uint32_t req_version, uint32_t version) 762checkversion(struct pwddb *db)
747{ 763{
748 (void)fprintf(stderr, "%s: you cannot change a single " 764 (void)fprintf(stderr, "%s: you cannot change a single "
749 "record from version %u to version %u\n", getprogname(), 765 "record from version %u to version %u\n", getprogname(),
750 version, req_version); 766 db->rversion, db->wversion);
751 bailout(); 767 bailout();
752} 768}
753 769
754/* 770/*
755 * Write entries to a database for a single user.  771 * Write entries to a database for a single user.
756 * 772 *
757 * The databases actually contain three copies of the original data. Each 773 * The databases actually contain three copies of the original data. Each
758 * password file entry is converted into a rough approximation of a ``struct 774 * password file entry is converted into a rough approximation of a ``struct
759 * passwd'', with the strings placed inline. This object is then stored as 775 * passwd'', with the strings placed inline. This object is then stored as
760 * the data for three separate keys. The first key * is the pw_name field 776 * the data for three separate keys. The first key * is the pw_name field
761 * prepended by the _PW_KEYBYNAME character. The second key is the pw_uid 777 * prepended by the _PW_KEYBYNAME character. The second key is the pw_uid
762 * field prepended by the _PW_KEYBYUID character. The third key is the line 778 * field prepended by the _PW_KEYBYUID character. The third key is the line
763 * number in the original file prepended by the _PW_KEYBYNUM character.  779 * number in the original file prepended by the _PW_KEYBYNUM character.
764 * (The special characters are prepended to ensure that the keys do not 780 * (The special characters are prepended to ensure that the keys do not
765 * collide.) 781 * collide.)
766 */ 782 */
767#define COMPACT(e) for (t = e; (*p++ = *t++) != '\0';) 783#define COMPACT(e) for (t = e; (*p++ = *t++) != '\0';)
768 784
769void 785void
770putdbents(DB *dp, struct passwd *pw, const char *passwd, int flags, 786putdbents(struct pwddb *db, struct passwd *pw, const char *passwd, int flags,
771 const char *fn, int lineno, int dbflg, int uid_dbflg, uint32_t version) 787 int lineno, int dbflg, int uid_dbflg)
772{ 788{
773 struct passwd pwd; 789 struct passwd pwd;
774 char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024], *p; 790 char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024], *p;
775 DBT data, key; 791 DBT data, key;
776 const char *t; 792 const char *t;
777 u_int32_t x; 793 u_int32_t x;
778 int len; 794 int len;
779 795
780 memcpy(&pwd, pw, sizeof(pwd)); 796 memcpy(&pwd, pw, sizeof(pwd));
781 data.data = (u_char *)buf; 797 data.data = (u_char *)buf;
782 key.data = (u_char *)tbuf; 798 key.data = (u_char *)tbuf;
783 799
784 if (lorder != BYTE_ORDER) { 800 if (lorder != BYTE_ORDER) {
785 pwd.pw_uid = SWAP(pwd.pw_uid); 801 pwd.pw_uid = SWAP(pwd.pw_uid);
786 pwd.pw_gid = SWAP(pwd.pw_gid); 802 pwd.pw_gid = SWAP(pwd.pw_gid);
787 } 803 }
788 804
789#define WRITEPWTIMEVAR(pwvar) \ 805#define WRITEPWTIMEVAR(pwvar) \
790 do { \ 806 do { \
791 if (version == 0 && \ 807 if (db->wversion == 0 && \
792 sizeof(pwvar) == sizeof(uint64_t)) { \ 808 sizeof(pwvar) == sizeof(uint64_t)) { \
793 uint32_t tmp = (uint32_t)pwvar; \ 809 uint32_t tmp = (uint32_t)pwvar; \
794 if (lorder != BYTE_ORDER) \ 810 if (lorder != BYTE_ORDER) \
795 tmp = SWAP(tmp); \ 811 tmp = SWAP(tmp); \
796 memmove(p, &tmp, sizeof(tmp)); \ 812 memmove(p, &tmp, sizeof(tmp)); \
797 p += sizeof(tmp); \ 813 p += sizeof(tmp); \
798 } else if (version == 1 && \ 814 } else if (db->wversion == 1 && \
799 sizeof(pwvar) == sizeof(uint32_t)) { \ 815 sizeof(pwvar) == sizeof(uint32_t)) { \
800 uint64_t tmp = pwvar; \ 816 uint64_t tmp = pwvar; \
801 if (lorder != BYTE_ORDER) \ 817 if (lorder != BYTE_ORDER) \
802 tmp = SWAP(tmp); \ 818 tmp = SWAP(tmp); \
803 memmove(p, &tmp, sizeof(tmp)); \ 819 memmove(p, &tmp, sizeof(tmp)); \
804 p += sizeof(tmp); \ 820 p += sizeof(tmp); \
805 } else { \ 821 } else { \
806 if (lorder != BYTE_ORDER) \ 822 if (lorder != BYTE_ORDER) \
807 pwvar = SWAP(pwvar); \ 823 pwvar = SWAP(pwvar); \
808 memmove(p, &pwvar, sizeof(pwvar)); \ 824 memmove(p, &pwvar, sizeof(pwvar)); \
809 p += sizeof(pwvar); \ 825 p += sizeof(pwvar); \
810 } \ 826 } \
811 } while (/*CONSTCOND*/0) 827 } while (/*CONSTCOND*/0)
812 828
813 /* Create insecure data. */ 829 /* Create insecure data. */
814 p = buf; 830 p = buf;
815 COMPACT(pwd.pw_name); 831 COMPACT(pwd.pw_name);
816 COMPACT(passwd); 832 COMPACT(passwd);
817 memmove(p, &pwd.pw_uid, sizeof(pwd.pw_uid)); 833 memmove(p, &pwd.pw_uid, sizeof(pwd.pw_uid));
818 p += sizeof(pwd.pw_uid); 834 p += sizeof(pwd.pw_uid);
819 memmove(p, &pwd.pw_gid, sizeof(pwd.pw_gid)); 835 memmove(p, &pwd.pw_gid, sizeof(pwd.pw_gid));
820 p += sizeof(pwd.pw_gid); 836 p += sizeof(pwd.pw_gid);
821 WRITEPWTIMEVAR(pwd.pw_change); 837 WRITEPWTIMEVAR(pwd.pw_change);
822 COMPACT(pwd.pw_class); 838 COMPACT(pwd.pw_class);
823 COMPACT(pwd.pw_gecos); 839 COMPACT(pwd.pw_gecos);
824 COMPACT(pwd.pw_dir); 840 COMPACT(pwd.pw_dir);
825 COMPACT(pwd.pw_shell); 841 COMPACT(pwd.pw_shell);
826 WRITEPWTIMEVAR(pwd.pw_expire); 842 WRITEPWTIMEVAR(pwd.pw_expire);
827 x = flags; 843 x = flags;
828 if (lorder != BYTE_ORDER) 844 if (lorder != BYTE_ORDER)
829 x = SWAP(x); 845 x = SWAP(x);
830 memmove(p, &x, sizeof(x)); 846 memmove(p, &x, sizeof(x));
831 p += sizeof(flags); 847 p += sizeof(flags);
832 data.size = p - buf; 848 data.size = p - buf;
833 849
834 /* Store insecure by name. */ 850 /* Store insecure by name. */
835 tbuf[0] = _PW_KEYBYNAME; 851 tbuf[0] = _PW_KEYBYNAME;
836 len = strlen(pwd.pw_name); 852 len = strlen(pwd.pw_name);
837 memmove(tbuf + 1, pwd.pw_name, len); 853 memmove(tbuf + 1, pwd.pw_name, len);
838 key.size = len + 1; 854 key.size = len + 1;
839 if ((*dp->put)(dp, &key, &data, dbflg) == -1) 855 if ((*db->db->put)(db->db, &key, &data, dbflg) == -1)
840 wr_error(fn); 856 wr_error(db->dbname);
841 857
842 /* Store insecure by number. */ 858 /* Store insecure by number. */
843 tbuf[0] = _PW_KEYBYNUM; 859 tbuf[0] = _PW_KEYBYNUM;
844 x = lineno; 860 x = lineno;
845 if (lorder != BYTE_ORDER) 861 if (lorder != BYTE_ORDER)
846 x = SWAP(x); 862 x = SWAP(x);
847 memmove(tbuf + 1, &x, sizeof(x)); 863 memmove(tbuf + 1, &x, sizeof(x));
848 key.size = sizeof(x) + 1; 864 key.size = sizeof(x) + 1;
849 if ((*dp->put)(dp, &key, &data, dbflg) == -1) 865 if ((*db->db->put)(db->db, &key, &data, dbflg) == -1)
850 wr_error(fn); 866 wr_error(db->dbname);
851 867
852 /* Store insecure by uid. */ 868 /* Store insecure by uid. */
853 tbuf[0] = _PW_KEYBYUID; 869 tbuf[0] = _PW_KEYBYUID;
854 memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid)); 870 memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
855 key.size = sizeof(pwd.pw_uid) + 1; 871 key.size = sizeof(pwd.pw_uid) + 1;
856 if ((*dp->put)(dp, &key, &data, uid_dbflg) == -1) 872 if ((*db->db->put)(db->db, &key, &data, uid_dbflg) == -1)
857 wr_error(fn); 873 wr_error(db->dbname);
858} 874}
859 875
860int 876int
861deldbent(DB *dp, const char *fn, int type, void *keyp) 877deldbent(struct pwddb *db, int type, void *keyp)
862{ 878{
863 char tbuf[1024]; 879 char tbuf[1024];
864 DBT key; 880 DBT key;
865 u_int32_t x; 881 u_int32_t x;
866 int len, rv; 882 int len, rv;
867 883
868 key.data = (u_char *)tbuf; 884 key.data = (u_char *)tbuf;
869 885
870 switch (tbuf[0] = type) { 886 switch (tbuf[0] = type) {
871 case _PW_KEYBYNAME: 887 case _PW_KEYBYNAME:
872 len = strlen((char *)keyp); 888 len = strlen((char *)keyp);
873 memcpy(tbuf + 1, keyp, len); 889 memcpy(tbuf + 1, keyp, len);
874 key.size = len + 1; 890 key.size = len + 1;
875 break; 891 break;
876 892
877 case _PW_KEYBYNUM: 893 case _PW_KEYBYNUM:
878 case _PW_KEYBYUID: 894 case _PW_KEYBYUID:
879 x = *(int *)keyp; 895 x = *(int *)keyp;
880 if (lorder != BYTE_ORDER) 896 if (lorder != BYTE_ORDER)
881 x = SWAP(x); 897 x = SWAP(x);
882 memmove(tbuf + 1, &x, sizeof(x)); 898 memmove(tbuf + 1, &x, sizeof(x));
883 key.size = sizeof(x) + 1; 899 key.size = sizeof(x) + 1;
884 break; 900 break;
885 } 901 }
886 902
887 if ((rv = (*dp->del)(dp, &key, 0)) == -1) 903 if ((rv = (*db->db->del)(db->db, &key, 0)) == -1)
888 wr_error(fn); 904 wr_error(db->dbname);
889 return (rv); 905 return (rv);
890} 906}
891 907
892int 908int
893getdbent(DB *dp, const char *fn, int type, void *keyp, struct passwd **tpwd, 909getdbent(struct pwddb *db, int type, void *keyp, struct passwd **tpwd)
894 uint32_t version) 
895{ 910{
896 static char buf[MAX(MAXPATHLEN, LINE_MAX * 2)]; 911 static char buf[MAX(MAXPATHLEN, LINE_MAX * 2)];
897 static struct passwd pwd; 912 static struct passwd pwd;
898 char tbuf[1024], *p; 913 char tbuf[1024], *p;
899 DBT key, data; 914 DBT key, data;
900 u_int32_t x; 915 u_int32_t x;
901 int len, rv; 916 int len, rv;
902 917
903 data.data = (u_char *)buf; 918 data.data = (u_char *)buf;
904 data.size = sizeof(buf); 919 data.size = sizeof(buf);
905 key.data = (u_char *)tbuf; 920 key.data = (u_char *)tbuf;
906 921
907 switch (tbuf[0] = type) { 922 switch (tbuf[0] = type) {
908 case _PW_KEYBYNAME: 923 case _PW_KEYBYNAME:
909 len = strlen((char *)keyp); 924 len = strlen((char *)keyp);
910 memcpy(tbuf + 1, keyp, len); 925 memcpy(tbuf + 1, keyp, len);
911 key.size = len + 1; 926 key.size = len + 1;
912 break; 927 break;
913 928
914 case _PW_KEYBYNUM: 929 case _PW_KEYBYNUM:
915 case _PW_KEYBYUID: 930 case _PW_KEYBYUID:
916 x = *(int *)keyp; 931 x = *(int *)keyp;
917 if (lorder != BYTE_ORDER) 932 if (lorder != BYTE_ORDER)
918 x = SWAP(x); 933 x = SWAP(x);
919 memmove(tbuf + 1, &x, sizeof(x)); 934 memmove(tbuf + 1, &x, sizeof(x));
920 key.size = sizeof(x) + 1; 935 key.size = sizeof(x) + 1;
921 break; 936 break;
922 } 937 }
923 938
924 if ((rv = (*dp->get)(dp, &key, &data, 0)) == 1) 939 if ((rv = (*db->db->get)(db->db, &key, &data, 0)) == 1)
925 return (rv); 940 return (rv);
926 if (rv == -1) 941 if (rv == -1)
927 error(pwd_Sdb_tmp); 942 error(db->dbname);
928 943
929 p = (char *)data.data; 944 p = (char *)data.data;
930 945
931 pwd.pw_name = p; 946 pwd.pw_name = p;
932 while (*p++ != '\0') 947 while (*p++ != '\0')
933 continue; 948 continue;
934 pwd.pw_passwd = p; 949 pwd.pw_passwd = p;
935 while (*p++ != '\0') 950 while (*p++ != '\0')
936 continue; 951 continue;
937 952
938 memcpy(&pwd.pw_uid, p, sizeof(pwd.pw_uid)); 953 memcpy(&pwd.pw_uid, p, sizeof(pwd.pw_uid));
939 p += sizeof(pwd.pw_uid); 954 p += sizeof(pwd.pw_uid);
940 memcpy(&pwd.pw_gid, p, sizeof(pwd.pw_gid)); 955 memcpy(&pwd.pw_gid, p, sizeof(pwd.pw_gid));
941 p += sizeof(pwd.pw_gid); 956 p += sizeof(pwd.pw_gid);
942 957
943#define READPWTIMEVAR(pwvar) \ 958#define READPWTIMEVAR(pwvar) \
944 do { \ 959 do { \
945 if (version == 0 && \ 960 if (db->rversion == 0 && \
946 sizeof(pwvar) == sizeof(uint64_t)) { \ 961 sizeof(pwvar) == sizeof(uint64_t)) { \
947 uint32_t tmp; \ 962 uint32_t tmp; \
948 memcpy(&tmp, p, sizeof(tmp)); \ 963 memcpy(&tmp, p, sizeof(tmp)); \
949 p += sizeof(tmp); \ 964 p += sizeof(tmp); \
950 if (lorder != BYTE_ORDER) \ 965 if (lorder != BYTE_ORDER) \
951 pwvar = SWAP(tmp); \ 966 pwvar = SWAP(tmp); \
952 else \ 967 else \
953 pwvar = tmp; \ 968 pwvar = tmp; \
954 } else if (version == 1 && \ 969 } else if (db->rversion == 1 && \
955 sizeof(pwvar) == sizeof(uint32_t)) { \ 970 sizeof(pwvar) == sizeof(uint32_t)) { \
956 uint64_t tmp; \ 971 uint64_t tmp; \
957 memcpy(&tmp, p, sizeof(tmp)); \ 972 memcpy(&tmp, p, sizeof(tmp)); \
958 p += sizeof(tmp); \ 973 p += sizeof(tmp); \
959 if (lorder != BYTE_ORDER) \ 974 if (lorder != BYTE_ORDER) \
960 pwvar = (uint32_t)SWAP(tmp); \ 975 pwvar = (uint32_t)SWAP(tmp); \
961 else \ 976 else \
962 pwvar = (uint32_t)tmp; \ 977 pwvar = (uint32_t)tmp; \
963 } else { \ 978 } else { \
964 memcpy(&pwvar, p, sizeof(pwvar)); \ 979 memcpy(&pwvar, p, sizeof(pwvar)); \
965 p += sizeof(pwvar); \ 980 p += sizeof(pwvar); \
966 if (lorder != BYTE_ORDER) \ 981 if (lorder != BYTE_ORDER) \
967 pwvar = SWAP(pwvar); \ 982 pwvar = SWAP(pwvar); \
968 } \ 983 } \
969 } while (/*CONSTCOND*/0) 984 } while (/*CONSTCOND*/0)
970  985
971 READPWTIMEVAR(pwd.pw_change); 986 READPWTIMEVAR(pwd.pw_change);
972 987
973 pwd.pw_class = p; 988 pwd.pw_class = p;
974 while (*p++ != '\0') 989 while (*p++ != '\0')
975 continue; 990 continue;
976 pwd.pw_gecos = p; 991 pwd.pw_gecos = p;
977 while (*p++ != '\0') 992 while (*p++ != '\0')
978 continue; 993 continue;
979 pwd.pw_dir = p; 994 pwd.pw_dir = p;
980 while (*p++ != '\0') 995 while (*p++ != '\0')
981 continue; 996 continue;
982 pwd.pw_shell = p; 997 pwd.pw_shell = p;
983 while (*p++ != '\0') 998 while (*p++ != '\0')
984 continue; 999 continue;
985 1000
986 READPWTIMEVAR(pwd.pw_expire); 1001 READPWTIMEVAR(pwd.pw_expire);
987 1002
988 if (lorder != BYTE_ORDER) { 1003 if (lorder != BYTE_ORDER) {
989 pwd.pw_uid = SWAP(pwd.pw_uid); 1004 pwd.pw_uid = SWAP(pwd.pw_uid);
990 pwd.pw_gid = SWAP(pwd.pw_gid); 1005 pwd.pw_gid = SWAP(pwd.pw_gid);
991 } 1006 }
992 1007
993 *tpwd = &pwd; 1008 *tpwd = &pwd;
994 return (0); 1009 return (0);
995} 1010}
996 1011
997void 1012void
998putyptoken(DB *dp, const char *fn) 1013putyptoken(struct pwddb *db)
999{ 1014{
1000 DBT data, key; 1015 DBT data, key;
1001 1016
1002 key.data = __UNCONST(__yp_token); 1017 key.data = __UNCONST(__yp_token);
1003 key.size = strlen(__yp_token); 1018 key.size = strlen(__yp_token);
1004 data.data = (u_char *)NULL; 1019 data.data = (u_char *)NULL;
1005 data.size = 0; 1020 data.size = 0;
1006 1021
1007 if ((*dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1) 1022 if ((*db->db->put)(db->db, &key, &data, R_NOOVERWRITE) == -1)
1008 wr_error(fn); 1023 wr_error(db->dbname);
1009} 1024}
1010 1025
1011void 1026void
1012usage(void) 1027usage(void)
1013{ 1028{
1014 1029
1015 (void)fprintf(stderr, 1030 (void)fprintf(stderr,
1016 "Usage: %s [-BLpsv] [-c cachesize] [-d directory] [-u user] " 1031 "Usage: %s [-BLpsvw] [-c cachesize] [-d directory] [-u user] "
1017 "[-V version] file\n", 1032 "[-V version] file\n",
1018 getprogname()); 1033 getprogname());
1019 exit(EXIT_FAILURE); 1034 exit(EXIT_FAILURE);
1020} 1035}