diff options
author | nectar <nectar@FreeBSD.org> | 2000-09-06 18:16:48 +0000 |
---|---|---|
committer | nectar <nectar@FreeBSD.org> | 2000-09-06 18:16:48 +0000 |
commit | 748554442d0ac4467fdac2ce9d42006588fd4481 (patch) | |
tree | aed2ddbcac97f46f60ee9c2063a3345553f6a1ee /lib/libc/gen/getpwent.c | |
parent | 59ffb36b778f8e629622726f6bd32dfa4fda7e35 (diff) | |
download | FreeBSD-src-748554442d0ac4467fdac2ce9d42006588fd4481.zip FreeBSD-src-748554442d0ac4467fdac2ce9d42006588fd4481.tar.gz |
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
Diffstat (limited to 'lib/libc/gen/getpwent.c')
-rw-r--r-- | lib/libc/gen/getpwent.c | 1665 |
1 files changed, 990 insertions, 675 deletions
diff --git a/lib/libc/gen/getpwent.c b/lib/libc/gen/getpwent.c index 00e6ca3..3c8620e 100644 --- a/lib/libc/gen/getpwent.c +++ b/lib/libc/gen/getpwent.c @@ -1,6 +1,9 @@ +/* $NetBSD: getpwent.c,v 1.40.2.2 1999/04/27 22:09:45 perry Exp $ */ + /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. + * Portions Copyright (c) 1994, 1995, Jason Downs. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,15 +32,14 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ +#include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getpwent.c 8.2 (Berkeley) 4/27/95"; +static const char *rcsid[] = + "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ -#include <stdio.h> #include <sys/param.h> #include <fcntl.h> #include <db.h> @@ -49,11 +51,27 @@ static char sccsid[] = "@(#)getpwent.c 8.2 (Berkeley) 4/27/95"; #include <stdlib.h> #include <string.h> #include <limits.h> -#include <grp.h> +#include <nsswitch.h> +#ifdef HESIOD +#include <hesiod.h> +#endif +#ifdef YP +#include <machine/param.h> +#include <stdio.h> +#include <rpc/rpc.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> +#endif + +extern void setnetgrent __P((char *)); +extern int getnetgrent __P((char **, char **, char **)); +extern int innetgr __P((const char *, const char *, const char *, const char *)); -extern void setnetgrent __P(( char * )); -extern int getnetgrent __P(( char **, char **, char ** )); -extern int innetgr __P(( const char *, const char *, const char *, const char * )); +#include "pw_scan.h" + +#if defined(YP) || defined(HESIOD) +#define _PASSWD_COMPAT +#endif /* * The lookup techniques and data extraction code here must be kept @@ -62,799 +80,1096 @@ extern int innetgr __P(( const char *, const char *, const char *, const char * static struct passwd _pw_passwd; /* password structure */ static DB *_pw_db; /* password database */ -static int _pw_keynum; /* key counter */ +static int _pw_keynum; /* key counter. no more records if -1 */ static int _pw_stayopen; /* keep fd's open */ -#ifdef YP -#include <rpc/rpc.h> -#include <rpcsvc/yp_prot.h> -#include <rpcsvc/ypclnt.h> +static int _pw_flags; /* password flags */ -static struct passwd _pw_copy; -static DBT empty = { NULL, 0 }; -static DB *_ypcache = (DB *)NULL; -static int _yp_exclusions = 0; -static int _yp_enabled = -1; -static int _pw_stepping_yp; /* set true when stepping thru map */ -static char _ypnam[YPMAXRECORD]; -#define YP_HAVE_MASTER 2 -#define YP_HAVE_ADJUNCT 1 -#define YP_HAVE_NONE 0 -static int _gotmaster; -static char *_pw_yp_domain; -static inline int unwind __P(( char * )); -static void _ypinitdb __P(( void )); -static int _havemaster __P((char *)); -static int _getyppass __P((struct passwd *, const char *, const char * )); -static int _nextyppass __P((struct passwd *)); -static inline int lookup __P((const char *)); -static inline void store __P((const char *)); -static inline int ingr __P((const char *, const char*)); -static inline int verf __P((const char *)); -static char * _get_adjunct_pw __P((const char *)); -#endif -static int __hashpw(DBT *); -static int __initdb(void); - -struct passwd * -getpwent() -{ - DBT key; - char bf[sizeof(_pw_keynum) + 1]; - int rv; +static int __hashpw __P((DBT *)); +static int __initdb __P((void)); - if (!_pw_db && !__initdb()) - return((struct passwd *)NULL); +static const ns_src compatsrc[] = { + { NSSRC_COMPAT, NS_SUCCESS }, + { 0 } +}; #ifdef YP - if(_pw_stepping_yp) { - _pw_passwd = _pw_copy; - if (unwind((char *)&_ypnam)) - return(&_pw_passwd); - } +static char *__ypcurrent, *__ypdomain; +static int __ypcurrentlen; +static int _pw_ypdone; /* non-zero if no more yp records */ #endif -tryagain: - ++_pw_keynum; - bf[0] = _PW_KEYBYNUM; - bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); - key.data = (u_char *)bf; - key.size = sizeof(_pw_keynum) + 1; - rv = __hashpw(&key); - if(!rv) return (struct passwd *)NULL; -#ifdef YP - if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { - if (_yp_enabled == -1) - _ypinitdb(); - bzero((char *)&_ypnam, sizeof(_ypnam)); - bcopy(_pw_passwd.pw_name, _ypnam, - strlen(_pw_passwd.pw_name)); - _pw_copy = _pw_passwd; - if (unwind((char *)&_ypnam) == 0) - goto tryagain; - else - return(&_pw_passwd); - } -#else - /* Ignore YP password file entries when YP is disabled. */ - if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { - goto tryagain; - } +#ifdef HESIOD +static int _pw_hesnum; /* hes counter. no more records if -1 */ #endif - return(&_pw_passwd); -} -struct passwd * -getpwnam(name) +#ifdef _PASSWD_COMPAT +enum _pwmode { PWMODE_NONE, PWMODE_FULL, PWMODE_USER, PWMODE_NETGRP }; +static enum _pwmode __pwmode; + +enum _ypmap { YPMAP_NONE, YPMAP_ADJUNCT, YPMAP_MASTER }; + +static struct passwd *__pwproto = (struct passwd *)NULL; +static int __pwproto_flags; +static char line[1024]; +static long prbuf[1024 / sizeof(long)]; +static DB *__pwexclude = (DB *)NULL; + +static int __pwexclude_add __P((const char *)); +static int __pwexclude_is __P((const char *)); +static void __pwproto_set __P((void)); +static int __ypmaptype __P((void)); +static int __pwparse __P((struct passwd *, char *)); + + /* macros for deciding which YP maps to use. */ +#define PASSWD_BYNAME (__ypmaptype() == YPMAP_MASTER \ + ? "master.passwd.byname" : "passwd.byname") +#define PASSWD_BYUID (__ypmaptype() == YPMAP_MASTER \ + ? "master.passwd.byuid" : "passwd.byuid") + +/* + * add a name to the compat mode exclude list + */ +static int +__pwexclude_add(name) const char *name; { DBT key; - int len, rval; - char bf[UT_NAMESIZE + 2]; + DBT data; - if (!_pw_db && !__initdb()) - return((struct passwd *)NULL); + /* initialize the exclusion table if needed. */ + if(__pwexclude == (DB *)NULL) { + __pwexclude = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL); + if(__pwexclude == (DB *)NULL) + return 1; + } - bf[0] = _PW_KEYBYNAME; - len = strlen(name); - if (len > UT_NAMESIZE) - return(NULL); - bcopy(name, bf + 1, len); - key.data = (u_char *)bf; - key.size = len + 1; - rval = __hashpw(&key); + /* set up the key */ + key.size = strlen(name); + /* LINTED key does not get modified */ + key.data = (char *)name; -#ifdef YP - if (!rval) { - if (_yp_enabled == -1) - _ypinitdb(); - if (_yp_enabled) - rval = _getyppass(&_pw_passwd, name, "passwd.byname"); - } -#endif - /* - * Prevent login attempts when YP is not enabled but YP entries - * are in /etc/master.passwd. - */ - if (rval && (_pw_passwd.pw_name[0] == '+'|| - _pw_passwd.pw_name[0] == '-')) rval = 0; + /* data is nothing. */ + data.data = NULL; + data.size = 0; - if (!_pw_stayopen) - endpwent(); - return(rval ? &_pw_passwd : (struct passwd *)NULL); + /* store it */ + if((__pwexclude->put)(__pwexclude, &key, &data, 0) == -1) + return 1; + + return 0; } -struct passwd * -getpwuid(uid) - uid_t uid; +/* + * test if a name is on the compat mode exclude list + */ +static int +__pwexclude_is(name) + const char *name; { DBT key; - int keyuid, rval; - char bf[sizeof(keyuid) + 1]; - - if (!_pw_db && !__initdb()) - return((struct passwd *)NULL); + DBT data; - bf[0] = _PW_KEYBYUID; - keyuid = uid; - bcopy(&keyuid, bf + 1, sizeof(keyuid)); - key.data = (u_char *)bf; - key.size = sizeof(keyuid) + 1; - rval = __hashpw(&key); + if(__pwexclude == (DB *)NULL) + return 0; /* nothing excluded */ -#ifdef YP - if (!rval) { - if (_yp_enabled == -1) - _ypinitdb(); - if (_yp_enabled) { - char ypbuf[16]; /* big enough for 32-bit uids */ - snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid); - rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid"); - } - } -#endif - /* - * Prevent login attempts when YP is not enabled but YP entries - * are in /etc/master.passwd. - */ - if (rval && (_pw_passwd.pw_name[0] == '+'|| - _pw_passwd.pw_name[0] == '-')) rval = 0; + /* set up the key */ + key.size = strlen(name); + /* LINTED key does not get modified */ + key.data = (char *)name; - if (!_pw_stayopen) - endpwent(); - return(rval ? &_pw_passwd : (struct passwd *)NULL); + if((__pwexclude->get)(__pwexclude, &key, &data, 0) == 0) + return 1; /* excluded */ + + return 0; } -int -setpassent(stayopen) - int stayopen; +/* + * setup the compat mode prototype template + */ +static void +__pwproto_set() { - _pw_keynum = 0; -#ifdef YP - _pw_stepping_yp = 0; - if (stayopen) - setgroupent(1); -#endif - _pw_stayopen = stayopen; - return(1); + char *ptr; + struct passwd *pw = &_pw_passwd; + + /* make this the new prototype */ + ptr = (char *)(void *)prbuf; + + /* first allocate the struct. */ + __pwproto = (struct passwd *)(void *)ptr; + ptr += sizeof(struct passwd); + + /* name */ + if(pw->pw_name && (pw->pw_name)[0]) { + ptr = (char *)ALIGN((u_long)ptr); + memmove(ptr, pw->pw_name, strlen(pw->pw_name) + 1); + __pwproto->pw_name = ptr; + ptr += (strlen(pw->pw_name) + 1); + } else + __pwproto->pw_name = (char *)NULL; + + /* password */ + if(pw->pw_passwd && (pw->pw_passwd)[0]) { + ptr = (char *)ALIGN((u_long)ptr); + memmove(ptr, pw->pw_passwd, strlen(pw->pw_passwd) + 1); + __pwproto->pw_passwd = ptr; + ptr += (strlen(pw->pw_passwd) + 1); + } else + __pwproto->pw_passwd = (char *)NULL; + + /* uid */ + __pwproto->pw_uid = pw->pw_uid; + + /* gid */ + __pwproto->pw_gid = pw->pw_gid; + + /* change (ignored anyway) */ + __pwproto->pw_change = pw->pw_change; + + /* class (ignored anyway) */ + __pwproto->pw_class = ""; + + /* gecos */ + if(pw->pw_gecos && (pw->pw_gecos)[0]) { + ptr = (char *)ALIGN((u_long)ptr); + memmove(ptr, pw->pw_gecos, strlen(pw->pw_gecos) + 1); + __pwproto->pw_gecos = ptr; + ptr += (strlen(pw->pw_gecos) + 1); + } else + __pwproto->pw_gecos = (char *)NULL; + + /* dir */ + if(pw->pw_dir && (pw->pw_dir)[0]) { + ptr = (char *)ALIGN((u_long)ptr); + memmove(ptr, pw->pw_dir, strlen(pw->pw_dir) + 1); + __pwproto->pw_dir = ptr; + ptr += (strlen(pw->pw_dir) + 1); + } else + __pwproto->pw_dir = (char *)NULL; + + /* shell */ + if(pw->pw_shell && (pw->pw_shell)[0]) { + ptr = (char *)ALIGN((u_long)ptr); + memmove(ptr, pw->pw_shell, strlen(pw->pw_shell) + 1); + __pwproto->pw_shell = ptr; + ptr += (strlen(pw->pw_shell) + 1); + } else + __pwproto->pw_shell = (char *)NULL; + + /* expire (ignored anyway) */ + __pwproto->pw_expire = pw->pw_expire; + + /* flags */ + __pwproto_flags = _pw_flags; } -void -setpwent() +static int +__ypmaptype() { - (void)setpassent(0); -} + static int maptype = -1; + int order, r; -void -endpwent() -{ - _pw_keynum = 0; -#ifdef YP - _pw_stepping_yp = 0; -#endif - if (_pw_db) { - (void)(_pw_db->close)(_pw_db); - _pw_db = (DB *)NULL; - } -#ifdef YP - if (_ypcache) { - (void)(_ypcache->close)(_ypcache); - _ypcache = (DB *)NULL; - _yp_exclusions = 0; - } - /* Fix for PR #12008 */ - _yp_enabled = -1; -#endif -} + if (maptype != -1) + return (maptype); -static int -__initdb() -{ - static int warned; - char *p; + maptype = YPMAP_NONE; + if (geteuid() != 0) + return (maptype); - p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB; - _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL); - if (_pw_db) - return(1); - if (!warned++) - syslog(LOG_ERR, "%s: %m", p); - return(0); -} + if (!__ypdomain) { + if( _yp_check(&__ypdomain) == 0) + return (maptype); + } -static int -__hashpw(key) - DBT *key; -{ - register char *p, *t; - static u_int max; - static char *line; - DBT data; + r = yp_order(__ypdomain, "master.passwd.byname", &order); + if (r == 0) { + maptype = YPMAP_MASTER; + return (maptype); + } - if ((_pw_db->get)(_pw_db, key, &data, 0)) - return(0); - p = (char *)data.data; + /* + * NIS+ in YP compat mode doesn't support + * YPPROC_ORDER -- no point in continuing. + */ + if (r == YPERR_YPERR) + return (maptype); - /* Increase buffer size for long lines if necessary. */ - if (data.size > max) { - max = data.size + 1024; - if (!(line = reallocf(line, max))) - return(0); + /* master.passwd doesn't exist -- try passwd.adjunct */ + if (r == YPERR_MAP) { + r = yp_order(__ypdomain, "passwd.adjunct.byname", &order); + if (r == 0) + maptype = YPMAP_ADJUNCT; + return (maptype); } - /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ - t = line; -#define EXPAND(e) e = t; while ( (*t++ = *p++) ); -#define SCALAR(v) memmove(&(v), p, sizeof v); p += sizeof v - EXPAND(_pw_passwd.pw_name); - EXPAND(_pw_passwd.pw_passwd); - SCALAR(_pw_passwd.pw_uid); - SCALAR(_pw_passwd.pw_gid); - SCALAR(_pw_passwd.pw_change); - EXPAND(_pw_passwd.pw_class); - EXPAND(_pw_passwd.pw_gecos); - EXPAND(_pw_passwd.pw_dir); - EXPAND(_pw_passwd.pw_shell); - SCALAR(_pw_passwd.pw_expire); - bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields); - p += sizeof _pw_passwd.pw_fields; - return(1); + return (maptype); } -#ifdef YP - -static void -_ypinitdb() +/* + * parse a passwd file line (from NIS or HESIOD). + * assumed to be `old-style' if maptype != YPMAP_MASTER. + */ +static int +__pwparse(pw, s) + struct passwd *pw; + char *s; { - DBT key, data; - char buf[] = { _PW_KEYYPENABLED }; - key.data = buf; - key.size = 1; - _yp_enabled = 0; - if ((_pw_db->get)(_pw_db, &key, &data, 0) == 0) { - _yp_enabled = (int)*((char *)data.data) - 2; - /* Don't even bother with this if we aren't root. */ - if (!geteuid()) { - if (!_pw_yp_domain) - if (yp_get_default_domain(&_pw_yp_domain)) - return; - _gotmaster = _havemaster(_pw_yp_domain); - } else _gotmaster = YP_HAVE_NONE; - /* - * Create a DB hash database in memory. Bet you didn't know you - * could do a dbopen() with a NULL filename, did you. - */ - if (_ypcache == (DB *)NULL) - _ypcache = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL); + static char adjunctpw[YPMAXRECORD + 2]; + int flags, maptype; + + maptype = __ypmaptype(); + flags = 0; + if (maptype == YPMAP_MASTER) + flags |= _PWSCAN_MASTER; + if (! __pw_scan(s, pw, flags)) + return 1; + + /* now let the prototype override, if set. */ + if(__pwproto != (struct passwd *)NULL) { +#ifdef PW_OVERRIDE_PASSWD + if(__pwproto_flags & _PWF_PASSWD) + pw->pw_passwd = __pwproto->pw_passwd; +#endif + if(__pwproto_flags & _PWF_UID) + pw->pw_uid = __pwproto->pw_uid; + if(__pwproto_flags & _PWF_GID) + pw->pw_gid = __pwproto->pw_gid; + if(__pwproto_flags & _PWF_GECOS) + pw->pw_gecos = __pwproto->pw_gecos; + if(__pwproto_flags & _PWF_DIR) + pw->pw_dir = __pwproto->pw_dir; + if(__pwproto_flags & _PWF_SHELL) + pw->pw_shell = __pwproto->pw_shell; } + if ((maptype == YPMAP_ADJUNCT) && + (strstr(pw->pw_passwd, "##") != NULL)) { + char *data, *bp; + int datalen; + + if (yp_match(__ypdomain, "passwd.adjunct.byname", pw->pw_name, + (int)strlen(pw->pw_name), &data, &datalen) == 0) { + if (datalen > sizeof(adjunctpw) - 1) + datalen = sizeof(adjunctpw) - 1; + strncpy(adjunctpw, data, (size_t)datalen); + + /* skip name to get password */ + if ((bp = strsep(&data, ":")) != NULL && + (bp = strsep(&data, ":")) != NULL) + pw->pw_passwd = bp; + } + } + return 0; } +#endif /* _PASSWD_COMPAT */ /* - * See if a user is in the blackballed list. + * local files implementation of getpw*() + * varargs: type, [ uid (type == _PW_KEYBYUID) | name (type == _PW_KEYBYNAME) ] */ -static inline int -lookup(name) - const char *name; +static int _local_getpw __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_local_getpw(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; { - DBT key; + DBT key; + char bf[/*CONSTCOND*/ MAX(MAXLOGNAME, sizeof(_pw_keynum)) + 1]; + uid_t uid; + int search, len, rval; + const char *name; - if (!_yp_exclusions) - return(0); + if (!_pw_db && !__initdb()) + return NS_UNAVAIL; + + search = va_arg(ap, int); + bf[0] = search; + switch (search) { + case _PW_KEYBYNUM: + if (_pw_keynum == -1) + return NS_NOTFOUND; /* no more local records */ + ++_pw_keynum; + memmove(bf + 1, &_pw_keynum, sizeof(_pw_keynum)); + key.size = sizeof(_pw_keynum) + 1; + break; + case _PW_KEYBYNAME: + name = va_arg(ap, const char *); + len = strlen(name); + memmove(bf + 1, name, (size_t)MIN(len, MAXLOGNAME)); + key.size = len + 1; + break; + case _PW_KEYBYUID: + uid = va_arg(ap, uid_t); + memmove(bf + 1, &uid, sizeof(len)); + key.size = sizeof(uid) + 1; + break; + default: + abort(); + } - key.data = (char *)name; - key.size = strlen(name); + key.data = (u_char *)bf; + rval = __hashpw(&key); + if (rval == NS_NOTFOUND && search == _PW_KEYBYNUM) + _pw_keynum = -1; /* flag `no more local records' */ - if ((_ypcache->get)(_ypcache, &key, &empty, 0)) { - return(0); + if (!_pw_stayopen && (search != _PW_KEYBYNUM)) { + (void)(_pw_db->close)(_pw_db); + _pw_db = (DB *)NULL; } - - return(1); + return (rval); } +#ifdef HESIOD /* - * Store a blackballed user in an in-core hash database. + * hesiod implementation of getpw*() + * varargs: type, [ uid (type == _PW_KEYBYUID) | name (type == _PW_KEYBYNAME) ] */ -static inline void -store(key) - const char *key; -{ - DBT lkey; -/* - if (lookup(key)) - return; -*/ - - _yp_exclusions = 1; +static int _dns_getpw __P((void *, void *, va_list)); - lkey.data = (char *)key; - lkey.size = strlen(key); +/*ARGSUSED*/ +static int +_dns_getpw(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; +{ + const char *name; + uid_t uid; + int search; + + const char *map; + char **hp; + void *context; + int r; + + search = va_arg(ap, int); + nextdnsbynum: + switch (search) { + case _PW_KEYBYNUM: + if (_pw_hesnum == -1) + return NS_NOTFOUND; /* no more hesiod records */ + snprintf(line, sizeof(line) - 1, "passwd-%u", _pw_hesnum); + _pw_hesnum++; + map = "passwd"; + break; + case _PW_KEYBYNAME: + name = va_arg(ap, const char *); + strncpy(line, name, sizeof(line)); + map = "passwd"; + break; + case _PW_KEYBYUID: + uid = va_arg(ap, uid_t); + snprintf(line, sizeof(line), "%u", (unsigned int)uid); + map = "uid"; /* XXX this is `passwd' on ultrix */ + break; + default: + abort(); + } + line[sizeof(line) - 1] = '\0'; + + r = NS_UNAVAIL; + if (hesiod_init(&context) == -1) + return (r); + + hp = hesiod_resolve(context, line, map); + if (hp == NULL) { + if (errno == ENOENT) { + /* flag `no more hesiod records' */ + if (search == _PW_KEYBYNUM) + _pw_hesnum = -1; + r = NS_NOTFOUND; + } + goto cleanup_dns_getpw; + } - (void)(_ypcache->put)(_ypcache, &lkey, &empty, R_NOOVERWRITE); + strncpy(line, hp[0], sizeof(line)); /* only check first elem */ + line[sizeof(line) - 1] = '\0'; + hesiod_free_list(context, hp); + if (__pwparse(&_pw_passwd, line)) { + if (search == _PW_KEYBYNUM) + goto nextdnsbynum; /* skip dogdy entries */ + r = NS_UNAVAIL; + } else + r = NS_SUCCESS; + cleanup_dns_getpw: + hesiod_end(context); + return (r); } +#endif +#ifdef YP /* - * Parse the + entries in the password database and do appropriate - * NIS lookups. While ugly to look at, this is optimized to do only - * as many lookups as are absolutely necessary in any given case. - * Basically, the getpwent() function will feed us + and - lines - * as they appear in the database. For + lines, we do netgroup/group - * and user lookups to find all usernames that match the rule and - * extract them from the NIS passwd maps. For - lines, we save the - * matching names in a database and a) exlude them, and b) make sure - * we don't consider them when processing other + lines that appear - * later. + * nis implementation of getpw*() + * varargs: type, [ uid (type == _PW_KEYBYUID) | name (type == _PW_KEYBYNAME) ] */ -static inline int -unwind(grp) - char *grp; +static int _nis_getpw __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_nis_getpw(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; { - char *user, *host, *domain; - static int latch = 0; - static struct group *gr = NULL; - int rv = 0; - - if (grp[0] == '+') { - if (strlen(grp) == 1) { - return(_nextyppass(&_pw_passwd)); + const char *name; + uid_t uid; + int search; + char *key, *data; + char *map; + int keylen, datalen, r, rval; + + if(__ypdomain == NULL) { + if(_yp_check(&__ypdomain) == 0) + return NS_UNAVAIL; + } + + map = PASSWD_BYNAME; + search = va_arg(ap, int); + switch (search) { + case _PW_KEYBYNUM: + break; + case _PW_KEYBYNAME: + name = va_arg(ap, const char *); + strncpy(line, name, sizeof(line)); + break; + case _PW_KEYBYUID: + uid = va_arg(ap, uid_t); + snprintf(line, sizeof(line), "%u", (unsigned int)uid); + map = PASSWD_BYUID; + break; + default: + abort(); + } + line[sizeof(line) - 1] = '\0'; + rval = NS_UNAVAIL; + if (search != _PW_KEYBYNUM) { + data = NULL; + r = yp_match(__ypdomain, map, line, (int)strlen(line), + &data, &datalen); + if (r == YPERR_KEY) + rval = NS_NOTFOUND; + if (r != 0) { + if (data) + free(data); + return (rval); } - if (grp[1] == '@') { - _pw_stepping_yp = 1; -grpagain: - if (gr != NULL) { - if (*gr->gr_mem != NULL) { - if (lookup(*gr->gr_mem)) { - gr->gr_mem++; - goto grpagain; - } - rv = _getyppass(&_pw_passwd, - *gr->gr_mem, - "passwd.byname"); - gr->gr_mem++; - return(rv); - } else { - latch = 0; - _pw_stepping_yp = 0; - gr = NULL; - return(0); - } - } - if (!latch) { - setnetgrent(grp+2); - latch++; - } -again: - if (getnetgrent(&host, &user, &domain) == 0) { - if ((gr = getgrnam(grp+2)) != NULL) - goto grpagain; - latch = 0; - _pw_stepping_yp = 0; - return(0); - } else { - if (lookup(user)) - goto again; - if (_getyppass(&_pw_passwd, user, - "passwd.byname")) - return(1); - else - goto again; + data[datalen] = '\0'; /* clear trailing \n */ + strncpy(line, data, sizeof(line)); + line[sizeof(line) - 1] = '\0'; + free(data); + if (__pwparse(&_pw_passwd, line)) + return NS_UNAVAIL; + return NS_SUCCESS; + } + + if (_pw_ypdone) + return NS_NOTFOUND; + for (;;) { + data = key = NULL; + if (__ypcurrent) { + r = yp_next(__ypdomain, map, + __ypcurrent, __ypcurrentlen, + &key, &keylen, &data, &datalen); + free(__ypcurrent); + switch (r) { + case 0: + __ypcurrent = key; + __ypcurrentlen = keylen; + break; + case YPERR_NOMORE: + __ypcurrent = NULL; + /* flag `no more yp records' */ + _pw_ypdone = 1; + rval = NS_NOTFOUND; } } else { - if (lookup(grp+1)) - return(0); - return(_getyppass(&_pw_passwd, grp+1, "passwd.byname")); + r = yp_first(__ypdomain, map, &__ypcurrent, + &__ypcurrentlen, &data, &datalen); } - } else { - if (grp[1] == '@') { - setnetgrent(grp+2); - rv = 0; - while(getnetgrent(&host, &user, &domain) != 0) { - store(user); - rv++; - } - if (!rv && (gr = getgrnam(grp+2)) != NULL) { - while(*gr->gr_mem) { - store(*gr->gr_mem); - gr->gr_mem++; - } - } - } else { - store(grp+1); + if (r != 0) { + if (key) + free(key); + if (data) + free(data); + return (rval); } + data[datalen] = '\0'; /* clear trailing \n */ + strncpy(line, data, sizeof(line)); + line[sizeof(line) - 1] = '\0'; + free(data); + if (! __pwparse(&_pw_passwd, line)) + return NS_SUCCESS; } - return(0); -} + /* NOTREACHED */ +} /* _nis_getpw */ +#endif +#ifdef _PASSWD_COMPAT /* - * See if a user is a member of a particular group. + * See if the compat token is in the database. Only works if pwd_mkdb knows + * about the token. */ -static inline int -ingr(grp, name) - const char *grp; - const char *name; +static int __has_compatpw __P((void)); + +static int +__has_compatpw() { - register struct group *gr; + DBT key, data; + DBT pkey, pdata; + char bf[MAXLOGNAME]; + u_char cyp[] = { _PW_KEYYPENABLED }; - if ((gr = getgrnam(grp)) == NULL) - return(0); + /*LINTED*/ + key.data = cyp; + key.size = 1; - while(*gr->gr_mem) { - if (!strcmp(*gr->gr_mem, name)) - return(1); - gr->gr_mem++; - } + /* Pre-token database support. */ + bf[0] = _PW_KEYBYNAME; + bf[1] = '+'; + pkey.data = (u_char *)bf; + pkey.size = 2; - return(0); + if ((_pw_db->get)(_pw_db, &key, &data, 0) + && (_pw_db->get)(_pw_db, &pkey, &pdata, 0)) + return 0; /* No compat token */ + return 1; } /* - * Check a user against the +@netgroup/-@netgroup lines listed in - * the local password database. Also checks +user/-user lines. - * If no netgroup exists that matches +@netgroup/-@netgroup, - * try searching regular groups with the same name. + * log an error if "files" or "compat" is specified in passwd_compat database */ -static inline int -verf(name) - const char *name; -{ - DBT key; - char bf[sizeof(_pw_keynum) + 1]; - int keynum = 0; +static int _bad_getpw __P((void *, void *, va_list)); -again: - ++keynum; - bf[0] = _PW_KEYYPBYNUM; - bcopy((char *)&keynum, bf + 1, sizeof(keynum)); - key.data = (u_char *)bf; - key.size = sizeof(keynum) + 1; - if (!__hashpw(&key)) { - /* Try again using old format */ - bf[0] = _PW_KEYBYNUM; - bcopy((char *)&keynum, bf + 1, sizeof(keynum)); - key.data = (u_char *)bf; - if (!__hashpw(&key)) - return(0); - } - if (_pw_passwd.pw_name[0] != '+' && (_pw_passwd.pw_name[0] != '-')) - goto again; - if (_pw_passwd.pw_name[0] == '+') { - if (strlen(_pw_passwd.pw_name) == 1) /* Wildcard */ - return(1); - if (_pw_passwd.pw_name[1] == '@') { - if ((innetgr(_pw_passwd.pw_name+2, NULL, name, - _pw_yp_domain) || - ingr(_pw_passwd.pw_name+2, name)) && !lookup(name)) - return(1); - else - goto again; - } else { - if (!strcmp(name, _pw_passwd.pw_name+1) && - !lookup(name)) - return(1); - else - goto again; - } - } - if (_pw_passwd.pw_name[0] == '-') { - /* Note that a minus wildcard is a no-op. */ - if (_pw_passwd.pw_name[1] == '@') { - if (innetgr(_pw_passwd.pw_name+2, NULL, name, - _pw_yp_domain) || - ingr(_pw_passwd.pw_name+2, name)) { - store(name); - return(0); - } else - goto again; - } else { - if (!strcmp(name, _pw_passwd.pw_name+1)) { - store(name); - return(0); - } else - goto again; - } - +/*ARGSUSED*/ +static int +_bad_getpw(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; +{ + static int warned; + if (!warned) { + syslog(LOG_ERR, + "nsswitch.conf passwd_compat database can't use '%s'", + (char *)cb_data); } - return(0); + warned = 1; + return NS_UNAVAIL; } -static char * -_get_adjunct_pw(name) - const char *name; -{ - static char adjunctbuf[YPMAXRECORD+2]; - int rval; - char *result; - int resultlen; - char *map = "passwd.adjunct.byname"; - char *s; - - if ((rval = yp_match(_pw_yp_domain, map, name, strlen(name), - &result, &resultlen))) - return(NULL); - - strncpy(adjunctbuf, result, resultlen); - adjunctbuf[resultlen] = '\0'; - free(result); - result = (char *)&adjunctbuf; - - /* Don't care about the name. */ - if ((s = strsep(&result, ":")) == NULL) - return (NULL); /* name */ - if ((s = strsep(&result, ":")) == NULL) - return (NULL); /* password */ +/* + * when a name lookup in compat mode is required (e.g., '+name', or a name in + * '+@netgroup'), look it up in the 'passwd_compat' nsswitch database. + * only Hesiod and NIS is supported - it doesn't make sense to lookup + * compat names from 'files' or 'compat'. + */ +static int __getpwcompat __P((int, uid_t, const char *)); - return(s); +static int +__getpwcompat(type, uid, name) + int type; + uid_t uid; + const char *name; +{ + static const ns_dtab dtab[] = { + NS_FILES_CB(_bad_getpw, "files") + NS_DNS_CB(_dns_getpw, NULL) + NS_NIS_CB(_nis_getpw, NULL) + NS_COMPAT_CB(_bad_getpw, "compat") + { 0 } + }; + static const ns_src defaultnis[] = { + { NSSRC_NIS, NS_SUCCESS }, + { 0 } + }; + + switch (type) { + case _PW_KEYBYNUM: + return nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "getpwcompat", + defaultnis, type); + case _PW_KEYBYNAME: + return nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "getpwcompat", + defaultnis, type, name); + case _PW_KEYBYUID: + return nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "getpwcompat", + defaultnis, type, uid); + default: + abort(); + /*NOTREACHED*/ + } } +#endif /* _PASSWD_COMPAT */ + +/* + * compat implementation of getpwent() + * varargs (ignored): + * type, [ uid (type == _PW_KEYBYUID) | name (type == _PW_KEYBYNAME) ] + */ +static int _compat_getpwent __P((void *, void *, va_list)); +/*ARGSUSED*/ static int -_pw_breakout_yp(struct passwd *pw, char *res, int resultlen, int master) +_compat_getpwent(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; { - char *s, *result; - static char resbuf[YPMAXRECORD+2]; + DBT key; + int rval; + char bf[sizeof(_pw_keynum) + 1]; +#ifdef _PASSWD_COMPAT + static char *name = NULL; + char *user, *host, *dom; + int has_compatpw; +#endif - /* - * Be triple, ultra super-duper paranoid: reject entries - * that start with a + or -. yp_mkdb and /var/yp/Makefile - * are _both_ supposed to strip these out, but you never - * know. - */ - if (*res == '+' || *res == '-') - return 0; + if (!_pw_db && !__initdb()) + return NS_UNAVAIL; - /* - * The NIS protocol definition limits the size of an NIS - * record to YPMAXRECORD bytes. We need to do a copy to - * a static buffer here since the memory pointed to by - * res will be free()ed when this function returns. - */ - strncpy((char *)&resbuf, res, resultlen); - resbuf[resultlen] = '\0'; - result = (char *)&resbuf; +#ifdef _PASSWD_COMPAT + has_compatpw = __has_compatpw(); - /* - * XXX Sanity check: make sure all fields are valid (no NULLs). - * If we find a badly formatted entry, we punt. - */ - if ((s = strsep(&result, ":")) == NULL) return 0; /* name */ - /* - * We don't care what pw_fields says: we _always_ want the - * username returned to us by NIS. - */ - pw->pw_name = s; - pw->pw_fields |= _PWF_NAME; - - if ((s = strsep(&result, ":")) == NULL) return 0; /* password */ - if(!(pw->pw_fields & _PWF_PASSWD)) { - /* SunOS passwd.adjunct hack */ - if (master == YP_HAVE_ADJUNCT && strstr(s, "##") != NULL) { - char *realpw; - realpw = _get_adjunct_pw(pw->pw_name); - if (realpw == NULL) - pw->pw_passwd = s; - else - pw->pw_passwd = realpw; - } else { - pw->pw_passwd = s; +again: + if (has_compatpw && (__pwmode != PWMODE_NONE)) { + int r; + + switch (__pwmode) { + case PWMODE_FULL: + r = __getpwcompat(_PW_KEYBYNUM, 0, NULL); + if (r == NS_SUCCESS) + return r; + __pwmode = PWMODE_NONE; + break; + + case PWMODE_NETGRP: + r = getnetgrent(&host, &user, &dom); + if (r == 0) { /* end of group */ + endnetgrent(); + __pwmode = PWMODE_NONE; + break; + } + if (!user || !*user) + break; + r = __getpwcompat(_PW_KEYBYNAME, 0, user); + if (r == NS_SUCCESS) + return r; + break; + + case PWMODE_USER: + if (name == NULL) { + __pwmode = PWMODE_NONE; + break; + } + r = __getpwcompat(_PW_KEYBYNAME, 0, name); + free(name); + name = NULL; + if (r == NS_SUCCESS) + return r; + break; + + case PWMODE_NONE: + abort(); } - pw->pw_fields |= _PWF_PASSWD; + goto again; } +#endif - if ((s = strsep(&result, ":")) == NULL) return 0; /* uid */ - if(!(pw->pw_fields & _PWF_UID)) { - pw->pw_uid = atoi(s); - pw->pw_fields |= _PWF_UID; - } + if (_pw_keynum == -1) + return NS_NOTFOUND; /* no more local records */ + ++_pw_keynum; + bf[0] = _PW_KEYBYNUM; + memmove(bf + 1, &_pw_keynum, sizeof(_pw_keynum)); + key.data = (u_char *)bf; + key.size = sizeof(_pw_keynum) + 1; + rval = __hashpw(&key); + if (rval == NS_NOTFOUND) + _pw_keynum = -1; /* flag `no more local records' */ + else if (rval == NS_SUCCESS) { +#ifdef _PASSWD_COMPAT + /* if we don't have YP at all, don't bother. */ + if (has_compatpw) { + if(_pw_passwd.pw_name[0] == '+') { + /* set the mode */ + switch(_pw_passwd.pw_name[1]) { + case '\0': + __pwmode = PWMODE_FULL; + break; + case '@': + __pwmode = PWMODE_NETGRP; + setnetgrent(_pw_passwd.pw_name + 2); + break; + default: + __pwmode = PWMODE_USER; + name = strdup(_pw_passwd.pw_name + 1); + break; + } - if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */ - if(!(pw->pw_fields & _PWF_GID)) { - pw->pw_gid = atoi(s); - pw->pw_fields |= _PWF_GID; + /* save the prototype */ + __pwproto_set(); + goto again; + } else if(_pw_passwd.pw_name[0] == '-') { + /* an attempted exclusion */ + switch(_pw_passwd.pw_name[1]) { + case '\0': + break; + case '@': + setnetgrent(_pw_passwd.pw_name + 2); + while(getnetgrent(&host, &user, &dom)) { + if(user && *user) + __pwexclude_add(user); + } + endnetgrent(); + break; + default: + __pwexclude_add(_pw_passwd.pw_name + 1); + break; + } + goto again; + } + } +#endif } + return (rval); +} - if (master == YP_HAVE_MASTER) { - if ((s = strsep(&result, ":")) == NULL) return 0; /* class */ - if(!(pw->pw_fields & _PWF_CLASS)) { - pw->pw_class = s; - pw->pw_fields |= _PWF_CLASS; - } +/* + * compat implementation of getpwnam() and getpwuid() + * varargs: type, [ uid (type == _PW_KEYBYUID) | name (type == _PW_KEYBYNAME) ] + */ +static int _compat_getpw __P((void *, void *, va_list)); - if ((s = strsep(&result, ":")) == NULL) return 0; /* change */ - if(!(pw->pw_fields & _PWF_CHANGE)) { - pw->pw_change = atol(s); - pw->pw_fields |= _PWF_CHANGE; - } +static int +_compat_getpw(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; +{ +#ifdef _PASSWD_COMPAT + DBT key; + int search, rval, r, s, keynum; + uid_t uid; + char bf[sizeof(keynum) + 1]; + char *name, *host, *user, *dom; +#endif - if ((s = strsep(&result, ":")) == NULL) return 0; /* expire */ - if(!(pw->pw_fields & _PWF_EXPIRE)) { - pw->pw_expire = atol(s); - pw->pw_fields |= _PWF_EXPIRE; - } - } + if (!_pw_db && !__initdb()) + return NS_UNAVAIL; - if ((s = strsep(&result, ":")) == NULL) return 0; /* gecos */ - if(!(pw->pw_fields & _PWF_GECOS)) { - pw->pw_gecos = s; - pw->pw_fields |= _PWF_GECOS; + /* + * If there isn't a compat token in the database, use files. + */ +#ifdef _PASSWD_COMPAT + if (! __has_compatpw()) +#endif + return (_local_getpw(rv, cb_data, ap)); + +#ifdef _PASSWD_COMPAT + search = va_arg(ap, int); + uid = 0; + name = NULL; + rval = NS_NOTFOUND; + switch (search) { + case _PW_KEYBYNAME: + name = va_arg(ap, char *); + break; + case _PW_KEYBYUID: + uid = va_arg(ap, uid_t); + break; + default: + abort(); } - if ((s = strsep(&result, ":")) == NULL) return 0; /* dir */ - if(!(pw->pw_fields & _PWF_DIR)) { - pw->pw_dir = s; - pw->pw_fields |= _PWF_DIR; + for (s = -1, keynum = 1 ; ; keynum++) { + bf[0] = _PW_KEYBYNUM; + memmove(bf + 1, &keynum, sizeof(keynum)); + key.data = (u_char *)bf; + key.size = sizeof(keynum) + 1; + if(__hashpw(&key) != NS_SUCCESS) + break; + switch(_pw_passwd.pw_name[0]) { + case '+': + /* save the prototype */ + __pwproto_set(); + + switch(_pw_passwd.pw_name[1]) { + case '\0': + r = __getpwcompat(search, uid, name); + if (r != NS_SUCCESS) + continue; + break; + case '@': +pwnam_netgrp: +#if 0 /* XXX: is this a hangover from pre-nsswitch? */ + if(__ypcurrent) { + free(__ypcurrent); + __ypcurrent = NULL; + } +#endif + if (s == -1) /* first time */ + setnetgrent(_pw_passwd.pw_name + 2); + s = getnetgrent(&host, &user, &dom); + if (s == 0) { /* end of group */ + endnetgrent(); + s = -1; + continue; + } + if (!user || !*user) + goto pwnam_netgrp; + + r = __getpwcompat(_PW_KEYBYNAME, 0, user); + + if (r == NS_UNAVAIL) + return r; + if (r == NS_NOTFOUND) { + /* + * just because this user is bad + * it doesn't mean they all are. + */ + goto pwnam_netgrp; + } + break; + default: + user = _pw_passwd.pw_name + 1; + r = __getpwcompat(_PW_KEYBYNAME, 0, user); + + if (r == NS_UNAVAIL) + return r; + if (r == NS_NOTFOUND) + continue; + break; + } + if(__pwexclude_is(_pw_passwd.pw_name)) { + if(s == 1) /* inside netgroup */ + goto pwnam_netgrp; + continue; + } + break; + case '-': + /* attempted exclusion */ + switch(_pw_passwd.pw_name[1]) { + case '\0': + break; + case '@': + setnetgrent(_pw_passwd.pw_name + 2); + while(getnetgrent(&host, &user, &dom)) { + if(user && *user) + __pwexclude_add(user); + } + endnetgrent(); + break; + default: + __pwexclude_add(_pw_passwd.pw_name + 1); + break; + } + break; + } + if ((search == _PW_KEYBYNAME && + strcmp(_pw_passwd.pw_name, name) == 0) + || (search == _PW_KEYBYUID && _pw_passwd.pw_uid == uid)) { + rval = NS_SUCCESS; + break; + } + if(s == 1) /* inside netgroup */ + goto pwnam_netgrp; + continue; } + __pwproto = (struct passwd *)NULL; - if ((s = strsep(&result, ":")) == NULL) return 0; /* shell */ - if(!(pw->pw_fields & _PWF_SHELL)) { - pw->pw_shell = s; - pw->pw_fields |= _PWF_SHELL; + if (!_pw_stayopen) { + (void)(_pw_db->close)(_pw_db); + _pw_db = (DB *)NULL; } - - /* Be consistent. */ - if ((s = strchr(pw->pw_shell, '\n'))) *s = '\0'; - - return 1; + if(__pwexclude != (DB *)NULL) { + (void)(__pwexclude->close)(__pwexclude); + __pwexclude = (DB *)NULL; + } + return rval; +#endif /* _PASSWD_COMPAT */ } -static int -_havemaster(char *_yp_domain) +struct passwd * +getpwent() { - int order; - int rval; + int r; + static const ns_dtab dtab[] = { + NS_FILES_CB(_local_getpw, NULL) + NS_DNS_CB(_dns_getpw, NULL) + NS_NIS_CB(_nis_getpw, NULL) + NS_COMPAT_CB(_compat_getpwent, NULL) + { 0 } + }; + + r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwent", compatsrc, + _PW_KEYBYNUM); + if (r != NS_SUCCESS) + return (struct passwd *)NULL; + return &_pw_passwd; +} - if (!(rval = yp_order(_yp_domain, "master.passwd.byname", &order))) - return(YP_HAVE_MASTER); +struct passwd * +getpwnam(name) + const char *name; +{ + int r; + static const ns_dtab dtab[] = { + NS_FILES_CB(_local_getpw, NULL) + NS_DNS_CB(_dns_getpw, NULL) + NS_NIS_CB(_nis_getpw, NULL) + NS_COMPAT_CB(_compat_getpw, NULL) + { 0 } + }; + + if (name == NULL || name[0] == '\0') + return (struct passwd *)NULL; + + r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwnam", compatsrc, + _PW_KEYBYNAME, name); + return (r == NS_SUCCESS ? &_pw_passwd : (struct passwd *)NULL); +} - /* - * NIS+ in YP compat mode doesn't support - * YPPROC_ORDER -- no point in continuing. - */ - if (rval == YPERR_YPERR) - return(YP_HAVE_NONE); +struct passwd * +getpwuid(uid) + uid_t uid; +{ + int r; + static const ns_dtab dtab[] = { + NS_FILES_CB(_local_getpw, NULL) + NS_DNS_CB(_dns_getpw, NULL) + NS_NIS_CB(_nis_getpw, NULL) + NS_COMPAT_CB(_compat_getpw, NULL) + { 0 } + }; + + r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwuid", compatsrc, + _PW_KEYBYUID, uid); + return (r == NS_SUCCESS ? &_pw_passwd : (struct passwd *)NULL); +} - /* master.passwd doesn't exist -- try passwd.adjunct */ - if (rval == YPERR_MAP) { - rval = yp_order(_yp_domain, "passwd.adjunct.byname", &order); - if (!rval) - return(YP_HAVE_ADJUNCT); +int +setpassent(stayopen) + int stayopen; +{ + _pw_keynum = 0; + _pw_stayopen = stayopen; +#ifdef YP + __pwmode = PWMODE_NONE; + if(__ypcurrent) + free(__ypcurrent); + __ypcurrent = NULL; + _pw_ypdone = 0; +#endif +#ifdef HESIOD + _pw_hesnum = 0; +#endif +#ifdef _PASSWD_COMPAT + if(__pwexclude != (DB *)NULL) { + (void)(__pwexclude->close)(__pwexclude); + __pwexclude = (DB *)NULL; } + __pwproto = (struct passwd *)NULL; +#endif + return 1; +} - return (YP_HAVE_NONE); +void +setpwent() +{ + (void) setpassent(0); } -static int -_getyppass(struct passwd *pw, const char *name, const char *map) +void +endpwent() { - char *result, *s; - int resultlen; - int rv; - char mastermap[YPMAXRECORD]; - - if(!_pw_yp_domain) { - if(yp_get_default_domain(&_pw_yp_domain)) - return 0; + _pw_keynum = 0; + if (_pw_db) { + (void)(_pw_db->close)(_pw_db); + _pw_db = (DB *)NULL; } - - if (_gotmaster == YP_HAVE_MASTER) - snprintf(mastermap, sizeof(mastermap), "master.%s", map); - else - snprintf(mastermap, sizeof(mastermap), "%s", map); - - if(yp_match(_pw_yp_domain, (char *)&mastermap, name, strlen(name), - &result, &resultlen)) { - if (_gotmaster != YP_HAVE_MASTER) - return 0; - snprintf(mastermap, sizeof(mastermap), "%s", map); - if (yp_match(_pw_yp_domain, (char *)&mastermap, - name, strlen(name), &result, &resultlen)) - return 0; - _gotmaster = YP_HAVE_NONE; +#ifdef _PASSWD_COMPAT + __pwmode = PWMODE_NONE; +#endif +#ifdef YP + if(__ypcurrent) + free(__ypcurrent); + __ypcurrent = NULL; + _pw_ypdone = 0; +#endif +#ifdef HESIOD + _pw_hesnum = 0; +#endif +#ifdef _PASSWD_COMPAT + if(__pwexclude != (DB *)NULL) { + (void)(__pwexclude->close)(__pwexclude); + __pwexclude = (DB *)NULL; } + __pwproto = (struct passwd *)NULL; +#endif +} - if (!_pw_stepping_yp) { - s = strchr(result, ':'); - if (s) { - *s = '\0'; - } else { - /* Must be a malformed entry if no colons. */ - free(result); - return(0); - } - - if (!verf(result)) { - *s = ':'; - free(result); - return(0); - } +static int +__initdb() +{ + static int warned; + char *p; - *s = ':'; /* Put back the colon we previously replaced with a NUL. */ +#ifdef _PASSWD_COMPAT + __pwmode = PWMODE_NONE; +#endif + if (geteuid() == 0) { + _pw_db = dbopen((p = _PATH_SMP_DB), O_RDONLY, 0, DB_HASH, NULL); + if (_pw_db) + return(1); } - - rv = _pw_breakout_yp(pw, result, resultlen, _gotmaster); - free(result); - return(rv); + _pw_db = dbopen((p = _PATH_MP_DB), O_RDONLY, 0, DB_HASH, NULL); + if (_pw_db) + return 1; + if (!warned) + syslog(LOG_ERR, "%s: %m", p); + warned = 1; + return 0; } static int -_nextyppass(struct passwd *pw) +__hashpw(key) + DBT *key; { - static char *key; - static int keylen; - char *lastkey, *result, *s; - int resultlen; - int rv; - char *map = "passwd.byname"; - - if(!_pw_yp_domain) { - if(yp_get_default_domain(&_pw_yp_domain)) - return 0; - } - - if (_gotmaster == YP_HAVE_MASTER) - map = "master.passwd.byname"; + char *p, *t; + static u_int max; + static char *buf; + DBT data; - if(!_pw_stepping_yp) { - if(key) free(key); - rv = yp_first(_pw_yp_domain, map, - &key, &keylen, &result, &resultlen); - if(rv) { - return 0; - } - _pw_stepping_yp = 1; - goto unpack; - } else { -tryagain: - lastkey = key; - rv = yp_next(_pw_yp_domain, map, key, keylen, - &key, &keylen, &result, &resultlen); - free(lastkey); -unpack: - if(rv) { - _pw_stepping_yp = 0; - return 0; - } + switch ((_pw_db->get)(_pw_db, key, &data, 0)) { + case 0: + break; /* found */ + case 1: + return NS_NOTFOUND; + case -1: + return NS_UNAVAIL; /* error in db routines */ + default: + abort(); + } - s = strchr(result, ':'); - if (s) { - *s = '\0'; - } else { - /* Must be a malformed entry if no colons. */ - free(result); - goto tryagain; - } + p = (char *)data.data; + if (data.size > max && !(buf = realloc(buf, (max += 1024)))) + return NS_UNAVAIL; - if (lookup(result)) { - *s = ':'; - free(result); - goto tryagain; - } + /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ + t = buf; +#define EXPAND(e) e = t; while ((*t++ = *p++)); +#define SCALAR(v) memmove(&(v), p, sizeof v); p += sizeof v + EXPAND(_pw_passwd.pw_name); + EXPAND(_pw_passwd.pw_passwd); + SCALAR(_pw_passwd.pw_uid); + SCALAR(_pw_passwd.pw_gid); + SCALAR(_pw_passwd.pw_change); + EXPAND(_pw_passwd.pw_class); + EXPAND(_pw_passwd.pw_gecos); + EXPAND(_pw_passwd.pw_dir); + EXPAND(_pw_passwd.pw_shell); + SCALAR(_pw_passwd.pw_expire); + SCALAR(_pw_passwd.pw_fields); - *s = ':'; /* Put back the colon we previously replaced with a NUL. */ - if (_pw_breakout_yp(pw, result, resultlen, _gotmaster)) { - free(result); - return(1); - } else { - free(result); - goto tryagain; - } - } + return NS_SUCCESS; } - -#endif /* YP */ |