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