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