Sun Dec 28 01:21:23 2008 UTC ()
- provide and use our own swapping functions instead of db's (XXX convert
  to htole?)
- add version record.


(christos)
diff -r1.18 -r1.18.40.1 src/usr.sbin/pwd_mkdb/Makefile
diff -r1.34 -r1.34.6.1 src/usr.sbin/pwd_mkdb/pwd_mkdb.c

cvs diff -r1.18 -r1.18.40.1 src/usr.sbin/pwd_mkdb/Makefile (expand / switch to unified diff)

--- src/usr.sbin/pwd_mkdb/Makefile 2003/05/18 07:57:40 1.18
+++ src/usr.sbin/pwd_mkdb/Makefile 2008/12/28 01:21:23 1.18.40.1
@@ -1,15 +1,15 @@ @@ -1,15 +1,15 @@
1# from: @(#)Makefile 8.1 (Berkeley) 6/6/93 1# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
2# $NetBSD: Makefile,v 1.18 2003/05/18 07:57:40 lukem Exp $ 2# $NetBSD: Makefile,v 1.18.40.1 2008/12/28 01:21:23 christos Exp $
3 3
4.include <bsd.own.mk> 4.include <bsd.own.mk>
5 5
6PROG= pwd_mkdb 6PROG= pwd_mkdb
7MAN= pwd_mkdb.8 7MAN= pwd_mkdb.8
8CPPFLAGS+= -I${NETBSDSRCDIR}/lib/libc/include -D__DBINTERFACE_PRIVATE 8CPPFLAGS+= -I${NETBSDSRCDIR}/lib/libc/include
9 9
10.ifndef HOSTPROG 10.ifndef HOSTPROG
11LDADD+= -lutil 11LDADD+= -lutil
12DPADD+= ${LIBUTIL} 12DPADD+= ${LIBUTIL}
13.endif 13.endif
14 14
15.include <bsd.prog.mk> 15.include <bsd.prog.mk>

cvs diff -r1.34 -r1.34.6.1 src/usr.sbin/pwd_mkdb/pwd_mkdb.c (expand / switch to unified diff)

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