xref: /titanic_44/usr/src/lib/libc/port/gen/getnetgrent.c (revision 7257d1b4d25bfac0c802847390e98a464fd787ac)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5cb5caa98Sdjl  * Common Development and Distribution License (the "License").
6cb5caa98Sdjl  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
212e145884Sraf 
227c478bd9Sstevel@tonic-gate /*
23*7257d1b4Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * getnetgrent.c
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  *	- name-service switch frontend routines for the netgroup API.
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * Policy decision:
357c478bd9Sstevel@tonic-gate  *	If netgroup A refers to netgroup B, both must occur in the same
367c478bd9Sstevel@tonic-gate  *	source (any other choice gives very confusing semantics).  This
377c478bd9Sstevel@tonic-gate  *	assumption is deeply embedded in the code below and in the backends.
387c478bd9Sstevel@tonic-gate  *
397c478bd9Sstevel@tonic-gate  * innetgr() is implemented on top of something called __multi_innetgr(),
407c478bd9Sstevel@tonic-gate  * which replaces each (char *) argument of innetgr() with a counted vector
417c478bd9Sstevel@tonic-gate  * of (char *).  The semantics are the same as an OR of the results of
427c478bd9Sstevel@tonic-gate  * innetgr() operations on each possible 4-tuple picked from the arguments,
437c478bd9Sstevel@tonic-gate  * but it's possible to implement some cases more efficiently.  This is
447c478bd9Sstevel@tonic-gate  * important for mountd, which used to read YP netgroup.byhost directly in
457c478bd9Sstevel@tonic-gate  * order to determine efficiently whether a given host belonged to any one
467c478bd9Sstevel@tonic-gate  * of a long list of netgroups.  Wildcarded arguments are indicated by a
477c478bd9Sstevel@tonic-gate  * count of zero.
487c478bd9Sstevel@tonic-gate  */
497c478bd9Sstevel@tonic-gate 
50*7257d1b4Sraf #include "lint.h"
517c478bd9Sstevel@tonic-gate #include <string.h>
527c478bd9Sstevel@tonic-gate #include <synch.h>
537c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
547c478bd9Sstevel@tonic-gate #include <mtlib.h>
557c478bd9Sstevel@tonic-gate #include <libc.h>
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root);
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate void
_nss_initf_netgroup(p)607c478bd9Sstevel@tonic-gate _nss_initf_netgroup(p)
617c478bd9Sstevel@tonic-gate 	nss_db_params_t	*p;
627c478bd9Sstevel@tonic-gate {
637c478bd9Sstevel@tonic-gate 	p->name	= NSS_DBNAM_NETGROUP;
647c478bd9Sstevel@tonic-gate 	p->default_config = NSS_DEFCONF_NETGROUP;
657c478bd9Sstevel@tonic-gate }
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /*
687c478bd9Sstevel@tonic-gate  * The netgroup routines aren't quite like the majority of the switch clients.
697c478bd9Sstevel@tonic-gate  *   innetgr() more-or-less fits the getXXXbyYYY mould, but for the others:
707c478bd9Sstevel@tonic-gate  *	- setnetgrent("netgroup") is really a getXXXbyYYY routine, i.e. it
717c478bd9Sstevel@tonic-gate  *	  searches the sources until it finds an entry with the given name.
727c478bd9Sstevel@tonic-gate  *	  Rather than returning the (potentially large) entry, it simply
737c478bd9Sstevel@tonic-gate  *	  initializes a cursor, and then...
747c478bd9Sstevel@tonic-gate  *      - getnetgrent(...) is repeatedly invoked by the user to extract the
757c478bd9Sstevel@tonic-gate  *	  contents of the entry found by setnetgrent().
767c478bd9Sstevel@tonic-gate  *	- endnetgrent() is almost like a real endXXXent routine.
77cb5caa98Sdjl  * The behaviour in NSS was:
787c478bd9Sstevel@tonic-gate  *  If we were certain that all the backends could provide netgroup information
797c478bd9Sstevel@tonic-gate  *  in a common form, we could make the setnetgrent() backend return the entire
807c478bd9Sstevel@tonic-gate  *  entry to the frontend, then implement getnetgrent() and endnetgrent()
817c478bd9Sstevel@tonic-gate  *  strictly in the frontend (aka here).  But we're not certain, so we won't.
82cb5caa98Sdjl  * In NSS2:
83cb5caa98Sdjl  *  Since nscd returns the results, and it is nscd that accumulates
84cb5caa98Sdjl  *  the results, then we can return the entire result on the setnetgrent.
857c478bd9Sstevel@tonic-gate  *
867c478bd9Sstevel@tonic-gate  * NOTE:
877c478bd9Sstevel@tonic-gate  *	In the SunOS 4.x (YP) version of this code, innetgr() did not
887c478bd9Sstevel@tonic-gate  *	affect the state of {set,get,end}netgrent().  Somewhere out
897c478bd9Sstevel@tonic-gate  *	there probably lurks a program that depends on this behaviour,
907c478bd9Sstevel@tonic-gate  *	so this version (both frontend and backends) had better
917c478bd9Sstevel@tonic-gate  *	behave the same way.
927c478bd9Sstevel@tonic-gate  */
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate /* ===> ?? fix "__" name */
957c478bd9Sstevel@tonic-gate int
__multi_innetgr(ngroup,pgroup,nhost,phost,nuser,puser,ndomain,pdomain)967c478bd9Sstevel@tonic-gate __multi_innetgr(ngroup,	pgroup,
977c478bd9Sstevel@tonic-gate 		nhost,	phost,
987c478bd9Sstevel@tonic-gate 		nuser,	puser,
997c478bd9Sstevel@tonic-gate 		ndomain, pdomain)
1007c478bd9Sstevel@tonic-gate 	nss_innetgr_argc	ngroup, nhost, nuser, ndomain;
1017c478bd9Sstevel@tonic-gate 	nss_innetgr_argv	pgroup, phost, puser, pdomain;
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate 	struct nss_innetgr_args	ia;
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	if (ngroup == 0) {
1067c478bd9Sstevel@tonic-gate 		return (0);	/* One thing fewer to worry backends */
1077c478bd9Sstevel@tonic-gate 	}
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	ia.groups.argc			= ngroup;
1107c478bd9Sstevel@tonic-gate 	ia.groups.argv			= pgroup;
1117c478bd9Sstevel@tonic-gate 	ia.arg[NSS_NETGR_MACHINE].argc	= nhost;
1127c478bd9Sstevel@tonic-gate 	ia.arg[NSS_NETGR_MACHINE].argv	= phost;
1137c478bd9Sstevel@tonic-gate 	ia.arg[NSS_NETGR_USER].argc	= nuser;
1147c478bd9Sstevel@tonic-gate 	ia.arg[NSS_NETGR_USER].argv	= puser;
1157c478bd9Sstevel@tonic-gate 	ia.arg[NSS_NETGR_DOMAIN].argc	= ndomain;
1167c478bd9Sstevel@tonic-gate 	ia.arg[NSS_NETGR_DOMAIN].argv	= pdomain;
1177c478bd9Sstevel@tonic-gate 	ia.status			= NSS_NETGR_NO;
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	(void) nss_search(&db_root, _nss_initf_netgroup,
1207c478bd9Sstevel@tonic-gate 	    NSS_DBOP_NETGROUP_IN, &ia);
1217c478bd9Sstevel@tonic-gate 	return (ia.status == NSS_NETGR_FOUND);
1227c478bd9Sstevel@tonic-gate }
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate int
innetgr(group,host,user,domain)1257c478bd9Sstevel@tonic-gate innetgr(group, host, user, domain)
1267c478bd9Sstevel@tonic-gate 	const char *group, *host, *user, *domain;
1277c478bd9Sstevel@tonic-gate {
1287c478bd9Sstevel@tonic-gate #define	IA(charp)	\
1297c478bd9Sstevel@tonic-gate 	(nss_innetgr_argc)((charp) != 0), (nss_innetgr_argv)(&(charp))
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	return (__multi_innetgr(IA(group), IA(host), IA(user), IA(domain)));
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate /*
1357c478bd9Sstevel@tonic-gate  * Context for setnetgrent()/getnetgrent().  If the user is being sensible
1367c478bd9Sstevel@tonic-gate  * the requests will be serialized anyway, but let's play safe and
1377c478bd9Sstevel@tonic-gate  * serialize them ourselves (anything to prevent a coredump)...
1387c478bd9Sstevel@tonic-gate  * We can't use lmutex_lock() here because we don't know what the backends
1397c478bd9Sstevel@tonic-gate  * that we call may call in turn.  They might call malloc()/free().
14098c1a6b4Sraf  * So we use the brute-force callout_lock_enter() instead.
1417c478bd9Sstevel@tonic-gate  */
1427c478bd9Sstevel@tonic-gate static nss_backend_t	*getnetgrent_backend;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate int
setnetgrent(const char * netgroup)1457c478bd9Sstevel@tonic-gate setnetgrent(const char *netgroup)
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate 	nss_backend_t	*be;
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	if (netgroup == NULL) {
1507c478bd9Sstevel@tonic-gate 		/* Prevent coredump, otherwise don't do anything profound */
1517c478bd9Sstevel@tonic-gate 		netgroup = "";
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 
15498c1a6b4Sraf 	callout_lock_enter();
1557c478bd9Sstevel@tonic-gate 	be = getnetgrent_backend;
1567c478bd9Sstevel@tonic-gate 	if (be != NULL && NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT,
1577c478bd9Sstevel@tonic-gate 	    (void *)netgroup) != NSS_SUCCESS) {
1587c478bd9Sstevel@tonic-gate 		(void) NSS_INVOKE_DBOP(be, NSS_DBOP_DESTRUCTOR, 0);
1597c478bd9Sstevel@tonic-gate 		be = NULL;
1607c478bd9Sstevel@tonic-gate 	}
1617c478bd9Sstevel@tonic-gate 	if (be == NULL) {
1627c478bd9Sstevel@tonic-gate 		struct nss_setnetgrent_args	args;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 		args.netgroup	= netgroup;
1657c478bd9Sstevel@tonic-gate 		args.iterator	= 0;
1667c478bd9Sstevel@tonic-gate 		(void) nss_search(&db_root, _nss_initf_netgroup,
1677c478bd9Sstevel@tonic-gate 		    NSS_DBOP_NETGROUP_SET, &args);
1687c478bd9Sstevel@tonic-gate 		be = args.iterator;
1697c478bd9Sstevel@tonic-gate 	}
1707c478bd9Sstevel@tonic-gate 	getnetgrent_backend = be;
17198c1a6b4Sraf 	callout_lock_exit();
1727c478bd9Sstevel@tonic-gate 	return (0);
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate int
getnetgrent_r(machinep,namep,domainp,buffer,buflen)1767c478bd9Sstevel@tonic-gate getnetgrent_r(machinep, namep, domainp, buffer, buflen)
1777c478bd9Sstevel@tonic-gate 	char		**machinep;
1787c478bd9Sstevel@tonic-gate 	char		**namep;
1797c478bd9Sstevel@tonic-gate 	char		**domainp;
1807c478bd9Sstevel@tonic-gate 	char		*buffer;
1817c478bd9Sstevel@tonic-gate 	int		buflen;
1827c478bd9Sstevel@tonic-gate {
1837c478bd9Sstevel@tonic-gate 	struct nss_getnetgrent_args	args;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	args.buffer	= buffer;
1867c478bd9Sstevel@tonic-gate 	args.buflen	= buflen;
1877c478bd9Sstevel@tonic-gate 	args.status	= NSS_NETGR_NO;
1887c478bd9Sstevel@tonic-gate 
18998c1a6b4Sraf 	callout_lock_enter();
1907c478bd9Sstevel@tonic-gate 	if (getnetgrent_backend != 0) {
1917c478bd9Sstevel@tonic-gate 		(void) NSS_INVOKE_DBOP(getnetgrent_backend,
1927c478bd9Sstevel@tonic-gate 			NSS_DBOP_GETENT, &args);
1937c478bd9Sstevel@tonic-gate 	}
19498c1a6b4Sraf 	callout_lock_exit();
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	if (args.status == NSS_NETGR_FOUND) {
1977c478bd9Sstevel@tonic-gate 		*machinep = args.retp[NSS_NETGR_MACHINE];
1987c478bd9Sstevel@tonic-gate 		*namep	  = args.retp[NSS_NETGR_USER];
1997c478bd9Sstevel@tonic-gate 		*domainp  = args.retp[NSS_NETGR_DOMAIN];
2007c478bd9Sstevel@tonic-gate 		return (1);
2017c478bd9Sstevel@tonic-gate 	} else {
2027c478bd9Sstevel@tonic-gate 		return (0);
2037c478bd9Sstevel@tonic-gate 	}
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate static nss_XbyY_buf_t *buf;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate int
getnetgrent(machinep,namep,domainp)2097c478bd9Sstevel@tonic-gate getnetgrent(machinep, namep, domainp)
2107c478bd9Sstevel@tonic-gate 	char		**machinep;
2117c478bd9Sstevel@tonic-gate 	char		**namep;
2127c478bd9Sstevel@tonic-gate 	char		**domainp;
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate 	(void) NSS_XbyY_ALLOC(&buf, 0, NSS_BUFLEN_NETGROUP);
2157c478bd9Sstevel@tonic-gate 	return (getnetgrent_r(machinep, namep, domainp,
2167c478bd9Sstevel@tonic-gate 	    buf->buffer, buf->buflen));
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate int
endnetgrent()2207c478bd9Sstevel@tonic-gate endnetgrent()
2217c478bd9Sstevel@tonic-gate {
22298c1a6b4Sraf 	callout_lock_enter();
2237c478bd9Sstevel@tonic-gate 	if (getnetgrent_backend != 0) {
2247c478bd9Sstevel@tonic-gate 		(void) NSS_INVOKE_DBOP(getnetgrent_backend,
2257c478bd9Sstevel@tonic-gate 		    NSS_DBOP_DESTRUCTOR, 0);
2267c478bd9Sstevel@tonic-gate 		getnetgrent_backend = 0;
2277c478bd9Sstevel@tonic-gate 	}
22898c1a6b4Sraf 	callout_lock_exit();
2297c478bd9Sstevel@tonic-gate 	nss_delete(&db_root);	/* === ? */
2307c478bd9Sstevel@tonic-gate 	NSS_XbyY_FREE(&buf);
2317c478bd9Sstevel@tonic-gate 	return (0);
2327c478bd9Sstevel@tonic-gate }
233