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