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