xref: /titanic_41/usr/src/lib/libc/port/gen/getnetgrent.c (revision 70025d765b044c6d8594bb965a2247a61e991a99)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * getnetgrent.c
31  *
32  *	- name-service switch frontend routines for the netgroup API.
33  *
34  * Policy decision:
35  *	If netgroup A refers to netgroup B, both must occur in the same
36  *	source (any other choice gives very confusing semantics).  This
37  *	assumption is deeply embedded in the code below and in the backends.
38  *
39  * innetgr() is implemented on top of something called __multi_innetgr(),
40  * which replaces each (char *) argument of innetgr() with a counted vector
41  * of (char *).  The semantics are the same as an OR of the results of
42  * innetgr() operations on each possible 4-tuple picked from the arguments,
43  * but it's possible to implement some cases more efficiently.  This is
44  * important for mountd, which used to read YP netgroup.byhost directly in
45  * order to determine efficiently whether a given host belonged to any one
46  * of a long list of netgroups.  Wildcarded arguments are indicated by a
47  * count of zero.
48  */
49 
50 #include "synonyms.h"
51 #include <string.h>
52 #include <synch.h>
53 #include <nss_dbdefs.h>
54 #include <mtlib.h>
55 #include <libc.h>
56 
57 static DEFINE_NSS_DB_ROOT(db_root);
58 
59 void
60 _nss_initf_netgroup(p)
61 	nss_db_params_t	*p;
62 {
63 	p->name	= NSS_DBNAM_NETGROUP;
64 	p->default_config = NSS_DEFCONF_NETGROUP;
65 }
66 
67 /*
68  * The netgroup routines aren't quite like the majority of the switch clients.
69  *   innetgr() more-or-less fits the getXXXbyYYY mould, but for the others:
70  *	- setnetgrent("netgroup") is really a getXXXbyYYY routine, i.e. it
71  *	  searches the sources until it finds an entry with the given name.
72  *	  Rather than returning the (potentially large) entry, it simply
73  *	  initializes a cursor, and then...
74  *      - getnetgrent(...) is repeatedly invoked by the user to extract the
75  *	  contents of the entry found by setnetgrent().
76  *	- endnetgrent() is almost like a real endXXXent routine.
77  * If we were certain that all the backends could provide netgroup information
78  * in a common form, we could make the setnetgrent() backend return the entire
79  * entry to the frontend, then implement getnetgrent() and endnetgrent()
80  * strictly in the frontend (aka here).  But we're not certain, so we won't.
81  *
82  * NOTE:
83  *	In the SunOS 4.x (YP) version of this code, innetgr() did not
84  *	affect the state of {set,get,end}netgrent().  Somewhere out
85  *	there probably lurks a program that depends on this behaviour,
86  *	so this version (both frontend and backends) had better
87  *	behave the same way.
88  */
89 
90 /* ===> ?? fix "__" name */
91 int
92 __multi_innetgr(ngroup,	pgroup,
93 		nhost,	phost,
94 		nuser,	puser,
95 		ndomain, pdomain)
96 	nss_innetgr_argc	ngroup, nhost, nuser, ndomain;
97 	nss_innetgr_argv	pgroup, phost, puser, pdomain;
98 {
99 	struct nss_innetgr_args	ia;
100 
101 	if (ngroup == 0) {
102 		return (0);	/* One thing fewer to worry backends */
103 	}
104 
105 	ia.groups.argc			= ngroup;
106 	ia.groups.argv			= pgroup;
107 	ia.arg[NSS_NETGR_MACHINE].argc	= nhost;
108 	ia.arg[NSS_NETGR_MACHINE].argv	= phost;
109 	ia.arg[NSS_NETGR_USER].argc	= nuser;
110 	ia.arg[NSS_NETGR_USER].argv	= puser;
111 	ia.arg[NSS_NETGR_DOMAIN].argc	= ndomain;
112 	ia.arg[NSS_NETGR_DOMAIN].argv	= pdomain;
113 	ia.status			= NSS_NETGR_NO;
114 
115 	(void) nss_search(&db_root, _nss_initf_netgroup,
116 	    NSS_DBOP_NETGROUP_IN, &ia);
117 	return (ia.status == NSS_NETGR_FOUND);
118 }
119 
120 int
121 innetgr(group, host, user, domain)
122 	const char *group, *host, *user, *domain;
123 {
124 #define	IA(charp)	\
125 	(nss_innetgr_argc)((charp) != 0), (nss_innetgr_argv)(&(charp))
126 
127 	return (__multi_innetgr(IA(group), IA(host), IA(user), IA(domain)));
128 }
129 
130 /*
131  * Context for setnetgrent()/getnetgrent().  If the user is being sensible
132  * the requests will be serialized anyway, but let's play safe and
133  * serialize them ourselves (anything to prevent a coredump)...
134  * We can't use lmutex_lock() here because we don't know what the backends
135  * that we call may call in turn.  They might call malloc()/free().
136  * So we use the brute-force fork_lock_enter() instead.
137  */
138 static nss_backend_t	*getnetgrent_backend;
139 
140 int
141 setnetgrent(const char *netgroup)
142 {
143 	nss_backend_t	*be;
144 
145 	if (netgroup == NULL) {
146 		/* Prevent coredump, otherwise don't do anything profound */
147 		netgroup = "";
148 	}
149 
150 	(void) fork_lock_enter(NULL);
151 	be = getnetgrent_backend;
152 	if (be != NULL && NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT,
153 	    (void *)netgroup) != NSS_SUCCESS) {
154 		(void) NSS_INVOKE_DBOP(be, NSS_DBOP_DESTRUCTOR, 0);
155 		be = NULL;
156 	}
157 	if (be == NULL) {
158 		struct nss_setnetgrent_args	args;
159 
160 		args.netgroup	= netgroup;
161 		args.iterator	= 0;
162 		(void) nss_search(&db_root, _nss_initf_netgroup,
163 		    NSS_DBOP_NETGROUP_SET, &args);
164 		be = args.iterator;
165 	}
166 	getnetgrent_backend = be;
167 	fork_lock_exit();
168 	return (0);
169 }
170 
171 int
172 getnetgrent_r(machinep, namep, domainp, buffer, buflen)
173 	char		**machinep;
174 	char		**namep;
175 	char		**domainp;
176 	char		*buffer;
177 	int		buflen;
178 {
179 	struct nss_getnetgrent_args	args;
180 
181 	args.buffer	= buffer;
182 	args.buflen	= buflen;
183 	args.status	= NSS_NETGR_NO;
184 
185 	(void) fork_lock_enter(NULL);
186 	if (getnetgrent_backend != 0) {
187 		(void) NSS_INVOKE_DBOP(getnetgrent_backend,
188 			NSS_DBOP_GETENT, &args);
189 	}
190 	fork_lock_exit();
191 
192 	if (args.status == NSS_NETGR_FOUND) {
193 		*machinep = args.retp[NSS_NETGR_MACHINE];
194 		*namep	  = args.retp[NSS_NETGR_USER];
195 		*domainp  = args.retp[NSS_NETGR_DOMAIN];
196 		return (1);
197 	} else {
198 		return (0);
199 	}
200 }
201 
202 static nss_XbyY_buf_t *buf;
203 
204 int
205 getnetgrent(machinep, namep, domainp)
206 	char		**machinep;
207 	char		**namep;
208 	char		**domainp;
209 {
210 	(void) NSS_XbyY_ALLOC(&buf, 0, NSS_BUFLEN_NETGROUP);
211 	return (getnetgrent_r(machinep, namep, domainp,
212 	    buf->buffer, buf->buflen));
213 }
214 
215 int
216 endnetgrent()
217 {
218 	(void) fork_lock_enter(NULL);
219 	if (getnetgrent_backend != 0) {
220 		(void) NSS_INVOKE_DBOP(getnetgrent_backend,
221 			NSS_DBOP_DESTRUCTOR, 0);
222 		getnetgrent_backend = 0;
223 	}
224 	fork_lock_exit();
225 	nss_delete(&db_root);	/* === ? */
226 	NSS_XbyY_FREE(&buf);
227 	return (0);
228 }
229