1 /* $NetBSD: pwd_mkdb.c,v 1.30 2005/06/02 09:18:14 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\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.30 2005/06/02 09:18:14 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 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 166 while ((ch = getopt(argc, argv, "BLd:psu:v")) != -1) 167 switch (ch) { 168 case 'B': /* big-endian output */ 169 lorder = BIG_ENDIAN; 170 break; 171 case 'L': /* little-endian output */ 172 lorder = LITTLE_ENDIAN; 173 break; 174 case 'd': /* set prefix */ 175 strlcpy(prefix, optarg, sizeof(prefix)); 176 break; 177 case 'p': /* create V7 "file.orig" */ 178 makeold = 1; 179 break; 180 case 's': /* modify secure db only */ 181 secureonly = 1; 182 break; 183 case 'u': /* modify one user only */ 184 username = optarg; 185 break; 186 case 'v': /* backward compatible */ 187 break; 188 case '?': 189 default: 190 usage(); 191 } 192 argc -= optind; 193 argv += optind; 194 195 if (argc != 1) 196 usage(); 197 if (username != NULL) 198 if (username[0] == '+' || username[0] == '-') 199 usage(); 200 if (secureonly) 201 makeold = 0; 202 203 /* 204 * This could be changed to allow the user to interrupt. 205 * Probably not worth the effort. 206 */ 207 sigemptyset(&set); 208 sigaddset(&set, SIGTSTP); 209 sigaddset(&set, SIGHUP); 210 sigaddset(&set, SIGINT); 211 sigaddset(&set, SIGQUIT); 212 sigaddset(&set, SIGTERM); 213 (void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL); 214 215 /* We don't care what the user wants. */ 216 (void)umask(0); 217 218 if (username == NULL) 219 flags = O_RDWR | O_CREAT | O_EXCL; 220 else 221 flags = O_RDWR; 222 223 pname = *argv; 224 /* Open the original password file */ 225 if ((fp = fopen(pname, "r")) == NULL) 226 error(pname); 227 228 openinfo.lorder = lorder; 229 230 if (fstat(fileno(fp), &st) == -1) 231 error(pname); 232 233 /* Tweak openinfo values for large passwd files. */ 234 cachesize = st.st_size * 20; 235 if (cachesize > MAX_CACHESIZE) 236 cachesize = MAX_CACHESIZE; 237 else if (cachesize < MIN_CACHESIZE) 238 cachesize = MIN_CACHESIZE; 239 openinfo.cachesize = cachesize; 240 241 /* Open the temporary insecure password database. */ 242 if (!secureonly) { 243 (void)snprintf(pwd_db_tmp, sizeof(pwd_db_tmp), "%s%s.tmp", 244 prefix, _PATH_MP_DB); 245 if (username != NULL) { 246 snprintf(buf, sizeof(buf), "%s" _PATH_MP_DB, prefix); 247 cp(buf, pwd_db_tmp, PERM_INSECURE); 248 } 249 dp = dbopen(pwd_db_tmp, flags, PERM_INSECURE, DB_HASH, 250 &openinfo); 251 if (dp == NULL) 252 error(pwd_db_tmp); 253 clean |= FILE_INSECURE; 254 } 255 256 /* Open the temporary encrypted password database. */ 257 (void)snprintf(pwd_Sdb_tmp, sizeof(pwd_Sdb_tmp), "%s%s.tmp", prefix, 258 _PATH_SMP_DB); 259 if (username != NULL) { 260 snprintf(buf, sizeof(buf), "%s" _PATH_SMP_DB, prefix); 261 cp(buf, pwd_Sdb_tmp, PERM_SECURE); 262 } 263 edp = dbopen(pwd_Sdb_tmp, flags, PERM_SECURE, DB_HASH, &openinfo); 264 if (!edp) 265 error(pwd_Sdb_tmp); 266 clean |= FILE_SECURE; 267 268 /* 269 * Open file for old password file. Minor trickiness -- don't want to 270 * chance the file already existing, since someone (stupidly) might 271 * still be using this for permission checking. So, open it first and 272 * fdopen the resulting fd. The resulting file should be readable by 273 * everyone. 274 */ 275 if (makeold) { 276 (void)snprintf(oldpwdfile, sizeof(oldpwdfile), "%s.orig", 277 pname); 278 if ((tfd = open(oldpwdfile, O_WRONLY | O_CREAT | O_EXCL, 279 PERM_INSECURE)) < 0) 280 error(oldpwdfile); 281 clean |= FILE_ORIG; 282 if ((oldfp = fdopen(tfd, "w")) == NULL) 283 error(oldpwdfile); 284 } 285 286 if (username != NULL) { 287 uid_dbflg = 0; 288 dbflg = 0; 289 290 /* 291 * Determine if this is a new entry. 292 */ 293 if (getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYNAME, username, &tpwd)) 294 newuser = 1; 295 else { 296 newuser = 0; 297 olduid = tpwd->pw_uid; 298 } 299 300 } else { 301 uid_dbflg = R_NOOVERWRITE; 302 dbflg = R_NOOVERWRITE; 303 } 304 305 /* 306 * If we see something go by that looks like YP, we save a special 307 * pointer record, which if YP is enabled in the C lib, will speed 308 * things up. 309 */ 310 for (lineno = 0; scan(fp, &pwd, &flags, &lineno);) { 311 /* 312 * Create original format password file entry. 313 */ 314 if (makeold) { 315 (void)fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n", 316 pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos, 317 pwd.pw_dir, pwd.pw_shell); 318 if (ferror(oldfp)) 319 wr_error(oldpwdfile); 320 } 321 322 if (username == NULL) { 323 /* Look like YP? */ 324 if (pwd.pw_name[0] == '+' || pwd.pw_name[0] == '-') 325 hasyp++; 326 327 /* Warn about potentially unsafe uid/gid overrides. */ 328 if (pwd.pw_name[0] == '+') { 329 if ((flags & _PASSWORD_NOUID) == 0 && 330 pwd.pw_uid == 0) 331 warnx("line %d: superuser override " 332 "in YP inclusion", lineno); 333 if ((flags & _PASSWORD_NOGID) == 0 && 334 pwd.pw_gid == 0) 335 warnx("line %d: wheel override " 336 "in YP inclusion", lineno); 337 } 338 339 /* Write the database entry out. */ 340 if (!secureonly) 341 putdbents(dp, &pwd, "*", flags, pwd_db_tmp, 342 lineno, dbflg, uid_dbflg); 343 continue; 344 } else if (strcmp(username, pwd.pw_name) != 0) 345 continue; 346 347 if (found) { 348 warnx("user `%s' listed twice in password file", 349 username); 350 bailout(); 351 } 352 353 /* 354 * Ensure that the text file and database agree on 355 * which line the record is from. 356 */ 357 rv = getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYNUM, &lineno, &tpwd); 358 if (newuser) { 359 if (rv == 0) 360 inconsistancy(); 361 } else if (rv == -1 || 362 strcmp(username, tpwd->pw_name) != 0) 363 inconsistancy(); 364 else if (olduid != pwd.pw_uid) { 365 /* 366 * If we're changing UID, remove the BYUID 367 * record for the old UID only if it has the 368 * same username. 369 */ 370 if (!getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYUID, &olduid, 371 &tpwd)) { 372 if (strcmp(username, tpwd->pw_name) == 0) { 373 if (!secureonly) 374 deldbent(dp, pwd_db_tmp, 375 _PW_KEYBYUID, &olduid); 376 deldbent(edp, pwd_Sdb_tmp, 377 _PW_KEYBYUID, &olduid); 378 } 379 } else 380 inconsistancy(); 381 } 382 383 /* 384 * If there's an existing BYUID record for the new UID and 385 * the username doesn't match then be sure not to overwrite 386 * it. 387 */ 388 if (!getdbent(edp, pwd_Sdb_tmp, _PW_KEYBYUID, &pwd.pw_uid, 389 &tpwd)) 390 if (strcmp(username, tpwd->pw_name) != 0) 391 uid_dbflg = R_NOOVERWRITE; 392 393 /* Write the database entries out */ 394 if (!secureonly) 395 putdbents(dp, &pwd, "*", flags, pwd_db_tmp, lineno, 396 dbflg, uid_dbflg); 397 putdbents(edp, &pwd, pwd.pw_passwd, flags, pwd_Sdb_tmp, 398 lineno, dbflg, uid_dbflg); 399 400 found = 1; 401 if (!makeold) 402 break; 403 } 404 405 if (!secureonly) { 406 /* Store YP token if needed. */ 407 if (hasyp) 408 putyptoken(dp, pwd_db_tmp); 409 410 /* Close the insecure database. */ 411 if ((*dp->close)(dp) < 0) 412 wr_error(pwd_db_tmp); 413 } 414 415 /* 416 * If rebuilding the databases, we re-parse the text file and write 417 * the secure entries out in a separate pass. 418 */ 419 if (username == NULL) { 420 rewind(fp); 421 for (lineno = 0; scan(fp, &pwd, &flags, &lineno);) 422 putdbents(edp, &pwd, pwd.pw_passwd, flags, pwd_Sdb_tmp, 423 lineno, dbflg, uid_dbflg); 424 425 /* Store YP token if needed. */ 426 if (hasyp) 427 putyptoken(edp, pwd_Sdb_tmp); 428 } else if (!found) { 429 warnx("user `%s' not found in password file", username); 430 bailout(); 431 } 432 433 /* Close the secure database. */ 434 if ((*edp->close)(edp) < 0) 435 wr_error(pwd_Sdb_tmp); 436 437 /* Install as the real password files. */ 438 if (!secureonly) 439 install(pwd_db_tmp, _PATH_MP_DB); 440 install(pwd_Sdb_tmp, _PATH_SMP_DB); 441 442 /* Install the V7 password file. */ 443 if (makeold) { 444 if (fflush(oldfp) == EOF) 445 wr_error(oldpwdfile); 446 if (fclose(oldfp) == EOF) 447 wr_error(oldpwdfile); 448 install(oldpwdfile, _PATH_PASSWD); 449 } 450 451 /* Set master.passwd permissions, in case caller forgot. */ 452 (void)fchmod(fileno(fp), S_IRUSR|S_IWUSR); 453 if (fclose(fp) == EOF) 454 wr_error(pname); 455 456 /* 457 * Move the temporary master password file LAST -- chpass(1), 458 * passwd(1), vipw(8) and friends all use its existance to block 459 * other incarnations of themselves. The rename means that 460 * everything is unlocked, as the original file can no longer be 461 * accessed. 462 */ 463 install(pname, _PATH_MASTERPASSWD); 464 exit(EXIT_SUCCESS); 465 /* NOTREACHED */ 466 } 467 468 int 469 scan(FILE *fp, struct passwd *pw, int *flags, int *lineno) 470 { 471 static char line[LINE_MAX]; 472 char *p; 473 int oflags; 474 475 if (fgets(line, sizeof(line), fp) == NULL) 476 return (0); 477 (*lineno)++; 478 479 /* 480 * ``... if I swallow anything evil, put your fingers down my 481 * throat...'' 482 * -- The Who 483 */ 484 if ((p = strchr(line, '\n')) == NULL) { 485 warnx("line too long"); 486 errno = EFTYPE; /* XXX */ 487 error(pname); 488 } 489 *p = '\0'; 490 if (strcmp(line, "+") == 0) 491 strcpy(line, "+:::::::::"); /* pw_scan() can't handle "+" */ 492 oflags = 0; 493 if (!pw_scan(line, pw, &oflags)) { 494 warnx("at line #%d", *lineno); 495 errno = EFTYPE; /* XXX */ 496 error(pname); 497 } 498 *flags = oflags; 499 500 return (1); 501 } 502 503 void 504 install(const char *from, const char *to) 505 { 506 char buf[MAXPATHLEN]; 507 int sverrno; 508 509 snprintf(buf, sizeof(buf), "%s%s", prefix, to); 510 if (rename(from, buf)) { 511 sverrno = errno; 512 (void)snprintf(buf, sizeof(buf), "%s to %s", from, buf); 513 errno = sverrno; 514 error(buf); 515 } 516 } 517 518 void 519 rm(const char *victim) 520 { 521 522 if (unlink(victim) < 0) 523 warn("unlink(%s)", victim); 524 } 525 526 void 527 cp(const char *from, const char *to, mode_t mode) 528 { 529 static char buf[MAXBSIZE]; 530 int from_fd, rcount, to_fd, wcount, sverrno; 531 532 if ((from_fd = open(from, O_RDONLY, 0)) < 0) 533 error(from); 534 if ((to_fd = open(to, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) 535 error(to); 536 while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) { 537 wcount = write(to_fd, buf, rcount); 538 if (rcount != wcount || wcount == -1) { 539 sverrno = errno; 540 (void)snprintf(buf, sizeof(buf), "%s to %s", from, to); 541 errno = sverrno; 542 error(buf); 543 } 544 } 545 546 if (rcount < 0) { 547 sverrno = errno; 548 (void)snprintf(buf, sizeof(buf), "%s to %s", from, to); 549 errno = sverrno; 550 error(buf); 551 } 552 } 553 554 void 555 wr_error(const char *str) 556 { 557 char errbuf[BUFSIZ]; 558 int sverrno; 559 560 sverrno = errno; 561 562 (void)snprintf(errbuf, sizeof(errbuf), 563 "attempt to write %s failed", str); 564 565 errno = sverrno; 566 error(errbuf); 567 } 568 569 void 570 error(const char *str) 571 { 572 573 warn("%s", str); 574 bailout(); 575 } 576 577 void 578 inconsistancy(void) 579 { 580 581 warnx("text files and databases are inconsistent"); 582 warnx("re-build the databases without -u"); 583 bailout(); 584 } 585 586 void 587 bailout(void) 588 { 589 590 if ((clean & FILE_ORIG) != 0) 591 rm(oldpwdfile); 592 if ((clean & FILE_SECURE) != 0) 593 rm(pwd_Sdb_tmp); 594 if ((clean & FILE_INSECURE) != 0) 595 rm(pwd_db_tmp); 596 597 exit(EXIT_FAILURE); 598 } 599 600 /* 601 * Write entries to a database for a single user. 602 * 603 * The databases actually contain three copies of the original data. Each 604 * password file entry is converted into a rough approximation of a ``struct 605 * passwd'', with the strings placed inline. This object is then stored as 606 * the data for three separate keys. The first key * is the pw_name field 607 * prepended by the _PW_KEYBYNAME character. The second key is the pw_uid 608 * field prepended by the _PW_KEYBYUID character. The third key is the line 609 * number in the original file prepended by the _PW_KEYBYNUM character. 610 * (The special characters are prepended to ensure that the keys do not 611 * collide.) 612 */ 613 #define COMPACT(e) for (t = e; (*p++ = *t++) != '\0';) 614 615 void 616 putdbents(DB *dp, struct passwd *pw, const char *passwd, int flags, 617 const char *fn, int lineno, int dbflg, int uid_dbflg) 618 { 619 struct passwd pwd; 620 char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024], *p; 621 DBT data, key; 622 const char *t; 623 u_int32_t x; 624 int len; 625 626 memcpy(&pwd, pw, sizeof(pwd)); 627 data.data = (u_char *)buf; 628 key.data = (u_char *)tbuf; 629 630 if (lorder != BYTE_ORDER) { 631 M_32_SWAP(pwd.pw_uid); 632 M_32_SWAP(pwd.pw_gid); 633 M_32_SWAP(pwd.pw_change); 634 M_32_SWAP(pwd.pw_expire); 635 } 636 637 /* Create insecure data. */ 638 p = buf; 639 COMPACT(pwd.pw_name); 640 COMPACT(passwd); 641 memmove(p, &pwd.pw_uid, sizeof(pwd.pw_uid)); 642 p += sizeof(pwd.pw_uid); 643 memmove(p, &pwd.pw_gid, sizeof(pwd.pw_gid)); 644 p += sizeof(pwd.pw_gid); 645 memmove(p, &pwd.pw_change, sizeof(pwd.pw_change)); 646 p += sizeof(pwd.pw_change); 647 COMPACT(pwd.pw_class); 648 COMPACT(pwd.pw_gecos); 649 COMPACT(pwd.pw_dir); 650 COMPACT(pwd.pw_shell); 651 memmove(p, &pwd.pw_expire, sizeof(pwd.pw_expire)); 652 p += sizeof(pwd.pw_expire); 653 x = flags; 654 if (lorder != BYTE_ORDER) 655 M_32_SWAP(x); 656 memmove(p, &x, sizeof(x)); 657 p += sizeof(flags); 658 data.size = p - buf; 659 660 /* Store insecure by name. */ 661 tbuf[0] = _PW_KEYBYNAME; 662 len = strlen(pwd.pw_name); 663 memmove(tbuf + 1, pwd.pw_name, len); 664 key.size = len + 1; 665 if ((*dp->put)(dp, &key, &data, dbflg) == -1) 666 wr_error(fn); 667 668 /* Store insecure by number. */ 669 tbuf[0] = _PW_KEYBYNUM; 670 x = lineno; 671 if (lorder != BYTE_ORDER) 672 M_32_SWAP(x); 673 memmove(tbuf + 1, &x, sizeof(x)); 674 key.size = sizeof(x) + 1; 675 if ((*dp->put)(dp, &key, &data, dbflg) == -1) 676 wr_error(fn); 677 678 /* Store insecure by uid. */ 679 tbuf[0] = _PW_KEYBYUID; 680 memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid)); 681 key.size = sizeof(pwd.pw_uid) + 1; 682 if ((*dp->put)(dp, &key, &data, uid_dbflg) == -1) 683 wr_error(fn); 684 } 685 686 int 687 deldbent(DB *dp, const char *fn, int type, void *keyp) 688 { 689 char tbuf[1024]; 690 DBT key; 691 u_int32_t x; 692 int len, rv; 693 694 key.data = (u_char *)tbuf; 695 696 switch (tbuf[0] = type) { 697 case _PW_KEYBYNAME: 698 len = strlen((char *)keyp); 699 memcpy(tbuf + 1, keyp, len); 700 key.size = len + 1; 701 break; 702 703 case _PW_KEYBYNUM: 704 case _PW_KEYBYUID: 705 x = *(int *)keyp; 706 if (lorder != BYTE_ORDER) 707 M_32_SWAP(x); 708 memmove(tbuf + 1, &x, sizeof(x)); 709 key.size = sizeof(x) + 1; 710 break; 711 } 712 713 if ((rv = (*dp->del)(dp, &key, 0)) == -1) 714 wr_error(fn); 715 return (rv); 716 } 717 718 int 719 getdbent(DB *dp, const char *fn, int type, void *keyp, struct passwd **tpwd) 720 { 721 static char buf[MAX(MAXPATHLEN, LINE_MAX * 2)]; 722 static struct passwd pwd; 723 char tbuf[1024], *p; 724 DBT key, data; 725 u_int32_t x; 726 int len, rv; 727 728 data.data = (u_char *)buf; 729 data.size = sizeof(buf); 730 key.data = (u_char *)tbuf; 731 732 switch (tbuf[0] = type) { 733 case _PW_KEYBYNAME: 734 len = strlen((char *)keyp); 735 memcpy(tbuf + 1, keyp, len); 736 key.size = len + 1; 737 break; 738 739 case _PW_KEYBYNUM: 740 case _PW_KEYBYUID: 741 x = *(int *)keyp; 742 if (lorder != BYTE_ORDER) 743 M_32_SWAP(x); 744 memmove(tbuf + 1, &x, sizeof(x)); 745 key.size = sizeof(x) + 1; 746 break; 747 } 748 749 if ((rv = (*dp->get)(dp, &key, &data, 0)) == 1) 750 return (rv); 751 if (rv == -1) 752 error(pwd_Sdb_tmp); 753 754 p = (char *)data.data; 755 756 pwd.pw_name = p; 757 while (*p++ != '\0') 758 ; 759 pwd.pw_passwd = p; 760 while (*p++ != '\0') 761 ; 762 763 memcpy(&pwd.pw_uid, p, sizeof(pwd.pw_uid)); 764 p += sizeof(pwd.pw_uid); 765 memcpy(&pwd.pw_gid, p, sizeof(pwd.pw_gid)); 766 p += sizeof(pwd.pw_gid); 767 memcpy(&pwd.pw_change, p, sizeof(pwd.pw_change)); 768 p += sizeof(pwd.pw_change); 769 770 pwd.pw_class = p; 771 while (*p++ != '\0') 772 ; 773 pwd.pw_gecos = p; 774 while (*p++ != '\0') 775 ; 776 pwd.pw_dir = p; 777 while (*p++ != '\0') 778 ; 779 pwd.pw_shell = p; 780 while (*p++ != '\0') 781 ; 782 783 memcpy(&pwd.pw_expire, p, sizeof(pwd.pw_expire)); 784 p += sizeof(pwd.pw_expire); 785 786 if (lorder != BYTE_ORDER) { 787 M_32_SWAP(pwd.pw_uid); 788 M_32_SWAP(pwd.pw_gid); 789 M_32_SWAP(pwd.pw_change); 790 M_32_SWAP(pwd.pw_expire); 791 } 792 793 *tpwd = &pwd; 794 return (0); 795 } 796 797 void 798 putyptoken(DB *dp, const char *fn) 799 { 800 DBT data, key; 801 802 key.data = (u_char *)__yp_token; 803 key.size = strlen(__yp_token); 804 data.data = (u_char *)NULL; 805 data.size = 0; 806 807 if ((*dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1) 808 wr_error(fn); 809 } 810 811 void 812 usage(void) 813 { 814 815 (void)fprintf(stderr, 816 "usage: pwd_mkdb [-BLps] [-d directory] [-u user] file\n"); 817 exit(EXIT_FAILURE); 818 } 819