1 /* $NetBSD: getpwent.c,v 1.14 1995/07/28 05:43:01 phil 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.14 1995/07/28 05:43:01 phil 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 register char *ptr; 143 register 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; 222 223 /* since this is currently using strsep(), parse it first */ 224 bp = s; 225 pw->pw_name = strsep(&bp, ":\n"); 226 pw->pw_passwd = strsep(&bp, ":\n"); 227 if (!(cp = strsep(&bp, ":\n"))) 228 return 1; 229 pw->pw_uid = atoi(cp); 230 if (!(cp = strsep(&bp, ":\n"))) 231 return 1; 232 pw->pw_gid = atoi(cp); 233 pw->pw_change = 0; 234 pw->pw_class = ""; 235 pw->pw_gecos = strsep(&bp, ":\n"); 236 pw->pw_dir = strsep(&bp, ":\n"); 237 pw->pw_shell = strsep(&bp, ":\n"); 238 pw->pw_expire = 0; 239 240 /* now let the prototype override, if set. */ 241 if(__ypproto != (struct passwd *)NULL) { 242 #ifdef YP_OVERRIDE_PASSWD 243 if(__ypproto->pw_passwd != (char *)NULL) 244 pw->pw_passwd = __ypproto->pw_passwd; 245 #endif 246 if(!(__ypflags & _PASSWORD_NOUID)) 247 pw->pw_uid = __ypproto->pw_uid; 248 if(!(__ypflags & _PASSWORD_NOGID)) 249 pw->pw_gid = __ypproto->pw_gid; 250 if(__ypproto->pw_gecos != (char *)NULL) 251 pw->pw_gecos = __ypproto->pw_gecos; 252 if(__ypproto->pw_dir != (char *)NULL) 253 pw->pw_dir = __ypproto->pw_dir; 254 if(__ypproto->pw_shell != (char *)NULL) 255 pw->pw_shell = __ypproto->pw_shell; 256 } 257 return 0; 258 } 259 #endif 260 261 struct passwd * 262 getpwent() 263 { 264 DBT key; 265 char bf[sizeof(_pw_keynum) + 1]; 266 #ifdef YP 267 char *cp; 268 static char *name = (char *)NULL; 269 const char *user, *host, *dom; 270 int has_yppw; 271 #endif 272 273 if (!_pw_db && !__initdb()) 274 return((struct passwd *)NULL); 275 276 #ifdef YP 277 has_yppw = __has_yppw(); 278 279 again: 280 if(has_yppw && (__ypmode != YPMODE_NONE)) { 281 char *key, *data; 282 int keylen, datalen; 283 int r, s; 284 285 if(!__ypdomain) { 286 if( _yp_check(&__ypdomain) == 0) { 287 __ypmode = YPMODE_NONE; 288 goto again; 289 } 290 } 291 switch(__ypmode) { 292 case YPMODE_FULL: 293 if(__ypcurrent) { 294 r = yp_next(__ypdomain, "passwd.byname", 295 __ypcurrent, __ypcurrentlen, 296 &key, &keylen, &data, &datalen); 297 free(__ypcurrent); 298 if(r != 0) { 299 __ypcurrent = NULL; 300 __ypmode = YPMODE_NONE; 301 if(data) 302 free(data); 303 data = NULL; 304 goto again; 305 } 306 __ypcurrent = key; 307 __ypcurrentlen = keylen; 308 bcopy(data, line, datalen); 309 free(data); 310 data = NULL; 311 } else { 312 r = yp_first(__ypdomain, "passwd.byname", 313 &__ypcurrent, &__ypcurrentlen, 314 &data, &datalen); 315 if(r != 0) { 316 __ypmode = YPMODE_NONE; 317 if(data) 318 free(data); 319 goto again; 320 } 321 bcopy(data, line, datalen); 322 free(data); 323 data = NULL; 324 } 325 break; 326 case YPMODE_NETGRP: 327 s = getnetgrent(&host, &user, &dom); 328 if(s == 0) { /* end of group */ 329 endnetgrent(); 330 __ypmode = YPMODE_NONE; 331 goto again; 332 } 333 if(user && *user) { 334 r = yp_match(__ypdomain, "passwd.byname", 335 user, strlen(user), 336 &data, &datalen); 337 } else 338 goto again; 339 if(r != 0) { 340 /* 341 * if the netgroup is invalid, keep looking 342 * as there may be valid users later on. 343 */ 344 if(data) 345 free(data); 346 goto again; 347 } 348 bcopy(data, line, datalen); 349 free(data); 350 data = (char *)NULL; 351 break; 352 case YPMODE_USER: 353 if(name != (char *)NULL) { 354 r = yp_match(__ypdomain, "passwd.byname", 355 name, strlen(name), 356 &data, &datalen); 357 __ypmode = YPMODE_NONE; 358 free(name); 359 name = (char *)NULL; 360 if(r != 0) { 361 if(data) 362 free(data); 363 goto again; 364 } 365 bcopy(data, line, datalen); 366 free(data); 367 data = (char *)NULL; 368 } else { /* XXX */ 369 __ypmode = YPMODE_NONE; 370 goto again; 371 } 372 break; 373 } 374 375 line[datalen] = '\0'; 376 if (__ypparse(&_pw_passwd, line)) 377 goto again; 378 return &_pw_passwd; 379 } 380 #endif 381 382 ++_pw_keynum; 383 bf[0] = _PW_KEYBYNUM; 384 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); 385 key.data = (u_char *)bf; 386 key.size = sizeof(_pw_keynum) + 1; 387 if(__hashpw(&key)) { 388 #ifdef YP 389 /* if we don't have YP at all, don't bother. */ 390 if(has_yppw) { 391 if(_pw_passwd.pw_name[0] == '+') { 392 /* set the mode */ 393 switch(_pw_passwd.pw_name[1]) { 394 case '\0': 395 __ypmode = YPMODE_FULL; 396 break; 397 case '@': 398 __ypmode = YPMODE_NETGRP; 399 setnetgrent(_pw_passwd.pw_name + 2); 400 break; 401 default: 402 __ypmode = YPMODE_USER; 403 name = strdup(_pw_passwd.pw_name + 1); 404 break; 405 } 406 407 /* save the prototype */ 408 __ypproto_set(); 409 goto again; 410 } else if(_pw_passwd.pw_name[0] == '-') { 411 /* an attempted exclusion */ 412 switch(_pw_passwd.pw_name[1]) { 413 case '\0': 414 break; 415 case '@': 416 setnetgrent(_pw_passwd.pw_name + 2); 417 while(getnetgrent(&host, &user, &dom)) { 418 if(user && *user) 419 __ypexclude_add(user); 420 } 421 endnetgrent(); 422 break; 423 default: 424 __ypexclude_add(_pw_passwd.pw_name + 1); 425 break; 426 } 427 goto again; 428 } 429 } 430 #endif 431 return &_pw_passwd; 432 } 433 return (struct passwd *)NULL; 434 } 435 436 #ifdef YP 437 438 /* 439 * See if the YP token is in the database. Only works if pwd_mkdb knows 440 * about the token. 441 */ 442 static int 443 __has_yppw() 444 { 445 DBT key, data; 446 DBT pkey, pdata; 447 int len; 448 char bf[UT_NAMESIZE]; 449 450 key.data = (u_char *)__yp_token; 451 key.size = strlen(__yp_token); 452 453 /* Pre-token database support. */ 454 bf[0] = _PW_KEYBYNAME; 455 len = strlen("+"); 456 bcopy("+", bf + 1, MIN(len, UT_NAMESIZE)); 457 pkey.data = (u_char *)bf; 458 pkey.size = len + 1; 459 460 if ((_pw_db->get)(_pw_db, &key, &data, 0) 461 && (_pw_db->get)(_pw_db, &pkey, &pdata, 0)) 462 return(0); /* No YP. */ 463 return(1); 464 } 465 #endif 466 467 struct passwd * 468 getpwnam(name) 469 const char *name; 470 { 471 DBT key; 472 int len, rval; 473 char bf[UT_NAMESIZE + 1]; 474 475 if (!_pw_db && !__initdb()) 476 return((struct passwd *)NULL); 477 478 #ifdef YP 479 /* 480 * If YP is active, we must sequence through the passwd file 481 * in sequence. 482 */ 483 if (__has_yppw()) { 484 int r; 485 int s = -1; 486 const char *host, *user, *dom; 487 488 for(_pw_keynum=1; _pw_keynum; _pw_keynum++) { 489 bf[0] = _PW_KEYBYNUM; 490 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); 491 key.data = (u_char *)bf; 492 key.size = sizeof(_pw_keynum) + 1; 493 if(__hashpw(&key) == 0) 494 break; 495 switch(_pw_passwd.pw_name[0]) { 496 case '+': 497 if(!__ypdomain) { 498 if(_yp_check(&__ypdomain) == 0) { 499 continue; 500 } 501 } 502 /* save the prototype */ 503 __ypproto_set(); 504 505 switch(_pw_passwd.pw_name[1]) { 506 case '\0': 507 if(__ypcurrent) { 508 free(__ypcurrent); 509 __ypcurrent = NULL; 510 } 511 r = yp_match(__ypdomain, 512 "passwd.byname", 513 name, strlen(name), 514 &__ypcurrent, &__ypcurrentlen); 515 if(r != 0) { 516 if(__ypcurrent) 517 free(__ypcurrent); 518 __ypcurrent = NULL; 519 continue; 520 } 521 break; 522 case '@': 523 pwnam_netgrp: 524 if(__ypcurrent) { 525 free(__ypcurrent); 526 __ypcurrent = NULL; 527 } 528 if(s == -1) /* first time */ 529 setnetgrent(_pw_passwd.pw_name + 2); 530 s = getnetgrent(&host, &user, &dom); 531 if(s == 0) { /* end of group */ 532 endnetgrent(); 533 s = -1; 534 continue; 535 } else { 536 if(user && *user) { 537 r = yp_match(__ypdomain, 538 "passwd.byname", 539 user, strlen(user), 540 &__ypcurrent, 541 &__ypcurrentlen); 542 } else 543 goto pwnam_netgrp; 544 if(r != 0) { 545 if(__ypcurrent) 546 free(__ypcurrent); 547 __ypcurrent = NULL; 548 /* 549 * just because this 550 * user is bad, doesn't 551 * mean they all are. 552 */ 553 goto pwnam_netgrp; 554 } 555 } 556 break; 557 default: 558 if(__ypcurrent) { 559 free(__ypcurrent); 560 __ypcurrent = NULL; 561 } 562 user = _pw_passwd.pw_name + 1; 563 r = yp_match(__ypdomain, 564 "passwd.byname", 565 user, strlen(user), 566 &__ypcurrent, 567 &__ypcurrentlen); 568 if(r != 0) { 569 if(__ypcurrent) 570 free(__ypcurrent); 571 __ypcurrent = NULL; 572 continue; 573 } 574 break; 575 } 576 bcopy(__ypcurrent, line, __ypcurrentlen); 577 line[__ypcurrentlen] = '\0'; 578 if(__ypparse(&_pw_passwd, line) 579 || __ypexclude_is(_pw_passwd.pw_name)) { 580 if(s == 1) /* inside netgrp */ 581 goto pwnam_netgrp; 582 continue; 583 } 584 break; 585 case '-': 586 /* attempted exclusion */ 587 switch(_pw_passwd.pw_name[1]) { 588 case '\0': 589 break; 590 case '@': 591 setnetgrent(_pw_passwd.pw_name + 2); 592 while(getnetgrent(&host, &user, &dom)) { 593 if(user && *user) 594 __ypexclude_add(user); 595 } 596 endnetgrent(); 597 break; 598 default: 599 __ypexclude_add(_pw_passwd.pw_name + 1); 600 break; 601 } 602 break; 603 604 continue; 605 } 606 if(strcmp(_pw_passwd.pw_name, name) == 0) { 607 if (!_pw_stayopen) { 608 (void)(_pw_db->close)(_pw_db); 609 _pw_db = (DB *)NULL; 610 } 611 if(__ypexclude != (DB *)NULL) { 612 (void)(__ypexclude->close)(__ypexclude); 613 __ypexclude = (DB *)NULL; 614 } 615 __ypproto = (struct passwd *)NULL; 616 return &_pw_passwd; 617 } 618 if(s == 1) /* inside netgrp */ 619 goto pwnam_netgrp; 620 continue; 621 } 622 if (!_pw_stayopen) { 623 (void)(_pw_db->close)(_pw_db); 624 _pw_db = (DB *)NULL; 625 } 626 if(__ypexclude != (DB *)NULL) { 627 (void)(__ypexclude->close)(__ypexclude); 628 __ypexclude = (DB *)NULL; 629 } 630 __ypproto = (struct passwd *)NULL; 631 return (struct passwd *)NULL; 632 } 633 #endif /* YP */ 634 635 bf[0] = _PW_KEYBYNAME; 636 len = strlen(name); 637 bcopy(name, bf + 1, MIN(len, UT_NAMESIZE)); 638 key.data = (u_char *)bf; 639 key.size = len + 1; 640 rval = __hashpw(&key); 641 642 if (!_pw_stayopen) { 643 (void)(_pw_db->close)(_pw_db); 644 _pw_db = (DB *)NULL; 645 } 646 return(rval ? &_pw_passwd : (struct passwd *)NULL); 647 } 648 649 struct passwd * 650 #ifdef __STDC__ 651 getpwuid(uid_t uid) 652 #else 653 getpwuid(uid) 654 int uid; 655 #endif 656 { 657 DBT key; 658 char bf[sizeof(_pw_keynum) + 1]; 659 int keyuid, rval; 660 661 if (!_pw_db && !__initdb()) 662 return((struct passwd *)NULL); 663 664 #ifdef YP 665 /* 666 * If YP is active, we must sequence through the passwd file 667 * in sequence. 668 */ 669 if (__has_yppw()) { 670 char uidbuf[20]; 671 int r; 672 int s = -1; 673 const char *host, *user, *dom; 674 675 sprintf(uidbuf, "%d", uid); 676 for(_pw_keynum=1; _pw_keynum; _pw_keynum++) { 677 bf[0] = _PW_KEYBYNUM; 678 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); 679 key.data = (u_char *)bf; 680 key.size = sizeof(_pw_keynum) + 1; 681 if(__hashpw(&key) == 0) 682 break; 683 switch(_pw_passwd.pw_name[0]) { 684 case '+': 685 if(!__ypdomain) { 686 if(_yp_check(&__ypdomain) == 0) { 687 continue; 688 } 689 } 690 /* save the prototype */ 691 __ypproto_set(); 692 693 switch(_pw_passwd.pw_name[1]) { 694 case '\0': 695 if(__ypcurrent) { 696 free(__ypcurrent); 697 __ypcurrent = NULL; 698 } 699 r = yp_match(__ypdomain, "passwd.byuid", 700 uidbuf, strlen(uidbuf), 701 &__ypcurrent, &__ypcurrentlen); 702 if(r != 0) { 703 if(__ypcurrent) 704 free(__ypcurrent); 705 __ypcurrent = NULL; 706 continue; 707 } 708 break; 709 case '@': 710 pwuid_netgrp: 711 if(__ypcurrent) { 712 free(__ypcurrent); 713 __ypcurrent = NULL; 714 } 715 if(s == -1) /* first time */ 716 setnetgrent(_pw_passwd.pw_name + 2); 717 s = getnetgrent(&host, &user, &dom); 718 if(s == 0) { /* end of group */ 719 endnetgrent(); 720 s = -1; 721 continue; 722 } else { 723 if(user && *user) { 724 r = yp_match(__ypdomain, 725 "passwd.byname", 726 user, strlen(user), 727 &__ypcurrent, 728 &__ypcurrentlen); 729 } else 730 goto pwuid_netgrp; 731 if(r != 0) { 732 if(__ypcurrent) 733 free(__ypcurrent); 734 __ypcurrent = NULL; 735 /* 736 * just because this 737 * user is bad, doesn't 738 * mean they all are. 739 */ 740 goto pwuid_netgrp; 741 } 742 } 743 break; 744 default: 745 if(__ypcurrent) { 746 free(__ypcurrent); 747 __ypcurrent = NULL; 748 } 749 user = _pw_passwd.pw_name + 1; 750 r = yp_match(__ypdomain, 751 "passwd.byname", 752 user, strlen(user), 753 &__ypcurrent, 754 &__ypcurrentlen); 755 if(r != 0) { 756 if(__ypcurrent) 757 free(__ypcurrent); 758 __ypcurrent = NULL; 759 continue; 760 } 761 break; 762 } 763 bcopy(__ypcurrent, line, __ypcurrentlen); 764 line[__ypcurrentlen] = '\0'; 765 if(__ypparse(&_pw_passwd, line) 766 || __ypexclude_is(_pw_passwd.pw_name)) { 767 if(s == 1) /* inside netgroup */ 768 goto pwuid_netgrp; 769 continue; 770 } 771 break; 772 case '-': 773 /* attempted exclusion */ 774 switch(_pw_passwd.pw_name[1]) { 775 case '\0': 776 break; 777 case '@': 778 setnetgrent(_pw_passwd.pw_name + 2); 779 while(getnetgrent(&host, &user, &dom)) { 780 if(user && *user) 781 __ypexclude_add(user); 782 } 783 endnetgrent(); 784 break; 785 default: 786 __ypexclude_add(_pw_passwd.pw_name + 1); 787 break; 788 } 789 break; 790 791 continue; 792 } 793 if( _pw_passwd.pw_uid == uid) { 794 if (!_pw_stayopen) { 795 (void)(_pw_db->close)(_pw_db); 796 _pw_db = (DB *)NULL; 797 } 798 if (__ypexclude != (DB *)NULL) { 799 (void)(__ypexclude->close)(__ypexclude); 800 __ypexclude = (DB *)NULL; 801 } 802 __ypproto = NULL; 803 return &_pw_passwd; 804 } 805 if(s == 1) /* inside netgroup */ 806 goto pwuid_netgrp; 807 continue; 808 } 809 if (!_pw_stayopen) { 810 (void)(_pw_db->close)(_pw_db); 811 _pw_db = (DB *)NULL; 812 } 813 if(__ypexclude != (DB *)NULL) { 814 (void)(__ypexclude->close)(__ypexclude); 815 __ypexclude = (DB *)NULL; 816 } 817 __ypproto = (struct passwd *)NULL; 818 return (struct passwd *)NULL; 819 } 820 #endif /* YP */ 821 822 bf[0] = _PW_KEYBYUID; 823 keyuid = uid; 824 bcopy(&keyuid, bf + 1, sizeof(keyuid)); 825 key.data = (u_char *)bf; 826 key.size = sizeof(keyuid) + 1; 827 rval = __hashpw(&key); 828 829 if (!_pw_stayopen) { 830 (void)(_pw_db->close)(_pw_db); 831 _pw_db = (DB *)NULL; 832 } 833 return(rval ? &_pw_passwd : (struct passwd *)NULL); 834 } 835 836 int 837 setpassent(stayopen) 838 int stayopen; 839 { 840 _pw_keynum = 0; 841 _pw_stayopen = stayopen; 842 #ifdef YP 843 __ypmode = YPMODE_NONE; 844 if(__ypcurrent) 845 free(__ypcurrent); 846 __ypcurrent = NULL; 847 if(__ypexclude != (DB *)NULL) { 848 (void)(__ypexclude->close)(__ypexclude); 849 __ypexclude = (DB *)NULL; 850 } 851 __ypproto = (struct passwd *)NULL; 852 #endif 853 return(1); 854 } 855 856 void 857 setpwent() 858 { 859 (void) setpassent(0); 860 } 861 862 void 863 endpwent() 864 { 865 _pw_keynum = 0; 866 if (_pw_db) { 867 (void)(_pw_db->close)(_pw_db); 868 _pw_db = (DB *)NULL; 869 } 870 #ifdef YP 871 __ypmode = YPMODE_NONE; 872 if(__ypcurrent) 873 free(__ypcurrent); 874 __ypcurrent = NULL; 875 if(__ypexclude != (DB *)NULL) { 876 (void)(__ypexclude->close)(__ypexclude); 877 __ypexclude = (DB *)NULL; 878 } 879 __ypproto = (struct passwd *)NULL; 880 #endif 881 } 882 883 static int 884 __initdb() 885 { 886 static int warned; 887 char *p; 888 889 #ifdef YP 890 __ypmode = YPMODE_NONE; 891 #endif 892 p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB; 893 _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL); 894 if (_pw_db) 895 return(1); 896 if (!warned) 897 syslog(LOG_ERR, "%s: %m", p); 898 warned = 1; 899 return(0); 900 } 901 902 static int 903 __hashpw(key) 904 DBT *key; 905 { 906 register char *p, *t; 907 static u_int max; 908 static char *line; 909 DBT data; 910 911 if ((_pw_db->get)(_pw_db, key, &data, 0)) 912 return(0); 913 p = (char *)data.data; 914 if (data.size > max && !(line = realloc(line, (max += 1024)))) 915 return(0); 916 917 t = line; 918 #define EXPAND(e) e = t; while ((*t++ = *p++)); 919 EXPAND(_pw_passwd.pw_name); 920 EXPAND(_pw_passwd.pw_passwd); 921 bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 922 p += sizeof(int); 923 bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 924 p += sizeof(int); 925 bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 926 p += sizeof(time_t); 927 EXPAND(_pw_passwd.pw_class); 928 EXPAND(_pw_passwd.pw_gecos); 929 EXPAND(_pw_passwd.pw_dir); 930 EXPAND(_pw_passwd.pw_shell); 931 bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 932 p += sizeof(time_t); 933 934 /* See if there's any data left. If so, read in flags. */ 935 if (data.size > (p - (char *)data.data)) { 936 bcopy(p, (char *)&_pw_flags, sizeof(int)); 937 p += sizeof(int); 938 } else 939 _pw_flags = _PASSWORD_NOUID|_PASSWORD_NOGID; /* default */ 940 941 return(1); 942 } 943