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