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