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