xref: /minix3/lib/libc/gen/getpwent.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*f14fb602SLionel Sambuc /*	$NetBSD: getpwent.c,v 1.81 2012/09/08 15:15:06 dholland Exp $	*/
22fe8fb19SBen Gras 
32fe8fb19SBen Gras /*-
42fe8fb19SBen Gras  * Copyright (c) 1997-2000, 2004-2005 The NetBSD Foundation, Inc.
52fe8fb19SBen Gras  * All rights reserved.
62fe8fb19SBen Gras  *
72fe8fb19SBen Gras  * This code is derived from software contributed to The NetBSD Foundation
82fe8fb19SBen Gras  * by Luke Mewburn.
92fe8fb19SBen Gras  *
102fe8fb19SBen Gras  * Redistribution and use in source and binary forms, with or without
112fe8fb19SBen Gras  * modification, are permitted provided that the following conditions
122fe8fb19SBen Gras  * are met:
132fe8fb19SBen Gras  * 1. Redistributions of source code must retain the above copyright
142fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer.
152fe8fb19SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
162fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer in the
172fe8fb19SBen Gras  *    documentation and/or other materials provided with the distribution.
182fe8fb19SBen Gras  *
192fe8fb19SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
202fe8fb19SBen Gras  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
212fe8fb19SBen Gras  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
222fe8fb19SBen Gras  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
232fe8fb19SBen Gras  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
242fe8fb19SBen Gras  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
252fe8fb19SBen Gras  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
262fe8fb19SBen Gras  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
272fe8fb19SBen Gras  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
282fe8fb19SBen Gras  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
292fe8fb19SBen Gras  * POSSIBILITY OF SUCH DAMAGE.
302fe8fb19SBen Gras  */
312fe8fb19SBen Gras 
322fe8fb19SBen Gras /*
332fe8fb19SBen Gras  * Copyright (c) 1988, 1993
342fe8fb19SBen Gras  *	The Regents of the University of California.  All rights reserved.
352fe8fb19SBen Gras  *
362fe8fb19SBen Gras  * Redistribution and use in source and binary forms, with or without
372fe8fb19SBen Gras  * modification, are permitted provided that the following conditions
382fe8fb19SBen Gras  * are met:
392fe8fb19SBen Gras  * 1. Redistributions of source code must retain the above copyright
402fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer.
412fe8fb19SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
422fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer in the
432fe8fb19SBen Gras  *    documentation and/or other materials provided with the distribution.
442fe8fb19SBen Gras  * 3. Neither the name of the University nor the names of its contributors
452fe8fb19SBen Gras  *    may be used to endorse or promote products derived from this software
462fe8fb19SBen Gras  *    without specific prior written permission.
472fe8fb19SBen Gras  *
482fe8fb19SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
492fe8fb19SBen Gras  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
502fe8fb19SBen Gras  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
512fe8fb19SBen Gras  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
522fe8fb19SBen Gras  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
532fe8fb19SBen Gras  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
542fe8fb19SBen Gras  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
552fe8fb19SBen Gras  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
562fe8fb19SBen Gras  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
572fe8fb19SBen Gras  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
582fe8fb19SBen Gras  * SUCH DAMAGE.
592fe8fb19SBen Gras  */
602fe8fb19SBen Gras 
612fe8fb19SBen Gras /*
622fe8fb19SBen Gras  * Portions Copyright (c) 1994, 1995, Jason Downs.  All rights reserved.
632fe8fb19SBen Gras  *
642fe8fb19SBen Gras  * Redistribution and use in source and binary forms, with or without
652fe8fb19SBen Gras  * modification, are permitted provided that the following conditions
662fe8fb19SBen Gras  * are met:
672fe8fb19SBen Gras  * 1. Redistributions of source code must retain the above copyright
682fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer.
692fe8fb19SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
702fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer in the
712fe8fb19SBen Gras  *    documentation and/or other materials provided with the distribution.
722fe8fb19SBen Gras  *
732fe8fb19SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
742fe8fb19SBen Gras  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
752fe8fb19SBen Gras  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
762fe8fb19SBen Gras  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
772fe8fb19SBen Gras  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
782fe8fb19SBen Gras  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
792fe8fb19SBen Gras  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
802fe8fb19SBen Gras  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
812fe8fb19SBen Gras  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
822fe8fb19SBen Gras  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
832fe8fb19SBen Gras  * SUCH DAMAGE.
842fe8fb19SBen Gras  */
852fe8fb19SBen Gras 
862fe8fb19SBen Gras #include <sys/cdefs.h>
872fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
882fe8fb19SBen Gras #if 0
892fe8fb19SBen Gras static char sccsid[] = "@(#)getpwent.c	8.2 (Berkeley) 4/27/95";
902fe8fb19SBen Gras #else
91*f14fb602SLionel Sambuc __RCSID("$NetBSD: getpwent.c,v 1.81 2012/09/08 15:15:06 dholland Exp $");
922fe8fb19SBen Gras #endif
932fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
942fe8fb19SBen Gras 
952fe8fb19SBen Gras #include "namespace.h"
962fe8fb19SBen Gras #include "reentrant.h"
972fe8fb19SBen Gras 
982fe8fb19SBen Gras #include <sys/param.h>
992fe8fb19SBen Gras 
1002fe8fb19SBen Gras #include <assert.h>
1012fe8fb19SBen Gras #include <db.h>
1022fe8fb19SBen Gras #include <errno.h>
1032fe8fb19SBen Gras #include <fcntl.h>
1042fe8fb19SBen Gras #include <limits.h>
1052fe8fb19SBen Gras #include <netgroup.h>
1062fe8fb19SBen Gras #include <nsswitch.h>
1072fe8fb19SBen Gras #include <pwd.h>
1082fe8fb19SBen Gras #include <stdarg.h>
1092fe8fb19SBen Gras #include <stdio.h>
1102fe8fb19SBen Gras #include <stdlib.h>
1112fe8fb19SBen Gras #include <string.h>
1122fe8fb19SBen Gras #include <syslog.h>
1132fe8fb19SBen Gras #include <unistd.h>
1142fe8fb19SBen Gras 
1152fe8fb19SBen Gras #ifdef HESIOD
1162fe8fb19SBen Gras #include <hesiod.h>
1172fe8fb19SBen Gras #endif
1182fe8fb19SBen Gras 
1192fe8fb19SBen Gras #ifdef YP
1202fe8fb19SBen Gras #include <machine/param.h>
1212fe8fb19SBen Gras #include <rpc/rpc.h>
1222fe8fb19SBen Gras #include <rpcsvc/yp_prot.h>
1232fe8fb19SBen Gras #include <rpcsvc/ypclnt.h>
1242fe8fb19SBen Gras #endif
1252fe8fb19SBen Gras 
1262fe8fb19SBen Gras #include "pw_private.h"
1272fe8fb19SBen Gras 
1282fe8fb19SBen Gras #define	_PASSWD_COMPAT	/* "passwd" defaults to compat, so always provide it */
1292fe8fb19SBen Gras 
1302fe8fb19SBen Gras #ifdef __weak_alias
1312fe8fb19SBen Gras __weak_alias(endpwent,_endpwent)
1322fe8fb19SBen Gras __weak_alias(setpassent,_setpassent)
1332fe8fb19SBen Gras __weak_alias(setpwent,_setpwent)
1342fe8fb19SBen Gras #endif
1352fe8fb19SBen Gras 
1362fe8fb19SBen Gras #ifdef _REENTRANT
1372fe8fb19SBen Gras static 	mutex_t			_pwmutex = MUTEX_INITIALIZER;
1382fe8fb19SBen Gras #endif
1392fe8fb19SBen Gras 
1402fe8fb19SBen Gras const char __yp_token[] = "__YP!";	/* Let pwd_mkdb pull this in. */
1412fe8fb19SBen Gras 
1422fe8fb19SBen Gras 
1432fe8fb19SBen Gras /*
1442fe8fb19SBen Gras  * The pwd.db lookup techniques and data extraction code here must be kept
1452fe8fb19SBen Gras  * in sync with that in `pwd_mkdb'.
1462fe8fb19SBen Gras  */
1472fe8fb19SBen Gras 
1482fe8fb19SBen Gras #if defined(YP) || defined(HESIOD)
1492fe8fb19SBen Gras /*
1502fe8fb19SBen Gras  * _pw_parse
1512fe8fb19SBen Gras  *	Parses entry using pw_scan(3) (without the trailing \n)
1522fe8fb19SBen Gras  *	after copying to buf, and fills in pw with corresponding values.
1532fe8fb19SBen Gras  *	If old is non-zero, entry is in _PASSWORD_OLDFMT.
1542fe8fb19SBen Gras  *	Returns 1 if parsed successfully, 0 on parse failure.
1552fe8fb19SBen Gras  */
1562fe8fb19SBen Gras static int
_pw_parse(const char * entry,struct passwd * pw,char * buf,size_t buflen,int old)1572fe8fb19SBen Gras _pw_parse(const char *entry, struct passwd *pw, char *buf, size_t buflen,
1582fe8fb19SBen Gras 	int old)
1592fe8fb19SBen Gras {
1602fe8fb19SBen Gras 	int	flags;
1612fe8fb19SBen Gras 
1622fe8fb19SBen Gras 	_DIAGASSERT(entry != NULL);
1632fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
1642fe8fb19SBen Gras 	_DIAGASSERT(buf != NULL);
1652fe8fb19SBen Gras 
1662fe8fb19SBen Gras 	if (strlcpy(buf, entry, buflen) >= buflen)
1672fe8fb19SBen Gras 		return 0;
1682fe8fb19SBen Gras 	flags = _PASSWORD_NOWARN;
1692fe8fb19SBen Gras 	if (old)
1702fe8fb19SBen Gras 		flags |= _PASSWORD_OLDFMT;
1712fe8fb19SBen Gras 	return __pw_scan(buf, pw, &flags);
1722fe8fb19SBen Gras }
1732fe8fb19SBen Gras #endif /* YP || HESIOD */
1742fe8fb19SBen Gras 
1752fe8fb19SBen Gras /*
1762fe8fb19SBen Gras  * _pw_opendb
1772fe8fb19SBen Gras  *	if *db is NULL, dbopen(3) /etc/spwd.db or /etc/pwd.db (depending
1782fe8fb19SBen Gras  *	upon permissions, etc)
1792fe8fb19SBen Gras  */
1802fe8fb19SBen Gras static int
_pw_opendb(DB ** db,int * version)1812fe8fb19SBen Gras _pw_opendb(DB **db, int *version)
1822fe8fb19SBen Gras {
1832fe8fb19SBen Gras 	static int	warned;
1842fe8fb19SBen Gras 	DBT		key;
1852fe8fb19SBen Gras 	DBT		value;
1862fe8fb19SBen Gras 
1872fe8fb19SBen Gras 	const char	*dbfile = NULL;
1882fe8fb19SBen Gras 
1892fe8fb19SBen Gras 	_DIAGASSERT(db != NULL);
1902fe8fb19SBen Gras 	_DIAGASSERT(version != NULL);
1912fe8fb19SBen Gras 	if (*db != NULL)					/* open *db */
1922fe8fb19SBen Gras 		return NS_SUCCESS;
1932fe8fb19SBen Gras 
1942fe8fb19SBen Gras 	if (geteuid() == 0) {
1952fe8fb19SBen Gras 		dbfile = _PATH_SMP_DB;
1962fe8fb19SBen Gras 		*db = dbopen(dbfile, O_RDONLY, 0, DB_HASH, NULL);
1972fe8fb19SBen Gras 	}
1982fe8fb19SBen Gras 	if (*db == NULL) {
1992fe8fb19SBen Gras 		dbfile = _PATH_MP_DB;
2002fe8fb19SBen Gras 		*db = dbopen(dbfile, O_RDONLY, 0, DB_HASH, NULL);
2012fe8fb19SBen Gras 	}
2022fe8fb19SBen Gras 	if (*db == NULL) {
2032fe8fb19SBen Gras 		if (!warned) {
2042fe8fb19SBen Gras 			int	serrno = errno;
2052fe8fb19SBen Gras 			syslog(LOG_ERR, "%s: %m", dbfile);
2062fe8fb19SBen Gras 			errno = serrno;
2072fe8fb19SBen Gras 		}
2082fe8fb19SBen Gras 		warned = 1;
2092fe8fb19SBen Gras 		return NS_UNAVAIL;
2102fe8fb19SBen Gras 	}
2112fe8fb19SBen Gras 	key.data = __UNCONST("VERSION");
2122fe8fb19SBen Gras 	key.size = strlen((char *)key.data) + 1;
2132fe8fb19SBen Gras 	switch ((*(*db)->get)(*db, &key, &value, 0)) {
2142fe8fb19SBen Gras 	case 0:
2152fe8fb19SBen Gras 		if (sizeof(*version) != value.size)
2162fe8fb19SBen Gras 			return NS_UNAVAIL;
2172fe8fb19SBen Gras 		(void)memcpy(version, value.data, value.size);
2182fe8fb19SBen Gras 		break;			/* found */
2192fe8fb19SBen Gras 	case 1:
2202fe8fb19SBen Gras 		*version = 0;		/* not found */
2212fe8fb19SBen Gras 		break;
2222fe8fb19SBen Gras 	case -1:
2232fe8fb19SBen Gras 		return NS_UNAVAIL;	/* error in db routines */
2242fe8fb19SBen Gras 	default:
2252fe8fb19SBen Gras 		abort();
2262fe8fb19SBen Gras 	}
2272fe8fb19SBen Gras 	return NS_SUCCESS;
2282fe8fb19SBen Gras }
2292fe8fb19SBen Gras 
2302fe8fb19SBen Gras /*
2312fe8fb19SBen Gras  * _pw_getkey
2322fe8fb19SBen Gras  *	Lookup key in *db, filling in pw
2332fe8fb19SBen Gras  *	with the result, allocating memory from buffer (size buflen).
2342fe8fb19SBen Gras  *	(The caller may point key.data to buffer on entry; the contents
2352fe8fb19SBen Gras  *	of key.data will be invalid on exit.)
2362fe8fb19SBen Gras  */
2372fe8fb19SBen Gras static int
_pw_getkey(DB * db,DBT * key,struct passwd * pw,char * buffer,size_t buflen,int * pwflags,int version)2382fe8fb19SBen Gras _pw_getkey(DB *db, DBT *key,
2392fe8fb19SBen Gras 	struct passwd *pw, char *buffer, size_t buflen, int *pwflags,
2402fe8fb19SBen Gras 	int version)
2412fe8fb19SBen Gras {
2422fe8fb19SBen Gras 	char		*p, *t;
2432fe8fb19SBen Gras 	DBT		data;
2442fe8fb19SBen Gras 
2452fe8fb19SBen Gras 	_DIAGASSERT(db != NULL);
2462fe8fb19SBen Gras 	_DIAGASSERT(key != NULL);
2472fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
2482fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
2492fe8fb19SBen Gras 	/* pwflags may be NULL (if we don't care about them */
2502fe8fb19SBen Gras 
2512fe8fb19SBen Gras 	if (db == NULL)			/* this shouldn't happen */
2522fe8fb19SBen Gras 		return NS_UNAVAIL;
2532fe8fb19SBen Gras 
2542fe8fb19SBen Gras 	switch ((db->get)(db, key, &data, 0)) {
2552fe8fb19SBen Gras 	case 0:
2562fe8fb19SBen Gras 		break;			/* found */
2572fe8fb19SBen Gras 	case 1:
2582fe8fb19SBen Gras 		return NS_NOTFOUND;	/* not found */
2592fe8fb19SBen Gras 	case -1:
2602fe8fb19SBen Gras 		return NS_UNAVAIL;	/* error in db routines */
2612fe8fb19SBen Gras 	default:
2622fe8fb19SBen Gras 		abort();
2632fe8fb19SBen Gras 	}
2642fe8fb19SBen Gras 
2652fe8fb19SBen Gras 	p = (char *)data.data;
2662fe8fb19SBen Gras 	if (data.size > buflen) {
2672fe8fb19SBen Gras 		errno = ERANGE;
2682fe8fb19SBen Gras 		return NS_UNAVAIL;
2692fe8fb19SBen Gras 	}
2702fe8fb19SBen Gras 
2712fe8fb19SBen Gras 			/*
2722fe8fb19SBen Gras 			 * THE DECODING BELOW MUST MATCH THAT IN pwd_mkdb.
2732fe8fb19SBen Gras 			 */
2742fe8fb19SBen Gras 	t = buffer;
2752fe8fb19SBen Gras #define MACRO(a)	do { a } while (/*CONSTCOND*/0)
2762fe8fb19SBen Gras #define	EXPAND(e)	MACRO(e = t; while ((*t++ = *p++));)
2772fe8fb19SBen Gras #define	SCALAR(v)	MACRO(memmove(&(v), p, sizeof v); p += sizeof v;)
2782fe8fb19SBen Gras 	EXPAND(pw->pw_name);
2792fe8fb19SBen Gras 	EXPAND(pw->pw_passwd);
2802fe8fb19SBen Gras 	SCALAR(pw->pw_uid);
2812fe8fb19SBen Gras 	SCALAR(pw->pw_gid);
2822fe8fb19SBen Gras 	if (version == 0) {
2832fe8fb19SBen Gras 		int32_t tmp;
2842fe8fb19SBen Gras 		SCALAR(tmp);
2852fe8fb19SBen Gras 		pw->pw_change = tmp;
2862fe8fb19SBen Gras 	} else
2872fe8fb19SBen Gras 		SCALAR(pw->pw_change);
2882fe8fb19SBen Gras 	EXPAND(pw->pw_class);
2892fe8fb19SBen Gras 	EXPAND(pw->pw_gecos);
2902fe8fb19SBen Gras 	EXPAND(pw->pw_dir);
2912fe8fb19SBen Gras 	EXPAND(pw->pw_shell);
2922fe8fb19SBen Gras 	if (version == 0) {
2932fe8fb19SBen Gras 		int32_t tmp;
2942fe8fb19SBen Gras 		SCALAR(tmp);
2952fe8fb19SBen Gras 		pw->pw_expire = tmp;
2962fe8fb19SBen Gras 	} else
2972fe8fb19SBen Gras 		SCALAR(pw->pw_expire);
2982fe8fb19SBen Gras 	if (pwflags) {
2992fe8fb19SBen Gras 		/* See if there's any data left.  If so, read in flags. */
3002fe8fb19SBen Gras 		if (data.size > (size_t) (p - (char *)data.data)) {
3012fe8fb19SBen Gras 			SCALAR(*pwflags);
3022fe8fb19SBen Gras 		} else {				/* default */
3032fe8fb19SBen Gras 			*pwflags = _PASSWORD_NOUID|_PASSWORD_NOGID;
3042fe8fb19SBen Gras 		}
3052fe8fb19SBen Gras 	}
3062fe8fb19SBen Gras 
3072fe8fb19SBen Gras 	return NS_SUCCESS;
3082fe8fb19SBen Gras }
3092fe8fb19SBen Gras 
3102fe8fb19SBen Gras /*
3112fe8fb19SBen Gras  * _pw_memfrombuf
3122fe8fb19SBen Gras  *	Obtain want bytes from buffer (of size buflen) and return a pointer
3132fe8fb19SBen Gras  *	to the available memory after adjusting buffer/buflen.
3142fe8fb19SBen Gras  *	Returns NULL if there is insufficient space.
3152fe8fb19SBen Gras  */
3162fe8fb19SBen Gras static char *
_pw_memfrombuf(size_t want,char ** buffer,size_t * buflen)3172fe8fb19SBen Gras _pw_memfrombuf(size_t want, char **buffer, size_t *buflen)
3182fe8fb19SBen Gras {
3192fe8fb19SBen Gras 	char	*rv;
3202fe8fb19SBen Gras 
3212fe8fb19SBen Gras 	if (want > *buflen) {
3222fe8fb19SBen Gras 		errno = ERANGE;
3232fe8fb19SBen Gras 		return NULL;
3242fe8fb19SBen Gras 	}
3252fe8fb19SBen Gras 	rv = *buffer;
3262fe8fb19SBen Gras 	*buffer += want;
3272fe8fb19SBen Gras 	*buflen -= want;
3282fe8fb19SBen Gras 	return rv;
3292fe8fb19SBen Gras }
3302fe8fb19SBen Gras 
3312fe8fb19SBen Gras /*
3322fe8fb19SBen Gras  * _pw_copy
3332fe8fb19SBen Gras  *	Copy the contents of frompw to pw; memory for strings
3342fe8fb19SBen Gras  *	and arrays will be allocated from buf (of size buflen).
3352fe8fb19SBen Gras  *	If proto != NULL, use various fields in proto in preference to frompw.
3362fe8fb19SBen Gras  *	Returns 1 if copied successfully, 0 on copy failure.
3372fe8fb19SBen Gras  *	NOTE: frompw must not use buf for its own pointers.
3382fe8fb19SBen Gras  */
3392fe8fb19SBen Gras static int
_pw_copy(const struct passwd * frompw,struct passwd * pw,char * buf,size_t buflen,const struct passwd * protopw,int protoflags)3402fe8fb19SBen Gras _pw_copy(const struct passwd *frompw, struct passwd *pw,
3412fe8fb19SBen Gras 	char *buf, size_t buflen, const struct passwd *protopw, int protoflags)
3422fe8fb19SBen Gras {
3432fe8fb19SBen Gras 	size_t	count;
3442fe8fb19SBen Gras 	int	useproto;
3452fe8fb19SBen Gras 
3462fe8fb19SBen Gras 	_DIAGASSERT(frompw != NULL);
3472fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
3482fe8fb19SBen Gras 	_DIAGASSERT(buf != NULL);
3492fe8fb19SBen Gras 	/* protopw may be NULL */
3502fe8fb19SBen Gras 
3512fe8fb19SBen Gras 	useproto = protopw && protopw->pw_name;
3522fe8fb19SBen Gras 
3532fe8fb19SBen Gras #define	COPYSTR(to, from) \
3542fe8fb19SBen Gras 	do { \
3552fe8fb19SBen Gras 		count = strlen((from)); \
3562fe8fb19SBen Gras 		(to) = _pw_memfrombuf(count+1, &buf, &buflen); \
3572fe8fb19SBen Gras 		if ((to) == NULL) \
3582fe8fb19SBen Gras 			return 0; \
3592fe8fb19SBen Gras 		memmove((to), (from), count); \
3602fe8fb19SBen Gras 		to[count] = '\0'; \
3612fe8fb19SBen Gras 	} while (0)	/* LINTED */
3622fe8fb19SBen Gras 
3632fe8fb19SBen Gras #define	COPYFIELD(field)	COPYSTR(pw->field, frompw->field)
3642fe8fb19SBen Gras 
3652fe8fb19SBen Gras #define	COPYPROTOFIELD(field)	COPYSTR(pw->field, \
3662fe8fb19SBen Gras 		(useproto && *protopw->field ? protopw->field : frompw->field))
3672fe8fb19SBen Gras 
3682fe8fb19SBen Gras 	COPYFIELD(pw_name);
3692fe8fb19SBen Gras 
3702fe8fb19SBen Gras #ifdef PW_OVERRIDE_PASSWD
3712fe8fb19SBen Gras 	COPYPROTOFIELD(pw_passwd);
3722fe8fb19SBen Gras #else
3732fe8fb19SBen Gras 	COPYFIELD(pw_passwd);
3742fe8fb19SBen Gras #endif
3752fe8fb19SBen Gras 
3762fe8fb19SBen Gras 	if (useproto && !(protoflags & _PASSWORD_NOUID))
3772fe8fb19SBen Gras 		pw->pw_uid = protopw->pw_uid;
3782fe8fb19SBen Gras 	else
3792fe8fb19SBen Gras 		pw->pw_uid = frompw->pw_uid;
3802fe8fb19SBen Gras 
3812fe8fb19SBen Gras 	if (useproto && !(protoflags & _PASSWORD_NOGID))
3822fe8fb19SBen Gras 		pw->pw_gid = protopw->pw_gid;
3832fe8fb19SBen Gras 	else
3842fe8fb19SBen Gras 		pw->pw_gid = frompw->pw_gid;
3852fe8fb19SBen Gras 
3862fe8fb19SBen Gras 	pw->pw_change = frompw->pw_change;
3872fe8fb19SBen Gras 	COPYFIELD(pw_class);
3882fe8fb19SBen Gras 	COPYPROTOFIELD(pw_gecos);
3892fe8fb19SBen Gras 	COPYPROTOFIELD(pw_dir);
3902fe8fb19SBen Gras 	COPYPROTOFIELD(pw_shell);
3912fe8fb19SBen Gras 
3922fe8fb19SBen Gras #undef COPYSTR
3932fe8fb19SBen Gras #undef COPYFIELD
3942fe8fb19SBen Gras #undef COPYPROTOFIELD
3952fe8fb19SBen Gras 
3962fe8fb19SBen Gras 	return 1;
3972fe8fb19SBen Gras }
3982fe8fb19SBen Gras 
3992fe8fb19SBen Gras 
4002fe8fb19SBen Gras 		/*
4012fe8fb19SBen Gras 		 *	files methods
4022fe8fb19SBen Gras 		 */
4032fe8fb19SBen Gras 
4042fe8fb19SBen Gras 	/* state shared between files methods */
4052fe8fb19SBen Gras struct files_state {
4062fe8fb19SBen Gras 	int	 stayopen;		/* see getpassent(3) */
4072fe8fb19SBen Gras 	DB	*db;			/* passwd file handle */
4082fe8fb19SBen Gras 	int	 keynum;		/* key counter, -1 if no more */
4092fe8fb19SBen Gras 	int	 version;
4102fe8fb19SBen Gras };
4112fe8fb19SBen Gras 
4122fe8fb19SBen Gras static struct files_state	_files_state;
4132fe8fb19SBen Gras 					/* storage for non _r functions */
4142fe8fb19SBen Gras static struct passwd		_files_passwd;
4152fe8fb19SBen Gras static char			_files_passwdbuf[_GETPW_R_SIZE_MAX];
4162fe8fb19SBen Gras 
4172fe8fb19SBen Gras static int
_files_start(struct files_state * state)4182fe8fb19SBen Gras _files_start(struct files_state *state)
4192fe8fb19SBen Gras {
4202fe8fb19SBen Gras 	int	rv;
4212fe8fb19SBen Gras 
4222fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
4232fe8fb19SBen Gras 
4242fe8fb19SBen Gras 	state->keynum = 0;
4252fe8fb19SBen Gras 	rv = _pw_opendb(&state->db, &state->version);
4262fe8fb19SBen Gras 	if (rv != NS_SUCCESS)
4272fe8fb19SBen Gras 		return rv;
4282fe8fb19SBen Gras 	return NS_SUCCESS;
4292fe8fb19SBen Gras }
4302fe8fb19SBen Gras 
4312fe8fb19SBen Gras static int
_files_end(struct files_state * state)4322fe8fb19SBen Gras _files_end(struct files_state *state)
4332fe8fb19SBen Gras {
4342fe8fb19SBen Gras 
4352fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
4362fe8fb19SBen Gras 
4372fe8fb19SBen Gras 	state->keynum = 0;
4382fe8fb19SBen Gras 	if (state->db) {
4392fe8fb19SBen Gras 		(void)(state->db->close)(state->db);
4402fe8fb19SBen Gras 		state->db = NULL;
4412fe8fb19SBen Gras 	}
4422fe8fb19SBen Gras 	return NS_SUCCESS;
4432fe8fb19SBen Gras }
4442fe8fb19SBen Gras 
4452fe8fb19SBen Gras /*
4462fe8fb19SBen Gras  * _files_pwscan
4472fe8fb19SBen Gras  *	Search state->db for the next desired entry.
4482fe8fb19SBen Gras  *	If search is _PW_KEYBYNUM, look for state->keynum.
4492fe8fb19SBen Gras  *	If search is _PW_KEYBYNAME, look for name.
4502fe8fb19SBen Gras  *	If search is _PW_KEYBYUID, look for uid.
4512fe8fb19SBen Gras  *	Sets *retval to the errno if the result is not NS_SUCCESS
4522fe8fb19SBen Gras  *	or NS_NOTFOUND.
4532fe8fb19SBen Gras  */
4542fe8fb19SBen Gras static int
_files_pwscan(int * retval,struct passwd * pw,char * buffer,size_t buflen,struct files_state * state,int search,const char * name,uid_t uid)4552fe8fb19SBen Gras _files_pwscan(int *retval, struct passwd *pw, char *buffer, size_t buflen,
4562fe8fb19SBen Gras 	struct files_state *state, int search, const char *name, uid_t uid)
4572fe8fb19SBen Gras {
4582fe8fb19SBen Gras 	const void	*from;
4592fe8fb19SBen Gras 	size_t		 fromlen;
4602fe8fb19SBen Gras 	DBT		 key;
4612fe8fb19SBen Gras 	int		 rv;
4622fe8fb19SBen Gras 
4632fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
4642fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
4652fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
4662fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
4672fe8fb19SBen Gras 	/* name is NULL to indicate searching for uid */
4682fe8fb19SBen Gras 
4692fe8fb19SBen Gras 	*retval = 0;
4702fe8fb19SBen Gras 
4712fe8fb19SBen Gras 	if (state->db == NULL) {	/* only start if file not open yet */
4722fe8fb19SBen Gras 		rv = _files_start(state);
4732fe8fb19SBen Gras 		if (rv != NS_SUCCESS)
4742fe8fb19SBen Gras 			goto filespwscan_out;
4752fe8fb19SBen Gras 	}
4762fe8fb19SBen Gras 
4772fe8fb19SBen Gras 	for (;;) {				/* search for a match */
4782fe8fb19SBen Gras 		switch (search) {
4792fe8fb19SBen Gras 		case _PW_KEYBYNUM:
4802fe8fb19SBen Gras 			if (state->keynum == -1)
4812fe8fb19SBen Gras 				return NS_NOTFOUND;	/* no more records */
4822fe8fb19SBen Gras 			state->keynum++;
4832fe8fb19SBen Gras 			from = &state->keynum;
4842fe8fb19SBen Gras 			fromlen = sizeof(state->keynum);
4852fe8fb19SBen Gras 			break;
4862fe8fb19SBen Gras 		case _PW_KEYBYNAME:
4872fe8fb19SBen Gras 			from = name;
4882fe8fb19SBen Gras 			fromlen = strlen(name);
4892fe8fb19SBen Gras 			break;
4902fe8fb19SBen Gras 		case _PW_KEYBYUID:
4912fe8fb19SBen Gras 			from = &uid;
4922fe8fb19SBen Gras 			fromlen = sizeof(uid);
4932fe8fb19SBen Gras 			break;
4942fe8fb19SBen Gras 		default:
4952fe8fb19SBen Gras 			abort();
4962fe8fb19SBen Gras 		}
4972fe8fb19SBen Gras 
4982fe8fb19SBen Gras 		if (buflen <= fromlen) {		/* buffer too small */
4992fe8fb19SBen Gras 			*retval = ERANGE;
5002fe8fb19SBen Gras 			return NS_UNAVAIL;
5012fe8fb19SBen Gras 		}
5022fe8fb19SBen Gras 		buffer[0] = search;			/* setup key */
5032fe8fb19SBen Gras 		memmove(buffer + 1, from, fromlen);
5042fe8fb19SBen Gras 		key.size = fromlen + 1;
5052fe8fb19SBen Gras 		key.data = (u_char *)buffer;
5062fe8fb19SBen Gras 
5072fe8fb19SBen Gras 							/* search for key */
5082fe8fb19SBen Gras 		rv = _pw_getkey(state->db, &key, pw, buffer, buflen, NULL,
5092fe8fb19SBen Gras 		    state->version);
5102fe8fb19SBen Gras 		if (rv != NS_SUCCESS)			/* no match */
5112fe8fb19SBen Gras 			break;
5122fe8fb19SBen Gras 		if (pw->pw_name[0] == '+' || pw->pw_name[0] == '-') {
5132fe8fb19SBen Gras 						/* if a compat line */
5142fe8fb19SBen Gras 			if (search == _PW_KEYBYNUM)
5152fe8fb19SBen Gras 				continue;	/* read next if pwent */
5162fe8fb19SBen Gras 			rv = NS_NOTFOUND;	/* don't match if pw{nam,uid} */
5172fe8fb19SBen Gras 			break;
5182fe8fb19SBen Gras 		}
5192fe8fb19SBen Gras 		break;
5202fe8fb19SBen Gras 	}
5212fe8fb19SBen Gras 
5222fe8fb19SBen Gras 	if (rv == NS_NOTFOUND && search == _PW_KEYBYNUM)
5232fe8fb19SBen Gras 		state->keynum = -1;		/* flag `no more records' */
5242fe8fb19SBen Gras 
5252fe8fb19SBen Gras 	if (rv == NS_SUCCESS) {
5262fe8fb19SBen Gras 		if ((search == _PW_KEYBYUID && pw->pw_uid != uid) ||
5272fe8fb19SBen Gras 		    (search == _PW_KEYBYNAME && strcmp(pw->pw_name, name) != 0))
5282fe8fb19SBen Gras 			rv = NS_NOTFOUND;
5292fe8fb19SBen Gras 	}
5302fe8fb19SBen Gras 
5312fe8fb19SBen Gras  filespwscan_out:
5322fe8fb19SBen Gras 	if (rv != NS_SUCCESS && rv != NS_NOTFOUND)
5332fe8fb19SBen Gras 		*retval = errno;
5342fe8fb19SBen Gras 	return rv;
5352fe8fb19SBen Gras }
5362fe8fb19SBen Gras 
5372fe8fb19SBen Gras /*ARGSUSED*/
5382fe8fb19SBen Gras static int
_files_setpwent(void * nsrv,void * nscb,va_list ap)5392fe8fb19SBen Gras _files_setpwent(void *nsrv, void *nscb, va_list ap)
5402fe8fb19SBen Gras {
5412fe8fb19SBen Gras 
5422fe8fb19SBen Gras 	_files_state.stayopen = 0;
5432fe8fb19SBen Gras 	return _files_start(&_files_state);
5442fe8fb19SBen Gras }
5452fe8fb19SBen Gras 
5462fe8fb19SBen Gras /*ARGSUSED*/
5472fe8fb19SBen Gras static int
_files_setpassent(void * nsrv,void * nscb,va_list ap)5482fe8fb19SBen Gras _files_setpassent(void *nsrv, void *nscb, va_list ap)
5492fe8fb19SBen Gras {
5502fe8fb19SBen Gras 	int	*retval		= va_arg(ap, int *);
5512fe8fb19SBen Gras 	int	 stayopen	= va_arg(ap, int);
5522fe8fb19SBen Gras 
5532fe8fb19SBen Gras 	int	rv;
5542fe8fb19SBen Gras 
5552fe8fb19SBen Gras 	_files_state.stayopen = stayopen;
5562fe8fb19SBen Gras 	rv = _files_start(&_files_state);
5572fe8fb19SBen Gras 	*retval = (rv == NS_SUCCESS);
5582fe8fb19SBen Gras 	return rv;
5592fe8fb19SBen Gras }
5602fe8fb19SBen Gras 
5612fe8fb19SBen Gras /*ARGSUSED*/
5622fe8fb19SBen Gras static int
_files_endpwent(void * nsrv,void * nscb,va_list ap)5632fe8fb19SBen Gras _files_endpwent(void *nsrv, void *nscb, va_list ap)
5642fe8fb19SBen Gras {
5652fe8fb19SBen Gras 
5662fe8fb19SBen Gras 	_files_state.stayopen = 0;
5672fe8fb19SBen Gras 	return _files_end(&_files_state);
5682fe8fb19SBen Gras }
5692fe8fb19SBen Gras 
5702fe8fb19SBen Gras /*ARGSUSED*/
5712fe8fb19SBen Gras static int
_files_getpwent(void * nsrv,void * nscb,va_list ap)5722fe8fb19SBen Gras _files_getpwent(void *nsrv, void *nscb, va_list ap)
5732fe8fb19SBen Gras {
5742fe8fb19SBen Gras 	struct passwd	**retval = va_arg(ap, struct passwd **);
5752fe8fb19SBen Gras 
5762fe8fb19SBen Gras 	int	rv, rerror;
5772fe8fb19SBen Gras 
5782fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
5792fe8fb19SBen Gras 
5802fe8fb19SBen Gras 	*retval = NULL;
5812fe8fb19SBen Gras 	rv = _files_pwscan(&rerror, &_files_passwd,
5822fe8fb19SBen Gras 	    _files_passwdbuf, sizeof(_files_passwdbuf),
5832fe8fb19SBen Gras 	    &_files_state, _PW_KEYBYNUM, NULL, 0);
5842fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
5852fe8fb19SBen Gras 		*retval = &_files_passwd;
5862fe8fb19SBen Gras 	return rv;
5872fe8fb19SBen Gras }
5882fe8fb19SBen Gras 
5892fe8fb19SBen Gras /*ARGSUSED*/
5902fe8fb19SBen Gras static int
_files_getpwent_r(void * nsrv,void * nscb,va_list ap)5912fe8fb19SBen Gras _files_getpwent_r(void *nsrv, void *nscb, va_list ap)
5922fe8fb19SBen Gras {
5932fe8fb19SBen Gras 	int		*retval	= va_arg(ap, int *);
5942fe8fb19SBen Gras 	struct passwd	*pw	= va_arg(ap, struct passwd *);
5952fe8fb19SBen Gras 	char		*buffer	= va_arg(ap, char *);
5962fe8fb19SBen Gras 	size_t		 buflen	= va_arg(ap, size_t);
5972fe8fb19SBen Gras 	struct passwd  **result	= va_arg(ap, struct passwd **);
5982fe8fb19SBen Gras 
5992fe8fb19SBen Gras 	int	rv;
6002fe8fb19SBen Gras 
6012fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
6022fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
6032fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
6042fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
6052fe8fb19SBen Gras 
6062fe8fb19SBen Gras 	rv = _files_pwscan(retval, pw, buffer, buflen, &_files_state,
6072fe8fb19SBen Gras 	    _PW_KEYBYNUM, NULL, 0);
6082fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
6092fe8fb19SBen Gras 		*result = pw;
6102fe8fb19SBen Gras 	else
6112fe8fb19SBen Gras 		*result = NULL;
6122fe8fb19SBen Gras 	return rv;
6132fe8fb19SBen Gras }
6142fe8fb19SBen Gras 
6152fe8fb19SBen Gras /*ARGSUSED*/
6162fe8fb19SBen Gras static int
_files_getpwnam(void * nsrv,void * nscb,va_list ap)6172fe8fb19SBen Gras _files_getpwnam(void *nsrv, void *nscb, va_list ap)
6182fe8fb19SBen Gras {
6192fe8fb19SBen Gras 	struct passwd	**retval = va_arg(ap, struct passwd **);
6202fe8fb19SBen Gras 	const char	*name	= va_arg(ap, const char *);
6212fe8fb19SBen Gras 
6222fe8fb19SBen Gras 	int	rv, rerror;
6232fe8fb19SBen Gras 
6242fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
6252fe8fb19SBen Gras 
6262fe8fb19SBen Gras 	*retval = NULL;
6272fe8fb19SBen Gras 	rv = _files_start(&_files_state);
6282fe8fb19SBen Gras 	if (rv != NS_SUCCESS)
6292fe8fb19SBen Gras 		return rv;
6302fe8fb19SBen Gras 	rv = _files_pwscan(&rerror, &_files_passwd,
6312fe8fb19SBen Gras 	    _files_passwdbuf, sizeof(_files_passwdbuf),
6322fe8fb19SBen Gras 	    &_files_state, _PW_KEYBYNAME, name, 0);
6332fe8fb19SBen Gras 	if (!_files_state.stayopen)
6342fe8fb19SBen Gras 		_files_end(&_files_state);
6352fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
6362fe8fb19SBen Gras 		*retval = &_files_passwd;
6372fe8fb19SBen Gras 	return rv;
6382fe8fb19SBen Gras }
6392fe8fb19SBen Gras 
6402fe8fb19SBen Gras /*ARGSUSED*/
6412fe8fb19SBen Gras static int
_files_getpwnam_r(void * nsrv,void * nscb,va_list ap)6422fe8fb19SBen Gras _files_getpwnam_r(void *nsrv, void *nscb, va_list ap)
6432fe8fb19SBen Gras {
6442fe8fb19SBen Gras 	int		*retval	= va_arg(ap, int *);
6452fe8fb19SBen Gras 	const char	*name	= va_arg(ap, const char *);
6462fe8fb19SBen Gras 	struct passwd	*pw	= va_arg(ap, struct passwd *);
6472fe8fb19SBen Gras 	char		*buffer	= va_arg(ap, char *);
6482fe8fb19SBen Gras 	size_t		 buflen	= va_arg(ap, size_t);
6492fe8fb19SBen Gras 	struct passwd  **result	= va_arg(ap, struct passwd **);
6502fe8fb19SBen Gras 
6512fe8fb19SBen Gras 	struct files_state state;
6522fe8fb19SBen Gras 	int	rv;
6532fe8fb19SBen Gras 
6542fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
6552fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
6562fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
6572fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
6582fe8fb19SBen Gras 
6592fe8fb19SBen Gras 	*result = NULL;
6602fe8fb19SBen Gras 	memset(&state, 0, sizeof(state));
6612fe8fb19SBen Gras 	rv = _files_pwscan(retval, pw, buffer, buflen, &state,
6622fe8fb19SBen Gras 	    _PW_KEYBYNAME, name, 0);
6632fe8fb19SBen Gras 	_files_end(&state);
6642fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
6652fe8fb19SBen Gras 		*result = pw;
6662fe8fb19SBen Gras 	return rv;
6672fe8fb19SBen Gras }
6682fe8fb19SBen Gras 
6692fe8fb19SBen Gras /*ARGSUSED*/
6702fe8fb19SBen Gras static int
_files_getpwuid(void * nsrv,void * nscb,va_list ap)6712fe8fb19SBen Gras _files_getpwuid(void *nsrv, void *nscb, va_list ap)
6722fe8fb19SBen Gras {
6732fe8fb19SBen Gras 	struct passwd	**retval = va_arg(ap, struct passwd **);
6742fe8fb19SBen Gras 	uid_t		 uid	= va_arg(ap, uid_t);
6752fe8fb19SBen Gras 
6762fe8fb19SBen Gras 	int	rv, rerror;
6772fe8fb19SBen Gras 
6782fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
6792fe8fb19SBen Gras 
6802fe8fb19SBen Gras 	*retval = NULL;
6812fe8fb19SBen Gras 	rv = _files_start(&_files_state);
6822fe8fb19SBen Gras 	if (rv != NS_SUCCESS)
6832fe8fb19SBen Gras 		return rv;
6842fe8fb19SBen Gras 	rv = _files_pwscan(&rerror, &_files_passwd,
6852fe8fb19SBen Gras 	    _files_passwdbuf, sizeof(_files_passwdbuf),
6862fe8fb19SBen Gras 	    &_files_state, _PW_KEYBYUID, NULL, uid);
6872fe8fb19SBen Gras 	if (!_files_state.stayopen)
6882fe8fb19SBen Gras 		_files_end(&_files_state);
6892fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
6902fe8fb19SBen Gras 		*retval = &_files_passwd;
6912fe8fb19SBen Gras 	return rv;
6922fe8fb19SBen Gras }
6932fe8fb19SBen Gras 
6942fe8fb19SBen Gras /*ARGSUSED*/
6952fe8fb19SBen Gras static int
_files_getpwuid_r(void * nsrv,void * nscb,va_list ap)6962fe8fb19SBen Gras _files_getpwuid_r(void *nsrv, void *nscb, va_list ap)
6972fe8fb19SBen Gras {
6982fe8fb19SBen Gras 	int		*retval	= va_arg(ap, int *);
6992fe8fb19SBen Gras 	uid_t		 uid	= va_arg(ap, uid_t);
7002fe8fb19SBen Gras 	struct passwd	*pw	= va_arg(ap, struct passwd *);
7012fe8fb19SBen Gras 	char		*buffer	= va_arg(ap, char *);
7022fe8fb19SBen Gras 	size_t		 buflen	= va_arg(ap, size_t);
7032fe8fb19SBen Gras 	struct passwd  **result	= va_arg(ap, struct passwd **);
7042fe8fb19SBen Gras 
7052fe8fb19SBen Gras 	struct files_state state;
7062fe8fb19SBen Gras 	int	rv;
7072fe8fb19SBen Gras 
7082fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
7092fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
7102fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
7112fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
7122fe8fb19SBen Gras 
7132fe8fb19SBen Gras 	*result = NULL;
7142fe8fb19SBen Gras 	memset(&state, 0, sizeof(state));
7152fe8fb19SBen Gras 	rv = _files_pwscan(retval, pw, buffer, buflen, &state,
7162fe8fb19SBen Gras 	    _PW_KEYBYUID, NULL, uid);
7172fe8fb19SBen Gras 	_files_end(&state);
7182fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
7192fe8fb19SBen Gras 		*result = pw;
7202fe8fb19SBen Gras 	return rv;
7212fe8fb19SBen Gras }
7222fe8fb19SBen Gras 
7232fe8fb19SBen Gras 
7242fe8fb19SBen Gras #ifdef HESIOD
7252fe8fb19SBen Gras 		/*
7262fe8fb19SBen Gras 		 *	dns methods
7272fe8fb19SBen Gras 		 */
7282fe8fb19SBen Gras 
7292fe8fb19SBen Gras 	/* state shared between dns methods */
7302fe8fb19SBen Gras struct dns_state {
7312fe8fb19SBen Gras 	int	 stayopen;		/* see getpassent(3) */
7322fe8fb19SBen Gras 	void	*context;		/* Hesiod context */
7332fe8fb19SBen Gras 	int	 num;			/* passwd index, -1 if no more */
7342fe8fb19SBen Gras };
7352fe8fb19SBen Gras 
7362fe8fb19SBen Gras static struct dns_state		_dns_state;
7372fe8fb19SBen Gras 					/* storage for non _r functions */
7382fe8fb19SBen Gras static struct passwd		_dns_passwd;
7392fe8fb19SBen Gras static char			_dns_passwdbuf[_GETPW_R_SIZE_MAX];
7402fe8fb19SBen Gras 
7412fe8fb19SBen Gras static int
_dns_start(struct dns_state * state)7422fe8fb19SBen Gras _dns_start(struct dns_state *state)
7432fe8fb19SBen Gras {
7442fe8fb19SBen Gras 
7452fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
7462fe8fb19SBen Gras 
7472fe8fb19SBen Gras 	state->num = 0;
7482fe8fb19SBen Gras 	if (state->context == NULL) {			/* setup Hesiod */
7492fe8fb19SBen Gras 		if (hesiod_init(&state->context) == -1)
7502fe8fb19SBen Gras 			return NS_UNAVAIL;
7512fe8fb19SBen Gras 	}
7522fe8fb19SBen Gras 
7532fe8fb19SBen Gras 	return NS_SUCCESS;
7542fe8fb19SBen Gras }
7552fe8fb19SBen Gras 
7562fe8fb19SBen Gras static int
_dns_end(struct dns_state * state)7572fe8fb19SBen Gras _dns_end(struct dns_state *state)
7582fe8fb19SBen Gras {
7592fe8fb19SBen Gras 
7602fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
7612fe8fb19SBen Gras 
7622fe8fb19SBen Gras 	state->num = 0;
7632fe8fb19SBen Gras 	if (state->context) {
7642fe8fb19SBen Gras 		hesiod_end(state->context);
7652fe8fb19SBen Gras 		state->context = NULL;
7662fe8fb19SBen Gras 	}
7672fe8fb19SBen Gras 	return NS_SUCCESS;
7682fe8fb19SBen Gras }
7692fe8fb19SBen Gras 
7702fe8fb19SBen Gras /*
7712fe8fb19SBen Gras  * _dns_pwscan
7722fe8fb19SBen Gras  *	Look for the Hesiod name provided in buffer in the NULL-terminated
7732fe8fb19SBen Gras  *	list of zones,
7742fe8fb19SBen Gras  *	and decode into pw/buffer/buflen.
7752fe8fb19SBen Gras  */
7762fe8fb19SBen Gras static int
_dns_pwscan(int * retval,struct passwd * pw,char * buffer,size_t buflen,struct dns_state * state,const char ** zones)7772fe8fb19SBen Gras _dns_pwscan(int *retval, struct passwd *pw, char *buffer, size_t buflen,
7782fe8fb19SBen Gras 	struct dns_state *state, const char **zones)
7792fe8fb19SBen Gras {
7802fe8fb19SBen Gras 	const char	**curzone;
7812fe8fb19SBen Gras 	char		**hp, *ep;
7822fe8fb19SBen Gras 	int		rv;
7832fe8fb19SBen Gras 
7842fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
7852fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
7862fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
7872fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
7882fe8fb19SBen Gras 	_DIAGASSERT(zones != NULL);
7892fe8fb19SBen Gras 
7902fe8fb19SBen Gras 	*retval = 0;
7912fe8fb19SBen Gras 
7922fe8fb19SBen Gras 	if (state->context == NULL) {	/* only start if Hesiod not setup */
7932fe8fb19SBen Gras 		rv = _dns_start(state);
7942fe8fb19SBen Gras 		if (rv != NS_SUCCESS)
7952fe8fb19SBen Gras 			return rv;
7962fe8fb19SBen Gras 	}
7972fe8fb19SBen Gras 
7982fe8fb19SBen Gras 	hp = NULL;
7992fe8fb19SBen Gras 	rv = NS_NOTFOUND;
8002fe8fb19SBen Gras 
8012fe8fb19SBen Gras 	for (curzone = zones; *curzone; curzone++) {	/* search zones */
8022fe8fb19SBen Gras 		hp = hesiod_resolve(state->context, buffer, *curzone);
8032fe8fb19SBen Gras 		if (hp != NULL)
8042fe8fb19SBen Gras 			break;
8052fe8fb19SBen Gras 		if (errno != ENOENT) {
8062fe8fb19SBen Gras 			rv = NS_UNAVAIL;
8072fe8fb19SBen Gras 			goto dnspwscan_out;
8082fe8fb19SBen Gras 		}
8092fe8fb19SBen Gras 	}
8102fe8fb19SBen Gras 	if (*curzone == NULL)
8112fe8fb19SBen Gras 		goto dnspwscan_out;
8122fe8fb19SBen Gras 
8132fe8fb19SBen Gras 	if ((ep = strchr(hp[0], '\n')) != NULL)
8142fe8fb19SBen Gras 		*ep = '\0';				/* clear trailing \n */
8152fe8fb19SBen Gras 	if (_pw_parse(hp[0], pw, buffer, buflen, 1))	/* validate line */
8162fe8fb19SBen Gras 		rv = NS_SUCCESS;
8172fe8fb19SBen Gras 	else
8182fe8fb19SBen Gras 		rv = NS_UNAVAIL;
8192fe8fb19SBen Gras 
8202fe8fb19SBen Gras  dnspwscan_out:
8212fe8fb19SBen Gras 	if (rv != NS_SUCCESS && rv != NS_NOTFOUND)
8222fe8fb19SBen Gras 		*retval = errno;
8232fe8fb19SBen Gras 	if (hp)
8242fe8fb19SBen Gras 		hesiod_free_list(state->context, hp);
8252fe8fb19SBen Gras 	return rv;
8262fe8fb19SBen Gras }
8272fe8fb19SBen Gras 
8282fe8fb19SBen Gras /*ARGSUSED*/
8292fe8fb19SBen Gras static int
_dns_setpwent(void * nsrv,void * nscb,va_list ap)8302fe8fb19SBen Gras _dns_setpwent(void *nsrv, void *nscb, va_list ap)
8312fe8fb19SBen Gras {
8322fe8fb19SBen Gras 
8332fe8fb19SBen Gras 	_dns_state.stayopen = 0;
8342fe8fb19SBen Gras 	return _dns_start(&_dns_state);
8352fe8fb19SBen Gras }
8362fe8fb19SBen Gras 
8372fe8fb19SBen Gras /*ARGSUSED*/
8382fe8fb19SBen Gras static int
_dns_setpassent(void * nsrv,void * nscb,va_list ap)8392fe8fb19SBen Gras _dns_setpassent(void *nsrv, void *nscb, va_list ap)
8402fe8fb19SBen Gras {
8412fe8fb19SBen Gras 	int	*retval		= va_arg(ap, int *);
8422fe8fb19SBen Gras 	int	 stayopen	= va_arg(ap, int);
8432fe8fb19SBen Gras 
8442fe8fb19SBen Gras 	int	rv;
8452fe8fb19SBen Gras 
8462fe8fb19SBen Gras 	_dns_state.stayopen = stayopen;
8472fe8fb19SBen Gras 	rv = _dns_start(&_dns_state);
8482fe8fb19SBen Gras 	*retval = (rv == NS_SUCCESS);
8492fe8fb19SBen Gras 	return rv;
8502fe8fb19SBen Gras }
8512fe8fb19SBen Gras 
8522fe8fb19SBen Gras /*ARGSUSED*/
8532fe8fb19SBen Gras static int
_dns_endpwent(void * nsrv,void * nscb,va_list ap)8542fe8fb19SBen Gras _dns_endpwent(void *nsrv, void *nscb, va_list ap)
8552fe8fb19SBen Gras {
8562fe8fb19SBen Gras 
8572fe8fb19SBen Gras 	_dns_state.stayopen = 0;
8582fe8fb19SBen Gras 	return _dns_end(&_dns_state);
8592fe8fb19SBen Gras }
8602fe8fb19SBen Gras 
8612fe8fb19SBen Gras /*ARGSUSED*/
8622fe8fb19SBen Gras static int
_dns_getpwent(void * nsrv,void * nscb,va_list ap)8632fe8fb19SBen Gras _dns_getpwent(void *nsrv, void *nscb, va_list ap)
8642fe8fb19SBen Gras {
8652fe8fb19SBen Gras 	struct passwd	**retval = va_arg(ap, struct passwd **);
8662fe8fb19SBen Gras 
8672fe8fb19SBen Gras 	char	**hp, *ep;
8682fe8fb19SBen Gras 	int	  rv;
8692fe8fb19SBen Gras 
8702fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
8712fe8fb19SBen Gras 
8722fe8fb19SBen Gras 	*retval = NULL;
8732fe8fb19SBen Gras 
8742fe8fb19SBen Gras 	if (_dns_state.num == -1)			/* exhausted search */
8752fe8fb19SBen Gras 		return NS_NOTFOUND;
8762fe8fb19SBen Gras 
8772fe8fb19SBen Gras 	if (_dns_state.context == NULL) {
8782fe8fb19SBen Gras 			/* only start if Hesiod not setup */
8792fe8fb19SBen Gras 		rv = _dns_start(&_dns_state);
8802fe8fb19SBen Gras 		if (rv != NS_SUCCESS)
8812fe8fb19SBen Gras 			return rv;
8822fe8fb19SBen Gras 	}
8832fe8fb19SBen Gras 
8842fe8fb19SBen Gras  next_dns_entry:
8852fe8fb19SBen Gras 	hp = NULL;
8862fe8fb19SBen Gras 	rv = NS_NOTFOUND;
8872fe8fb19SBen Gras 
8882fe8fb19SBen Gras 							/* find passwd-NNN */
8892fe8fb19SBen Gras 	snprintf(_dns_passwdbuf, sizeof(_dns_passwdbuf),
8902fe8fb19SBen Gras 	    "passwd-%u", _dns_state.num);
8912fe8fb19SBen Gras 	_dns_state.num++;
8922fe8fb19SBen Gras 
8932fe8fb19SBen Gras 	hp = hesiod_resolve(_dns_state.context, _dns_passwdbuf, "passwd");
8942fe8fb19SBen Gras 	if (hp == NULL) {
8952fe8fb19SBen Gras 		if (errno == ENOENT)
8962fe8fb19SBen Gras 			_dns_state.num = -1;
8972fe8fb19SBen Gras 		else
8982fe8fb19SBen Gras 			rv = NS_UNAVAIL;
8992fe8fb19SBen Gras 	} else {
9002fe8fb19SBen Gras 		if ((ep = strchr(hp[0], '\n')) != NULL)
9012fe8fb19SBen Gras 			*ep = '\0';			/* clear trailing \n */
9022fe8fb19SBen Gras 							/* validate line */
9032fe8fb19SBen Gras 		if (_pw_parse(hp[0], &_dns_passwd,
9042fe8fb19SBen Gras 		    _dns_passwdbuf, sizeof(_dns_passwdbuf), 1))
9052fe8fb19SBen Gras 			rv = NS_SUCCESS;
9062fe8fb19SBen Gras 		else {				/* dodgy entry, try again */
9072fe8fb19SBen Gras 			hesiod_free_list(_dns_state.context, hp);
9082fe8fb19SBen Gras 			goto next_dns_entry;
9092fe8fb19SBen Gras 		}
9102fe8fb19SBen Gras 	}
9112fe8fb19SBen Gras 
9122fe8fb19SBen Gras 	if (hp)
9132fe8fb19SBen Gras 		hesiod_free_list(_dns_state.context, hp);
9142fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
9152fe8fb19SBen Gras 		*retval = &_dns_passwd;
9162fe8fb19SBen Gras 	return rv;
9172fe8fb19SBen Gras }
9182fe8fb19SBen Gras 
9192fe8fb19SBen Gras /*ARGSUSED*/
9202fe8fb19SBen Gras static int
_dns_getpwent_r(void * nsrv,void * nscb,va_list ap)9212fe8fb19SBen Gras _dns_getpwent_r(void *nsrv, void *nscb, va_list ap)
9222fe8fb19SBen Gras {
9232fe8fb19SBen Gras 	int		*retval	= va_arg(ap, int *);
9242fe8fb19SBen Gras 	struct passwd	*pw	= va_arg(ap, struct passwd *);
9252fe8fb19SBen Gras 	char		*buffer	= va_arg(ap, char *);
9262fe8fb19SBen Gras 	size_t		 buflen	= va_arg(ap, size_t);
9272fe8fb19SBen Gras 	struct passwd  **result	= va_arg(ap, struct passwd **);
9282fe8fb19SBen Gras 
9292fe8fb19SBen Gras 	char	**hp, *ep;
9302fe8fb19SBen Gras 	int	  rv;
9312fe8fb19SBen Gras 
9322fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
9332fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
9342fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
9352fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
9362fe8fb19SBen Gras 
9372fe8fb19SBen Gras 	*retval = 0;
9382fe8fb19SBen Gras 
9392fe8fb19SBen Gras 	if (_dns_state.num == -1)			/* exhausted search */
9402fe8fb19SBen Gras 		return NS_NOTFOUND;
9412fe8fb19SBen Gras 
9422fe8fb19SBen Gras 	if (_dns_state.context == NULL) {
9432fe8fb19SBen Gras 			/* only start if Hesiod not setup */
9442fe8fb19SBen Gras 		rv = _dns_start(&_dns_state);
9452fe8fb19SBen Gras 		if (rv != NS_SUCCESS)
9462fe8fb19SBen Gras 			return rv;
9472fe8fb19SBen Gras 	}
9482fe8fb19SBen Gras 
9492fe8fb19SBen Gras  next_dns_entry:
9502fe8fb19SBen Gras 	hp = NULL;
9512fe8fb19SBen Gras 	rv = NS_NOTFOUND;
9522fe8fb19SBen Gras 
9532fe8fb19SBen Gras 							/* find passwd-NNN */
9542fe8fb19SBen Gras 	snprintf(buffer, buflen, "passwd-%u", _dns_state.num);
9552fe8fb19SBen Gras 	_dns_state.num++;
9562fe8fb19SBen Gras 
9572fe8fb19SBen Gras 	hp = hesiod_resolve(_dns_state.context, buffer, "passwd");
9582fe8fb19SBen Gras 	if (hp == NULL) {
9592fe8fb19SBen Gras 		if (errno == ENOENT)
9602fe8fb19SBen Gras 			_dns_state.num = -1;
9612fe8fb19SBen Gras 		else
9622fe8fb19SBen Gras 			rv = NS_UNAVAIL;
9632fe8fb19SBen Gras 	} else {
9642fe8fb19SBen Gras 		if ((ep = strchr(hp[0], '\n')) != NULL)
9652fe8fb19SBen Gras 			*ep = '\0';			/* clear trailing \n */
9662fe8fb19SBen Gras 							/* validate line */
9672fe8fb19SBen Gras 		if (_pw_parse(hp[0], pw, buffer, buflen, 1))
9682fe8fb19SBen Gras 			rv = NS_SUCCESS;
9692fe8fb19SBen Gras 		else {				/* dodgy entry, try again */
9702fe8fb19SBen Gras 			hesiod_free_list(_dns_state.context, hp);
9712fe8fb19SBen Gras 			goto next_dns_entry;
9722fe8fb19SBen Gras 		}
9732fe8fb19SBen Gras 	}
9742fe8fb19SBen Gras 
9752fe8fb19SBen Gras 	if (hp)
9762fe8fb19SBen Gras 		hesiod_free_list(_dns_state.context, hp);
9772fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
9782fe8fb19SBen Gras 		*result = pw;
9792fe8fb19SBen Gras 	else
9802fe8fb19SBen Gras 		*result = NULL;
9812fe8fb19SBen Gras 	return rv;
9822fe8fb19SBen Gras }
9832fe8fb19SBen Gras 
9842fe8fb19SBen Gras static const char *_dns_uid_zones[] = {
9852fe8fb19SBen Gras 	"uid",
9862fe8fb19SBen Gras 	"passwd",
9872fe8fb19SBen Gras 	NULL
9882fe8fb19SBen Gras };
9892fe8fb19SBen Gras 
9902fe8fb19SBen Gras /*ARGSUSED*/
9912fe8fb19SBen Gras static int
_dns_getpwuid(void * nsrv,void * nscb,va_list ap)9922fe8fb19SBen Gras _dns_getpwuid(void *nsrv, void *nscb, va_list ap)
9932fe8fb19SBen Gras {
9942fe8fb19SBen Gras 	struct passwd	**retval = va_arg(ap, struct passwd **);
9952fe8fb19SBen Gras 	uid_t		 uid	= va_arg(ap, uid_t);
9962fe8fb19SBen Gras 
9972fe8fb19SBen Gras 	int	rv, rerror;
9982fe8fb19SBen Gras 
9992fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
10002fe8fb19SBen Gras 
10012fe8fb19SBen Gras 	*retval = NULL;
10022fe8fb19SBen Gras 	rv = _dns_start(&_dns_state);
10032fe8fb19SBen Gras 	if (rv != NS_SUCCESS)
10042fe8fb19SBen Gras 		return rv;
10052fe8fb19SBen Gras 	snprintf(_dns_passwdbuf, sizeof(_dns_passwdbuf),
10062fe8fb19SBen Gras 	    "%u", (unsigned int)uid);
10072fe8fb19SBen Gras 	rv = _dns_pwscan(&rerror, &_dns_passwd,
10082fe8fb19SBen Gras 	    _dns_passwdbuf, sizeof(_dns_passwdbuf),
10092fe8fb19SBen Gras 	    &_dns_state, _dns_uid_zones);
10102fe8fb19SBen Gras 	if (!_dns_state.stayopen)
10112fe8fb19SBen Gras 		_dns_end(&_dns_state);
10122fe8fb19SBen Gras 	if (rv == NS_SUCCESS && uid == _dns_passwd.pw_uid)
10132fe8fb19SBen Gras 		*retval = &_dns_passwd;
10142fe8fb19SBen Gras 	return rv;
10152fe8fb19SBen Gras }
10162fe8fb19SBen Gras 
10172fe8fb19SBen Gras /*ARGSUSED*/
10182fe8fb19SBen Gras static int
_dns_getpwuid_r(void * nsrv,void * nscb,va_list ap)10192fe8fb19SBen Gras _dns_getpwuid_r(void *nsrv, void *nscb, va_list ap)
10202fe8fb19SBen Gras {
10212fe8fb19SBen Gras 	int		*retval	= va_arg(ap, int *);
10222fe8fb19SBen Gras 	uid_t		 uid	= va_arg(ap, uid_t);
10232fe8fb19SBen Gras 	struct passwd	*pw	= va_arg(ap, struct passwd *);
10242fe8fb19SBen Gras 	char		*buffer	= va_arg(ap, char *);
10252fe8fb19SBen Gras 	size_t		 buflen	= va_arg(ap, size_t);
10262fe8fb19SBen Gras 	struct passwd  **result	= va_arg(ap, struct passwd **);
10272fe8fb19SBen Gras 
10282fe8fb19SBen Gras 	struct dns_state state;
10292fe8fb19SBen Gras 	int	rv;
10302fe8fb19SBen Gras 
10312fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
10322fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
10332fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
10342fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
10352fe8fb19SBen Gras 
10362fe8fb19SBen Gras 	*result = NULL;
10372fe8fb19SBen Gras 	memset(&state, 0, sizeof(state));
10382fe8fb19SBen Gras 	snprintf(buffer, buflen, "%u", (unsigned int)uid);
10392fe8fb19SBen Gras 	rv = _dns_pwscan(retval, pw, buffer, buflen, &state, _dns_uid_zones);
10402fe8fb19SBen Gras 	_dns_end(&state);
10412fe8fb19SBen Gras 	if (rv != NS_SUCCESS)
10422fe8fb19SBen Gras 		return rv;
10432fe8fb19SBen Gras 	if (uid == pw->pw_uid) {
10442fe8fb19SBen Gras 		*result = pw;
10452fe8fb19SBen Gras 		return NS_SUCCESS;
10462fe8fb19SBen Gras 	} else
10472fe8fb19SBen Gras 		return NS_NOTFOUND;
10482fe8fb19SBen Gras }
10492fe8fb19SBen Gras 
10502fe8fb19SBen Gras static const char *_dns_nam_zones[] = {
10512fe8fb19SBen Gras 	"passwd",
10522fe8fb19SBen Gras 	NULL
10532fe8fb19SBen Gras };
10542fe8fb19SBen Gras 
10552fe8fb19SBen Gras /*ARGSUSED*/
10562fe8fb19SBen Gras static int
_dns_getpwnam(void * nsrv,void * nscb,va_list ap)10572fe8fb19SBen Gras _dns_getpwnam(void *nsrv, void *nscb, va_list ap)
10582fe8fb19SBen Gras {
10592fe8fb19SBen Gras 	struct passwd	**retval = va_arg(ap, struct passwd **);
10602fe8fb19SBen Gras 	const char	*name	= va_arg(ap, const char *);
10612fe8fb19SBen Gras 
10622fe8fb19SBen Gras 	int	rv, rerror;
10632fe8fb19SBen Gras 
10642fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
10652fe8fb19SBen Gras 
10662fe8fb19SBen Gras 	*retval = NULL;
10672fe8fb19SBen Gras 	rv = _dns_start(&_dns_state);
10682fe8fb19SBen Gras 	if (rv != NS_SUCCESS)
10692fe8fb19SBen Gras 		return rv;
10702fe8fb19SBen Gras 	snprintf(_dns_passwdbuf, sizeof(_dns_passwdbuf), "%s", name);
10712fe8fb19SBen Gras 	rv = _dns_pwscan(&rerror, &_dns_passwd,
10722fe8fb19SBen Gras 	    _dns_passwdbuf, sizeof(_dns_passwdbuf),
10732fe8fb19SBen Gras 	    &_dns_state, _dns_nam_zones);
10742fe8fb19SBen Gras 	if (!_dns_state.stayopen)
10752fe8fb19SBen Gras 		_dns_end(&_dns_state);
10762fe8fb19SBen Gras 	if (rv == NS_SUCCESS && strcmp(name, _dns_passwd.pw_name) == 0)
10772fe8fb19SBen Gras 		*retval = &_dns_passwd;
10782fe8fb19SBen Gras 	return rv;
10792fe8fb19SBen Gras }
10802fe8fb19SBen Gras 
10812fe8fb19SBen Gras /*ARGSUSED*/
10822fe8fb19SBen Gras static int
_dns_getpwnam_r(void * nsrv,void * nscb,va_list ap)10832fe8fb19SBen Gras _dns_getpwnam_r(void *nsrv, void *nscb, va_list ap)
10842fe8fb19SBen Gras {
10852fe8fb19SBen Gras 	int		*retval	= va_arg(ap, int *);
10862fe8fb19SBen Gras 	const char	*name	= va_arg(ap, const char *);
10872fe8fb19SBen Gras 	struct passwd	*pw	= va_arg(ap, struct passwd *);
10882fe8fb19SBen Gras 	char		*buffer	= va_arg(ap, char *);
10892fe8fb19SBen Gras 	size_t		 buflen	= va_arg(ap, size_t);
10902fe8fb19SBen Gras 	struct passwd  **result	= va_arg(ap, struct passwd **);
10912fe8fb19SBen Gras 
10922fe8fb19SBen Gras 	struct dns_state state;
10932fe8fb19SBen Gras 	int	rv;
10942fe8fb19SBen Gras 
10952fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
10962fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
10972fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
10982fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
10992fe8fb19SBen Gras 
11002fe8fb19SBen Gras 	*result = NULL;
11012fe8fb19SBen Gras 	memset(&state, 0, sizeof(state));
11022fe8fb19SBen Gras 	snprintf(buffer, buflen, "%s", name);
11032fe8fb19SBen Gras 	rv = _dns_pwscan(retval, pw, buffer, buflen, &state, _dns_nam_zones);
11042fe8fb19SBen Gras 	_dns_end(&state);
11052fe8fb19SBen Gras 	if (rv != NS_SUCCESS)
11062fe8fb19SBen Gras 		return rv;
11072fe8fb19SBen Gras 	if (strcmp(name, pw->pw_name) == 0) {
11082fe8fb19SBen Gras 		*result = pw;
11092fe8fb19SBen Gras 		return NS_SUCCESS;
11102fe8fb19SBen Gras 	} else
11112fe8fb19SBen Gras 		return NS_NOTFOUND;
11122fe8fb19SBen Gras }
11132fe8fb19SBen Gras 
11142fe8fb19SBen Gras #endif /* HESIOD */
11152fe8fb19SBen Gras 
11162fe8fb19SBen Gras 
11172fe8fb19SBen Gras #ifdef YP
11182fe8fb19SBen Gras 		/*
11192fe8fb19SBen Gras 		 *	nis methods
11202fe8fb19SBen Gras 		 */
11212fe8fb19SBen Gras 	/* state shared between nis methods */
11222fe8fb19SBen Gras struct nis_state {
11232fe8fb19SBen Gras 	int		 stayopen;	/* see getpassent(3) */
11242fe8fb19SBen Gras 	char		*domain;	/* NIS domain */
11252fe8fb19SBen Gras 	int		 done;		/* non-zero if search exhausted */
11262fe8fb19SBen Gras 	char		*current;	/* current first/next match */
11272fe8fb19SBen Gras 	int		 currentlen;	/* length of _nis_current */
11282fe8fb19SBen Gras 	enum {				/* shadow map type */
1129*f14fb602SLionel Sambuc 		NISMAP_UNKNOWN = 0,	/*  unknown ... */
11302fe8fb19SBen Gras 		NISMAP_NONE,		/*  none: use "passwd.by*" */
11312fe8fb19SBen Gras 		NISMAP_ADJUNCT,		/*  pw_passwd from "passwd.adjunct.*" */
11322fe8fb19SBen Gras 		NISMAP_MASTER		/*  all from "master.passwd.by*" */
11332fe8fb19SBen Gras 	}		 maptype;
11342fe8fb19SBen Gras };
11352fe8fb19SBen Gras 
11362fe8fb19SBen Gras static struct nis_state		_nis_state;
11372fe8fb19SBen Gras 					/* storage for non _r functions */
11382fe8fb19SBen Gras static struct passwd		_nis_passwd;
11392fe8fb19SBen Gras static char			_nis_passwdbuf[_GETPW_R_SIZE_MAX];
11402fe8fb19SBen Gras 
1141*f14fb602SLionel Sambuc static const char __nis_pw_n_1[] = "master.passwd.byname";
1142*f14fb602SLionel Sambuc static const char __nis_pw_n_2[] = "passwd.byname";
1143*f14fb602SLionel Sambuc static const char __nis_pw_u_1[] = "master.passwd.byuid";
1144*f14fb602SLionel Sambuc static const char __nis_pw_u_2[] = "passwd.byuid";
1145*f14fb602SLionel Sambuc 
1146*f14fb602SLionel Sambuc static const char * const __nis_pw_n_map[4] = { __nis_pw_n_2, __nis_pw_n_2, __nis_pw_n_2, __nis_pw_n_1 };
1147*f14fb602SLionel Sambuc static const char * const __nis_pw_u_map[4] = { __nis_pw_u_2, __nis_pw_u_2, __nis_pw_u_2, __nis_pw_u_1 };
1148*f14fb602SLionel Sambuc 
11492fe8fb19SBen Gras 	/* macros for deciding which NIS maps to use. */
1150*f14fb602SLionel Sambuc #define	PASSWD_BYNAME(x)	((x)->maptype == NISMAP_MASTER ? __nis_pw_n_1 : __nis_pw_n_2)
1151*f14fb602SLionel Sambuc #define	PASSWD_BYUID(x)		((x)->maptype == NISMAP_MASTER ? __nis_pw_u_1 : __nis_pw_u_2)
11522fe8fb19SBen Gras 
11532fe8fb19SBen Gras static int
_nis_start(struct nis_state * state)11542fe8fb19SBen Gras _nis_start(struct nis_state *state)
11552fe8fb19SBen Gras {
11562fe8fb19SBen Gras 
11572fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
11582fe8fb19SBen Gras 
11592fe8fb19SBen Gras 	state->done = 0;
11602fe8fb19SBen Gras 	if (state->current) {
11612fe8fb19SBen Gras 		free(state->current);
11622fe8fb19SBen Gras 		state->current = NULL;
11632fe8fb19SBen Gras 	}
11642fe8fb19SBen Gras 	if (state->domain == NULL) {			/* setup NIS */
11652fe8fb19SBen Gras 		switch (yp_get_default_domain(&state->domain)) {
11662fe8fb19SBen Gras 		case 0:
11672fe8fb19SBen Gras 			break;
11682fe8fb19SBen Gras 		case YPERR_RESRC:
11692fe8fb19SBen Gras 			return NS_TRYAGAIN;
11702fe8fb19SBen Gras 		default:
11712fe8fb19SBen Gras 			return NS_UNAVAIL;
11722fe8fb19SBen Gras 		}
11732fe8fb19SBen Gras 	}
11742fe8fb19SBen Gras 
11752fe8fb19SBen Gras 				/* determine where to get pw_passwd from */
11762fe8fb19SBen Gras 	if (state->maptype == NISMAP_UNKNOWN) {
11772fe8fb19SBen Gras 		int	r, order;
11782fe8fb19SBen Gras 
11792fe8fb19SBen Gras 		state->maptype = NISMAP_NONE;	/* default to no adjunct */
11802fe8fb19SBen Gras 		if (geteuid() != 0)		/* non-root can't use adjunct */
11812fe8fb19SBen Gras 			return NS_SUCCESS;
11822fe8fb19SBen Gras 
11832fe8fb19SBen Gras 						/* look for "master.passwd.*" */
11842fe8fb19SBen Gras 		r = yp_order(state->domain, "master.passwd.byname", &order);
11852fe8fb19SBen Gras 		if (r == 0) {
11862fe8fb19SBen Gras 			state->maptype = NISMAP_MASTER;
11872fe8fb19SBen Gras 			return NS_SUCCESS;
11882fe8fb19SBen Gras 		}
11892fe8fb19SBen Gras 
11902fe8fb19SBen Gras 			/* master.passwd doesn't exist, try passwd.adjunct */
11912fe8fb19SBen Gras 		if (r == YPERR_MAP) {
11922fe8fb19SBen Gras 			r = yp_order(state->domain, "passwd.adjunct.byname",
11932fe8fb19SBen Gras 			    &order);
11942fe8fb19SBen Gras 			if (r == 0)
11952fe8fb19SBen Gras 				state->maptype = NISMAP_ADJUNCT;
11962fe8fb19SBen Gras 		}
11972fe8fb19SBen Gras 	}
11982fe8fb19SBen Gras 	return NS_SUCCESS;
11992fe8fb19SBen Gras }
12002fe8fb19SBen Gras 
12012fe8fb19SBen Gras static int
_nis_end(struct nis_state * state)12022fe8fb19SBen Gras _nis_end(struct nis_state *state)
12032fe8fb19SBen Gras {
12042fe8fb19SBen Gras 
12052fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
12062fe8fb19SBen Gras 
12072fe8fb19SBen Gras 	if (state->domain)
12082fe8fb19SBen Gras 		state->domain = NULL;
12092fe8fb19SBen Gras 	state->done = 0;
12102fe8fb19SBen Gras 	if (state->current)
12112fe8fb19SBen Gras 		free(state->current);
12122fe8fb19SBen Gras 	state->current = NULL;
12132fe8fb19SBen Gras 	state->maptype = NISMAP_UNKNOWN;
12142fe8fb19SBen Gras 	return NS_SUCCESS;
12152fe8fb19SBen Gras }
12162fe8fb19SBen Gras 
12172fe8fb19SBen Gras /*
12182fe8fb19SBen Gras  * nis_parse
12192fe8fb19SBen Gras  *	wrapper to _pw_parse that obtains the real password from the
12202fe8fb19SBen Gras  *	"passwd.adjunct.byname" NIS map if the maptype is NISMAP_ADJUNCT.
12212fe8fb19SBen Gras  */
12222fe8fb19SBen Gras static int
_nis_parse(const char * entry,struct passwd * pw,char * buf,size_t buflen,struct nis_state * state)12232fe8fb19SBen Gras _nis_parse(const char *entry, struct passwd *pw, char *buf, size_t buflen,
12242fe8fb19SBen Gras 	struct nis_state *state)
12252fe8fb19SBen Gras {
12262fe8fb19SBen Gras 	size_t	elen;
12272fe8fb19SBen Gras 
12282fe8fb19SBen Gras 	_DIAGASSERT(entry != NULL);
12292fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
12302fe8fb19SBen Gras 	_DIAGASSERT(buf != NULL);
12312fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
12322fe8fb19SBen Gras 
1233*f14fb602SLionel Sambuc 	elen = strlen(entry) + 1;
12342fe8fb19SBen Gras 	if (elen >= buflen)
12352fe8fb19SBen Gras 		return 0;
12362fe8fb19SBen Gras 	if (! _pw_parse(entry, pw, buf, buflen,
12372fe8fb19SBen Gras 	    !(state->maptype == NISMAP_MASTER)))
12382fe8fb19SBen Gras 		return 0;
12392fe8fb19SBen Gras 
12402fe8fb19SBen Gras 	if ((state->maptype == NISMAP_ADJUNCT) &&
12412fe8fb19SBen Gras 	    (strstr(pw->pw_passwd, "##") != NULL)) {
12422fe8fb19SBen Gras 		char	*data;
12432fe8fb19SBen Gras 		int	datalen;
12442fe8fb19SBen Gras 
12452fe8fb19SBen Gras 		if (yp_match(state->domain, "passwd.adjunct.byname",
12462fe8fb19SBen Gras 		    pw->pw_name, (int)strlen(pw->pw_name),
12472fe8fb19SBen Gras 		    &data, &datalen) == 0) {
12482fe8fb19SBen Gras 			char	*bp, *ep;
12492fe8fb19SBen Gras 						/* skip name to get password */
12502fe8fb19SBen Gras 			ep = data;
1251*f14fb602SLionel Sambuc 			if (strsep(&ep, ":") != NULL &&
12522fe8fb19SBen Gras 			    (bp = strsep(&ep, ":")) != NULL) {
12532fe8fb19SBen Gras 					/* store new pw_passwd after entry */
1254*f14fb602SLionel Sambuc 				if (strlcpy(buf + elen, bp, buflen - elen) >=
1255*f14fb602SLionel Sambuc 				    buflen - elen) {
1256*f14fb602SLionel Sambuc 					free(data);
1257*f14fb602SLionel Sambuc 					return 0;
1258*f14fb602SLionel Sambuc 				}
12592fe8fb19SBen Gras 				pw->pw_passwd = &buf[elen];
12602fe8fb19SBen Gras 			}
12612fe8fb19SBen Gras 			free(data);
12622fe8fb19SBen Gras 		}
12632fe8fb19SBen Gras 	}
12642fe8fb19SBen Gras 
12652fe8fb19SBen Gras 	return 1;
12662fe8fb19SBen Gras }
12672fe8fb19SBen Gras 
12682fe8fb19SBen Gras 
12692fe8fb19SBen Gras /*
12702fe8fb19SBen Gras  * _nis_pwscan
12712fe8fb19SBen Gras  *	Look for the yp key provided in buffer from map,
12722fe8fb19SBen Gras  *	and decode into pw/buffer/buflen.
12732fe8fb19SBen Gras  */
12742fe8fb19SBen Gras static int
_nis_pwscan(int * retval,struct passwd * pw,char * buffer,size_t buflen,struct nis_state * state,const char * const * map_arr,size_t nmaps)12752fe8fb19SBen Gras _nis_pwscan(int *retval, struct passwd *pw, char *buffer, size_t buflen,
1276*f14fb602SLionel Sambuc 	struct nis_state *state, const char * const *map_arr, size_t nmaps)
12772fe8fb19SBen Gras {
12782fe8fb19SBen Gras 	char	*data;
12792fe8fb19SBen Gras 	int	nisr, rv, datalen;
12802fe8fb19SBen Gras 
12812fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
12822fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
12832fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
12842fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
1285*f14fb602SLionel Sambuc 	_DIAGASSERT(map_arr != NULL);
12862fe8fb19SBen Gras 
12872fe8fb19SBen Gras 	*retval = 0;
12882fe8fb19SBen Gras 
12892fe8fb19SBen Gras 	if (state->domain == NULL) {	/* only start if NIS not setup */
12902fe8fb19SBen Gras 		rv = _nis_start(state);
12912fe8fb19SBen Gras 		if (rv != NS_SUCCESS)
12922fe8fb19SBen Gras 			return rv;
12932fe8fb19SBen Gras 	}
12942fe8fb19SBen Gras 
12952fe8fb19SBen Gras 	data = NULL;
12962fe8fb19SBen Gras 	rv = NS_NOTFOUND;
1297*f14fb602SLionel Sambuc 	_DIAGASSERT(state->maptype != NISMAP_UNKNOWN &&
1298*f14fb602SLionel Sambuc 		    (unsigned)state->maptype < nmaps);
12992fe8fb19SBen Gras 
13002fe8fb19SBen Gras 							/* search map */
1301*f14fb602SLionel Sambuc 	nisr = yp_match(state->domain, map_arr[state->maptype], buffer, (int)strlen(buffer),
13022fe8fb19SBen Gras 	    &data, &datalen);
13032fe8fb19SBen Gras 	switch (nisr) {
13042fe8fb19SBen Gras 	case 0:
13052fe8fb19SBen Gras 		data[datalen] = '\0';			/* clear trailing \n */
13062fe8fb19SBen Gras 		if (_nis_parse(data, pw, buffer, buflen, state))
13072fe8fb19SBen Gras 			rv = NS_SUCCESS;		/* validate line */
13082fe8fb19SBen Gras 		else
13092fe8fb19SBen Gras 			rv = NS_UNAVAIL;
13102fe8fb19SBen Gras 		break;
13112fe8fb19SBen Gras 	case YPERR_KEY:
13122fe8fb19SBen Gras 		break;
13132fe8fb19SBen Gras 	default:
13142fe8fb19SBen Gras 		rv = NS_UNAVAIL;
13152fe8fb19SBen Gras 		break;
13162fe8fb19SBen Gras 	}
13172fe8fb19SBen Gras 
13182fe8fb19SBen Gras 	if (rv != NS_SUCCESS && rv != NS_NOTFOUND)
13192fe8fb19SBen Gras 		*retval = errno;
13202fe8fb19SBen Gras 	if (data)
13212fe8fb19SBen Gras 		free(data);
13222fe8fb19SBen Gras 	return rv;
13232fe8fb19SBen Gras }
13242fe8fb19SBen Gras 
13252fe8fb19SBen Gras /*ARGSUSED*/
13262fe8fb19SBen Gras static int
_nis_setpwent(void * nsrv,void * nscb,va_list ap)13272fe8fb19SBen Gras _nis_setpwent(void *nsrv, void *nscb, va_list ap)
13282fe8fb19SBen Gras {
13292fe8fb19SBen Gras 
13302fe8fb19SBen Gras 	_nis_state.stayopen = 0;
13312fe8fb19SBen Gras 	return _nis_start(&_nis_state);
13322fe8fb19SBen Gras }
13332fe8fb19SBen Gras 
13342fe8fb19SBen Gras /*ARGSUSED*/
13352fe8fb19SBen Gras static int
_nis_setpassent(void * nsrv,void * nscb,va_list ap)13362fe8fb19SBen Gras _nis_setpassent(void *nsrv, void *nscb, va_list ap)
13372fe8fb19SBen Gras {
13382fe8fb19SBen Gras 	int	*retval		= va_arg(ap, int *);
13392fe8fb19SBen Gras 	int	 stayopen	= va_arg(ap, int);
13402fe8fb19SBen Gras 
13412fe8fb19SBen Gras 	int	rv;
13422fe8fb19SBen Gras 
13432fe8fb19SBen Gras 	_nis_state.stayopen = stayopen;
13442fe8fb19SBen Gras 	rv = _nis_start(&_nis_state);
13452fe8fb19SBen Gras 	*retval = (rv == NS_SUCCESS);
13462fe8fb19SBen Gras 	return rv;
13472fe8fb19SBen Gras }
13482fe8fb19SBen Gras 
13492fe8fb19SBen Gras /*ARGSUSED*/
13502fe8fb19SBen Gras static int
_nis_endpwent(void * nsrv,void * nscb,va_list ap)13512fe8fb19SBen Gras _nis_endpwent(void *nsrv, void *nscb, va_list ap)
13522fe8fb19SBen Gras {
13532fe8fb19SBen Gras 
13542fe8fb19SBen Gras 	return _nis_end(&_nis_state);
13552fe8fb19SBen Gras }
13562fe8fb19SBen Gras 
13572fe8fb19SBen Gras 
13582fe8fb19SBen Gras /*ARGSUSED*/
13592fe8fb19SBen Gras static int
_nis_getpwent(void * nsrv,void * nscb,va_list ap)13602fe8fb19SBen Gras _nis_getpwent(void *nsrv, void *nscb, va_list ap)
13612fe8fb19SBen Gras {
13622fe8fb19SBen Gras 	struct passwd	**retval = va_arg(ap, struct passwd **);
13632fe8fb19SBen Gras 
13642fe8fb19SBen Gras 	char	*key, *data;
13652fe8fb19SBen Gras 	int	keylen, datalen, rv, nisr;
13662fe8fb19SBen Gras 
13672fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
13682fe8fb19SBen Gras 
13692fe8fb19SBen Gras 	*retval = NULL;
13702fe8fb19SBen Gras 
13712fe8fb19SBen Gras 	if (_nis_state.done)				/* exhausted search */
13722fe8fb19SBen Gras 		return NS_NOTFOUND;
13732fe8fb19SBen Gras 	if (_nis_state.domain == NULL) {
13742fe8fb19SBen Gras 					/* only start if NIS not setup */
13752fe8fb19SBen Gras 		rv = _nis_start(&_nis_state);
13762fe8fb19SBen Gras 		if (rv != NS_SUCCESS)
13772fe8fb19SBen Gras 			return rv;
13782fe8fb19SBen Gras 	}
13792fe8fb19SBen Gras 
13802fe8fb19SBen Gras  next_nis_entry:
13812fe8fb19SBen Gras 	key = NULL;
13822fe8fb19SBen Gras 	data = NULL;
13832fe8fb19SBen Gras 	rv = NS_NOTFOUND;
13842fe8fb19SBen Gras 
13852fe8fb19SBen Gras 	if (_nis_state.current) {			/* already searching */
13862fe8fb19SBen Gras 		nisr = yp_next(_nis_state.domain, PASSWD_BYNAME(&_nis_state),
13872fe8fb19SBen Gras 		    _nis_state.current, _nis_state.currentlen,
13882fe8fb19SBen Gras 		    &key, &keylen, &data, &datalen);
13892fe8fb19SBen Gras 		free(_nis_state.current);
13902fe8fb19SBen Gras 		_nis_state.current = NULL;
13912fe8fb19SBen Gras 		switch (nisr) {
13922fe8fb19SBen Gras 		case 0:
13932fe8fb19SBen Gras 			_nis_state.current = key;
13942fe8fb19SBen Gras 			_nis_state.currentlen = keylen;
13952fe8fb19SBen Gras 			key = NULL;
13962fe8fb19SBen Gras 			break;
13972fe8fb19SBen Gras 		case YPERR_NOMORE:
13982fe8fb19SBen Gras 			_nis_state.done = 1;
13992fe8fb19SBen Gras 			goto nisent_out;
14002fe8fb19SBen Gras 		default:
14012fe8fb19SBen Gras 			rv = NS_UNAVAIL;
14022fe8fb19SBen Gras 			goto nisent_out;
14032fe8fb19SBen Gras 		}
14042fe8fb19SBen Gras 	} else {					/* new search */
14052fe8fb19SBen Gras 		if (yp_first(_nis_state.domain, PASSWD_BYNAME(&_nis_state),
14062fe8fb19SBen Gras 		    &_nis_state.current, &_nis_state.currentlen,
14072fe8fb19SBen Gras 		    &data, &datalen)) {
14082fe8fb19SBen Gras 			rv = NS_UNAVAIL;
14092fe8fb19SBen Gras 			goto nisent_out;
14102fe8fb19SBen Gras 		}
14112fe8fb19SBen Gras 	}
14122fe8fb19SBen Gras 
14132fe8fb19SBen Gras 	data[datalen] = '\0';				/* clear trailing \n */
14142fe8fb19SBen Gras 							/* validate line */
14152fe8fb19SBen Gras 	if (_nis_parse(data, &_nis_passwd,
14162fe8fb19SBen Gras 	    _nis_passwdbuf, sizeof(_nis_passwdbuf), &_nis_state))
14172fe8fb19SBen Gras 		rv = NS_SUCCESS;
14182fe8fb19SBen Gras 	else {					/* dodgy entry, try again */
14192fe8fb19SBen Gras 		free(data);
14202fe8fb19SBen Gras 		goto next_nis_entry;
14212fe8fb19SBen Gras 	}
14222fe8fb19SBen Gras 
14232fe8fb19SBen Gras  nisent_out:
14242fe8fb19SBen Gras 	if (key)
14252fe8fb19SBen Gras 		free(key);
14262fe8fb19SBen Gras 	if (data)
14272fe8fb19SBen Gras 		free(data);
14282fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
14292fe8fb19SBen Gras 		*retval = &_nis_passwd;
14302fe8fb19SBen Gras 	return rv;
14312fe8fb19SBen Gras }
14322fe8fb19SBen Gras 
14332fe8fb19SBen Gras /*ARGSUSED*/
14342fe8fb19SBen Gras static int
_nis_getpwent_r(void * nsrv,void * nscb,va_list ap)14352fe8fb19SBen Gras _nis_getpwent_r(void *nsrv, void *nscb, va_list ap)
14362fe8fb19SBen Gras {
14372fe8fb19SBen Gras 	int		*retval	= va_arg(ap, int *);
14382fe8fb19SBen Gras 	struct passwd	*pw	= va_arg(ap, struct passwd *);
14392fe8fb19SBen Gras 	char		*buffer	= va_arg(ap, char *);
14402fe8fb19SBen Gras 	size_t		 buflen	= va_arg(ap, size_t);
14412fe8fb19SBen Gras 	struct passwd  **result	= va_arg(ap, struct passwd **);
14422fe8fb19SBen Gras 
14432fe8fb19SBen Gras 	char	*key, *data;
14442fe8fb19SBen Gras 	int	keylen, datalen, rv, nisr;
14452fe8fb19SBen Gras 
14462fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
14472fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
14482fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
14492fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
14502fe8fb19SBen Gras 
14512fe8fb19SBen Gras 	*retval = 0;
14522fe8fb19SBen Gras 
14532fe8fb19SBen Gras 	if (_nis_state.done)				/* exhausted search */
14542fe8fb19SBen Gras 		return NS_NOTFOUND;
14552fe8fb19SBen Gras 	if (_nis_state.domain == NULL) {
14562fe8fb19SBen Gras 					/* only start if NIS not setup */
14572fe8fb19SBen Gras 		rv = _nis_start(&_nis_state);
14582fe8fb19SBen Gras 		if (rv != NS_SUCCESS)
14592fe8fb19SBen Gras 			return rv;
14602fe8fb19SBen Gras 	}
14612fe8fb19SBen Gras 
14622fe8fb19SBen Gras  next_nis_entry:
14632fe8fb19SBen Gras 	key = NULL;
14642fe8fb19SBen Gras 	data = NULL;
14652fe8fb19SBen Gras 	rv = NS_NOTFOUND;
14662fe8fb19SBen Gras 
14672fe8fb19SBen Gras 	if (_nis_state.current) {			/* already searching */
14682fe8fb19SBen Gras 		nisr = yp_next(_nis_state.domain, PASSWD_BYNAME(&_nis_state),
14692fe8fb19SBen Gras 		    _nis_state.current, _nis_state.currentlen,
14702fe8fb19SBen Gras 		    &key, &keylen, &data, &datalen);
14712fe8fb19SBen Gras 		free(_nis_state.current);
14722fe8fb19SBen Gras 		_nis_state.current = NULL;
14732fe8fb19SBen Gras 		switch (nisr) {
14742fe8fb19SBen Gras 		case 0:
14752fe8fb19SBen Gras 			_nis_state.current = key;
14762fe8fb19SBen Gras 			_nis_state.currentlen = keylen;
14772fe8fb19SBen Gras 			key = NULL;
14782fe8fb19SBen Gras 			break;
14792fe8fb19SBen Gras 		case YPERR_NOMORE:
14802fe8fb19SBen Gras 			_nis_state.done = 1;
14812fe8fb19SBen Gras 			goto nisent_out;
14822fe8fb19SBen Gras 		default:
14832fe8fb19SBen Gras 			rv = NS_UNAVAIL;
14842fe8fb19SBen Gras 			goto nisent_out;
14852fe8fb19SBen Gras 		}
14862fe8fb19SBen Gras 	} else {					/* new search */
14872fe8fb19SBen Gras 		if (yp_first(_nis_state.domain, PASSWD_BYNAME(&_nis_state),
14882fe8fb19SBen Gras 		    &_nis_state.current, &_nis_state.currentlen,
14892fe8fb19SBen Gras 		    &data, &datalen)) {
14902fe8fb19SBen Gras 			rv = NS_UNAVAIL;
14912fe8fb19SBen Gras 			goto nisent_out;
14922fe8fb19SBen Gras 		}
14932fe8fb19SBen Gras 	}
14942fe8fb19SBen Gras 
14952fe8fb19SBen Gras 	data[datalen] = '\0';				/* clear trailing \n */
14962fe8fb19SBen Gras 							/* validate line */
14972fe8fb19SBen Gras 	if (_nis_parse(data, pw, buffer, buflen, &_nis_state))
14982fe8fb19SBen Gras 		rv = NS_SUCCESS;
14992fe8fb19SBen Gras 	else {					/* dodgy entry, try again */
15002fe8fb19SBen Gras 		if (key)
15012fe8fb19SBen Gras 			free(key);
15022fe8fb19SBen Gras 		free(data);
15032fe8fb19SBen Gras 		goto next_nis_entry;
15042fe8fb19SBen Gras 	}
15052fe8fb19SBen Gras 
15062fe8fb19SBen Gras  nisent_out:
15072fe8fb19SBen Gras 	if (key)
15082fe8fb19SBen Gras 		free(key);
15092fe8fb19SBen Gras 	if (data)
15102fe8fb19SBen Gras 		free(data);
15112fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
15122fe8fb19SBen Gras 		*result = pw;
15132fe8fb19SBen Gras 	else
15142fe8fb19SBen Gras 		*result = NULL;
15152fe8fb19SBen Gras 	return rv;
15162fe8fb19SBen Gras }
15172fe8fb19SBen Gras 
15182fe8fb19SBen Gras /*ARGSUSED*/
15192fe8fb19SBen Gras static int
_nis_getpwuid(void * nsrv,void * nscb,va_list ap)15202fe8fb19SBen Gras _nis_getpwuid(void *nsrv, void *nscb, va_list ap)
15212fe8fb19SBen Gras {
15222fe8fb19SBen Gras 	struct passwd	**retval = va_arg(ap, struct passwd **);
15232fe8fb19SBen Gras 	uid_t		 uid	= va_arg(ap, uid_t);
15242fe8fb19SBen Gras 
15252fe8fb19SBen Gras 	int	rv, rerror;
15262fe8fb19SBen Gras 
15272fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
15282fe8fb19SBen Gras 
15292fe8fb19SBen Gras 	*retval = NULL;
15302fe8fb19SBen Gras 	rv = _nis_start(&_nis_state);
15312fe8fb19SBen Gras 	if (rv != NS_SUCCESS)
15322fe8fb19SBen Gras 		return rv;
15332fe8fb19SBen Gras 	snprintf(_nis_passwdbuf, sizeof(_nis_passwdbuf), "%u", (unsigned int)uid);
15342fe8fb19SBen Gras 	rv = _nis_pwscan(&rerror, &_nis_passwd,
15352fe8fb19SBen Gras 	    _nis_passwdbuf, sizeof(_nis_passwdbuf),
1536*f14fb602SLionel Sambuc 	    &_nis_state, __nis_pw_u_map, __arraycount(__nis_pw_u_map));
15372fe8fb19SBen Gras 	if (!_nis_state.stayopen)
15382fe8fb19SBen Gras 		_nis_end(&_nis_state);
15392fe8fb19SBen Gras 	if (rv == NS_SUCCESS && uid == _nis_passwd.pw_uid)
15402fe8fb19SBen Gras 		*retval = &_nis_passwd;
15412fe8fb19SBen Gras 	return rv;
15422fe8fb19SBen Gras }
15432fe8fb19SBen Gras 
15442fe8fb19SBen Gras /*ARGSUSED*/
15452fe8fb19SBen Gras static int
_nis_getpwuid_r(void * nsrv,void * nscb,va_list ap)15462fe8fb19SBen Gras _nis_getpwuid_r(void *nsrv, void *nscb, va_list ap)
15472fe8fb19SBen Gras {
15482fe8fb19SBen Gras 	int		*retval	= va_arg(ap, int *);
15492fe8fb19SBen Gras 	uid_t		 uid	= va_arg(ap, uid_t);
15502fe8fb19SBen Gras 	struct passwd	*pw	= va_arg(ap, struct passwd *);
15512fe8fb19SBen Gras 	char		*buffer	= va_arg(ap, char *);
15522fe8fb19SBen Gras 	size_t		 buflen	= va_arg(ap, size_t);
15532fe8fb19SBen Gras 	struct passwd  **result	= va_arg(ap, struct passwd **);
15542fe8fb19SBen Gras 
15552fe8fb19SBen Gras 	struct nis_state state;
15562fe8fb19SBen Gras 	int	rv;
15572fe8fb19SBen Gras 
15582fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
15592fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
15602fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
15612fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
15622fe8fb19SBen Gras 
15632fe8fb19SBen Gras 	*result = NULL;
15642fe8fb19SBen Gras 	snprintf(buffer, buflen, "%u", (unsigned int)uid);
1565*f14fb602SLionel Sambuc /* remark: we run under a global mutex inside of this module ... */
1566*f14fb602SLionel Sambuc 	if (_nis_state.stayopen)
1567*f14fb602SLionel Sambuc 	  { /* use global state only if stayopen is set - otherwise we would blow up getpwent_r() ... */
15682fe8fb19SBen Gras 	    rv = _nis_pwscan(retval, pw, buffer, buflen,
1569*f14fb602SLionel Sambuc 		&_nis_state, __nis_pw_u_map, __arraycount(__nis_pw_u_map));
1570*f14fb602SLionel Sambuc 	  }
1571*f14fb602SLionel Sambuc 	else
1572*f14fb602SLionel Sambuc 	  { /* keep old semantic if no stayopen set - no need to call _nis_start() here - _nis_pwscan() will do it for us ... */
1573*f14fb602SLionel Sambuc 	    /* use same way as in getgrent.c ... */
1574*f14fb602SLionel Sambuc 	    memset(&state, 0, sizeof(state));
1575*f14fb602SLionel Sambuc 	    rv = _nis_pwscan(retval, pw, buffer, buflen,
1576*f14fb602SLionel Sambuc 		&state, __nis_pw_u_map, __arraycount(__nis_pw_u_map));
15772fe8fb19SBen Gras 	    _nis_end(&state);
1578*f14fb602SLionel Sambuc 	  }
15792fe8fb19SBen Gras 	if (rv != NS_SUCCESS)
15802fe8fb19SBen Gras 		return rv;
15812fe8fb19SBen Gras 	if (uid == pw->pw_uid) {
15822fe8fb19SBen Gras 		*result = pw;
15832fe8fb19SBen Gras 		return NS_SUCCESS;
15842fe8fb19SBen Gras 	} else
15852fe8fb19SBen Gras 		return NS_NOTFOUND;
15862fe8fb19SBen Gras }
15872fe8fb19SBen Gras 
15882fe8fb19SBen Gras /*ARGSUSED*/
15892fe8fb19SBen Gras static int
_nis_getpwnam(void * nsrv,void * nscb,va_list ap)15902fe8fb19SBen Gras _nis_getpwnam(void *nsrv, void *nscb, va_list ap)
15912fe8fb19SBen Gras {
15922fe8fb19SBen Gras 	struct passwd	**retval = va_arg(ap, struct passwd **);
15932fe8fb19SBen Gras 	const char	*name	= va_arg(ap, const char *);
15942fe8fb19SBen Gras 
15952fe8fb19SBen Gras 	int	rv, rerror;
15962fe8fb19SBen Gras 
15972fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
15982fe8fb19SBen Gras 
15992fe8fb19SBen Gras 	*retval = NULL;
16002fe8fb19SBen Gras 	rv = _nis_start(&_nis_state);
16012fe8fb19SBen Gras 	if (rv != NS_SUCCESS)
16022fe8fb19SBen Gras 		return rv;
16032fe8fb19SBen Gras 	snprintf(_nis_passwdbuf, sizeof(_nis_passwdbuf), "%s", name);
16042fe8fb19SBen Gras 	rv = _nis_pwscan(&rerror, &_nis_passwd,
16052fe8fb19SBen Gras 	    _nis_passwdbuf, sizeof(_nis_passwdbuf),
1606*f14fb602SLionel Sambuc 	    &_nis_state, __nis_pw_n_map, __arraycount(__nis_pw_n_map));
16072fe8fb19SBen Gras 	if (!_nis_state.stayopen)
16082fe8fb19SBen Gras 		_nis_end(&_nis_state);
16092fe8fb19SBen Gras 	if (rv == NS_SUCCESS && strcmp(name, _nis_passwd.pw_name) == 0)
16102fe8fb19SBen Gras 		*retval = &_nis_passwd;
16112fe8fb19SBen Gras 	return rv;
16122fe8fb19SBen Gras }
16132fe8fb19SBen Gras 
16142fe8fb19SBen Gras /*ARGSUSED*/
16152fe8fb19SBen Gras static int
_nis_getpwnam_r(void * nsrv,void * nscb,va_list ap)16162fe8fb19SBen Gras _nis_getpwnam_r(void *nsrv, void *nscb, va_list ap)
16172fe8fb19SBen Gras {
16182fe8fb19SBen Gras 	int		*retval	= va_arg(ap, int *);
16192fe8fb19SBen Gras 	const char	*name	= va_arg(ap, const char *);
16202fe8fb19SBen Gras 	struct passwd	*pw	= va_arg(ap, struct passwd *);
16212fe8fb19SBen Gras 	char		*buffer	= va_arg(ap, char *);
16222fe8fb19SBen Gras 	size_t		 buflen	= va_arg(ap, size_t);
16232fe8fb19SBen Gras 	struct passwd  **result	= va_arg(ap, struct passwd **);
16242fe8fb19SBen Gras 
16252fe8fb19SBen Gras 	struct nis_state state;
16262fe8fb19SBen Gras 	int	rv;
16272fe8fb19SBen Gras 
16282fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
16292fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
16302fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
16312fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
16322fe8fb19SBen Gras 
16332fe8fb19SBen Gras 	*result = NULL;
16342fe8fb19SBen Gras 	snprintf(buffer, buflen, "%s", name);
1635*f14fb602SLionel Sambuc /* remark: we run under a global mutex inside of this module ... */
1636*f14fb602SLionel Sambuc 	if (_nis_state.stayopen)
1637*f14fb602SLionel Sambuc 	  { /* use global state only if stayopen is set - otherwise we would blow up getpwent_r() ... */
16382fe8fb19SBen Gras 	    rv = _nis_pwscan(retval, pw, buffer, buflen,
1639*f14fb602SLionel Sambuc 		&_nis_state, __nis_pw_n_map, __arraycount(__nis_pw_n_map));
1640*f14fb602SLionel Sambuc 	  }
1641*f14fb602SLionel Sambuc 	else
1642*f14fb602SLionel Sambuc 	  { /* keep old semantic if no stayopen set - no need to call _nis_start() here - _nis_pwscan() will do it for us ... */
1643*f14fb602SLionel Sambuc 	    /* use same way as in getgrent.c ... */
1644*f14fb602SLionel Sambuc 	    memset(&state, 0, sizeof(state));
1645*f14fb602SLionel Sambuc 	    rv = _nis_pwscan(retval, pw, buffer, buflen,
1646*f14fb602SLionel Sambuc 		&state, __nis_pw_n_map, __arraycount(__nis_pw_n_map));
16472fe8fb19SBen Gras 	    _nis_end(&state);
1648*f14fb602SLionel Sambuc 	  }
16492fe8fb19SBen Gras 	if (rv != NS_SUCCESS)
16502fe8fb19SBen Gras 		return rv;
16512fe8fb19SBen Gras 	if (strcmp(name, pw->pw_name) == 0) {
16522fe8fb19SBen Gras 		*result = pw;
16532fe8fb19SBen Gras 		return NS_SUCCESS;
16542fe8fb19SBen Gras 	} else
16552fe8fb19SBen Gras 		return NS_NOTFOUND;
16562fe8fb19SBen Gras }
16572fe8fb19SBen Gras 
16582fe8fb19SBen Gras #endif /* YP */
16592fe8fb19SBen Gras 
16602fe8fb19SBen Gras 
16612fe8fb19SBen Gras #ifdef _PASSWD_COMPAT
16622fe8fb19SBen Gras 		/*
16632fe8fb19SBen Gras 		 *	compat methods
16642fe8fb19SBen Gras 		 */
16652fe8fb19SBen Gras 
16662fe8fb19SBen Gras 	/* state shared between compat methods */
16672fe8fb19SBen Gras 
16682fe8fb19SBen Gras struct compat_state {
16692fe8fb19SBen Gras 	int		 stayopen;	/* see getpassent(3) */
16702fe8fb19SBen Gras 	DB		*db;		/* passwd DB */
16712fe8fb19SBen Gras 	int		 keynum;	/* key counter, -1 if no more */
16722fe8fb19SBen Gras 	enum {				/* current compat mode */
16732fe8fb19SBen Gras 		COMPAT_NOTOKEN = 0,	/*  no compat token present */
16742fe8fb19SBen Gras 		COMPAT_NONE,		/*  parsing normal pwd.db line */
16752fe8fb19SBen Gras 		COMPAT_FULL,		/*  parsing `+' entries */
16762fe8fb19SBen Gras 		COMPAT_USER,		/*  parsing `+name' entries */
16772fe8fb19SBen Gras 		COMPAT_NETGROUP		/*  parsing `+@netgroup' entries */
16782fe8fb19SBen Gras 	}		 mode;
16792fe8fb19SBen Gras 	char		*user;		/* COMPAT_USER "+name" */
16802fe8fb19SBen Gras 	DB		*exclude;	/* compat exclude DB */
16812fe8fb19SBen Gras 	struct passwd	 proto;		/* proto passwd entry */
16822fe8fb19SBen Gras 	char		 protobuf[_GETPW_R_SIZE_MAX];
16832fe8fb19SBen Gras 					/* buffer for proto ptrs */
16842fe8fb19SBen Gras 	int		 protoflags;	/* proto passwd flags */
16852fe8fb19SBen Gras 	int		 version;
16862fe8fb19SBen Gras };
16872fe8fb19SBen Gras 
16882fe8fb19SBen Gras static struct compat_state	_compat_state;
16892fe8fb19SBen Gras 					/* storage for non _r functions */
16902fe8fb19SBen Gras static struct passwd		_compat_passwd;
16912fe8fb19SBen Gras static char			_compat_passwdbuf[_GETPW_R_SIZE_MAX];
16922fe8fb19SBen Gras 
16932fe8fb19SBen Gras static int
_compat_start(struct compat_state * state)16942fe8fb19SBen Gras _compat_start(struct compat_state *state)
16952fe8fb19SBen Gras {
16962fe8fb19SBen Gras 	int	rv;
16972fe8fb19SBen Gras 
16982fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
16992fe8fb19SBen Gras 
17002fe8fb19SBen Gras 	state->keynum = 0;
17012fe8fb19SBen Gras 	if (state->db == NULL) {		/* not open yet */
17022fe8fb19SBen Gras 		DBT	key, data;
17032fe8fb19SBen Gras 		DBT	pkey, pdata;
17042fe8fb19SBen Gras 		char	bf[MAXLOGNAME];
17052fe8fb19SBen Gras 
17062fe8fb19SBen Gras 		rv = _pw_opendb(&state->db, &state->version);
17072fe8fb19SBen Gras 		if (rv != NS_SUCCESS)
17082fe8fb19SBen Gras 			return rv;
17092fe8fb19SBen Gras 
17102fe8fb19SBen Gras 		state->mode = COMPAT_NOTOKEN;
17112fe8fb19SBen Gras 
17122fe8fb19SBen Gras 		/*
17132fe8fb19SBen Gras 		 *	Determine if the "compat" token is present in pwd.db;
17142fe8fb19SBen Gras 		 *	either "__YP!" or PW_KEYBYNAME+"+".
17152fe8fb19SBen Gras 		 *	Only works if pwd_mkdb installs the token.
17162fe8fb19SBen Gras 		 */
17172fe8fb19SBen Gras 		key.data = (u_char *)__UNCONST(__yp_token);
17182fe8fb19SBen Gras 		key.size = strlen(__yp_token);
17192fe8fb19SBen Gras 
17202fe8fb19SBen Gras 		bf[0] = _PW_KEYBYNAME;	 /* Pre-token database support. */
17212fe8fb19SBen Gras 		bf[1] = '+';
17222fe8fb19SBen Gras 		pkey.data = (u_char *)bf;
17232fe8fb19SBen Gras 		pkey.size = 2;
17242fe8fb19SBen Gras 
17252fe8fb19SBen Gras 		if ((state->db->get)(state->db, &key, &data, 0) == 0
17262fe8fb19SBen Gras 		    || (state->db->get)(state->db, &pkey, &pdata, 0) == 0)
17272fe8fb19SBen Gras 			state->mode = COMPAT_NONE;
17282fe8fb19SBen Gras 	}
17292fe8fb19SBen Gras 	return NS_SUCCESS;
17302fe8fb19SBen Gras }
17312fe8fb19SBen Gras 
17322fe8fb19SBen Gras static int
_compat_end(struct compat_state * state)17332fe8fb19SBen Gras _compat_end(struct compat_state *state)
17342fe8fb19SBen Gras {
17352fe8fb19SBen Gras 
17362fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
17372fe8fb19SBen Gras 
17382fe8fb19SBen Gras 	state->keynum = 0;
17392fe8fb19SBen Gras 	if (state->db) {
17402fe8fb19SBen Gras 		(void)(state->db->close)(state->db);
17412fe8fb19SBen Gras 		state->db = NULL;
17422fe8fb19SBen Gras 	}
17432fe8fb19SBen Gras 	state->mode = COMPAT_NOTOKEN;
17442fe8fb19SBen Gras 	if (state->user)
17452fe8fb19SBen Gras 		free(state->user);
17462fe8fb19SBen Gras 	state->user = NULL;
17472fe8fb19SBen Gras 	if (state->exclude != NULL)
17482fe8fb19SBen Gras 		(void)(state->exclude->close)(state->exclude);
17492fe8fb19SBen Gras 	state->exclude = NULL;
17502fe8fb19SBen Gras 	state->proto.pw_name = NULL;
17512fe8fb19SBen Gras 	state->protoflags = 0;
17522fe8fb19SBen Gras 	return NS_SUCCESS;
17532fe8fb19SBen Gras }
17542fe8fb19SBen Gras 
17552fe8fb19SBen Gras /*
17562fe8fb19SBen Gras  * _compat_add_exclude
17572fe8fb19SBen Gras  *	add the name to the exclude list in state->exclude.
17582fe8fb19SBen Gras  */
17592fe8fb19SBen Gras static int
_compat_add_exclude(struct compat_state * state,const char * name)17602fe8fb19SBen Gras _compat_add_exclude(struct compat_state *state, const char *name)
17612fe8fb19SBen Gras {
17622fe8fb19SBen Gras 	DBT	key, data;
17632fe8fb19SBen Gras 
17642fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
17652fe8fb19SBen Gras 	_DIAGASSERT(name != NULL);
17662fe8fb19SBen Gras 
17672fe8fb19SBen Gras 				/* initialize the exclusion table if needed */
17682fe8fb19SBen Gras 	if (state->exclude == NULL) {
17692fe8fb19SBen Gras 		state->exclude = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL);
17702fe8fb19SBen Gras 		if (state->exclude == NULL)
17712fe8fb19SBen Gras 			return 0;
17722fe8fb19SBen Gras 	}
17732fe8fb19SBen Gras 
17742fe8fb19SBen Gras 	key.size = strlen(name);			/* set up the key */
17752fe8fb19SBen Gras 	key.data = (u_char *)__UNCONST(name);
17762fe8fb19SBen Gras 
17772fe8fb19SBen Gras 	data.data = NULL;				/* data is nothing */
17782fe8fb19SBen Gras 	data.size = 0;
17792fe8fb19SBen Gras 
17802fe8fb19SBen Gras 							/* store it */
17812fe8fb19SBen Gras 	if ((state->exclude->put)(state->exclude, &key, &data, 0) == -1)
17822fe8fb19SBen Gras 		return 0;
17832fe8fb19SBen Gras 
17842fe8fb19SBen Gras 	return 1;
17852fe8fb19SBen Gras }
17862fe8fb19SBen Gras 
17872fe8fb19SBen Gras /*
17882fe8fb19SBen Gras  * _compat_is_excluded
17892fe8fb19SBen Gras  *	test if a name is on the compat mode exclude list
17902fe8fb19SBen Gras  */
17912fe8fb19SBen Gras static int
_compat_is_excluded(struct compat_state * state,const char * name)17922fe8fb19SBen Gras _compat_is_excluded(struct compat_state *state, const char *name)
17932fe8fb19SBen Gras {
17942fe8fb19SBen Gras 	DBT	key, data;
17952fe8fb19SBen Gras 
17962fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
17972fe8fb19SBen Gras 	_DIAGASSERT(name != NULL);
17982fe8fb19SBen Gras 
17992fe8fb19SBen Gras 	if (state->exclude == NULL)
18002fe8fb19SBen Gras 		return 0;	/* nothing excluded */
18012fe8fb19SBen Gras 
18022fe8fb19SBen Gras 	key.size = strlen(name);			/* set up the key */
18032fe8fb19SBen Gras 	key.data = (u_char *)__UNCONST(name);
18042fe8fb19SBen Gras 
18052fe8fb19SBen Gras 	if ((state->exclude->get)(state->exclude, &key, &data, 0) == 0)
18062fe8fb19SBen Gras 		return 1;				/* is excluded */
18072fe8fb19SBen Gras 
18082fe8fb19SBen Gras 	return 0;
18092fe8fb19SBen Gras }
18102fe8fb19SBen Gras 
18112fe8fb19SBen Gras 
18122fe8fb19SBen Gras /*
18132fe8fb19SBen Gras  * _passwdcompat_bad
18142fe8fb19SBen Gras  *	log an error if "files" or "compat" is specified in
18152fe8fb19SBen Gras  *	passwd_compat database
18162fe8fb19SBen Gras  */
18172fe8fb19SBen Gras /*ARGSUSED*/
18182fe8fb19SBen Gras static int
_passwdcompat_bad(void * nsrv,void * nscb,va_list ap)18192fe8fb19SBen Gras _passwdcompat_bad(void *nsrv, void *nscb, va_list ap)
18202fe8fb19SBen Gras {
18212fe8fb19SBen Gras 	static int warned;
18222fe8fb19SBen Gras 
18232fe8fb19SBen Gras 	_DIAGASSERT(nsrv != NULL);
18242fe8fb19SBen Gras 	_DIAGASSERT(nscb != NULL);
18252fe8fb19SBen Gras 
18262fe8fb19SBen Gras 	if (!warned) {
18272fe8fb19SBen Gras 		syslog(LOG_ERR,
18282fe8fb19SBen Gras 			"nsswitch.conf passwd_compat database can't use '%s'",
18292fe8fb19SBen Gras 			(char *)nscb);
18302fe8fb19SBen Gras 	}
18312fe8fb19SBen Gras 	warned = 1;
18322fe8fb19SBen Gras 	return NS_UNAVAIL;
18332fe8fb19SBen Gras }
18342fe8fb19SBen Gras 
18352fe8fb19SBen Gras /*
18362fe8fb19SBen Gras  * _passwdcompat_setpassent
18372fe8fb19SBen Gras  *	Call setpassent for all passwd_compat sources.
18382fe8fb19SBen Gras  */
18392fe8fb19SBen Gras static int
_passwdcompat_setpassent(int stayopen)18402fe8fb19SBen Gras _passwdcompat_setpassent(int stayopen)
18412fe8fb19SBen Gras {
18422fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
18432fe8fb19SBen Gras 		NS_FILES_CB(_passwdcompat_bad, "files")
18442fe8fb19SBen Gras 		NS_DNS_CB(_dns_setpassent, NULL)
18452fe8fb19SBen Gras 		NS_NIS_CB(_nis_setpassent, NULL)
18462fe8fb19SBen Gras 		NS_COMPAT_CB(_passwdcompat_bad, "compat")
18472fe8fb19SBen Gras 		NS_NULL_CB
18482fe8fb19SBen Gras 	};
18492fe8fb19SBen Gras 
18502fe8fb19SBen Gras 	int	rv, result;
18512fe8fb19SBen Gras 
18522fe8fb19SBen Gras 	rv = nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "setpassent",
18532fe8fb19SBen Gras 	    __nsdefaultnis_forceall, &result, stayopen);
18542fe8fb19SBen Gras 	return rv;
18552fe8fb19SBen Gras }
18562fe8fb19SBen Gras 
18572fe8fb19SBen Gras /*
18582fe8fb19SBen Gras  * _passwdcompat_endpwent
18592fe8fb19SBen Gras  *	Call endpwent for all passwd_compat sources.
18602fe8fb19SBen Gras  */
18612fe8fb19SBen Gras static int
_passwdcompat_endpwent(void)18622fe8fb19SBen Gras _passwdcompat_endpwent(void)
18632fe8fb19SBen Gras {
18642fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
18652fe8fb19SBen Gras 		NS_FILES_CB(_passwdcompat_bad, "files")
18662fe8fb19SBen Gras 		NS_DNS_CB(_dns_endpwent, NULL)
18672fe8fb19SBen Gras 		NS_NIS_CB(_nis_endpwent, NULL)
18682fe8fb19SBen Gras 		NS_COMPAT_CB(_passwdcompat_bad, "compat")
18692fe8fb19SBen Gras 		NS_NULL_CB
18702fe8fb19SBen Gras 	};
18712fe8fb19SBen Gras 
18722fe8fb19SBen Gras 	return nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "endpwent",
18732fe8fb19SBen Gras 	    __nsdefaultnis_forceall);
18742fe8fb19SBen Gras }
18752fe8fb19SBen Gras 
18762fe8fb19SBen Gras /*
18772fe8fb19SBen Gras  * _passwdcompat_pwscan
18782fe8fb19SBen Gras  *	When a name lookup in compat mode is required (e.g., `+name', or a
18792fe8fb19SBen Gras  *	name in `+@netgroup'), look it up in the 'passwd_compat' nsswitch
18802fe8fb19SBen Gras  *	database.
18812fe8fb19SBen Gras  *	Fail if passwd_compat contains files or compat.
18822fe8fb19SBen Gras  */
18832fe8fb19SBen Gras static int
_passwdcompat_pwscan(struct passwd * pw,char * buffer,size_t buflen,int search,const char * name,uid_t uid)18842fe8fb19SBen Gras _passwdcompat_pwscan(struct passwd *pw, char *buffer, size_t buflen,
18852fe8fb19SBen Gras 	int search, const char *name, uid_t uid)
18862fe8fb19SBen Gras {
18872fe8fb19SBen Gras 	static const ns_dtab compatentdtab[] = {
18882fe8fb19SBen Gras 		NS_FILES_CB(_passwdcompat_bad, "files")
18892fe8fb19SBen Gras 		NS_DNS_CB(_dns_getpwent_r, NULL)
18902fe8fb19SBen Gras 		NS_NIS_CB(_nis_getpwent_r, NULL)
18912fe8fb19SBen Gras 		NS_COMPAT_CB(_passwdcompat_bad, "compat")
18922fe8fb19SBen Gras 		NS_NULL_CB
18932fe8fb19SBen Gras 	};
18942fe8fb19SBen Gras 	static const ns_dtab compatuiddtab[] = {
18952fe8fb19SBen Gras 		NS_FILES_CB(_passwdcompat_bad, "files")
18962fe8fb19SBen Gras 		NS_DNS_CB(_dns_getpwuid_r, NULL)
18972fe8fb19SBen Gras 		NS_NIS_CB(_nis_getpwuid_r, NULL)
18982fe8fb19SBen Gras 		NS_COMPAT_CB(_passwdcompat_bad, "compat")
18992fe8fb19SBen Gras 		NS_NULL_CB
19002fe8fb19SBen Gras 	};
19012fe8fb19SBen Gras 	static const ns_dtab compatnamdtab[] = {
19022fe8fb19SBen Gras 		NS_FILES_CB(_passwdcompat_bad, "files")
19032fe8fb19SBen Gras 		NS_DNS_CB(_dns_getpwnam_r, NULL)
19042fe8fb19SBen Gras 		NS_NIS_CB(_nis_getpwnam_r, NULL)
19052fe8fb19SBen Gras 		NS_COMPAT_CB(_passwdcompat_bad, "compat")
19062fe8fb19SBen Gras 		NS_NULL_CB
19072fe8fb19SBen Gras 	};
19082fe8fb19SBen Gras 
19092fe8fb19SBen Gras 	int		rv, crv;
19102fe8fb19SBen Gras 	struct passwd	*cpw;
19112fe8fb19SBen Gras 
19122fe8fb19SBen Gras 	switch (search) {
19132fe8fb19SBen Gras 	case _PW_KEYBYNUM:
19142fe8fb19SBen Gras 		rv = nsdispatch(NULL, compatentdtab,
19152fe8fb19SBen Gras 		    NSDB_PASSWD_COMPAT, "getpwent_r", __nsdefaultnis,
19162fe8fb19SBen Gras 		    &crv, pw, buffer, buflen, &cpw);
19172fe8fb19SBen Gras 		break;
19182fe8fb19SBen Gras 	case _PW_KEYBYNAME:
19192fe8fb19SBen Gras 		_DIAGASSERT(name != NULL);
19202fe8fb19SBen Gras 		rv = nsdispatch(NULL, compatnamdtab,
19212fe8fb19SBen Gras 		    NSDB_PASSWD_COMPAT, "getpwnam_r", __nsdefaultnis,
19222fe8fb19SBen Gras 		    &crv, name, pw, buffer, buflen, &cpw);
19232fe8fb19SBen Gras 		break;
19242fe8fb19SBen Gras 	case _PW_KEYBYUID:
19252fe8fb19SBen Gras 		rv = nsdispatch(NULL, compatuiddtab,
19262fe8fb19SBen Gras 		    NSDB_PASSWD_COMPAT, "getpwuid_r", __nsdefaultnis,
19272fe8fb19SBen Gras 		    &crv, uid, pw, buffer, buflen, &cpw);
19282fe8fb19SBen Gras 		break;
19292fe8fb19SBen Gras 	default:
19302fe8fb19SBen Gras 		abort();
19312fe8fb19SBen Gras 		/*NOTREACHED*/
19322fe8fb19SBen Gras 	}
19332fe8fb19SBen Gras 	return rv;
19342fe8fb19SBen Gras }
19352fe8fb19SBen Gras 
19362fe8fb19SBen Gras /*
19372fe8fb19SBen Gras  * _compat_pwscan
19382fe8fb19SBen Gras  *	Search state->db for the next desired entry.
19392fe8fb19SBen Gras  *	If search is _PW_KEYBYNUM, look for state->keynum.
19402fe8fb19SBen Gras  *	If search is _PW_KEYBYNAME, look for name.
19412fe8fb19SBen Gras  *	If search is _PW_KEYBYUID, look for uid.
19422fe8fb19SBen Gras  *	Sets *retval to the errno if the result is not NS_SUCCESS
19432fe8fb19SBen Gras  *	or NS_NOTFOUND.
19442fe8fb19SBen Gras  */
19452fe8fb19SBen Gras static int
_compat_pwscan(int * retval,struct passwd * pw,char * buffer,size_t buflen,struct compat_state * state,int search,const char * name,uid_t uid)19462fe8fb19SBen Gras _compat_pwscan(int *retval, struct passwd *pw, char *buffer, size_t buflen,
19472fe8fb19SBen Gras 	struct compat_state *state, int search, const char *name, uid_t uid)
19482fe8fb19SBen Gras {
19492fe8fb19SBen Gras 	DBT		 key;
19502fe8fb19SBen Gras 	int		 rv, r, pwflags;
19512fe8fb19SBen Gras 	const char	*user, *host, *dom;
19522fe8fb19SBen Gras 	const void	*from;
19532fe8fb19SBen Gras 	size_t		 fromlen;
19542fe8fb19SBen Gras 
19552fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
19562fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
19572fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
19582fe8fb19SBen Gras 	_DIAGASSERT(state != NULL);
19592fe8fb19SBen Gras 	/* name may be NULL */
19602fe8fb19SBen Gras 
19612fe8fb19SBen Gras 	*retval = 0;
19622fe8fb19SBen Gras 
19632fe8fb19SBen Gras 	if (state->db == NULL) {
19642fe8fb19SBen Gras 		rv = _compat_start(state);
19652fe8fb19SBen Gras 		if (rv != NS_SUCCESS)
19662fe8fb19SBen Gras 			return rv;
19672fe8fb19SBen Gras 	}
19682fe8fb19SBen Gras 	if (buflen <= 1) {			/* buffer too small */
19692fe8fb19SBen Gras 		*retval = ERANGE;
19702fe8fb19SBen Gras 		return NS_UNAVAIL;
19712fe8fb19SBen Gras 	}
19722fe8fb19SBen Gras 
19732fe8fb19SBen Gras 	for (;;) {				/* loop over pwd.db */
19742fe8fb19SBen Gras 		rv = NS_NOTFOUND;
19752fe8fb19SBen Gras 		if (state->mode != COMPAT_NOTOKEN &&
19762fe8fb19SBen Gras 		    state->mode != COMPAT_NONE) {
19772fe8fb19SBen Gras 						/* doing a compat lookup */
19782fe8fb19SBen Gras 			struct passwd	cpw;
19792fe8fb19SBen Gras 			char		cbuf[_GETPW_R_SIZE_MAX];
19802fe8fb19SBen Gras 
19812fe8fb19SBen Gras 			switch (state->mode) {
19822fe8fb19SBen Gras 
19832fe8fb19SBen Gras 			case COMPAT_FULL:
19842fe8fb19SBen Gras 					/* get next user or lookup by key */
19852fe8fb19SBen Gras 				rv = _passwdcompat_pwscan(&cpw,
19862fe8fb19SBen Gras 				    cbuf, sizeof(cbuf), search, name, uid);
19872fe8fb19SBen Gras 				if (rv != NS_SUCCESS)
19882fe8fb19SBen Gras 					state->mode = COMPAT_NONE;
19892fe8fb19SBen Gras 				break;
19902fe8fb19SBen Gras 
19912fe8fb19SBen Gras 			case COMPAT_NETGROUP:
19922fe8fb19SBen Gras /* XXXREENTRANT: getnetgrent is not thread safe */
19932fe8fb19SBen Gras 					/* get next user from netgroup */
19942fe8fb19SBen Gras 				r = getnetgrent(&host, &user, &dom);
19952fe8fb19SBen Gras 				if (r == 0) {	/* end of group */
19962fe8fb19SBen Gras 					endnetgrent();
19972fe8fb19SBen Gras 					state->mode = COMPAT_NONE;
19982fe8fb19SBen Gras 					break;
19992fe8fb19SBen Gras 				}
20002fe8fb19SBen Gras 				if (!user || !*user)
20012fe8fb19SBen Gras 					break;
20022fe8fb19SBen Gras 				rv = _passwdcompat_pwscan(&cpw,
20032fe8fb19SBen Gras 				    cbuf, sizeof(cbuf),
20042fe8fb19SBen Gras 				    _PW_KEYBYNAME, user, 0);
20052fe8fb19SBen Gras 				break;
20062fe8fb19SBen Gras 
20072fe8fb19SBen Gras 			case COMPAT_USER:
20082fe8fb19SBen Gras 					/* get specific user */
20092fe8fb19SBen Gras 				if (state->user == NULL) {
20102fe8fb19SBen Gras 					state->mode = COMPAT_NONE;
20112fe8fb19SBen Gras 					break;
20122fe8fb19SBen Gras 				}
20132fe8fb19SBen Gras 				rv = _passwdcompat_pwscan(&cpw,
20142fe8fb19SBen Gras 				    cbuf, sizeof(cbuf),
20152fe8fb19SBen Gras 				    _PW_KEYBYNAME, state->user, 0);
20162fe8fb19SBen Gras 				free(state->user);
20172fe8fb19SBen Gras 				state->user = NULL;
20182fe8fb19SBen Gras 				state->mode = COMPAT_NONE;
20192fe8fb19SBen Gras 				break;
20202fe8fb19SBen Gras 
20212fe8fb19SBen Gras 			case COMPAT_NOTOKEN:
20222fe8fb19SBen Gras 			case COMPAT_NONE:
20232fe8fb19SBen Gras 				abort();
20242fe8fb19SBen Gras 
20252fe8fb19SBen Gras 			}
20262fe8fb19SBen Gras 			if (rv != NS_SUCCESS)	/* if not matched, next loop */
20272fe8fb19SBen Gras 				continue;
20282fe8fb19SBen Gras 
20292fe8fb19SBen Gras 				/* copy cpw to pw, applying prototype */
20302fe8fb19SBen Gras 			if (! _pw_copy(&cpw, pw, buffer, buflen,
20312fe8fb19SBen Gras 			    &state->proto, state->protoflags)) {
20322fe8fb19SBen Gras 				rv = NS_UNAVAIL;
20332fe8fb19SBen Gras 				break;
20342fe8fb19SBen Gras 			}
20352fe8fb19SBen Gras 
20362fe8fb19SBen Gras 			if (_compat_is_excluded(state, pw->pw_name))
20372fe8fb19SBen Gras 				continue;	/* excluded; next loop */
20382fe8fb19SBen Gras 
20392fe8fb19SBen Gras 			if ((search == _PW_KEYBYNAME
20402fe8fb19SBen Gras 					&& strcmp(pw->pw_name, name) != 0)
20412fe8fb19SBen Gras 			    || (search == _PW_KEYBYUID && pw->pw_uid != uid)) {
20422fe8fb19SBen Gras 				continue;	/* not specific; next loop */
20432fe8fb19SBen Gras 			}
20442fe8fb19SBen Gras 
20452fe8fb19SBen Gras 			break;			/* exit loop if found */
20462fe8fb19SBen Gras 		} else {			/* not a compat line */
20472fe8fb19SBen Gras 			state->proto.pw_name = NULL;
20482fe8fb19SBen Gras 						/* clear prototype */
20492fe8fb19SBen Gras 		}
20502fe8fb19SBen Gras 
20512fe8fb19SBen Gras 		if (state->mode == COMPAT_NOTOKEN) {
20522fe8fb19SBen Gras 				/* no compat token; do direct lookup */
20532fe8fb19SBen Gras 			switch (search) {
20542fe8fb19SBen Gras 			case _PW_KEYBYNUM:
20552fe8fb19SBen Gras 				if (state->keynum == -1)  /* no more records */
20562fe8fb19SBen Gras 					return NS_NOTFOUND;
20572fe8fb19SBen Gras 				state->keynum++;
20582fe8fb19SBen Gras 				from = &state->keynum;
20592fe8fb19SBen Gras 				fromlen = sizeof(state->keynum);
20602fe8fb19SBen Gras 				break;
20612fe8fb19SBen Gras 			case _PW_KEYBYNAME:
20622fe8fb19SBen Gras 				from = name;
20632fe8fb19SBen Gras 				fromlen = strlen(name);
20642fe8fb19SBen Gras 				break;
20652fe8fb19SBen Gras 			case _PW_KEYBYUID:
20662fe8fb19SBen Gras 				from = &uid;
20672fe8fb19SBen Gras 				fromlen = sizeof(uid);
20682fe8fb19SBen Gras 				break;
20692fe8fb19SBen Gras 			default:
20702fe8fb19SBen Gras 				abort();
20712fe8fb19SBen Gras 			}
20722fe8fb19SBen Gras 			buffer[0] = search;
20732fe8fb19SBen Gras 		} else {
20742fe8fb19SBen Gras 				/* compat token; do line by line */
20752fe8fb19SBen Gras 			if (state->keynum == -1)  /* no more records */
20762fe8fb19SBen Gras 				return NS_NOTFOUND;
20772fe8fb19SBen Gras 			state->keynum++;
20782fe8fb19SBen Gras 			from = &state->keynum;
20792fe8fb19SBen Gras 			fromlen = sizeof(state->keynum);
20802fe8fb19SBen Gras 			buffer[0] = _PW_KEYBYNUM;
20812fe8fb19SBen Gras 		}
20822fe8fb19SBen Gras 
20832fe8fb19SBen Gras 		if (buflen <= fromlen) {		/* buffer too small */
20842fe8fb19SBen Gras 			*retval = ERANGE;
20852fe8fb19SBen Gras 			return NS_UNAVAIL;
20862fe8fb19SBen Gras 		}
20872fe8fb19SBen Gras 		memmove(buffer + 1, from, fromlen);	/* setup key */
20882fe8fb19SBen Gras 		key.size = fromlen + 1;
20892fe8fb19SBen Gras 		key.data = (u_char *)buffer;
20902fe8fb19SBen Gras 
20912fe8fb19SBen Gras 		rv = _pw_getkey(state->db, &key, pw, buffer, buflen, &pwflags,
20922fe8fb19SBen Gras 		    state->version);
20932fe8fb19SBen Gras 		if (rv != NS_SUCCESS)		/* stop on error */
20942fe8fb19SBen Gras 			break;
20952fe8fb19SBen Gras 
20962fe8fb19SBen Gras 		if (state->mode == COMPAT_NOTOKEN)
20972fe8fb19SBen Gras 			break;			/* stop if no compat token */
20982fe8fb19SBen Gras 
20992fe8fb19SBen Gras 		if (pw->pw_name[0] == '+') {
21002fe8fb19SBen Gras 						/* compat inclusion */
21012fe8fb19SBen Gras 			switch(pw->pw_name[1]) {
21022fe8fb19SBen Gras 			case '\0':		/* `+' */
21032fe8fb19SBen Gras 				state->mode = COMPAT_FULL;
21042fe8fb19SBen Gras 						/* reset passwd_compat search */
21052fe8fb19SBen Gras /* XXXREENTRANT: setpassent is not thread safe ? */
2106*f14fb602SLionel Sambuc 				(void) _passwdcompat_setpassent(_compat_state.stayopen);
21072fe8fb19SBen Gras 				break;
21082fe8fb19SBen Gras 			case '@':		/* `+@netgroup' */
21092fe8fb19SBen Gras 				state->mode = COMPAT_NETGROUP;
21102fe8fb19SBen Gras 						/* reset netgroup search */
21112fe8fb19SBen Gras /* XXXREENTRANT: setnetgrent is not thread safe */
21122fe8fb19SBen Gras 				setnetgrent(pw->pw_name + 2);
21132fe8fb19SBen Gras 				break;
21142fe8fb19SBen Gras 			default:		/* `+name' */
21152fe8fb19SBen Gras 				state->mode = COMPAT_USER;
21162fe8fb19SBen Gras 				if (state->user)
21172fe8fb19SBen Gras 					free(state->user);
21182fe8fb19SBen Gras 				state->user = strdup(pw->pw_name + 1);
21192fe8fb19SBen Gras 				break;
21202fe8fb19SBen Gras 			}
21212fe8fb19SBen Gras 						/* save the prototype */
21222fe8fb19SBen Gras 			state->protoflags = pwflags;
21232fe8fb19SBen Gras 			if (! _pw_copy(pw, &state->proto, state->protobuf,
21242fe8fb19SBen Gras 			    sizeof(state->protobuf), NULL, 0)) {
21252fe8fb19SBen Gras 				rv = NS_UNAVAIL;
21262fe8fb19SBen Gras 				break;
21272fe8fb19SBen Gras 			}
21282fe8fb19SBen Gras 			continue;		/* loop again after inclusion */
21292fe8fb19SBen Gras 		} else if (pw->pw_name[0] == '-') {
21302fe8fb19SBen Gras 						/* compat exclusion */
21312fe8fb19SBen Gras 			rv = NS_SUCCESS;
21322fe8fb19SBen Gras 			switch(pw->pw_name[1]) {
21332fe8fb19SBen Gras 			case '\0':		/* `-' */
21342fe8fb19SBen Gras 				break;
21352fe8fb19SBen Gras 			case '@':		/* `-@netgroup' */
21362fe8fb19SBen Gras /* XXXREENTRANT: {set,get,end}netgrent is not thread safe */
21372fe8fb19SBen Gras 				setnetgrent(pw->pw_name + 2);
21382fe8fb19SBen Gras 				while (getnetgrent(&host, &user, &dom)) {
21392fe8fb19SBen Gras 					if (!user || !*user)
21402fe8fb19SBen Gras 						continue;
21412fe8fb19SBen Gras 					if (! _compat_add_exclude(state,user)) {
21422fe8fb19SBen Gras 						rv = NS_UNAVAIL;
21432fe8fb19SBen Gras 						break;
21442fe8fb19SBen Gras 					}
21452fe8fb19SBen Gras 				}
21462fe8fb19SBen Gras 				endnetgrent();
21472fe8fb19SBen Gras 				break;
21482fe8fb19SBen Gras 			default:		/* `-name' */
21492fe8fb19SBen Gras 				if (! _compat_add_exclude(state,
21502fe8fb19SBen Gras 				    pw->pw_name + 1)) {
21512fe8fb19SBen Gras 					rv = NS_UNAVAIL;
21522fe8fb19SBen Gras 				}
21532fe8fb19SBen Gras 				break;
21542fe8fb19SBen Gras 			}
21552fe8fb19SBen Gras 			if (rv != NS_SUCCESS)	/* exclusion failure */
21562fe8fb19SBen Gras 				break;
21572fe8fb19SBen Gras 			continue;		/* loop again after exclusion */
21582fe8fb19SBen Gras 		}
21592fe8fb19SBen Gras 		if (search == _PW_KEYBYNUM ||
21602fe8fb19SBen Gras 		    (search == _PW_KEYBYUID && pw->pw_uid == uid) ||
21612fe8fb19SBen Gras 		    (search == _PW_KEYBYNAME && strcmp(pw->pw_name, name) == 0))
21622fe8fb19SBen Gras 			break;			/* token mode match found */
21632fe8fb19SBen Gras 	}
21642fe8fb19SBen Gras 
21652fe8fb19SBen Gras 	if (rv == NS_NOTFOUND &&
21662fe8fb19SBen Gras 	    (search == _PW_KEYBYNUM || state->mode != COMPAT_NOTOKEN))
21672fe8fb19SBen Gras 		state->keynum = -1;		/* flag `no more records' */
21682fe8fb19SBen Gras 
21692fe8fb19SBen Gras 	if (rv == NS_SUCCESS) {
21702fe8fb19SBen Gras 		if ((search == _PW_KEYBYNAME && strcmp(pw->pw_name, name) != 0)
21712fe8fb19SBen Gras 		    || (search == _PW_KEYBYUID && pw->pw_uid != uid))
21722fe8fb19SBen Gras 			rv = NS_NOTFOUND;
21732fe8fb19SBen Gras 	}
21742fe8fb19SBen Gras 
21752fe8fb19SBen Gras 	if (rv != NS_SUCCESS && rv != NS_NOTFOUND)
21762fe8fb19SBen Gras 		*retval = errno;
21772fe8fb19SBen Gras 	return rv;
21782fe8fb19SBen Gras }
21792fe8fb19SBen Gras 
21802fe8fb19SBen Gras /*ARGSUSED*/
21812fe8fb19SBen Gras static int
_compat_setpwent(void * nsrv,void * nscb,va_list ap)21822fe8fb19SBen Gras _compat_setpwent(void *nsrv, void *nscb, va_list ap)
21832fe8fb19SBen Gras {
21842fe8fb19SBen Gras 
21852fe8fb19SBen Gras 					/* force passwd_compat setpwent() */
21862fe8fb19SBen Gras 	(void) _passwdcompat_setpassent(0);
21872fe8fb19SBen Gras 
21882fe8fb19SBen Gras 					/* reset state, keep db open */
21892fe8fb19SBen Gras 	_compat_state.stayopen = 0;
21902fe8fb19SBen Gras 	return _compat_start(&_compat_state);
21912fe8fb19SBen Gras }
21922fe8fb19SBen Gras 
21932fe8fb19SBen Gras /*ARGSUSED*/
21942fe8fb19SBen Gras static int
_compat_setpassent(void * nsrv,void * nscb,va_list ap)21952fe8fb19SBen Gras _compat_setpassent(void *nsrv, void *nscb, va_list ap)
21962fe8fb19SBen Gras {
21972fe8fb19SBen Gras 	int	*retval		= va_arg(ap, int *);
21982fe8fb19SBen Gras 	int	 stayopen	= va_arg(ap, int);
21992fe8fb19SBen Gras 
22002fe8fb19SBen Gras 	int	rv;
22012fe8fb19SBen Gras 
22022fe8fb19SBen Gras 					/* force passwd_compat setpassent() */
22032fe8fb19SBen Gras 	(void) _passwdcompat_setpassent(stayopen);
22042fe8fb19SBen Gras 
22052fe8fb19SBen Gras 	_compat_state.stayopen = stayopen;
22062fe8fb19SBen Gras 	rv = _compat_start(&_compat_state);
22072fe8fb19SBen Gras 	*retval = (rv == NS_SUCCESS);
22082fe8fb19SBen Gras 	return rv;
22092fe8fb19SBen Gras }
22102fe8fb19SBen Gras 
22112fe8fb19SBen Gras /*ARGSUSED*/
22122fe8fb19SBen Gras static int
_compat_endpwent(void * nsrv,void * nscb,va_list ap)22132fe8fb19SBen Gras _compat_endpwent(void *nsrv, void *nscb, va_list ap)
22142fe8fb19SBen Gras {
22152fe8fb19SBen Gras 
22162fe8fb19SBen Gras 					/* force passwd_compat endpwent() */
22172fe8fb19SBen Gras 	(void) _passwdcompat_endpwent();
22182fe8fb19SBen Gras 
22192fe8fb19SBen Gras 					/* reset state, close db */
22202fe8fb19SBen Gras 	_compat_state.stayopen = 0;
22212fe8fb19SBen Gras 	return _compat_end(&_compat_state);
22222fe8fb19SBen Gras }
22232fe8fb19SBen Gras 
22242fe8fb19SBen Gras 
22252fe8fb19SBen Gras /*ARGSUSED*/
22262fe8fb19SBen Gras static int
_compat_getpwent(void * nsrv,void * nscb,va_list ap)22272fe8fb19SBen Gras _compat_getpwent(void *nsrv, void *nscb, va_list ap)
22282fe8fb19SBen Gras {
22292fe8fb19SBen Gras 	struct passwd	**retval = va_arg(ap, struct passwd **);
22302fe8fb19SBen Gras 
22312fe8fb19SBen Gras 	int	rv, rerror;
22322fe8fb19SBen Gras 
22332fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
22342fe8fb19SBen Gras 
22352fe8fb19SBen Gras 	*retval = NULL;
22362fe8fb19SBen Gras 	rv = _compat_pwscan(&rerror, &_compat_passwd,
22372fe8fb19SBen Gras 	    _compat_passwdbuf, sizeof(_compat_passwdbuf),
22382fe8fb19SBen Gras 	    &_compat_state, _PW_KEYBYNUM, NULL, 0);
22392fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
22402fe8fb19SBen Gras 		*retval = &_compat_passwd;
22412fe8fb19SBen Gras 	return rv;
22422fe8fb19SBen Gras }
22432fe8fb19SBen Gras 
22442fe8fb19SBen Gras /*ARGSUSED*/
22452fe8fb19SBen Gras static int
_compat_getpwent_r(void * nsrv,void * nscb,va_list ap)22462fe8fb19SBen Gras _compat_getpwent_r(void *nsrv, void *nscb, va_list ap)
22472fe8fb19SBen Gras {
22482fe8fb19SBen Gras 	int		*retval	= va_arg(ap, int *);
22492fe8fb19SBen Gras 	struct passwd	*pw	= va_arg(ap, struct passwd *);
22502fe8fb19SBen Gras 	char		*buffer	= va_arg(ap, char *);
22512fe8fb19SBen Gras 	size_t		 buflen	= va_arg(ap, size_t);
22522fe8fb19SBen Gras 	struct passwd  **result	= va_arg(ap, struct passwd **);
22532fe8fb19SBen Gras 
22542fe8fb19SBen Gras 	int		rv;
22552fe8fb19SBen Gras 
22562fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
22572fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
22582fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
22592fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
22602fe8fb19SBen Gras 
22612fe8fb19SBen Gras 	rv = _compat_pwscan(retval, pw, buffer, buflen, &_compat_state,
22622fe8fb19SBen Gras 	    _PW_KEYBYNUM, NULL, 0);
22632fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
22642fe8fb19SBen Gras 		*result = pw;
22652fe8fb19SBen Gras 	else
22662fe8fb19SBen Gras 		*result = NULL;
22672fe8fb19SBen Gras 	return rv;
22682fe8fb19SBen Gras }
22692fe8fb19SBen Gras 
22702fe8fb19SBen Gras 
22712fe8fb19SBen Gras /*ARGSUSED*/
22722fe8fb19SBen Gras static int
_compat_getpwnam(void * nsrv,void * nscb,va_list ap)22732fe8fb19SBen Gras _compat_getpwnam(void *nsrv, void *nscb, va_list ap)
22742fe8fb19SBen Gras {
22752fe8fb19SBen Gras 	struct passwd	**retval = va_arg(ap, struct passwd **);
22762fe8fb19SBen Gras 	const char	*name	= va_arg(ap, const char *);
22772fe8fb19SBen Gras 
22782fe8fb19SBen Gras 	int	rv, rerror;
22792fe8fb19SBen Gras 
22802fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
22812fe8fb19SBen Gras 
22822fe8fb19SBen Gras 	*retval = NULL;
22832fe8fb19SBen Gras 	rv = _compat_start(&_compat_state);
22842fe8fb19SBen Gras 	if (rv != NS_SUCCESS)
22852fe8fb19SBen Gras 		return rv;
22862fe8fb19SBen Gras 	rv = _compat_pwscan(&rerror, &_compat_passwd,
22872fe8fb19SBen Gras 	    _compat_passwdbuf, sizeof(_compat_passwdbuf),
22882fe8fb19SBen Gras 	    &_compat_state, _PW_KEYBYNAME, name, 0);
22892fe8fb19SBen Gras 	if (!_compat_state.stayopen)
22902fe8fb19SBen Gras 		_compat_end(&_compat_state);
22912fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
22922fe8fb19SBen Gras 		*retval = &_compat_passwd;
22932fe8fb19SBen Gras 	return rv;
22942fe8fb19SBen Gras }
22952fe8fb19SBen Gras 
22962fe8fb19SBen Gras /*ARGSUSED*/
22972fe8fb19SBen Gras static int
_compat_getpwnam_r(void * nsrv,void * nscb,va_list ap)22982fe8fb19SBen Gras _compat_getpwnam_r(void *nsrv, void *nscb, va_list ap)
22992fe8fb19SBen Gras {
23002fe8fb19SBen Gras 	int		*retval	= va_arg(ap, int *);
23012fe8fb19SBen Gras 	const char	*name	= va_arg(ap, const char *);
23022fe8fb19SBen Gras 	struct passwd	*pw	= va_arg(ap, struct passwd *);
23032fe8fb19SBen Gras 	char		*buffer	= va_arg(ap, char *);
23042fe8fb19SBen Gras 	size_t		 buflen	= va_arg(ap, size_t);
23052fe8fb19SBen Gras 	struct passwd  **result	= va_arg(ap, struct passwd **);
23062fe8fb19SBen Gras 
23072fe8fb19SBen Gras 	struct compat_state	state;
23082fe8fb19SBen Gras 	int		rv;
23092fe8fb19SBen Gras 
23102fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
23112fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
23122fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
23132fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
23142fe8fb19SBen Gras 
23152fe8fb19SBen Gras 	*result = NULL;
23162fe8fb19SBen Gras 	memset(&state, 0, sizeof(state));
23172fe8fb19SBen Gras 	rv = _compat_pwscan(retval, pw, buffer, buflen, &state,
23182fe8fb19SBen Gras 	    _PW_KEYBYNAME, name, 0);
23192fe8fb19SBen Gras 	_compat_end(&state);
23202fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
23212fe8fb19SBen Gras 		*result = pw;
23222fe8fb19SBen Gras 	return rv;
23232fe8fb19SBen Gras }
23242fe8fb19SBen Gras 
23252fe8fb19SBen Gras /*ARGSUSED*/
23262fe8fb19SBen Gras static int
_compat_getpwuid(void * nsrv,void * nscb,va_list ap)23272fe8fb19SBen Gras _compat_getpwuid(void *nsrv, void *nscb, va_list ap)
23282fe8fb19SBen Gras {
23292fe8fb19SBen Gras 	struct passwd	**retval = va_arg(ap, struct passwd **);
23302fe8fb19SBen Gras 	uid_t		 uid	= va_arg(ap, uid_t);
23312fe8fb19SBen Gras 
23322fe8fb19SBen Gras 	int	rv, rerror;
23332fe8fb19SBen Gras 
23342fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
23352fe8fb19SBen Gras 
23362fe8fb19SBen Gras 	*retval = NULL;
23372fe8fb19SBen Gras 	rv = _compat_start(&_compat_state);
23382fe8fb19SBen Gras 	if (rv != NS_SUCCESS)
23392fe8fb19SBen Gras 		return rv;
23402fe8fb19SBen Gras 	rv = _compat_pwscan(&rerror, &_compat_passwd,
23412fe8fb19SBen Gras 	    _compat_passwdbuf, sizeof(_compat_passwdbuf),
23422fe8fb19SBen Gras 	    &_compat_state, _PW_KEYBYUID, NULL, uid);
23432fe8fb19SBen Gras 	if (!_compat_state.stayopen)
23442fe8fb19SBen Gras 		_compat_end(&_compat_state);
23452fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
23462fe8fb19SBen Gras 		*retval = &_compat_passwd;
23472fe8fb19SBen Gras 	return rv;
23482fe8fb19SBen Gras }
23492fe8fb19SBen Gras 
23502fe8fb19SBen Gras /*ARGSUSED*/
23512fe8fb19SBen Gras static int
_compat_getpwuid_r(void * nsrv,void * nscb,va_list ap)23522fe8fb19SBen Gras _compat_getpwuid_r(void *nsrv, void *nscb, va_list ap)
23532fe8fb19SBen Gras {
23542fe8fb19SBen Gras 	int		*retval	= va_arg(ap, int *);
23552fe8fb19SBen Gras 	uid_t		 uid	= va_arg(ap, uid_t);
23562fe8fb19SBen Gras 	struct passwd	*pw	= va_arg(ap, struct passwd *);
23572fe8fb19SBen Gras 	char		*buffer	= va_arg(ap, char *);
23582fe8fb19SBen Gras 	size_t		 buflen	= va_arg(ap, size_t);
23592fe8fb19SBen Gras 	struct passwd  **result	= va_arg(ap, struct passwd **);
23602fe8fb19SBen Gras 
23612fe8fb19SBen Gras 	struct compat_state	state;
23622fe8fb19SBen Gras 	int		rv;
23632fe8fb19SBen Gras 
23642fe8fb19SBen Gras 	_DIAGASSERT(retval != NULL);
23652fe8fb19SBen Gras 	_DIAGASSERT(pw != NULL);
23662fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
23672fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
23682fe8fb19SBen Gras 
23692fe8fb19SBen Gras 	*result = NULL;
23702fe8fb19SBen Gras 	memset(&state, 0, sizeof(state));
23712fe8fb19SBen Gras 	rv = _compat_pwscan(retval, pw, buffer, buflen, &state,
23722fe8fb19SBen Gras 	    _PW_KEYBYUID, NULL, uid);
23732fe8fb19SBen Gras 	_compat_end(&state);
23742fe8fb19SBen Gras 	if (rv == NS_SUCCESS)
23752fe8fb19SBen Gras 		*result = pw;
23762fe8fb19SBen Gras 	return rv;
23772fe8fb19SBen Gras }
23782fe8fb19SBen Gras 
23792fe8fb19SBen Gras #endif /* _PASSWD_COMPAT */
23802fe8fb19SBen Gras 
23812fe8fb19SBen Gras 
23822fe8fb19SBen Gras 		/*
23832fe8fb19SBen Gras 		 *	public functions
23842fe8fb19SBen Gras 		 */
23852fe8fb19SBen Gras 
23862fe8fb19SBen Gras struct passwd *
getpwent(void)23872fe8fb19SBen Gras getpwent(void)
23882fe8fb19SBen Gras {
23892fe8fb19SBen Gras 	int		r;
23902fe8fb19SBen Gras 	struct passwd	*retval;
23912fe8fb19SBen Gras 
23922fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
23932fe8fb19SBen Gras 		NS_FILES_CB(_files_getpwent, NULL)
23942fe8fb19SBen Gras 		NS_DNS_CB(_dns_getpwent, NULL)
23952fe8fb19SBen Gras 		NS_NIS_CB(_nis_getpwent, NULL)
23962fe8fb19SBen Gras 		NS_COMPAT_CB(_compat_getpwent, NULL)
23972fe8fb19SBen Gras 		NS_NULL_CB
23982fe8fb19SBen Gras 	};
23992fe8fb19SBen Gras 
24002fe8fb19SBen Gras 	mutex_lock(&_pwmutex);
24012fe8fb19SBen Gras 	r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwent", __nsdefaultcompat,
24022fe8fb19SBen Gras 	    &retval);
24032fe8fb19SBen Gras 	mutex_unlock(&_pwmutex);
24042fe8fb19SBen Gras 	return (r == NS_SUCCESS) ? retval : NULL;
24052fe8fb19SBen Gras }
24062fe8fb19SBen Gras 
24072fe8fb19SBen Gras int
getpwent_r(struct passwd * pwd,char * buffer,size_t buflen,struct passwd ** result)24082fe8fb19SBen Gras getpwent_r(struct passwd *pwd, char *buffer, size_t buflen,
24092fe8fb19SBen Gras     struct passwd **result)
24102fe8fb19SBen Gras {
24112fe8fb19SBen Gras 	int	r, retval;
24122fe8fb19SBen Gras 
24132fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
24142fe8fb19SBen Gras 		NS_FILES_CB(_files_getpwent_r, NULL)
24152fe8fb19SBen Gras 		NS_DNS_CB(_dns_getpwent_r, NULL)
24162fe8fb19SBen Gras 		NS_NIS_CB(_nis_getpwent_r, NULL)
24172fe8fb19SBen Gras 		NS_COMPAT_CB(_compat_getpwent_r, NULL)
24182fe8fb19SBen Gras 		NS_NULL_CB
24192fe8fb19SBen Gras 	};
24202fe8fb19SBen Gras 
24212fe8fb19SBen Gras 	_DIAGASSERT(pwd != NULL);
24222fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
24232fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
24242fe8fb19SBen Gras 
24252fe8fb19SBen Gras 	*result = NULL;
24262fe8fb19SBen Gras 	retval = 0;
24272fe8fb19SBen Gras 	mutex_lock(&_pwmutex);
24282fe8fb19SBen Gras 	r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwent_r", __nsdefaultcompat,
24292fe8fb19SBen Gras 	    &retval, pwd, buffer, buflen, result);
24302fe8fb19SBen Gras 	mutex_unlock(&_pwmutex);
24312fe8fb19SBen Gras 	switch (r) {
24322fe8fb19SBen Gras 	case NS_SUCCESS:
24332fe8fb19SBen Gras 	case NS_NOTFOUND:
24342fe8fb19SBen Gras 		return 0;
24352fe8fb19SBen Gras 	default:
24362fe8fb19SBen Gras 		return retval;
24372fe8fb19SBen Gras 	}
24382fe8fb19SBen Gras }
24392fe8fb19SBen Gras 
24402fe8fb19SBen Gras 
24412fe8fb19SBen Gras struct passwd *
getpwnam(const char * name)24422fe8fb19SBen Gras getpwnam(const char *name)
24432fe8fb19SBen Gras {
24442fe8fb19SBen Gras 	int		rv;
24452fe8fb19SBen Gras 	struct passwd	*retval;
24462fe8fb19SBen Gras 
24472fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
24482fe8fb19SBen Gras 		NS_FILES_CB(_files_getpwnam, NULL)
24492fe8fb19SBen Gras 		NS_DNS_CB(_dns_getpwnam, NULL)
24502fe8fb19SBen Gras 		NS_NIS_CB(_nis_getpwnam, NULL)
24512fe8fb19SBen Gras 		NS_COMPAT_CB(_compat_getpwnam, NULL)
24522fe8fb19SBen Gras 		NS_NULL_CB
24532fe8fb19SBen Gras 	};
24542fe8fb19SBen Gras 
24552fe8fb19SBen Gras 	mutex_lock(&_pwmutex);
24562fe8fb19SBen Gras 	rv = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwnam", __nsdefaultcompat,
24572fe8fb19SBen Gras 	    &retval, name);
24582fe8fb19SBen Gras 	mutex_unlock(&_pwmutex);
24592fe8fb19SBen Gras 	return (rv == NS_SUCCESS) ? retval : NULL;
24602fe8fb19SBen Gras }
24612fe8fb19SBen Gras 
24622fe8fb19SBen Gras int
getpwnam_r(const char * name,struct passwd * pwd,char * buffer,size_t buflen,struct passwd ** result)24632fe8fb19SBen Gras getpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t buflen,
24642fe8fb19SBen Gras 	struct passwd **result)
24652fe8fb19SBen Gras {
24662fe8fb19SBen Gras 	int	r, retval;
24672fe8fb19SBen Gras 
24682fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
24692fe8fb19SBen Gras 		NS_FILES_CB(_files_getpwnam_r, NULL)
24702fe8fb19SBen Gras 		NS_DNS_CB(_dns_getpwnam_r, NULL)
24712fe8fb19SBen Gras 		NS_NIS_CB(_nis_getpwnam_r, NULL)
24722fe8fb19SBen Gras 		NS_COMPAT_CB(_compat_getpwnam_r, NULL)
24732fe8fb19SBen Gras 		NS_NULL_CB
24742fe8fb19SBen Gras 	};
24752fe8fb19SBen Gras 
24762fe8fb19SBen Gras 	_DIAGASSERT(name != NULL);
24772fe8fb19SBen Gras 	_DIAGASSERT(pwd != NULL);
24782fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
24792fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
24802fe8fb19SBen Gras 
24812fe8fb19SBen Gras 	*result = NULL;
24822fe8fb19SBen Gras 	retval = 0;
24832fe8fb19SBen Gras 	mutex_lock(&_pwmutex);
24842fe8fb19SBen Gras 	r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwnam_r", __nsdefaultcompat,
24852fe8fb19SBen Gras 	    &retval, name, pwd, buffer, buflen, result);
24862fe8fb19SBen Gras 	mutex_unlock(&_pwmutex);
24872fe8fb19SBen Gras 	switch (r) {
24882fe8fb19SBen Gras 	case NS_SUCCESS:
24892fe8fb19SBen Gras 	case NS_NOTFOUND:
24902fe8fb19SBen Gras 		return 0;
24912fe8fb19SBen Gras 	default:
24922fe8fb19SBen Gras 		return retval;
24932fe8fb19SBen Gras 	}
24942fe8fb19SBen Gras }
24952fe8fb19SBen Gras 
24962fe8fb19SBen Gras struct passwd *
getpwuid(uid_t uid)24972fe8fb19SBen Gras getpwuid(uid_t uid)
24982fe8fb19SBen Gras {
24992fe8fb19SBen Gras 	int		rv;
25002fe8fb19SBen Gras 	struct passwd	*retval;
25012fe8fb19SBen Gras 
25022fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
25032fe8fb19SBen Gras 		NS_FILES_CB(_files_getpwuid, NULL)
25042fe8fb19SBen Gras 		NS_DNS_CB(_dns_getpwuid, NULL)
25052fe8fb19SBen Gras 		NS_NIS_CB(_nis_getpwuid, NULL)
25062fe8fb19SBen Gras 		NS_COMPAT_CB(_compat_getpwuid, NULL)
25072fe8fb19SBen Gras 		NS_NULL_CB
25082fe8fb19SBen Gras 	};
25092fe8fb19SBen Gras 
25102fe8fb19SBen Gras 	mutex_lock(&_pwmutex);
25112fe8fb19SBen Gras 	rv = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwuid", __nsdefaultcompat,
25122fe8fb19SBen Gras 	    &retval, uid);
25132fe8fb19SBen Gras 	mutex_unlock(&_pwmutex);
25142fe8fb19SBen Gras 	return (rv == NS_SUCCESS) ? retval : NULL;
25152fe8fb19SBen Gras }
25162fe8fb19SBen Gras 
25172fe8fb19SBen Gras int
getpwuid_r(uid_t uid,struct passwd * pwd,char * buffer,size_t buflen,struct passwd ** result)25182fe8fb19SBen Gras getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t buflen,
25192fe8fb19SBen Gras 	struct passwd **result)
25202fe8fb19SBen Gras {
25212fe8fb19SBen Gras 	int	r, retval;
25222fe8fb19SBen Gras 
25232fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
25242fe8fb19SBen Gras 		NS_FILES_CB(_files_getpwuid_r, NULL)
25252fe8fb19SBen Gras 		NS_DNS_CB(_dns_getpwuid_r, NULL)
25262fe8fb19SBen Gras 		NS_NIS_CB(_nis_getpwuid_r, NULL)
25272fe8fb19SBen Gras 		NS_COMPAT_CB(_compat_getpwuid_r, NULL)
25282fe8fb19SBen Gras 		NS_NULL_CB
25292fe8fb19SBen Gras 	};
25302fe8fb19SBen Gras 
25312fe8fb19SBen Gras 	_DIAGASSERT(pwd != NULL);
25322fe8fb19SBen Gras 	_DIAGASSERT(buffer != NULL);
25332fe8fb19SBen Gras 	_DIAGASSERT(result != NULL);
25342fe8fb19SBen Gras 
25352fe8fb19SBen Gras 	*result = NULL;
25362fe8fb19SBen Gras 	retval = 0;
25372fe8fb19SBen Gras 	mutex_lock(&_pwmutex);
25382fe8fb19SBen Gras 	r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwuid_r", __nsdefaultcompat,
25392fe8fb19SBen Gras 	    &retval, uid, pwd, buffer, buflen, result);
25402fe8fb19SBen Gras 	mutex_unlock(&_pwmutex);
25412fe8fb19SBen Gras 	switch (r) {
25422fe8fb19SBen Gras 	case NS_SUCCESS:
25432fe8fb19SBen Gras 	case NS_NOTFOUND:
25442fe8fb19SBen Gras 		return 0;
25452fe8fb19SBen Gras 	default:
25462fe8fb19SBen Gras 		return retval;
25472fe8fb19SBen Gras 	}
25482fe8fb19SBen Gras }
25492fe8fb19SBen Gras 
25502fe8fb19SBen Gras void
endpwent(void)25512fe8fb19SBen Gras endpwent(void)
25522fe8fb19SBen Gras {
25532fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
25542fe8fb19SBen Gras 		NS_FILES_CB(_files_endpwent, NULL)
25552fe8fb19SBen Gras 		NS_DNS_CB(_dns_endpwent, NULL)
25562fe8fb19SBen Gras 		NS_NIS_CB(_nis_endpwent, NULL)
25572fe8fb19SBen Gras 		NS_COMPAT_CB(_compat_endpwent, NULL)
25582fe8fb19SBen Gras 		NS_NULL_CB
25592fe8fb19SBen Gras 	};
25602fe8fb19SBen Gras 
25612fe8fb19SBen Gras 	mutex_lock(&_pwmutex);
25622fe8fb19SBen Gras 					/* force all endpwent() methods */
25632fe8fb19SBen Gras 	(void) nsdispatch(NULL, dtab, NSDB_PASSWD, "endpwent",
25642fe8fb19SBen Gras 	    __nsdefaultcompat_forceall);
25652fe8fb19SBen Gras 	mutex_unlock(&_pwmutex);
25662fe8fb19SBen Gras }
25672fe8fb19SBen Gras 
25682fe8fb19SBen Gras /*ARGSUSED*/
25692fe8fb19SBen Gras int
setpassent(int stayopen)25702fe8fb19SBen Gras setpassent(int stayopen)
25712fe8fb19SBen Gras {
25722fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
25732fe8fb19SBen Gras 		NS_FILES_CB(_files_setpassent, NULL)
25742fe8fb19SBen Gras 		NS_DNS_CB(_dns_setpassent, NULL)
25752fe8fb19SBen Gras 		NS_NIS_CB(_nis_setpassent, NULL)
25762fe8fb19SBen Gras 		NS_COMPAT_CB(_compat_setpassent, NULL)
25772fe8fb19SBen Gras 		NS_NULL_CB
25782fe8fb19SBen Gras 	};
25792fe8fb19SBen Gras 	int	rv, retval;
25802fe8fb19SBen Gras 
25812fe8fb19SBen Gras 	mutex_lock(&_pwmutex);
25822fe8fb19SBen Gras 					/* force all setpassent() methods */
25832fe8fb19SBen Gras 	rv = nsdispatch(NULL, dtab, NSDB_PASSWD, "setpassent",
25842fe8fb19SBen Gras 	    __nsdefaultcompat_forceall, &retval, stayopen);
25852fe8fb19SBen Gras 	mutex_unlock(&_pwmutex);
25862fe8fb19SBen Gras 	return (rv == NS_SUCCESS) ? retval : 0;
25872fe8fb19SBen Gras }
25882fe8fb19SBen Gras 
25892fe8fb19SBen Gras void
setpwent(void)25902fe8fb19SBen Gras setpwent(void)
25912fe8fb19SBen Gras {
25922fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
25932fe8fb19SBen Gras 		NS_FILES_CB(_files_setpwent, NULL)
25942fe8fb19SBen Gras 		NS_DNS_CB(_dns_setpwent, NULL)
25952fe8fb19SBen Gras 		NS_NIS_CB(_nis_setpwent, NULL)
25962fe8fb19SBen Gras 		NS_COMPAT_CB(_compat_setpwent, NULL)
25972fe8fb19SBen Gras 		NS_NULL_CB
25982fe8fb19SBen Gras 	};
25992fe8fb19SBen Gras 
26002fe8fb19SBen Gras 	mutex_lock(&_pwmutex);
26012fe8fb19SBen Gras 					/* force all setpwent() methods */
26022fe8fb19SBen Gras 	(void) nsdispatch(NULL, dtab, NSDB_PASSWD, "setpwent",
26032fe8fb19SBen Gras 	    __nsdefaultcompat_forceall);
26042fe8fb19SBen Gras 	mutex_unlock(&_pwmutex);
26052fe8fb19SBen Gras }
2606