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