xref: /onnv-gate/usr/src/lib/nsswitch/ldap/common/getnetgrent.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <syslog.h>
30*0Sstevel@tonic-gate #include "ldap_common.h"
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate /* netgroup attributes filters */
33*0Sstevel@tonic-gate #define	_N_NAME			"cn"
34*0Sstevel@tonic-gate #define	_N_TRIPLE		"nisnetgrouptriple"
35*0Sstevel@tonic-gate #define	_N_MEMBER		"membernisnetgroup"
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #define	PRINT_VAL(a)		(((a).argc == 0) || ((a).argv == NULL) || \
38*0Sstevel@tonic-gate 				    ((a).argv[0] == NULL)) ? "*" : (a).argv[0]
39*0Sstevel@tonic-gate #define	ISWILD(a)		((a) == NULL)
40*0Sstevel@tonic-gate #define	GET_ARGV(a)		(((a).argc == 0) || ((a).argv == NULL) || \
41*0Sstevel@tonic-gate 				    ((a).argv[0] == NULL)) ? NULL : (a).argv[0]
42*0Sstevel@tonic-gate #define	ISNULL(a)		(a == NULL ? "<NULL>" : a)
43*0Sstevel@tonic-gate #define	MAX_NETGR_NAME_LEN	256
44*0Sstevel@tonic-gate #define	MAX_DOMAIN_LEN		1024
45*0Sstevel@tonic-gate #define	MAX_TRIPLE_LEN		(MAXHOSTNAMELEN + LOGNAME_MAX + \
46*0Sstevel@tonic-gate 					MAX_DOMAIN_LEN + 5)
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate #define	_F_GETNETGR_TRIPLE		\
49*0Sstevel@tonic-gate 	"(&(objectClass=nisNetGroup)"	\
50*0Sstevel@tonic-gate 		"(|(nisnetgrouptriple=(%s,%s,*))(nisnetgrouptriple=(%s,,*))" \
51*0Sstevel@tonic-gate 		"(nisnetgrouptriple=(,%s,*))(nisnetgrouptriple=(,,*))))"
52*0Sstevel@tonic-gate #define	_F_GETNETGR_TRIPLE_SSD		\
53*0Sstevel@tonic-gate 	"(&(%%s)(|(nisnetgrouptriple=(%s,%s,*))(nisnetgrouptriple=(%s,,*))" \
54*0Sstevel@tonic-gate 		"(nisnetgrouptriple=(,%s,*))(nisnetgrouptriple=(,,*))))"
55*0Sstevel@tonic-gate #define	_F_GETNETGR_TRIPLE_MACHINE	\
56*0Sstevel@tonic-gate 	"(&(objectClass=nisNetGroup)"	\
57*0Sstevel@tonic-gate 		"(|(nisnetgrouptriple=(%s,*,*))(nisnetgrouptriple=(,*,*))))"
58*0Sstevel@tonic-gate #define	_F_GETNETGR_TRIPLE_MACHINE_SSD	\
59*0Sstevel@tonic-gate 	"(&(%%s)(|(nisnetgrouptriple=(%s,*,*))(nisnetgrouptriple=(,*,*))))"
60*0Sstevel@tonic-gate #define	_F_GETNETGRENT		\
61*0Sstevel@tonic-gate 	"(&(objectClass=nisNetGroup)(nisnetgrouptriple=(%s,%s,%s)))"
62*0Sstevel@tonic-gate #define	_F_GETNETGRENT_SSD	\
63*0Sstevel@tonic-gate 	"(&(%%s)(nisnetgrouptriple=(%s,%s,%s)))"
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate /*
66*0Sstevel@tonic-gate  * Although the filter should include the test for (*,,*), this leads to
67*0Sstevel@tonic-gate  * an unindexed search. To support this, a plugin should be the directory
68*0Sstevel@tonic-gate  * server.
69*0Sstevel@tonic-gate  */
70*0Sstevel@tonic-gate #define	_F_GETNETGR_TRIPLE_USER		\
71*0Sstevel@tonic-gate 	"(&(objectClass=nisNetGroup)(nisnetgrouptriple=(*,%s,*)))"
72*0Sstevel@tonic-gate #define	_F_GETNETGR_TRIPLE_USER_SSD	\
73*0Sstevel@tonic-gate 	"(&(%%s)(nisnetgrouptriple=(*,%s,*)))"
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate #define	_F_GETMEMBERGRENT	\
76*0Sstevel@tonic-gate 	"(&(objectClass=nisNetGroup)(membernisnetgroup=%s))"
77*0Sstevel@tonic-gate #define	_F_GETMEMBERGRENT_SSD	\
78*0Sstevel@tonic-gate 	"(&(%%s)(membernisnetgroup=%s))"
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate #define	_F_ISMEMBERGRENT	\
81*0Sstevel@tonic-gate 	"(&(objectClass=nisNetGroup)(cn=%s)(membernisnetgroup=%s))"
82*0Sstevel@tonic-gate #define	_F_ISMEMBERGRENT_SSD	\
83*0Sstevel@tonic-gate 	"(&(%%s)(cn=%s)(membernisnetgroup=%s))"
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate #define	MAX_INNETGR_FILTER_LEN (2 * MAXHOSTNAMELEN + 2 * LOGNAME_MAX + 140)
86*0Sstevel@tonic-gate #define	MAX_GETMEM_FILTER_LEN (MAX_NETGR_NAME_LEN + 50)
87*0Sstevel@tonic-gate #define	MAX_ISMEM_FILTER_LEN (2 * MAX_NETGR_NAME_LEN + 56)
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate #define	_F_GETMEMBER		\
90*0Sstevel@tonic-gate 	"(&(objectClass=nisNetGroup)(membernisnetgroup=%s))"
91*0Sstevel@tonic-gate #define	_F_GETMEMBER_SSD	"(&(%%s)(membernisnetgroup=%s))"
92*0Sstevel@tonic-gate #define	_F_SETMEMBER		"(&(objectClass=nisNetGroup)(cn=%s))"
93*0Sstevel@tonic-gate #define	_F_SETMEMBER_SSD	"(&(%%s)(cn=%s))"
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate #define	N_HASH		257
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate static const char *netgrent_attrs[] = {
98*0Sstevel@tonic-gate 	_N_TRIPLE,
99*0Sstevel@tonic-gate 	_N_MEMBER,
100*0Sstevel@tonic-gate 	(char *)NULL
101*0Sstevel@tonic-gate };
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate static const char *netgr_name_attrs[] = {
104*0Sstevel@tonic-gate 	_N_NAME,
105*0Sstevel@tonic-gate 	(char *)NULL
106*0Sstevel@tonic-gate };
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate static const char *netgr_leaf_attrs[] = {
109*0Sstevel@tonic-gate 	_N_NAME,
110*0Sstevel@tonic-gate 	_N_TRIPLE,
111*0Sstevel@tonic-gate 	(char *)NULL
112*0Sstevel@tonic-gate };
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate static const char *netgr_node_attrs[] = {
115*0Sstevel@tonic-gate 	_N_NAME,
116*0Sstevel@tonic-gate 	_N_MEMBER,
117*0Sstevel@tonic-gate 	(char *)NULL
118*0Sstevel@tonic-gate };
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate typedef struct netgroup_name {
121*0Sstevel@tonic-gate 	char *name;
122*0Sstevel@tonic-gate 	struct netgroup_name *next;
123*0Sstevel@tonic-gate 	struct netgroup_name *next_hash;
124*0Sstevel@tonic-gate } netgroup_name_t;
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate typedef struct {
127*0Sstevel@tonic-gate 	netgroup_name_t *hash_list[N_HASH];
128*0Sstevel@tonic-gate 	netgroup_name_t *to_do;
129*0Sstevel@tonic-gate 	netgroup_name_t *done;
130*0Sstevel@tonic-gate } netgroup_table_t;
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate typedef struct {
133*0Sstevel@tonic-gate 	ns_ldap_result_t *results;
134*0Sstevel@tonic-gate 	ns_ldap_entry_t *entry;
135*0Sstevel@tonic-gate 	char **attrs;
136*0Sstevel@tonic-gate 	void *cookie;
137*0Sstevel@tonic-gate 	char *netgroup;
138*0Sstevel@tonic-gate 	netgroup_table_t tab;
139*0Sstevel@tonic-gate } getnetgrent_cookie_t;
140*0Sstevel@tonic-gate 
141*0Sstevel@tonic-gate typedef struct {
142*0Sstevel@tonic-gate 	struct nss_innetgr_args *ia;
143*0Sstevel@tonic-gate 	const char *ssd_filter;
144*0Sstevel@tonic-gate 	const char *netgrname;
145*0Sstevel@tonic-gate 	const char *membername;
146*0Sstevel@tonic-gate 	netgroup_table_t tab;
147*0Sstevel@tonic-gate } innetgr_cookie_t;
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate typedef unsigned int hash_t;
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate static hash_t
152*0Sstevel@tonic-gate get_hash(const char *s)
153*0Sstevel@tonic-gate {
154*0Sstevel@tonic-gate 	unsigned int sum = 0;
155*0Sstevel@tonic-gate 	unsigned int i;
156*0Sstevel@tonic-gate 
157*0Sstevel@tonic-gate 	for (i = 0; s[i] != '\0'; i++)
158*0Sstevel@tonic-gate 		sum += ((unsigned char *)s)[i];
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 	return ((sum + i) % N_HASH);
161*0Sstevel@tonic-gate }
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate static netgroup_name_t *
164*0Sstevel@tonic-gate in_netgroup_table(const char *name, netgroup_table_t *tab)
165*0Sstevel@tonic-gate {
166*0Sstevel@tonic-gate 	hash_t		h;
167*0Sstevel@tonic-gate 	netgroup_name_t *ret;
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate 	if (tab == NULL || name == NULL || *name == '\0')
170*0Sstevel@tonic-gate 		return (NULL);
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate 	h = get_hash(name);
173*0Sstevel@tonic-gate 	ret = tab->hash_list[h];
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 	while (ret != NULL) {
176*0Sstevel@tonic-gate 		if (strcmp(name, ret->name) == 0)
177*0Sstevel@tonic-gate 			break;
178*0Sstevel@tonic-gate 		ret = ret->next_hash;
179*0Sstevel@tonic-gate 	}
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate 	return (ret);
182*0Sstevel@tonic-gate }
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate /*
185*0Sstevel@tonic-gate  * Adds a name to the netgroup table
186*0Sstevel@tonic-gate  *
187*0Sstevel@tonic-gate  * Returns
188*0Sstevel@tonic-gate  *	0 if successfully added or already present
189*0Sstevel@tonic-gate  *	-1 if memory allocation error
190*0Sstevel@tonic-gate  */
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate static int
193*0Sstevel@tonic-gate add_netgroup_name(const char *name, netgroup_table_t *tab)
194*0Sstevel@tonic-gate {
195*0Sstevel@tonic-gate 	hash_t		h;
196*0Sstevel@tonic-gate 	netgroup_name_t	*ng;
197*0Sstevel@tonic-gate 	netgroup_name_t	*ng_new;
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate 	if (tab == NULL || name == NULL || *name == '\0')
200*0Sstevel@tonic-gate 	return (NULL);
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate 	h = get_hash(name);
203*0Sstevel@tonic-gate 	ng = tab->hash_list[h];
204*0Sstevel@tonic-gate 
205*0Sstevel@tonic-gate 	while (ng != NULL) {
206*0Sstevel@tonic-gate 		if (strcmp(name, ng->name) == 0)
207*0Sstevel@tonic-gate 			break;
208*0Sstevel@tonic-gate 		ng = ng->next_hash;
209*0Sstevel@tonic-gate 	}
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 	if (ng == NULL) {
212*0Sstevel@tonic-gate 		ng_new = (netgroup_name_t *)
213*0Sstevel@tonic-gate 			calloc(1, sizeof (netgroup_name_t));
214*0Sstevel@tonic-gate 		if (ng_new == NULL)
215*0Sstevel@tonic-gate 			return (-1);
216*0Sstevel@tonic-gate 		ng_new->name = strdup(name);
217*0Sstevel@tonic-gate 		if (ng_new->name == NULL) {
218*0Sstevel@tonic-gate 			free(ng_new);
219*0Sstevel@tonic-gate 			return (-1);
220*0Sstevel@tonic-gate 		}
221*0Sstevel@tonic-gate 		ng_new->next_hash = tab->hash_list[h];
222*0Sstevel@tonic-gate 		tab->hash_list[h] = ng_new;
223*0Sstevel@tonic-gate 		ng_new->next = tab->to_do;
224*0Sstevel@tonic-gate 		tab->to_do = ng_new;
225*0Sstevel@tonic-gate 	}
226*0Sstevel@tonic-gate 	return (0);
227*0Sstevel@tonic-gate }
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate static netgroup_name_t *
230*0Sstevel@tonic-gate get_next_netgroup(netgroup_table_t *tab)
231*0Sstevel@tonic-gate {
232*0Sstevel@tonic-gate 	netgroup_name_t *ng;
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate 	if (tab == NULL)
235*0Sstevel@tonic-gate 		return (NULL);
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 	ng = tab->to_do;
238*0Sstevel@tonic-gate 	if (ng != NULL) {
239*0Sstevel@tonic-gate 		tab->to_do = ng->next;
240*0Sstevel@tonic-gate 		ng->next = tab->done;
241*0Sstevel@tonic-gate 		tab->done = ng;
242*0Sstevel@tonic-gate 	}
243*0Sstevel@tonic-gate 	return (ng);
244*0Sstevel@tonic-gate }
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate static void
247*0Sstevel@tonic-gate free_netgroup_table(netgroup_table_t *tab)
248*0Sstevel@tonic-gate {
249*0Sstevel@tonic-gate 	netgroup_name_t *ng, *next;
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate 	if (tab == NULL)
252*0Sstevel@tonic-gate 		return;
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate 	for (ng = tab->to_do; ng != NULL; ng = next) {
255*0Sstevel@tonic-gate 		if (ng->name != NULL)
256*0Sstevel@tonic-gate 			free(ng->name);
257*0Sstevel@tonic-gate 		next = ng->next;
258*0Sstevel@tonic-gate 		free(ng);
259*0Sstevel@tonic-gate 	}
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate 	for (ng = tab->done; ng != NULL; ng = next) {
262*0Sstevel@tonic-gate 		if (ng->name != NULL)
263*0Sstevel@tonic-gate 			free(ng->name);
264*0Sstevel@tonic-gate 		next = ng->next;
265*0Sstevel@tonic-gate 		free(ng);
266*0Sstevel@tonic-gate 	}
267*0Sstevel@tonic-gate 	(void) memset(tab, 0, sizeof (*tab));
268*0Sstevel@tonic-gate }
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate /*
271*0Sstevel@tonic-gate  * domain comparing routine
272*0Sstevel@tonic-gate  * 	n1: See if n1 is n2 or an ancestor of it
273*0Sstevel@tonic-gate  * 	n2: (in string terms, n1 is a suffix of n2)
274*0Sstevel@tonic-gate  * Returns ZERO for success, -1 for failure.
275*0Sstevel@tonic-gate  */
276*0Sstevel@tonic-gate static int
277*0Sstevel@tonic-gate domcmp(const char *n1, const char *n2)
278*0Sstevel@tonic-gate {
279*0Sstevel@tonic-gate #define	PASS	0
280*0Sstevel@tonic-gate #define	FAIL	-1
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	size_t		l1, l2;
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 	if ((n1 == NULL) || (n2 == NULL))
285*0Sstevel@tonic-gate 		return (FAIL);
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate 	l1 = strlen(n1);
288*0Sstevel@tonic-gate 	l2 = strlen(n2);
289*0Sstevel@tonic-gate 
290*0Sstevel@tonic-gate 	/* Turn a blind eye to the presence or absence of trailing periods */
291*0Sstevel@tonic-gate 	if (l1 != 0 && n1[l1 - 1] == '.') {
292*0Sstevel@tonic-gate 		--l1;
293*0Sstevel@tonic-gate 	}
294*0Sstevel@tonic-gate 	if (l2 != 0 && n2[l2 - 1] == '.') {
295*0Sstevel@tonic-gate 		--l2;
296*0Sstevel@tonic-gate 	}
297*0Sstevel@tonic-gate 	if (l1 > l2) {		/* Can't be a suffix */
298*0Sstevel@tonic-gate 		return (FAIL);
299*0Sstevel@tonic-gate 	} else if (l1 == 0) {	/* Trivially a suffix; */
300*0Sstevel@tonic-gate 				/* (do we want this case?) */
301*0Sstevel@tonic-gate 		return (PASS);
302*0Sstevel@tonic-gate 	}
303*0Sstevel@tonic-gate 	/* So 0 < l1 <= l2 */
304*0Sstevel@tonic-gate 	if (l1 < l2 && n2[l2 - l1 - 1] != '.') {
305*0Sstevel@tonic-gate 		return (FAIL);
306*0Sstevel@tonic-gate 	}
307*0Sstevel@tonic-gate 	if (strncasecmp(n1, &n2[l2 - l1], l1) == 0) {
308*0Sstevel@tonic-gate 		return (PASS);
309*0Sstevel@tonic-gate 	} else {
310*0Sstevel@tonic-gate 		return (FAIL);
311*0Sstevel@tonic-gate 	}
312*0Sstevel@tonic-gate }
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate static int
315*0Sstevel@tonic-gate split_triple(char *triple, char **hostname, char **username, char **domain)
316*0Sstevel@tonic-gate {
317*0Sstevel@tonic-gate 	int	i, syntax_err;
318*0Sstevel@tonic-gate 	char	*splittriple[3];
319*0Sstevel@tonic-gate 	char	*p = triple;
320*0Sstevel@tonic-gate 
321*0Sstevel@tonic-gate #ifdef	DEBUG
322*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: split_triple]\n");
323*0Sstevel@tonic-gate #endif	/* DEBUG */
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate 	if (triple == NULL)
326*0Sstevel@tonic-gate 		return (-1);
327*0Sstevel@tonic-gate 
328*0Sstevel@tonic-gate 	p++;
329*0Sstevel@tonic-gate 	syntax_err = 0;
330*0Sstevel@tonic-gate 	for (i = 0; i < 3; i++) {
331*0Sstevel@tonic-gate 		char	*start;
332*0Sstevel@tonic-gate 		char	*limit;
333*0Sstevel@tonic-gate 		const char	*terminators = ",) \t";
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate 		if (i == 2) {
336*0Sstevel@tonic-gate 			/* Don't allow comma */
337*0Sstevel@tonic-gate 			terminators++;
338*0Sstevel@tonic-gate 		}
339*0Sstevel@tonic-gate 		while (isspace(*p)) {
340*0Sstevel@tonic-gate 			p++;
341*0Sstevel@tonic-gate 		}
342*0Sstevel@tonic-gate 		start = p;
343*0Sstevel@tonic-gate 		limit = strpbrk(start, terminators);
344*0Sstevel@tonic-gate 		if (limit == 0) {
345*0Sstevel@tonic-gate 			syntax_err++;
346*0Sstevel@tonic-gate 			break;
347*0Sstevel@tonic-gate 		}
348*0Sstevel@tonic-gate 		p = limit;
349*0Sstevel@tonic-gate 		while (isspace(*p)) {
350*0Sstevel@tonic-gate 			p++;
351*0Sstevel@tonic-gate 		}
352*0Sstevel@tonic-gate 		if (*p == terminators[0]) {
353*0Sstevel@tonic-gate 			/*
354*0Sstevel@tonic-gate 			 * Successfully parsed this name and
355*0Sstevel@tonic-gate 			 * the separator after it (comma or
356*0Sstevel@tonic-gate 			 * right paren); leave p ready for
357*0Sstevel@tonic-gate 			 * next parse.
358*0Sstevel@tonic-gate 			 */
359*0Sstevel@tonic-gate 			p++;
360*0Sstevel@tonic-gate 			if (start == limit) {
361*0Sstevel@tonic-gate 				/* Wildcard */
362*0Sstevel@tonic-gate 				splittriple[i] = NULL;
363*0Sstevel@tonic-gate 			} else {
364*0Sstevel@tonic-gate 				*limit = '\0';
365*0Sstevel@tonic-gate 				splittriple[i] = start;
366*0Sstevel@tonic-gate 			}
367*0Sstevel@tonic-gate 		} else {
368*0Sstevel@tonic-gate 			syntax_err++;
369*0Sstevel@tonic-gate 			break;
370*0Sstevel@tonic-gate 		}
371*0Sstevel@tonic-gate 	}
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 	if (syntax_err != 0)
374*0Sstevel@tonic-gate 		return (-1);
375*0Sstevel@tonic-gate 
376*0Sstevel@tonic-gate 	*hostname = splittriple[0];
377*0Sstevel@tonic-gate 	*username = splittriple[1];
378*0Sstevel@tonic-gate 	*domain = splittriple[2];
379*0Sstevel@tonic-gate 
380*0Sstevel@tonic-gate 	return (0);
381*0Sstevel@tonic-gate }
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate /*
384*0Sstevel@tonic-gate  * check the domain part of the triples.
385*0Sstevel@tonic-gate  *	-1 = fails to match, 0 = match
386*0Sstevel@tonic-gate  */
387*0Sstevel@tonic-gate 
388*0Sstevel@tonic-gate static int
389*0Sstevel@tonic-gate match_triple_entry(struct nss_innetgr_args *ia, const ns_ldap_entry_t *entry)
390*0Sstevel@tonic-gate {
391*0Sstevel@tonic-gate 	int	ndomains;
392*0Sstevel@tonic-gate 	char	**pdomains;
393*0Sstevel@tonic-gate 	int	nhost;
394*0Sstevel@tonic-gate 	char	**phost;
395*0Sstevel@tonic-gate 	int	nusers;
396*0Sstevel@tonic-gate 	char	**pusers;
397*0Sstevel@tonic-gate 	char	**attr;
398*0Sstevel@tonic-gate 	char	triple[MAX_TRIPLE_LEN];
399*0Sstevel@tonic-gate 	char	*tuser, *thost, *tdomain;
400*0Sstevel@tonic-gate 	int	i;
401*0Sstevel@tonic-gate 
402*0Sstevel@tonic-gate 	nhost = ia->arg[NSS_NETGR_MACHINE].argc;
403*0Sstevel@tonic-gate 	phost = (char **)ia->arg[NSS_NETGR_MACHINE].argv;
404*0Sstevel@tonic-gate 	if (phost == NULL || *phost == NULL)
405*0Sstevel@tonic-gate 		nhost = 0;
406*0Sstevel@tonic-gate 	nusers = ia->arg[NSS_NETGR_USER].argc;
407*0Sstevel@tonic-gate 	pusers = (char **)ia->arg[NSS_NETGR_USER].argv;
408*0Sstevel@tonic-gate 	if (pusers == NULL || *pusers == NULL)
409*0Sstevel@tonic-gate 		nusers = 0;
410*0Sstevel@tonic-gate 	ndomains = ia->arg[NSS_NETGR_DOMAIN].argc;
411*0Sstevel@tonic-gate 	pdomains = (char **)ia->arg[NSS_NETGR_DOMAIN].argv;
412*0Sstevel@tonic-gate 	if (pdomains == NULL || *pdomains == NULL)
413*0Sstevel@tonic-gate 		ndomains = 0;
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate 	attr = __ns_ldap_getAttr(entry, _N_TRIPLE);
416*0Sstevel@tonic-gate 	if (attr == NULL || *attr == NULL)
417*0Sstevel@tonic-gate 		return (0);
418*0Sstevel@tonic-gate 
419*0Sstevel@tonic-gate 	for (; *attr; attr++) {
420*0Sstevel@tonic-gate 	    if (strlcpy(triple, *attr, sizeof (triple)) >= sizeof (triple))
421*0Sstevel@tonic-gate 		continue;
422*0Sstevel@tonic-gate 	    if (split_triple(triple, &thost, &tuser, &tdomain) != 0)
423*0Sstevel@tonic-gate 		continue;
424*0Sstevel@tonic-gate 	    if (thost != NULL && *thost != '\0' && nhost != 0) {
425*0Sstevel@tonic-gate 		for (i = 0; i < nhost; i++)
426*0Sstevel@tonic-gate 		    if (strcasecmp(thost, phost[i]) == 0)
427*0Sstevel@tonic-gate 			break;
428*0Sstevel@tonic-gate 		if (i == nhost)
429*0Sstevel@tonic-gate 		    continue;
430*0Sstevel@tonic-gate 	    }
431*0Sstevel@tonic-gate 	    if (tuser != NULL && *tuser != '\0' && nusers != 0) {
432*0Sstevel@tonic-gate 		for (i = 0; i < nusers; i++)
433*0Sstevel@tonic-gate 		    if (strcmp(tuser, pusers[i]) == 0)
434*0Sstevel@tonic-gate 			break;
435*0Sstevel@tonic-gate 		if (i == nusers)
436*0Sstevel@tonic-gate 		    continue;
437*0Sstevel@tonic-gate 	    }
438*0Sstevel@tonic-gate 	    if (tdomain != NULL && *tdomain != '\0' && ndomains != 0) {
439*0Sstevel@tonic-gate 		for (i = 0; i < ndomains; i++)
440*0Sstevel@tonic-gate 		    if (domcmp(tdomain, pdomains[i]) == 0)
441*0Sstevel@tonic-gate 			break;
442*0Sstevel@tonic-gate 		if (i == ndomains)
443*0Sstevel@tonic-gate 		    continue;
444*0Sstevel@tonic-gate 	    }
445*0Sstevel@tonic-gate 	    return (1);
446*0Sstevel@tonic-gate 	}
447*0Sstevel@tonic-gate 
448*0Sstevel@tonic-gate 	return (0);
449*0Sstevel@tonic-gate }
450*0Sstevel@tonic-gate 
451*0Sstevel@tonic-gate static int
452*0Sstevel@tonic-gate match_triple(struct nss_innetgr_args *ia, ns_ldap_result_t *result)
453*0Sstevel@tonic-gate {
454*0Sstevel@tonic-gate 	ns_ldap_entry_t	*entry;
455*0Sstevel@tonic-gate 
456*0Sstevel@tonic-gate 	for (entry = result->entry; entry != NULL; entry = entry->next)
457*0Sstevel@tonic-gate 	    if (match_triple_entry(ia, entry) == 1)
458*0Sstevel@tonic-gate 		return (1);
459*0Sstevel@tonic-gate 
460*0Sstevel@tonic-gate 	return (0);
461*0Sstevel@tonic-gate }
462*0Sstevel@tonic-gate 
463*0Sstevel@tonic-gate static int
464*0Sstevel@tonic-gate add_netgroup_member_entry(ns_ldap_entry_t *entry, netgroup_table_t *tab)
465*0Sstevel@tonic-gate {
466*0Sstevel@tonic-gate 	char		**attrs;
467*0Sstevel@tonic-gate 	char		**a;
468*0Sstevel@tonic-gate 
469*0Sstevel@tonic-gate 	attrs = __ns_ldap_getAttr(entry, _N_MEMBER);
470*0Sstevel@tonic-gate 	if (attrs == NULL || *attrs == NULL)
471*0Sstevel@tonic-gate 		return (0);
472*0Sstevel@tonic-gate 
473*0Sstevel@tonic-gate 	for (a = attrs; *a != NULL; a++) {}
474*0Sstevel@tonic-gate 
475*0Sstevel@tonic-gate 	do {
476*0Sstevel@tonic-gate 		a--;
477*0Sstevel@tonic-gate 		if (add_netgroup_name(*a, tab) != 0)
478*0Sstevel@tonic-gate 			return (-1);
479*0Sstevel@tonic-gate 	} while (a > attrs);
480*0Sstevel@tonic-gate 	return (0);
481*0Sstevel@tonic-gate }
482*0Sstevel@tonic-gate 
483*0Sstevel@tonic-gate static int
484*0Sstevel@tonic-gate add_netgroup_member(ns_ldap_result_t *result, netgroup_table_t *tab)
485*0Sstevel@tonic-gate {
486*0Sstevel@tonic-gate 	ns_ldap_entry_t	*entry;
487*0Sstevel@tonic-gate 	int		ret = 0;
488*0Sstevel@tonic-gate 
489*0Sstevel@tonic-gate 	for (entry = result->entry; entry != NULL; entry = entry->next) {
490*0Sstevel@tonic-gate 	    ret = add_netgroup_member_entry(entry, tab);
491*0Sstevel@tonic-gate 	    if (ret != 0)
492*0Sstevel@tonic-gate 		break;
493*0Sstevel@tonic-gate 	}
494*0Sstevel@tonic-gate 	return (ret);
495*0Sstevel@tonic-gate }
496*0Sstevel@tonic-gate 
497*0Sstevel@tonic-gate /*
498*0Sstevel@tonic-gate  * top_down_search checks only checks the netgroup specified in netgrname
499*0Sstevel@tonic-gate  */
500*0Sstevel@tonic-gate static nss_status_t
501*0Sstevel@tonic-gate top_down_search(struct nss_innetgr_args *ia, char *netgrname)
502*0Sstevel@tonic-gate {
503*0Sstevel@tonic-gate 	char			searchfilter[SEARCHFILTERLEN];
504*0Sstevel@tonic-gate 	char			name[SEARCHFILTERLEN];
505*0Sstevel@tonic-gate 	char			userdata[SEARCHFILTERLEN];
506*0Sstevel@tonic-gate 	ns_ldap_result_t	*result = NULL;
507*0Sstevel@tonic-gate 	ns_ldap_error_t		*error = NULL;
508*0Sstevel@tonic-gate 	int			rc;
509*0Sstevel@tonic-gate 	void			*cookie = NULL;
510*0Sstevel@tonic-gate 	nss_status_t		status = NSS_NOTFOUND;
511*0Sstevel@tonic-gate 	netgroup_table_t	tab;
512*0Sstevel@tonic-gate 	netgroup_name_t		*ng;
513*0Sstevel@tonic-gate 	int			ret;
514*0Sstevel@tonic-gate 
515*0Sstevel@tonic-gate 	(void) memset(&tab, 0, sizeof (tab));
516*0Sstevel@tonic-gate 
517*0Sstevel@tonic-gate 	if (add_netgroup_name(netgrname, &tab) != 0)
518*0Sstevel@tonic-gate 	    return ((nss_status_t)NSS_NOTFOUND);
519*0Sstevel@tonic-gate 
520*0Sstevel@tonic-gate 	while ((ng = get_next_netgroup(&tab)) != NULL) {
521*0Sstevel@tonic-gate 	    if (_ldap_filter_name(name, ng->name, sizeof (name)) != 0)
522*0Sstevel@tonic-gate 		break;
523*0Sstevel@tonic-gate 	    ret = snprintf(searchfilter, sizeof (searchfilter), _F_SETMEMBER,
524*0Sstevel@tonic-gate 		    name);
525*0Sstevel@tonic-gate 	    if (ret >= sizeof (searchfilter) || ret < 0)
526*0Sstevel@tonic-gate 		break;
527*0Sstevel@tonic-gate 
528*0Sstevel@tonic-gate 	    ret = snprintf(userdata, sizeof (userdata), _F_SETMEMBER_SSD, name);
529*0Sstevel@tonic-gate 	    if (ret >= sizeof (userdata) || ret < 0)
530*0Sstevel@tonic-gate 		break;
531*0Sstevel@tonic-gate 
532*0Sstevel@tonic-gate 	    rc = __ns_ldap_firstEntry(_NETGROUP, searchfilter,
533*0Sstevel@tonic-gate 		_merge_SSD_filter, netgrent_attrs, NULL, 0, &cookie, &result,
534*0Sstevel@tonic-gate 		&error, userdata);
535*0Sstevel@tonic-gate 
536*0Sstevel@tonic-gate 	    (void) __ns_ldap_freeError(&error);
537*0Sstevel@tonic-gate 	    while (rc == NS_LDAP_SUCCESS && result != NULL) {
538*0Sstevel@tonic-gate 		if (match_triple(ia, result) == 1) {
539*0Sstevel@tonic-gate 		    /* We found a match */
540*0Sstevel@tonic-gate 		    ia->status = NSS_NETGR_FOUND;
541*0Sstevel@tonic-gate 		    status = NSS_SUCCESS;
542*0Sstevel@tonic-gate 		    break;
543*0Sstevel@tonic-gate 		}
544*0Sstevel@tonic-gate 
545*0Sstevel@tonic-gate 		rc = add_netgroup_member(result, &tab);
546*0Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&result);
547*0Sstevel@tonic-gate 
548*0Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS)
549*0Sstevel@tonic-gate 			break;
550*0Sstevel@tonic-gate 		rc = __ns_ldap_nextEntry(cookie, &result, &error);
551*0Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
552*0Sstevel@tonic-gate 	    }
553*0Sstevel@tonic-gate 	    (void) __ns_ldap_freeResult(&result);
554*0Sstevel@tonic-gate 	    (void) __ns_ldap_endEntry(&cookie, &error);
555*0Sstevel@tonic-gate 	    (void) __ns_ldap_freeError(&error);
556*0Sstevel@tonic-gate 
557*0Sstevel@tonic-gate 	    if (status == NSS_SUCCESS ||
558*0Sstevel@tonic-gate 			(rc != NS_LDAP_SUCCESS && rc != NS_LDAP_NOTFOUND))
559*0Sstevel@tonic-gate 		break;
560*0Sstevel@tonic-gate 	}
561*0Sstevel@tonic-gate 
562*0Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&result);
563*0Sstevel@tonic-gate 	(void) __ns_ldap_endEntry(&cookie, &error);
564*0Sstevel@tonic-gate 	(void) __ns_ldap_freeError(&error);
565*0Sstevel@tonic-gate 	free_netgroup_table(&tab);
566*0Sstevel@tonic-gate 	return (status);
567*0Sstevel@tonic-gate }
568*0Sstevel@tonic-gate 
569*0Sstevel@tonic-gate static int
570*0Sstevel@tonic-gate innetgr_SSD_filter(const ns_ldap_search_desc_t *desc, char **realfilter,
571*0Sstevel@tonic-gate 		const void *userdata)
572*0Sstevel@tonic-gate {
573*0Sstevel@tonic-gate 	const innetgr_cookie_t	*cookie = (innetgr_cookie_t *)userdata;
574*0Sstevel@tonic-gate 
575*0Sstevel@tonic-gate 	return (_merge_SSD_filter(desc, realfilter, cookie->ssd_filter));
576*0Sstevel@tonic-gate }
577*0Sstevel@tonic-gate 
578*0Sstevel@tonic-gate static int process_innetgr_node(const ns_ldap_entry_t *entry,
579*0Sstevel@tonic-gate 	const void *userdata);
580*0Sstevel@tonic-gate 
581*0Sstevel@tonic-gate /* return 1 when done, 0 otherwise */
582*0Sstevel@tonic-gate static int
583*0Sstevel@tonic-gate check_parent(const char *gr_name, innetgr_cookie_t *cookie)
584*0Sstevel@tonic-gate {
585*0Sstevel@tonic-gate 	ns_ldap_result_t	*result = NULL;
586*0Sstevel@tonic-gate 	ns_ldap_error_t		*error = NULL;
587*0Sstevel@tonic-gate 	char			searchfilter[MAX_GETMEM_FILTER_LEN];
588*0Sstevel@tonic-gate 	char			name[MAX_GETMEM_FILTER_LEN];
589*0Sstevel@tonic-gate 	char			ssd_filter[MAX_GETMEM_FILTER_LEN];
590*0Sstevel@tonic-gate 	const char		*ssd_filter_sav = cookie->ssd_filter;
591*0Sstevel@tonic-gate 	int			ret;
592*0Sstevel@tonic-gate 
593*0Sstevel@tonic-gate #ifdef DEBUG
594*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: check_parent:%s]\n", gr_name);
595*0Sstevel@tonic-gate #endif /* DEBUG */
596*0Sstevel@tonic-gate 
597*0Sstevel@tonic-gate 	if (_ldap_filter_name(name, gr_name, sizeof (name)) != 0)
598*0Sstevel@tonic-gate 		return (0);
599*0Sstevel@tonic-gate 	ret = snprintf(searchfilter, sizeof (searchfilter),
600*0Sstevel@tonic-gate 		    _F_GETMEMBERGRENT, name);
601*0Sstevel@tonic-gate 	if (ret >= sizeof (searchfilter) || ret < 0)
602*0Sstevel@tonic-gate 		return (0);
603*0Sstevel@tonic-gate 
604*0Sstevel@tonic-gate 	ret = snprintf(ssd_filter, sizeof (ssd_filter),
605*0Sstevel@tonic-gate 		    _F_GETMEMBERGRENT_SSD, name);
606*0Sstevel@tonic-gate 	if (ret >= sizeof (ssd_filter) || ret < 0)
607*0Sstevel@tonic-gate 		return (0);
608*0Sstevel@tonic-gate 
609*0Sstevel@tonic-gate 	cookie->ssd_filter = ssd_filter;
610*0Sstevel@tonic-gate 	cookie->membername = gr_name;
611*0Sstevel@tonic-gate 
612*0Sstevel@tonic-gate 	(void) __ns_ldap_list(_NETGROUP, searchfilter, innetgr_SSD_filter,
613*0Sstevel@tonic-gate 		netgr_node_attrs, NULL, 0, &result, &error,
614*0Sstevel@tonic-gate 		process_innetgr_node, cookie);
615*0Sstevel@tonic-gate 
616*0Sstevel@tonic-gate 	cookie->ssd_filter = ssd_filter_sav;
617*0Sstevel@tonic-gate 
618*0Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&result);
619*0Sstevel@tonic-gate 	(void) __ns_ldap_freeError(&error);
620*0Sstevel@tonic-gate 
621*0Sstevel@tonic-gate 	return (cookie->ia->status == NSS_NETGR_NO ? 0 : 1);
622*0Sstevel@tonic-gate }
623*0Sstevel@tonic-gate 
624*0Sstevel@tonic-gate /* Use the server's matching rule if not a case exact match */
625*0Sstevel@tonic-gate 
626*0Sstevel@tonic-gate static int
627*0Sstevel@tonic-gate server_match(innetgr_cookie_t *cookie)
628*0Sstevel@tonic-gate {
629*0Sstevel@tonic-gate 	ns_ldap_result_t	*result = NULL;
630*0Sstevel@tonic-gate 	ns_ldap_error_t		*error = NULL;
631*0Sstevel@tonic-gate 	char			searchfilter[MAX_ISMEM_FILTER_LEN];
632*0Sstevel@tonic-gate 	char			netgrname[MAX_ISMEM_FILTER_LEN];
633*0Sstevel@tonic-gate 	char			membername[MAX_ISMEM_FILTER_LEN];
634*0Sstevel@tonic-gate 	char			ssd_filter[MAX_ISMEM_FILTER_LEN];
635*0Sstevel@tonic-gate 	const char		*ssd_filter_sav = cookie->ssd_filter;
636*0Sstevel@tonic-gate 	int			rc;
637*0Sstevel@tonic-gate 	int			ret;
638*0Sstevel@tonic-gate 
639*0Sstevel@tonic-gate 	if (_ldap_filter_name(netgrname, cookie->netgrname,
640*0Sstevel@tonic-gate 		    sizeof (netgrname)) != 0)
641*0Sstevel@tonic-gate 		return (0);
642*0Sstevel@tonic-gate 	if (_ldap_filter_name(membername, cookie->membername,
643*0Sstevel@tonic-gate 		    sizeof (membername)) != 0)
644*0Sstevel@tonic-gate 		return (0);
645*0Sstevel@tonic-gate 	ret = snprintf(searchfilter, sizeof (searchfilter), _F_ISMEMBERGRENT,
646*0Sstevel@tonic-gate 		    netgrname, membername);
647*0Sstevel@tonic-gate 	if (ret >= sizeof (searchfilter) || ret < 0)
648*0Sstevel@tonic-gate 		return (0);
649*0Sstevel@tonic-gate 
650*0Sstevel@tonic-gate 	ret = snprintf(ssd_filter, sizeof (ssd_filter), _F_ISMEMBERGRENT_SSD,
651*0Sstevel@tonic-gate 		    netgrname, membername);
652*0Sstevel@tonic-gate 	if (ret >= sizeof (ssd_filter) || ret < 0)
653*0Sstevel@tonic-gate 		return (0);
654*0Sstevel@tonic-gate 
655*0Sstevel@tonic-gate 	cookie->ssd_filter = ssd_filter;
656*0Sstevel@tonic-gate 
657*0Sstevel@tonic-gate 	rc = __ns_ldap_list(_NETGROUP, searchfilter, innetgr_SSD_filter,
658*0Sstevel@tonic-gate 		netgr_name_attrs, NULL, 0, &result, &error,
659*0Sstevel@tonic-gate 		NULL, &cookie);
660*0Sstevel@tonic-gate 
661*0Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&result);
662*0Sstevel@tonic-gate 	(void) __ns_ldap_freeError(&error);
663*0Sstevel@tonic-gate 
664*0Sstevel@tonic-gate 	cookie->ssd_filter = ssd_filter_sav;
665*0Sstevel@tonic-gate 	return (rc == NS_LDAP_SUCCESS);
666*0Sstevel@tonic-gate }
667*0Sstevel@tonic-gate 
668*0Sstevel@tonic-gate static int
669*0Sstevel@tonic-gate process_innetgr_node(const ns_ldap_entry_t *entry, const void *userdata)
670*0Sstevel@tonic-gate {
671*0Sstevel@tonic-gate 	innetgr_cookie_t *cookie = (innetgr_cookie_t *)userdata;
672*0Sstevel@tonic-gate 	char **a, **attr;
673*0Sstevel@tonic-gate 
674*0Sstevel@tonic-gate 	attr = __ns_ldap_getAttr(entry, _N_NAME);
675*0Sstevel@tonic-gate 	if (attr == NULL)
676*0Sstevel@tonic-gate 	    return (NS_LDAP_CB_NEXT);
677*0Sstevel@tonic-gate 
678*0Sstevel@tonic-gate 	for (a = attr; *a; a++) {
679*0Sstevel@tonic-gate #ifdef DEBUG
680*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: process_innetgr_node:%s]\n",
681*0Sstevel@tonic-gate 		*a);
682*0Sstevel@tonic-gate #endif /* DEBUG */
683*0Sstevel@tonic-gate 
684*0Sstevel@tonic-gate 	    if (strcasecmp(*a, cookie->netgrname) == 0) {
685*0Sstevel@tonic-gate 		if (strcmp(*a, cookie->netgrname) == 0 ||
686*0Sstevel@tonic-gate 			server_match(cookie)) {
687*0Sstevel@tonic-gate 		    cookie->ia->status = NSS_NETGR_FOUND;
688*0Sstevel@tonic-gate 		    return (NS_LDAP_CB_DONE);
689*0Sstevel@tonic-gate 		}
690*0Sstevel@tonic-gate 	    }
691*0Sstevel@tonic-gate 	}
692*0Sstevel@tonic-gate 	for (a = attr; *a; a++) {
693*0Sstevel@tonic-gate 	    /* check if we have already visited this node */
694*0Sstevel@tonic-gate 	    if (in_netgroup_table(*a, &cookie->tab) != NULL)
695*0Sstevel@tonic-gate 		continue;
696*0Sstevel@tonic-gate 	    if (add_netgroup_name(*a, &cookie->tab) != 0) {
697*0Sstevel@tonic-gate 		cookie->ia->status = NSS_NETGR_NOMEM;
698*0Sstevel@tonic-gate 		return (NS_LDAP_CB_DONE);
699*0Sstevel@tonic-gate 	    }
700*0Sstevel@tonic-gate 	    if (check_parent(*a, cookie) == 1)
701*0Sstevel@tonic-gate 		return (NS_LDAP_CB_DONE);
702*0Sstevel@tonic-gate 	}
703*0Sstevel@tonic-gate 	return (NS_LDAP_CB_NEXT);
704*0Sstevel@tonic-gate }
705*0Sstevel@tonic-gate 
706*0Sstevel@tonic-gate static int
707*0Sstevel@tonic-gate process_innetgr_leaf(const ns_ldap_entry_t *entry, const void *userdata)
708*0Sstevel@tonic-gate {
709*0Sstevel@tonic-gate 	innetgr_cookie_t *cookie = (innetgr_cookie_t *)userdata;
710*0Sstevel@tonic-gate 
711*0Sstevel@tonic-gate 	/* Check to see if this entry matches the triple */
712*0Sstevel@tonic-gate 	if (match_triple_entry(cookie->ia, entry) != 1)
713*0Sstevel@tonic-gate 		return (NS_LDAP_CB_NEXT);
714*0Sstevel@tonic-gate 
715*0Sstevel@tonic-gate 	return (process_innetgr_node(entry, userdata));
716*0Sstevel@tonic-gate }
717*0Sstevel@tonic-gate 
718*0Sstevel@tonic-gate /*
719*0Sstevel@tonic-gate  * __netgr_in checks only checks the netgroup specified in ngroup
720*0Sstevel@tonic-gate  */
721*0Sstevel@tonic-gate static nss_status_t
722*0Sstevel@tonic-gate __netgr_in(void *a, char *netgrname)
723*0Sstevel@tonic-gate {
724*0Sstevel@tonic-gate 	struct nss_innetgr_args	*ia = (struct nss_innetgr_args *)a;
725*0Sstevel@tonic-gate 	char			searchfilter[MAX_INNETGR_FILTER_LEN];
726*0Sstevel@tonic-gate 	char			ssd_filter[MAX_INNETGR_FILTER_LEN];
727*0Sstevel@tonic-gate 	char			mach[MAX_INNETGR_FILTER_LEN];
728*0Sstevel@tonic-gate 	char			user[MAX_INNETGR_FILTER_LEN];
729*0Sstevel@tonic-gate 	ns_ldap_result_t	*result = NULL;
730*0Sstevel@tonic-gate 	ns_ldap_error_t		*error = NULL;
731*0Sstevel@tonic-gate 	int			rc;
732*0Sstevel@tonic-gate 	nss_status_t		status = NSS_NOTFOUND;
733*0Sstevel@tonic-gate 	innetgr_cookie_t	cookie = {NULL, NULL, NULL};
734*0Sstevel@tonic-gate 	int			user_wild, mach_wild;
735*0Sstevel@tonic-gate 	int			ret;
736*0Sstevel@tonic-gate 
737*0Sstevel@tonic-gate #ifdef DEBUG
738*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: netgr_in]\n");
739*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\tmachine: argc[%d]='%s' user: "
740*0Sstevel@tonic-gate 			    "argc[%d]='%s',\n\tdomain:argc[%d]='%s' "
741*0Sstevel@tonic-gate 			    "netgroup: argc[%d]='%s'\n",
742*0Sstevel@tonic-gate 			    NSS_NETGR_MACHINE,
743*0Sstevel@tonic-gate 			    PRINT_VAL(ia->arg[NSS_NETGR_MACHINE]),
744*0Sstevel@tonic-gate 			    NSS_NETGR_USER,
745*0Sstevel@tonic-gate 			    PRINT_VAL(ia->arg[NSS_NETGR_USER]),
746*0Sstevel@tonic-gate 			    NSS_NETGR_DOMAIN,
747*0Sstevel@tonic-gate 			    PRINT_VAL(ia->arg[NSS_NETGR_DOMAIN]),
748*0Sstevel@tonic-gate 			    NSS_NETGR_N,
749*0Sstevel@tonic-gate 			    PRINT_VAL(ia->arg[NSS_NETGR_N]));
750*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\tgroups='%s'\n", netgrname);
751*0Sstevel@tonic-gate #endif	/* DEBUG */
752*0Sstevel@tonic-gate 
753*0Sstevel@tonic-gate 	ia->status = NSS_NETGR_NO;
754*0Sstevel@tonic-gate 
755*0Sstevel@tonic-gate 	if (netgrname == NULL)
756*0Sstevel@tonic-gate 		return (status);
757*0Sstevel@tonic-gate 
758*0Sstevel@tonic-gate 	mach_wild = (ia->arg[NSS_NETGR_MACHINE].argc == 0) ||
759*0Sstevel@tonic-gate 	    (ia->arg[NSS_NETGR_MACHINE].argv == NULL) ||
760*0Sstevel@tonic-gate 	    (ia->arg[NSS_NETGR_MACHINE].argv[0] == NULL);
761*0Sstevel@tonic-gate 
762*0Sstevel@tonic-gate 	user_wild = (ia->arg[NSS_NETGR_USER].argc == 0) ||
763*0Sstevel@tonic-gate 	    (ia->arg[NSS_NETGR_USER].argv == NULL) ||
764*0Sstevel@tonic-gate 	    (ia->arg[NSS_NETGR_USER].argv[0] == NULL);
765*0Sstevel@tonic-gate 
766*0Sstevel@tonic-gate 	if (!mach_wild && _ldap_filter_name(mach,
767*0Sstevel@tonic-gate 	    ia->arg[NSS_NETGR_MACHINE].argv[0], sizeof (mach)) != 0)
768*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
769*0Sstevel@tonic-gate 
770*0Sstevel@tonic-gate 	if (!user_wild && _ldap_filter_name(user,
771*0Sstevel@tonic-gate 	    ia->arg[NSS_NETGR_USER].argv[0], sizeof (user)) != 0)
772*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
773*0Sstevel@tonic-gate 
774*0Sstevel@tonic-gate 	if (!mach_wild && !user_wild) {
775*0Sstevel@tonic-gate 	    ret = snprintf(searchfilter, sizeof (searchfilter),
776*0Sstevel@tonic-gate 			_F_GETNETGR_TRIPLE, mach, user, mach, user);
777*0Sstevel@tonic-gate 	    if (ret >= sizeof (searchfilter) || ret < 0)
778*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
779*0Sstevel@tonic-gate 
780*0Sstevel@tonic-gate 	    ret = snprintf(ssd_filter, sizeof (ssd_filter),
781*0Sstevel@tonic-gate 			_F_GETNETGR_TRIPLE_SSD, mach, user, mach, user);
782*0Sstevel@tonic-gate 	    if (ret >= sizeof (ssd_filter) || ret < 0)
783*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
784*0Sstevel@tonic-gate 	} else if (!mach_wild && user_wild) {
785*0Sstevel@tonic-gate 	    ret = snprintf(searchfilter, sizeof (searchfilter),
786*0Sstevel@tonic-gate 			_F_GETNETGR_TRIPLE_MACHINE, mach);
787*0Sstevel@tonic-gate 	    if (ret >= sizeof (searchfilter) || ret < 0)
788*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
789*0Sstevel@tonic-gate 
790*0Sstevel@tonic-gate 	    ret = snprintf(ssd_filter, sizeof (ssd_filter),
791*0Sstevel@tonic-gate 			_F_GETNETGR_TRIPLE_MACHINE_SSD, mach);
792*0Sstevel@tonic-gate 	    if (ret >= sizeof (ssd_filter) || ret < 0)
793*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
794*0Sstevel@tonic-gate 	} else if (mach_wild && !user_wild) {
795*0Sstevel@tonic-gate 	    ret = snprintf(searchfilter, sizeof (searchfilter),
796*0Sstevel@tonic-gate 			_F_GETNETGR_TRIPLE_USER, user);
797*0Sstevel@tonic-gate 	    if (ret >= sizeof (searchfilter) || ret < 0)
798*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
799*0Sstevel@tonic-gate 
800*0Sstevel@tonic-gate 	    ret = snprintf(ssd_filter, sizeof (ssd_filter),
801*0Sstevel@tonic-gate 			_F_GETNETGR_TRIPLE_USER_SSD, user);
802*0Sstevel@tonic-gate 	    if (ret >= sizeof (ssd_filter) || ret < 0)
803*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
804*0Sstevel@tonic-gate 	} else {
805*0Sstevel@tonic-gate 	    return (top_down_search(ia, netgrname));
806*0Sstevel@tonic-gate 	}
807*0Sstevel@tonic-gate 
808*0Sstevel@tonic-gate 	cookie.ia = ia;
809*0Sstevel@tonic-gate 	cookie.ssd_filter = ssd_filter;
810*0Sstevel@tonic-gate 	cookie.netgrname = netgrname;
811*0Sstevel@tonic-gate 	(void) memset(&cookie.tab, 0, sizeof (cookie.tab));
812*0Sstevel@tonic-gate 
813*0Sstevel@tonic-gate 	rc = __ns_ldap_list(_NETGROUP, searchfilter, innetgr_SSD_filter,
814*0Sstevel@tonic-gate 		netgr_leaf_attrs, NULL, 0, &result, &error,
815*0Sstevel@tonic-gate 		process_innetgr_leaf, &cookie);
816*0Sstevel@tonic-gate 	status = switch_err(rc, error);
817*0Sstevel@tonic-gate 
818*0Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&result);
819*0Sstevel@tonic-gate 	(void) __ns_ldap_freeError(&error);
820*0Sstevel@tonic-gate 	free_netgroup_table(&cookie.tab);
821*0Sstevel@tonic-gate 
822*0Sstevel@tonic-gate 	return (status);
823*0Sstevel@tonic-gate }
824*0Sstevel@tonic-gate 
825*0Sstevel@tonic-gate /*ARGSUSED0*/
826*0Sstevel@tonic-gate static nss_status_t
827*0Sstevel@tonic-gate netgr_in(ldap_backend_ptr be, void *a)
828*0Sstevel@tonic-gate {
829*0Sstevel@tonic-gate 	struct nss_innetgr_args	*ia = (struct nss_innetgr_args *)a;
830*0Sstevel@tonic-gate 	int	i;
831*0Sstevel@tonic-gate 	nss_status_t	rc = (nss_status_t)NSS_NOTFOUND;
832*0Sstevel@tonic-gate 
833*0Sstevel@tonic-gate 	ia->status = NSS_NETGR_NO;
834*0Sstevel@tonic-gate 	for (i = 0; i < ia->groups.argc; i++) {
835*0Sstevel@tonic-gate 		rc = __netgr_in(a, ia->groups.argv[i]);
836*0Sstevel@tonic-gate 		if (ia->status == NSS_NETGR_FOUND)
837*0Sstevel@tonic-gate 			return (NSS_SUCCESS);
838*0Sstevel@tonic-gate 	}
839*0Sstevel@tonic-gate 	return (rc);
840*0Sstevel@tonic-gate }
841*0Sstevel@tonic-gate 
842*0Sstevel@tonic-gate /*
843*0Sstevel@tonic-gate  *
844*0Sstevel@tonic-gate  */
845*0Sstevel@tonic-gate 
846*0Sstevel@tonic-gate static nss_status_t
847*0Sstevel@tonic-gate getnetgr_ldap_setent(ldap_backend_ptr be, void *a)
848*0Sstevel@tonic-gate {
849*0Sstevel@tonic-gate 	const char	*netgroup = (const char *) a;
850*0Sstevel@tonic-gate 	getnetgrent_cookie_t	*cookie;
851*0Sstevel@tonic-gate 
852*0Sstevel@tonic-gate #ifdef	DEBUG
853*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_setent]\n");
854*0Sstevel@tonic-gate #endif	/* DEBUG */
855*0Sstevel@tonic-gate 
856*0Sstevel@tonic-gate 	cookie = (getnetgrent_cookie_t *)be->netgroup_cookie;
857*0Sstevel@tonic-gate 	if (cookie != NULL && cookie->netgroup != NULL) {
858*0Sstevel@tonic-gate 		/* is this another set on the same netgroup */
859*0Sstevel@tonic-gate 		if (strcmp(cookie->netgroup, netgroup) == 0)
860*0Sstevel@tonic-gate 			return ((nss_status_t)NSS_SUCCESS);
861*0Sstevel@tonic-gate 	}
862*0Sstevel@tonic-gate 
863*0Sstevel@tonic-gate 	return (NSS_NOTFOUND);
864*0Sstevel@tonic-gate }
865*0Sstevel@tonic-gate 
866*0Sstevel@tonic-gate static void
867*0Sstevel@tonic-gate free_getnetgrent_cookie(getnetgrent_cookie_t **cookie)
868*0Sstevel@tonic-gate {
869*0Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
870*0Sstevel@tonic-gate 	getnetgrent_cookie_t *p = *cookie;
871*0Sstevel@tonic-gate 
872*0Sstevel@tonic-gate #ifdef DEBUG
873*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: free_getnetgrent_cookie]\n");
874*0Sstevel@tonic-gate #endif	/* DEBUG */
875*0Sstevel@tonic-gate 
876*0Sstevel@tonic-gate 	if (p == NULL)
877*0Sstevel@tonic-gate 		return;
878*0Sstevel@tonic-gate 
879*0Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&p->results);
880*0Sstevel@tonic-gate 	(void) __ns_ldap_endEntry(&p->cookie, &error);
881*0Sstevel@tonic-gate 	(void) __ns_ldap_freeError(&error);
882*0Sstevel@tonic-gate 	free_netgroup_table(&p->tab);
883*0Sstevel@tonic-gate 	free(p->netgroup);
884*0Sstevel@tonic-gate 	free(p);
885*0Sstevel@tonic-gate 	*cookie = NULL;
886*0Sstevel@tonic-gate }
887*0Sstevel@tonic-gate 
888*0Sstevel@tonic-gate /*ARGSUSED1*/
889*0Sstevel@tonic-gate static nss_status_t
890*0Sstevel@tonic-gate getnetgr_ldap_endent(ldap_backend_ptr be, void *a)
891*0Sstevel@tonic-gate {
892*0Sstevel@tonic-gate 
893*0Sstevel@tonic-gate #ifdef	DEBUG
894*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_endent]\n");
895*0Sstevel@tonic-gate #endif	/* DEBUG */
896*0Sstevel@tonic-gate 
897*0Sstevel@tonic-gate 	free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
898*0Sstevel@tonic-gate 
899*0Sstevel@tonic-gate 	return ((nss_status_t)NSS_NOTFOUND);
900*0Sstevel@tonic-gate }
901*0Sstevel@tonic-gate 
902*0Sstevel@tonic-gate 
903*0Sstevel@tonic-gate /*ARGSUSED1*/
904*0Sstevel@tonic-gate static nss_status_t
905*0Sstevel@tonic-gate getnetgr_ldap_destr(ldap_backend_ptr be, void *a)
906*0Sstevel@tonic-gate {
907*0Sstevel@tonic-gate 
908*0Sstevel@tonic-gate #ifdef	DEBUG
909*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_destr]\n");
910*0Sstevel@tonic-gate #endif	/* DEBUG */
911*0Sstevel@tonic-gate 
912*0Sstevel@tonic-gate 	free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
913*0Sstevel@tonic-gate 	free(be);
914*0Sstevel@tonic-gate 
915*0Sstevel@tonic-gate 	return ((nss_status_t)NSS_NOTFOUND);
916*0Sstevel@tonic-gate }
917*0Sstevel@tonic-gate 
918*0Sstevel@tonic-gate 
919*0Sstevel@tonic-gate static nss_status_t
920*0Sstevel@tonic-gate getnetgr_ldap_getent(ldap_backend_ptr be, void *a)
921*0Sstevel@tonic-gate {
922*0Sstevel@tonic-gate 	struct nss_getnetgrent_args	*args;
923*0Sstevel@tonic-gate 	getnetgrent_cookie_t	*p;
924*0Sstevel@tonic-gate 	char			searchfilter[SEARCHFILTERLEN];
925*0Sstevel@tonic-gate 	char			userdata[SEARCHFILTERLEN];
926*0Sstevel@tonic-gate 	char			name[SEARCHFILTERLEN];
927*0Sstevel@tonic-gate 	int			rc;
928*0Sstevel@tonic-gate 	void			*cookie = NULL;
929*0Sstevel@tonic-gate 	ns_ldap_result_t	*result = NULL;
930*0Sstevel@tonic-gate 	ns_ldap_error_t		*error = NULL;
931*0Sstevel@tonic-gate 	char			**attrs;
932*0Sstevel@tonic-gate 	char			*hostname, *username, *domain;
933*0Sstevel@tonic-gate 	char			*buffer;
934*0Sstevel@tonic-gate 	nss_status_t		status = NSS_SUCCESS;
935*0Sstevel@tonic-gate 	netgroup_name_t		*ng;
936*0Sstevel@tonic-gate 	int			ret;
937*0Sstevel@tonic-gate 
938*0Sstevel@tonic-gate #ifdef	DEBUG
939*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_getent]\n");
940*0Sstevel@tonic-gate #endif	/* DEBUG */
941*0Sstevel@tonic-gate 
942*0Sstevel@tonic-gate 	args = (struct nss_getnetgrent_args *)a;
943*0Sstevel@tonic-gate 
944*0Sstevel@tonic-gate 	args->status = NSS_NETGR_NO;
945*0Sstevel@tonic-gate 
946*0Sstevel@tonic-gate 	p = (getnetgrent_cookie_t *)be->netgroup_cookie;
947*0Sstevel@tonic-gate 	if (p == NULL)
948*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_SUCCESS);
949*0Sstevel@tonic-gate 
950*0Sstevel@tonic-gate 	for (;;) {
951*0Sstevel@tonic-gate 	    while (p->cookie == NULL) {
952*0Sstevel@tonic-gate 		ng = get_next_netgroup(&p->tab);
953*0Sstevel@tonic-gate 		if (ng == NULL)	 /* no more */
954*0Sstevel@tonic-gate 		    break;
955*0Sstevel@tonic-gate 
956*0Sstevel@tonic-gate 		if (_ldap_filter_name(name, ng->name, sizeof (name)) != 0)
957*0Sstevel@tonic-gate 			break;
958*0Sstevel@tonic-gate 
959*0Sstevel@tonic-gate 		ret = snprintf(searchfilter, sizeof (searchfilter),
960*0Sstevel@tonic-gate 			_F_SETMEMBER, name);
961*0Sstevel@tonic-gate 		if (ret >= sizeof (searchfilter) || ret < 0)
962*0Sstevel@tonic-gate 			break;
963*0Sstevel@tonic-gate 
964*0Sstevel@tonic-gate 		ret = snprintf(userdata, sizeof (userdata), _F_SETMEMBER_SSD,
965*0Sstevel@tonic-gate 			name);
966*0Sstevel@tonic-gate 		if (ret >= sizeof (userdata) || ret < 0)
967*0Sstevel@tonic-gate 			break;
968*0Sstevel@tonic-gate 
969*0Sstevel@tonic-gate 		result = NULL;
970*0Sstevel@tonic-gate 		rc = __ns_ldap_firstEntry(_NETGROUP, searchfilter,
971*0Sstevel@tonic-gate 			_merge_SSD_filter, netgrent_attrs, NULL, 0, &cookie,
972*0Sstevel@tonic-gate 			&result, &error, userdata);
973*0Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
974*0Sstevel@tonic-gate 
975*0Sstevel@tonic-gate 		if (rc == NS_LDAP_SUCCESS && result != NULL) {
976*0Sstevel@tonic-gate 			p->cookie = cookie;
977*0Sstevel@tonic-gate 			p->results = result;
978*0Sstevel@tonic-gate 			break;
979*0Sstevel@tonic-gate 		}
980*0Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&result);
981*0Sstevel@tonic-gate 		(void) __ns_ldap_endEntry(&cookie, &error);
982*0Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
983*0Sstevel@tonic-gate 	    }
984*0Sstevel@tonic-gate 	    if (p->cookie == NULL)
985*0Sstevel@tonic-gate 		break;
986*0Sstevel@tonic-gate 	    if (p->results == NULL) {
987*0Sstevel@tonic-gate 		result = NULL;
988*0Sstevel@tonic-gate 		rc = __ns_ldap_nextEntry(p->cookie, &result, &error);
989*0Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
990*0Sstevel@tonic-gate 		if (rc == NS_LDAP_SUCCESS && result != NULL)
991*0Sstevel@tonic-gate 			p->results = result;
992*0Sstevel@tonic-gate 		else {
993*0Sstevel@tonic-gate 		    (void) __ns_ldap_freeResult(&result);
994*0Sstevel@tonic-gate 		    (void) __ns_ldap_endEntry(&p->cookie, &error);
995*0Sstevel@tonic-gate 		    (void) __ns_ldap_freeError(&error);
996*0Sstevel@tonic-gate 		    p->cookie = NULL;
997*0Sstevel@tonic-gate 		}
998*0Sstevel@tonic-gate 	    }
999*0Sstevel@tonic-gate 	    if (p->results == NULL)
1000*0Sstevel@tonic-gate 		continue;
1001*0Sstevel@tonic-gate 
1002*0Sstevel@tonic-gate 	    if (p->entry == NULL)
1003*0Sstevel@tonic-gate 		p->entry = p->results->entry;
1004*0Sstevel@tonic-gate 
1005*0Sstevel@tonic-gate 	    if (p->entry == NULL)
1006*0Sstevel@tonic-gate 		continue;
1007*0Sstevel@tonic-gate 
1008*0Sstevel@tonic-gate 	    if (p->attrs == NULL) {
1009*0Sstevel@tonic-gate 		attrs = __ns_ldap_getAttr(p->entry, _N_TRIPLE);
1010*0Sstevel@tonic-gate 		if (attrs != NULL && *attrs != NULL)
1011*0Sstevel@tonic-gate 		    p->attrs = attrs;
1012*0Sstevel@tonic-gate 	    }
1013*0Sstevel@tonic-gate 
1014*0Sstevel@tonic-gate 	    if (p->attrs != NULL) {
1015*0Sstevel@tonic-gate 		attrs = p->attrs;
1016*0Sstevel@tonic-gate 		buffer = args->buffer;
1017*0Sstevel@tonic-gate 
1018*0Sstevel@tonic-gate 		if (strlcpy(buffer, *attrs, args->buflen) >= args->buflen) {
1019*0Sstevel@tonic-gate 		    status = NSS_STR_PARSE_ERANGE;
1020*0Sstevel@tonic-gate 		    break;
1021*0Sstevel@tonic-gate 		}
1022*0Sstevel@tonic-gate 
1023*0Sstevel@tonic-gate 		rc = split_triple(buffer, &hostname, &username, &domain);
1024*0Sstevel@tonic-gate 		attrs++;
1025*0Sstevel@tonic-gate 		if (attrs != NULL && *attrs != NULL)
1026*0Sstevel@tonic-gate 		    p->attrs = attrs;
1027*0Sstevel@tonic-gate 		else
1028*0Sstevel@tonic-gate 		    p->attrs = NULL;
1029*0Sstevel@tonic-gate 		if (rc == 0) {
1030*0Sstevel@tonic-gate 		    args->retp[NSS_NETGR_MACHINE] = hostname;
1031*0Sstevel@tonic-gate 		    args->retp[NSS_NETGR_USER] = username;
1032*0Sstevel@tonic-gate 		    args->retp[NSS_NETGR_DOMAIN] = domain;
1033*0Sstevel@tonic-gate 		    args->status = NSS_NETGR_FOUND;
1034*0Sstevel@tonic-gate 		    if (p->attrs != NULL)
1035*0Sstevel@tonic-gate 			break;
1036*0Sstevel@tonic-gate 		}
1037*0Sstevel@tonic-gate 	    }
1038*0Sstevel@tonic-gate 
1039*0Sstevel@tonic-gate 	    if (p->attrs == NULL) {
1040*0Sstevel@tonic-gate 		rc = add_netgroup_member_entry(p->entry, &p->tab);
1041*0Sstevel@tonic-gate 		if (rc != 0) {
1042*0Sstevel@tonic-gate 		    args->status = NSS_NETGR_NO;
1043*0Sstevel@tonic-gate 		    break;
1044*0Sstevel@tonic-gate 		}
1045*0Sstevel@tonic-gate 
1046*0Sstevel@tonic-gate 		p->entry = p->entry->next;
1047*0Sstevel@tonic-gate 		if (p->entry == NULL)
1048*0Sstevel@tonic-gate 		    (void) __ns_ldap_freeResult(&p->results);
1049*0Sstevel@tonic-gate 		if (args->status == NSS_NETGR_FOUND)
1050*0Sstevel@tonic-gate 		    break;
1051*0Sstevel@tonic-gate 	    }
1052*0Sstevel@tonic-gate 	}
1053*0Sstevel@tonic-gate 
1054*0Sstevel@tonic-gate 	return (status);
1055*0Sstevel@tonic-gate }
1056*0Sstevel@tonic-gate 
1057*0Sstevel@tonic-gate static ldap_backend_op_t getnetgroup_ops[] = {
1058*0Sstevel@tonic-gate 	getnetgr_ldap_destr,
1059*0Sstevel@tonic-gate 	getnetgr_ldap_endent,
1060*0Sstevel@tonic-gate 	getnetgr_ldap_setent,
1061*0Sstevel@tonic-gate 	getnetgr_ldap_getent,
1062*0Sstevel@tonic-gate };
1063*0Sstevel@tonic-gate 
1064*0Sstevel@tonic-gate /*
1065*0Sstevel@tonic-gate  *
1066*0Sstevel@tonic-gate  */
1067*0Sstevel@tonic-gate 
1068*0Sstevel@tonic-gate static nss_status_t
1069*0Sstevel@tonic-gate netgr_set(ldap_backend_ptr be, void *a)
1070*0Sstevel@tonic-gate {
1071*0Sstevel@tonic-gate 	struct nss_setnetgrent_args	*args =
1072*0Sstevel@tonic-gate 				(struct nss_setnetgrent_args *)a;
1073*0Sstevel@tonic-gate 	ldap_backend_ptr		get_be;
1074*0Sstevel@tonic-gate 	getnetgrent_cookie_t		*p;
1075*0Sstevel@tonic-gate 
1076*0Sstevel@tonic-gate #ifdef DEBUG
1077*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: netgr_set]\n");
1078*0Sstevel@tonic-gate 	(void) fprintf(stdout,
1079*0Sstevel@tonic-gate 		"\targs->netgroup: %s\n", ISNULL(args->netgroup));
1080*0Sstevel@tonic-gate #endif /* DEBUG */
1081*0Sstevel@tonic-gate 
1082*0Sstevel@tonic-gate 	if (args->netgroup == NULL)
1083*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
1084*0Sstevel@tonic-gate 
1085*0Sstevel@tonic-gate 	free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
1086*0Sstevel@tonic-gate 	p = (getnetgrent_cookie_t *)calloc(1, sizeof (getnetgrent_cookie_t));
1087*0Sstevel@tonic-gate 	if (p == NULL)
1088*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
1089*0Sstevel@tonic-gate 	p->netgroup = strdup(args->netgroup);
1090*0Sstevel@tonic-gate 	if (p->netgroup == NULL) {
1091*0Sstevel@tonic-gate 		free(p);
1092*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
1093*0Sstevel@tonic-gate 	}
1094*0Sstevel@tonic-gate 	if (add_netgroup_name(args->netgroup, &p->tab) == -1) {
1095*0Sstevel@tonic-gate 		free_getnetgrent_cookie(&p);
1096*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
1097*0Sstevel@tonic-gate 	}
1098*0Sstevel@tonic-gate 
1099*0Sstevel@tonic-gate 	/* now allocate and return iteration backend structure */
1100*0Sstevel@tonic-gate 	if ((get_be = (ldap_backend_ptr)malloc(sizeof (*get_be))) == NULL)
1101*0Sstevel@tonic-gate 		return (NSS_UNAVAIL);
1102*0Sstevel@tonic-gate 	get_be->ops = getnetgroup_ops;
1103*0Sstevel@tonic-gate 	get_be->nops = sizeof (getnetgroup_ops) / sizeof (getnetgroup_ops[0]);
1104*0Sstevel@tonic-gate 	get_be->tablename = NULL;
1105*0Sstevel@tonic-gate 	get_be->attrs = netgrent_attrs;
1106*0Sstevel@tonic-gate 	get_be->result = NULL;
1107*0Sstevel@tonic-gate 	get_be->ldapobj2ent = NULL;
1108*0Sstevel@tonic-gate 	get_be->setcalled = 1;
1109*0Sstevel@tonic-gate 	get_be->filter = NULL;
1110*0Sstevel@tonic-gate 	get_be->toglue = NULL;
1111*0Sstevel@tonic-gate 	get_be->enumcookie = NULL;
1112*0Sstevel@tonic-gate 	get_be->netgroup_cookie = p;
1113*0Sstevel@tonic-gate 	args->iterator = (nss_backend_t *)get_be;
1114*0Sstevel@tonic-gate 
1115*0Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
1116*0Sstevel@tonic-gate 
1117*0Sstevel@tonic-gate 	return (NSS_SUCCESS);
1118*0Sstevel@tonic-gate }
1119*0Sstevel@tonic-gate 
1120*0Sstevel@tonic-gate 
1121*0Sstevel@tonic-gate /*ARGSUSED1*/
1122*0Sstevel@tonic-gate static nss_status_t
1123*0Sstevel@tonic-gate netgr_ldap_destr(ldap_backend_ptr be, void *a)
1124*0Sstevel@tonic-gate {
1125*0Sstevel@tonic-gate 
1126*0Sstevel@tonic-gate #ifdef	DEBUG
1127*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: netgr_ldap_destr]\n");
1128*0Sstevel@tonic-gate #endif	/* DEBUG */
1129*0Sstevel@tonic-gate 
1130*0Sstevel@tonic-gate 	(void) _clean_ldap_backend(be);
1131*0Sstevel@tonic-gate 
1132*0Sstevel@tonic-gate 	return ((nss_status_t)NSS_NOTFOUND);
1133*0Sstevel@tonic-gate }
1134*0Sstevel@tonic-gate 
1135*0Sstevel@tonic-gate 
1136*0Sstevel@tonic-gate 
1137*0Sstevel@tonic-gate 
1138*0Sstevel@tonic-gate static ldap_backend_op_t netgroup_ops[] = {
1139*0Sstevel@tonic-gate 	netgr_ldap_destr,
1140*0Sstevel@tonic-gate 	0,
1141*0Sstevel@tonic-gate 	0,
1142*0Sstevel@tonic-gate 	0,
1143*0Sstevel@tonic-gate 	netgr_in,		/*	innetgr()	*/
1144*0Sstevel@tonic-gate 	netgr_set		/*	setnetgrent()	*/
1145*0Sstevel@tonic-gate };
1146*0Sstevel@tonic-gate 
1147*0Sstevel@tonic-gate 
1148*0Sstevel@tonic-gate /*
1149*0Sstevel@tonic-gate  * _nss_ldap_netgroup_constr is where life begins. This function calls the
1150*0Sstevel@tonic-gate  * generic ldap constructor function to define and build the abstract data
1151*0Sstevel@tonic-gate  * types required to support ldap operations.
1152*0Sstevel@tonic-gate  */
1153*0Sstevel@tonic-gate 
1154*0Sstevel@tonic-gate /*ARGSUSED0*/
1155*0Sstevel@tonic-gate nss_backend_t *
1156*0Sstevel@tonic-gate _nss_ldap_netgroup_constr(const char *dummy1, const char *dummy2,
1157*0Sstevel@tonic-gate 			const char *dummy3)
1158*0Sstevel@tonic-gate {
1159*0Sstevel@tonic-gate 
1160*0Sstevel@tonic-gate #ifdef	DEBUG
1161*0Sstevel@tonic-gate 	(void) fprintf(stdout,
1162*0Sstevel@tonic-gate 		    "\n[getnetgrent.c: _nss_ldap_netgroup_constr]\n");
1163*0Sstevel@tonic-gate #endif	/* DEBUG */
1164*0Sstevel@tonic-gate 
1165*0Sstevel@tonic-gate 	return ((nss_backend_t *)_nss_ldap_constr(netgroup_ops,
1166*0Sstevel@tonic-gate 		sizeof (netgroup_ops)/sizeof (netgroup_ops[0]), _NETGROUP,
1167*0Sstevel@tonic-gate 		netgrent_attrs, NULL));
1168*0Sstevel@tonic-gate }
1169