xref: /freebsd/lib/libc/gen/getpwent.c (revision 8be26e5d0fba112f3a6662f06b5babf14555a00e)
158f0484fSRodney W. Grimes /*
258f0484fSRodney W. Grimes  * Copyright (c) 1988, 1993
358f0484fSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
458f0484fSRodney W. Grimes  *
558f0484fSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
658f0484fSRodney W. Grimes  * modification, are permitted provided that the following conditions
758f0484fSRodney W. Grimes  * are met:
858f0484fSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
958f0484fSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
1058f0484fSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
1158f0484fSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
1258f0484fSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
1358f0484fSRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
1458f0484fSRodney W. Grimes  *    must display the following acknowledgement:
1558f0484fSRodney W. Grimes  *	This product includes software developed by the University of
1658f0484fSRodney W. Grimes  *	California, Berkeley and its contributors.
1758f0484fSRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
1858f0484fSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
1958f0484fSRodney W. Grimes  *    without specific prior written permission.
2058f0484fSRodney W. Grimes  *
2158f0484fSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2258f0484fSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2358f0484fSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2458f0484fSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2558f0484fSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2658f0484fSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2758f0484fSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2858f0484fSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2958f0484fSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3058f0484fSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3158f0484fSRodney W. Grimes  * SUCH DAMAGE.
3258f0484fSRodney W. Grimes  */
3358f0484fSRodney W. Grimes 
3458f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint)
35adf6ad9eSPeter Wemm static char sccsid[] = "@(#)getpwent.c	8.2 (Berkeley) 4/27/95";
3658f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */
3758f0484fSRodney W. Grimes 
38958f4e36SBill Paul #include <stdio.h>
3958f0484fSRodney W. Grimes #include <sys/param.h>
4058f0484fSRodney W. Grimes #include <fcntl.h>
4158f0484fSRodney W. Grimes #include <db.h>
4258f0484fSRodney W. Grimes #include <syslog.h>
4358f0484fSRodney W. Grimes #include <pwd.h>
4458f0484fSRodney W. Grimes #include <utmp.h>
4558f0484fSRodney W. Grimes #include <errno.h>
4658f0484fSRodney W. Grimes #include <unistd.h>
4758f0484fSRodney W. Grimes #include <stdlib.h>
4858f0484fSRodney W. Grimes #include <string.h>
4958f0484fSRodney W. Grimes #include <limits.h>
50958f4e36SBill Paul #include <grp.h>
5158f0484fSRodney W. Grimes 
5251295a4dSJordan K. Hubbard extern void setnetgrent __P(( char * ));
5351295a4dSJordan K. Hubbard extern int getnetgrent __P(( char **, char **, char ** ));
5451295a4dSJordan K. Hubbard extern int innetgr __P(( const char *, const char *, const char *, const char * ));
5551295a4dSJordan K. Hubbard 
56adf6ad9eSPeter Wemm /*
57adf6ad9eSPeter Wemm  * The lookup techniques and data extraction code here must be kept
58adf6ad9eSPeter Wemm  * in sync with that in `pwd_mkdb'.
59adf6ad9eSPeter Wemm  */
60adf6ad9eSPeter Wemm 
6158f0484fSRodney W. Grimes static struct passwd _pw_passwd;	/* password structure */
6258f0484fSRodney W. Grimes static DB *_pw_db;			/* password database */
6358f0484fSRodney W. Grimes static int _pw_keynum;			/* key counter */
6458f0484fSRodney W. Grimes static int _pw_stayopen;		/* keep fd's open */
65d5b7518dSGarrett Wollman #ifdef YP
66958f4e36SBill Paul #include <rpc/rpc.h>
67958f4e36SBill Paul #include <rpcsvc/yp_prot.h>
68958f4e36SBill Paul #include <rpcsvc/ypclnt.h>
6994c53e1fSBill Paul 
70d5b7518dSGarrett Wollman static struct passwd _pw_copy;
7194c53e1fSBill Paul static DBT empty = { NULL, 0 };
7294c53e1fSBill Paul static DB *_ypcache = (DB *)NULL;
7394c53e1fSBill Paul static int _yp_exclusions = 0;
74d5b7518dSGarrett Wollman static int _yp_enabled;			/* set true when yp enabled */
75d5b7518dSGarrett Wollman static int _pw_stepping_yp;		/* set true when stepping thru map */
7694c53e1fSBill Paul static char _ypnam[YPMAXRECORD];
772be5d4cbSBill Paul #define YP_HAVE_MASTER 2
782be5d4cbSBill Paul #define YP_HAVE_ADJUNCT 1
792be5d4cbSBill Paul #define YP_HAVE_NONE 0
803948edc2SBill Paul static int _gotmaster;
813948edc2SBill Paul static char *_pw_yp_domain;
8294c53e1fSBill Paul static inline int unwind __P(( char * ));
8394c53e1fSBill Paul static inline void _ypinitdb __P(( void ));
8494c53e1fSBill Paul static int _havemaster __P((char *));
8594c53e1fSBill Paul static int _getyppass __P((struct passwd *, const char *, const char * ));
8694c53e1fSBill Paul static int _nextyppass __P((struct passwd *));
873948edc2SBill Paul #endif
883948edc2SBill Paul static int __hashpw(), __initdb();
89d5b7518dSGarrett Wollman 
9058f0484fSRodney W. Grimes struct passwd *
9158f0484fSRodney W. Grimes getpwent()
9258f0484fSRodney W. Grimes {
9358f0484fSRodney W. Grimes 	DBT key;
9458f0484fSRodney W. Grimes 	char bf[sizeof(_pw_keynum) + 1];
95d5b7518dSGarrett Wollman 	int rv;
9658f0484fSRodney W. Grimes 
9758f0484fSRodney W. Grimes 	if (!_pw_db && !__initdb())
9858f0484fSRodney W. Grimes 		return((struct passwd *)NULL);
9958f0484fSRodney W. Grimes 
100d5b7518dSGarrett Wollman #ifdef YP
101d5b7518dSGarrett Wollman 	if(_pw_stepping_yp) {
102d5b7518dSGarrett Wollman 		_pw_passwd = _pw_copy;
10394c53e1fSBill Paul 		if (unwind((char *)&_ypnam))
104d454389cSBill Paul 			return(&_pw_passwd);
105d5b7518dSGarrett Wollman 	}
106958f4e36SBill Paul #endif
107d454389cSBill Paul tryagain:
108d454389cSBill Paul 
10958f0484fSRodney W. Grimes 	++_pw_keynum;
11058f0484fSRodney W. Grimes 	bf[0] = _PW_KEYBYNUM;
11158f0484fSRodney W. Grimes 	bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
11258f0484fSRodney W. Grimes 	key.data = (u_char *)bf;
11358f0484fSRodney W. Grimes 	key.size = sizeof(_pw_keynum) + 1;
114d5b7518dSGarrett Wollman 	rv = __hashpw(&key);
115d5b7518dSGarrett Wollman 	if(!rv) return (struct passwd *)NULL;
116d5b7518dSGarrett Wollman #ifdef YP
11782844700SBill Paul 	if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') {
11894c53e1fSBill Paul 		bzero((char *)&_ypnam, sizeof(_ypnam));
11994c53e1fSBill Paul 		bcopy(_pw_passwd.pw_name, _ypnam,
12094c53e1fSBill Paul 			strlen(_pw_passwd.pw_name));
121d5b7518dSGarrett Wollman 		_pw_copy = _pw_passwd;
12294c53e1fSBill Paul 		if (unwind((char *)&_ypnam) == 0)
123d454389cSBill Paul 			goto tryagain;
124d454389cSBill Paul 		else
125d454389cSBill Paul 			return(&_pw_passwd);
126d5b7518dSGarrett Wollman 	}
127d5b7518dSGarrett Wollman #else
128d5b7518dSGarrett Wollman 	/* Ignore YP password file entries when YP is disabled. */
12982844700SBill Paul 	if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') {
130d5b7518dSGarrett Wollman 		goto tryagain;
131d5b7518dSGarrett Wollman 	}
132d5b7518dSGarrett Wollman #endif
133d5b7518dSGarrett Wollman 	return(&_pw_passwd);
13458f0484fSRodney W. Grimes }
13558f0484fSRodney W. Grimes 
13658f0484fSRodney W. Grimes struct passwd *
13758f0484fSRodney W. Grimes getpwnam(name)
13858f0484fSRodney W. Grimes 	const char *name;
13958f0484fSRodney W. Grimes {
14058f0484fSRodney W. Grimes 	DBT key;
14158f0484fSRodney W. Grimes 	int len, rval;
142d5b7518dSGarrett Wollman 	char bf[UT_NAMESIZE + 2];
14358f0484fSRodney W. Grimes 
14458f0484fSRodney W. Grimes 	if (!_pw_db && !__initdb())
14558f0484fSRodney W. Grimes 		return((struct passwd *)NULL);
14658f0484fSRodney W. Grimes 
14758f0484fSRodney W. Grimes 	bf[0] = _PW_KEYBYNAME;
14858f0484fSRodney W. Grimes 	len = strlen(name);
14958f0484fSRodney W. Grimes 	bcopy(name, bf + 1, MIN(len, UT_NAMESIZE));
15058f0484fSRodney W. Grimes 	key.data = (u_char *)bf;
15158f0484fSRodney W. Grimes 	key.size = len + 1;
15258f0484fSRodney W. Grimes 	rval = __hashpw(&key);
15358f0484fSRodney W. Grimes 
154d5b7518dSGarrett Wollman #ifdef YP
1555f115c9dSBill Paul 	if (!rval && _yp_enabled)
156d5b7518dSGarrett Wollman 		rval = _getyppass(&_pw_passwd, name, "passwd.byname");
157c7da24ddSGarrett Wollman #endif
158d5b7518dSGarrett Wollman 	/*
159d5b7518dSGarrett Wollman 	 * Prevent login attempts when YP is not enabled but YP entries
160d5b7518dSGarrett Wollman 	 * are in /etc/master.passwd.
161d5b7518dSGarrett Wollman 	 */
16282844700SBill Paul 	if (rval && (_pw_passwd.pw_name[0] == '+'||
16382844700SBill Paul 			_pw_passwd.pw_name[0] == '-')) rval = 0;
164bb38a730SGarrett Wollman 
1659531ca93SBill Paul 	endpwent();
16658f0484fSRodney W. Grimes 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
16758f0484fSRodney W. Grimes }
16858f0484fSRodney W. Grimes 
16958f0484fSRodney W. Grimes struct passwd *
17058f0484fSRodney W. Grimes getpwuid(uid)
171adf6ad9eSPeter Wemm 	uid_t uid;
17258f0484fSRodney W. Grimes {
17358f0484fSRodney W. Grimes 	DBT key;
17458f0484fSRodney W. Grimes 	int keyuid, rval;
17558f0484fSRodney W. Grimes 	char bf[sizeof(keyuid) + 1];
17658f0484fSRodney W. Grimes 
17758f0484fSRodney W. Grimes 	if (!_pw_db && !__initdb())
17858f0484fSRodney W. Grimes 		return((struct passwd *)NULL);
17958f0484fSRodney W. Grimes 
18058f0484fSRodney W. Grimes 	bf[0] = _PW_KEYBYUID;
18158f0484fSRodney W. Grimes 	keyuid = uid;
18258f0484fSRodney W. Grimes 	bcopy(&keyuid, bf + 1, sizeof(keyuid));
18358f0484fSRodney W. Grimes 	key.data = (u_char *)bf;
18458f0484fSRodney W. Grimes 	key.size = sizeof(keyuid) + 1;
18558f0484fSRodney W. Grimes 	rval = __hashpw(&key);
18658f0484fSRodney W. Grimes 
187d5b7518dSGarrett Wollman #ifdef YP
188d5b7518dSGarrett Wollman 	if (!rval && _yp_enabled) {
189d5b7518dSGarrett Wollman 		char ypbuf[16];	/* big enough for 32-bit uids and then some */
190d5b7518dSGarrett Wollman 		snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid);
191d5b7518dSGarrett Wollman 		rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid");
192d5b7518dSGarrett Wollman 	}
193d5b7518dSGarrett Wollman #endif
19482844700SBill Paul 	/*
19582844700SBill Paul 	 * Prevent login attempts when YP is not enabled but YP entries
19682844700SBill Paul 	 * are in /etc/master.passwd.
19782844700SBill Paul 	 */
19882844700SBill Paul 	if (rval && (_pw_passwd.pw_name[0] == '+'||
19982844700SBill Paul 			_pw_passwd.pw_name[0] == '-')) rval = 0;
2009531ca93SBill Paul 
2019531ca93SBill Paul 	endpwent();
20258f0484fSRodney W. Grimes 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
20358f0484fSRodney W. Grimes }
20458f0484fSRodney W. Grimes 
20558f0484fSRodney W. Grimes int
20658f0484fSRodney W. Grimes setpassent(stayopen)
20758f0484fSRodney W. Grimes 	int stayopen;
20858f0484fSRodney W. Grimes {
20958f0484fSRodney W. Grimes 	_pw_keynum = 0;
210d5b7518dSGarrett Wollman #ifdef YP
21194c53e1fSBill Paul 	_pw_stepping_yp = 0;
212d5b7518dSGarrett Wollman #endif
21358f0484fSRodney W. Grimes 	_pw_stayopen = stayopen;
21458f0484fSRodney W. Grimes 	return(1);
21558f0484fSRodney W. Grimes }
21658f0484fSRodney W. Grimes 
21758f0484fSRodney W. Grimes int
21858f0484fSRodney W. Grimes setpwent()
21958f0484fSRodney W. Grimes {
22058f0484fSRodney W. Grimes 	_pw_keynum = 0;
221d5b7518dSGarrett Wollman #ifdef YP
22294c53e1fSBill Paul 	_pw_stepping_yp = 0;
223d5b7518dSGarrett Wollman #endif
22458f0484fSRodney W. Grimes 	_pw_stayopen = 0;
22558f0484fSRodney W. Grimes 	return(1);
22658f0484fSRodney W. Grimes }
22758f0484fSRodney W. Grimes 
22858f0484fSRodney W. Grimes void
22958f0484fSRodney W. Grimes endpwent()
23058f0484fSRodney W. Grimes {
23158f0484fSRodney W. Grimes 	_pw_keynum = 0;
232d5b7518dSGarrett Wollman #ifdef YP
23394c53e1fSBill Paul 	_pw_stepping_yp = 0;
234d5b7518dSGarrett Wollman #endif
23558f0484fSRodney W. Grimes 	if (_pw_db) {
23658f0484fSRodney W. Grimes 		(void)(_pw_db->close)(_pw_db);
23758f0484fSRodney W. Grimes 		_pw_db = (DB *)NULL;
23858f0484fSRodney W. Grimes 	}
23994c53e1fSBill Paul #ifdef YP
24094c53e1fSBill Paul 	if (_ypcache) {
24194c53e1fSBill Paul 		(void)(_ypcache->close)(_ypcache);
24294c53e1fSBill Paul 		_ypcache = (DB *)NULL;
24394c53e1fSBill Paul 		_yp_exclusions = 0;
24494c53e1fSBill Paul 	}
24594c53e1fSBill Paul #endif
24658f0484fSRodney W. Grimes }
24758f0484fSRodney W. Grimes 
24851295a4dSJordan K. Hubbard static int
24958f0484fSRodney W. Grimes __initdb()
25058f0484fSRodney W. Grimes {
25158f0484fSRodney W. Grimes 	static int warned;
25258f0484fSRodney W. Grimes 	char *p;
25358f0484fSRodney W. Grimes 
25458f0484fSRodney W. Grimes 	p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB;
25558f0484fSRodney W. Grimes 	_pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL);
256d5b7518dSGarrett Wollman 	if (_pw_db) {
257d5b7518dSGarrett Wollman #ifdef YP
258d5b7518dSGarrett Wollman 		DBT key, data;
259d5b7518dSGarrett Wollman 		char buf[] = { _PW_KEYYPENABLED };
260d5b7518dSGarrett Wollman 		key.data = buf;
261d5b7518dSGarrett Wollman 		key.size = 1;
262d5b7518dSGarrett Wollman 		if ((_pw_db->get)(_pw_db, &key, &data, 0)) {
263d5b7518dSGarrett Wollman 			_yp_enabled = 0;
264d5b7518dSGarrett Wollman 		} else {
265468bb86aSGarrett Wollman 			_yp_enabled = (int)*((char *)data.data) - 2;
2663948edc2SBill Paul 		/* Don't even bother with this if we aren't root. */
2673948edc2SBill Paul 			if (!geteuid()) {
2683948edc2SBill Paul 				if (!_pw_yp_domain)
2693948edc2SBill Paul 					if (yp_get_default_domain(&_pw_yp_domain))
2703948edc2SBill Paul 					return(1);
2713948edc2SBill Paul 				_gotmaster = _havemaster(_pw_yp_domain);
2722be5d4cbSBill Paul 			} else _gotmaster = YP_HAVE_NONE;
27394c53e1fSBill Paul 			if (!_ypcache)
27494c53e1fSBill Paul 				_ypinitdb();
275d5b7518dSGarrett Wollman 		}
276d5b7518dSGarrett Wollman #endif
27758f0484fSRodney W. Grimes 		return(1);
278d5b7518dSGarrett Wollman 	}
27988ce2dd1SBill Paul 	if (!warned++)
28058f0484fSRodney W. Grimes 		syslog(LOG_ERR, "%s: %m", p);
28158f0484fSRodney W. Grimes 	return(0);
28258f0484fSRodney W. Grimes }
28358f0484fSRodney W. Grimes 
28451295a4dSJordan K. Hubbard static int
28558f0484fSRodney W. Grimes __hashpw(key)
28658f0484fSRodney W. Grimes 	DBT *key;
28758f0484fSRodney W. Grimes {
28858f0484fSRodney W. Grimes 	register char *p, *t;
28958f0484fSRodney W. Grimes 	static u_int max;
29058f0484fSRodney W. Grimes 	static char *line;
29158f0484fSRodney W. Grimes 	DBT data;
29258f0484fSRodney W. Grimes 
2935f115c9dSBill Paul 	if ((_pw_db->get)(_pw_db, key, &data, 0))
29458f0484fSRodney W. Grimes 		return(0);
29558f0484fSRodney W. Grimes 	p = (char *)data.data;
2968be26e5dSWolfram Schneider 
2978be26e5dSWolfram Schneider 	/* increase buffer size for long lines if necessary */
2988be26e5dSWolfram Schneider 	if (data.size > max) {
2998be26e5dSWolfram Schneider 		max = data.size + 1024;
3008be26e5dSWolfram Schneider                 if (!(line = realloc(line, max)))
30158f0484fSRodney W. Grimes                         return(0);
3028be26e5dSWolfram Schneider         }
30358f0484fSRodney W. Grimes 
304adf6ad9eSPeter Wemm 	/* THIS CODE MUST MATCH THAT IN pwd_mkdb. */
30558f0484fSRodney W. Grimes 	t = line;
30651295a4dSJordan K. Hubbard #define	EXPAND(e)	e = t; while ( (*t++ = *p++) );
307adf6ad9eSPeter Wemm #define	SCALAR(v)	memmove(&(v), p, sizeof v); p += sizeof v
30858f0484fSRodney W. Grimes 	EXPAND(_pw_passwd.pw_name);
30958f0484fSRodney W. Grimes 	EXPAND(_pw_passwd.pw_passwd);
310adf6ad9eSPeter Wemm 	SCALAR(_pw_passwd.pw_uid);
311adf6ad9eSPeter Wemm 	SCALAR(_pw_passwd.pw_gid);
312adf6ad9eSPeter Wemm 	SCALAR(_pw_passwd.pw_change);
31358f0484fSRodney W. Grimes 	EXPAND(_pw_passwd.pw_class);
31458f0484fSRodney W. Grimes 	EXPAND(_pw_passwd.pw_gecos);
31558f0484fSRodney W. Grimes 	EXPAND(_pw_passwd.pw_dir);
31658f0484fSRodney W. Grimes 	EXPAND(_pw_passwd.pw_shell);
317adf6ad9eSPeter Wemm 	SCALAR(_pw_passwd.pw_expire);
318d5b7518dSGarrett Wollman 	bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields);
319d5b7518dSGarrett Wollman 	p += sizeof _pw_passwd.pw_fields;
32058f0484fSRodney W. Grimes 	return(1);
32158f0484fSRodney W. Grimes }
322d5b7518dSGarrett Wollman 
323d5b7518dSGarrett Wollman #ifdef YP
32494c53e1fSBill Paul 
3259531ca93SBill Paul /*
32694c53e1fSBill Paul  * Create a DB hash database in memory. Bet you didn't know you
32794c53e1fSBill Paul  * could do a dbopen() will a NULL filename, did you.
3289531ca93SBill Paul  */
32994c53e1fSBill Paul static inline void _ypinitdb()
3309531ca93SBill Paul {
33194c53e1fSBill Paul 	if (_ypcache == (DB *)NULL)
33294c53e1fSBill Paul 		_ypcache = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL);
33389395683SBill Paul 	return;
3349531ca93SBill Paul }
3359531ca93SBill Paul 
3369531ca93SBill Paul /*
33794c53e1fSBill Paul  * See if a user is in the blackballed list.
3389531ca93SBill Paul  */
33994c53e1fSBill Paul static inline int lookup(name)
34094c53e1fSBill Paul 	char *name;
3419531ca93SBill Paul {
34294c53e1fSBill Paul 	DBT key;
3439531ca93SBill Paul 
34494c53e1fSBill Paul 	if (!_yp_exclusions)
34594c53e1fSBill Paul 		return(0);
34694c53e1fSBill Paul 
34794c53e1fSBill Paul 	key.data = name;
34894c53e1fSBill Paul 	key.size = strlen(name);
34994c53e1fSBill Paul 
35094c53e1fSBill Paul 	if ((_ypcache->get)(_ypcache, &key, &empty, 0)) {
35194c53e1fSBill Paul 		return(0);
3529531ca93SBill Paul 	}
3539531ca93SBill Paul 
354d454389cSBill Paul 	return(1);
355d454389cSBill Paul }
35694c53e1fSBill Paul 
35794c53e1fSBill Paul /*
35894c53e1fSBill Paul  * Store a blackballed user in an in-core hash database.
35994c53e1fSBill Paul  */
36094c53e1fSBill Paul static inline void store(key)
36194c53e1fSBill Paul 	char *key;
36294c53e1fSBill Paul {
36394c53e1fSBill Paul 	DBT lkey;
36494c53e1fSBill Paul /*
36594c53e1fSBill Paul 	if (lookup(key))
36694c53e1fSBill Paul 		return;
36794c53e1fSBill Paul */
36894c53e1fSBill Paul 
36994c53e1fSBill Paul 	_yp_exclusions = 1;
37094c53e1fSBill Paul 
37194c53e1fSBill Paul 	lkey.data = key;
37294c53e1fSBill Paul 	lkey.size = strlen(key);
37394c53e1fSBill Paul 
37494c53e1fSBill Paul 	(void)(_ypcache->put)(_ypcache, &lkey, &empty, R_NOOVERWRITE);
37594c53e1fSBill Paul }
37694c53e1fSBill Paul 
37794c53e1fSBill Paul /*
37894c53e1fSBill Paul  * Parse the + entries in the password database and do appropriate
37994c53e1fSBill Paul  * NIS lookups. While ugly to look at, this is optimized to do only
38094c53e1fSBill Paul  * as many lookups as are absolutely necessary in any given case.
38194c53e1fSBill Paul  * Basically, the getpwent() function will feed us + and - lines
38294c53e1fSBill Paul  * as they appear in the database. For + lines, we do netgroup/group
38394c53e1fSBill Paul  * and user lookups to find all usernames that match the rule and
38494c53e1fSBill Paul  * extract them from the NIS passwd maps. For - lines, we save the
38594c53e1fSBill Paul  * matching names in a database and a) exlude them, and b) make sure
38694c53e1fSBill Paul  * we don't consider them when processing other + lines that appear
38794c53e1fSBill Paul  * later.
38894c53e1fSBill Paul  */
38994c53e1fSBill Paul static inline int unwind(grp)
39094c53e1fSBill Paul 	char *grp;
39194c53e1fSBill Paul {
39294c53e1fSBill Paul 	char *user, *host, *domain;
39394c53e1fSBill Paul 	static int latch = 0;
39494c53e1fSBill Paul 	static struct group *gr = NULL;
39594c53e1fSBill Paul 	int rv = 0;
39694c53e1fSBill Paul 
39794c53e1fSBill Paul 	if (grp[0] == '+') {
39894c53e1fSBill Paul 		if (strlen(grp) == 1) {
39994c53e1fSBill Paul 			return(_nextyppass(&_pw_passwd));
40094c53e1fSBill Paul 		}
40194c53e1fSBill Paul 		if (grp[1] == '@') {
40294c53e1fSBill Paul 			_pw_stepping_yp = 1;
40394c53e1fSBill Paul grpagain:
40494c53e1fSBill Paul 			if (gr != NULL) {
40594c53e1fSBill Paul 				if (*gr->gr_mem != NULL) {
40694c53e1fSBill Paul 					if (lookup(*gr->gr_mem)) {
40794c53e1fSBill Paul 						gr->gr_mem++;
40894c53e1fSBill Paul 						goto grpagain;
40994c53e1fSBill Paul 					}
41094c53e1fSBill Paul 					rv = _getyppass(&_pw_passwd,
41194c53e1fSBill Paul 							*gr->gr_mem,
41294c53e1fSBill Paul 							"passwd.byname");
41394c53e1fSBill Paul 					gr->gr_mem++;
41494c53e1fSBill Paul 					return(rv);
41594c53e1fSBill Paul 				} else {
41694c53e1fSBill Paul 					endgrent();
41794c53e1fSBill Paul 					latch = 0;
41894c53e1fSBill Paul 					gr = NULL;
41994c53e1fSBill Paul 					return(0);
420d454389cSBill Paul 				}
421d454389cSBill Paul 			}
42294c53e1fSBill Paul 			if (!latch) {
42394c53e1fSBill Paul 				setnetgrent(grp+2);
42494c53e1fSBill Paul 				latch++;
425d454389cSBill Paul 			}
42694c53e1fSBill Paul again:
42794c53e1fSBill Paul 			if (getnetgrent(&host, &user, &domain) == NULL) {
42894c53e1fSBill Paul 				if ((gr = getgrnam(grp+2)) != NULL)
42994c53e1fSBill Paul 					goto grpagain;
43094c53e1fSBill Paul 				latch = 0;
43194c53e1fSBill Paul 				_pw_stepping_yp = 0;
43294c53e1fSBill Paul 				return(0);
43394c53e1fSBill Paul 			} else {
43494c53e1fSBill Paul 				if (lookup(user))
43594c53e1fSBill Paul 					goto again;
43694c53e1fSBill Paul 				if (_getyppass(&_pw_passwd, user,
43794c53e1fSBill Paul 							"passwd.byname"))
43894c53e1fSBill Paul 					return(1);
43994c53e1fSBill Paul 				else
44094c53e1fSBill Paul 					goto again;
441d454389cSBill Paul 			}
44294c53e1fSBill Paul 		} else {
44394c53e1fSBill Paul 			if (lookup(grp+1))
44494c53e1fSBill Paul 				return(0);
44594c53e1fSBill Paul 			return(_getyppass(&_pw_passwd, grp+1, "passwd.byname"));
44694c53e1fSBill Paul 		}
44794c53e1fSBill Paul 	} else {
44894c53e1fSBill Paul 		if (grp[1] == '@') {
44994c53e1fSBill Paul 			setnetgrent(grp+2);
45094c53e1fSBill Paul 			rv = 0;
45194c53e1fSBill Paul 			while(getnetgrent(&host, &user, &domain) != NULL) {
45294c53e1fSBill Paul 				store(user);
45394c53e1fSBill Paul 				rv++;
45494c53e1fSBill Paul 			}
45594c53e1fSBill Paul 			if (!rv && (gr = getgrnam(grp+2)) != NULL) {
45694c53e1fSBill Paul 				while(gr->gr_mem) {
45794c53e1fSBill Paul 					store(gr->gr_mem);
45894c53e1fSBill Paul 					gr->gr_mem++;
45994c53e1fSBill Paul 				}
46094c53e1fSBill Paul 			}
46194c53e1fSBill Paul 		} else {
46294c53e1fSBill Paul 			store(grp+1);
46394c53e1fSBill Paul 		}
46494c53e1fSBill Paul 	}
46594c53e1fSBill Paul 	return(0);
46694c53e1fSBill Paul }
46794c53e1fSBill Paul 
46894c53e1fSBill Paul /*
46994c53e1fSBill Paul  * See if a user is a member of a particular group.
47094c53e1fSBill Paul  */
47194c53e1fSBill Paul static inline int ingr(grp, name)
47294c53e1fSBill Paul 	char *grp;
47394c53e1fSBill Paul 	char *name;
47494c53e1fSBill Paul {
47594c53e1fSBill Paul 	register struct group *gr;
47694c53e1fSBill Paul 
47794c53e1fSBill Paul 	if ((gr = getgrnam(grp)) == NULL)
47894c53e1fSBill Paul 		return(0);
47994c53e1fSBill Paul 
48094c53e1fSBill Paul 	while(*gr->gr_mem) {
48194c53e1fSBill Paul 		if (!strcmp(*gr->gr_mem, name)) {
48294c53e1fSBill Paul 			endgrent();
48394c53e1fSBill Paul 			return(1);
48494c53e1fSBill Paul 		}
48594c53e1fSBill Paul 		gr->gr_mem++;
48694c53e1fSBill Paul 	}
48794c53e1fSBill Paul 
48894c53e1fSBill Paul 	endgrent();
48994c53e1fSBill Paul 	return(0);
49094c53e1fSBill Paul }
49194c53e1fSBill Paul 
49294c53e1fSBill Paul /*
49394c53e1fSBill Paul  * Check a user against the +@netgroup/-@netgroup lines listed in
49494c53e1fSBill Paul  * the local password database. Also checks +user/-user lines.
49594c53e1fSBill Paul  * If no netgroup exists that matches +@netgroup/-@netgroup,
49694c53e1fSBill Paul  * try searching regular groups with the same name.
49794c53e1fSBill Paul  */
49894c53e1fSBill Paul static inline int verf(name)
49994c53e1fSBill Paul 	char *name;
50094c53e1fSBill Paul {
50194c53e1fSBill Paul 	DBT key;
50294c53e1fSBill Paul 	char bf[sizeof(_pw_keynum) + 1];
50394c53e1fSBill Paul 	int keynum = 0;
50494c53e1fSBill Paul 
50594c53e1fSBill Paul again:
50694c53e1fSBill Paul 	++keynum;
50794c53e1fSBill Paul 	bf[0] = _PW_KEYYPBYNUM;
50894c53e1fSBill Paul 	bcopy((char *)&keynum, bf + 1, sizeof(keynum));
50994c53e1fSBill Paul 	key.data = (u_char *)bf;
51094c53e1fSBill Paul 	key.size = sizeof(keynum) + 1;
51194c53e1fSBill Paul 	if (!__hashpw(&key)) {
51294c53e1fSBill Paul 		/* Try again using old format */
51394c53e1fSBill Paul 		bf[0] = _PW_KEYBYNUM;
51494c53e1fSBill Paul 		bcopy((char *)&keynum, bf + 1, sizeof(keynum));
51594c53e1fSBill Paul 		key.data = (u_char *)bf;
51694c53e1fSBill Paul 		if (!__hashpw(&key))
51794c53e1fSBill Paul 			return(0);
51894c53e1fSBill Paul 	}
51994c53e1fSBill Paul 	if (_pw_passwd.pw_name[0] != '+' && (_pw_passwd.pw_name[0] != '-'))
52094c53e1fSBill Paul 		goto again;
52194c53e1fSBill Paul 	if (_pw_passwd.pw_name[0] == '+') {
52294c53e1fSBill Paul 		if (strlen(_pw_passwd.pw_name) == 1) /* Wildcard */
52394c53e1fSBill Paul 			return(1);
52494c53e1fSBill Paul 		if (_pw_passwd.pw_name[1] == '@') {
52594c53e1fSBill Paul 			if ((innetgr(_pw_passwd.pw_name+2, NULL, name,
52694c53e1fSBill Paul 							_pw_yp_domain) ||
52794c53e1fSBill Paul 			    ingr(_pw_passwd.pw_name+2, name)) && !lookup(name))
52894c53e1fSBill Paul 				return(1);
52994c53e1fSBill Paul 			else
53094c53e1fSBill Paul 				goto again;
53194c53e1fSBill Paul 		} else {
53294c53e1fSBill Paul 			if (!strcmp(name, _pw_passwd.pw_name+1) &&
53394c53e1fSBill Paul 								!lookup(name))
53494c53e1fSBill Paul 				return(1);
53594c53e1fSBill Paul 			else
53694c53e1fSBill Paul 				goto again;
53794c53e1fSBill Paul 		}
53894c53e1fSBill Paul 	}
53994c53e1fSBill Paul 	if (_pw_passwd.pw_name[0] == '-') {
54094c53e1fSBill Paul 		/* Note that a minus wildcard is a no-op. */
54194c53e1fSBill Paul 		if (_pw_passwd.pw_name[1] == '@') {
54294c53e1fSBill Paul 			if (innetgr(_pw_passwd.pw_name+2, NULL, name,
54394c53e1fSBill Paul 							_pw_yp_domain) ||
54494c53e1fSBill Paul 			    ingr(_pw_passwd.pw_name+2, name)) {
54594c53e1fSBill Paul 				store(name);
54694c53e1fSBill Paul 				return(0);
54794c53e1fSBill Paul 			} else
54894c53e1fSBill Paul 				goto again;
54994c53e1fSBill Paul 		} else {
55094c53e1fSBill Paul 			if (!strcmp(name, _pw_passwd.pw_name+1)) {
55194c53e1fSBill Paul 				store(name);
55294c53e1fSBill Paul 				return(0);
55394c53e1fSBill Paul 			} else
55494c53e1fSBill Paul 				goto again;
55594c53e1fSBill Paul 		}
55694c53e1fSBill Paul 
557d454389cSBill Paul 	}
558d454389cSBill Paul 	return(0);
559d454389cSBill Paul }
560d454389cSBill Paul 
5612be5d4cbSBill Paul static char * _get_adjunct_pw(name)
5622be5d4cbSBill Paul 	char *name;
5632be5d4cbSBill Paul {
5642be5d4cbSBill Paul 	static char adjunctbuf[YPMAXRECORD+2];
5652be5d4cbSBill Paul 	int rval;
5662be5d4cbSBill Paul 	char *result;
5672be5d4cbSBill Paul 	int resultlen;
5682be5d4cbSBill Paul 	char *map = "passwd.adjunct.byname";
5692be5d4cbSBill Paul 	char *s;
5702be5d4cbSBill Paul 
5712be5d4cbSBill Paul 	if ((rval = yp_match(_pw_yp_domain, map, name, strlen(name),
5722be5d4cbSBill Paul 		    &result, &resultlen)))
5732be5d4cbSBill Paul 		return(NULL);
5742be5d4cbSBill Paul 
5751d2493ffSBill Paul 	strncpy(adjunctbuf, result, resultlen);
5761d2493ffSBill Paul 	adjunctbuf[resultlen] = '\0';
5772be5d4cbSBill Paul 	free(result);
5782be5d4cbSBill Paul 	result = (char *)&adjunctbuf;
5792be5d4cbSBill Paul 
5802be5d4cbSBill Paul 	/* Don't care about the name. */
5812be5d4cbSBill Paul 	if ((s = strsep(&result, ":")) == NULL)
5822be5d4cbSBill Paul 		return (NULL); /* name */
5832be5d4cbSBill Paul 	if ((s = strsep(&result, ":")) == NULL)
5842be5d4cbSBill Paul 		return (NULL); /* password */
5852be5d4cbSBill Paul 
5862be5d4cbSBill Paul 	return(s);
5872be5d4cbSBill Paul }
5882be5d4cbSBill Paul 
5896c0828a6SBill Paul static int
5901d2493ffSBill Paul _pw_breakout_yp(struct passwd *pw, char *res, int resultlen, int master)
591d5b7518dSGarrett Wollman {
5928b102407SPoul-Henning Kamp 	char *s, *result;
5933948edc2SBill Paul 	static char resbuf[YPMAXRECORD+2];
594d3628763SRodney W. Grimes 
5953948edc2SBill Paul 	/*
5963948edc2SBill Paul 	 * Be triple, ultra super-duper paranoid: reject entries
5973948edc2SBill Paul 	 * that start with a + or -. yp_mkdb and /var/yp/Makefile
5983948edc2SBill Paul 	 * are _both_ supposed to strip these out, but you never
5993948edc2SBill Paul 	 * know.
6003948edc2SBill Paul 	 */
6013948edc2SBill Paul 	if (*res == '+' || *res == '-')
6023948edc2SBill Paul 		return 0;
6033948edc2SBill Paul 
6043948edc2SBill Paul 	/*
6053948edc2SBill Paul 	 * The NIS protocol definition limits the size of an NIS
6063948edc2SBill Paul 	 * record to YPMAXRECORD bytes. We need to do a copy to
6073948edc2SBill Paul 	 * a static buffer here since the memory pointed to by
6083948edc2SBill Paul 	 * res will be free()ed when this function returns.
6093948edc2SBill Paul 	 */
6101d2493ffSBill Paul 	strncpy((char *)&resbuf, res, resultlen);
6111d2493ffSBill Paul 	resbuf[resultlen] = '\0';
6123948edc2SBill Paul 	result = (char *)&resbuf;
613d5b7518dSGarrett Wollman 
6146c0828a6SBill Paul 	/*
6156c0828a6SBill Paul 	 * XXX Sanity check: make sure all fields are valid (no NULLs).
6166c0828a6SBill Paul 	 * If we find a badly formatted entry, we punt.
6176c0828a6SBill Paul 	 */
6186c0828a6SBill Paul 	if ((s = strsep(&result, ":")) == NULL) return 0; /* name */
6193948edc2SBill Paul 	/*
6203948edc2SBill Paul 	 * We don't care what pw_fields says: we _always_ want the
6213948edc2SBill Paul 	 * username returned to us by NIS.
6223948edc2SBill Paul 	 */
623d5b7518dSGarrett Wollman 	pw->pw_name = s;
624d5b7518dSGarrett Wollman 	pw->pw_fields |= _PWF_NAME;
625d5b7518dSGarrett Wollman 
6266c0828a6SBill Paul 	if ((s = strsep(&result, ":")) == NULL) return 0; /* password */
627d5b7518dSGarrett Wollman 	if(!(pw->pw_fields & _PWF_PASSWD)) {
6282be5d4cbSBill Paul 		/* SunOS passwd.adjunct hack */
62909e84628SBill Paul 		if (master == YP_HAVE_ADJUNCT && strstr(s, "##") != NULL) {
6302be5d4cbSBill Paul 			char *realpw;
6312be5d4cbSBill Paul 			realpw = _get_adjunct_pw(pw->pw_name);
6322be5d4cbSBill Paul 			if (realpw == NULL)
633d5b7518dSGarrett Wollman 				pw->pw_passwd = s;
6342be5d4cbSBill Paul 			else
6352be5d4cbSBill Paul 				pw->pw_passwd = realpw;
6362be5d4cbSBill Paul 		} else {
6372be5d4cbSBill Paul 			pw->pw_passwd = s;
6382be5d4cbSBill Paul 		}
639d5b7518dSGarrett Wollman 		pw->pw_fields |= _PWF_PASSWD;
640d5b7518dSGarrett Wollman 	}
641d5b7518dSGarrett Wollman 
6426c0828a6SBill Paul 	if ((s = strsep(&result, ":")) == NULL) return 0; /* uid */
643d5b7518dSGarrett Wollman 	if(!(pw->pw_fields & _PWF_UID)) {
644d5b7518dSGarrett Wollman 		pw->pw_uid = atoi(s);
645d5b7518dSGarrett Wollman 		pw->pw_fields |= _PWF_UID;
646d5b7518dSGarrett Wollman 	}
647d5b7518dSGarrett Wollman 
6486c0828a6SBill Paul 	if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */
649d5b7518dSGarrett Wollman 	if(!(pw->pw_fields & _PWF_GID))  {
650d5b7518dSGarrett Wollman 		pw->pw_gid = atoi(s);
651d5b7518dSGarrett Wollman 		pw->pw_fields |= _PWF_GID;
652d5b7518dSGarrett Wollman 	}
653d5b7518dSGarrett Wollman 
6542be5d4cbSBill Paul 	if (master == YP_HAVE_MASTER) {
6556c0828a6SBill Paul 		if ((s = strsep(&result, ":")) == NULL) return 0; /* class */
656d0ef6688SBill Paul 		if(!(pw->pw_fields & _PWF_CLASS))  {
657d0ef6688SBill Paul 			pw->pw_class = s;
658d0ef6688SBill Paul 			pw->pw_fields |= _PWF_CLASS;
659d0ef6688SBill Paul 		}
660d0ef6688SBill Paul 
6616c0828a6SBill Paul 		if ((s = strsep(&result, ":")) == NULL) return 0; /* change */
662d0ef6688SBill Paul 		if(!(pw->pw_fields & _PWF_CHANGE))  {
663d0ef6688SBill Paul 			pw->pw_change = atol(s);
664d0ef6688SBill Paul 			pw->pw_fields |= _PWF_CHANGE;
665d0ef6688SBill Paul 		}
666d0ef6688SBill Paul 
6676c0828a6SBill Paul 		if ((s = strsep(&result, ":")) == NULL) return 0; /* expire */
668d0ef6688SBill Paul 		if(!(pw->pw_fields & _PWF_EXPIRE))  {
669d0ef6688SBill Paul 			pw->pw_expire = atol(s);
670d0ef6688SBill Paul 			pw->pw_fields |= _PWF_EXPIRE;
671d0ef6688SBill Paul 		}
672d66efc62SBill Paul 	}
673d0ef6688SBill Paul 
6746c0828a6SBill Paul 	if ((s = strsep(&result, ":")) == NULL) return 0; /* gecos */
675d0ef6688SBill Paul 	if(!(pw->pw_fields & _PWF_GECOS)) {
676d0ef6688SBill Paul 		pw->pw_gecos = s;
677d0ef6688SBill Paul 		pw->pw_fields |= _PWF_GECOS;
678d0ef6688SBill Paul 	}
679d0ef6688SBill Paul 
6806c0828a6SBill Paul 	if ((s = strsep(&result, ":")) == NULL) return 0; /* dir */
681d0ef6688SBill Paul 	if(!(pw->pw_fields & _PWF_DIR)) {
682d0ef6688SBill Paul 		pw->pw_dir = s;
683d0ef6688SBill Paul 		pw->pw_fields |= _PWF_DIR;
684d0ef6688SBill Paul 	}
685d0ef6688SBill Paul 
6866c0828a6SBill Paul 	if ((s = strsep(&result, ":")) == NULL) return 0; /* shell */
687d0ef6688SBill Paul 	if(!(pw->pw_fields & _PWF_SHELL)) {
688d0ef6688SBill Paul 		pw->pw_shell = s;
689d0ef6688SBill Paul 		pw->pw_fields |= _PWF_SHELL;
690d0ef6688SBill Paul 	}
6916c0828a6SBill Paul 
6923948edc2SBill Paul 	/* Be consistent. */
6933948edc2SBill Paul 	if ((s = strchr(pw->pw_shell, '\n'))) *s = '\0';
6943948edc2SBill Paul 
6956c0828a6SBill Paul 	return 1;
696d0ef6688SBill Paul }
697d0ef6688SBill Paul 
698d5b7518dSGarrett Wollman static int
699c333ae82SDavid Nugent _havemaster(char *_yp_domain)
700d0ef6688SBill Paul {
7012be5d4cbSBill Paul 	int order;
7022be5d4cbSBill Paul 	int rval;
703d0ef6688SBill Paul 
704c333ae82SDavid Nugent 	if (!(rval = yp_order(_yp_domain, "master.passwd.byname", &order)))
7052be5d4cbSBill Paul 		return(YP_HAVE_MASTER);
7062be5d4cbSBill Paul 
7072be5d4cbSBill Paul 	/*
7082be5d4cbSBill Paul 	 * NIS+ in YP compat mode doesn't support
7092be5d4cbSBill Paul 	 * YPPROC_ORDER -- no point in continuing.
7102be5d4cbSBill Paul 	 */
7112be5d4cbSBill Paul 	if (rval == YPERR_YPERR)
7122be5d4cbSBill Paul 		return(YP_HAVE_NONE);
7132be5d4cbSBill Paul 
7142be5d4cbSBill Paul 	/* master.passwd doesn't exist -- try passwd.adjunct */
7152be5d4cbSBill Paul 	if (rval == YPERR_MAP) {
716c333ae82SDavid Nugent 		rval = yp_order(_yp_domain, "passwd.adjunct.byname", &order);
7172be5d4cbSBill Paul 		if (!rval)
7182be5d4cbSBill Paul 			return(YP_HAVE_ADJUNCT);
719b38bb6d3SBill Paul 	}
7202be5d4cbSBill Paul 
7212be5d4cbSBill Paul 	return (YP_HAVE_NONE);
722d0ef6688SBill Paul }
723d0ef6688SBill Paul 
724d0ef6688SBill Paul static int
725d5b7518dSGarrett Wollman _getyppass(struct passwd *pw, const char *name, const char *map)
726d5b7518dSGarrett Wollman {
727d5b7518dSGarrett Wollman 	char *result, *s;
728d5b7518dSGarrett Wollman 	int resultlen;
7293948edc2SBill Paul 	int rv;
73094c53e1fSBill Paul 	char mastermap[YPMAXRECORD];
731d5b7518dSGarrett Wollman 
732d5b7518dSGarrett Wollman 	if(!_pw_yp_domain) {
733d5b7518dSGarrett Wollman 		if(yp_get_default_domain(&_pw_yp_domain))
734d5b7518dSGarrett Wollman 		  return 0;
735d5b7518dSGarrett Wollman 	}
736d5b7518dSGarrett Wollman 
737d0ef6688SBill Paul 	sprintf(mastermap,"%s",map);
738d0ef6688SBill Paul 
7392be5d4cbSBill Paul 	if (_gotmaster == YP_HAVE_MASTER)
740320ce7b7SBill Paul 		sprintf(mastermap,"master.%s", map);
741d0ef6688SBill Paul 
742958f4e36SBill Paul 	if(yp_match(_pw_yp_domain, (char *)&mastermap, name, strlen(name),
743d5b7518dSGarrett Wollman 		    &result, &resultlen))
744d5b7518dSGarrett Wollman 		return 0;
745d5b7518dSGarrett Wollman 
74694c53e1fSBill Paul 	if (!_pw_stepping_yp) {
7473948edc2SBill Paul 		s = strchr(result, ':');
7483948edc2SBill Paul 		if (s) {
7493948edc2SBill Paul 			*s = '\0';
7503948edc2SBill Paul 		} else {
7513948edc2SBill Paul 			/* Must be a malformed entry if no colons. */
7523948edc2SBill Paul 			free(result);
7533948edc2SBill Paul 			return(0);
7543948edc2SBill Paul 		}
75594c53e1fSBill Paul 
75694c53e1fSBill Paul 		if (!verf(result)) {
75794c53e1fSBill Paul 			*s = ':';
7589531ca93SBill Paul 			free(result);
7599531ca93SBill Paul 			return(0);
7603948edc2SBill Paul 		}
76194c53e1fSBill Paul 
7623948edc2SBill Paul 		*s = ':'; /* Put back the colon we previously replaced with a NUL. */
76394c53e1fSBill Paul 	}
76494c53e1fSBill Paul 
7651d2493ffSBill Paul 	rv = _pw_breakout_yp(pw, result, resultlen, _gotmaster);
7663948edc2SBill Paul 	free(result);
7673948edc2SBill Paul 	return(rv);
768d5b7518dSGarrett Wollman }
769d5b7518dSGarrett Wollman 
770d5b7518dSGarrett Wollman static int
771d5b7518dSGarrett Wollman _nextyppass(struct passwd *pw)
772d5b7518dSGarrett Wollman {
773958f4e36SBill Paul 	static char *key;
774d5b7518dSGarrett Wollman 	static int keylen;
7753948edc2SBill Paul 	char *lastkey, *result, *s;
776d5b7518dSGarrett Wollman 	int resultlen;
777d5b7518dSGarrett Wollman 	int rv;
778d0ef6688SBill Paul 	char *map = "passwd.byname";
779d5b7518dSGarrett Wollman 
780d5b7518dSGarrett Wollman 	if(!_pw_yp_domain) {
781d5b7518dSGarrett Wollman 		if(yp_get_default_domain(&_pw_yp_domain))
782d5b7518dSGarrett Wollman 		  return 0;
783d5b7518dSGarrett Wollman 	}
784d5b7518dSGarrett Wollman 
7852be5d4cbSBill Paul 	if (_gotmaster == YP_HAVE_MASTER)
786d0ef6688SBill Paul 		map = "master.passwd.byname";
787d0ef6688SBill Paul 
788d5b7518dSGarrett Wollman 	if(!_pw_stepping_yp) {
789d5b7518dSGarrett Wollman 		if(key) free(key);
790d0ef6688SBill Paul 			rv = yp_first(_pw_yp_domain, map,
791d5b7518dSGarrett Wollman 				      &key, &keylen, &result, &resultlen);
792d5b7518dSGarrett Wollman 		if(rv) {
793d5b7518dSGarrett Wollman 			return 0;
794d5b7518dSGarrett Wollman 		}
795d5b7518dSGarrett Wollman 		_pw_stepping_yp = 1;
796d5b7518dSGarrett Wollman 		goto unpack;
797d5b7518dSGarrett Wollman 	} else {
798d5b7518dSGarrett Wollman tryagain:
799d5b7518dSGarrett Wollman 		lastkey = key;
800d0ef6688SBill Paul 			rv = yp_next(_pw_yp_domain, map, key, keylen,
801d5b7518dSGarrett Wollman 			     &key, &keylen, &result, &resultlen);
802d5b7518dSGarrett Wollman 		free(lastkey);
803d5b7518dSGarrett Wollman unpack:
804d5b7518dSGarrett Wollman 		if(rv) {
805d5b7518dSGarrett Wollman 			_pw_stepping_yp = 0;
806d5b7518dSGarrett Wollman 			return 0;
807d5b7518dSGarrett Wollman 		}
808d5b7518dSGarrett Wollman 
8093948edc2SBill Paul 		s = strchr(result, ':');
8103948edc2SBill Paul 		if (s) {
8113948edc2SBill Paul 			*s = '\0';
8123948edc2SBill Paul 		} else {
81394c53e1fSBill Paul 			/* Must be a malformed entry if no colons. */
814d5b7518dSGarrett Wollman 			free(result);
815d5b7518dSGarrett Wollman 			goto tryagain;
816d5b7518dSGarrett Wollman 		}
81794c53e1fSBill Paul 
81894c53e1fSBill Paul 		if (lookup(result)) {
81994c53e1fSBill Paul 			*s = ':';
8209531ca93SBill Paul 			free(result);
8219531ca93SBill Paul 			goto tryagain;
8223948edc2SBill Paul 		}
82394c53e1fSBill Paul 
82494c53e1fSBill Paul 		*s = ':'; /* Put back the colon we previously replaced with a NUL. */
8251d2493ffSBill Paul 		if (_pw_breakout_yp(pw, result, resultlen, _gotmaster)) {
8263948edc2SBill Paul 			free(result);
827400b8413SBill Paul 			return(1);
8283948edc2SBill Paul 		} else {
8293948edc2SBill Paul 			free(result);
830400b8413SBill Paul 			goto tryagain;
831d5b7518dSGarrett Wollman 		}
832d5b7518dSGarrett Wollman 	}
8333948edc2SBill Paul }
834d5b7518dSGarrett Wollman 
835d5b7518dSGarrett Wollman #endif /* YP */
836