summaryrefslogtreecommitdiffstats
path: root/lib/libc/gen/getpwent.c
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>1996-12-03 17:55:49 +0000
committerwpaul <wpaul@FreeBSD.org>1996-12-03 17:55:49 +0000
commit1aa66460f8fa844a7fec1e9c9cf4bca3e5528b72 (patch)
tree6d4b9312da6bf1063cbb7f47b58bcbfc866aa3e5 /lib/libc/gen/getpwent.c
parent7cf00c59ae98be4882f9c07acc883c309b8f417d (diff)
downloadFreeBSD-src-1aa66460f8fa844a7fec1e9c9cf4bca3e5528b72.zip
FreeBSD-src-1aa66460f8fa844a7fec1e9c9cf4bca3e5528b72.tar.gz
Add support for detecting and hopefully using the passwd.adjunct.byname
NIS map which is present on SunOS NIS servers with the SunOS C2 security hack^Woption installed. I'm convinced that the C2 security option restricts access to the passwd.adjunct.byname map in the same way that I restrict access to the master.passwd.{byname,buid} maps (checking for reserved ports), which means that we should be able to handle passwd.adjunct.byname map correctly. If _havemaster() doesn't find a master.passwd.byname map, it will now test for a passwd.adjunct.byname map before defaulting back to the standard non-shadowed passwd.{byname,byuid} maps. If _pw_breakout_yp() sees that the adjunct map was found and the password from the standard maps starts with ##, it will try to grab the correct password field from the adjunct map. As with the master.passwd maps, this only happens if the caller is root, so the shadowing feature is preserved; non-root users just get back ##username as the encrypted password. Note that all we do is grab the second field from the passwd.adjunct.byname entry, which is designated to be the real encrypted password. There are other auditing fields in the entry but they aren't of much use to us. Also switched back to using yp_order() to probe for the maps (instead of yp_first()). The original problem with yp_order() was that it barfed with NIS+ servers in YP compat mode since they don't support the YPPROC_ORDER procedure. This condition is handled a bit more gracefully in yplib now: we can detect the error and just punt on the probing.
Diffstat (limited to 'lib/libc/gen/getpwent.c')
-rw-r--r--lib/libc/gen/getpwent.c78
1 files changed, 65 insertions, 13 deletions
diff --git a/lib/libc/gen/getpwent.c b/lib/libc/gen/getpwent.c
index 1831458..20f1d2c 100644
--- a/lib/libc/gen/getpwent.c
+++ b/lib/libc/gen/getpwent.c
@@ -69,6 +69,9 @@ static int _yp_exclusions = 0;
static int _yp_enabled; /* set true when yp enabled */
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 * ));
@@ -265,7 +268,7 @@ __initdb()
if (yp_get_default_domain(&_pw_yp_domain))
return(1);
_gotmaster = _havemaster(_pw_yp_domain);
- } else _gotmaster = 0;
+ } else _gotmaster = YP_HAVE_NONE;
if (!_ypcache)
_ypinitdb();
}
@@ -550,7 +553,34 @@ again:
}
return(0);
}
-
+
+static char * _get_adjunct_pw(name)
+ 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((char *)&adjunctbuf, result, YPMAXRECORD);
+ 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 */
+
+ return(s);
+}
+
static int
_pw_breakout_yp(struct passwd *pw, char *res, int master)
{
@@ -589,7 +619,17 @@ _pw_breakout_yp(struct passwd *pw, char *res, int master)
if ((s = strsep(&result, ":")) == NULL) return 0; /* password */
if(!(pw->pw_fields & _PWF_PASSWD)) {
- pw->pw_passwd = s;
+ /* SunOS passwd.adjunct hack */
+ if (master == YP_HAVE_ADJUNCT && !strstr(s, "##")) {
+ 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;
+ }
pw->pw_fields |= _PWF_PASSWD;
}
@@ -605,7 +645,7 @@ _pw_breakout_yp(struct passwd *pw, char *res, int master)
pw->pw_fields |= _PWF_GID;
}
- if (master) {
+ if (master == YP_HAVE_MASTER) {
if ((s = strsep(&result, ":")) == NULL) return 0; /* class */
if(!(pw->pw_fields & _PWF_CLASS)) {
pw->pw_class = s;
@@ -652,15 +692,27 @@ _pw_breakout_yp(struct passwd *pw, char *res, int master)
static int
_havemaster(char *_pw_yp_domain)
{
- int keylen, resultlen;
- char *key, *result;
+ int order;
+ int rval;
- if (yp_first(_pw_yp_domain, "master.passwd.byname",
- &key, &keylen, &result, &resultlen)) {
- return 0;
+ if (!(rval = yp_order(_pw_yp_domain, "master.passwd.byname", &order)))
+ return(YP_HAVE_MASTER);
+
+ /*
+ * NIS+ in YP compat mode doesn't support
+ * YPPROC_ORDER -- no point in continuing.
+ */
+ if (rval == YPERR_YPERR)
+ return(YP_HAVE_NONE);
+
+ /* master.passwd doesn't exist -- try passwd.adjunct */
+ if (rval == YPERR_MAP) {
+ rval = yp_order(_pw_yp_domain, "passwd.adjunct.byname", &order);
+ if (!rval)
+ return(YP_HAVE_ADJUNCT);
}
- free(result);
- return 1;
+
+ return (YP_HAVE_NONE);
}
static int
@@ -678,7 +730,7 @@ _getyppass(struct passwd *pw, const char *name, const char *map)
sprintf(mastermap,"%s",map);
- if (_gotmaster)
+ if (_gotmaster == YP_HAVE_MASTER)
sprintf(mastermap,"master.%s", map);
if(yp_match(_pw_yp_domain, (char *)&mastermap, name, strlen(name),
@@ -724,7 +776,7 @@ _nextyppass(struct passwd *pw)
return 0;
}
- if (_gotmaster)
+ if (_gotmaster == YP_HAVE_MASTER)
map = "master.passwd.byname";
if(!_pw_stepping_yp) {
OpenPOWER on IntegriCloud