diff options
author | Gordon Ross <gwr@nexenta.com> | 2021-06-21 19:28:20 +0200 |
---|---|---|
committer | Robert Mustacchi <rm@fingolfin.org> | 2021-07-06 11:42:09 -0700 |
commit | 74e12c43fe52f2c30f36e65a4d0fb0e8dfd7068a (patch) | |
tree | 12a16bf4b9b74058e5176dfa4f5a66ce7050f769 | |
parent | 1a065e93eee983124652c3eb0cfdcb4776cd89ab (diff) | |
download | illumos-joyent-74e12c43fe52f2c30f36e65a4d0fb0e8dfd7068a.tar.gz |
3163 nss: need local netgroup implementation
Portions contributed by: Marco van Wieringen <marco.van.wieringen@planets.elm.net>
Reviewed by: Andy Fiddaman <andy@omnios.org>
Reviewed by: Peter Tribble <peter.tribble@gmail.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Approved by: Robert Mustacchi <rm@fingolfin.org>
-rw-r--r-- | usr/src/cmd/getent/Makefile | 1 | ||||
-rw-r--r-- | usr/src/cmd/getent/dogetnetgr.c | 71 | ||||
-rw-r--r-- | usr/src/cmd/getent/getent.c | 5 | ||||
-rw-r--r-- | usr/src/cmd/getent/getent.h | 2 | ||||
-rw-r--r-- | usr/src/cmd/netfiles/nsswitch.ad | 2 | ||||
-rw-r--r-- | usr/src/cmd/netfiles/nsswitch.conf | 2 | ||||
-rw-r--r-- | usr/src/cmd/netfiles/nsswitch.dns | 5 | ||||
-rw-r--r-- | usr/src/cmd/netfiles/nsswitch.files | 3 | ||||
-rw-r--r-- | usr/src/cmd/netfiles/nsswitch.ldap | 3 | ||||
-rw-r--r-- | usr/src/cmd/netfiles/nsswitch.nis | 3 | ||||
-rw-r--r-- | usr/src/head/nss_dbdefs.h | 11 | ||||
-rw-r--r-- | usr/src/lib/nsswitch/files/Makefile.com | 4 | ||||
-rw-r--r-- | usr/src/lib/nsswitch/files/common/getnetgrent.c | 869 | ||||
-rw-r--r-- | usr/src/lib/nsswitch/files/common/mapfile-vers | 4 | ||||
-rw-r--r-- | usr/src/man/man1m/getent.1m | 53 | ||||
-rw-r--r-- | usr/src/man/man3c/getnetgrent.3c | 13 | ||||
-rw-r--r-- | usr/src/man/man4/netgroup.4 | 61 |
17 files changed, 1035 insertions, 77 deletions
diff --git a/usr/src/cmd/getent/Makefile b/usr/src/cmd/getent/Makefile index c68e2d91fe..174cb40fbb 100644 --- a/usr/src/cmd/getent/Makefile +++ b/usr/src/cmd/getent/Makefile @@ -38,6 +38,7 @@ OBJECTS= \ dogethost.o \ dogetipnodes.o \ dogetnet.o \ + dogetnetgr.o \ dogetnetmask.o \ dogetprofattr.o \ dogetproject.o \ diff --git a/usr/src/cmd/getent/dogetnetgr.c b/usr/src/cmd/getent/dogetnetgr.c new file mode 100644 index 0000000000..7addef787b --- /dev/null +++ b/usr/src/cmd/getent/dogetnetgr.c @@ -0,0 +1,71 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2012 Nexenta Systems, Inc. All rights reserved. + * Copyright 2021 Planets Communications B.V. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <netdb.h> +#include <string.h> +#include "getent.h" + +int +dogetnetgr(const char **list) +{ + uint_t cnt; + char *host, *user, *dom; + const char *host_filter, *user_filter, *dom_filter; + int rc = EXC_SUCCESS; + + if (list == NULL || *list == NULL) + return (EXC_ENUM_NOT_SUPPORTED); + + /* + * Count the arguments given. + */ + cnt = 0; + while (list[cnt] != NULL) + cnt++; + + switch (cnt) { + case 1: + if (setnetgrent(list[0]) != 0) + return (EXC_ERROR); + printf("%s", list[0]); + while (getnetgrent(&host, &user, &dom) != 0) { + printf(" (%s,%s,%s)", + (host) ? host : "", + (user) ? user : "", + (dom) ? dom : ""); + } + printf("\n"); + break; + case 4: + host_filter = (strcmp(list[1], "*") == 0) ? NULL : list[1]; + user_filter = (strcmp(list[2], "*") == 0) ? NULL : list[2]; + dom_filter = (strcmp(list[3], "*") == 0) ? NULL : list[3]; + printf("%-21s (%s,%s,%s) = %d\n", list[0], + (host_filter) ? host_filter : "", + (user_filter) ? user_filter : "", + (dom_filter) ? dom_filter : "", + innetgr(list[0], host_filter, user_filter, dom_filter)); + break; + default: + rc = EXC_SYNTAX; + break; + } + + return (rc); +} diff --git a/usr/src/cmd/getent/getent.c b/usr/src/cmd/getent/getent.c index 782034d956..ea15e1dd9b 100644 --- a/usr/src/cmd/getent/getent.c +++ b/usr/src/cmd/getent/getent.c @@ -56,6 +56,7 @@ static struct table t[] = { { "exec_attr", dogetexecattr }, { "prof_attr", dogetprofattr }, { "user_attr", dogetuserattr }, + { "netgroup", dogetnetgr }, { NULL, NULL } }; @@ -89,6 +90,10 @@ main(int argc, const char **argv) (void) fprintf(stderr, gettext("Syntax error\n")); break; + case EXC_ERROR: + (void) fprintf(stderr, + gettext("Internal error\n")); + break; case EXC_ENUM_NOT_SUPPORTED: (void) fprintf(stderr, gettext("Enumeration not supported on %s\n"), argv[1]); diff --git a/usr/src/cmd/getent/getent.h b/usr/src/cmd/getent/getent.h index 99b5cac075..6d5f6ed74a 100644 --- a/usr/src/cmd/getent/getent.h +++ b/usr/src/cmd/getent/getent.h @@ -40,6 +40,7 @@ extern "C" { #define EXC_SYNTAX 1 #define EXC_NAME_NOT_FOUND 2 #define EXC_ENUM_NOT_SUPPORTED 3 +#define EXC_ERROR 4 extern int dogetpw(const char **); extern int dogetsp(const char **); @@ -56,6 +57,7 @@ extern int dogetauthattr(const char **); extern int dogetexecattr(const char **); extern int dogetprofattr(const char **); extern int dogetuserattr(const char **); +extern int dogetnetgr(const char **); #ifdef __cplusplus } diff --git a/usr/src/cmd/netfiles/nsswitch.ad b/usr/src/cmd/netfiles/nsswitch.ad index e869c6bd32..bec5c72c2d 100644 --- a/usr/src/cmd/netfiles/nsswitch.ad +++ b/usr/src/cmd/netfiles/nsswitch.ad @@ -61,8 +61,6 @@ ethers: files netmasks: files bootparams: files publickey: files -# At present there isn't a 'files' backend for netgroup; the system will -# figure it out pretty quickly, and won't use netgroups at all. netgroup: files automount: files aliases: files diff --git a/usr/src/cmd/netfiles/nsswitch.conf b/usr/src/cmd/netfiles/nsswitch.conf index 58ec600c9a..a88791b430 100644 --- a/usr/src/cmd/netfiles/nsswitch.conf +++ b/usr/src/cmd/netfiles/nsswitch.conf @@ -38,8 +38,6 @@ ethers: files netmasks: files bootparams: files publickey: files -# At present there isn't a 'files' backend for netgroup; the system will -# figure it out pretty quickly, and won't use netgroups at all. netgroup: files automount: files aliases: files diff --git a/usr/src/cmd/netfiles/nsswitch.dns b/usr/src/cmd/netfiles/nsswitch.dns index ff4bafcc0c..cb58c3bc0a 100644 --- a/usr/src/cmd/netfiles/nsswitch.dns +++ b/usr/src/cmd/netfiles/nsswitch.dns @@ -21,7 +21,6 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" # # /etc/nsswitch.dns: @@ -39,7 +38,7 @@ passwd: files group: files # You must also set up the /etc/resolv.conf file for DNS name -# server lookup. See resolv.conf(4). For lookup via mdns +# server lookup. See resolv.conf(4). For lookup via mdns # svc:/network/dns/multicast:default must also be enabled. See mdnsd(1M) hosts: files dns mdns @@ -54,8 +53,6 @@ ethers: files netmasks: files bootparams: files publickey: files -# At present there isn't a 'files' backend for netgroup; the system will -# figure it out pretty quickly, and won't use netgroups at all. netgroup: files automount: files aliases: files diff --git a/usr/src/cmd/netfiles/nsswitch.files b/usr/src/cmd/netfiles/nsswitch.files index da48bed918..f847a442f6 100644 --- a/usr/src/cmd/netfiles/nsswitch.files +++ b/usr/src/cmd/netfiles/nsswitch.files @@ -20,7 +20,6 @@ # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" # # /etc/nsswitch.files: @@ -42,8 +41,6 @@ ethers: files netmasks: files bootparams: files publickey: files -# At present there isn't a 'files' backend for netgroup; the system will -# figure it out pretty quickly, and won't use netgroups at all. netgroup: files automount: files aliases: files diff --git a/usr/src/cmd/netfiles/nsswitch.ldap b/usr/src/cmd/netfiles/nsswitch.ldap index ccf75b4962..abf28da3d1 100644 --- a/usr/src/cmd/netfiles/nsswitch.ldap +++ b/usr/src/cmd/netfiles/nsswitch.ldap @@ -36,7 +36,6 @@ passwd: files ldap group: files ldap -# consult /etc "files" only if ldap is down. hosts: files ldap # Note that IPv4 addresses are searched for in all of the ipnodes databases @@ -51,7 +50,7 @@ netmasks: files ldap bootparams: files ldap publickey: files ldap -netgroup: ldap +netgroup: files ldap automount: files ldap aliases: files ldap diff --git a/usr/src/cmd/netfiles/nsswitch.nis b/usr/src/cmd/netfiles/nsswitch.nis index 064fdc40d9..9d31c9ac4d 100644 --- a/usr/src/cmd/netfiles/nsswitch.nis +++ b/usr/src/cmd/netfiles/nsswitch.nis @@ -36,7 +36,6 @@ passwd: files nis group: files nis -# consult /etc "files" only if nis is down. hosts: files nis # Note that IPv4 addresses are searched for in all of the ipnodes databases @@ -51,7 +50,7 @@ netmasks: files nis bootparams: files nis publickey: files nis -netgroup: nis +netgroup: files nis automount: files nis aliases: files nis diff --git a/usr/src/head/nss_dbdefs.h b/usr/src/head/nss_dbdefs.h index 458715632c..ca5f9abf6e 100644 --- a/usr/src/head/nss_dbdefs.h +++ b/usr/src/head/nss_dbdefs.h @@ -21,6 +21,8 @@ /* * Copyright 2014 Garrett D'Amore <garrett@damore.org> * + * Copyright 2012 Nexenta Systems, Inc. All rights reserved. + * * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * @@ -148,6 +150,7 @@ extern "C" { #define NSS_LINELEN_GROUP ((NSS_BUFSIZ) * 8) #define NSS_LINELEN_HOSTS ((NSS_BUFSIZ) * 8) #define NSS_LINELEN_IPNODES ((NSS_BUFSIZ) * 8) +#define NSS_LINELEN_NETGROUP ((NSS_BUFSIZ) * 32) #define NSS_LINELEN_NETMASKS NSS_BUFSIZ #define NSS_LINELEN_NETWORKS NSS_BUFSIZ #define NSS_LINELEN_PASSWD NSS_BUFSIZ @@ -358,6 +361,12 @@ struct nss_innetgr_args { enum nss_netgr_status status; }; +/* For NSS_DBOP_NETGROUP_BYNAME */ +struct nss_netgrent { + char *netgr_name; + char *netgr_members; +}; + /* * nss_XbyY_buf_t -- structure containing the generic arguments passwd to * getXXXbyYYY_r() and getXXXent_r() routines. The (void *) value points to @@ -779,9 +788,11 @@ extern nss_status_t nss_packed_getkey(void *, size_t, char **, int *, /* * The "real" backend for netgroup (__multi_innetgr, setnetgrent) + * Note: _BYNAME is implemented only in "files" (for now). */ #define NSS_DBOP_NETGROUP_IN (NSS_DBOP_next_iter) #define NSS_DBOP_NETGROUP_SET (NSS_DBOP_NETGROUP_IN + 1) +#define NSS_DBOP_NETGROUP_BYNAME (NSS_DBOP_NETGROUP_SET + 1) /* * The backend for getpublickey and getsecretkey (getkeys) diff --git a/usr/src/lib/nsswitch/files/Makefile.com b/usr/src/lib/nsswitch/files/Makefile.com index e79567aaaf..5b57f6b6ed 100644 --- a/usr/src/lib/nsswitch/files/Makefile.com +++ b/usr/src/lib/nsswitch/files/Makefile.com @@ -22,6 +22,7 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2012 Nexenta Systems, Inc. All rights reserved LIBRARY = libnss_files.a VERS = .1 @@ -33,6 +34,7 @@ OBJECTS = bootparams_getbyname.o \ gethostent.o \ gethostent6.o \ getnetent.o \ + getnetgrent.o \ getprojent.o \ getprotoent.o \ getpwnam.o \ @@ -75,3 +77,5 @@ $(ROOT)/etc/lib/$(DYNLIB1) := COMPATLINKTARGET= ../../lib/$(DYNLIB1) all: $(DYNLIB1) +pics/getnetgrent.o := CERRWARN= +pics/getnetgrent.o := SMATCH= diff --git a/usr/src/lib/nsswitch/files/common/getnetgrent.c b/usr/src/lib/nsswitch/files/common/getnetgrent.c new file mode 100644 index 0000000000..58e5eaae3e --- /dev/null +++ b/usr/src/lib/nsswitch/files/common/getnetgrent.c @@ -0,0 +1,869 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2012 Nexenta Systems, Inc. All rights reserved. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * files/getnetgrent.c -- "files" backend for nsswitch "netgroup" database + * + * The API for netgroups differs sufficiently from that for the average + * getXXXbyYYY function that we use very few of the support routines in + * files_common.h. + * + * The implementation of setnetgrent()/getnetgrent() here follows the + * the 4.x code, inasmuch as the setnetgrent() routine does all the work + * of traversing the netgroup graph and building a (potentially large) + * list in memory, and getnetgrent() just steps down the list. + * + * An alternative, and probably better, implementation would lazy-eval + * the netgroup graph in response to getnetgrent() calls (though + * setnetgrent() should still check for the top-level netgroup name + * and return NSS_SUCCESS / NSS_NOTFOUND). + */ + +#include "files_common.h" +#include <ctype.h> +#include <rpcsvc/ypclnt.h> +#include <malloc.h> +#include <string.h> +#include <ctype.h> +#include <sys/sysmacros.h> + +/* + * Tricky debug support + */ + +#pragma weak __nss_files_netgr_debug +#pragma weak __nss_files_netgr_error +extern void __nss_files_netgr_debug(const char *, ...); +extern void __nss_files_netgr_error(const char *, ...); + +/* + * Start of stuff borrowed from getgrent.c + */ +static uint_t +hash_netgrname(nss_XbyY_args_t *argp, int keyhash, const char *line, + int linelen) +{ + const char *name; + uint_t namelen, i; + uint_t hash = 0; + + if (keyhash) { + name = argp->key.name; + namelen = strlen(name); + } else { + name = line; + namelen = 0; + while (linelen-- && !isspace(*line)) { + line++; + namelen++; + } + } + + for (i = 0; i < namelen; i++) + hash = hash * 15 + name[i]; + return (hash); +} + +static files_hash_func hash_netgr[1] = { hash_netgrname }; + +static files_hash_t hashinfo = { + DEFAULTMUTEX, + sizeof (struct nss_netgrent), + NSS_LINELEN_NETGROUP, + 1, + hash_netgr +}; + +static int +check_netgrname(nss_XbyY_args_t *argp, const char *line, int linelen) +{ + const char *linep, *limit; + const char *keyp = argp->key.name; + + linep = line; + limit = line + linelen; + + /* +/- entries valid for compat source only */ + if (linelen == 0 || *line == '+' || *line == '-') + return (0); + while (*keyp && linep < limit && *keyp == *linep) { + keyp++; + linep++; + } + return (linep < limit && *keyp == '\0' && isspace(*linep)); +} + +static nss_status_t +getbyname(files_backend_ptr_t be, void *a) +{ + return (_nss_files_XY_hash(be, a, 1, &hashinfo, 0, check_netgrname)); +} + +/* + * End of stuff borrowed from getgrent.c + * + * Now some "glue" functions based loosely on + * lib/libc/port/gen/getgrnam_r.c + */ + + +/* + * This is a special purpose str2ent (parse) function used only in + * the _nss_files_getbyname() below. A general-purpose version of + * this parser would copy the incoming line buffer to the passed + * temporary buffer, and fill in the passed struct nss_netgrent with + * pointers into that temporary buffer. Our caller only needs the + * list of members of this netgroup, and since that string already + * exists in ready-to-use form in the incoming line buffer, we just + * use that. Also special here is the fact that we allocate a copy + * of the member list, both because the caller wants it allocated, + * and because the buffer at *instr will change after we return. + * The caller passes null for a temporary buffer, which we ignore. + * + * See the test program: cmd/nsstest/netgr_get.c + * for a more generic version of this function. + */ +static int +str2netgr(const char *instr, int lenstr, void *ent, char *buffer, int buflen) +{ + const char sep[] = " \t\n"; + struct nss_netgrent *netgr = ent; + const char *p; + + /* skip leading space */ + p = instr; + while (isspace(*p)) + p++; + + /* should be at the key */ + if (*p == '\0') + return (NSS_STR_PARSE_PARSE); + /* Full parser would set netgr_name = p here. */ + + /* skip the key ... */ + p = strpbrk(p, sep); + if (p == NULL) + return (NSS_STR_PARSE_PARSE); + /* Full parser would store a null at *p here. */ + + /* skip separators */ + while (isspace(*p)) + p++; + + /* + * Should be at the members list, which is the + * rest of the input line. + */ + if (*p == '\0') + return (NSS_STR_PARSE_PARSE); + + /* + * Caller wants this allocated. Do it now, + * before the inbuf gets re-used. + */ + netgr->netgr_members = strdup(p); + if (netgr->netgr_members == NULL) + return (NSS_STR_PARSE_PARSE); + + return (NSS_STR_PARSE_SUCCESS); +} + +/* + * This is a compatibility "shim" used by top_down() to get + * the list of members for some netgroup. On success, the + * list of members is returned in allocated memory via valp. + */ +static nss_status_t +netgr_get_members(struct files_backend *be, + const char *name, char **valp) +{ + struct nss_netgrent netgr; + nss_XbyY_args_t args; + nss_status_t result; + + if (name == (const char *)NULL) + return (NSS_ERROR); + + (void) memset(&netgr, '\0', sizeof (netgr)); + (void) memset(&args, '\0', sizeof (args)); + args.buf.result = &netgr; + args.str2ent = str2netgr; + args.key.name = name; + result = getbyname(be, &args); + + if (result == NSS_SUCCESS) { + /* Note: allocated memory. */ + *valp = netgr.netgr_members; + if (*valp == NULL) + result = NSS_UNAVAIL; + } + + return (result); +} + + +/* + * End "glue" functions + * + * The rest of this is based on: + * lib/nsswitch/nis/common/getnetgrent.c + */ + + +/* + * The nss_backend_t for a getnetgrent() sequence; we actually give the + * netgroup frontend a pointer to one of these structures in response to + * a (successful) setnetgrent() call on the files_backend backend + * described further down in this file. + */ + +struct files_getnetgr_be; +typedef nss_status_t (*files_getnetgr_op_t)( + struct files_getnetgr_be *, void *); + +struct files_getnetgr_be { + files_getnetgr_op_t *ops; + nss_dbop_t n_ops; + /* + * State for set/get/endnetgrent() + */ + char *netgroup; + struct grouplist *all_members; + struct grouplist *next_member; +}; + +struct grouplist { /* One element of the list generated by a setnetgrent() */ + char *triple[NSS_NETGR_N]; + struct grouplist *gl_nxt; +}; + +static nss_status_t +getnetgr_set(struct files_getnetgr_be *be, void *a) +{ + const char *netgroup = (const char *) a; + + if (be->netgroup != NULL && + strcmp(be->netgroup, netgroup) == 0) { + /* We already have the member-list; regurgitate it */ + be->next_member = be->all_members; + return (NSS_SUCCESS); + } + return (NSS_NOTFOUND); +} + +static nss_status_t +getnetgr_get(struct files_getnetgr_be *be, void *a) +{ + struct nss_getnetgrent_args *args = (struct nss_getnetgrent_args *)a; + struct grouplist *mem; + + if ((mem = be->next_member) == 0) { + args->status = NSS_NETGR_NO; + } else { + char *buffer = args->buffer; + int buflen = args->buflen; + enum nss_netgr_argn i; + + args->status = NSS_NETGR_FOUND; + + for (i = 0; i < NSS_NETGR_N; i++) { + const char *str; + ssize_t len; + + if ((str = mem->triple[i]) == 0) { + args->retp[i] = NULL; + } else if ((len = strlen(str) + 1) <= buflen) { + args->retp[i] = buffer; + (void) memcpy(buffer, str, len); + buffer += len; + buflen -= len; + } else { + args->status = NSS_NETGR_NOMEM; + break; + } + } + be->next_member = mem->gl_nxt; + } + return (NSS_SUCCESS); /* Yup, even for end-of-list, i.e. */ + /* do NOT advance to next backend. */ +} + +static nss_status_t +getnetgr_end(struct files_getnetgr_be *be, void *dummy) +{ + struct grouplist *gl; + struct grouplist *next; + + for (gl = be->all_members; gl != NULL; gl = next) { + enum nss_netgr_argn i; + + next = gl->gl_nxt; + for (i = NSS_NETGR_MACHINE; i < NSS_NETGR_N; i++) { + free(gl->triple[i]); + } + free(gl); + } + be->all_members = NULL; + be->next_member = NULL; + free(be->netgroup); + be->netgroup = NULL; + return (NSS_SUCCESS); +} + +static nss_status_t +getnetgr_destr(struct files_getnetgr_be *be, void *dummy) +{ + if (be != NULL) { + (void) getnetgr_end(be, NULL); + free(be); + } + return (NSS_SUCCESS); +} + +static files_getnetgr_op_t getnetgr_ops[] = { + getnetgr_destr, + getnetgr_end, + getnetgr_set, + getnetgr_get, /* getnetgrent_r() */ +}; + + +/* + * The nss_backend_t for innetgr() and setnetgrent(). + * Also getbyname(), but that's only for testing. + */ + + + +/* + * Code to do top-down search in the graph defined by the 'netgroup' YP map + */ + +/* + * ===> This code is now used for setnetgrent(), not just innetgr(). + * + * If the easy way doesn't pan out, recursively search the 'netgroup' map. + * In order to do this, we: + * + * - remember all the netgroup names we've seen during this search, + * whether or not we've expanded them yet (we want fast insertion + * with duplicate-detection, so use yet another chained hash table), + * + * - keep a list of all the netgroups we haven't expanded yet (we just + * want fast insertion and pop-first, so a linked list will do fine). + * If we insert at the head, we get a depth-first search; insertion + * at the tail gives breadth-first (?), which seems preferable (?). + * + * A netgrnam struct contains pointers for both the hash-table and the list. + * It also contains the netgroup name; note that we embed the name at the + * end of the structure rather than holding a pointer to yet another + * malloc()ed region. + * + * A netgrtab structure contains the hash-chain heads and the head/tail + * pointers for the expansion list. + */ + +struct netgrnam { + struct netgrnam *hash_chain; + struct netgrnam *expand_next; + char name[1]; /* Really [strlen(name) + 1] */ +}; + +#define HASHMOD 113 + +struct netgrtab { + struct netgrnam *expand_first; + struct netgrnam **expand_lastp; + struct netgrnam *hash_heads[HASHMOD]; +}; + +static void +ngt_init(struct netgrtab *ngt) +{ + (void) memset((void *)ngt, '\0', sizeof (*ngt)); + ngt->expand_lastp = &ngt->expand_first; +} + +/* === ? Change ngt_init() and ngt_destroy() to malloc/free struct netgrtab */ + +static void +/* ==> ? Should return 'failed' (out-of-memory) status ? */ +ngt_insert(struct netgrtab *ngt, const char *name, size_t namelen) +{ + unsigned hashval; + size_t i; + struct netgrnam *cur; + struct netgrnam **head; + + if (__nss_files_netgr_debug != NULL) { + __nss_files_netgr_debug( + "ngt_insert: ngt=%p names=%s", ngt, name); + } + + for (hashval = 0, i = 0; i < namelen; i++) { + hashval = (hashval << 2) + hashval + + ((const unsigned char *)name)[i]; + } + head = &ngt->hash_heads[hashval % HASHMOD]; + for (cur = *head; cur != 0; cur = cur->hash_chain) { + if (strncmp(cur->name, name, namelen) == 0 && + cur->name[namelen] == 0) { + return; /* Already in table, do nothing */ + } + } + /* Create new netgrnam struct */ + cur = malloc(offsetof(struct netgrnam, name) + namelen + 1); + if (cur == NULL) { + return; /* Out of memory, too bad */ + } + (void) memcpy(cur->name, name, namelen); + cur->name[namelen] = '\0'; + + /* Insert in hash table */ + cur->hash_chain = *head; + *head = cur; + + /* Insert in expansion list (insert at end for breadth-first search */ + cur->expand_next = NULL; + *ngt->expand_lastp = cur; + ngt->expand_lastp = &cur->expand_next; +} + +static const char * +ngt_next(struct netgrtab *ngt) +{ + struct netgrnam *first; + + if ((first = ngt->expand_first) == NULL) { + return (NULL); + } + if ((ngt->expand_first = first->expand_next) == NULL) { + ngt->expand_lastp = &ngt->expand_first; + } + return (first->name); +} + +static void +ngt_destroy(struct netgrtab *ngt) +{ + struct netgrnam *cur; + struct netgrnam *next; + int i; + + for (i = 0; i < HASHMOD; i++) { + for (cur = ngt->hash_heads[i]; cur != NULL; ) { + next = cur->hash_chain; + free(cur); + cur = next; + } + } + /* Don't bother zeroing pointers; must do init if we want to reuse */ +} + +typedef const char *ccp; + +static nss_status_t +top_down(struct files_backend *be, const char **groups, int ngroups, + int (*func)(ccp triple[3], void *iter_args, nss_status_t *return_val), + void *iter_args) +{ + struct netgrtab *ngt; + /* netgrtab goes on the heap, not the stack, because it's large and */ + /* stacks may not be all that big in multi-threaded programs. */ + + const char *group; + int nfound; + int done; + nss_status_t result; + + if ((ngt = malloc(sizeof (*ngt))) == NULL) { + return (NSS_UNAVAIL); + } + ngt_init(ngt); + + while (ngroups > 0) { + ngt_insert(ngt, *groups, strlen(*groups)); + groups++; + ngroups--; + } + + done = 0; /* Set to 1 to indicate that we cut the iteration */ + /* short (and 'result' holds the return value) */ + nfound = 0; /* Number of successful netgroup getbyname calls */ + + while (!done && (group = ngt_next(ngt)) != NULL) { + char *val = NULL; + char *p; + + result = netgr_get_members(be, group, &val); + if (result != NSS_SUCCESS) { + if (result == NSS_NOTFOUND) { + if (__nss_files_netgr_error != NULL) + __nss_files_netgr_error( + "files netgroup lookup: %s doesn't exist", + group); + } else { + if (__nss_files_netgr_error != NULL) + __nss_files_netgr_error( + "files netgroup lookup: getbyname returned [%s]", + strerror(errno)); + done = 1; /* Give up, return result */ + } + /* Don't need to clean up anything */ + continue; + } + + if (__nss_files_netgr_debug != NULL) { + __nss_files_netgr_debug( + "ngt_top: ngt=%p grp=%s members=\"%s\"", + ngt, group, val); + } + + nfound++; + + if ((p = strpbrk(val, "#\n")) != NULL) { + *p = '\0'; + } + p = val; + + /* Parse val into triples and recursive netgroup references */ + for (;;) { + ccp triple[NSS_NETGR_N]; + int syntax_err; + enum nss_netgr_argn i; + + while (isspace(*p)) + p++; + if (*p == '\0') { + /* Finished processing this particular val */ + break; + } + if (*p != '(') { + /* Doesn't look like the start of a triple, */ + /* so assume it's a recursive netgroup. */ + char *start = p; + p = strpbrk(start, " \t"); + if (p == 0) { + /* Point p at the final '\0' */ + p = start + strlen(start); + } + ngt_insert(ngt, start, (size_t)(p - start)); + continue; + } + + /* Main case: a (machine, user, domain) triple */ + p++; + syntax_err = 0; + for (i = NSS_NETGR_MACHINE; i < NSS_NETGR_N; i++) { + char *start; + char *limit; + const char *terminators = ",) \t"; + + if (i == NSS_NETGR_DOMAIN) { + /* Don't allow comma */ + terminators++; + } + while (isspace(*p)) + p++; + start = p; + limit = strpbrk(start, terminators); + if (limit == 0) { + syntax_err++; + break; + } + p = limit; + while (isspace(*p)) + p++; + if (*p == terminators[0]) { + /* + * Successfully parsed this name and + * the separator after it (comma or + * right paren); leave p ready for + * next parse. + */ + p++; + if (start == limit) { + /* Wildcard */ + triple[i] = 0; + } else { + *limit = '\0'; + triple[i] = start; + } + } else { + syntax_err++; + break; + } + } + + if (syntax_err) { +/* + * ===> log it; + * ===> try skipping past next ')'; failing that, abandon the line; + */ + break; /* Abandon this line */ + } else if ((*func)(triple, iter_args, &result) == 0) { + /* Return result, good or bad */ + done = 1; + break; + } + } + /* End of inner loop over val[] */ + free(val); + val = NULL; + } + /* End of outer loop (!done && ngt_next(ngt) != 0) */ + + ngt_destroy(ngt); + free(ngt); + + if (done) { + return (result); + } else if (nfound > 0) { + /* ==== ? Should only do this if all the top-level groups */ + /* exist in YP? */ + return (NSS_SUCCESS); + } else { + return (NSS_NOTFOUND); + } +} + + +/* + * Code for setnetgrent() + */ + +/* + * Iterator function for setnetgrent(): copy triple, add to be->all_members + */ +static int +save_triple(ccp trippp[NSS_NETGR_N], void *headp_arg, + nss_status_t *return_val) +{ + struct grouplist **headp = headp_arg; + struct grouplist *gl; + enum nss_netgr_argn i; + + if (__nss_files_netgr_debug != NULL) { + __nss_files_netgr_debug( + "save_tripple: h=%s u=%s d=%s", + trippp[0] ? trippp[0] : "*", + trippp[1] ? trippp[1] : "*", + trippp[2] ? trippp[2] : "*"); + } + + if ((gl = malloc(sizeof (*gl))) == NULL) { + /* Out of memory */ + *return_val = NSS_UNAVAIL; + return (0); + } + for (i = NSS_NETGR_MACHINE; i < NSS_NETGR_N; i++) { + if (trippp[i] == NULL) { + /* Wildcard */ + gl->triple[i] = NULL; + } else if ((gl->triple[i] = strdup(trippp[i])) == NULL) { + /* Out of memory. Free any we've allocated */ + enum nss_netgr_argn j; + + for (j = NSS_NETGR_MACHINE; j < i; j++) { + free(gl->triple[j]); + } + free(gl); + *return_val = NSS_UNAVAIL; + return (0); + } + } + gl->gl_nxt = *headp; + *headp = gl; + return (1); /* Tell top_down() to keep iterating */ +} + +static nss_status_t +netgr_set(struct files_backend *be, void *a) +{ + struct nss_setnetgrent_args *args = (struct nss_setnetgrent_args *)a; + struct files_getnetgr_be *get_be; + nss_status_t res; + + get_be = malloc(sizeof (*get_be)); + if (get_be == NULL) { + return (NSS_UNAVAIL); + } + + get_be->all_members = NULL; + res = top_down(be, &args->netgroup, 1, save_triple, + &get_be->all_members); + + if (res == NSS_SUCCESS) { + get_be->ops = getnetgr_ops; + get_be->n_ops = ARRAY_SIZE(getnetgr_ops); + get_be->netgroup = strdup(args->netgroup); + if (get_be->netgroup == NULL) { + /* Out of memory. */ + args->iterator = NULL; + free(get_be); + return (NSS_UNAVAIL); + } + get_be->next_member = get_be->all_members; + + args->iterator = (nss_backend_t *)get_be; + } else { + args->iterator = NULL; + free(get_be); + } + return (res); +} + + +/* + * Code for innetgr() + */ + +/* + * Iterator function for innetgr(): Check whether triple matches args + */ +static int +match_triple(ccp triple[NSS_NETGR_N], void *ia_arg, nss_status_t *return_val) +{ + struct nss_innetgr_args *ia = ia_arg; + enum nss_netgr_argn i; + + if (__nss_files_netgr_debug != NULL) { + __nss_files_netgr_debug( + "match_triple: h=%s u=%s d=%s", + triple[0] ? triple[0] : "*", + triple[1] ? triple[1] : "*", + triple[2] ? triple[2] : "*"); + } + + for (i = NSS_NETGR_MACHINE; i < NSS_NETGR_N; i++) { + int (*cmpf)(const char *, const char *); + char **argv; + uint_t n; + const char *name = triple[i]; + int argc = ia->arg[i].argc; + + if (argc == 0 || name == NULL) { + /* Wildcarded on one side or t'other */ + continue; + } + argv = ia->arg[i].argv; + cmpf = (i == NSS_NETGR_MACHINE) ? strcasecmp : strcmp; + for (n = 0; n < argc; n++) { + if ((*cmpf)(argv[n], name) == 0) { + break; + } + } + if (n >= argc) { + /* Match failed, tell top_down() to keep looking */ + return (1); + } + } + /* Matched on all three, so quit looking and declare victory */ + + if (__nss_files_netgr_debug != NULL) + __nss_files_netgr_debug("match_triple: found"); + + ia->status = NSS_NETGR_FOUND; + *return_val = NSS_SUCCESS; + return (0); +} + +/* + * Used to have easy_way() and it's support functions here. + */ + +static nss_status_t +netgr_in(struct files_backend *be, void *a) +{ + struct nss_innetgr_args *ia = (struct nss_innetgr_args *)a; + nss_status_t res; + + ia->status = NSS_NETGR_NO; + + /* + * Used to have "easy_way" calls here for the cases + * where we have just a user, or just a machine. + * + * That was important for NIS, where getting the list of + * members for some netgroup was a yp_match call that may + * need to go over-the-wire. Here in the "files" backend, + * getting the members of a group (getbyname) is a strictly + * local operation, and is cached (see hashinfo above) so + * it can normally complete with just memory operations. + * + * With a low-cost getbyname operation, the simple + * top_down algorithm has acceptable performance. + */ + + /* Nope, try the slow way */ + ia->status = NSS_NETGR_NO; + res = top_down(be, (const char **)ia->groups.argv, ia->groups.argc, + match_triple, ia); + return (res); +} + + +/* + * (Almost) boilerplate for a switch backend + */ + +static nss_status_t +netgr_destr(struct files_backend *be, void *dummy) +{ + free(be); + return (NSS_SUCCESS); +} + +static files_backend_op_t netgroup_ops[] = { + netgr_destr, + NULL, /* No endent, because no setent/getent */ + NULL, /* No setent; setnetgrent() is really a getXbyY() */ + NULL, /* No getent in the normal sense */ + + netgr_in, /* innetgr(), via NSS_DBOP_NETGROUP_IN */ + netgr_set, /* setnetgrent(), via NSS_DBOP_NETGROUP_SET */ + getbyname, /* For testing, via NSS_DBOP_NETGROUP_BYNAME */ +}; + +/* + * This is the one-and-only external entry point in this file. + * It's called by the NSS framework when loading this backend. + */ +nss_backend_t * +_nss_files_netgroup_constr(const char *dummy1, const char *dummy2, + const char *dummy3) +{ + nss_backend_t *be; + + be = _nss_files_constr(netgroup_ops, + ARRAY_SIZE(netgroup_ops), + "/etc/netgroup", + NSS_LINELEN_NETGROUP, + &hashinfo); + + return (be); +} diff --git a/usr/src/lib/nsswitch/files/common/mapfile-vers b/usr/src/lib/nsswitch/files/common/mapfile-vers index 722c5c27f8..3e40dade95 100644 --- a/usr/src/lib/nsswitch/files/common/mapfile-vers +++ b/usr/src/lib/nsswitch/files/common/mapfile-vers @@ -1,5 +1,6 @@ # # Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012 Nexenta Systems, Inc. All rights reserved. # # CDDL HEADER START # @@ -46,11 +47,12 @@ SYMBOL_VERSION SUNWprivate_1.1 { _nss_files_bootparams_constr; _nss_files_auth_attr_constr; _nss_files_audit_user_constr; - _nss_files_ethers_constr; + _nss_files_ethers_constr; _nss_files_exec_attr_constr; _nss_files_group_constr; _nss_files_hosts_constr; _nss_files_ipnodes_constr; + _nss_files_netgroup_constr; _nss_files_netmasks_constr; _nss_files_networks_constr; _nss_files_passwd_constr; diff --git a/usr/src/man/man1m/getent.1m b/usr/src/man/man1m/getent.1m index af87eb677b..71a71c496f 100644 --- a/usr/src/man/man1m/getent.1m +++ b/usr/src/man/man1m/getent.1m @@ -19,7 +19,7 @@ .\" Copyright (c) 2014 Gary Mills .\" Copyright (c) 2018 Peter Tribble .\" -.Dd August 13, 2018 +.Dd June 17, 2021 .Dt GETENT 1M .Os .Sh NAME @@ -56,14 +56,16 @@ This can be .Cm auth_attr , .Cm exec_attr , .Cm prof_attr , +.Cm user_attr , or -.Cm user_attr . +.Cm netgroup . For each of these databases, .Nm uses the appropriate library routines described in .Xr getpwnam 3C , .Xr getspnam 3C , .Xr getgrnam 3C , +.Xr getnetgrent 3C , .Xr gethostbyaddr 3NSL , .Xr gethostbyname 3NSL , .Xr getipnodebyaddr 3SOCKET , @@ -101,6 +103,7 @@ line, in the format of the matching administrative file: .Xr services 4 , .Xr protocols 4 , .Xr ethers 4 , +.Xr netgroup 4 , .Xr networks 4 , .Xr netmasks 4 , .Xr auth_attr 4 , @@ -117,9 +120,10 @@ are printed. Enumeration is not supported on .Cm ipnodes , .Cm ethers , +.Cm netgroup , or .Cm netmasks . -.Ss Key Interpretation for passwd, group, and user_attr Databases +.Ss Key Interpretation for passwd, group, netgroup, and user_attr Databases When .Nm is invoked with @@ -173,6 +177,46 @@ When is invoked with .Ar database set to +.Cm netgroup , +only a single lookup key is supported, which must be in the following format: +.Bd -ragged -offset Ds +.Ar netgroup Oo Ar host Ar user Ar domain Oc +.Ed +.Pp +Specifying only the +.Ar netgroup +name will result in entries from the selected netgroup being displayed as +string triples +.Pq hostname, username, domain , +in a format compatible with +.Xr netgroup 4 . +.Pp +Specifying the +.Ar netgroup +along with +.Ar host , +.Ar user +and +.Ar domain +will filter the netgroup display based on these entries. +An asterisk +.Pq \&* +can be used as a wildcard for the +.Ar host , +.Ar user +or +.Ar domain +fields. +.Pp +Since the +.Cm netgroup +database does not support enumeration, a lookup key must always be specified. +.Pp +When +.Nm +is invoked with +.Ar database +set to .Cm user_attr , each key value is processed as follows: .Bl -bullet @@ -216,6 +260,8 @@ Ethernet address to hostname database or domain network name database .It Pa /etc/netmasks network mask database +.It Pa /etc/netgroup +network group database .It Pa /etc/user_attr extended user attributes database .It Pa /etc/security/auth_attr @@ -241,6 +287,7 @@ There is no support for enumeration on this database. .El .Sh SEE ALSO .Xr getgrnam 3C , +.Xr getnetgrent 3C , .Xr getpwnam 3C , .Xr getspnam 3C , .Xr gethostbyaddr 3NSL , diff --git a/usr/src/man/man3c/getnetgrent.3c b/usr/src/man/man3c/getnetgrent.3c index a404bbaad5..024064d633 100644 --- a/usr/src/man/man3c/getnetgrent.3c +++ b/usr/src/man/man3c/getnetgrent.3c @@ -8,7 +8,6 @@ getnetgrent, getnetgrent_r, setnetgrent, endnetgrent, innetgr \- get network group entry .SH SYNOPSIS -.LP .nf #include <netdb.h> @@ -38,7 +37,6 @@ group entry .fi .SH DESCRIPTION -.LP These functions are used to test membership in and enumerate members of ``netgroup'' network groups defined in a system database. Netgroups are sets of (machine,user,domain) triples (see \fBnetgroup\fR(4)). @@ -122,7 +120,6 @@ multiple threads interleave calls to \fBgetnetgrent_r()\fR each will enumerate a disjoint subset of the netgroup. Thus the effective use of these functions in multi-threaded applications may require coordination by the caller. .SH ERRORS -.LP The function \fBgetnetgrent_r()\fR will return \fB0\fR and set \fBerrno\fR to \fBERANGE\fR if the length of the buffer supplied by caller is not large enough to store the result. See \fBIntro\fR(2) for the proper usage and @@ -141,7 +138,6 @@ success. .RE .SH ATTRIBUTES -.LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -156,18 +152,17 @@ MT-Level See \fBDESCRIPTION\fR section. .TE .SH SEE ALSO -.LP \fBIntro\fR(2), \fBIntro\fR(3), \fBnetgroup\fR(4), \fBnsswitch.conf\fR(4), \fBattributes\fR(5) .SH WARNINGS -.LP The function \fBgetnetgrent_r()\fR is included in this release on an uncommitted basis only, and is subject to change or removal in future minor releases. .SH NOTES -.LP -Only the Network Information Services, \fBNIS\fR, is supported -as a source for the \fBnetgroup\fR database. +Network groups are usually stored in network information services, +such as \fBLDAP\fR, or \fBNIS\fR, but may alternatively be stored in +the local \fB/etc/netgroup\fR file. The \fBnetgroup\fR line of the +\fBnsswitch.conf\fR(4) file determines which of those sources are used. .sp .LP When compiling multi-threaded applications, see \fBIntro\fR(3), \fINotes On diff --git a/usr/src/man/man4/netgroup.4 b/usr/src/man/man4/netgroup.4 index a7d8e8d4b4..b693d6a7be 100644 --- a/usr/src/man/man4/netgroup.4 +++ b/usr/src/man/man4/netgroup.4 @@ -1,34 +1,30 @@ '\" te +.\" Copyright 2012 Nexenta Systems, Inc. All rights reserved. .\" Copyright (C) 2003, Sun Microsystems, Inc. All Rights Reserved .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH NETGROUP 4 "Feb 25, 2017" +.TH NETGROUP 4 "Jun 17, 2021" .SH NAME netgroup \- list of network groups .SH SYNOPSIS -.LP .nf \fB/etc/netgroup\fR .fi - .SH DESCRIPTION -.LP A \fBnetgroup\fR defines a network-wide group of hosts and users. Use a \fBnetgroup\fR to restrict access to shared \fBNFS\fR filesystems and to restrict remote login and shell access. .sp -.LP -Network groups are stored in a network information service, such as -\fBLDAP\fR or \fBNIS\fR, not in a local file. +Network groups are usually stored in network information services, +such as \fBLDAP\fR, or \fBNIS\fR, but may alternatively be stored in +the local \fB/etc/netgroup\fR file. The \fBnetgroup\fR line of the +\fBnsswitch.conf\fR(4) file determines which of those sources are used. .sp -.LP This manual page describes the format for a file that is used to supply input -to a program such as \fBldapaddent\fR(1M) for LDAP or \fBmakedbm\fR(1M) for -NIS. These programs build maps or tables used by -their corresponding network information services. +to a program such as \fBldapaddent\fR(1M) for LDAP, or \fBmakedbm\fR(1M) for +NIS. The same file format is used in the local \fB/etc/netgroup\fR file. .sp -.LP Each line of the file defines the name and membership of a network group. The line should have the format: .sp @@ -38,13 +34,10 @@ line should have the format: .fi .in -2 .sp - .sp -.LP The items on a line can be separated by a combination of one or more spaces or tabs. .sp -.LP The \fIgroupname\fR is the name of the group being defined. This is followed by a list of members of the group. Each \fImember\fR is either another group name, all of whose members are to be included in the group being defined, or a triple @@ -56,9 +49,7 @@ of the form: .fi .in -2 .sp - .sp -.LP In each triple, any of the three fields \fIhostname\fR, \fIusername\fR, and \fIdomainname\fR, can be empty. An empty field signifies a wildcard that matches any value in that field. Thus: @@ -69,13 +60,10 @@ everything (\|,\|,this.domain) .fi .in -2 .sp - .sp -.LP defines a group named "everything" for the domain "this.domain" to which every host and user belongs. .sp -.LP The \fIdomainname\fR field refers to the domain in which the triple is valid, not the domain containing the host or user. In fact, applications using \fBnetgroup\fR generally do not check the \fIdomainname\fR. Therefore, using @@ -86,9 +74,7 @@ not the domain containing the host or user. In fact, applications using .fi .in -2 .sp - .sp -.LP is equivalent to .sp .in +2 @@ -97,27 +83,22 @@ is equivalent to .fi .in -2 .sp - .sp -.LP You can also use netgroups to control \fBNFS\fR mount access (see \fBshare_nfs\fR(1M)) and to control remote login and shell access (see \fBhosts.equiv\fR(4)). You can also use them to control local login access (see \fBpasswd\fR(4), \fBshadow\fR(4), and \fBcompat\fR in \fBnsswitch.conf\fR(4)). .sp -.LP When used for these purposes, a host is considered a member of a \fBnetgroup\fR if the \fBnetgroup\fR contains any triple in which the \fBhostname\fR field matches the name of the host requesting access and the \fBdomainname\fR field matches the domain of the host controlling access. .sp -.LP Similarly, a user is considered a member of a \fBnetgroup\fR if the \fBnetgroup\fR contains any triple in which the \fIusername\fR field matches the name of the \fBuser\fR requesting access and the \fIdomainname\fR field matches the domain of the host controlling access. .sp -.LP Note that when netgroups are used to control NFS mount access, access is granted depending only on whether the requesting host is a member of the \fBnetgroup\fR. Remote login and shell access can be controlled both on the @@ -130,30 +111,19 @@ basis of host and user membership in separate netgroups. .RS 17n Used by a network information service's utility to construct a map or table that contains \fBnetgroup\fR information. For example, \fBldapaddent\fR(1M) -uses \fB/etc/netgroup\fR to construct an LDAP container. +uses \fB/etc/netgroup\fR to construct an LDAP container. Alternatively, +the \fB/etc/netgroup\fR file may be used directly if the \fBfiles\fR +source is specified in \fBnsswitch.conf\fR(4) for the \fBnetgroup\fR +database. .RE - -.sp -.LP -Note that the netgroup information must always be stored in a network -information service, such as \fBLDAP\fR or \fBNIS\fR. The local file is -only used to construct a map or table for the network information service. It -is never consulted directly. .SH SEE ALSO -.LP \fBldapaddent\fR(1M), \fBmakedbm\fR(1M), \fBshare_nfs\fR(1M), \fBinnetgr\fR(3C), \fBhosts\fR(4), \fBhosts.equiv\fR(4), \fBnsswitch.conf\fR(4), \fBpasswd\fR(4), \fBshadow\fR(4) .SH NOTES -.LP -\fBnetgroup\fR requires a network information service such as \fBLDAP\fR -or \fBNIS\fR. -.sp -.LP Applications may make general membership tests using the \fBinnetgr()\fR function. See \fBinnetgr\fR(3C). .sp -.LP Because the "-" character will not match any specific username or hostname, it is commonly used as a placeholder that will match only wildcarded membership queries. So, for example: @@ -165,17 +135,13 @@ onlyusers (-,john,our.domain) (-,linda,our.domain) .fi .in -2 .sp - .sp -.LP effectively define netgroups containing only hosts and only users, respectively. Any other string that is guaranteed not to be a legal username or hostname will also suffice for this purpose. .sp -.LP Use of placeholders will improve search performance. .sp -.LP When a machine with multiple interfaces and multiple names is defined as a member of a \fBnetgroup\fR, one must list all of the names. See \fBhosts\fR(4). A manageable way to do this is to define a \fBnetgroup\fR containing all of the @@ -188,8 +154,5 @@ gateway (gateway-subnet1,\|,our.domain) (gateway-subnet2,\|,our.domain) .fi .in -2 .sp - -.sp -.LP and use this \fBnetgroup\fR "\fBgateway\fR" whenever the host is to be included in another \fBnetgroup\fR. |