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.1 (Berkeley) 6/4/93"; 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 static struct passwd _pw_passwd; /* password structure */ 53 static DB *_pw_db; /* password database */ 54 static int _pw_keynum; /* key counter */ 55 static int _pw_stayopen; /* keep fd's open */ 56 #ifdef YP 57 #include <rpc/rpc.h> 58 #include <rpcsvc/yp_prot.h> 59 #include <rpcsvc/ypclnt.h> 60 struct _namelist { 61 char *name; 62 struct _namelist *next; 63 }; 64 static struct passwd _pw_copy; 65 struct _pw_cache { 66 struct passwd pw_entry; 67 struct _namelist *namelist; 68 struct _pw_cache *next; 69 }; 70 static int _pluscnt, _minuscnt; 71 static struct _pw_cache *_plushead = NULL, *_minushead = NULL; 72 static void _createcaches(), _freecaches(); 73 static int _scancaches(char *); 74 static int _yp_enabled; /* set true when yp enabled */ 75 static int _pw_stepping_yp; /* set true when stepping thru map */ 76 static int _yp_done; 77 static int _gotmaster; 78 static char *_pw_yp_domain; 79 static int _havemaster(char *); 80 static int _getyppass(struct passwd *, const char *, const char *); 81 static int _nextyppass(struct passwd *); 82 #endif 83 static int __hashpw(), __initdb(); 84 85 struct passwd * 86 getpwent() 87 { 88 DBT key; 89 char bf[sizeof(_pw_keynum) + 1]; 90 int rv; 91 92 if (!_pw_db && !__initdb()) 93 return((struct passwd *)NULL); 94 95 #ifdef YP 96 if(_pw_stepping_yp) { 97 _pw_passwd = _pw_copy; 98 if (_nextyppass(&_pw_passwd)) 99 return (&_pw_passwd); 100 else 101 _yp_done = 1; 102 } 103 #endif 104 tryagain: 105 106 ++_pw_keynum; 107 bf[0] = _PW_KEYBYNUM; 108 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); 109 key.data = (u_char *)bf; 110 key.size = sizeof(_pw_keynum) + 1; 111 rv = __hashpw(&key); 112 if(!rv) return (struct passwd *)NULL; 113 #ifdef YP 114 if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { 115 _pw_copy = _pw_passwd; 116 if (_yp_done || !_nextyppass(&_pw_passwd)) 117 goto tryagain; 118 else 119 return (&_pw_passwd); 120 } 121 #else 122 /* Ignore YP password file entries when YP is disabled. */ 123 if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { 124 goto tryagain; 125 } 126 #endif 127 return(&_pw_passwd); 128 } 129 130 struct passwd * 131 getpwnam(name) 132 const char *name; 133 { 134 DBT key; 135 int len, rval; 136 char bf[UT_NAMESIZE + 2]; 137 138 if (!_pw_db && !__initdb()) 139 return((struct passwd *)NULL); 140 141 bf[0] = _PW_KEYBYNAME; 142 len = strlen(name); 143 bcopy(name, bf + 1, MIN(len, UT_NAMESIZE)); 144 key.data = (u_char *)bf; 145 key.size = len + 1; 146 rval = __hashpw(&key); 147 148 #ifdef YP 149 if (!rval && _yp_enabled) 150 rval = _getyppass(&_pw_passwd, name, "passwd.byname"); 151 #endif 152 /* 153 * Prevent login attempts when YP is not enabled but YP entries 154 * are in /etc/master.passwd. 155 */ 156 if (rval && (_pw_passwd.pw_name[0] == '+'|| 157 _pw_passwd.pw_name[0] == '-')) rval = 0; 158 159 endpwent(); 160 return(rval ? &_pw_passwd : (struct passwd *)NULL); 161 } 162 163 struct passwd * 164 #ifdef __STDC__ 165 getpwuid(uid_t uid) 166 #else 167 getpwuid(uid) 168 int uid; 169 #endif 170 { 171 DBT key; 172 int keyuid, rval; 173 char bf[sizeof(keyuid) + 1]; 174 175 if (!_pw_db && !__initdb()) 176 return((struct passwd *)NULL); 177 178 bf[0] = _PW_KEYBYUID; 179 keyuid = uid; 180 bcopy(&keyuid, bf + 1, sizeof(keyuid)); 181 key.data = (u_char *)bf; 182 key.size = sizeof(keyuid) + 1; 183 rval = __hashpw(&key); 184 185 #ifdef YP 186 if (!rval && _yp_enabled) { 187 char ypbuf[16]; /* big enough for 32-bit uids and then some */ 188 snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid); 189 rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid"); 190 } 191 #endif 192 /* 193 * Prevent login attempts when YP is not enabled but YP entries 194 * are in /etc/master.passwd. 195 */ 196 if (rval && (_pw_passwd.pw_name[0] == '+'|| 197 _pw_passwd.pw_name[0] == '-')) rval = 0; 198 199 endpwent(); 200 return(rval ? &_pw_passwd : (struct passwd *)NULL); 201 } 202 203 int 204 setpassent(stayopen) 205 int stayopen; 206 { 207 _pw_keynum = 0; 208 #ifdef YP 209 _pw_stepping_yp = _yp_done = 0; 210 #endif 211 _pw_stayopen = stayopen; 212 return(1); 213 } 214 215 int 216 setpwent() 217 { 218 _pw_keynum = 0; 219 #ifdef YP 220 _pw_stepping_yp = _yp_done = 0; 221 #endif 222 _pw_stayopen = 0; 223 return(1); 224 } 225 226 void 227 endpwent() 228 { 229 _pw_keynum = 0; 230 #ifdef YP 231 _pw_stepping_yp = _yp_done = 0; 232 #endif 233 if (_pw_db) { 234 (void)(_pw_db->close)(_pw_db); 235 _pw_db = (DB *)NULL; 236 #ifdef YP 237 _freecaches(); 238 #endif 239 } 240 } 241 242 static 243 __initdb() 244 { 245 static int warned; 246 char *p; 247 248 p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB; 249 _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL); 250 if (_pw_db) { 251 #ifdef YP 252 DBT key, data; 253 char buf[] = { _PW_KEYYPENABLED }; 254 key.data = buf; 255 key.size = 1; 256 if ((_pw_db->get)(_pw_db, &key, &data, 0)) { 257 _yp_enabled = 0; 258 } else { 259 _yp_enabled = (int)*((char *)data.data) - 2; 260 _createcaches(); 261 /* Don't even bother with this if we aren't root. */ 262 if (!geteuid()) { 263 if (!_pw_yp_domain) 264 if (yp_get_default_domain(&_pw_yp_domain)) 265 return(1); 266 _gotmaster = _havemaster(_pw_yp_domain); 267 } else _gotmaster = 0; 268 } 269 #endif 270 return(1); 271 } 272 if (!warned) 273 syslog(LOG_ERR, "%s: %m", p); 274 return(0); 275 } 276 277 static 278 __hashpw(key) 279 DBT *key; 280 { 281 register char *p, *t; 282 static u_int max; 283 static char *line; 284 DBT data; 285 286 if ((_pw_db->get)(_pw_db, key, &data, 0)) 287 return(0); 288 p = (char *)data.data; 289 if (data.size > max && !(line = realloc(line, max += 1024))) 290 return(0); 291 292 t = line; 293 #define EXPAND(e) e = t; while (*t++ = *p++); 294 EXPAND(_pw_passwd.pw_name); 295 EXPAND(_pw_passwd.pw_passwd); 296 bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 297 p += sizeof(int); 298 bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 299 p += sizeof(int); 300 bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 301 p += sizeof(time_t); 302 EXPAND(_pw_passwd.pw_class); 303 EXPAND(_pw_passwd.pw_gecos); 304 EXPAND(_pw_passwd.pw_dir); 305 EXPAND(_pw_passwd.pw_shell); 306 bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 307 p += sizeof(time_t); 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 * Build special +@netgroup and -@netgroup caches. We also handle ordinary 316 * +user/-user entries, *and* +@group/-@group entries, which are special 317 * cases of the +@netgroup/-@netgroup substitutions: if we can't find 318 * netgroup 'foo', we look for a regular user group called 'foo' and 319 * match against that instead. The netgroup takes precedence since the 320 * +group/-group support is basically just a hack to make Justin T. Gibbs 321 * happy. :) Sorting out all the funny business here lets us have a 322 * yp_enabled flag with a simple on or off value instead of the somewhat 323 * bogus setup we had before. 324 * 325 * We cache everything here in one shot so that we only have to scan 326 * each netgroup/group once. The alternative is to use innetgr() inside the 327 * NIS lookup functions, which would make retrieving the whole password 328 * database though getpwent() very slow. +user/-user entries are treated 329 * like @groups/@netgroups with only one member. 330 */ 331 static void 332 _createcaches() 333 { 334 DBT key, data; 335 int i; 336 char bf[UT_NAMESIZE + 2]; 337 struct _pw_cache *p, *m; 338 struct _namelist *n, *namehead; 339 char *user, *host, *domain; 340 struct group *grp; 341 342 /* 343 * Assume that the database has already been initialized 344 * but be paranoid and check that YP is in fact enabled. 345 */ 346 347 if (!_yp_enabled) 348 return; 349 /* 350 * For the plus list, we have to store both the linked list of 351 * names and the +entries from the password database so we can 352 * do the substitution later if we find a match. 353 */ 354 bf[0] = _PW_KEYPLUSCNT; 355 key.data = (u_char*)bf; 356 key.size = 1; 357 if (!(_pw_db->get)(_pw_db, &key, &data, 0)) { 358 _pluscnt = (int)*((char *)data.data); 359 for (i = 0; i < _pluscnt; i++) { 360 bf[0] = _PW_KEYPLUSBYNUM; 361 bcopy(&i, bf + 1, sizeof(i) + 1); 362 key.size = (sizeof(i)) + 1; 363 if (__hashpw(&key)) { 364 p = (struct _pw_cache *)malloc(sizeof (struct _pw_cache)); 365 if (strlen(_pw_passwd.pw_name) > 2 && _pw_passwd.pw_name[1] == '@') { 366 setnetgrent(_pw_passwd.pw_name+2); 367 namehead = NULL; 368 while(getnetgrent(&host, &user, &domain)) { 369 n = (struct _namelist *)malloc(sizeof (struct _namelist)); 370 n->name = strdup(user); 371 n->next = namehead; 372 namehead = n; 373 } 374 /* 375 * If netgroup 'foo' doesn't exist, 376 * try group 'foo' instead. 377 */ 378 if (namehead == NULL && (grp = getgrnam(_pw_passwd.pw_name+2)) != NULL) { 379 while(*grp->gr_mem) { 380 n = (struct _namelist *)malloc(sizeof (struct _namelist)); 381 n->name = strdup(*grp->gr_mem); 382 n->next = namehead; 383 namehead = n; 384 grp->gr_mem++; 385 } 386 } 387 } else { 388 if (_pw_passwd.pw_name[1] != '@') { 389 namehead = (struct _namelist *)malloc(sizeof (struct _namelist)); 390 namehead->name = strdup(_pw_passwd.pw_name+1); 391 namehead->next = NULL; 392 } 393 } 394 p->namelist = namehead; 395 p->pw_entry.pw_name = strdup(_pw_passwd.pw_name); 396 p->pw_entry.pw_passwd = strdup(_pw_passwd.pw_passwd); 397 p->pw_entry.pw_uid = _pw_passwd.pw_uid; 398 p->pw_entry.pw_gid = _pw_passwd.pw_gid; 399 p->pw_entry.pw_expire = _pw_passwd.pw_expire; 400 p->pw_entry.pw_change = _pw_passwd.pw_change; 401 p->pw_entry.pw_class = strdup(_pw_passwd.pw_class); 402 p->pw_entry.pw_gecos = strdup(_pw_passwd.pw_gecos); 403 p->pw_entry.pw_dir = strdup(_pw_passwd.pw_dir); 404 p->pw_entry.pw_shell = strdup(_pw_passwd.pw_shell); 405 p->pw_entry.pw_fields = _pw_passwd.pw_fields; 406 p->next = _plushead; 407 _plushead = p; 408 } 409 } 410 } 411 412 /* 413 * All we need for the minuslist is the usernames. 414 * The actual -entries data can be ignored since no substitution 415 * will be done: anybody on the minus list is treated like a 416 * non-person. 417 */ 418 bf[0] = _PW_KEYMINUSCNT; 419 key.data = (u_char*)bf; 420 key.size = 1; 421 if (!(_pw_db->get)(_pw_db, &key, &data, 0)) { 422 _minuscnt = (int)*((char *)data.data); 423 for (i = _minuscnt; i > -1; i--) { 424 bf[0] = _PW_KEYMINUSBYNUM; 425 bcopy(&i, bf + 1, sizeof(i) + 1); 426 key.size = (sizeof(i)) + 1; 427 if (__hashpw(&key)) { 428 m = (struct _pw_cache *)malloc(sizeof (struct _pw_cache)); 429 if (strlen (_pw_passwd.pw_name) > 2 && _pw_passwd.pw_name[1] == '@') { 430 namehead = NULL; 431 setnetgrent(_pw_passwd.pw_name+2); 432 while(getnetgrent(&host, &user, &domain)) { 433 n = (struct _namelist *)malloc(sizeof (struct _namelist)); 434 n->name = strdup(user); 435 n->next = namehead; 436 namehead = n; 437 } 438 /* 439 * If netgroup 'foo' doesn't exist, 440 * try group 'foo' instead. 441 */ 442 if (namehead == NULL && (grp = getgrnam(_pw_passwd.pw_name+2)) != NULL) { 443 while(*grp->gr_mem) { 444 n = (struct _namelist *)malloc(sizeof (struct _namelist)); 445 n->name = strdup(*grp->gr_mem); 446 n->next = namehead; 447 namehead = n; 448 grp->gr_mem++; 449 } 450 } 451 } else { 452 if (_pw_passwd.pw_name[1] != '@') { 453 namehead = (struct _namelist *)malloc(sizeof (struct _namelist)); 454 namehead->name = strdup(_pw_passwd.pw_name+1); 455 namehead->next = NULL; 456 } 457 } 458 /* Save just the name */ 459 m->pw_entry.pw_name = strdup(_pw_passwd.pw_name); 460 m->namelist = namehead; 461 m->next = _minushead; 462 _minushead = m; 463 } 464 } 465 } 466 endgrent(); 467 endnetgrent(); 468 } 469 470 /* 471 * Free the +@netgroup/-@netgroup caches. Should be called 472 * from endpwent(). We have to blow away both the list of 473 * netgroups and the attached linked lists of usernames. 474 */ 475 static void 476 _freecaches() 477 { 478 struct _pw_cache *p, *m; 479 struct _namelist *n; 480 481 while (_plushead) { 482 while(_plushead->namelist) { 483 n = _plushead->namelist->next; 484 free(_plushead->namelist->name); 485 free(_plushead->namelist); 486 _plushead->namelist = n; 487 } 488 free(_plushead->pw_entry.pw_name); 489 free(_plushead->pw_entry.pw_passwd); 490 free(_plushead->pw_entry.pw_class); 491 free(_plushead->pw_entry.pw_gecos); 492 free(_plushead->pw_entry.pw_dir); 493 free(_plushead->pw_entry.pw_shell); 494 p = _plushead->next; 495 free(_plushead); 496 _plushead = p; 497 } 498 499 while(_minushead) { 500 while(_minushead->namelist) { 501 n = _minushead->namelist->next; 502 free(_minushead->namelist->name); 503 free(_minushead->namelist); 504 _minushead->namelist = n; 505 } 506 m = _minushead->next; 507 free(_minushead); 508 _minushead = m; 509 } 510 _pluscnt = _minuscnt = 0; 511 } 512 513 static int _scancaches(user) 514 char *user; 515 { 516 register struct _pw_cache *m, *p; 517 register struct _namelist *n; 518 519 if (_minuscnt && _minushead) { 520 m = _minushead; 521 while (m) { 522 n = m->namelist; 523 while (n) { 524 if (!strcmp(n->name,user) || *n->name == '\0') 525 return (1); 526 n = n->next; 527 } 528 m = m->next; 529 } 530 } 531 if (_pluscnt && _plushead) { 532 p = _plushead; 533 while (p) { 534 n = p->namelist; 535 while (n) { 536 if (!strcmp(n->name, user) || *n->name == '\0') 537 bcopy((char *)&p->pw_entry, 538 (char *)&_pw_passwd, sizeof(p->pw_entry)); 539 n = n->next; 540 } 541 p = p->next; 542 } 543 } 544 return(0); 545 } 546 547 static int 548 _pw_breakout_yp(struct passwd *pw, char *res, int master) 549 { 550 char *s, *result; 551 static char resbuf[YPMAXRECORD+2]; 552 553 /* 554 * Be triple, ultra super-duper paranoid: reject entries 555 * that start with a + or -. yp_mkdb and /var/yp/Makefile 556 * are _both_ supposed to strip these out, but you never 557 * know. 558 */ 559 if (*res == '+' || *res == '-') 560 return 0; 561 562 /* 563 * The NIS protocol definition limits the size of an NIS 564 * record to YPMAXRECORD bytes. We need to do a copy to 565 * a static buffer here since the memory pointed to by 566 * res will be free()ed when this function returns. 567 */ 568 strncpy((char *)&resbuf, res, YPMAXRECORD); 569 result = (char *)&resbuf; 570 571 /* 572 * XXX Sanity check: make sure all fields are valid (no NULLs). 573 * If we find a badly formatted entry, we punt. 574 */ 575 if ((s = strsep(&result, ":")) == NULL) return 0; /* name */ 576 /* 577 * We don't care what pw_fields says: we _always_ want the 578 * username returned to us by NIS. 579 */ 580 pw->pw_name = s; 581 pw->pw_fields |= _PWF_NAME; 582 583 if ((s = strsep(&result, ":")) == NULL) return 0; /* password */ 584 if(!(pw->pw_fields & _PWF_PASSWD)) { 585 pw->pw_passwd = s; 586 pw->pw_fields |= _PWF_PASSWD; 587 } 588 589 if ((s = strsep(&result, ":")) == NULL) return 0; /* uid */ 590 if(!(pw->pw_fields & _PWF_UID)) { 591 pw->pw_uid = atoi(s); 592 pw->pw_fields |= _PWF_UID; 593 } 594 595 if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */ 596 if(!(pw->pw_fields & _PWF_GID)) { 597 pw->pw_gid = atoi(s); 598 pw->pw_fields |= _PWF_GID; 599 } 600 601 if (master) { 602 if ((s = strsep(&result, ":")) == NULL) return 0; /* class */ 603 if(!(pw->pw_fields & _PWF_CLASS)) { 604 pw->pw_class = s; 605 pw->pw_fields |= _PWF_CLASS; 606 } 607 608 if ((s = strsep(&result, ":")) == NULL) return 0; /* change */ 609 if(!(pw->pw_fields & _PWF_CHANGE)) { 610 pw->pw_change = atol(s); 611 pw->pw_fields |= _PWF_CHANGE; 612 } 613 614 if ((s = strsep(&result, ":")) == NULL) return 0; /* expire */ 615 if(!(pw->pw_fields & _PWF_EXPIRE)) { 616 pw->pw_expire = atol(s); 617 pw->pw_fields |= _PWF_EXPIRE; 618 } 619 } 620 621 if ((s = strsep(&result, ":")) == NULL) return 0; /* gecos */ 622 if(!(pw->pw_fields & _PWF_GECOS)) { 623 pw->pw_gecos = s; 624 pw->pw_fields |= _PWF_GECOS; 625 } 626 627 if ((s = strsep(&result, ":")) == NULL) return 0; /* dir */ 628 if(!(pw->pw_fields & _PWF_DIR)) { 629 pw->pw_dir = s; 630 pw->pw_fields |= _PWF_DIR; 631 } 632 633 if ((s = strsep(&result, ":")) == NULL) return 0; /* shell */ 634 if(!(pw->pw_fields & _PWF_SHELL)) { 635 pw->pw_shell = s; 636 pw->pw_fields |= _PWF_SHELL; 637 } 638 639 /* Be consistent. */ 640 if ((s = strchr(pw->pw_shell, '\n'))) *s = '\0'; 641 642 return 1; 643 } 644 645 static int 646 _havemaster(char *_pw_yp_domain) 647 { 648 int keylen, resultlen; 649 char *key, *result; 650 651 if (yp_first(_pw_yp_domain, "master.passwd.byname", 652 &key, &keylen, &result, &resultlen)) { 653 free(result); 654 return 0; 655 } 656 free(result); 657 return 1; 658 } 659 660 static int 661 _getyppass(struct passwd *pw, const char *name, const char *map) 662 { 663 char *result, *s; 664 int resultlen; 665 int rv; 666 char mastermap[1024]; 667 668 if(!_pw_yp_domain) { 669 if(yp_get_default_domain(&_pw_yp_domain)) 670 return 0; 671 } 672 673 sprintf(mastermap,"%s",map); 674 675 if (_gotmaster) 676 sprintf(mastermap,"master.%s", map); 677 678 if(yp_match(_pw_yp_domain, (char *)&mastermap, name, strlen(name), 679 &result, &resultlen)) 680 return 0; 681 682 s = strchr(result, ':'); 683 if (s) { 684 *s = '\0'; 685 } else { 686 /* Must be a malformed entry if no colons. */ 687 free(result); 688 return(0); 689 } 690 _pw_passwd.pw_fields = -1; /* Impossible value */ 691 if (_scancaches(result)) { 692 free(result); 693 return(0); 694 } 695 /* No hits in the plus or minus lists: Bzzt! reject. */ 696 if (_pw_passwd.pw_fields == -1) { 697 free(result); 698 return(0); 699 } 700 *s = ':'; /* Put back the colon we previously replaced with a NUL. */ 701 rv = _pw_breakout_yp(pw, result, _gotmaster); 702 free(result); 703 return(rv); 704 } 705 706 static int 707 _nextyppass(struct passwd *pw) 708 { 709 static char *key; 710 static int keylen; 711 char *lastkey, *result, *s; 712 int resultlen; 713 int rv; 714 char *map = "passwd.byname"; 715 716 if(!_pw_yp_domain) { 717 if(yp_get_default_domain(&_pw_yp_domain)) 718 return 0; 719 } 720 721 if (_gotmaster) 722 map = "master.passwd.byname"; 723 724 if(!_pw_stepping_yp) { 725 if(key) free(key); 726 rv = yp_first(_pw_yp_domain, map, 727 &key, &keylen, &result, &resultlen); 728 if(rv) { 729 return 0; 730 } 731 _pw_stepping_yp = 1; 732 goto unpack; 733 } else { 734 tryagain: 735 lastkey = key; 736 rv = yp_next(_pw_yp_domain, map, key, keylen, 737 &key, &keylen, &result, &resultlen); 738 free(lastkey); 739 unpack: 740 if(rv) { 741 _pw_stepping_yp = 0; 742 return 0; 743 } 744 745 s = strchr(result, ':'); 746 if (s) { 747 *s = '\0'; 748 } else { 749 /* Must be a malformed entry if no colon. */ 750 free(result); 751 goto tryagain; 752 } 753 _pw_passwd.pw_fields = -1; /* Impossible value */ 754 if (_scancaches(result)) { 755 free(result); 756 goto tryagain; 757 } 758 /* No plus or minus hits: Bzzzt! reject. */ 759 if (_pw_passwd.pw_fields == -1) { 760 free(result); 761 goto tryagain; 762 } 763 *s = ':'; /* Put back colon we previously replaced with a NUL. */ 764 if(s = strchr(result, '\n')) *s = '\0'; 765 if (_pw_breakout_yp(pw, result, _gotmaster)) { 766 free(result); 767 return(1); 768 } else { 769 free(result); 770 goto tryagain; 771 } 772 } 773 } 774 775 #endif /* YP */ 776