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