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
5e429788eSmj162486  * Common Development and Distribution License (the "License").
6e429788eSmj162486  * 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  */
217c478bd9Sstevel@tonic-gate /*
22*3d047983Smichen  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <syslog.h>
297c478bd9Sstevel@tonic-gate #include "ldap_common.h"
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /* netgroup attributes filters */
327c478bd9Sstevel@tonic-gate #define	_N_TRIPLE		"nisnetgrouptriple"
337c478bd9Sstevel@tonic-gate #define	_N_MEMBER		"membernisnetgroup"
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #define	PRINT_VAL(a)		(((a).argc == 0) || ((a).argv == NULL) || \
367c478bd9Sstevel@tonic-gate 				    ((a).argv[0] == NULL)) ? "*" : (a).argv[0]
377c478bd9Sstevel@tonic-gate #define	ISNULL(a)		(a == NULL ? "<NULL>" : a)
387c478bd9Sstevel@tonic-gate #define	MAX_DOMAIN_LEN		1024
397c478bd9Sstevel@tonic-gate #define	MAX_TRIPLE_LEN		(MAXHOSTNAMELEN + LOGNAME_MAX + \
407c478bd9Sstevel@tonic-gate 					MAX_DOMAIN_LEN + 5)
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #define	_F_SETMEMBER		"(&(objectClass=nisNetGroup)(cn=%s))"
437c478bd9Sstevel@tonic-gate #define	_F_SETMEMBER_SSD	"(&(%%s)(cn=%s))"
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #define	N_HASH		257
46e429788eSmj162486 #define	COMMA		','
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate static const char *netgrent_attrs[] = {
497c478bd9Sstevel@tonic-gate 	_N_TRIPLE,
507c478bd9Sstevel@tonic-gate 	_N_MEMBER,
517c478bd9Sstevel@tonic-gate 	(char *)NULL
527c478bd9Sstevel@tonic-gate };
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate typedef struct netgroup_name {
557c478bd9Sstevel@tonic-gate 	char *name;
567c478bd9Sstevel@tonic-gate 	struct netgroup_name *next;
577c478bd9Sstevel@tonic-gate 	struct netgroup_name *next_hash;
587c478bd9Sstevel@tonic-gate } netgroup_name_t;
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate typedef struct {
617c478bd9Sstevel@tonic-gate 	netgroup_name_t *hash_list[N_HASH];
627c478bd9Sstevel@tonic-gate 	netgroup_name_t *to_do;
637c478bd9Sstevel@tonic-gate 	netgroup_name_t *done;
647c478bd9Sstevel@tonic-gate } netgroup_table_t;
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate typedef struct {
677c478bd9Sstevel@tonic-gate 	ns_ldap_result_t *results;
687c478bd9Sstevel@tonic-gate 	ns_ldap_entry_t *entry;
697c478bd9Sstevel@tonic-gate 	char **attrs;
707c478bd9Sstevel@tonic-gate 	void *cookie;
717c478bd9Sstevel@tonic-gate 	char *netgroup;
727c478bd9Sstevel@tonic-gate 	netgroup_table_t tab;
737c478bd9Sstevel@tonic-gate } getnetgrent_cookie_t;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate typedef struct {
767c478bd9Sstevel@tonic-gate 	struct nss_innetgr_args *ia;
777c478bd9Sstevel@tonic-gate 	const char *ssd_filter;
787c478bd9Sstevel@tonic-gate 	const char *netgrname;
797c478bd9Sstevel@tonic-gate 	const char *membername;
807c478bd9Sstevel@tonic-gate 	netgroup_table_t tab;
817c478bd9Sstevel@tonic-gate } innetgr_cookie_t;
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate typedef unsigned int hash_t;
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate static hash_t
867c478bd9Sstevel@tonic-gate get_hash(const char *s)
877c478bd9Sstevel@tonic-gate {
887c478bd9Sstevel@tonic-gate 	unsigned int sum = 0;
897c478bd9Sstevel@tonic-gate 	unsigned int i;
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 	for (i = 0; s[i] != '\0'; i++)
927c478bd9Sstevel@tonic-gate 		sum += ((unsigned char *)s)[i];
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	return ((sum + i) % N_HASH);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate  * Adds a name to the netgroup table
997c478bd9Sstevel@tonic-gate  *
1007c478bd9Sstevel@tonic-gate  * Returns
1017c478bd9Sstevel@tonic-gate  *	0 if successfully added or already present
1027c478bd9Sstevel@tonic-gate  *	-1 if memory allocation error
1037c478bd9Sstevel@tonic-gate  */
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate static int
1067c478bd9Sstevel@tonic-gate add_netgroup_name(const char *name, netgroup_table_t *tab)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	hash_t		h;
1097c478bd9Sstevel@tonic-gate 	netgroup_name_t	*ng;
1107c478bd9Sstevel@tonic-gate 	netgroup_name_t	*ng_new;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	if (tab == NULL || name == NULL || *name == '\0')
1137c478bd9Sstevel@tonic-gate 	return (NULL);
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	h = get_hash(name);
1167c478bd9Sstevel@tonic-gate 	ng = tab->hash_list[h];
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	while (ng != NULL) {
1197c478bd9Sstevel@tonic-gate 		if (strcmp(name, ng->name) == 0)
1207c478bd9Sstevel@tonic-gate 			break;
1217c478bd9Sstevel@tonic-gate 		ng = ng->next_hash;
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	if (ng == NULL) {
1257c478bd9Sstevel@tonic-gate 		ng_new = (netgroup_name_t *)
1267c478bd9Sstevel@tonic-gate 		    calloc(1, sizeof (netgroup_name_t));
1277c478bd9Sstevel@tonic-gate 		if (ng_new == NULL)
1287c478bd9Sstevel@tonic-gate 			return (-1);
1297c478bd9Sstevel@tonic-gate 		ng_new->name = strdup(name);
1307c478bd9Sstevel@tonic-gate 		if (ng_new->name == NULL) {
1317c478bd9Sstevel@tonic-gate 			free(ng_new);
1327c478bd9Sstevel@tonic-gate 			return (-1);
1337c478bd9Sstevel@tonic-gate 		}
1347c478bd9Sstevel@tonic-gate 		ng_new->next_hash = tab->hash_list[h];
1357c478bd9Sstevel@tonic-gate 		tab->hash_list[h] = ng_new;
1367c478bd9Sstevel@tonic-gate 		ng_new->next = tab->to_do;
1377c478bd9Sstevel@tonic-gate 		tab->to_do = ng_new;
1387c478bd9Sstevel@tonic-gate 	}
1397c478bd9Sstevel@tonic-gate 	return (0);
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate static netgroup_name_t *
1437c478bd9Sstevel@tonic-gate get_next_netgroup(netgroup_table_t *tab)
1447c478bd9Sstevel@tonic-gate {
1457c478bd9Sstevel@tonic-gate 	netgroup_name_t *ng;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	if (tab == NULL)
1487c478bd9Sstevel@tonic-gate 		return (NULL);
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	ng = tab->to_do;
1517c478bd9Sstevel@tonic-gate 	if (ng != NULL) {
1527c478bd9Sstevel@tonic-gate 		tab->to_do = ng->next;
1537c478bd9Sstevel@tonic-gate 		ng->next = tab->done;
1547c478bd9Sstevel@tonic-gate 		tab->done = ng;
1557c478bd9Sstevel@tonic-gate 	}
1567c478bd9Sstevel@tonic-gate 	return (ng);
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate static void
1607c478bd9Sstevel@tonic-gate free_netgroup_table(netgroup_table_t *tab)
1617c478bd9Sstevel@tonic-gate {
1627c478bd9Sstevel@tonic-gate 	netgroup_name_t *ng, *next;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	if (tab == NULL)
1657c478bd9Sstevel@tonic-gate 		return;
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	for (ng = tab->to_do; ng != NULL; ng = next) {
1687c478bd9Sstevel@tonic-gate 		if (ng->name != NULL)
1697c478bd9Sstevel@tonic-gate 			free(ng->name);
1707c478bd9Sstevel@tonic-gate 		next = ng->next;
1717c478bd9Sstevel@tonic-gate 		free(ng);
1727c478bd9Sstevel@tonic-gate 	}
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 	for (ng = tab->done; ng != NULL; ng = next) {
1757c478bd9Sstevel@tonic-gate 		if (ng->name != NULL)
1767c478bd9Sstevel@tonic-gate 			free(ng->name);
1777c478bd9Sstevel@tonic-gate 		next = ng->next;
1787c478bd9Sstevel@tonic-gate 		free(ng);
1797c478bd9Sstevel@tonic-gate 	}
1807c478bd9Sstevel@tonic-gate 	(void) memset(tab, 0, sizeof (*tab));
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate  * domain comparing routine
1857c478bd9Sstevel@tonic-gate  * 	n1: See if n1 is n2 or an ancestor of it
1867c478bd9Sstevel@tonic-gate  * 	n2: (in string terms, n1 is a suffix of n2)
1877c478bd9Sstevel@tonic-gate  * Returns ZERO for success, -1 for failure.
1887c478bd9Sstevel@tonic-gate  */
1897c478bd9Sstevel@tonic-gate static int
1907c478bd9Sstevel@tonic-gate domcmp(const char *n1, const char *n2)
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate #define	PASS	0
1937c478bd9Sstevel@tonic-gate #define	FAIL	-1
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	size_t		l1, l2;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	if ((n1 == NULL) || (n2 == NULL))
1987c478bd9Sstevel@tonic-gate 		return (FAIL);
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	l1 = strlen(n1);
2017c478bd9Sstevel@tonic-gate 	l2 = strlen(n2);
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	/* Turn a blind eye to the presence or absence of trailing periods */
2047c478bd9Sstevel@tonic-gate 	if (l1 != 0 && n1[l1 - 1] == '.') {
2057c478bd9Sstevel@tonic-gate 		--l1;
2067c478bd9Sstevel@tonic-gate 	}
2077c478bd9Sstevel@tonic-gate 	if (l2 != 0 && n2[l2 - 1] == '.') {
2087c478bd9Sstevel@tonic-gate 		--l2;
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate 	if (l1 > l2) {		/* Can't be a suffix */
2117c478bd9Sstevel@tonic-gate 		return (FAIL);
2127c478bd9Sstevel@tonic-gate 	} else if (l1 == 0) {	/* Trivially a suffix; */
2137c478bd9Sstevel@tonic-gate 				/* (do we want this case?) */
2147c478bd9Sstevel@tonic-gate 		return (PASS);
2157c478bd9Sstevel@tonic-gate 	}
2167c478bd9Sstevel@tonic-gate 	/* So 0 < l1 <= l2 */
2177c478bd9Sstevel@tonic-gate 	if (l1 < l2 && n2[l2 - l1 - 1] != '.') {
2187c478bd9Sstevel@tonic-gate 		return (FAIL);
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate 	if (strncasecmp(n1, &n2[l2 - l1], l1) == 0) {
2217c478bd9Sstevel@tonic-gate 		return (PASS);
2227c478bd9Sstevel@tonic-gate 	} else {
2237c478bd9Sstevel@tonic-gate 		return (FAIL);
2247c478bd9Sstevel@tonic-gate 	}
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate static int
2287c478bd9Sstevel@tonic-gate split_triple(char *triple, char **hostname, char **username, char **domain)
2297c478bd9Sstevel@tonic-gate {
2307c478bd9Sstevel@tonic-gate 	int	i, syntax_err;
2317c478bd9Sstevel@tonic-gate 	char	*splittriple[3];
2327c478bd9Sstevel@tonic-gate 	char	*p = triple;
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate #ifdef	DEBUG
2357c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: split_triple]\n");
2367c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	if (triple == NULL)
2397c478bd9Sstevel@tonic-gate 		return (-1);
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	p++;
2427c478bd9Sstevel@tonic-gate 	syntax_err = 0;
2437c478bd9Sstevel@tonic-gate 	for (i = 0; i < 3; i++) {
2447c478bd9Sstevel@tonic-gate 		char	*start;
2457c478bd9Sstevel@tonic-gate 		char	*limit;
2467c478bd9Sstevel@tonic-gate 		const char	*terminators = ",) \t";
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 		if (i == 2) {
2497c478bd9Sstevel@tonic-gate 			/* Don't allow comma */
2507c478bd9Sstevel@tonic-gate 			terminators++;
2517c478bd9Sstevel@tonic-gate 		}
2527c478bd9Sstevel@tonic-gate 		while (isspace(*p)) {
2537c478bd9Sstevel@tonic-gate 			p++;
2547c478bd9Sstevel@tonic-gate 		}
2557c478bd9Sstevel@tonic-gate 		start = p;
2567c478bd9Sstevel@tonic-gate 		limit = strpbrk(start, terminators);
2577c478bd9Sstevel@tonic-gate 		if (limit == 0) {
2587c478bd9Sstevel@tonic-gate 			syntax_err++;
2597c478bd9Sstevel@tonic-gate 			break;
2607c478bd9Sstevel@tonic-gate 		}
2617c478bd9Sstevel@tonic-gate 		p = limit;
2627c478bd9Sstevel@tonic-gate 		while (isspace(*p)) {
2637c478bd9Sstevel@tonic-gate 			p++;
2647c478bd9Sstevel@tonic-gate 		}
2657c478bd9Sstevel@tonic-gate 		if (*p == terminators[0]) {
2667c478bd9Sstevel@tonic-gate 			/*
2677c478bd9Sstevel@tonic-gate 			 * Successfully parsed this name and
2687c478bd9Sstevel@tonic-gate 			 * the separator after it (comma or
2697c478bd9Sstevel@tonic-gate 			 * right paren); leave p ready for
2707c478bd9Sstevel@tonic-gate 			 * next parse.
2717c478bd9Sstevel@tonic-gate 			 */
2727c478bd9Sstevel@tonic-gate 			p++;
2737c478bd9Sstevel@tonic-gate 			if (start == limit) {
2747c478bd9Sstevel@tonic-gate 				/* Wildcard */
2757c478bd9Sstevel@tonic-gate 				splittriple[i] = NULL;
2767c478bd9Sstevel@tonic-gate 			} else {
2777c478bd9Sstevel@tonic-gate 				*limit = '\0';
2787c478bd9Sstevel@tonic-gate 				splittriple[i] = start;
2797c478bd9Sstevel@tonic-gate 			}
2807c478bd9Sstevel@tonic-gate 		} else {
2817c478bd9Sstevel@tonic-gate 			syntax_err++;
2827c478bd9Sstevel@tonic-gate 			break;
2837c478bd9Sstevel@tonic-gate 		}
2847c478bd9Sstevel@tonic-gate 	}
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	if (syntax_err != 0)
2877c478bd9Sstevel@tonic-gate 		return (-1);
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	*hostname = splittriple[0];
2907c478bd9Sstevel@tonic-gate 	*username = splittriple[1];
2917c478bd9Sstevel@tonic-gate 	*domain = splittriple[2];
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	return (0);
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate /*
297e429788eSmj162486  * Test membership in triple
298e429788eSmj162486  *	return 0 = no match
299e429788eSmj162486  *	return 1 = match
3007c478bd9Sstevel@tonic-gate  */
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate static int
3037c478bd9Sstevel@tonic-gate match_triple_entry(struct nss_innetgr_args *ia, const ns_ldap_entry_t *entry)
3047c478bd9Sstevel@tonic-gate {
3057c478bd9Sstevel@tonic-gate 	int	ndomains;
3067c478bd9Sstevel@tonic-gate 	char	**pdomains;
3077c478bd9Sstevel@tonic-gate 	int	nhost;
3087c478bd9Sstevel@tonic-gate 	char	**phost;
3097c478bd9Sstevel@tonic-gate 	int	nusers;
3107c478bd9Sstevel@tonic-gate 	char	**pusers;
3117c478bd9Sstevel@tonic-gate 	char	**attr;
3127c478bd9Sstevel@tonic-gate 	char	triple[MAX_TRIPLE_LEN];
3137c478bd9Sstevel@tonic-gate 	char	*tuser, *thost, *tdomain;
3147c478bd9Sstevel@tonic-gate 	int	i;
315e429788eSmj162486 	char	*current, *limit;
316e429788eSmj162486 	int	pulen, phlen;
317e429788eSmj162486 	char	*pusers0, *phost0;
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	nhost = ia->arg[NSS_NETGR_MACHINE].argc;
3207c478bd9Sstevel@tonic-gate 	phost = (char **)ia->arg[NSS_NETGR_MACHINE].argv;
321e429788eSmj162486 	if (phost == NULL || *phost == NULL) {
3227c478bd9Sstevel@tonic-gate 		nhost = 0;
323e429788eSmj162486 	} else {
324e429788eSmj162486 		phost0 = phost[0];
325e429788eSmj162486 		phlen = strlen(phost0);
326e429788eSmj162486 	}
3277c478bd9Sstevel@tonic-gate 	nusers = ia->arg[NSS_NETGR_USER].argc;
3287c478bd9Sstevel@tonic-gate 	pusers = (char **)ia->arg[NSS_NETGR_USER].argv;
329e429788eSmj162486 	if (pusers == NULL || *pusers == NULL) {
3307c478bd9Sstevel@tonic-gate 		nusers = 0;
331e429788eSmj162486 	} else {
332e429788eSmj162486 		pusers0 = pusers[0];
333e429788eSmj162486 		pulen = strlen(pusers0);
334e429788eSmj162486 	}
3357c478bd9Sstevel@tonic-gate 	ndomains = ia->arg[NSS_NETGR_DOMAIN].argc;
3367c478bd9Sstevel@tonic-gate 	pdomains = (char **)ia->arg[NSS_NETGR_DOMAIN].argv;
3377c478bd9Sstevel@tonic-gate 	if (pdomains == NULL || *pdomains == NULL)
3387c478bd9Sstevel@tonic-gate 		ndomains = 0;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	attr = __ns_ldap_getAttr(entry, _N_TRIPLE);
3417c478bd9Sstevel@tonic-gate 	if (attr == NULL || *attr == NULL)
3427c478bd9Sstevel@tonic-gate 		return (0);
3437c478bd9Sstevel@tonic-gate 
344e429788eSmj162486 	/* Special cases for speedup */
345e429788eSmj162486 	if (nusers == 1 && nhost == 0 && ndomains == 0) {
346e429788eSmj162486 		/* Special case for finding a single user in a netgroup */
3477c478bd9Sstevel@tonic-gate 		for (; *attr; attr++) {
348e429788eSmj162486 			/* jump to first comma and check next character */
349e429788eSmj162486 			current = *attr;
350e429788eSmj162486 			if ((current = strchr(current, COMMA)) == NULL)
351e429788eSmj162486 				continue;
352e429788eSmj162486 			current++;
353e429788eSmj162486 
354e429788eSmj162486 			/* skip whitespaces */
355e429788eSmj162486 			while (isspace(*current))
356e429788eSmj162486 				current++;
357e429788eSmj162486 
358e429788eSmj162486 			/* if user part is null, then treat as wildcard */
359e429788eSmj162486 			if (*current == COMMA)
360e429788eSmj162486 				return (1);
361e429788eSmj162486 
362e429788eSmj162486 			/* compare first character */
363e429788eSmj162486 			if (*pusers0 != *current)
364e429788eSmj162486 				continue;
365e429788eSmj162486 
366e429788eSmj162486 			/* limit username to COMMA */
367e429788eSmj162486 			if ((limit = strchr(current, COMMA)) == NULL)
368e429788eSmj162486 				continue;
369e429788eSmj162486 			*limit = '\0';
370e429788eSmj162486 
371e429788eSmj162486 			/* remove blanks before COMMA */
372e429788eSmj162486 			if ((limit = strpbrk(current, " \t")) != NULL)
373e429788eSmj162486 				*limit = '\0';
374e429788eSmj162486 
375e429788eSmj162486 			/* compare size of username */
376e429788eSmj162486 			if (pulen != strlen(current)) {
377e429788eSmj162486 				continue;
378e429788eSmj162486 			}
379e429788eSmj162486 
380e429788eSmj162486 			/* do actual compare */
381e429788eSmj162486 			if (strncmp(pusers0, current, pulen) == 0) {
382e429788eSmj162486 				return (1);
383e429788eSmj162486 			} else {
384e429788eSmj162486 				continue;
385e429788eSmj162486 			}
386e429788eSmj162486 		}
387e429788eSmj162486 	} else if (nusers == 0 && nhost == 1 && ndomains == 0) {
388e429788eSmj162486 		/* Special case for finding a single host in a netgroup */
389e429788eSmj162486 		for (; *attr; attr++) {
390e429788eSmj162486 
391e429788eSmj162486 			/* jump to first character and check */
392e429788eSmj162486 			current = *attr;
393e429788eSmj162486 			current++;
394e429788eSmj162486 
395e429788eSmj162486 			/* skip whitespaces */
396e429788eSmj162486 			while (isspace(*current))
397e429788eSmj162486 				current++;
398e429788eSmj162486 
399e429788eSmj162486 			/* if host part is null, then treat as wildcard */
400e429788eSmj162486 			if (*current == COMMA)
401e429788eSmj162486 				return (1);
402e429788eSmj162486 
403e429788eSmj162486 			/* limit hostname to COMMA */
404e429788eSmj162486 			if ((limit = strchr(current, COMMA)) == NULL)
405e429788eSmj162486 				continue;
406e429788eSmj162486 			*limit = '\0';
407e429788eSmj162486 
408e429788eSmj162486 			/* remove blanks before COMMA */
409e429788eSmj162486 			if ((limit = strpbrk(current, " \t")) != NULL)
410e429788eSmj162486 				*limit = '\0';
411e429788eSmj162486 
412e429788eSmj162486 			/* compare size of hostname */
413e429788eSmj162486 			if (phlen != strlen(current)) {
414e429788eSmj162486 				continue;
415e429788eSmj162486 			}
416e429788eSmj162486 
417e429788eSmj162486 			/* do actual compare */
418e429788eSmj162486 			if (strncasecmp(phost0, current, phlen) == 0) {
419e429788eSmj162486 				return (1);
420e429788eSmj162486 			} else {
421e429788eSmj162486 				continue;
422e429788eSmj162486 			}
423e429788eSmj162486 		}
424e429788eSmj162486 	} else {
425e429788eSmj162486 		for (; *attr; attr++) {
426e429788eSmj162486 			if (strlcpy(triple, *attr,
427e429788eSmj162486 			    sizeof (triple)) >= sizeof (triple))
4287c478bd9Sstevel@tonic-gate 				continue;
4297c478bd9Sstevel@tonic-gate 			if (split_triple(triple, &thost, &tuser, &tdomain) != 0)
4307c478bd9Sstevel@tonic-gate 				continue;
4317c478bd9Sstevel@tonic-gate 			if (thost != NULL && *thost != '\0' && nhost != 0) {
4327c478bd9Sstevel@tonic-gate 				for (i = 0; i < nhost; i++)
4337c478bd9Sstevel@tonic-gate 					if (strcasecmp(thost, phost[i]) == 0)
4347c478bd9Sstevel@tonic-gate 						break;
4357c478bd9Sstevel@tonic-gate 				if (i == nhost)
4367c478bd9Sstevel@tonic-gate 					continue;
4377c478bd9Sstevel@tonic-gate 			}
4387c478bd9Sstevel@tonic-gate 			if (tuser != NULL && *tuser != '\0' && nusers != 0) {
4397c478bd9Sstevel@tonic-gate 				for (i = 0; i < nusers; i++)
4407c478bd9Sstevel@tonic-gate 					if (strcmp(tuser, pusers[i]) == 0)
4417c478bd9Sstevel@tonic-gate 						break;
4427c478bd9Sstevel@tonic-gate 				if (i == nusers)
4437c478bd9Sstevel@tonic-gate 					continue;
4447c478bd9Sstevel@tonic-gate 			}
445e429788eSmj162486 			if (tdomain != NULL && *tdomain != '\0' &&
446e429788eSmj162486 			    ndomains != 0) {
4477c478bd9Sstevel@tonic-gate 				for (i = 0; i < ndomains; i++)
4487c478bd9Sstevel@tonic-gate 					if (domcmp(tdomain, pdomains[i]) == 0)
4497c478bd9Sstevel@tonic-gate 						break;
4507c478bd9Sstevel@tonic-gate 				if (i == ndomains)
4517c478bd9Sstevel@tonic-gate 					continue;
4527c478bd9Sstevel@tonic-gate 			}
4537c478bd9Sstevel@tonic-gate 			return (1);
4547c478bd9Sstevel@tonic-gate 		}
455e429788eSmj162486 	}
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	return (0);
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate static int
4617c478bd9Sstevel@tonic-gate match_triple(struct nss_innetgr_args *ia, ns_ldap_result_t *result)
4627c478bd9Sstevel@tonic-gate {
4637c478bd9Sstevel@tonic-gate 	ns_ldap_entry_t	*entry;
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	for (entry = result->entry; entry != NULL; entry = entry->next)
4667c478bd9Sstevel@tonic-gate 		if (match_triple_entry(ia, entry) == 1)
4677c478bd9Sstevel@tonic-gate 			return (1);
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	return (0);
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate static int
4737c478bd9Sstevel@tonic-gate add_netgroup_member_entry(ns_ldap_entry_t *entry, netgroup_table_t *tab)
4747c478bd9Sstevel@tonic-gate {
4757c478bd9Sstevel@tonic-gate 	char		**attrs;
4767c478bd9Sstevel@tonic-gate 	char		**a;
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	attrs = __ns_ldap_getAttr(entry, _N_MEMBER);
4797c478bd9Sstevel@tonic-gate 	if (attrs == NULL || *attrs == NULL)
4807c478bd9Sstevel@tonic-gate 		return (0);
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	for (a = attrs; *a != NULL; a++) {}
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	do {
4857c478bd9Sstevel@tonic-gate 		a--;
4867c478bd9Sstevel@tonic-gate 		if (add_netgroup_name(*a, tab) != 0)
4877c478bd9Sstevel@tonic-gate 			return (-1);
4887c478bd9Sstevel@tonic-gate 	} while (a > attrs);
4897c478bd9Sstevel@tonic-gate 	return (0);
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate static int
4937c478bd9Sstevel@tonic-gate add_netgroup_member(ns_ldap_result_t *result, netgroup_table_t *tab)
4947c478bd9Sstevel@tonic-gate {
4957c478bd9Sstevel@tonic-gate 	ns_ldap_entry_t	*entry;
4967c478bd9Sstevel@tonic-gate 	int		ret = 0;
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	for (entry = result->entry; entry != NULL; entry = entry->next) {
4997c478bd9Sstevel@tonic-gate 		ret = add_netgroup_member_entry(entry, tab);
5007c478bd9Sstevel@tonic-gate 		if (ret != 0)
5017c478bd9Sstevel@tonic-gate 			break;
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 	return (ret);
5047c478bd9Sstevel@tonic-gate }
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate /*
5077c478bd9Sstevel@tonic-gate  * top_down_search checks only checks the netgroup specified in netgrname
5087c478bd9Sstevel@tonic-gate  */
5097c478bd9Sstevel@tonic-gate static nss_status_t
5107c478bd9Sstevel@tonic-gate top_down_search(struct nss_innetgr_args *ia, char *netgrname)
5117c478bd9Sstevel@tonic-gate {
5127c478bd9Sstevel@tonic-gate 	char			searchfilter[SEARCHFILTERLEN];
5137c478bd9Sstevel@tonic-gate 	char			name[SEARCHFILTERLEN];
5147c478bd9Sstevel@tonic-gate 	char			userdata[SEARCHFILTERLEN];
5157c478bd9Sstevel@tonic-gate 	ns_ldap_result_t	*result = NULL;
5167c478bd9Sstevel@tonic-gate 	ns_ldap_error_t		*error = NULL;
5177c478bd9Sstevel@tonic-gate 	int			rc;
5187c478bd9Sstevel@tonic-gate 	void			*cookie = NULL;
5197c478bd9Sstevel@tonic-gate 	nss_status_t		status = NSS_NOTFOUND;
520*3d047983Smichen 	nss_status_t		status1;
5217c478bd9Sstevel@tonic-gate 	netgroup_table_t	tab;
5227c478bd9Sstevel@tonic-gate 	netgroup_name_t		*ng;
5237c478bd9Sstevel@tonic-gate 	int			ret;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	(void) memset(&tab, 0, sizeof (tab));
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 	if (add_netgroup_name(netgrname, &tab) != 0)
5287c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	while ((ng = get_next_netgroup(&tab)) != NULL) {
5317c478bd9Sstevel@tonic-gate 		if (_ldap_filter_name(name, ng->name, sizeof (name)) != 0)
5327c478bd9Sstevel@tonic-gate 			break;
533*3d047983Smichen 		ret = snprintf(searchfilter, sizeof (searchfilter),
534*3d047983Smichen 		    _F_SETMEMBER, name);
5357c478bd9Sstevel@tonic-gate 		if (ret >= sizeof (searchfilter) || ret < 0)
5367c478bd9Sstevel@tonic-gate 			break;
5377c478bd9Sstevel@tonic-gate 
538*3d047983Smichen 		ret = snprintf(userdata, sizeof (userdata), _F_SETMEMBER_SSD,
539*3d047983Smichen 		    name);
5407c478bd9Sstevel@tonic-gate 		if (ret >= sizeof (userdata) || ret < 0)
5417c478bd9Sstevel@tonic-gate 			break;
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 		rc = __ns_ldap_firstEntry(_NETGROUP, searchfilter,
544*3d047983Smichen 		    _merge_SSD_filter, netgrent_attrs, NULL, 0, &cookie,
545*3d047983Smichen 		    &result, &error, userdata);
546*3d047983Smichen 
547*3d047983Smichen 		if (error != NULL) {
548*3d047983Smichen 			status1 = switch_err(rc, error);
549*3d047983Smichen 			if (status1 == NSS_TRYAGAIN) {
550*3d047983Smichen 				(void) __ns_ldap_freeError(&error);
551*3d047983Smichen 				free_netgroup_table(&tab);
552*3d047983Smichen 				return (status1);
553*3d047983Smichen 			}
554*3d047983Smichen 		}
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
5577c478bd9Sstevel@tonic-gate 		while (rc == NS_LDAP_SUCCESS && result != NULL) {
5587c478bd9Sstevel@tonic-gate 			if (match_triple(ia, result) == 1) {
5597c478bd9Sstevel@tonic-gate 				/* We found a match */
5607c478bd9Sstevel@tonic-gate 				ia->status = NSS_NETGR_FOUND;
5617c478bd9Sstevel@tonic-gate 				status = NSS_SUCCESS;
5627c478bd9Sstevel@tonic-gate 				break;
5637c478bd9Sstevel@tonic-gate 			}
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 			rc = add_netgroup_member(result, &tab);
5667c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeResult(&result);
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 			if (rc != NS_LDAP_SUCCESS)
5697c478bd9Sstevel@tonic-gate 				break;
5707c478bd9Sstevel@tonic-gate 			rc = __ns_ldap_nextEntry(cookie, &result, &error);
571*3d047983Smichen 			if (error != NULL) {
572*3d047983Smichen 				status1 = switch_err(rc, error);
573*3d047983Smichen 				if (status1 == NSS_TRYAGAIN) {
574*3d047983Smichen 					free_netgroup_table(&tab);
575*3d047983Smichen 					(void) __ns_ldap_freeError(&error);
576*3d047983Smichen 					(void) __ns_ldap_endEntry(&cookie,
577*3d047983Smichen 					    &error);
578*3d047983Smichen 					(void) __ns_ldap_freeError(&error);
579*3d047983Smichen 					return (status1);
580*3d047983Smichen 				}
581*3d047983Smichen 			}
5827c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeError(&error);
5837c478bd9Sstevel@tonic-gate 		}
5847c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&result);
5857c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_endEntry(&cookie, &error);
5867c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 		if (status == NSS_SUCCESS ||
5897c478bd9Sstevel@tonic-gate 		    (rc != NS_LDAP_SUCCESS && rc != NS_LDAP_NOTFOUND))
5907c478bd9Sstevel@tonic-gate 		break;
5917c478bd9Sstevel@tonic-gate 	}
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&result);
5947c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_endEntry(&cookie, &error);
5957c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeError(&error);
5967c478bd9Sstevel@tonic-gate 	free_netgroup_table(&tab);
5977c478bd9Sstevel@tonic-gate 	return (status);
5987c478bd9Sstevel@tonic-gate }
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate /*
6017c478bd9Sstevel@tonic-gate  * __netgr_in checks only checks the netgroup specified in ngroup
6027c478bd9Sstevel@tonic-gate  */
6037c478bd9Sstevel@tonic-gate static nss_status_t
6047c478bd9Sstevel@tonic-gate __netgr_in(void *a, char *netgrname)
6057c478bd9Sstevel@tonic-gate {
6067c478bd9Sstevel@tonic-gate 	struct nss_innetgr_args	*ia = (struct nss_innetgr_args *)a;
6077c478bd9Sstevel@tonic-gate 	nss_status_t		status = NSS_NOTFOUND;
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate #ifdef DEBUG
6107c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: netgr_in]\n");
6117c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\tmachine: argc[%d]='%s' user: "
6127c478bd9Sstevel@tonic-gate 	    "argc[%d]='%s',\n\tdomain:argc[%d]='%s' "
6137c478bd9Sstevel@tonic-gate 	    "netgroup: argc[%d]='%s'\n",
6147c478bd9Sstevel@tonic-gate 	    NSS_NETGR_MACHINE,
6157c478bd9Sstevel@tonic-gate 	    PRINT_VAL(ia->arg[NSS_NETGR_MACHINE]),
6167c478bd9Sstevel@tonic-gate 	    NSS_NETGR_USER,
6177c478bd9Sstevel@tonic-gate 	    PRINT_VAL(ia->arg[NSS_NETGR_USER]),
6187c478bd9Sstevel@tonic-gate 	    NSS_NETGR_DOMAIN,
6197c478bd9Sstevel@tonic-gate 	    PRINT_VAL(ia->arg[NSS_NETGR_DOMAIN]),
6207c478bd9Sstevel@tonic-gate 	    NSS_NETGR_N,
6217c478bd9Sstevel@tonic-gate 	    PRINT_VAL(ia->arg[NSS_NETGR_N]));
6227c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\tgroups='%s'\n", netgrname);
6237c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate 	ia->status = NSS_NETGR_NO;
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	if (netgrname == NULL)
6287c478bd9Sstevel@tonic-gate 		return (status);
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 	return (top_down_search(ia, netgrname));
6317c478bd9Sstevel@tonic-gate }
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate /*ARGSUSED0*/
6347c478bd9Sstevel@tonic-gate static nss_status_t
6357c478bd9Sstevel@tonic-gate netgr_in(ldap_backend_ptr be, void *a)
6367c478bd9Sstevel@tonic-gate {
6377c478bd9Sstevel@tonic-gate 	struct nss_innetgr_args	*ia = (struct nss_innetgr_args *)a;
6387c478bd9Sstevel@tonic-gate 	int	i;
6397c478bd9Sstevel@tonic-gate 	nss_status_t	rc = (nss_status_t)NSS_NOTFOUND;
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	ia->status = NSS_NETGR_NO;
6427c478bd9Sstevel@tonic-gate 	for (i = 0; i < ia->groups.argc; i++) {
6437c478bd9Sstevel@tonic-gate 		rc = __netgr_in(a, ia->groups.argv[i]);
6447c478bd9Sstevel@tonic-gate 		if (ia->status == NSS_NETGR_FOUND)
6457c478bd9Sstevel@tonic-gate 			return (NSS_SUCCESS);
6467c478bd9Sstevel@tonic-gate 	}
6477c478bd9Sstevel@tonic-gate 	return (rc);
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate /*
6517c478bd9Sstevel@tonic-gate  *
6527c478bd9Sstevel@tonic-gate  */
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate static nss_status_t
6557c478bd9Sstevel@tonic-gate getnetgr_ldap_setent(ldap_backend_ptr be, void *a)
6567c478bd9Sstevel@tonic-gate {
6577c478bd9Sstevel@tonic-gate 	const char	*netgroup = (const char *) a;
6587c478bd9Sstevel@tonic-gate 	getnetgrent_cookie_t	*cookie;
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate #ifdef	DEBUG
6617c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_setent]\n");
6627c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	cookie = (getnetgrent_cookie_t *)be->netgroup_cookie;
6657c478bd9Sstevel@tonic-gate 	if (cookie != NULL && cookie->netgroup != NULL) {
6667c478bd9Sstevel@tonic-gate 		/* is this another set on the same netgroup */
6677c478bd9Sstevel@tonic-gate 		if (strcmp(cookie->netgroup, netgroup) == 0)
6687c478bd9Sstevel@tonic-gate 			return ((nss_status_t)NSS_SUCCESS);
6697c478bd9Sstevel@tonic-gate 	}
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 	return (NSS_NOTFOUND);
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate static void
6757c478bd9Sstevel@tonic-gate free_getnetgrent_cookie(getnetgrent_cookie_t **cookie)
6767c478bd9Sstevel@tonic-gate {
6777c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
6787c478bd9Sstevel@tonic-gate 	getnetgrent_cookie_t *p = *cookie;
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate #ifdef DEBUG
6817c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: free_getnetgrent_cookie]\n");
6827c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	if (p == NULL)
6857c478bd9Sstevel@tonic-gate 		return;
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&p->results);
6887c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_endEntry(&p->cookie, &error);
6897c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeError(&error);
6907c478bd9Sstevel@tonic-gate 	free_netgroup_table(&p->tab);
6917c478bd9Sstevel@tonic-gate 	free(p->netgroup);
6927c478bd9Sstevel@tonic-gate 	free(p);
6937c478bd9Sstevel@tonic-gate 	*cookie = NULL;
6947c478bd9Sstevel@tonic-gate }
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
6977c478bd9Sstevel@tonic-gate static nss_status_t
6987c478bd9Sstevel@tonic-gate getnetgr_ldap_endent(ldap_backend_ptr be, void *a)
6997c478bd9Sstevel@tonic-gate {
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate #ifdef	DEBUG
7027c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_endent]\n");
7037c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 	free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_NOTFOUND);
7087c478bd9Sstevel@tonic-gate }
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
7127c478bd9Sstevel@tonic-gate static nss_status_t
7137c478bd9Sstevel@tonic-gate getnetgr_ldap_destr(ldap_backend_ptr be, void *a)
7147c478bd9Sstevel@tonic-gate {
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate #ifdef	DEBUG
7177c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_destr]\n");
7187c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 	free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
7217c478bd9Sstevel@tonic-gate 	free(be);
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_NOTFOUND);
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate static nss_status_t
7287c478bd9Sstevel@tonic-gate getnetgr_ldap_getent(ldap_backend_ptr be, void *a)
7297c478bd9Sstevel@tonic-gate {
7307c478bd9Sstevel@tonic-gate 	struct nss_getnetgrent_args	*args;
7317c478bd9Sstevel@tonic-gate 	getnetgrent_cookie_t	*p;
7327c478bd9Sstevel@tonic-gate 	char			searchfilter[SEARCHFILTERLEN];
7337c478bd9Sstevel@tonic-gate 	char			userdata[SEARCHFILTERLEN];
7347c478bd9Sstevel@tonic-gate 	char			name[SEARCHFILTERLEN];
7357c478bd9Sstevel@tonic-gate 	int			rc;
7367c478bd9Sstevel@tonic-gate 	void			*cookie = NULL;
7377c478bd9Sstevel@tonic-gate 	ns_ldap_result_t	*result = NULL;
7387c478bd9Sstevel@tonic-gate 	ns_ldap_error_t		*error = NULL;
7397c478bd9Sstevel@tonic-gate 	char			**attrs;
7407c478bd9Sstevel@tonic-gate 	char			*hostname, *username, *domain;
7417c478bd9Sstevel@tonic-gate 	char			*buffer;
7427c478bd9Sstevel@tonic-gate 	nss_status_t		status = NSS_SUCCESS;
7437c478bd9Sstevel@tonic-gate 	netgroup_name_t		*ng;
7447c478bd9Sstevel@tonic-gate 	int			ret;
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate #ifdef	DEBUG
7477c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_getent]\n");
7487c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 	args = (struct nss_getnetgrent_args *)a;
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 	args->status = NSS_NETGR_NO;
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	p = (getnetgrent_cookie_t *)be->netgroup_cookie;
7557c478bd9Sstevel@tonic-gate 	if (p == NULL)
7567c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_SUCCESS);
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 	for (;;) {
7597c478bd9Sstevel@tonic-gate 		while (p->cookie == NULL) {
7607c478bd9Sstevel@tonic-gate 			ng = get_next_netgroup(&p->tab);
7617c478bd9Sstevel@tonic-gate 			if (ng == NULL)	 /* no more */
7627c478bd9Sstevel@tonic-gate 				break;
7637c478bd9Sstevel@tonic-gate 
764*3d047983Smichen 			if (_ldap_filter_name(name, ng->name,
765*3d047983Smichen 			    sizeof (name)) != 0)
7667c478bd9Sstevel@tonic-gate 				break;
7677c478bd9Sstevel@tonic-gate 
768*3d047983Smichen 			ret = snprintf(searchfilter,
769*3d047983Smichen 			    sizeof (searchfilter),
7707c478bd9Sstevel@tonic-gate 			    _F_SETMEMBER, name);
7717c478bd9Sstevel@tonic-gate 			if (ret >= sizeof (searchfilter) || ret < 0)
7727c478bd9Sstevel@tonic-gate 				break;
7737c478bd9Sstevel@tonic-gate 
774*3d047983Smichen 			ret = snprintf(userdata, sizeof (userdata),
775*3d047983Smichen 			    _F_SETMEMBER_SSD, name);
7767c478bd9Sstevel@tonic-gate 			if (ret >= sizeof (userdata) || ret < 0)
7777c478bd9Sstevel@tonic-gate 				break;
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 			result = NULL;
780*3d047983Smichen 			rc = __ns_ldap_firstEntry(_NETGROUP,
781*3d047983Smichen 			    searchfilter,
782*3d047983Smichen 			    _merge_SSD_filter, netgrent_attrs,
783*3d047983Smichen 			    NULL, 0, &cookie,
7847c478bd9Sstevel@tonic-gate 			    &result, &error, userdata);
7857c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeError(&error);
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 			if (rc == NS_LDAP_SUCCESS && result != NULL) {
7887c478bd9Sstevel@tonic-gate 				p->cookie = cookie;
7897c478bd9Sstevel@tonic-gate 				p->results = result;
7907c478bd9Sstevel@tonic-gate 				break;
7917c478bd9Sstevel@tonic-gate 			}
7927c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeResult(&result);
7937c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_endEntry(&cookie, &error);
7947c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeError(&error);
7957c478bd9Sstevel@tonic-gate 		}
7967c478bd9Sstevel@tonic-gate 		if (p->cookie == NULL)
7977c478bd9Sstevel@tonic-gate 			break;
7987c478bd9Sstevel@tonic-gate 		if (p->results == NULL) {
7997c478bd9Sstevel@tonic-gate 			result = NULL;
800*3d047983Smichen 			rc = __ns_ldap_nextEntry(p->cookie, &result,
801*3d047983Smichen 			    &error);
8027c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeError(&error);
8037c478bd9Sstevel@tonic-gate 			if (rc == NS_LDAP_SUCCESS && result != NULL)
8047c478bd9Sstevel@tonic-gate 				p->results = result;
8057c478bd9Sstevel@tonic-gate 			else {
8067c478bd9Sstevel@tonic-gate 				(void) __ns_ldap_freeResult(&result);
807*3d047983Smichen 				(void) __ns_ldap_endEntry(&p->cookie,
808*3d047983Smichen 				    &error);
8097c478bd9Sstevel@tonic-gate 				(void) __ns_ldap_freeError(&error);
8107c478bd9Sstevel@tonic-gate 				p->cookie = NULL;
8117c478bd9Sstevel@tonic-gate 			}
8127c478bd9Sstevel@tonic-gate 		}
8137c478bd9Sstevel@tonic-gate 		if (p->results == NULL)
8147c478bd9Sstevel@tonic-gate 			continue;
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 		if (p->entry == NULL)
8177c478bd9Sstevel@tonic-gate 			p->entry = p->results->entry;
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 		if (p->entry == NULL)
8207c478bd9Sstevel@tonic-gate 			continue;
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate 		if (p->attrs == NULL) {
8237c478bd9Sstevel@tonic-gate 			attrs = __ns_ldap_getAttr(p->entry, _N_TRIPLE);
8247c478bd9Sstevel@tonic-gate 			if (attrs != NULL && *attrs != NULL)
8257c478bd9Sstevel@tonic-gate 				p->attrs = attrs;
8267c478bd9Sstevel@tonic-gate 		}
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 		if (p->attrs != NULL) {
8297c478bd9Sstevel@tonic-gate 			attrs = p->attrs;
8307c478bd9Sstevel@tonic-gate 			buffer = args->buffer;
8317c478bd9Sstevel@tonic-gate 
832*3d047983Smichen 			if (strlcpy(buffer, *attrs, args->buflen) >=
833*3d047983Smichen 			    args->buflen) {
8347c478bd9Sstevel@tonic-gate 				status = NSS_STR_PARSE_ERANGE;
8357c478bd9Sstevel@tonic-gate 				break;
8367c478bd9Sstevel@tonic-gate 			}
8377c478bd9Sstevel@tonic-gate 
838*3d047983Smichen 			rc = split_triple(buffer, &hostname, &username,
839*3d047983Smichen 			    &domain);
8407c478bd9Sstevel@tonic-gate 			attrs++;
8417c478bd9Sstevel@tonic-gate 			if (attrs != NULL && *attrs != NULL)
8427c478bd9Sstevel@tonic-gate 				p->attrs = attrs;
8437c478bd9Sstevel@tonic-gate 			else
8447c478bd9Sstevel@tonic-gate 				p->attrs = NULL;
8457c478bd9Sstevel@tonic-gate 			if (rc == 0) {
8467c478bd9Sstevel@tonic-gate 				args->retp[NSS_NETGR_MACHINE] = hostname;
8477c478bd9Sstevel@tonic-gate 				args->retp[NSS_NETGR_USER] = username;
8487c478bd9Sstevel@tonic-gate 				args->retp[NSS_NETGR_DOMAIN] = domain;
8497c478bd9Sstevel@tonic-gate 				args->status = NSS_NETGR_FOUND;
8507c478bd9Sstevel@tonic-gate 				if (p->attrs != NULL)
8517c478bd9Sstevel@tonic-gate 					break;
8527c478bd9Sstevel@tonic-gate 			}
8537c478bd9Sstevel@tonic-gate 		}
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 		if (p->attrs == NULL) {
8567c478bd9Sstevel@tonic-gate 			rc = add_netgroup_member_entry(p->entry, &p->tab);
8577c478bd9Sstevel@tonic-gate 			if (rc != 0) {
8587c478bd9Sstevel@tonic-gate 				args->status = NSS_NETGR_NO;
8597c478bd9Sstevel@tonic-gate 				break;
8607c478bd9Sstevel@tonic-gate 			}
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 			p->entry = p->entry->next;
8637c478bd9Sstevel@tonic-gate 			if (p->entry == NULL)
8647c478bd9Sstevel@tonic-gate 				(void) __ns_ldap_freeResult(&p->results);
8657c478bd9Sstevel@tonic-gate 			if (args->status == NSS_NETGR_FOUND)
8667c478bd9Sstevel@tonic-gate 				break;
8677c478bd9Sstevel@tonic-gate 		}
8687c478bd9Sstevel@tonic-gate 	}
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 	return (status);
8717c478bd9Sstevel@tonic-gate }
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate static ldap_backend_op_t getnetgroup_ops[] = {
8747c478bd9Sstevel@tonic-gate 	getnetgr_ldap_destr,
8757c478bd9Sstevel@tonic-gate 	getnetgr_ldap_endent,
8767c478bd9Sstevel@tonic-gate 	getnetgr_ldap_setent,
8777c478bd9Sstevel@tonic-gate 	getnetgr_ldap_getent,
8787c478bd9Sstevel@tonic-gate };
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate /*
8817c478bd9Sstevel@tonic-gate  *
8827c478bd9Sstevel@tonic-gate  */
8837c478bd9Sstevel@tonic-gate 
8847c478bd9Sstevel@tonic-gate static nss_status_t
8857c478bd9Sstevel@tonic-gate netgr_set(ldap_backend_ptr be, void *a)
8867c478bd9Sstevel@tonic-gate {
8877c478bd9Sstevel@tonic-gate 	struct nss_setnetgrent_args	*args =
8887c478bd9Sstevel@tonic-gate 	    (struct nss_setnetgrent_args *)a;
8897c478bd9Sstevel@tonic-gate 	ldap_backend_ptr		get_be;
8907c478bd9Sstevel@tonic-gate 	getnetgrent_cookie_t		*p;
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate #ifdef DEBUG
8937c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: netgr_set]\n");
8947c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout,
8957c478bd9Sstevel@tonic-gate 	    "\targs->netgroup: %s\n", ISNULL(args->netgroup));
8967c478bd9Sstevel@tonic-gate #endif /* DEBUG */
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate 	if (args->netgroup == NULL)
8997c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 	free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
9027c478bd9Sstevel@tonic-gate 	p = (getnetgrent_cookie_t *)calloc(1, sizeof (getnetgrent_cookie_t));
9037c478bd9Sstevel@tonic-gate 	if (p == NULL)
9047c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
9057c478bd9Sstevel@tonic-gate 	p->netgroup = strdup(args->netgroup);
9067c478bd9Sstevel@tonic-gate 	if (p->netgroup == NULL) {
9077c478bd9Sstevel@tonic-gate 		free(p);
9087c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
9097c478bd9Sstevel@tonic-gate 	}
9107c478bd9Sstevel@tonic-gate 	if (add_netgroup_name(args->netgroup, &p->tab) == -1) {
9117c478bd9Sstevel@tonic-gate 		free_getnetgrent_cookie(&p);
9127c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
9137c478bd9Sstevel@tonic-gate 	}
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate 	/* now allocate and return iteration backend structure */
9167c478bd9Sstevel@tonic-gate 	if ((get_be = (ldap_backend_ptr)malloc(sizeof (*get_be))) == NULL)
9177c478bd9Sstevel@tonic-gate 		return (NSS_UNAVAIL);
9187c478bd9Sstevel@tonic-gate 	get_be->ops = getnetgroup_ops;
9197c478bd9Sstevel@tonic-gate 	get_be->nops = sizeof (getnetgroup_ops) / sizeof (getnetgroup_ops[0]);
9207c478bd9Sstevel@tonic-gate 	get_be->tablename = NULL;
9217c478bd9Sstevel@tonic-gate 	get_be->attrs = netgrent_attrs;
9227c478bd9Sstevel@tonic-gate 	get_be->result = NULL;
923cb5caa98Sdjl 	get_be->ldapobj2str = NULL;
9247c478bd9Sstevel@tonic-gate 	get_be->setcalled = 1;
9257c478bd9Sstevel@tonic-gate 	get_be->filter = NULL;
9267c478bd9Sstevel@tonic-gate 	get_be->toglue = NULL;
9277c478bd9Sstevel@tonic-gate 	get_be->enumcookie = NULL;
9287c478bd9Sstevel@tonic-gate 	get_be->netgroup_cookie = p;
9297c478bd9Sstevel@tonic-gate 	args->iterator = (nss_backend_t *)get_be;
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate 	return (NSS_SUCCESS);
9347c478bd9Sstevel@tonic-gate }
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
9387c478bd9Sstevel@tonic-gate static nss_status_t
9397c478bd9Sstevel@tonic-gate netgr_ldap_destr(ldap_backend_ptr be, void *a)
9407c478bd9Sstevel@tonic-gate {
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate #ifdef	DEBUG
9437c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: netgr_ldap_destr]\n");
9447c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 	(void) _clean_ldap_backend(be);
9477c478bd9Sstevel@tonic-gate 
9487c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_NOTFOUND);
9497c478bd9Sstevel@tonic-gate }
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate static ldap_backend_op_t netgroup_ops[] = {
9557c478bd9Sstevel@tonic-gate 	netgr_ldap_destr,
9567c478bd9Sstevel@tonic-gate 	0,
9577c478bd9Sstevel@tonic-gate 	0,
9587c478bd9Sstevel@tonic-gate 	0,
9597c478bd9Sstevel@tonic-gate 	netgr_in,		/*	innetgr()	*/
9607c478bd9Sstevel@tonic-gate 	netgr_set		/*	setnetgrent()	*/
9617c478bd9Sstevel@tonic-gate };
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate /*
9657c478bd9Sstevel@tonic-gate  * _nss_ldap_netgroup_constr is where life begins. This function calls the
9667c478bd9Sstevel@tonic-gate  * generic ldap constructor function to define and build the abstract data
9677c478bd9Sstevel@tonic-gate  * types required to support ldap operations.
9687c478bd9Sstevel@tonic-gate  */
9697c478bd9Sstevel@tonic-gate 
9707c478bd9Sstevel@tonic-gate /*ARGSUSED0*/
9717c478bd9Sstevel@tonic-gate nss_backend_t *
9727c478bd9Sstevel@tonic-gate _nss_ldap_netgroup_constr(const char *dummy1, const char *dummy2,
9737c478bd9Sstevel@tonic-gate 			const char *dummy3)
9747c478bd9Sstevel@tonic-gate {
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate #ifdef	DEBUG
9777c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout,
9787c478bd9Sstevel@tonic-gate 	    "\n[getnetgrent.c: _nss_ldap_netgroup_constr]\n");
9797c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 	return ((nss_backend_t *)_nss_ldap_constr(netgroup_ops,
9827c478bd9Sstevel@tonic-gate 	    sizeof (netgroup_ops)/sizeof (netgroup_ops[0]), _NETGROUP,
9837c478bd9Sstevel@tonic-gate 	    netgrent_attrs, NULL));
9847c478bd9Sstevel@tonic-gate }
985