pwd_mkdb.c revision 1.32 1 /* $NetBSD: pwd_mkdb.c,v 1.32 2006/09/23 17:38:42 sketch 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\n\
64 The NetBSD Foundation, Inc. All rights reserved.\n\
65 Copyright (c) 1991, 1993, 1994\n\
66 The Regents of the University of California. All rights reserved.\n");
67 __SCCSID("from: @(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94");
68 __RCSID("$NetBSD: pwd_mkdb.c,v 1.32 2006/09/23 17:38:42 sketch 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
99 static const char __yp_token[] = "__YP!";
100 #else
101 /* Pull this out of the C library. */
102 extern const char __yp_token[];
103 #endif
104
105 HASHINFO 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
118 static char *pname; /* password file name */
119 static char prefix[MAXPATHLEN];
120 static char oldpwdfile[MAX(MAXPATHLEN, LINE_MAX * 2)];
121 static char pwd_db_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)];
122 static char pwd_Sdb_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)];
123 static int lorder = BYTE_ORDER;
124 static int clean;
125
126 void bailout(void);
127 void cp(const char *, const char *, mode_t);
128 int deldbent(DB *, const char *, int, void *);
129 void error(const char *);
130 int getdbent(DB *, const char *, int, void *, struct passwd **);
131 void inconsistancy(void);
132 void install(const char *, const char *);
133 int main(int, char **);
134 void putdbents(DB *, struct passwd *, const char *, int, const char *, int,
135 int, int);
136 void putyptoken(DB *, const char *);
137 void rm(const char *);
138 int scan(FILE *, struct passwd *, int *, int *);
139 void usage(void);
140 void wr_error(const char *);
141
142 int
143 main(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 existance 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
476 int
477 scan(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
511 void
512 install(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
527 void
528 rm(const char *victim)
529 {
530
531 if (unlink(victim) < 0)
532 warn("unlink(%s)", victim);
533 }
534
535 void
536 cp(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
563 void
564 wr_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
578 void
579 error(const char *str)
580 {
581
582 warn("%s", str);
583 bailout();
584 }
585
586 void
587 inconsistancy(void)
588 {
589
590 warnx("text files and databases are inconsistent");
591 warnx("re-build the databases without -u");
592 bailout();
593 }
594
595 void
596 bailout(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
624 void
625 putdbents(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
695 int
696 deldbent(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
727 int
728 getdbent(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
806 void
807 putyptoken(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
820 void
821 usage(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 }
828