1 /* $NetBSD: getpwent.c,v 1.21 1997/05/22 10:38:11 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * Portions Copyright (c) 1994, 1995, 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 defined(LIBC_SCCS) && !defined(lint) 38 #if 0 39 static char sccsid[] = "@(#)getpwent.c 8.1 (Berkeley) 6/4/93"; 40 #else 41 static char rcsid[] = "$NetBSD: getpwent.c,v 1.21 1997/05/22 10:38:11 lukem Exp $"; 42 #endif 43 #endif /* LIBC_SCCS and not lint */ 44 45 #include <sys/param.h> 46 #include <fcntl.h> 47 #include <db.h> 48 #include <syslog.h> 49 #include <pwd.h> 50 #include <utmp.h> 51 #include <errno.h> 52 #include <unistd.h> 53 #include <stdlib.h> 54 #include <string.h> 55 #include <limits.h> 56 #include <netgroup.h> 57 #ifdef YP 58 #include <machine/param.h> 59 #include <stdio.h> 60 #include <rpc/rpc.h> 61 #include <rpcsvc/yp_prot.h> 62 #include <rpcsvc/ypclnt.h> 63 #endif 64 65 static struct passwd _pw_passwd; /* password structure */ 66 static DB *_pw_db; /* password database */ 67 static int _pw_keynum; /* key counter */ 68 static int _pw_stayopen; /* keep fd's open */ 69 static int _pw_flags; /* password flags */ 70 static int __hashpw __P((DBT *)); 71 static int __initdb __P((void)); 72 73 const char __yp_token[] = "__YP!"; /* Let pwd_mkdb pull this in. */ 74 75 #ifdef YP 76 enum _ypmode { YPMODE_NONE, YPMODE_FULL, YPMODE_USER, YPMODE_NETGRP }; 77 static enum _ypmode __ypmode; 78 79 static char *__ypcurrent, *__ypdomain; 80 static int __ypcurrentlen; 81 static struct passwd *__ypproto = (struct passwd *)NULL; 82 static int __ypflags; 83 static char line[1024]; 84 static long prbuf[1024 / sizeof(long)]; 85 static DB *__ypexclude = (DB *)NULL; 86 87 static int __has_yppw __P((void)); 88 static int __ypexclude_add __P((const char *)); 89 static int __ypexclude_is __P((const char *)); 90 static void __ypproto_set __P((void)); 91 92 static int 93 __ypexclude_add(name) 94 const char *name; 95 { 96 DBT key, data; 97 98 /* initialize the exclusion table if needed. */ 99 if(__ypexclude == (DB *)NULL) { 100 __ypexclude = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL); 101 if(__ypexclude == (DB *)NULL) 102 return(1); 103 } 104 105 /* set up the key */ 106 key.data = (char *)name; 107 key.size = strlen(name); 108 109 /* data is nothing. */ 110 data.data = NULL; 111 data.size = 0; 112 113 /* store it */ 114 if((__ypexclude->put)(__ypexclude, &key, &data, 0) == -1) 115 return(1); 116 117 return(0); 118 } 119 120 static int 121 __ypexclude_is(name) 122 const char *name; 123 { 124 DBT key, data; 125 126 if(__ypexclude == (DB *)NULL) 127 return(0); /* nothing excluded */ 128 129 /* set up the key */ 130 key.data = (char *)name; 131 key.size = strlen(name); 132 133 if((__ypexclude->get)(__ypexclude, &key, &data, 0) == 0) 134 return(1); /* excluded */ 135 136 return(0); 137 } 138 139 static void 140 __ypproto_set() 141 { 142 char *ptr; 143 struct passwd *pw = &_pw_passwd; 144 145 /* make this the new prototype */ 146 ptr = (char *)prbuf; 147 148 /* first allocate the struct. */ 149 __ypproto = (struct passwd *)ptr; 150 ptr += sizeof(struct passwd); 151 152 /* name */ 153 if(pw->pw_name && (pw->pw_name)[0]) { 154 ptr = (char *)ALIGN(ptr); 155 bcopy(pw->pw_name, ptr, strlen(pw->pw_name) + 1); 156 __ypproto->pw_name = ptr; 157 ptr += (strlen(pw->pw_name) + 1); 158 } else 159 __ypproto->pw_name = (char *)NULL; 160 161 /* password */ 162 if(pw->pw_passwd && (pw->pw_passwd)[0]) { 163 ptr = (char *)ALIGN(ptr); 164 bcopy(pw->pw_passwd, ptr, strlen(pw->pw_passwd) + 1); 165 __ypproto->pw_passwd = ptr; 166 ptr += (strlen(pw->pw_passwd) + 1); 167 } else 168 __ypproto->pw_passwd = (char *)NULL; 169 170 /* uid */ 171 __ypproto->pw_uid = pw->pw_uid; 172 173 /* gid */ 174 __ypproto->pw_gid = pw->pw_gid; 175 176 /* change (ignored anyway) */ 177 __ypproto->pw_change = pw->pw_change; 178 179 /* class (ignored anyway) */ 180 __ypproto->pw_class = ""; 181 182 /* gecos */ 183 if(pw->pw_gecos && (pw->pw_gecos)[0]) { 184 ptr = (char *)ALIGN(ptr); 185 bcopy(pw->pw_gecos, ptr, strlen(pw->pw_gecos) + 1); 186 __ypproto->pw_gecos = ptr; 187 ptr += (strlen(pw->pw_gecos) + 1); 188 } else 189 __ypproto->pw_gecos = (char *)NULL; 190 191 /* dir */ 192 if(pw->pw_dir && (pw->pw_dir)[0]) { 193 ptr = (char *)ALIGN(ptr); 194 bcopy(pw->pw_dir, ptr, strlen(pw->pw_dir) + 1); 195 __ypproto->pw_dir = ptr; 196 ptr += (strlen(pw->pw_dir) + 1); 197 } else 198 __ypproto->pw_dir = (char *)NULL; 199 200 /* shell */ 201 if(pw->pw_shell && (pw->pw_shell)[0]) { 202 ptr = (char *)ALIGN(ptr); 203 bcopy(pw->pw_shell, ptr, strlen(pw->pw_shell) + 1); 204 __ypproto->pw_shell = ptr; 205 ptr += (strlen(pw->pw_shell) + 1); 206 } else 207 __ypproto->pw_shell = (char *)NULL; 208 209 /* expire (ignored anyway) */ 210 __ypproto->pw_expire = pw->pw_expire; 211 212 /* flags */ 213 __ypflags = _pw_flags; 214 } 215 216 static int 217 __ypparse(pw, s) 218 struct passwd *pw; 219 char *s; 220 { 221 char *bp, *cp, *ep; 222 unsigned long id; 223 224 /* since this is currently using strsep(), parse it first */ 225 bp = s; 226 pw->pw_name = strsep(&bp, ":\n"); 227 pw->pw_passwd = strsep(&bp, ":\n"); 228 if (!(cp = strsep(&bp, ":\n"))) 229 return 1; 230 id = strtoul(cp, &ep, 10); 231 if (id > UID_MAX || *ep != '\0') 232 return 1; 233 pw->pw_uid = (uid_t)id; 234 if (!(cp = strsep(&bp, ":\n"))) 235 return 1; 236 id = strtoul(cp, &ep, 10); 237 if (id > GID_MAX || *ep != '\0') 238 return 1; 239 pw->pw_gid = (gid_t)id; 240 pw->pw_change = 0; 241 pw->pw_class = ""; 242 pw->pw_gecos = strsep(&bp, ":\n"); 243 pw->pw_dir = strsep(&bp, ":\n"); 244 pw->pw_shell = strsep(&bp, ":\n"); 245 pw->pw_expire = 0; 246 247 /* now let the prototype override, if set. */ 248 if(__ypproto != (struct passwd *)NULL) { 249 #ifdef YP_OVERRIDE_PASSWD 250 if(__ypproto->pw_passwd != (char *)NULL) 251 pw->pw_passwd = __ypproto->pw_passwd; 252 #endif 253 if(!(__ypflags & _PASSWORD_NOUID)) 254 pw->pw_uid = __ypproto->pw_uid; 255 if(!(__ypflags & _PASSWORD_NOGID)) 256 pw->pw_gid = __ypproto->pw_gid; 257 if(__ypproto->pw_gecos != (char *)NULL) 258 pw->pw_gecos = __ypproto->pw_gecos; 259 if(__ypproto->pw_dir != (char *)NULL) 260 pw->pw_dir = __ypproto->pw_dir; 261 if(__ypproto->pw_shell != (char *)NULL) 262 pw->pw_shell = __ypproto->pw_shell; 263 } 264 return 0; 265 } 266 #endif 267 268 struct passwd * 269 getpwent() 270 { 271 DBT key; 272 char bf[sizeof(_pw_keynum) + 1]; 273 #ifdef YP 274 char *cp; 275 static char *name = (char *)NULL; 276 const char *user, *host, *dom; 277 int has_yppw; 278 #endif 279 280 if (!_pw_db && !__initdb()) 281 return((struct passwd *)NULL); 282 283 #ifdef YP 284 has_yppw = __has_yppw(); 285 286 again: 287 if(has_yppw && (__ypmode != YPMODE_NONE)) { 288 char *key, *data; 289 int keylen, datalen; 290 int r, s; 291 292 if(!__ypdomain) { 293 if( _yp_check(&__ypdomain) == 0) { 294 __ypmode = YPMODE_NONE; 295 goto again; 296 } 297 } 298 switch(__ypmode) { 299 case YPMODE_FULL: 300 data = NULL; 301 if(__ypcurrent) { 302 key = NULL; 303 r = yp_next(__ypdomain, "passwd.byname", 304 __ypcurrent, __ypcurrentlen, 305 &key, &keylen, &data, &datalen); 306 free(__ypcurrent); 307 if(r != 0) { 308 __ypcurrent = NULL; 309 if (key) 310 free(key); 311 } 312 else { 313 __ypcurrent = key; 314 __ypcurrentlen = keylen; 315 } 316 } else { 317 r = yp_first(__ypdomain, "passwd.byname", 318 &__ypcurrent, &__ypcurrentlen, 319 &data, &datalen); 320 } 321 if(r != 0) { 322 __ypmode = YPMODE_NONE; 323 if(data) 324 free(data); 325 data = NULL; 326 goto again; 327 } 328 bcopy(data, line, datalen); 329 free(data); 330 data = NULL; 331 break; 332 case YPMODE_NETGRP: 333 s = getnetgrent(&host, &user, &dom); 334 if(s == 0) { /* end of group */ 335 endnetgrent(); 336 __ypmode = YPMODE_NONE; 337 goto again; 338 } 339 if(user && *user) { 340 data = NULL; 341 r = yp_match(__ypdomain, "passwd.byname", 342 user, strlen(user), 343 &data, &datalen); 344 } else 345 goto again; 346 if(r != 0) { 347 /* 348 * if the netgroup is invalid, keep looking 349 * as there may be valid users later on. 350 */ 351 if(data) 352 free(data); 353 goto again; 354 } 355 bcopy(data, line, datalen); 356 free(data); 357 data = NULL; 358 break; 359 case YPMODE_USER: 360 if(name != (char *)NULL) { 361 data = NULL; 362 r = yp_match(__ypdomain, "passwd.byname", 363 name, strlen(name), 364 &data, &datalen); 365 __ypmode = YPMODE_NONE; 366 free(name); 367 name = NULL; 368 if(r != 0) { 369 if(data) 370 free(data); 371 goto again; 372 } 373 bcopy(data, line, datalen); 374 free(data); 375 data = (char *)NULL; 376 } else { /* XXX */ 377 __ypmode = YPMODE_NONE; 378 goto again; 379 } 380 break; 381 } 382 383 line[datalen] = '\0'; 384 if (__ypparse(&_pw_passwd, line)) 385 goto again; 386 return &_pw_passwd; 387 } 388 #endif 389 390 ++_pw_keynum; 391 bf[0] = _PW_KEYBYNUM; 392 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); 393 key.data = (u_char *)bf; 394 key.size = sizeof(_pw_keynum) + 1; 395 if(__hashpw(&key)) { 396 #ifdef YP 397 /* if we don't have YP at all, don't bother. */ 398 if(has_yppw) { 399 if(_pw_passwd.pw_name[0] == '+') { 400 /* set the mode */ 401 switch(_pw_passwd.pw_name[1]) { 402 case '\0': 403 __ypmode = YPMODE_FULL; 404 break; 405 case '@': 406 __ypmode = YPMODE_NETGRP; 407 setnetgrent(_pw_passwd.pw_name + 2); 408 break; 409 default: 410 __ypmode = YPMODE_USER; 411 name = strdup(_pw_passwd.pw_name + 1); 412 break; 413 } 414 415 /* save the prototype */ 416 __ypproto_set(); 417 goto again; 418 } else if(_pw_passwd.pw_name[0] == '-') { 419 /* an attempted exclusion */ 420 switch(_pw_passwd.pw_name[1]) { 421 case '\0': 422 break; 423 case '@': 424 setnetgrent(_pw_passwd.pw_name + 2); 425 while(getnetgrent(&host, &user, &dom)) { 426 if(user && *user) 427 __ypexclude_add(user); 428 } 429 endnetgrent(); 430 break; 431 default: 432 __ypexclude_add(_pw_passwd.pw_name + 1); 433 break; 434 } 435 goto again; 436 } 437 } 438 #endif 439 return &_pw_passwd; 440 } 441 return (struct passwd *)NULL; 442 } 443 444 #ifdef YP 445 446 /* 447 * See if the YP token is in the database. Only works if pwd_mkdb knows 448 * about the token. 449 */ 450 static int 451 __has_yppw() 452 { 453 DBT key, data; 454 DBT pkey, pdata; 455 int len; 456 char bf[MAXLOGNAME]; 457 458 key.data = (u_char *)__yp_token; 459 key.size = strlen(__yp_token); 460 461 /* Pre-token database support. */ 462 bf[0] = _PW_KEYBYNAME; 463 bf[1] = '+'; 464 pkey.data = (u_char *)bf; 465 pkey.size = 2; 466 467 if ((_pw_db->get)(_pw_db, &key, &data, 0) 468 && (_pw_db->get)(_pw_db, &pkey, &pdata, 0)) 469 return(0); /* No YP. */ 470 return(1); 471 } 472 #endif 473 474 struct passwd * 475 getpwnam(name) 476 const char *name; 477 { 478 DBT key; 479 int len, rval; 480 char bf[MAXLOGNAME + 1]; 481 482 if (!_pw_db && !__initdb()) 483 return((struct passwd *)NULL); 484 485 #ifdef YP 486 /* 487 * If YP is active, we must sequence through the passwd file 488 * in sequence. 489 */ 490 if (__has_yppw()) { 491 int r; 492 int s = -1; 493 const char *host, *user, *dom; 494 495 for(_pw_keynum=1; _pw_keynum; _pw_keynum++) { 496 bf[0] = _PW_KEYBYNUM; 497 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); 498 key.data = (u_char *)bf; 499 key.size = sizeof(_pw_keynum) + 1; 500 if(__hashpw(&key) == 0) 501 break; 502 switch(_pw_passwd.pw_name[0]) { 503 case '+': 504 if(!__ypdomain) { 505 if(_yp_check(&__ypdomain) == 0) { 506 continue; 507 } 508 } 509 /* save the prototype */ 510 __ypproto_set(); 511 512 switch(_pw_passwd.pw_name[1]) { 513 case '\0': 514 if(__ypcurrent) { 515 free(__ypcurrent); 516 __ypcurrent = NULL; 517 } 518 r = yp_match(__ypdomain, 519 "passwd.byname", 520 name, strlen(name), 521 &__ypcurrent, &__ypcurrentlen); 522 if(r != 0) { 523 if(__ypcurrent) 524 free(__ypcurrent); 525 __ypcurrent = NULL; 526 continue; 527 } 528 break; 529 case '@': 530 pwnam_netgrp: 531 if(__ypcurrent) { 532 free(__ypcurrent); 533 __ypcurrent = NULL; 534 } 535 if(s == -1) /* first time */ 536 setnetgrent(_pw_passwd.pw_name + 2); 537 s = getnetgrent(&host, &user, &dom); 538 if(s == 0) { /* end of group */ 539 endnetgrent(); 540 s = -1; 541 continue; 542 } else { 543 if(user && *user) { 544 r = yp_match(__ypdomain, 545 "passwd.byname", 546 user, strlen(user), 547 &__ypcurrent, 548 &__ypcurrentlen); 549 } else 550 goto pwnam_netgrp; 551 if(r != 0) { 552 if(__ypcurrent) 553 free(__ypcurrent); 554 __ypcurrent = NULL; 555 /* 556 * just because this 557 * user is bad, doesn't 558 * mean they all are. 559 */ 560 goto pwnam_netgrp; 561 } 562 } 563 break; 564 default: 565 if(__ypcurrent) { 566 free(__ypcurrent); 567 __ypcurrent = NULL; 568 } 569 user = _pw_passwd.pw_name + 1; 570 r = yp_match(__ypdomain, 571 "passwd.byname", 572 user, strlen(user), 573 &__ypcurrent, 574 &__ypcurrentlen); 575 if(r != 0) { 576 if(__ypcurrent) 577 free(__ypcurrent); 578 __ypcurrent = NULL; 579 continue; 580 } 581 break; 582 } 583 bcopy(__ypcurrent, line, __ypcurrentlen); 584 line[__ypcurrentlen] = '\0'; 585 if(__ypparse(&_pw_passwd, line) 586 || __ypexclude_is(_pw_passwd.pw_name)) { 587 if(s == 1) /* inside netgrp */ 588 goto pwnam_netgrp; 589 continue; 590 } 591 break; 592 case '-': 593 /* attempted exclusion */ 594 switch(_pw_passwd.pw_name[1]) { 595 case '\0': 596 break; 597 case '@': 598 setnetgrent(_pw_passwd.pw_name + 2); 599 while(getnetgrent(&host, &user, &dom)) { 600 if(user && *user) 601 __ypexclude_add(user); 602 } 603 endnetgrent(); 604 break; 605 default: 606 __ypexclude_add(_pw_passwd.pw_name + 1); 607 break; 608 } 609 break; 610 611 continue; 612 } 613 if(strcmp(_pw_passwd.pw_name, name) == 0) { 614 if (!_pw_stayopen) { 615 (void)(_pw_db->close)(_pw_db); 616 _pw_db = (DB *)NULL; 617 } 618 if(__ypexclude != (DB *)NULL) { 619 (void)(__ypexclude->close)(__ypexclude); 620 __ypexclude = (DB *)NULL; 621 } 622 __ypproto = (struct passwd *)NULL; 623 return &_pw_passwd; 624 } 625 if(s == 1) /* inside netgrp */ 626 goto pwnam_netgrp; 627 continue; 628 } 629 if (!_pw_stayopen) { 630 (void)(_pw_db->close)(_pw_db); 631 _pw_db = (DB *)NULL; 632 } 633 if(__ypexclude != (DB *)NULL) { 634 (void)(__ypexclude->close)(__ypexclude); 635 __ypexclude = (DB *)NULL; 636 } 637 __ypproto = (struct passwd *)NULL; 638 return (struct passwd *)NULL; 639 } 640 #endif /* YP */ 641 642 bf[0] = _PW_KEYBYNAME; 643 len = strlen(name); 644 len = MIN(len, MAXLOGNAME); 645 bcopy(name, bf + 1, len); 646 key.data = (u_char *)bf; 647 key.size = len + 1; 648 rval = __hashpw(&key); 649 650 if (!_pw_stayopen) { 651 (void)(_pw_db->close)(_pw_db); 652 _pw_db = (DB *)NULL; 653 } 654 return(rval ? &_pw_passwd : (struct passwd *)NULL); 655 } 656 657 struct passwd * 658 #ifdef __STDC__ 659 getpwuid(uid_t uid) 660 #else 661 getpwuid(uid) 662 uid_t uid; 663 #endif 664 { 665 DBT key; 666 char bf[sizeof(_pw_keynum) + 1]; 667 uid_t keyuid; 668 int rval; 669 670 if (!_pw_db && !__initdb()) 671 return((struct passwd *)NULL); 672 673 #ifdef YP 674 /* 675 * If YP is active, we must sequence through the passwd file 676 * in sequence. 677 */ 678 if (__has_yppw()) { 679 char uidbuf[20]; 680 int r; 681 int s = -1; 682 const char *host, *user, *dom; 683 684 snprintf(uidbuf, sizeof(uidbuf), "%u", uid); 685 for(_pw_keynum=1; _pw_keynum; _pw_keynum++) { 686 bf[0] = _PW_KEYBYNUM; 687 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); 688 key.data = (u_char *)bf; 689 key.size = sizeof(_pw_keynum) + 1; 690 if(__hashpw(&key) == 0) 691 break; 692 switch(_pw_passwd.pw_name[0]) { 693 case '+': 694 if(!__ypdomain) { 695 if(_yp_check(&__ypdomain) == 0) { 696 continue; 697 } 698 } 699 /* save the prototype */ 700 __ypproto_set(); 701 702 switch(_pw_passwd.pw_name[1]) { 703 case '\0': 704 if(__ypcurrent) { 705 free(__ypcurrent); 706 __ypcurrent = NULL; 707 } 708 r = yp_match(__ypdomain, "passwd.byuid", 709 uidbuf, strlen(uidbuf), 710 &__ypcurrent, &__ypcurrentlen); 711 if(r != 0) { 712 if(__ypcurrent) 713 free(__ypcurrent); 714 __ypcurrent = NULL; 715 continue; 716 } 717 break; 718 case '@': 719 pwuid_netgrp: 720 if(__ypcurrent) { 721 free(__ypcurrent); 722 __ypcurrent = NULL; 723 } 724 if(s == -1) /* first time */ 725 setnetgrent(_pw_passwd.pw_name + 2); 726 s = getnetgrent(&host, &user, &dom); 727 if(s == 0) { /* end of group */ 728 endnetgrent(); 729 s = -1; 730 continue; 731 } else { 732 if(user && *user) { 733 r = yp_match(__ypdomain, 734 "passwd.byname", 735 user, strlen(user), 736 &__ypcurrent, 737 &__ypcurrentlen); 738 } else 739 goto pwuid_netgrp; 740 if(r != 0) { 741 if(__ypcurrent) 742 free(__ypcurrent); 743 __ypcurrent = NULL; 744 /* 745 * just because this 746 * user is bad, doesn't 747 * mean they all are. 748 */ 749 goto pwuid_netgrp; 750 } 751 } 752 break; 753 default: 754 if(__ypcurrent) { 755 free(__ypcurrent); 756 __ypcurrent = NULL; 757 } 758 user = _pw_passwd.pw_name + 1; 759 r = yp_match(__ypdomain, 760 "passwd.byname", 761 user, strlen(user), 762 &__ypcurrent, 763 &__ypcurrentlen); 764 if(r != 0) { 765 if(__ypcurrent) 766 free(__ypcurrent); 767 __ypcurrent = NULL; 768 continue; 769 } 770 break; 771 } 772 bcopy(__ypcurrent, line, __ypcurrentlen); 773 line[__ypcurrentlen] = '\0'; 774 if(__ypparse(&_pw_passwd, line) 775 || __ypexclude_is(_pw_passwd.pw_name)) { 776 if(s == 1) /* inside netgroup */ 777 goto pwuid_netgrp; 778 continue; 779 } 780 break; 781 case '-': 782 /* attempted exclusion */ 783 switch(_pw_passwd.pw_name[1]) { 784 case '\0': 785 break; 786 case '@': 787 setnetgrent(_pw_passwd.pw_name + 2); 788 while(getnetgrent(&host, &user, &dom)) { 789 if(user && *user) 790 __ypexclude_add(user); 791 } 792 endnetgrent(); 793 break; 794 default: 795 __ypexclude_add(_pw_passwd.pw_name + 1); 796 break; 797 } 798 break; 799 800 continue; 801 } 802 if( _pw_passwd.pw_uid == uid) { 803 if (!_pw_stayopen) { 804 (void)(_pw_db->close)(_pw_db); 805 _pw_db = (DB *)NULL; 806 } 807 if (__ypexclude != (DB *)NULL) { 808 (void)(__ypexclude->close)(__ypexclude); 809 __ypexclude = (DB *)NULL; 810 } 811 __ypproto = NULL; 812 return &_pw_passwd; 813 } 814 if(s == 1) /* inside netgroup */ 815 goto pwuid_netgrp; 816 continue; 817 } 818 if (!_pw_stayopen) { 819 (void)(_pw_db->close)(_pw_db); 820 _pw_db = (DB *)NULL; 821 } 822 if(__ypexclude != (DB *)NULL) { 823 (void)(__ypexclude->close)(__ypexclude); 824 __ypexclude = (DB *)NULL; 825 } 826 __ypproto = (struct passwd *)NULL; 827 return (struct passwd *)NULL; 828 } 829 #endif /* YP */ 830 831 bf[0] = _PW_KEYBYUID; 832 keyuid = uid; 833 bcopy(&keyuid, bf + 1, sizeof(keyuid)); 834 key.data = (u_char *)bf; 835 key.size = sizeof(keyuid) + 1; 836 rval = __hashpw(&key); 837 838 if (!_pw_stayopen) { 839 (void)(_pw_db->close)(_pw_db); 840 _pw_db = (DB *)NULL; 841 } 842 return(rval ? &_pw_passwd : (struct passwd *)NULL); 843 } 844 845 int 846 setpassent(stayopen) 847 int stayopen; 848 { 849 _pw_keynum = 0; 850 _pw_stayopen = stayopen; 851 #ifdef YP 852 __ypmode = YPMODE_NONE; 853 if(__ypcurrent) 854 free(__ypcurrent); 855 __ypcurrent = NULL; 856 if(__ypexclude != (DB *)NULL) { 857 (void)(__ypexclude->close)(__ypexclude); 858 __ypexclude = (DB *)NULL; 859 } 860 __ypproto = (struct passwd *)NULL; 861 #endif 862 return(1); 863 } 864 865 void 866 setpwent() 867 { 868 (void) setpassent(0); 869 } 870 871 void 872 endpwent() 873 { 874 _pw_keynum = 0; 875 if (_pw_db) { 876 (void)(_pw_db->close)(_pw_db); 877 _pw_db = (DB *)NULL; 878 } 879 #ifdef YP 880 __ypmode = YPMODE_NONE; 881 if(__ypcurrent) 882 free(__ypcurrent); 883 __ypcurrent = NULL; 884 if(__ypexclude != (DB *)NULL) { 885 (void)(__ypexclude->close)(__ypexclude); 886 __ypexclude = (DB *)NULL; 887 } 888 __ypproto = (struct passwd *)NULL; 889 #endif 890 } 891 892 static int 893 __initdb() 894 { 895 static int warned; 896 char *p; 897 898 #ifdef YP 899 __ypmode = YPMODE_NONE; 900 #endif 901 p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB; 902 _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL); 903 if (_pw_db) 904 return(1); 905 if (!warned) 906 syslog(LOG_ERR, "%s: %m", p); 907 warned = 1; 908 return(0); 909 } 910 911 static int 912 __hashpw(key) 913 DBT *key; 914 { 915 char *p, *t; 916 static u_int max; 917 static char *line; 918 DBT data; 919 920 if ((_pw_db->get)(_pw_db, key, &data, 0)) 921 return(0); 922 p = (char *)data.data; 923 if (data.size > max && !(line = realloc(line, (max += 1024)))) 924 return(0); 925 926 t = line; 927 #define EXPAND(e) e = t; while ((*t++ = *p++)); 928 EXPAND(_pw_passwd.pw_name); 929 EXPAND(_pw_passwd.pw_passwd); 930 bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 931 p += sizeof(int); 932 bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 933 p += sizeof(int); 934 bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 935 p += sizeof(time_t); 936 EXPAND(_pw_passwd.pw_class); 937 EXPAND(_pw_passwd.pw_gecos); 938 EXPAND(_pw_passwd.pw_dir); 939 EXPAND(_pw_passwd.pw_shell); 940 bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 941 p += sizeof(time_t); 942 943 /* See if there's any data left. If so, read in flags. */ 944 if (data.size > (p - (char *)data.data)) { 945 bcopy(p, (char *)&_pw_flags, sizeof(int)); 946 p += sizeof(int); 947 } else 948 _pw_flags = _PASSWORD_NOUID|_PASSWORD_NOGID; /* default */ 949 950 return(1); 951 } 952