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