getpwent.c revision 41898
1194679Snwhitehorn/* 2194679Snwhitehorn * Copyright (c) 1988, 1993 3194679Snwhitehorn * The Regents of the University of California. All rights reserved. 4194679Snwhitehorn * 5194679Snwhitehorn * Redistribution and use in source and binary forms, with or without 6194679Snwhitehorn * modification, are permitted provided that the following conditions 7194679Snwhitehorn * are met: 8194679Snwhitehorn * 1. Redistributions of source code must retain the above copyright 9194679Snwhitehorn * notice, this list of conditions and the following disclaimer. 10194679Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 11194679Snwhitehorn * notice, this list of conditions and the following disclaimer in the 12194679Snwhitehorn * documentation and/or other materials provided with the distribution. 13194679Snwhitehorn * 3. All advertising materials mentioning features or use of this software 14194679Snwhitehorn * must display the following acknowledgement: 15194679Snwhitehorn * This product includes software developed by the University of 16194679Snwhitehorn * California, Berkeley and its contributors. 17194679Snwhitehorn * 4. Neither the name of the University nor the names of its contributors 18194679Snwhitehorn * may be used to endorse or promote products derived from this software 19194679Snwhitehorn * without specific prior written permission. 20194679Snwhitehorn * 21194679Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22194679Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23194679Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24194679Snwhitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25194679Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26194679Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27194679Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28194679Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29194679Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30194679Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31194679Snwhitehorn * SUCH DAMAGE. 32194679Snwhitehorn */ 33194679Snwhitehorn 34194679Snwhitehorn#if defined(LIBC_SCCS) && !defined(lint) 35194679Snwhitehornstatic char sccsid[] = "@(#)getpwent.c 8.2 (Berkeley) 4/27/95"; 36194679Snwhitehorn#endif /* LIBC_SCCS and not lint */ 37204082Snwhitehorn 38194679Snwhitehorn#include <stdio.h> 39194679Snwhitehorn#include <sys/param.h> 40194679Snwhitehorn#include <fcntl.h> 41194679Snwhitehorn#include <db.h> 42194679Snwhitehorn#include <syslog.h> 43194679Snwhitehorn#include <pwd.h> 44194679Snwhitehorn#include <utmp.h> 45194679Snwhitehorn#include <errno.h> 46194679Snwhitehorn#include <unistd.h> 47194679Snwhitehorn#include <stdlib.h> 48194679Snwhitehorn#include <string.h> 49194679Snwhitehorn#include <limits.h> 50204082Snwhitehorn#include <grp.h> 51194679Snwhitehorn 52194679Snwhitehornextern void setnetgrent __P(( char * )); 53194679Snwhitehornextern int getnetgrent __P(( char **, char **, char ** )); 54194679Snwhitehornextern int innetgr __P(( const char *, const char *, const char *, const char * )); 55204082Snwhitehorn 56204082Snwhitehorn/* 57204082Snwhitehorn * The lookup techniques and data extraction code here must be kept 58204082Snwhitehorn * in sync with that in `pwd_mkdb'. 59204082Snwhitehorn */ 60204082Snwhitehorn 61204082Snwhitehornstatic struct passwd _pw_passwd; /* password structure */ 62204082Snwhitehornstatic DB *_pw_db; /* password database */ 63204082Snwhitehornstatic int _pw_keynum; /* key counter */ 64204082Snwhitehornstatic int _pw_stayopen; /* keep fd's open */ 65204082Snwhitehorn#ifdef YP 66204082Snwhitehorn#include <rpc/rpc.h> 67204082Snwhitehorn#include <rpcsvc/yp_prot.h> 68204082Snwhitehorn#include <rpcsvc/ypclnt.h> 69204082Snwhitehorn 70204082Snwhitehornstatic struct passwd _pw_copy; 71204082Snwhitehornstatic DBT empty = { NULL, 0 }; 72204082Snwhitehornstatic DB *_ypcache = (DB *)NULL; 73204082Snwhitehornstatic int _yp_exclusions = 0; 74194679Snwhitehornstatic int _yp_enabled = -1; 75194679Snwhitehornstatic int _pw_stepping_yp; /* set true when stepping thru map */ 76194679Snwhitehornstatic char _ypnam[YPMAXRECORD]; 77194679Snwhitehorn#define YP_HAVE_MASTER 2 78194679Snwhitehorn#define YP_HAVE_ADJUNCT 1 79194679Snwhitehorn#define YP_HAVE_NONE 0 80194679Snwhitehornstatic int _gotmaster; 81194679Snwhitehornstatic char *_pw_yp_domain; 82194679Snwhitehornstatic inline int unwind __P(( char * )); 83194679Snwhitehornstatic void _ypinitdb __P(( void )); 84194679Snwhitehornstatic int _havemaster __P((char *)); 85194679Snwhitehornstatic int _getyppass __P((struct passwd *, const char *, const char * )); 86194679Snwhitehornstatic int _nextyppass __P((struct passwd *)); 87194679Snwhitehornstatic inline int lookup __P((const char *)); 88204082Snwhitehornstatic inline void store __P((const char *)); 89204082Snwhitehornstatic inline int ingr __P((const char *, const char*)); 90204082Snwhitehornstatic inline int verf __P((const char *)); 91204082Snwhitehornstatic char * _get_adjunct_pw __P((const char *)); 92204082Snwhitehorn#endif 93204082Snwhitehornstatic int __hashpw(DBT *); 94204082Snwhitehornstatic int __initdb(void); 95204082Snwhitehorn 96204082Snwhitehornstruct passwd * 97204082Snwhitehorngetpwent() 98204082Snwhitehorn{ 99204082Snwhitehorn DBT key; 100204082Snwhitehorn char bf[sizeof(_pw_keynum) + 1]; 101204082Snwhitehorn int rv; 102204082Snwhitehorn 103204082Snwhitehorn if (!_pw_db && !__initdb()) 104204082Snwhitehorn return((struct passwd *)NULL); 105194679Snwhitehorn 106194679Snwhitehorn#ifdef YP 107194679Snwhitehorn if(_pw_stepping_yp) { 108194679Snwhitehorn _pw_passwd = _pw_copy; 109194679Snwhitehorn if (unwind((char *)&_ypnam)) 110194679Snwhitehorn return(&_pw_passwd); 111194679Snwhitehorn } 112194679Snwhitehorn#endif 113194679Snwhitehorntryagain: 114194679Snwhitehorn 115194679Snwhitehorn ++_pw_keynum; 116194679Snwhitehorn bf[0] = _PW_KEYBYNUM; 117204082Snwhitehorn bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); 118204082Snwhitehorn key.data = (u_char *)bf; 119204082Snwhitehorn key.size = sizeof(_pw_keynum) + 1; 120204082Snwhitehorn rv = __hashpw(&key); 121204082Snwhitehorn if(!rv) return (struct passwd *)NULL; 122204082Snwhitehorn#ifdef YP 123194679Snwhitehorn if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { 124194679Snwhitehorn if (_yp_enabled == -1) 125194679Snwhitehorn _ypinitdb(); 126194679Snwhitehorn bzero((char *)&_ypnam, sizeof(_ypnam)); 127194679Snwhitehorn bcopy(_pw_passwd.pw_name, _ypnam, 128194679Snwhitehorn strlen(_pw_passwd.pw_name)); 129194679Snwhitehorn _pw_copy = _pw_passwd; 130194679Snwhitehorn if (unwind((char *)&_ypnam) == 0) 131194679Snwhitehorn goto tryagain; 132194679Snwhitehorn else 133194679Snwhitehorn return(&_pw_passwd); 134194679Snwhitehorn } 135194679Snwhitehorn#else 136194679Snwhitehorn /* Ignore YP password file entries when YP is disabled. */ 137194679Snwhitehorn if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { 138194679Snwhitehorn goto tryagain; 139194679Snwhitehorn } 140194679Snwhitehorn#endif 141194679Snwhitehorn return(&_pw_passwd); 142194679Snwhitehorn} 143204082Snwhitehorn 144194679Snwhitehornstruct passwd * 145204082Snwhitehorngetpwnam(name) 146194679Snwhitehorn const char *name; 147194679Snwhitehorn{ 148204082Snwhitehorn DBT key; 149204082Snwhitehorn int len, rval; 150204082Snwhitehorn char bf[UT_NAMESIZE + 2]; 151204082Snwhitehorn 152204082Snwhitehorn if (!_pw_db && !__initdb()) 153204082Snwhitehorn return((struct passwd *)NULL); 154204082Snwhitehorn 155204082Snwhitehorn bf[0] = _PW_KEYBYNAME; 156204082Snwhitehorn len = strlen(name); 157194679Snwhitehorn if (len > UT_NAMESIZE) 158204082Snwhitehorn return(NULL); 159204082Snwhitehorn bcopy(name, bf + 1, len); 160204082Snwhitehorn key.data = (u_char *)bf; 161204082Snwhitehorn key.size = len + 1; 162204082Snwhitehorn rval = __hashpw(&key); 163204082Snwhitehorn 164204082Snwhitehorn#ifdef YP 165204082Snwhitehorn if (!rval) { 166204082Snwhitehorn if (_yp_enabled == -1) 167204082Snwhitehorn _ypinitdb(); 168204082Snwhitehorn if (_yp_enabled) 169194679Snwhitehorn rval = _getyppass(&_pw_passwd, name, "passwd.byname"); 170194679Snwhitehorn } 171194679Snwhitehorn#endif 172194679Snwhitehorn /* 173194679Snwhitehorn * Prevent login attempts when YP is not enabled but YP entries 174194679Snwhitehorn * are in /etc/master.passwd. 175194679Snwhitehorn */ 176194679Snwhitehorn if (rval && (_pw_passwd.pw_name[0] == '+'|| 177194679Snwhitehorn _pw_passwd.pw_name[0] == '-')) rval = 0; 178194679Snwhitehorn 179194679Snwhitehorn endpwent(); 180194679Snwhitehorn return(rval ? &_pw_passwd : (struct passwd *)NULL); 181194679Snwhitehorn} 182194679Snwhitehorn 183194679Snwhitehornstruct passwd * 184194679Snwhitehorngetpwuid(uid) 185194679Snwhitehorn uid_t uid; 186194679Snwhitehorn{ 187194679Snwhitehorn DBT key; 188194679Snwhitehorn int keyuid, rval; 189194679Snwhitehorn char bf[sizeof(keyuid) + 1]; 190194679Snwhitehorn 191194679Snwhitehorn if (!_pw_db && !__initdb()) 192194679Snwhitehorn return((struct passwd *)NULL); 193204082Snwhitehorn 194204082Snwhitehorn bf[0] = _PW_KEYBYUID; 195194679Snwhitehorn keyuid = uid; 196194679Snwhitehorn bcopy(&keyuid, bf + 1, sizeof(keyuid)); 197194679Snwhitehorn key.data = (u_char *)bf; 198194679Snwhitehorn key.size = sizeof(keyuid) + 1; 199194679Snwhitehorn rval = __hashpw(&key); 200194679Snwhitehorn 201194679Snwhitehorn#ifdef YP 202194679Snwhitehorn if (!rval) { 203194679Snwhitehorn if (_yp_enabled == -1) 204194679Snwhitehorn _ypinitdb(); 205194679Snwhitehorn if (_yp_enabled) { 206194679Snwhitehorn char ypbuf[16]; /* big enough for 32-bit uids */ 207204082Snwhitehorn snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid); 208194679Snwhitehorn rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid"); 209194679Snwhitehorn } 210194679Snwhitehorn } 211194679Snwhitehorn#endif 212194679Snwhitehorn /* 213194679Snwhitehorn * Prevent login attempts when YP is not enabled but YP entries 214194679Snwhitehorn * are in /etc/master.passwd. 215194679Snwhitehorn */ 216194679Snwhitehorn if (rval && (_pw_passwd.pw_name[0] == '+'|| 217194679Snwhitehorn _pw_passwd.pw_name[0] == '-')) rval = 0; 218194679Snwhitehorn 219194679Snwhitehorn endpwent(); 220194679Snwhitehorn return(rval ? &_pw_passwd : (struct passwd *)NULL); 221194679Snwhitehorn} 222194679Snwhitehorn 223194679Snwhitehornint 224194679Snwhitehornsetpassent(stayopen) 225194679Snwhitehorn int stayopen; 226194679Snwhitehorn{ 227204082Snwhitehorn _pw_keynum = 0; 228204082Snwhitehorn#ifdef YP 229204082Snwhitehorn _pw_stepping_yp = 0; 230204082Snwhitehorn#endif 231204082Snwhitehorn _pw_stayopen = stayopen; 232204082Snwhitehorn return(1); 233204082Snwhitehorn} 234204082Snwhitehorn 235204082Snwhitehornvoid 236204082Snwhitehornsetpwent() 237204082Snwhitehorn{ 238204082Snwhitehorn (void)setpassent(0); 239204082Snwhitehorn} 240204082Snwhitehorn 241204082Snwhitehornvoid 242204082Snwhitehornendpwent() 243204082Snwhitehorn{ 244204082Snwhitehorn _pw_keynum = 0; 245204082Snwhitehorn#ifdef YP 246204082Snwhitehorn _pw_stepping_yp = 0; 247204082Snwhitehorn#endif 248204082Snwhitehorn if (_pw_db) { 249204082Snwhitehorn (void)(_pw_db->close)(_pw_db); 250204082Snwhitehorn _pw_db = (DB *)NULL; 251204082Snwhitehorn } 252204082Snwhitehorn#ifdef YP 253204082Snwhitehorn if (_ypcache) { 254204082Snwhitehorn (void)(_ypcache->close)(_ypcache); 255204082Snwhitehorn _ypcache = (DB *)NULL; 256204082Snwhitehorn _yp_exclusions = 0; 257204082Snwhitehorn } 258204082Snwhitehorn#endif 259204082Snwhitehorn} 260204082Snwhitehorn 261194679Snwhitehornstatic int 262194679Snwhitehorn__initdb() 263194679Snwhitehorn{ 264194679Snwhitehorn static int warned; 265194679Snwhitehorn char *p; 266194679Snwhitehorn 267194679Snwhitehorn p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB; 268204082Snwhitehorn _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL); 269194679Snwhitehorn if (_pw_db) 270194679Snwhitehorn return(1); 271194679Snwhitehorn if (!warned++) 272194679Snwhitehorn syslog(LOG_ERR, "%s: %m", p); 273194679Snwhitehorn return(0); 274204082Snwhitehorn} 275204082Snwhitehorn 276204082Snwhitehornstatic int 277194679Snwhitehorn__hashpw(key) 278194679Snwhitehorn DBT *key; 279194679Snwhitehorn{ 280194679Snwhitehorn register char *p, *t; 281194679Snwhitehorn static u_int max; 282204082Snwhitehorn static char *line; 283204082Snwhitehorn DBT data; 284194679Snwhitehorn 285194679Snwhitehorn if ((_pw_db->get)(_pw_db, key, &data, 0)) 286194679Snwhitehorn return(0); 287194679Snwhitehorn p = (char *)data.data; 288194679Snwhitehorn 289194679Snwhitehorn /* Increase buffer size for long lines if necessary. */ 290194679Snwhitehorn if (data.size > max) { 291194679Snwhitehorn max = data.size + 1024; 292194679Snwhitehorn if (!(line = reallocf(line, max))) 293204082Snwhitehorn return(0); 294194679Snwhitehorn } 295194679Snwhitehorn 296194679Snwhitehorn /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ 297194679Snwhitehorn t = line; 298194679Snwhitehorn#define EXPAND(e) e = t; while ( (*t++ = *p++) ); 299194679Snwhitehorn#define SCALAR(v) memmove(&(v), p, sizeof v); p += sizeof v 300194679Snwhitehorn EXPAND(_pw_passwd.pw_name); 301204082Snwhitehorn EXPAND(_pw_passwd.pw_passwd); 302194679Snwhitehorn SCALAR(_pw_passwd.pw_uid); 303194679Snwhitehorn SCALAR(_pw_passwd.pw_gid); 304194679Snwhitehorn SCALAR(_pw_passwd.pw_change); 305194679Snwhitehorn EXPAND(_pw_passwd.pw_class); 306204082Snwhitehorn EXPAND(_pw_passwd.pw_gecos); 307204082Snwhitehorn EXPAND(_pw_passwd.pw_dir); 308204082Snwhitehorn EXPAND(_pw_passwd.pw_shell); 309204082Snwhitehorn SCALAR(_pw_passwd.pw_expire); 310194679Snwhitehorn bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields); 311194679Snwhitehorn p += sizeof _pw_passwd.pw_fields; 312194679Snwhitehorn return(1); 313194679Snwhitehorn} 314194679Snwhitehorn 315204082Snwhitehorn#ifdef YP 316204082Snwhitehorn 317204082Snwhitehornstatic void 318204082Snwhitehorn_ypinitdb() 319204082Snwhitehorn{ 320204082Snwhitehorn DBT key, data; 321204082Snwhitehorn char buf[] = { _PW_KEYYPENABLED }; 322204082Snwhitehorn key.data = buf; 323204082Snwhitehorn key.size = 1; 324204082Snwhitehorn _yp_enabled = 0; 325204082Snwhitehorn if ((_pw_db->get)(_pw_db, &key, &data, 0) == 0) { 326204082Snwhitehorn _yp_enabled = (int)*((char *)data.data) - 2; 327204082Snwhitehorn /* Don't even bother with this if we aren't root. */ 328204082Snwhitehorn if (!geteuid()) { 329204082Snwhitehorn if (!_pw_yp_domain) 330204082Snwhitehorn if (yp_get_default_domain(&_pw_yp_domain)) 331204082Snwhitehorn return; 332204082Snwhitehorn _gotmaster = _havemaster(_pw_yp_domain); 333204082Snwhitehorn } else _gotmaster = YP_HAVE_NONE; 334204082Snwhitehorn /* 335204082Snwhitehorn * Create a DB hash database in memory. Bet you didn't know you 336204082Snwhitehorn * could do a dbopen() with a NULL filename, did you. 337204082Snwhitehorn */ 338204082Snwhitehorn if (_ypcache == (DB *)NULL) 339204082Snwhitehorn _ypcache = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL); 340204082Snwhitehorn } 341204082Snwhitehorn} 342204082Snwhitehorn 343204082Snwhitehorn/* 344194679Snwhitehorn * See if a user is in the blackballed list. 345194679Snwhitehorn */ 346194679Snwhitehornstatic inline int 347194679Snwhitehornlookup(name) 348194679Snwhitehorn const char *name; 349194679Snwhitehorn{ 350194679Snwhitehorn DBT key; 351194679Snwhitehorn 352194679Snwhitehorn if (!_yp_exclusions) 353194679Snwhitehorn return(0); 354194679Snwhitehorn 355194679Snwhitehorn key.data = (char *)name; 356194679Snwhitehorn key.size = strlen(name); 357194679Snwhitehorn 358194679Snwhitehorn if ((_ypcache->get)(_ypcache, &key, &empty, 0)) { 359194679Snwhitehorn return(0); 360194679Snwhitehorn } 361194679Snwhitehorn 362194679Snwhitehorn return(1); 363194679Snwhitehorn} 364194679Snwhitehorn 365194679Snwhitehorn/* 366194679Snwhitehorn * Store a blackballed user in an in-core hash database. 367194679Snwhitehorn */ 368194679Snwhitehornstatic inline void 369194679Snwhitehornstore(key) 370194679Snwhitehorn const char *key; 371194679Snwhitehorn{ 372194679Snwhitehorn DBT lkey; 373194679Snwhitehorn/* 374194679Snwhitehorn if (lookup(key)) 375194679Snwhitehorn return; 376194679Snwhitehorn*/ 377194679Snwhitehorn 378194679Snwhitehorn _yp_exclusions = 1; 379194679Snwhitehorn 380194679Snwhitehorn lkey.data = (char *)key; 381194679Snwhitehorn lkey.size = strlen(key); 382194679Snwhitehorn 383194679Snwhitehorn (void)(_ypcache->put)(_ypcache, &lkey, &empty, R_NOOVERWRITE); 384194679Snwhitehorn} 385194679Snwhitehorn 386194679Snwhitehorn/* 387194679Snwhitehorn * Parse the + entries in the password database and do appropriate 388194679Snwhitehorn * NIS lookups. While ugly to look at, this is optimized to do only 389194679Snwhitehorn * as many lookups as are absolutely necessary in any given case. 390194679Snwhitehorn * Basically, the getpwent() function will feed us + and - lines 391194679Snwhitehorn * as they appear in the database. For + lines, we do netgroup/group 392194679Snwhitehorn * and user lookups to find all usernames that match the rule and 393194679Snwhitehorn * extract them from the NIS passwd maps. For - lines, we save the 394194679Snwhitehorn * matching names in a database and a) exlude them, and b) make sure 395194679Snwhitehorn * we don't consider them when processing other + lines that appear 396194679Snwhitehorn * later. 397194679Snwhitehorn */ 398194679Snwhitehornstatic inline int 399194679Snwhitehornunwind(grp) 400194679Snwhitehorn char *grp; 401194679Snwhitehorn{ 402194679Snwhitehorn char *user, *host, *domain; 403194679Snwhitehorn static int latch = 0; 404194679Snwhitehorn static struct group *gr = NULL; 405194679Snwhitehorn int rv = 0; 406194679Snwhitehorn 407194679Snwhitehorn if (grp[0] == '+') { 408194679Snwhitehorn if (strlen(grp) == 1) { 409194679Snwhitehorn return(_nextyppass(&_pw_passwd)); 410194679Snwhitehorn } 411194679Snwhitehorn if (grp[1] == '@') { 412194679Snwhitehorn _pw_stepping_yp = 1; 413194679Snwhitehorngrpagain: 414194679Snwhitehorn if (gr != NULL) { 415194679Snwhitehorn if (*gr->gr_mem != NULL) { 416194679Snwhitehorn if (lookup(*gr->gr_mem)) { 417194679Snwhitehorn gr->gr_mem++; 418194679Snwhitehorn goto grpagain; 419194679Snwhitehorn } 420194679Snwhitehorn rv = _getyppass(&_pw_passwd, 421194679Snwhitehorn *gr->gr_mem, 422194679Snwhitehorn "passwd.byname"); 423194679Snwhitehorn gr->gr_mem++; 424204082Snwhitehorn return(rv); 425204082Snwhitehorn } else { 426204082Snwhitehorn endgrent(); 427204082Snwhitehorn latch = 0; 428204082Snwhitehorn gr = NULL; 429204082Snwhitehorn return(0); 430204082Snwhitehorn } 431204082Snwhitehorn } 432204082Snwhitehorn if (!latch) { 433204082Snwhitehorn setnetgrent(grp+2); 434204082Snwhitehorn latch++; 435204082Snwhitehorn } 436204082Snwhitehornagain: 437204082Snwhitehorn if (getnetgrent(&host, &user, &domain) == 0) { 438204082Snwhitehorn if ((gr = getgrnam(grp+2)) != NULL) 439204082Snwhitehorn goto grpagain; 440204082Snwhitehorn latch = 0; 441204082Snwhitehorn _pw_stepping_yp = 0; 442204082Snwhitehorn return(0); 443204082Snwhitehorn } else { 444204082Snwhitehorn if (lookup(user)) 445204082Snwhitehorn goto again; 446204082Snwhitehorn if (_getyppass(&_pw_passwd, user, 447204082Snwhitehorn "passwd.byname")) 448204082Snwhitehorn return(1); 449204082Snwhitehorn else 450204082Snwhitehorn goto again; 451204082Snwhitehorn } 452204082Snwhitehorn } else { 453204082Snwhitehorn if (lookup(grp+1)) 454204082Snwhitehorn return(0); 455204082Snwhitehorn return(_getyppass(&_pw_passwd, grp+1, "passwd.byname")); 456204082Snwhitehorn } 457204082Snwhitehorn } else { 458204082Snwhitehorn if (grp[1] == '@') { 459204082Snwhitehorn setnetgrent(grp+2); 460204082Snwhitehorn rv = 0; 461204082Snwhitehorn while(getnetgrent(&host, &user, &domain) != 0) { 462204082Snwhitehorn store(user); 463204082Snwhitehorn rv++; 464204082Snwhitehorn } 465204082Snwhitehorn if (!rv && (gr = getgrnam(grp+2)) != NULL) { 466204082Snwhitehorn while(*gr->gr_mem) { 467204082Snwhitehorn store(*gr->gr_mem); 468204082Snwhitehorn gr->gr_mem++; 469204082Snwhitehorn } 470204082Snwhitehorn } 471204082Snwhitehorn } else { 472204082Snwhitehorn store(grp+1); 473204082Snwhitehorn } 474204082Snwhitehorn } 475204082Snwhitehorn return(0); 476204082Snwhitehorn} 477204082Snwhitehorn 478204082Snwhitehorn/* 479204082Snwhitehorn * See if a user is a member of a particular group. 480204082Snwhitehorn */ 481204082Snwhitehornstatic inline int 482204082Snwhitehorningr(grp, name) 483204082Snwhitehorn const char *grp; 484204082Snwhitehorn const char *name; 485204082Snwhitehorn{ 486204082Snwhitehorn register struct group *gr; 487204082Snwhitehorn 488204082Snwhitehorn if ((gr = getgrnam(grp)) == NULL) 489204082Snwhitehorn return(0); 490204082Snwhitehorn 491204082Snwhitehorn while(*gr->gr_mem) { 492204082Snwhitehorn if (!strcmp(*gr->gr_mem, name)) { 493204082Snwhitehorn endgrent(); 494204082Snwhitehorn return(1); 495204082Snwhitehorn } 496204082Snwhitehorn gr->gr_mem++; 497204082Snwhitehorn } 498204082Snwhitehorn 499204082Snwhitehorn endgrent(); 500204082Snwhitehorn return(0); 501204082Snwhitehorn} 502204082Snwhitehorn 503204082Snwhitehorn/* 504204082Snwhitehorn * Check a user against the +@netgroup/-@netgroup lines listed in 505204082Snwhitehorn * the local password database. Also checks +user/-user lines. 506204082Snwhitehorn * If no netgroup exists that matches +@netgroup/-@netgroup, 507204082Snwhitehorn * try searching regular groups with the same name. 508204082Snwhitehorn */ 509204082Snwhitehornstatic inline int 510204082Snwhitehornverf(name) 511204082Snwhitehorn const char *name; 512204082Snwhitehorn{ 513204082Snwhitehorn DBT key; 514204082Snwhitehorn char bf[sizeof(_pw_keynum) + 1]; 515204082Snwhitehorn int keynum = 0; 516204082Snwhitehorn 517204082Snwhitehornagain: 518204082Snwhitehorn ++keynum; 519204082Snwhitehorn bf[0] = _PW_KEYYPBYNUM; 520204082Snwhitehorn bcopy((char *)&keynum, bf + 1, sizeof(keynum)); 521204082Snwhitehorn key.data = (u_char *)bf; 522204082Snwhitehorn key.size = sizeof(keynum) + 1; 523204082Snwhitehorn if (!__hashpw(&key)) { 524204082Snwhitehorn /* Try again using old format */ 525204082Snwhitehorn bf[0] = _PW_KEYBYNUM; 526204082Snwhitehorn bcopy((char *)&keynum, bf + 1, sizeof(keynum)); 527204082Snwhitehorn key.data = (u_char *)bf; 528204082Snwhitehorn if (!__hashpw(&key)) 529204082Snwhitehorn return(0); 530204082Snwhitehorn } 531204082Snwhitehorn if (_pw_passwd.pw_name[0] != '+' && (_pw_passwd.pw_name[0] != '-')) 532204082Snwhitehorn goto again; 533204082Snwhitehorn if (_pw_passwd.pw_name[0] == '+') { 534204082Snwhitehorn if (strlen(_pw_passwd.pw_name) == 1) /* Wildcard */ 535204082Snwhitehorn return(1); 536204082Snwhitehorn if (_pw_passwd.pw_name[1] == '@') { 537204082Snwhitehorn if ((innetgr(_pw_passwd.pw_name+2, NULL, name, 538204082Snwhitehorn _pw_yp_domain) || 539204082Snwhitehorn ingr(_pw_passwd.pw_name+2, name)) && !lookup(name)) 540204082Snwhitehorn return(1); 541204082Snwhitehorn else 542204082Snwhitehorn goto again; 543204082Snwhitehorn } else { 544204082Snwhitehorn if (!strcmp(name, _pw_passwd.pw_name+1) && 545204082Snwhitehorn !lookup(name)) 546204082Snwhitehorn return(1); 547204082Snwhitehorn else 548204082Snwhitehorn goto again; 549204082Snwhitehorn } 550204082Snwhitehorn } 551204082Snwhitehorn if (_pw_passwd.pw_name[0] == '-') { 552204082Snwhitehorn /* Note that a minus wildcard is a no-op. */ 553204082Snwhitehorn if (_pw_passwd.pw_name[1] == '@') { 554204082Snwhitehorn if (innetgr(_pw_passwd.pw_name+2, NULL, name, 555204082Snwhitehorn _pw_yp_domain) || 556204082Snwhitehorn ingr(_pw_passwd.pw_name+2, name)) { 557204082Snwhitehorn store(name); 558204082Snwhitehorn return(0); 559204082Snwhitehorn } else 560204082Snwhitehorn goto again; 561204082Snwhitehorn } else { 562204082Snwhitehorn if (!strcmp(name, _pw_passwd.pw_name+1)) { 563204082Snwhitehorn store(name); 564204082Snwhitehorn return(0); 565204082Snwhitehorn } else 566204082Snwhitehorn goto again; 567204082Snwhitehorn } 568204082Snwhitehorn 569204082Snwhitehorn } 570204082Snwhitehorn return(0); 571204082Snwhitehorn} 572204082Snwhitehorn 573204082Snwhitehornstatic char * 574204082Snwhitehorn_get_adjunct_pw(name) 575204082Snwhitehorn const char *name; 576204082Snwhitehorn{ 577204082Snwhitehorn static char adjunctbuf[YPMAXRECORD+2]; 578204082Snwhitehorn int rval; 579204082Snwhitehorn char *result; 580204082Snwhitehorn int resultlen; 581204082Snwhitehorn char *map = "passwd.adjunct.byname"; 582204082Snwhitehorn char *s; 583204082Snwhitehorn 584204082Snwhitehorn if ((rval = yp_match(_pw_yp_domain, map, name, strlen(name), 585204082Snwhitehorn &result, &resultlen))) 586204082Snwhitehorn return(NULL); 587204082Snwhitehorn 588204082Snwhitehorn strncpy(adjunctbuf, result, resultlen); 589204082Snwhitehorn adjunctbuf[resultlen] = '\0'; 590204082Snwhitehorn free(result); 591204082Snwhitehorn result = (char *)&adjunctbuf; 592204082Snwhitehorn 593204082Snwhitehorn /* Don't care about the name. */ 594204082Snwhitehorn if ((s = strsep(&result, ":")) == NULL) 595204082Snwhitehorn return (NULL); /* name */ 596204082Snwhitehorn if ((s = strsep(&result, ":")) == NULL) 597204082Snwhitehorn return (NULL); /* password */ 598204082Snwhitehorn 599204082Snwhitehorn return(s); 600204082Snwhitehorn} 601204082Snwhitehorn 602204082Snwhitehornstatic int 603204082Snwhitehorn_pw_breakout_yp(struct passwd *pw, char *res, int resultlen, int master) 604204082Snwhitehorn{ 605204082Snwhitehorn char *s, *result; 606204082Snwhitehorn static char resbuf[YPMAXRECORD+2]; 607204082Snwhitehorn 608204082Snwhitehorn /* 609204082Snwhitehorn * Be triple, ultra super-duper paranoid: reject entries 610204082Snwhitehorn * that start with a + or -. yp_mkdb and /var/yp/Makefile 611204082Snwhitehorn * are _both_ supposed to strip these out, but you never 612204082Snwhitehorn * know. 613204082Snwhitehorn */ 614204082Snwhitehorn if (*res == '+' || *res == '-') 615204082Snwhitehorn return 0; 616204082Snwhitehorn 617204082Snwhitehorn /* 618204082Snwhitehorn * The NIS protocol definition limits the size of an NIS 619204082Snwhitehorn * record to YPMAXRECORD bytes. We need to do a copy to 620204082Snwhitehorn * a static buffer here since the memory pointed to by 621204082Snwhitehorn * res will be free()ed when this function returns. 622204082Snwhitehorn */ 623204082Snwhitehorn strncpy((char *)&resbuf, res, resultlen); 624204082Snwhitehorn resbuf[resultlen] = '\0'; 625204082Snwhitehorn result = (char *)&resbuf; 626204082Snwhitehorn 627204082Snwhitehorn /* 628204082Snwhitehorn * XXX Sanity check: make sure all fields are valid (no NULLs). 629204082Snwhitehorn * If we find a badly formatted entry, we punt. 630204082Snwhitehorn */ 631204082Snwhitehorn if ((s = strsep(&result, ":")) == NULL) return 0; /* name */ 632204082Snwhitehorn /* 633204082Snwhitehorn * We don't care what pw_fields says: we _always_ want the 634204082Snwhitehorn * username returned to us by NIS. 635204082Snwhitehorn */ 636204082Snwhitehorn pw->pw_name = s; 637204082Snwhitehorn pw->pw_fields |= _PWF_NAME; 638204082Snwhitehorn 639204082Snwhitehorn if ((s = strsep(&result, ":")) == NULL) return 0; /* password */ 640204082Snwhitehorn if(!(pw->pw_fields & _PWF_PASSWD)) { 641204082Snwhitehorn /* SunOS passwd.adjunct hack */ 642204082Snwhitehorn if (master == YP_HAVE_ADJUNCT && strstr(s, "##") != NULL) { 643204082Snwhitehorn char *realpw; 644204082Snwhitehorn realpw = _get_adjunct_pw(pw->pw_name); 645204082Snwhitehorn if (realpw == NULL) 646204082Snwhitehorn pw->pw_passwd = s; 647204082Snwhitehorn else 648204082Snwhitehorn pw->pw_passwd = realpw; 649204082Snwhitehorn } else { 650204082Snwhitehorn pw->pw_passwd = s; 651204082Snwhitehorn } 652204082Snwhitehorn pw->pw_fields |= _PWF_PASSWD; 653204082Snwhitehorn } 654204082Snwhitehorn 655204082Snwhitehorn if ((s = strsep(&result, ":")) == NULL) return 0; /* uid */ 656204082Snwhitehorn if(!(pw->pw_fields & _PWF_UID)) { 657204082Snwhitehorn pw->pw_uid = atoi(s); 658204082Snwhitehorn pw->pw_fields |= _PWF_UID; 659204082Snwhitehorn } 660204082Snwhitehorn 661204082Snwhitehorn if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */ 662204082Snwhitehorn if(!(pw->pw_fields & _PWF_GID)) { 663204082Snwhitehorn pw->pw_gid = atoi(s); 664204082Snwhitehorn pw->pw_fields |= _PWF_GID; 665204082Snwhitehorn } 666204082Snwhitehorn 667204082Snwhitehorn if (master == YP_HAVE_MASTER) { 668204082Snwhitehorn if ((s = strsep(&result, ":")) == NULL) return 0; /* class */ 669204082Snwhitehorn if(!(pw->pw_fields & _PWF_CLASS)) { 670204082Snwhitehorn pw->pw_class = s; 671204082Snwhitehorn pw->pw_fields |= _PWF_CLASS; 672204082Snwhitehorn } 673204082Snwhitehorn 674204082Snwhitehorn if ((s = strsep(&result, ":")) == NULL) return 0; /* change */ 675204082Snwhitehorn if(!(pw->pw_fields & _PWF_CHANGE)) { 676204082Snwhitehorn pw->pw_change = atol(s); 677204082Snwhitehorn pw->pw_fields |= _PWF_CHANGE; 678204082Snwhitehorn } 679204082Snwhitehorn 680204082Snwhitehorn if ((s = strsep(&result, ":")) == NULL) return 0; /* expire */ 681204082Snwhitehorn if(!(pw->pw_fields & _PWF_EXPIRE)) { 682204082Snwhitehorn pw->pw_expire = atol(s); 683204082Snwhitehorn pw->pw_fields |= _PWF_EXPIRE; 684204082Snwhitehorn } 685204082Snwhitehorn } 686204082Snwhitehorn 687204082Snwhitehorn if ((s = strsep(&result, ":")) == NULL) return 0; /* gecos */ 688204082Snwhitehorn if(!(pw->pw_fields & _PWF_GECOS)) { 689204082Snwhitehorn pw->pw_gecos = s; 690204082Snwhitehorn pw->pw_fields |= _PWF_GECOS; 691204082Snwhitehorn } 692204082Snwhitehorn 693204082Snwhitehorn if ((s = strsep(&result, ":")) == NULL) return 0; /* dir */ 694204082Snwhitehorn if(!(pw->pw_fields & _PWF_DIR)) { 695204082Snwhitehorn pw->pw_dir = s; 696204082Snwhitehorn pw->pw_fields |= _PWF_DIR; 697204082Snwhitehorn } 698204082Snwhitehorn 699204082Snwhitehorn if ((s = strsep(&result, ":")) == NULL) return 0; /* shell */ 700204082Snwhitehorn if(!(pw->pw_fields & _PWF_SHELL)) { 701204082Snwhitehorn pw->pw_shell = s; 702204082Snwhitehorn pw->pw_fields |= _PWF_SHELL; 703204082Snwhitehorn } 704204082Snwhitehorn 705204082Snwhitehorn /* Be consistent. */ 706204082Snwhitehorn if ((s = strchr(pw->pw_shell, '\n'))) *s = '\0'; 707204082Snwhitehorn 708204082Snwhitehorn return 1; 709204082Snwhitehorn} 710204082Snwhitehorn 711204082Snwhitehornstatic int 712204082Snwhitehorn_havemaster(char *_yp_domain) 713204082Snwhitehorn{ 714204082Snwhitehorn int order; 715204082Snwhitehorn int rval; 716204082Snwhitehorn 717204082Snwhitehorn if (!(rval = yp_order(_yp_domain, "master.passwd.byname", &order))) 718204082Snwhitehorn return(YP_HAVE_MASTER); 719 720 /* 721 * NIS+ in YP compat mode doesn't support 722 * YPPROC_ORDER -- no point in continuing. 723 */ 724 if (rval == YPERR_YPERR) 725 return(YP_HAVE_NONE); 726 727 /* master.passwd doesn't exist -- try passwd.adjunct */ 728 if (rval == YPERR_MAP) { 729 rval = yp_order(_yp_domain, "passwd.adjunct.byname", &order); 730 if (!rval) 731 return(YP_HAVE_ADJUNCT); 732 } 733 734 return (YP_HAVE_NONE); 735} 736 737static int 738_getyppass(struct passwd *pw, const char *name, const char *map) 739{ 740 char *result, *s; 741 int resultlen; 742 int rv; 743 char mastermap[YPMAXRECORD]; 744 745 if(!_pw_yp_domain) { 746 if(yp_get_default_domain(&_pw_yp_domain)) 747 return 0; 748 } 749 750 sprintf(mastermap,"%s",map); 751 752 if (_gotmaster == YP_HAVE_MASTER) 753 sprintf(mastermap,"master.%s", map); 754 755 if(yp_match(_pw_yp_domain, (char *)&mastermap, name, strlen(name), 756 &result, &resultlen)) 757 return 0; 758 759 if (!_pw_stepping_yp) { 760 s = strchr(result, ':'); 761 if (s) { 762 *s = '\0'; 763 } else { 764 /* Must be a malformed entry if no colons. */ 765 free(result); 766 return(0); 767 } 768 769 if (!verf(result)) { 770 *s = ':'; 771 free(result); 772 return(0); 773 } 774 775 *s = ':'; /* Put back the colon we previously replaced with a NUL. */ 776 } 777 778 rv = _pw_breakout_yp(pw, result, resultlen, _gotmaster); 779 free(result); 780 return(rv); 781} 782 783static int 784_nextyppass(struct passwd *pw) 785{ 786 static char *key; 787 static int keylen; 788 char *lastkey, *result, *s; 789 int resultlen; 790 int rv; 791 char *map = "passwd.byname"; 792 793 if(!_pw_yp_domain) { 794 if(yp_get_default_domain(&_pw_yp_domain)) 795 return 0; 796 } 797 798 if (_gotmaster == YP_HAVE_MASTER) 799 map = "master.passwd.byname"; 800 801 if(!_pw_stepping_yp) { 802 if(key) free(key); 803 rv = yp_first(_pw_yp_domain, map, 804 &key, &keylen, &result, &resultlen); 805 if(rv) { 806 return 0; 807 } 808 _pw_stepping_yp = 1; 809 goto unpack; 810 } else { 811tryagain: 812 lastkey = key; 813 rv = yp_next(_pw_yp_domain, map, key, keylen, 814 &key, &keylen, &result, &resultlen); 815 free(lastkey); 816unpack: 817 if(rv) { 818 _pw_stepping_yp = 0; 819 return 0; 820 } 821 822 s = strchr(result, ':'); 823 if (s) { 824 *s = '\0'; 825 } else { 826 /* Must be a malformed entry if no colons. */ 827 free(result); 828 goto tryagain; 829 } 830 831 if (lookup(result)) { 832 *s = ':'; 833 free(result); 834 goto tryagain; 835 } 836 837 *s = ':'; /* Put back the colon we previously replaced with a NUL. */ 838 if (_pw_breakout_yp(pw, result, resultlen, _gotmaster)) { 839 free(result); 840 return(1); 841 } else { 842 free(result); 843 goto tryagain; 844 } 845 } 846} 847 848#endif /* YP */ 849