summaryrefslogtreecommitdiffstats
path: root/lib/libc/gen/getpwent.c
diff options
context:
space:
mode:
authornectar <nectar@FreeBSD.org>2000-09-06 18:16:48 +0000
committernectar <nectar@FreeBSD.org>2000-09-06 18:16:48 +0000
commit748554442d0ac4467fdac2ce9d42006588fd4481 (patch)
treeaed2ddbcac97f46f60ee9c2063a3345553f6a1ee /lib/libc/gen/getpwent.c
parent59ffb36b778f8e629622726f6bd32dfa4fda7e35 (diff)
downloadFreeBSD-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.c1665
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 */
OpenPOWER on IntegriCloud