summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libc/gen/getnetgrent.c201
-rw-r--r--lib/libc/net/ether_addr.c31
-rw-r--r--lib/libc/net/rcmd.c20
-rw-r--r--sbin/mountd/netgroup.569
-rw-r--r--usr.sbin/mountd/netgroup.569
5 files changed, 350 insertions, 40 deletions
diff --git a/lib/libc/gen/getnetgrent.c b/lib/libc/gen/getnetgrent.c
index 658cf63..b26af50 100644
--- a/lib/libc/gen/getnetgrent.c
+++ b/lib/libc/gen/getnetgrent.c
@@ -44,13 +44,60 @@ static char sccsid[] = "@(#)getnetgrent.c 8.1 (Berkeley) 6/4/93";
#include <unistd.h>
#ifdef YP
+/*
+ * Notes:
+ * We want to be able to use NIS netgroups properly while retaining
+ * the ability to use a local /etc/netgroup file. Unfortunately, you
+ * can't really do both at the same time - at least, not efficiently.
+ * NetBSD deals with this problem by creating a netgroup database
+ * using Berkeley DB (just like the password database) that allows
+ * for lookups using netgroup, netgroup.byuser or netgroup.byhost
+ * searches. This is a neat idea, but I don't have time to implement
+ * something like that now. (I think ultimately it would be nice
+ * if we DB-fied the group and netgroup stuff all in one shot, but
+ * for now I'm satisfied just to have something that works well
+ * without requiring massive code changes.)
+ *
+ * Therefore, to still permit the use of the local file and maintain
+ * optimum NIS performance, we allow for the following conditions:
+ *
+ * - If /etc/netgroup does not exist and NIS is turned on, we use
+ * NIS netgroups only.
+ *
+ * - If /etc/netgroup exists but is empty, we use NIS netgroups
+ * only.
+ *
+ * - If /etc/netgroup exists and contains _only_ a '+', we use
+ * NIS netgroups only.
+ *
+ * - If /etc/netgroup exists, contains locally defined netgroups
+ * and a '+', we use a mixture of NIS and the local entries.
+ * This method should return the same NIS data as just using
+ * NIS alone, but it will be slower if the NIS netgroup database
+ * is large (innetgr() in particular will suffer since extra
+ * processing has to be done in order to determine memberships
+ * using just the raw netgroup data).
+ *
+ * - If /etc/netgroup exists and contains only locally defined
+ * netgroup entries, we use just those local entries and ignore
+ * NIS (this is the original, pre-NIS behavior).
+ */
#include <rpc/rpc.h>
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+static char *_netgr_yp_domain;
+static int _use_only_yp;
static int _netgr_yp_enabled;
+static int _yp_innetgr;
#endif
+#ifndef _PATH_NETGROUP
#define _PATH_NETGROUP "/etc/netgroup"
+#endif
/*
* Static Variables and functions used by setnetgrent(), getnetgrent() and
@@ -102,6 +149,11 @@ void
setnetgrent(group)
char *group;
{
+#ifdef YP
+ struct stat _yp_statp;
+ char _yp_plus;
+#endif
+
/* Sanity check */
if (group == NULL || !strlen(group))
@@ -110,7 +162,36 @@ setnetgrent(group)
if (grouphead.gr == (struct netgrp *)0 ||
strcmp(group, grouphead.grname)) {
endnetgrent();
+#ifdef YP
+ /*
+ * IF /etc/netgroup doesn't exist or is empty,
+ * use NIS exclusively.
+ */
+ if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) &&
+ errno == ENOENT) || _yp_statp.st_size == 0)
+ _use_only_yp = _netgr_yp_enabled = 1;
+ if ((netf = fopen(_PATH_NETGROUP,"r")) != NULL ||_use_only_yp){
+ /*
+ * Icky: grab the first character of the netgroup file
+ * and turn on NIS if it's a '+'. rewind the stream
+ * afterwards so we don't goof up read_for_group() later.
+ */
+ if (netf) {
+ fscanf(netf, "%c", &_yp_plus);
+ rewind(netf);
+ if (_yp_plus == '+')
+ _use_only_yp = _netgr_yp_enabled = 1;
+ }
+ /*
+ * If we were called specifically for an innetgr()
+ * lookup and we're in NIS-only mode, short-circuit
+ * parse_netgroup() and cut directly to the chase.
+ */
+ if (_use_only_yp && _yp_innetgr)
+ return;
+#else
if (netf = fopen(_PATH_NETGROUP, "r")) {
+#endif
if (parse_netgrp(group))
endnetgrent();
else {
@@ -118,7 +199,8 @@ setnetgrent(group)
malloc(strlen(group) + 1);
strcpy(grouphead.grname, group);
}
- fclose(netf);
+ if (netf)
+ fclose(netf);
}
}
nextgrp = grouphead.gr;
@@ -131,6 +213,9 @@ int
getnetgrent(hostp, userp, domp)
char **hostp, **userp, **domp;
{
+#ifdef YP
+ _yp_innetgr = 0;
+#endif
if (nextgrp) {
*hostp = nextgrp->ng_str[NG_HOST];
@@ -182,6 +267,43 @@ endnetgrent()
#endif
}
+#ifdef YP
+static int _listmatch(list, group)
+char *list, *group;
+{
+ char *ptr = list;
+
+ while (ptr != NULL) {
+ if (!strncmp(ptr, group, strlen(group)) &&
+ (*(ptr+strlen(group)) == ',' ||
+ *(ptr+strlen(group)) == '\n'))
+ return(1);
+ ptr++;
+ }
+ return(0);
+}
+
+static int _buildkey(key, str, dom, rotation)
+char *key, *str, *dom;
+int *rotation;
+{
+ (*rotation)++;
+ if (*rotation > 4)
+ return(0);
+ switch(*rotation) {
+ case(1): sprintf((char *)key, "%s.%s", str, dom ? dom : "*");
+ break;
+ case(2): sprintf((char *)key, "%s.*", str);
+ break;
+ case(3): sprintf((char *)key, "*.%s", dom ? dom : "*");
+ break;
+ case(4): sprintf((char *)key, "*.*");
+ break;
+ }
+ return(1);
+}
+#endif
+
/*
* Search for a match in a netgroup.
*/
@@ -190,17 +312,60 @@ innetgr(group, host, user, dom)
char *group, *host, *user, *dom;
{
char *hst, *usr, *dm;
-
+#ifdef YP
+ char *result;
+ int resultlen;
+#endif
/* Sanity check */
if (group == NULL || !strlen(group))
return (0);
+#ifdef YP
+ _yp_innetgr = 1;
+#endif
+ setnetgrent(group);
+#ifdef YP
+ /*
+ * If we're in NIS-only mode, do the search using
+ * NIS 'reverse netgroup' lookups.
+ */
+ if (_use_only_yp) {
+ char _key[MAXHOSTNAMELEN];
+ int rot = 0;
+
+ if(yp_get_default_domain(&_netgr_yp_domain))
+ return(0);
+ while(_buildkey(&_key, user ? user : host, dom, &rot)) {
+ if (yp_match(_netgr_yp_domain, user? "netgroup.byuser":
+ "netgroup.byhost", _key, strlen(_key), &result,
+ &resultlen))
+ free(result);
+ else {
+ if (_listmatch(result, group)) {
+ free(result);
+ return(1);
+ }
+ }
+ }
+ free(result);
+#ifdef CHARITABLE
+ }
+ /*
+ * Couldn't match using NIS-exclusive mode -- try
+ * standard mode.
+ */
+ _yp_innetgr = 0;
setnetgrent(group);
+#else
+ return(0);
+ }
+#endif /* CHARITABLE */
+#endif /* YP */
while (getnetgrent(&hst, &usr, &dm))
- if ((host == (char *)0 || !strcmp(host, hst)) &&
- (user == (char *)0 || !strcmp(user, usr)) &&
- (dom == (char *)0 || !strcmp(dom, dm))) {
+ if ((host == NULL || hst == NULL || !strcmp(host, hst)) &&
+ (user == NULL || usr == NULL || !strcmp(user, usr)) &&
+ ( dom == NULL || dm == NULL || !strcmp(dom, dm))) {
endnetgrent();
return (1);
}
@@ -262,13 +427,13 @@ parse_netgrp(group)
fields = 0;
#endif
for (strpos = 0; strpos < 3; strpos++) {
- if (spos = strsep(&gpos, ",")) {
+ if ((spos = strsep(&gpos, ","))) {
#ifdef DEBUG
fields++;
#endif
while (*spos == ' ' || *spos == '\t')
spos++;
- if (epos = strpbrk(spos, " \t")) {
+ if ((epos = strpbrk(spos, " \t"))) {
*epos = '\0';
len = epos - spos;
} else
@@ -332,7 +497,6 @@ read_for_group(group)
struct linelist *lp;
char line[LINSIZ + 1];
#ifdef YP
- static char *_netgr_yp_domain;
char *result;
int resultlen;
@@ -344,7 +508,12 @@ read_for_group(group)
if (yp_match(_netgr_yp_domain, "netgroup", group,
strlen(group), &result, &resultlen)) {
free(result);
- return ((struct linelist *)0);
+ if (_use_only_yp)
+ return ((struct linelist *)0);
+ else {
+ _netgr_yp_enabled = 0;
+ continue;
+ }
}
sprintf(line, "%s %s", group, result);
free(result);
@@ -354,10 +523,6 @@ read_for_group(group)
#endif
pos = (char *)&line;
#ifdef YP
- /*
- * Once we default over to NIS, only
- * endnetgrent() can get us out again.
- */
if (*pos == '+') {
_netgr_yp_enabled = 1;
continue;
@@ -424,5 +589,15 @@ read_for_group(group)
return (lp);
}
}
+#ifdef YP
+ /*
+ * Yucky. The recursive nature of this whole mess might require
+ * us to make more than one pass through the netgroup file.
+ * This might be best left outside the #ifdef YP, but YP is
+ * defined by default anyway, so I'll leave it like this
+ * until I know better.
+ */
+ rewind(netf);
+#endif
return ((struct linelist *)0);
}
diff --git a/lib/libc/net/ether_addr.c b/lib/libc/net/ether_addr.c
index c628826..711bb7d 100644
--- a/lib/libc/net/ether_addr.c
+++ b/lib/libc/net/ether_addr.c
@@ -35,7 +35,7 @@
* Center for Telecommunications Research
* Columbia University, New York City
*
- * $Id: ether_addr.c,v 1.5 1995/03/26 02:37:00 wpaul Exp $
+ * $Id: ether_addr.c,v 1.1 1995/04/02 01:31:17 wpaul Exp $
*/
@@ -142,23 +142,16 @@ int ether_ntohost(hostname, e)
continue;
#ifdef YP
if (buf[0] == '+') {
- fclose(fp); /* Can ignore /etc/ethers from here on. */
if (yp_get_default_domain(&yp_domain))
- return(1);
+ continue;
ether_a = ether_ntoa(e);
if (yp_match(yp_domain, "ethers.byaddr", ether_a,
strlen(ether_a), &result, &resultlen)) {
free(result);
- return(1);
+ continue;
}
- if (!ether_line(result, &local_ether, &local_host)) {
- strcpy(hostname, (char *)&local_host);
- free(result);
- return(0);
- } else {
+ strncpy((char *)&buf, result, resultlen);
free(result);
- return(1);
- }
}
#endif
if (!ether_line(&buf, &local_ether, &local_host)) {
@@ -200,23 +193,15 @@ int ether_hostton(hostname, e)
continue;
#ifdef YP
if (buf[0] == '+') {
- fclose(fp); /* Can ignore /etc/ethers from here on. */
if (yp_get_default_domain(&yp_domain))
- return(1);
+ continue;
if (yp_match(yp_domain, "ethers.byname", hostname,
strlen(hostname), &result, &resultlen)) {
free(result);
- return(1);
- }
- if (!ether_line(result, &local_ether, &local_host)) {
- bcopy((char *)&local_ether.octet[0],
- (char *)&e->octet[0], 6);
- free(result);
- return(0);
- } else {
- free(result);
- return(1);
+ continue;
}
+ strncpy((char *)&buf, result, resultlen);
+ free(result);
}
#endif
if (!ether_line(&buf, &local_ether, &local_host)) {
diff --git a/lib/libc/net/rcmd.c b/lib/libc/net/rcmd.c
index 34ac18b..f0d756c 100644
--- a/lib/libc/net/rcmd.c
+++ b/lib/libc/net/rcmd.c
@@ -51,6 +51,11 @@ static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
#include <stdio.h>
#include <ctype.h>
#include <string.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
#define max(a, b) ((a > b) ? a : b)
@@ -359,7 +364,14 @@ __ivaliduser(hostf, raddr, luser, ruser)
struct hostent *hp;
/* Presumed guilty until proven innocent. */
int userok = 0, hostok = 0;
+#ifdef YP
+ char *ypdomain;
+ if (yp_get_default_domain(&ypdomain))
+ ypdomain = NULL;
+#else
+#define ypdomain NULL
+#endif
/* We need to get the damn hostname back for netgroup matching. */
if ((hp = gethostbyaddr((char *)&raddr, sizeof(u_long),
AF_INET)) == NULL)
@@ -403,14 +415,14 @@ __ivaliduser(hostf, raddr, luser, ruser)
}
if (buf[1] == '@') /* match a host by netgroup */
hostok = innetgr((char *)&buf[2], hp->h_name,
- NULL, NULL);
+ NULL, ypdomain);
else /* match a host by addr */
hostok = __icheckhost(raddr,(char *)&buf[1]);
break;
case '-': /* reject '-' hosts and all their users */
if (buf[1] == '@') {
if (innetgr((char *)&buf[2],
- hp->h_name, NULL, NULL))
+ hp->h_name, NULL, ypdomain))
return(-1);
} else {
if (__icheckhost(raddr,(char *)&buf[1]))
@@ -428,7 +440,7 @@ __ivaliduser(hostf, raddr, luser, ruser)
break;
}
if (*(user+1) == '@') /* match a user by netgroup */
- userok = innetgr(user+2, NULL, ruser, NULL);
+ userok = innetgr(user+2, NULL, ruser, ypdomain);
else /* match a user by direct specification */
userok = !(strcmp(ruser, user+1));
break;
@@ -438,7 +450,7 @@ __ivaliduser(hostf, raddr, luser, ruser)
return(-1);
if (*(user+1) == '@') {
if (innetgr(user+2, NULL,
- ruser, NULL))
+ ruser, ypdomain))
return(-1);
} else {
if (!strcmp(ruser, user+1))
diff --git a/sbin/mountd/netgroup.5 b/sbin/mountd/netgroup.5
index 9ad8c48..711e04f 100644
--- a/sbin/mountd/netgroup.5
+++ b/sbin/mountd/netgroup.5
@@ -73,6 +73,66 @@ should normally be used to access the
database.
.Pp
Lines that begin with a # are treated as comments.
+.Sh NIS/YP INTERACTION
+On most other platforms,
+.Nm netgroups
+are only used in conjunction with
+NIS and local
+.Pa /etc/netgroup
+files are ignored. With FreeBSD,
+.Nm netgroups
+can be used with either NIS or local files, but there are certain
+caveats to consider. The existing
+.Nm netgroup
+system is extremely inefficient where
+.Fn innetgr 3
+lookups are concerned since
+.Nm netgroup
+memberships are computed on the fly. By contrast, the NIS
+.Nm netgroup
+database consists of three seperate maps (netgroup, netgroup.byuser
+and netgroup.byhost) that are keyed to allow
+.Fn innetgr 3
+lookups to be done quickly. The FreeBSD
+.Nm netgroup
+system can interact with the NIS
+.Nm netgroup
+maps in the following ways:
+.Bl -bullet -offset indent
+.It
+If the
+.Pa /etc/netgroup
+file does not exist, or it exists and is empty, or
+it exists and contains only a '+', and NIS is running,
+.Nm netgroup
+lookups will be done exclusively through NIS, with
+.Fn innetgr 3
+taking advantage of the netgroup.byuser and
+netgroup.byhost maps to speed up searches. (This
+is more or less compatible with the behavior of SunOS and
+similar platforms.)
+.It
+If the
+.Pa /etc/netgroup
+exists and contains only local
+.Nm netgroup
+information (with no NIS '+' token), then only the local
+.Nm netgroup
+information will be processed (and NIS will be ingored).
+.It
+If
+.Pa /etc/netgroup
+exists and contains both local netgroup data
+.Pa and
+the NIS '+' token, the local data and the NIS netgroup
+map will be processed as a single combined
+.Nm netgroup
+database. While this configuration is the most flexible, it
+is also the least efficient: in particular,
+.Fn innetgr 3
+lookups will be especially slow if the
+database is large.
+.El
.Sh FILES
.Bl -tag -width /etc/netgroup -compact
.It Pa /etc/netgroup
@@ -89,3 +149,12 @@ The interpretation of access restrictions based on the member tuples of a
netgroup is left up to the various network applications.
Also, it is not obvious how the domain specification
applies to the BSD environment.
+.Pp
+The
+.Nm netgroup
+database should be stored in the form of a
+hashed
+.Xr db 3
+database just like the
+.Xr passwd 5
+database to speed up reverse lookups.
diff --git a/usr.sbin/mountd/netgroup.5 b/usr.sbin/mountd/netgroup.5
index 9ad8c48..711e04f 100644
--- a/usr.sbin/mountd/netgroup.5
+++ b/usr.sbin/mountd/netgroup.5
@@ -73,6 +73,66 @@ should normally be used to access the
database.
.Pp
Lines that begin with a # are treated as comments.
+.Sh NIS/YP INTERACTION
+On most other platforms,
+.Nm netgroups
+are only used in conjunction with
+NIS and local
+.Pa /etc/netgroup
+files are ignored. With FreeBSD,
+.Nm netgroups
+can be used with either NIS or local files, but there are certain
+caveats to consider. The existing
+.Nm netgroup
+system is extremely inefficient where
+.Fn innetgr 3
+lookups are concerned since
+.Nm netgroup
+memberships are computed on the fly. By contrast, the NIS
+.Nm netgroup
+database consists of three seperate maps (netgroup, netgroup.byuser
+and netgroup.byhost) that are keyed to allow
+.Fn innetgr 3
+lookups to be done quickly. The FreeBSD
+.Nm netgroup
+system can interact with the NIS
+.Nm netgroup
+maps in the following ways:
+.Bl -bullet -offset indent
+.It
+If the
+.Pa /etc/netgroup
+file does not exist, or it exists and is empty, or
+it exists and contains only a '+', and NIS is running,
+.Nm netgroup
+lookups will be done exclusively through NIS, with
+.Fn innetgr 3
+taking advantage of the netgroup.byuser and
+netgroup.byhost maps to speed up searches. (This
+is more or less compatible with the behavior of SunOS and
+similar platforms.)
+.It
+If the
+.Pa /etc/netgroup
+exists and contains only local
+.Nm netgroup
+information (with no NIS '+' token), then only the local
+.Nm netgroup
+information will be processed (and NIS will be ingored).
+.It
+If
+.Pa /etc/netgroup
+exists and contains both local netgroup data
+.Pa and
+the NIS '+' token, the local data and the NIS netgroup
+map will be processed as a single combined
+.Nm netgroup
+database. While this configuration is the most flexible, it
+is also the least efficient: in particular,
+.Fn innetgr 3
+lookups will be especially slow if the
+database is large.
+.El
.Sh FILES
.Bl -tag -width /etc/netgroup -compact
.It Pa /etc/netgroup
@@ -89,3 +149,12 @@ The interpretation of access restrictions based on the member tuples of a
netgroup is left up to the various network applications.
Also, it is not obvious how the domain specification
applies to the BSD environment.
+.Pp
+The
+.Nm netgroup
+database should be stored in the form of a
+hashed
+.Xr db 3
+database just like the
+.Xr passwd 5
+database to speed up reverse lookups.
OpenPOWER on IntegriCloud