1 /* 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #if defined(LIBC_SCCS) && !defined(lint) 35 static char sccsid[] = "@(#)getpwent.c 8.2 (Berkeley) 4/27/95"; 36 #endif /* LIBC_SCCS and not lint */ 37 38 #include <stdio.h> 39 #include <sys/param.h> 40 #include <fcntl.h> 41 #include <db.h> 42 #include <syslog.h> 43 #include <pwd.h> 44 #include <utmp.h> 45 #include <errno.h> 46 #include <unistd.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <limits.h> 50 #include <grp.h> 51 52 extern void setnetgrent __P(( char * )); 53 extern int getnetgrent __P(( char **, char **, char ** )); 54 extern int innetgr __P(( const char *, const char *, const char *, const char * )); 55 56 /* 57 * The lookup techniques and data extraction code here must be kept 58 * in sync with that in `pwd_mkdb'. 59 */ 60 61 static struct passwd _pw_passwd; /* password structure */ 62 static DB *_pw_db; /* password database */ 63 static int _pw_keynum; /* key counter */ 64 static int _pw_stayopen; /* keep fd's open */ 65 #ifdef YP 66 #include <rpc/rpc.h> 67 #include <rpcsvc/yp_prot.h> 68 #include <rpcsvc/ypclnt.h> 69 70 static struct passwd _pw_copy; 71 static DBT empty = { NULL, 0 }; 72 static DB *_ypcache = (DB *)NULL; 73 static int _yp_exclusions = 0; 74 static int _yp_enabled = -1; 75 static int _pw_stepping_yp; /* set true when stepping thru map */ 76 static char _ypnam[YPMAXRECORD]; 77 #define YP_HAVE_MASTER 2 78 #define YP_HAVE_ADJUNCT 1 79 #define YP_HAVE_NONE 0 80 static int _gotmaster; 81 static char *_pw_yp_domain; 82 static inline int unwind __P(( char * )); 83 static void _ypinitdb __P(( void )); 84 static int _havemaster __P((char *)); 85 static int _getyppass __P((struct passwd *, const char *, const char * )); 86 static int _nextyppass __P((struct passwd *)); 87 static inline int lookup __P((const char *)); 88 static inline void store __P((const char *)); 89 static inline int ingr __P((const char *, const char*)); 90 static inline int verf __P((const char *)); 91 static char * _get_adjunct_pw __P((const char *)); 92 #endif 93 static int __hashpw(DBT *); 94 static int __initdb(void); 95 96 struct passwd * 97 getpwent() 98 { 99 DBT key; 100 char bf[sizeof(_pw_keynum) + 1]; 101 int rv; 102 103 if (!_pw_db && !__initdb()) 104 return((struct passwd *)NULL); 105 106 #ifdef YP 107 if(_pw_stepping_yp) { 108 _pw_passwd = _pw_copy; 109 if (unwind((char *)&_ypnam)) 110 return(&_pw_passwd); 111 } 112 #endif 113 tryagain: 114 115 ++_pw_keynum; 116 bf[0] = _PW_KEYBYNUM; 117 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); 118 key.data = (u_char *)bf; 119 key.size = sizeof(_pw_keynum) + 1; 120 rv = __hashpw(&key); 121 if(!rv) return (struct passwd *)NULL; 122 #ifdef YP 123 if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { 124 if (_yp_enabled == -1) 125 _ypinitdb(); 126 bzero((char *)&_ypnam, sizeof(_ypnam)); 127 bcopy(_pw_passwd.pw_name, _ypnam, 128 strlen(_pw_passwd.pw_name)); 129 _pw_copy = _pw_passwd; 130 if (unwind((char *)&_ypnam) == 0) 131 goto tryagain; 132 else 133 return(&_pw_passwd); 134 } 135 #else 136 /* Ignore YP password file entries when YP is disabled. */ 137 if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { 138 goto tryagain; 139 } 140 #endif 141 return(&_pw_passwd); 142 } 143 144 struct passwd * 145 getpwnam(name) 146 const char *name; 147 { 148 DBT key; 149 int len, rval; 150 char bf[UT_NAMESIZE + 2]; 151 152 if (!_pw_db && !__initdb()) 153 return((struct passwd *)NULL); 154 155 bf[0] = _PW_KEYBYNAME; 156 len = strlen(name); 157 bcopy(name, bf + 1, MIN(len, UT_NAMESIZE)); 158 key.data = (u_char *)bf; 159 key.size = len + 1; 160 rval = __hashpw(&key); 161 162 #ifdef YP 163 if (!rval) { 164 if (_yp_enabled == -1) 165 _ypinitdb(); 166 if (_yp_enabled) 167 rval = _getyppass(&_pw_passwd, name, "passwd.byname"); 168 } 169 #endif 170 /* 171 * Prevent login attempts when YP is not enabled but YP entries 172 * are in /etc/master.passwd. 173 */ 174 if (rval && (_pw_passwd.pw_name[0] == '+'|| 175 _pw_passwd.pw_name[0] == '-')) rval = 0; 176 177 endpwent(); 178 return(rval ? &_pw_passwd : (struct passwd *)NULL); 179 } 180 181 struct passwd * 182 getpwuid(uid) 183 uid_t uid; 184 { 185 DBT key; 186 int keyuid, rval; 187 char bf[sizeof(keyuid) + 1]; 188 189 if (!_pw_db && !__initdb()) 190 return((struct passwd *)NULL); 191 192 bf[0] = _PW_KEYBYUID; 193 keyuid = uid; 194 bcopy(&keyuid, bf + 1, sizeof(keyuid)); 195 key.data = (u_char *)bf; 196 key.size = sizeof(keyuid) + 1; 197 rval = __hashpw(&key); 198 199 #ifdef YP 200 if (!rval) { 201 if (_yp_enabled == -1) 202 _ypinitdb(); 203 if (_yp_enabled) { 204 char ypbuf[16]; /* big enough for 32-bit uids */ 205 snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid); 206 rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid"); 207 } 208 } 209 #endif 210 /* 211 * Prevent login attempts when YP is not enabled but YP entries 212 * are in /etc/master.passwd. 213 */ 214 if (rval && (_pw_passwd.pw_name[0] == '+'|| 215 _pw_passwd.pw_name[0] == '-')) rval = 0; 216 217 endpwent(); 218 return(rval ? &_pw_passwd : (struct passwd *)NULL); 219 } 220 221 int 222 setpassent(stayopen) 223 int stayopen; 224 { 225 _pw_keynum = 0; 226 #ifdef YP 227 _pw_stepping_yp = 0; 228 #endif 229 _pw_stayopen = stayopen; 230 return(1); 231 } 232 233 void 234 setpwent() 235 { 236 (void)setpassent(0); 237 } 238 239 void 240 endpwent() 241 { 242 _pw_keynum = 0; 243 #ifdef YP 244 _pw_stepping_yp = 0; 245 #endif 246 if (_pw_db) { 247 (void)(_pw_db->close)(_pw_db); 248 _pw_db = (DB *)NULL; 249 } 250 #ifdef YP 251 if (_ypcache) { 252 (void)(_ypcache->close)(_ypcache); 253 _ypcache = (DB *)NULL; 254 _yp_exclusions = 0; 255 } 256 #endif 257 } 258 259 static int 260 __initdb() 261 { 262 static int warned; 263 char *p; 264 265 p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB; 266 _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL); 267 if (_pw_db) 268 return(1); 269 if (!warned++) 270 syslog(LOG_ERR, "%s: %m", p); 271 return(0); 272 } 273 274 static int 275 __hashpw(key) 276 DBT *key; 277 { 278 register char *p, *t; 279 static u_int max; 280 static char *line; 281 DBT data; 282 283 if ((_pw_db->get)(_pw_db, key, &data, 0)) 284 return(0); 285 p = (char *)data.data; 286 287 /* Increase buffer size for long lines if necessary. */ 288 if (data.size > max) { 289 max = data.size + 1024; 290 if (!(line = realloc(line, max))) 291 return(0); 292 } 293 294 /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ 295 t = line; 296 #define EXPAND(e) e = t; while ( (*t++ = *p++) ); 297 #define SCALAR(v) memmove(&(v), p, sizeof v); p += sizeof v 298 EXPAND(_pw_passwd.pw_name); 299 EXPAND(_pw_passwd.pw_passwd); 300 SCALAR(_pw_passwd.pw_uid); 301 SCALAR(_pw_passwd.pw_gid); 302 SCALAR(_pw_passwd.pw_change); 303 EXPAND(_pw_passwd.pw_class); 304 EXPAND(_pw_passwd.pw_gecos); 305 EXPAND(_pw_passwd.pw_dir); 306 EXPAND(_pw_passwd.pw_shell); 307 SCALAR(_pw_passwd.pw_expire); 308 bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields); 309 p += sizeof _pw_passwd.pw_fields; 310 return(1); 311 } 312 313 #ifdef YP 314 315 static void 316 _ypinitdb() 317 { 318 DBT key, data; 319 char buf[] = { _PW_KEYYPENABLED }; 320 key.data = buf; 321 key.size = 1; 322 _yp_enabled = 0; 323 if ((_pw_db->get)(_pw_db, &key, &data, 0) == 0) { 324 _yp_enabled = (int)*((char *)data.data) - 2; 325 /* Don't even bother with this if we aren't root. */ 326 if (!geteuid()) { 327 if (!_pw_yp_domain) 328 if (yp_get_default_domain(&_pw_yp_domain)) 329 return; 330 _gotmaster = _havemaster(_pw_yp_domain); 331 } else _gotmaster = YP_HAVE_NONE; 332 /* 333 * Create a DB hash database in memory. Bet you didn't know you 334 * could do a dbopen() with a NULL filename, did you. 335 */ 336 if (_ypcache == (DB *)NULL) 337 _ypcache = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL); 338 } 339 } 340 341 /* 342 * See if a user is in the blackballed list. 343 */ 344 static inline int 345 lookup(name) 346 const char *name; 347 { 348 DBT key; 349 350 if (!_yp_exclusions) 351 return(0); 352 353 key.data = (char *)name; 354 key.size = strlen(name); 355 356 if ((_ypcache->get)(_ypcache, &key, &empty, 0)) { 357 return(0); 358 } 359 360 return(1); 361 } 362 363 /* 364 * Store a blackballed user in an in-core hash database. 365 */ 366 static inline void 367 store(key) 368 const char *key; 369 { 370 DBT lkey; 371 /* 372 if (lookup(key)) 373 return; 374 */ 375 376 _yp_exclusions = 1; 377 378 lkey.data = (char *)key; 379 lkey.size = strlen(key); 380 381 (void)(_ypcache->put)(_ypcache, &lkey, &empty, R_NOOVERWRITE); 382 } 383 384 /* 385 * Parse the + entries in the password database and do appropriate 386 * NIS lookups. While ugly to look at, this is optimized to do only 387 * as many lookups as are absolutely necessary in any given case. 388 * Basically, the getpwent() function will feed us + and - lines 389 * as they appear in the database. For + lines, we do netgroup/group 390 * and user lookups to find all usernames that match the rule and 391 * extract them from the NIS passwd maps. For - lines, we save the 392 * matching names in a database and a) exlude them, and b) make sure 393 * we don't consider them when processing other + lines that appear 394 * later. 395 */ 396 static inline int 397 unwind(grp) 398 char *grp; 399 { 400 char *user, *host, *domain; 401 static int latch = 0; 402 static struct group *gr = NULL; 403 int rv = 0; 404 405 if (grp[0] == '+') { 406 if (strlen(grp) == 1) { 407 return(_nextyppass(&_pw_passwd)); 408 } 409 if (grp[1] == '@') { 410 _pw_stepping_yp = 1; 411 grpagain: 412 if (gr != NULL) { 413 if (*gr->gr_mem != NULL) { 414 if (lookup(*gr->gr_mem)) { 415 gr->gr_mem++; 416 goto grpagain; 417 } 418 rv = _getyppass(&_pw_passwd, 419 *gr->gr_mem, 420 "passwd.byname"); 421 gr->gr_mem++; 422 return(rv); 423 } else { 424 endgrent(); 425 latch = 0; 426 gr = NULL; 427 return(0); 428 } 429 } 430 if (!latch) { 431 setnetgrent(grp+2); 432 latch++; 433 } 434 again: 435 if (getnetgrent(&host, &user, &domain) == 0) { 436 if ((gr = getgrnam(grp+2)) != NULL) 437 goto grpagain; 438 latch = 0; 439 _pw_stepping_yp = 0; 440 return(0); 441 } else { 442 if (lookup(user)) 443 goto again; 444 if (_getyppass(&_pw_passwd, user, 445 "passwd.byname")) 446 return(1); 447 else 448 goto again; 449 } 450 } else { 451 if (lookup(grp+1)) 452 return(0); 453 return(_getyppass(&_pw_passwd, grp+1, "passwd.byname")); 454 } 455 } else { 456 if (grp[1] == '@') { 457 setnetgrent(grp+2); 458 rv = 0; 459 while(getnetgrent(&host, &user, &domain) != 0) { 460 store(user); 461 rv++; 462 } 463 if (!rv && (gr = getgrnam(grp+2)) != NULL) { 464 while(*gr->gr_mem) { 465 store(*gr->gr_mem); 466 gr->gr_mem++; 467 } 468 } 469 } else { 470 store(grp+1); 471 } 472 } 473 return(0); 474 } 475 476 /* 477 * See if a user is a member of a particular group. 478 */ 479 static inline int 480 ingr(grp, name) 481 const char *grp; 482 const char *name; 483 { 484 register struct group *gr; 485 486 if ((gr = getgrnam(grp)) == NULL) 487 return(0); 488 489 while(*gr->gr_mem) { 490 if (!strcmp(*gr->gr_mem, name)) { 491 endgrent(); 492 return(1); 493 } 494 gr->gr_mem++; 495 } 496 497 endgrent(); 498 return(0); 499 } 500 501 /* 502 * Check a user against the +@netgroup/-@netgroup lines listed in 503 * the local password database. Also checks +user/-user lines. 504 * If no netgroup exists that matches +@netgroup/-@netgroup, 505 * try searching regular groups with the same name. 506 */ 507 static inline int 508 verf(name) 509 const char *name; 510 { 511 DBT key; 512 char bf[sizeof(_pw_keynum) + 1]; 513 int keynum = 0; 514 515 again: 516 ++keynum; 517 bf[0] = _PW_KEYYPBYNUM; 518 bcopy((char *)&keynum, bf + 1, sizeof(keynum)); 519 key.data = (u_char *)bf; 520 key.size = sizeof(keynum) + 1; 521 if (!__hashpw(&key)) { 522 /* Try again using old format */ 523 bf[0] = _PW_KEYBYNUM; 524 bcopy((char *)&keynum, bf + 1, sizeof(keynum)); 525 key.data = (u_char *)bf; 526 if (!__hashpw(&key)) 527 return(0); 528 } 529 if (_pw_passwd.pw_name[0] != '+' && (_pw_passwd.pw_name[0] != '-')) 530 goto again; 531 if (_pw_passwd.pw_name[0] == '+') { 532 if (strlen(_pw_passwd.pw_name) == 1) /* Wildcard */ 533 return(1); 534 if (_pw_passwd.pw_name[1] == '@') { 535 if ((innetgr(_pw_passwd.pw_name+2, NULL, name, 536 _pw_yp_domain) || 537 ingr(_pw_passwd.pw_name+2, name)) && !lookup(name)) 538 return(1); 539 else 540 goto again; 541 } else { 542 if (!strcmp(name, _pw_passwd.pw_name+1) && 543 !lookup(name)) 544 return(1); 545 else 546 goto again; 547 } 548 } 549 if (_pw_passwd.pw_name[0] == '-') { 550 /* Note that a minus wildcard is a no-op. */ 551 if (_pw_passwd.pw_name[1] == '@') { 552 if (innetgr(_pw_passwd.pw_name+2, NULL, name, 553 _pw_yp_domain) || 554 ingr(_pw_passwd.pw_name+2, name)) { 555 store(name); 556 return(0); 557 } else 558 goto again; 559 } else { 560 if (!strcmp(name, _pw_passwd.pw_name+1)) { 561 store(name); 562 return(0); 563 } else 564 goto again; 565 } 566 567 } 568 return(0); 569 } 570 571 static char * 572 _get_adjunct_pw(name) 573 const char *name; 574 { 575 static char adjunctbuf[YPMAXRECORD+2]; 576 int rval; 577 char *result; 578 int resultlen; 579 char *map = "passwd.adjunct.byname"; 580 char *s; 581 582 if ((rval = yp_match(_pw_yp_domain, map, name, strlen(name), 583 &result, &resultlen))) 584 return(NULL); 585 586 strncpy(adjunctbuf, result, resultlen); 587 adjunctbuf[resultlen] = '\0'; 588 free(result); 589 result = (char *)&adjunctbuf; 590 591 /* Don't care about the name. */ 592 if ((s = strsep(&result, ":")) == NULL) 593 return (NULL); /* name */ 594 if ((s = strsep(&result, ":")) == NULL) 595 return (NULL); /* password */ 596 597 return(s); 598 } 599 600 static int 601 _pw_breakout_yp(struct passwd *pw, char *res, int resultlen, int master) 602 { 603 char *s, *result; 604 static char resbuf[YPMAXRECORD+2]; 605 606 /* 607 * Be triple, ultra super-duper paranoid: reject entries 608 * that start with a + or -. yp_mkdb and /var/yp/Makefile 609 * are _both_ supposed to strip these out, but you never 610 * know. 611 */ 612 if (*res == '+' || *res == '-') 613 return 0; 614 615 /* 616 * The NIS protocol definition limits the size of an NIS 617 * record to YPMAXRECORD bytes. We need to do a copy to 618 * a static buffer here since the memory pointed to by 619 * res will be free()ed when this function returns. 620 */ 621 strncpy((char *)&resbuf, res, resultlen); 622 resbuf[resultlen] = '\0'; 623 result = (char *)&resbuf; 624 625 /* 626 * XXX Sanity check: make sure all fields are valid (no NULLs). 627 * If we find a badly formatted entry, we punt. 628 */ 629 if ((s = strsep(&result, ":")) == NULL) return 0; /* name */ 630 /* 631 * We don't care what pw_fields says: we _always_ want the 632 * username returned to us by NIS. 633 */ 634 pw->pw_name = s; 635 pw->pw_fields |= _PWF_NAME; 636 637 if ((s = strsep(&result, ":")) == NULL) return 0; /* password */ 638 if(!(pw->pw_fields & _PWF_PASSWD)) { 639 /* SunOS passwd.adjunct hack */ 640 if (master == YP_HAVE_ADJUNCT && strstr(s, "##") != NULL) { 641 char *realpw; 642 realpw = _get_adjunct_pw(pw->pw_name); 643 if (realpw == NULL) 644 pw->pw_passwd = s; 645 else 646 pw->pw_passwd = realpw; 647 } else { 648 pw->pw_passwd = s; 649 } 650 pw->pw_fields |= _PWF_PASSWD; 651 } 652 653 if ((s = strsep(&result, ":")) == NULL) return 0; /* uid */ 654 if(!(pw->pw_fields & _PWF_UID)) { 655 pw->pw_uid = atoi(s); 656 pw->pw_fields |= _PWF_UID; 657 } 658 659 if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */ 660 if(!(pw->pw_fields & _PWF_GID)) { 661 pw->pw_gid = atoi(s); 662 pw->pw_fields |= _PWF_GID; 663 } 664 665 if (master == YP_HAVE_MASTER) { 666 if ((s = strsep(&result, ":")) == NULL) return 0; /* class */ 667 if(!(pw->pw_fields & _PWF_CLASS)) { 668 pw->pw_class = s; 669 pw->pw_fields |= _PWF_CLASS; 670 } 671 672 if ((s = strsep(&result, ":")) == NULL) return 0; /* change */ 673 if(!(pw->pw_fields & _PWF_CHANGE)) { 674 pw->pw_change = atol(s); 675 pw->pw_fields |= _PWF_CHANGE; 676 } 677 678 if ((s = strsep(&result, ":")) == NULL) return 0; /* expire */ 679 if(!(pw->pw_fields & _PWF_EXPIRE)) { 680 pw->pw_expire = atol(s); 681 pw->pw_fields |= _PWF_EXPIRE; 682 } 683 } 684 685 if ((s = strsep(&result, ":")) == NULL) return 0; /* gecos */ 686 if(!(pw->pw_fields & _PWF_GECOS)) { 687 pw->pw_gecos = s; 688 pw->pw_fields |= _PWF_GECOS; 689 } 690 691 if ((s = strsep(&result, ":")) == NULL) return 0; /* dir */ 692 if(!(pw->pw_fields & _PWF_DIR)) { 693 pw->pw_dir = s; 694 pw->pw_fields |= _PWF_DIR; 695 } 696 697 if ((s = strsep(&result, ":")) == NULL) return 0; /* shell */ 698 if(!(pw->pw_fields & _PWF_SHELL)) { 699 pw->pw_shell = s; 700 pw->pw_fields |= _PWF_SHELL; 701 } 702 703 /* Be consistent. */ 704 if ((s = strchr(pw->pw_shell, '\n'))) *s = '\0'; 705 706 return 1; 707 } 708 709 static int 710 _havemaster(char *_yp_domain) 711 { 712 int order; 713 int rval; 714 715 if (!(rval = yp_order(_yp_domain, "master.passwd.byname", &order))) 716 return(YP_HAVE_MASTER); 717 718 /* 719 * NIS+ in YP compat mode doesn't support 720 * YPPROC_ORDER -- no point in continuing. 721 */ 722 if (rval == YPERR_YPERR) 723 return(YP_HAVE_NONE); 724 725 /* master.passwd doesn't exist -- try passwd.adjunct */ 726 if (rval == YPERR_MAP) { 727 rval = yp_order(_yp_domain, "passwd.adjunct.byname", &order); 728 if (!rval) 729 return(YP_HAVE_ADJUNCT); 730 } 731 732 return (YP_HAVE_NONE); 733 } 734 735 static int 736 _getyppass(struct passwd *pw, const char *name, const char *map) 737 { 738 char *result, *s; 739 int resultlen; 740 int rv; 741 char mastermap[YPMAXRECORD]; 742 743 if(!_pw_yp_domain) { 744 if(yp_get_default_domain(&_pw_yp_domain)) 745 return 0; 746 } 747 748 sprintf(mastermap,"%s",map); 749 750 if (_gotmaster == YP_HAVE_MASTER) 751 sprintf(mastermap,"master.%s", map); 752 753 if(yp_match(_pw_yp_domain, (char *)&mastermap, name, strlen(name), 754 &result, &resultlen)) 755 return 0; 756 757 if (!_pw_stepping_yp) { 758 s = strchr(result, ':'); 759 if (s) { 760 *s = '\0'; 761 } else { 762 /* Must be a malformed entry if no colons. */ 763 free(result); 764 return(0); 765 } 766 767 if (!verf(result)) { 768 *s = ':'; 769 free(result); 770 return(0); 771 } 772 773 *s = ':'; /* Put back the colon we previously replaced with a NUL. */ 774 } 775 776 rv = _pw_breakout_yp(pw, result, resultlen, _gotmaster); 777 free(result); 778 return(rv); 779 } 780 781 static int 782 _nextyppass(struct passwd *pw) 783 { 784 static char *key; 785 static int keylen; 786 char *lastkey, *result, *s; 787 int resultlen; 788 int rv; 789 char *map = "passwd.byname"; 790 791 if(!_pw_yp_domain) { 792 if(yp_get_default_domain(&_pw_yp_domain)) 793 return 0; 794 } 795 796 if (_gotmaster == YP_HAVE_MASTER) 797 map = "master.passwd.byname"; 798 799 if(!_pw_stepping_yp) { 800 if(key) free(key); 801 rv = yp_first(_pw_yp_domain, map, 802 &key, &keylen, &result, &resultlen); 803 if(rv) { 804 return 0; 805 } 806 _pw_stepping_yp = 1; 807 goto unpack; 808 } else { 809 tryagain: 810 lastkey = key; 811 rv = yp_next(_pw_yp_domain, map, key, keylen, 812 &key, &keylen, &result, &resultlen); 813 free(lastkey); 814 unpack: 815 if(rv) { 816 _pw_stepping_yp = 0; 817 return 0; 818 } 819 820 s = strchr(result, ':'); 821 if (s) { 822 *s = '\0'; 823 } else { 824 /* Must be a malformed entry if no colons. */ 825 free(result); 826 goto tryagain; 827 } 828 829 if (lookup(result)) { 830 *s = ':'; 831 free(result); 832 goto tryagain; 833 } 834 835 *s = ':'; /* Put back the colon we previously replaced with a NUL. */ 836 if (_pw_breakout_yp(pw, result, resultlen, _gotmaster)) { 837 free(result); 838 return(1); 839 } else { 840 free(result); 841 goto tryagain; 842 } 843 } 844 } 845 846 #endif /* YP */ 847