getpwent.c revision 15668
119370Spst/* 219370Spst * Copyright (c) 1988, 1993 319370Spst * The Regents of the University of California. All rights reserved. 4130803Smarcel * 5130803Smarcel * Redistribution and use in source and binary forms, with or without 6130803Smarcel * modification, are permitted provided that the following conditions 7130803Smarcel * are met: 8130803Smarcel * 1. Redistributions of source code must retain the above copyright 9130803Smarcel * notice, this list of conditions and the following disclaimer. 10130803Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11130803Smarcel * notice, this list of conditions and the following disclaimer in the 12130803Smarcel * documentation and/or other materials provided with the distribution. 13130803Smarcel * 3. All advertising materials mentioning features or use of this software 14130803Smarcel * must display the following acknowledgement: 15130803Smarcel * This product includes software developed by the University of 16130803Smarcel * California, Berkeley and its contributors. 17130803Smarcel * 4. Neither the name of the University nor the names of its contributors 18130803Smarcel * may be used to endorse or promote products derived from this software 19130803Smarcel * without specific prior written permission. 20130803Smarcel * 21130803Smarcel * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22130803Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23130803Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24130803Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25130803Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26130803Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27130803Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28130803Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29130803Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30130803Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31130803Smarcel * SUCH DAMAGE. 32130803Smarcel */ 33130803Smarcel 34130803Smarcel#if defined(LIBC_SCCS) && !defined(lint) 35130803Smarcelstatic char sccsid[] = "@(#)getpwent.c 8.1 (Berkeley) 6/4/93"; 36130803Smarcel#endif /* LIBC_SCCS and not lint */ 37130803Smarcel 38130803Smarcel#include <stdio.h> 39130803Smarcel#include <sys/param.h> 40130803Smarcel#include <fcntl.h> 41130803Smarcel#include <db.h> 42130803Smarcel#include <syslog.h> 43130803Smarcel#include <pwd.h> 44130803Smarcel#include <utmp.h> 45130803Smarcel#include <errno.h> 46130803Smarcel#include <unistd.h> 47130803Smarcel#include <stdlib.h> 48130803Smarcel#include <string.h> 49130803Smarcel#include <limits.h> 50130803Smarcel#include <grp.h> 51130803Smarcel 52130803Smarcelstatic struct passwd _pw_passwd; /* password structure */ 53130803Smarcelstatic DB *_pw_db; /* password database */ 54130803Smarcelstatic int _pw_keynum; /* key counter */ 55130803Smarcelstatic int _pw_stayopen; /* keep fd's open */ 56130803Smarcel#ifdef YP 57130803Smarcel#include <rpc/rpc.h> 58130803Smarcel#include <rpcsvc/yp_prot.h> 59130803Smarcel#include <rpcsvc/ypclnt.h> 60130803Smarcel 61130803Smarcelstatic struct passwd _pw_copy; 62130803Smarcelstatic DBT empty = { NULL, 0 }; 63130803Smarcelstatic DB *_ypcache = (DB *)NULL; 64130803Smarcelstatic int _yp_exclusions = 0; 65130803Smarcelstatic int _yp_enabled; /* set true when yp enabled */ 66130803Smarcelstatic int _pw_stepping_yp; /* set true when stepping thru map */ 67130803Smarcelstatic char _ypnam[YPMAXRECORD]; 68130803Smarcelstatic int _gotmaster; 69130803Smarcelstatic char *_pw_yp_domain; 70130803Smarcelstatic inline int unwind __P(( char * )); 71130803Smarcelstatic inline void _ypinitdb __P(( void )); 72130803Smarcelstatic int _havemaster __P((char *)); 73130803Smarcelstatic int _getyppass __P((struct passwd *, const char *, const char * )); 74130803Smarcelstatic int _nextyppass __P((struct passwd *)); 75130803Smarcel#endif 76130803Smarcelstatic int __hashpw(), __initdb(); 77130803Smarcel 78130803Smarcelstruct passwd * 79130803Smarcelgetpwent() 80130803Smarcel{ 81130803Smarcel DBT key; 82130803Smarcel char bf[sizeof(_pw_keynum) + 1]; 83130803Smarcel int rv; 84130803Smarcel 85130803Smarcel if (!_pw_db && !__initdb()) 86130803Smarcel return((struct passwd *)NULL); 87130803Smarcel 88130803Smarcel#ifdef YP 89130803Smarcel if(_pw_stepping_yp) { 90130803Smarcel _pw_passwd = _pw_copy; 91130803Smarcel if (unwind((char *)&_ypnam)) 92130803Smarcel return(&_pw_passwd); 93130803Smarcel } 94130803Smarcel#endif 95130803Smarceltryagain: 96130803Smarcel 97130803Smarcel ++_pw_keynum; 98130803Smarcel bf[0] = _PW_KEYBYNUM; 99130803Smarcel bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); 100130803Smarcel key.data = (u_char *)bf; 101130803Smarcel key.size = sizeof(_pw_keynum) + 1; 102130803Smarcel rv = __hashpw(&key); 103130803Smarcel if(!rv) return (struct passwd *)NULL; 104130803Smarcel#ifdef YP 105130803Smarcel if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { 106130803Smarcel bzero((char *)&_ypnam, sizeof(_ypnam)); 107130803Smarcel bcopy(_pw_passwd.pw_name, _ypnam, 108130803Smarcel strlen(_pw_passwd.pw_name)); 109130803Smarcel _pw_copy = _pw_passwd; 110130803Smarcel if (unwind((char *)&_ypnam) == 0) 111130803Smarcel goto tryagain; 112130803Smarcel else 113130803Smarcel return(&_pw_passwd); 114130803Smarcel } 115130803Smarcel#else 116130803Smarcel /* Ignore YP password file entries when YP is disabled. */ 117130803Smarcel if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { 118130803Smarcel goto tryagain; 119130803Smarcel } 120130803Smarcel#endif 121130803Smarcel return(&_pw_passwd); 122130803Smarcel} 123130803Smarcel 124130803Smarcelstruct passwd * 125130803Smarcelgetpwnam(name) 126130803Smarcel const char *name; 127130803Smarcel{ 128130803Smarcel DBT key; 129130803Smarcel int len, rval; 130130803Smarcel char bf[UT_NAMESIZE + 2]; 131130803Smarcel 132130803Smarcel if (!_pw_db && !__initdb()) 133130803Smarcel return((struct passwd *)NULL); 134130803Smarcel 135130803Smarcel bf[0] = _PW_KEYBYNAME; 136130803Smarcel len = strlen(name); 137130803Smarcel bcopy(name, bf + 1, MIN(len, UT_NAMESIZE)); 138130803Smarcel key.data = (u_char *)bf; 139130803Smarcel key.size = len + 1; 140130803Smarcel rval = __hashpw(&key); 141130803Smarcel 142130803Smarcel#ifdef YP 143130803Smarcel if (!rval && _yp_enabled) 144130803Smarcel rval = _getyppass(&_pw_passwd, name, "passwd.byname"); 145130803Smarcel#endif 146130803Smarcel /* 147130803Smarcel * Prevent login attempts when YP is not enabled but YP entries 148130803Smarcel * are in /etc/master.passwd. 149130803Smarcel */ 150130803Smarcel if (rval && (_pw_passwd.pw_name[0] == '+'|| 151130803Smarcel _pw_passwd.pw_name[0] == '-')) rval = 0; 152130803Smarcel 153130803Smarcel endpwent(); 154130803Smarcel return(rval ? &_pw_passwd : (struct passwd *)NULL); 155130803Smarcel} 156130803Smarcel 157130803Smarcelstruct passwd * 158130803Smarcel#ifdef __STDC__ 159130803Smarcelgetpwuid(uid_t uid) 160130803Smarcel#else 161130803Smarcelgetpwuid(uid) 162130803Smarcel int uid; 163130803Smarcel#endif 164130803Smarcel{ 165130803Smarcel DBT key; 166130803Smarcel int keyuid, rval; 167130803Smarcel char bf[sizeof(keyuid) + 1]; 168130803Smarcel 169130803Smarcel if (!_pw_db && !__initdb()) 170130803Smarcel return((struct passwd *)NULL); 171130803Smarcel 172130803Smarcel bf[0] = _PW_KEYBYUID; 173130803Smarcel keyuid = uid; 174130803Smarcel bcopy(&keyuid, bf + 1, sizeof(keyuid)); 175130803Smarcel key.data = (u_char *)bf; 176130803Smarcel key.size = sizeof(keyuid) + 1; 177130803Smarcel rval = __hashpw(&key); 178130803Smarcel 179130803Smarcel#ifdef YP 180130803Smarcel if (!rval && _yp_enabled) { 181130803Smarcel char ypbuf[16]; /* big enough for 32-bit uids and then some */ 182130803Smarcel snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid); 183130803Smarcel rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid"); 184130803Smarcel } 185130803Smarcel#endif 186130803Smarcel /* 187130803Smarcel * Prevent login attempts when YP is not enabled but YP entries 188130803Smarcel * are in /etc/master.passwd. 189130803Smarcel */ 190130803Smarcel if (rval && (_pw_passwd.pw_name[0] == '+'|| 191130803Smarcel _pw_passwd.pw_name[0] == '-')) rval = 0; 192130803Smarcel 193130803Smarcel endpwent(); 194130803Smarcel return(rval ? &_pw_passwd : (struct passwd *)NULL); 195130803Smarcel} 196130803Smarcel 197130803Smarcelint 198130803Smarcelsetpassent(stayopen) 199130803Smarcel int stayopen; 200130803Smarcel{ 201130803Smarcel _pw_keynum = 0; 202130803Smarcel#ifdef YP 203130803Smarcel _pw_stepping_yp = 0; 204130803Smarcel#endif 205130803Smarcel _pw_stayopen = stayopen; 206130803Smarcel return(1); 207130803Smarcel} 208130803Smarcel 209130803Smarcelint 210130803Smarcelsetpwent() 211130803Smarcel{ 212130803Smarcel _pw_keynum = 0; 213130803Smarcel#ifdef YP 214130803Smarcel _pw_stepping_yp = 0; 215130803Smarcel#endif 216130803Smarcel _pw_stayopen = 0; 217130803Smarcel return(1); 218130803Smarcel} 219130803Smarcel 220130803Smarcelvoid 221130803Smarcelendpwent() 222130803Smarcel{ 223130803Smarcel _pw_keynum = 0; 224130803Smarcel#ifdef YP 225130803Smarcel _pw_stepping_yp = 0; 226130803Smarcel#endif 227130803Smarcel if (_pw_db) { 228130803Smarcel (void)(_pw_db->close)(_pw_db); 229130803Smarcel _pw_db = (DB *)NULL; 230130803Smarcel } 231130803Smarcel#ifdef YP 232130803Smarcel if (_ypcache) { 233130803Smarcel (void)(_ypcache->close)(_ypcache); 234130803Smarcel _ypcache = (DB *)NULL; 235130803Smarcel _yp_exclusions = 0; 236130803Smarcel } 237130803Smarcel#endif 238130803Smarcel} 239130803Smarcel 240130803Smarcelstatic 241130803Smarcel__initdb() 242130803Smarcel{ 243130803Smarcel static int warned; 244130803Smarcel char *p; 245130803Smarcel 246130803Smarcel p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB; 247130803Smarcel _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL); 248130803Smarcel if (_pw_db) { 249130803Smarcel#ifdef YP 250130803Smarcel DBT key, data; 251130803Smarcel char buf[] = { _PW_KEYYPENABLED }; 252130803Smarcel key.data = buf; 253130803Smarcel key.size = 1; 254130803Smarcel if ((_pw_db->get)(_pw_db, &key, &data, 0)) { 255130803Smarcel _yp_enabled = 0; 256130803Smarcel } else { 257130803Smarcel _yp_enabled = (int)*((char *)data.data) - 2; 258130803Smarcel /* Don't even bother with this if we aren't root. */ 259130803Smarcel if (!geteuid()) { 260130803Smarcel if (!_pw_yp_domain) 261130803Smarcel if (yp_get_default_domain(&_pw_yp_domain)) 262130803Smarcel return(1); 263130803Smarcel _gotmaster = _havemaster(_pw_yp_domain); 264130803Smarcel } else _gotmaster = 0; 265130803Smarcel if (!_ypcache) 266130803Smarcel _ypinitdb(); 267130803Smarcel } 268130803Smarcel#endif 269130803Smarcel return(1); 270130803Smarcel } 271130803Smarcel if (!warned++) 272130803Smarcel syslog(LOG_ERR, "%s: %m", p); 273130803Smarcel return(0); 274130803Smarcel} 275130803Smarcel 276130803Smarcelstatic 277130803Smarcel__hashpw(key) 278130803Smarcel DBT *key; 279130803Smarcel{ 280130803Smarcel register char *p, *t; 281130803Smarcel static u_int max; 282130803Smarcel static char *line; 283130803Smarcel DBT data; 284130803Smarcel 285130803Smarcel if ((_pw_db->get)(_pw_db, key, &data, 0)) 286130803Smarcel return(0); 287130803Smarcel p = (char *)data.data; 288130803Smarcel if (data.size > max && !(line = realloc(line, max += 1024))) 289130803Smarcel return(0); 290130803Smarcel 291130803Smarcel t = line; 292130803Smarcel#define EXPAND(e) e = t; while (*t++ = *p++); 293130803Smarcel EXPAND(_pw_passwd.pw_name); 294130803Smarcel EXPAND(_pw_passwd.pw_passwd); 295130803Smarcel bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 296130803Smarcel p += sizeof(int); 297130803Smarcel bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 298130803Smarcel p += sizeof(int); 299130803Smarcel bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 300130803Smarcel p += sizeof(time_t); 301130803Smarcel EXPAND(_pw_passwd.pw_class); 302130803Smarcel EXPAND(_pw_passwd.pw_gecos); 303130803Smarcel EXPAND(_pw_passwd.pw_dir); 304130803Smarcel EXPAND(_pw_passwd.pw_shell); 305130803Smarcel bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 306130803Smarcel p += sizeof(time_t); 307130803Smarcel bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields); 308130803Smarcel p += sizeof _pw_passwd.pw_fields; 309130803Smarcel return(1); 310130803Smarcel} 311130803Smarcel 312130803Smarcel#ifdef YP 313130803Smarcel 314130803Smarcel/* 315130803Smarcel * Create a DB hash database in memory. Bet you didn't know you 316130803Smarcel * could do a dbopen() will a NULL filename, did you. 317130803Smarcel */ 318130803Smarcelstatic inline void _ypinitdb() 319130803Smarcel{ 320130803Smarcel if (_ypcache == (DB *)NULL) 321130803Smarcel _ypcache = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL); 322130803Smarcel return; 323130803Smarcel} 324130803Smarcel 325130803Smarcel/* 326130803Smarcel * See if a user is in the blackballed list. 327130803Smarcel */ 328130803Smarcelstatic inline int lookup(name) 329130803Smarcel char *name; 330130803Smarcel{ 331130803Smarcel DBT key; 332130803Smarcel 333130803Smarcel if (!_yp_exclusions) 334130803Smarcel return(0); 335130803Smarcel 336130803Smarcel key.data = name; 337130803Smarcel key.size = strlen(name); 338130803Smarcel 339130803Smarcel if ((_ypcache->get)(_ypcache, &key, &empty, 0)) { 340130803Smarcel return(0); 341130803Smarcel } 342130803Smarcel 343130803Smarcel return(1); 344130803Smarcel} 345130803Smarcel 346130803Smarcel/* 347130803Smarcel * Store a blackballed user in an in-core hash database. 348130803Smarcel */ 349130803Smarcelstatic inline void store(key) 350130803Smarcel char *key; 351130803Smarcel{ 352130803Smarcel DBT lkey; 353130803Smarcel/* 354130803Smarcel if (lookup(key)) 355130803Smarcel return; 356130803Smarcel*/ 357130803Smarcel 358130803Smarcel _yp_exclusions = 1; 359130803Smarcel 360130803Smarcel lkey.data = key; 361130803Smarcel lkey.size = strlen(key); 362130803Smarcel 363130803Smarcel (void)(_ypcache->put)(_ypcache, &lkey, &empty, R_NOOVERWRITE); 364130803Smarcel} 365130803Smarcel 366130803Smarcel/* 367130803Smarcel * Parse the + entries in the password database and do appropriate 368130803Smarcel * NIS lookups. While ugly to look at, this is optimized to do only 369130803Smarcel * as many lookups as are absolutely necessary in any given case. 370130803Smarcel * Basically, the getpwent() function will feed us + and - lines 371130803Smarcel * as they appear in the database. For + lines, we do netgroup/group 372130803Smarcel * and user lookups to find all usernames that match the rule and 373130803Smarcel * extract them from the NIS passwd maps. For - lines, we save the 374130803Smarcel * matching names in a database and a) exlude them, and b) make sure 375130803Smarcel * we don't consider them when processing other + lines that appear 376130803Smarcel * later. 377130803Smarcel */ 378130803Smarcelstatic inline int unwind(grp) 379130803Smarcel char *grp; 380130803Smarcel{ 381130803Smarcel char *user, *host, *domain; 382130803Smarcel static int latch = 0; 383130803Smarcel static struct group *gr = NULL; 384130803Smarcel int rv = 0; 385130803Smarcel 386130803Smarcel if (grp[0] == '+') { 387130803Smarcel if (strlen(grp) == 1) { 388130803Smarcel return(_nextyppass(&_pw_passwd)); 389130803Smarcel } 390130803Smarcel if (grp[1] == '@') { 391130803Smarcel _pw_stepping_yp = 1; 392130803Smarcelgrpagain: 393130803Smarcel if (gr != NULL) { 394130803Smarcel if (*gr->gr_mem != NULL) { 395130803Smarcel if (lookup(*gr->gr_mem)) { 396130803Smarcel gr->gr_mem++; 397130803Smarcel goto grpagain; 398130803Smarcel } 399130803Smarcel rv = _getyppass(&_pw_passwd, 400130803Smarcel *gr->gr_mem, 401130803Smarcel "passwd.byname"); 402130803Smarcel gr->gr_mem++; 403130803Smarcel return(rv); 404130803Smarcel } else { 405130803Smarcel endgrent(); 406130803Smarcel latch = 0; 407130803Smarcel gr = NULL; 408130803Smarcel return(0); 409130803Smarcel } 410130803Smarcel } 411130803Smarcel if (!latch) { 412130803Smarcel setnetgrent(grp+2); 413130803Smarcel latch++; 414130803Smarcel } 415130803Smarcelagain: 416130803Smarcel if (getnetgrent(&host, &user, &domain) == NULL) { 417130803Smarcel if ((gr = getgrnam(grp+2)) != NULL) 418130803Smarcel goto grpagain; 419130803Smarcel latch = 0; 420130803Smarcel _pw_stepping_yp = 0; 421130803Smarcel return(0); 422130803Smarcel } else { 423130803Smarcel if (lookup(user)) 424130803Smarcel goto again; 425130803Smarcel if (_getyppass(&_pw_passwd, user, 426130803Smarcel "passwd.byname")) 427130803Smarcel return(1); 428130803Smarcel else 429130803Smarcel goto again; 430130803Smarcel } 431130803Smarcel } else { 432130803Smarcel if (lookup(grp+1)) 433130803Smarcel return(0); 434130803Smarcel return(_getyppass(&_pw_passwd, grp+1, "passwd.byname")); 435130803Smarcel } 436130803Smarcel } else { 437104990Smp if (grp[1] == '@') { 43898944Sobrien setnetgrent(grp+2); 43998944Sobrien rv = 0; 44098944Sobrien while(getnetgrent(&host, &user, &domain) != NULL) { 44198944Sobrien store(user); 44298944Sobrien rv++; 44398944Sobrien } 44498944Sobrien if (!rv && (gr = getgrnam(grp+2)) != NULL) { 44598944Sobrien while(gr->gr_mem) { 44698944Sobrien store(gr->gr_mem); 44798944Sobrien gr->gr_mem++; 44898944Sobrien } 44998944Sobrien } 45098944Sobrien } else { 45198944Sobrien store(grp+1); 45298944Sobrien } 453104990Smp } 454104990Smp return(0); 455104990Smp} 456104990Smp 457104990Smp/* 458104990Smp * See if a user is a member of a particular group. 459104990Smp */ 460104990Smpstatic inline int ingr(grp, name) 46198944Sobrien char *grp; 46298944Sobrien char *name; 46398944Sobrien{ 46498944Sobrien register struct group *gr; 46598944Sobrien 46698944Sobrien if ((gr = getgrnam(grp)) == NULL) 46798944Sobrien return(0); 46898944Sobrien 46998944Sobrien while(*gr->gr_mem) { 47098944Sobrien if (!strcmp(*gr->gr_mem, name)) { 47198944Sobrien endgrent(); 47298944Sobrien return(1); 47398944Sobrien } 47498944Sobrien gr->gr_mem++; 47598944Sobrien } 47698944Sobrien 47798944Sobrien endgrent(); 47898944Sobrien return(0); 47998944Sobrien} 48098944Sobrien 48198944Sobrien/* 48298944Sobrien * Check a user against the +@netgroup/-@netgroup lines listed in 48398944Sobrien * the local password database. Also checks +user/-user lines. 48498944Sobrien * If no netgroup exists that matches +@netgroup/-@netgroup, 48598944Sobrien * try searching regular groups with the same name. 48698944Sobrien */ 48798944Sobrienstatic inline int verf(name) 48898944Sobrien char *name; 48998944Sobrien{ 49098944Sobrien DBT key; 49198944Sobrien char bf[sizeof(_pw_keynum) + 1]; 49298944Sobrien int keynum = 0; 49398944Sobrien 49498944Sobrienagain: 49598944Sobrien ++keynum; 49698944Sobrien bf[0] = _PW_KEYYPBYNUM; 49798944Sobrien bcopy((char *)&keynum, bf + 1, sizeof(keynum)); 49898944Sobrien key.data = (u_char *)bf; 49998944Sobrien key.size = sizeof(keynum) + 1; 50098944Sobrien if (!__hashpw(&key)) { 50198944Sobrien /* Try again using old format */ 50298944Sobrien bf[0] = _PW_KEYBYNUM; 50398944Sobrien bcopy((char *)&keynum, bf + 1, sizeof(keynum)); 50498944Sobrien key.data = (u_char *)bf; 50598944Sobrien if (!__hashpw(&key)) 50698944Sobrien return(0); 50798944Sobrien } 50898944Sobrien if (_pw_passwd.pw_name[0] != '+' && (_pw_passwd.pw_name[0] != '-')) 50998944Sobrien goto again; 51098944Sobrien if (_pw_passwd.pw_name[0] == '+') { 51198944Sobrien if (strlen(_pw_passwd.pw_name) == 1) /* Wildcard */ 51298944Sobrien return(1); 51398944Sobrien if (_pw_passwd.pw_name[1] == '@') { 51498944Sobrien if ((innetgr(_pw_passwd.pw_name+2, NULL, name, 51598944Sobrien _pw_yp_domain) || 51698944Sobrien ingr(_pw_passwd.pw_name+2, name)) && !lookup(name)) 51798944Sobrien return(1); 51898944Sobrien else 51998944Sobrien goto again; 52098944Sobrien } else { 52198944Sobrien if (!strcmp(name, _pw_passwd.pw_name+1) && 52298944Sobrien !lookup(name)) 52398944Sobrien return(1); 52498944Sobrien else 52598944Sobrien goto again; 52698944Sobrien } 52798944Sobrien } 52898944Sobrien if (_pw_passwd.pw_name[0] == '-') { 52998944Sobrien /* Note that a minus wildcard is a no-op. */ 53098944Sobrien if (_pw_passwd.pw_name[1] == '@') { 53198944Sobrien if (innetgr(_pw_passwd.pw_name+2, NULL, name, 53298944Sobrien _pw_yp_domain) || 53398944Sobrien ingr(_pw_passwd.pw_name+2, name)) { 53498944Sobrien store(name); 53598944Sobrien return(0); 53698944Sobrien } else 53798944Sobrien goto again; 53898944Sobrien } else { 53998944Sobrien if (!strcmp(name, _pw_passwd.pw_name+1)) { 54098944Sobrien store(name); 54198944Sobrien return(0); 54298944Sobrien } else 54398944Sobrien goto again; 54498944Sobrien } 54598944Sobrien 54698944Sobrien } 54798944Sobrien return(0); 54898944Sobrien} 54998944Sobrien 55098944Sobrienstatic int 55198944Sobrien_pw_breakout_yp(struct passwd *pw, char *res, int master) 55298944Sobrien{ 55398944Sobrien char *s, *result; 55498944Sobrien static char resbuf[YPMAXRECORD+2]; 55598944Sobrien 55698944Sobrien /* 55798944Sobrien * Be triple, ultra super-duper paranoid: reject entries 55898944Sobrien * that start with a + or -. yp_mkdb and /var/yp/Makefile 55998944Sobrien * are _both_ supposed to strip these out, but you never 56098944Sobrien * know. 56198944Sobrien */ 56298944Sobrien if (*res == '+' || *res == '-') 56398944Sobrien return 0; 56498944Sobrien 56598944Sobrien /* 56698944Sobrien * The NIS protocol definition limits the size of an NIS 56798944Sobrien * record to YPMAXRECORD bytes. We need to do a copy to 56898944Sobrien * a static buffer here since the memory pointed to by 56998944Sobrien * res will be free()ed when this function returns. 57098944Sobrien */ 57198944Sobrien strncpy((char *)&resbuf, res, YPMAXRECORD); 57298944Sobrien result = (char *)&resbuf; 57398944Sobrien 57498944Sobrien /* 57598944Sobrien * XXX Sanity check: make sure all fields are valid (no NULLs). 57698944Sobrien * If we find a badly formatted entry, we punt. 57798944Sobrien */ 57898944Sobrien if ((s = strsep(&result, ":")) == NULL) return 0; /* name */ 57998944Sobrien /* 58098944Sobrien * We don't care what pw_fields says: we _always_ want the 58198944Sobrien * username returned to us by NIS. 58298944Sobrien */ 58398944Sobrien pw->pw_name = s; 58498944Sobrien pw->pw_fields |= _PWF_NAME; 58598944Sobrien 58698944Sobrien if ((s = strsep(&result, ":")) == NULL) return 0; /* password */ 58798944Sobrien if(!(pw->pw_fields & _PWF_PASSWD)) { 58898944Sobrien pw->pw_passwd = s; 58998944Sobrien pw->pw_fields |= _PWF_PASSWD; 59098944Sobrien } 59198944Sobrien 59298944Sobrien if ((s = strsep(&result, ":")) == NULL) return 0; /* uid */ 59398944Sobrien if(!(pw->pw_fields & _PWF_UID)) { 59498944Sobrien pw->pw_uid = atoi(s); 59598944Sobrien pw->pw_fields |= _PWF_UID; 59698944Sobrien } 59798944Sobrien 59898944Sobrien if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */ 59998944Sobrien if(!(pw->pw_fields & _PWF_GID)) { 60098944Sobrien pw->pw_gid = atoi(s); 60198944Sobrien pw->pw_fields |= _PWF_GID; 60298944Sobrien } 60398944Sobrien 60498944Sobrien if (master) { 60598944Sobrien if ((s = strsep(&result, ":")) == NULL) return 0; /* class */ 60698944Sobrien if(!(pw->pw_fields & _PWF_CLASS)) { 60798944Sobrien pw->pw_class = s; 60898944Sobrien pw->pw_fields |= _PWF_CLASS; 60998944Sobrien } 61098944Sobrien 61198944Sobrien if ((s = strsep(&result, ":")) == NULL) return 0; /* change */ 61298944Sobrien if(!(pw->pw_fields & _PWF_CHANGE)) { 61398944Sobrien pw->pw_change = atol(s); 61498944Sobrien pw->pw_fields |= _PWF_CHANGE; 61598944Sobrien } 61698944Sobrien 61798944Sobrien if ((s = strsep(&result, ":")) == NULL) return 0; /* expire */ 61898944Sobrien if(!(pw->pw_fields & _PWF_EXPIRE)) { 61998944Sobrien pw->pw_expire = atol(s); 62098944Sobrien pw->pw_fields |= _PWF_EXPIRE; 62198944Sobrien } 62298944Sobrien } 62398944Sobrien 62498944Sobrien if ((s = strsep(&result, ":")) == NULL) return 0; /* gecos */ 62598944Sobrien if(!(pw->pw_fields & _PWF_GECOS)) { 62698944Sobrien pw->pw_gecos = s; 62798944Sobrien pw->pw_fields |= _PWF_GECOS; 62898944Sobrien } 62998944Sobrien 63098944Sobrien if ((s = strsep(&result, ":")) == NULL) return 0; /* dir */ 63198944Sobrien if(!(pw->pw_fields & _PWF_DIR)) { 63298944Sobrien pw->pw_dir = s; 63398944Sobrien pw->pw_fields |= _PWF_DIR; 63498944Sobrien } 63598944Sobrien 63698944Sobrien if ((s = strsep(&result, ":")) == NULL) return 0; /* shell */ 63798944Sobrien if(!(pw->pw_fields & _PWF_SHELL)) { 63898944Sobrien pw->pw_shell = s; 63998944Sobrien pw->pw_fields |= _PWF_SHELL; 64098944Sobrien } 64198944Sobrien 64298944Sobrien /* Be consistent. */ 64398944Sobrien if ((s = strchr(pw->pw_shell, '\n'))) *s = '\0'; 64498944Sobrien 64598944Sobrien return 1; 64698944Sobrien} 64798944Sobrien 64898944Sobrienstatic int 64998944Sobrien_havemaster(char *_pw_yp_domain) 65098944Sobrien{ 65198944Sobrien int keylen, resultlen; 65298944Sobrien char *key, *result; 65398944Sobrien 65498944Sobrien if (yp_first(_pw_yp_domain, "master.passwd.byname", 65598944Sobrien &key, &keylen, &result, &resultlen)) { 65698944Sobrien return 0; 65798944Sobrien } 65898944Sobrien free(result); 65998944Sobrien return 1; 66098944Sobrien} 66198944Sobrien 66298944Sobrienstatic int 66398944Sobrien_getyppass(struct passwd *pw, const char *name, const char *map) 66498944Sobrien{ 66598944Sobrien char *result, *s; 66698944Sobrien int resultlen; 66798944Sobrien int rv; 66898944Sobrien char mastermap[YPMAXRECORD]; 66998944Sobrien 67098944Sobrien if(!_pw_yp_domain) { 67198944Sobrien if(yp_get_default_domain(&_pw_yp_domain)) 67298944Sobrien return 0; 67398944Sobrien } 67498944Sobrien 67598944Sobrien sprintf(mastermap,"%s",map); 67698944Sobrien 67798944Sobrien if (_gotmaster) 67898944Sobrien sprintf(mastermap,"master.%s", map); 67998944Sobrien 68098944Sobrien if(yp_match(_pw_yp_domain, (char *)&mastermap, name, strlen(name), 68198944Sobrien &result, &resultlen)) 68298944Sobrien return 0; 68398944Sobrien 68498944Sobrien if (!_pw_stepping_yp) { 68598944Sobrien s = strchr(result, ':'); 68698944Sobrien if (s) { 68798944Sobrien *s = '\0'; 68898944Sobrien } else { 68998944Sobrien /* Must be a malformed entry if no colons. */ 69098944Sobrien free(result); 69198944Sobrien return(0); 69298944Sobrien } 69398944Sobrien 69498944Sobrien if (!verf(result)) { 69598944Sobrien *s = ':'; 69698944Sobrien free(result); 69798944Sobrien return(0); 69898944Sobrien } 69998944Sobrien 70098944Sobrien *s = ':'; /* Put back the colon we previously replaced with a NUL. */ 70198944Sobrien } 70298944Sobrien 70398944Sobrien rv = _pw_breakout_yp(pw, result, _gotmaster); 70498944Sobrien free(result); 70598944Sobrien return(rv); 70698944Sobrien} 70798944Sobrien 70898944Sobrienstatic int 70998944Sobrien_nextyppass(struct passwd *pw) 71098944Sobrien{ 71198944Sobrien static char *key; 71298944Sobrien static int keylen; 71398944Sobrien char *lastkey, *result, *s; 71498944Sobrien int resultlen; 71598944Sobrien int rv; 71698944Sobrien char *map = "passwd.byname"; 71798944Sobrien 71898944Sobrien if(!_pw_yp_domain) { 71998944Sobrien if(yp_get_default_domain(&_pw_yp_domain)) 72098944Sobrien return 0; 72198944Sobrien } 72298944Sobrien 72398944Sobrien if (_gotmaster) 72498944Sobrien map = "master.passwd.byname"; 72598944Sobrien 72698944Sobrien if(!_pw_stepping_yp) { 72798944Sobrien if(key) free(key); 72898944Sobrien rv = yp_first(_pw_yp_domain, map, 72998944Sobrien &key, &keylen, &result, &resultlen); 73098944Sobrien if(rv) { 73198944Sobrien return 0; 73298944Sobrien } 73398944Sobrien _pw_stepping_yp = 1; 73498944Sobrien goto unpack; 73598944Sobrien } else { 73698944Sobrientryagain: 73798944Sobrien lastkey = key; 73898944Sobrien rv = yp_next(_pw_yp_domain, map, key, keylen, 73998944Sobrien &key, &keylen, &result, &resultlen); 74098944Sobrien free(lastkey); 74198944Sobrienunpack: 74298944Sobrien if(rv) { 74398944Sobrien _pw_stepping_yp = 0; 74498944Sobrien return 0; 74598944Sobrien } 74698944Sobrien 74798944Sobrien s = strchr(result, ':'); 74898944Sobrien if (s) { 74998944Sobrien *s = '\0'; 75098944Sobrien } else { 75198944Sobrien /* Must be a malformed entry if no colons. */ 75298944Sobrien free(result); 75398944Sobrien goto tryagain; 75498944Sobrien } 75598944Sobrien 75698944Sobrien if (lookup(result)) { 75798944Sobrien *s = ':'; 75898944Sobrien free(result); 75998944Sobrien goto tryagain; 76098944Sobrien } 76198944Sobrien 76298944Sobrien *s = ':'; /* Put back the colon we previously replaced with a NUL. */ 76398944Sobrien if (_pw_breakout_yp(pw, result, _gotmaster)) { 76498944Sobrien free(result); 76598944Sobrien return(1); 76698944Sobrien } else { 76798944Sobrien free(result); 76898944Sobrien goto tryagain; 76998944Sobrien } 77098944Sobrien } 77198944Sobrien} 77298944Sobrien 77398944Sobrien#endif /* YP */ 77498944Sobrien