xref: /onnv-gate/usr/src/lib/nsswitch/ldap/common/getnetgrent.c (revision 8777:685600be76fa)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52388Smj162486  * Common Development and Distribution License (the "License").
62388Smj162486  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*8777SSerge.Dussud@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include <syslog.h>
280Sstevel@tonic-gate #include "ldap_common.h"
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /* netgroup attributes filters */
310Sstevel@tonic-gate #define	_N_TRIPLE		"nisnetgrouptriple"
320Sstevel@tonic-gate #define	_N_MEMBER		"membernisnetgroup"
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #define	PRINT_VAL(a)		(((a).argc == 0) || ((a).argv == NULL) || \
350Sstevel@tonic-gate 				    ((a).argv[0] == NULL)) ? "*" : (a).argv[0]
360Sstevel@tonic-gate #define	ISNULL(a)		(a == NULL ? "<NULL>" : a)
370Sstevel@tonic-gate #define	MAX_DOMAIN_LEN		1024
380Sstevel@tonic-gate #define	MAX_TRIPLE_LEN		(MAXHOSTNAMELEN + LOGNAME_MAX + \
390Sstevel@tonic-gate 					MAX_DOMAIN_LEN + 5)
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #define	_F_SETMEMBER		"(&(objectClass=nisNetGroup)(cn=%s))"
420Sstevel@tonic-gate #define	_F_SETMEMBER_SSD	"(&(%%s)(cn=%s))"
430Sstevel@tonic-gate 
440Sstevel@tonic-gate #define	N_HASH		257
452388Smj162486 #define	COMMA		','
460Sstevel@tonic-gate 
470Sstevel@tonic-gate static const char *netgrent_attrs[] = {
480Sstevel@tonic-gate 	_N_TRIPLE,
490Sstevel@tonic-gate 	_N_MEMBER,
500Sstevel@tonic-gate 	(char *)NULL
510Sstevel@tonic-gate };
520Sstevel@tonic-gate 
530Sstevel@tonic-gate typedef struct netgroup_name {
540Sstevel@tonic-gate 	char *name;
550Sstevel@tonic-gate 	struct netgroup_name *next;
560Sstevel@tonic-gate 	struct netgroup_name *next_hash;
570Sstevel@tonic-gate } netgroup_name_t;
580Sstevel@tonic-gate 
590Sstevel@tonic-gate typedef struct {
600Sstevel@tonic-gate 	netgroup_name_t *hash_list[N_HASH];
610Sstevel@tonic-gate 	netgroup_name_t *to_do;
620Sstevel@tonic-gate 	netgroup_name_t *done;
630Sstevel@tonic-gate } netgroup_table_t;
640Sstevel@tonic-gate 
650Sstevel@tonic-gate typedef struct {
660Sstevel@tonic-gate 	ns_ldap_result_t *results;
670Sstevel@tonic-gate 	ns_ldap_entry_t *entry;
680Sstevel@tonic-gate 	char **attrs;
690Sstevel@tonic-gate 	char *netgroup;
700Sstevel@tonic-gate 	netgroup_table_t tab;
710Sstevel@tonic-gate } getnetgrent_cookie_t;
720Sstevel@tonic-gate 
730Sstevel@tonic-gate typedef struct {
740Sstevel@tonic-gate 	struct nss_innetgr_args *ia;
750Sstevel@tonic-gate 	const char *ssd_filter;
760Sstevel@tonic-gate 	const char *netgrname;
770Sstevel@tonic-gate 	const char *membername;
780Sstevel@tonic-gate 	netgroup_table_t tab;
790Sstevel@tonic-gate } innetgr_cookie_t;
800Sstevel@tonic-gate 
810Sstevel@tonic-gate typedef unsigned int hash_t;
820Sstevel@tonic-gate 
830Sstevel@tonic-gate static hash_t
get_hash(const char * s)840Sstevel@tonic-gate get_hash(const char *s)
850Sstevel@tonic-gate {
860Sstevel@tonic-gate 	unsigned int sum = 0;
870Sstevel@tonic-gate 	unsigned int i;
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	for (i = 0; s[i] != '\0'; i++)
900Sstevel@tonic-gate 		sum += ((unsigned char *)s)[i];
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 	return ((sum + i) % N_HASH);
930Sstevel@tonic-gate }
940Sstevel@tonic-gate 
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate  * Adds a name to the netgroup table
970Sstevel@tonic-gate  *
980Sstevel@tonic-gate  * Returns
990Sstevel@tonic-gate  *	0 if successfully added or already present
100*8777SSerge.Dussud@Sun.COM  *	-1 if memory allocation error or NULL netgroup_table_t
101*8777SSerge.Dussud@Sun.COM  *         from caller.
1020Sstevel@tonic-gate  */
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate static int
add_netgroup_name(const char * name,netgroup_table_t * tab)1050Sstevel@tonic-gate add_netgroup_name(const char *name, netgroup_table_t *tab)
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate 	hash_t		h;
1080Sstevel@tonic-gate 	netgroup_name_t	*ng;
1090Sstevel@tonic-gate 	netgroup_name_t	*ng_new;
1100Sstevel@tonic-gate 
111*8777SSerge.Dussud@Sun.COM 	if (tab == NULL) {
112*8777SSerge.Dussud@Sun.COM 		/*
113*8777SSerge.Dussud@Sun.COM 		 * Should never happen. But if it does,
114*8777SSerge.Dussud@Sun.COM 		 * that's an error condition.
115*8777SSerge.Dussud@Sun.COM 		 */
116*8777SSerge.Dussud@Sun.COM 		return (-1);
117*8777SSerge.Dussud@Sun.COM 	}
118*8777SSerge.Dussud@Sun.COM 	if (name == NULL || *name == '\0') {
119*8777SSerge.Dussud@Sun.COM 		/* no name to add means success */
120*8777SSerge.Dussud@Sun.COM 		return (0);
121*8777SSerge.Dussud@Sun.COM 	}
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	h = get_hash(name);
1240Sstevel@tonic-gate 	ng = tab->hash_list[h];
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	while (ng != NULL) {
1270Sstevel@tonic-gate 		if (strcmp(name, ng->name) == 0)
1280Sstevel@tonic-gate 			break;
1290Sstevel@tonic-gate 		ng = ng->next_hash;
1300Sstevel@tonic-gate 	}
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	if (ng == NULL) {
1330Sstevel@tonic-gate 		ng_new = (netgroup_name_t *)
1344953Smichen 		    calloc(1, sizeof (netgroup_name_t));
1350Sstevel@tonic-gate 		if (ng_new == NULL)
1360Sstevel@tonic-gate 			return (-1);
1370Sstevel@tonic-gate 		ng_new->name = strdup(name);
1380Sstevel@tonic-gate 		if (ng_new->name == NULL) {
1390Sstevel@tonic-gate 			free(ng_new);
1400Sstevel@tonic-gate 			return (-1);
1410Sstevel@tonic-gate 		}
1420Sstevel@tonic-gate 		ng_new->next_hash = tab->hash_list[h];
1430Sstevel@tonic-gate 		tab->hash_list[h] = ng_new;
1440Sstevel@tonic-gate 		ng_new->next = tab->to_do;
1450Sstevel@tonic-gate 		tab->to_do = ng_new;
1460Sstevel@tonic-gate 	}
1470Sstevel@tonic-gate 	return (0);
1480Sstevel@tonic-gate }
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate static netgroup_name_t *
get_next_netgroup(netgroup_table_t * tab)1510Sstevel@tonic-gate get_next_netgroup(netgroup_table_t *tab)
1520Sstevel@tonic-gate {
1530Sstevel@tonic-gate 	netgroup_name_t *ng;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	if (tab == NULL)
1560Sstevel@tonic-gate 		return (NULL);
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	ng = tab->to_do;
1590Sstevel@tonic-gate 	if (ng != NULL) {
1600Sstevel@tonic-gate 		tab->to_do = ng->next;
1610Sstevel@tonic-gate 		ng->next = tab->done;
1620Sstevel@tonic-gate 		tab->done = ng;
1630Sstevel@tonic-gate 	}
1640Sstevel@tonic-gate 	return (ng);
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate static void
free_netgroup_table(netgroup_table_t * tab)1680Sstevel@tonic-gate free_netgroup_table(netgroup_table_t *tab)
1690Sstevel@tonic-gate {
1700Sstevel@tonic-gate 	netgroup_name_t *ng, *next;
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 	if (tab == NULL)
1730Sstevel@tonic-gate 		return;
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	for (ng = tab->to_do; ng != NULL; ng = next) {
1760Sstevel@tonic-gate 		if (ng->name != NULL)
1770Sstevel@tonic-gate 			free(ng->name);
1780Sstevel@tonic-gate 		next = ng->next;
1790Sstevel@tonic-gate 		free(ng);
1800Sstevel@tonic-gate 	}
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	for (ng = tab->done; ng != NULL; ng = next) {
1830Sstevel@tonic-gate 		if (ng->name != NULL)
1840Sstevel@tonic-gate 			free(ng->name);
1850Sstevel@tonic-gate 		next = ng->next;
1860Sstevel@tonic-gate 		free(ng);
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate 	(void) memset(tab, 0, sizeof (*tab));
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate /*
1920Sstevel@tonic-gate  * domain comparing routine
1930Sstevel@tonic-gate  * 	n1: See if n1 is n2 or an ancestor of it
1940Sstevel@tonic-gate  * 	n2: (in string terms, n1 is a suffix of n2)
1950Sstevel@tonic-gate  * Returns ZERO for success, -1 for failure.
1960Sstevel@tonic-gate  */
1970Sstevel@tonic-gate static int
domcmp(const char * n1,const char * n2)1980Sstevel@tonic-gate domcmp(const char *n1, const char *n2)
1990Sstevel@tonic-gate {
2000Sstevel@tonic-gate #define	PASS	0
2010Sstevel@tonic-gate #define	FAIL	-1
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 	size_t		l1, l2;
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	if ((n1 == NULL) || (n2 == NULL))
2060Sstevel@tonic-gate 		return (FAIL);
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	l1 = strlen(n1);
2090Sstevel@tonic-gate 	l2 = strlen(n2);
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	/* Turn a blind eye to the presence or absence of trailing periods */
2120Sstevel@tonic-gate 	if (l1 != 0 && n1[l1 - 1] == '.') {
2130Sstevel@tonic-gate 		--l1;
2140Sstevel@tonic-gate 	}
2150Sstevel@tonic-gate 	if (l2 != 0 && n2[l2 - 1] == '.') {
2160Sstevel@tonic-gate 		--l2;
2170Sstevel@tonic-gate 	}
2180Sstevel@tonic-gate 	if (l1 > l2) {		/* Can't be a suffix */
2190Sstevel@tonic-gate 		return (FAIL);
2200Sstevel@tonic-gate 	} else if (l1 == 0) {	/* Trivially a suffix; */
2210Sstevel@tonic-gate 				/* (do we want this case?) */
2220Sstevel@tonic-gate 		return (PASS);
2230Sstevel@tonic-gate 	}
2240Sstevel@tonic-gate 	/* So 0 < l1 <= l2 */
2250Sstevel@tonic-gate 	if (l1 < l2 && n2[l2 - l1 - 1] != '.') {
2260Sstevel@tonic-gate 		return (FAIL);
2270Sstevel@tonic-gate 	}
2280Sstevel@tonic-gate 	if (strncasecmp(n1, &n2[l2 - l1], l1) == 0) {
2290Sstevel@tonic-gate 		return (PASS);
2300Sstevel@tonic-gate 	} else {
2310Sstevel@tonic-gate 		return (FAIL);
2320Sstevel@tonic-gate 	}
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate static int
split_triple(char * triple,char ** hostname,char ** username,char ** domain)2360Sstevel@tonic-gate split_triple(char *triple, char **hostname, char **username, char **domain)
2370Sstevel@tonic-gate {
2380Sstevel@tonic-gate 	int	i, syntax_err;
2390Sstevel@tonic-gate 	char	*splittriple[3];
2400Sstevel@tonic-gate 	char	*p = triple;
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate #ifdef	DEBUG
2430Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: split_triple]\n");
2440Sstevel@tonic-gate #endif	/* DEBUG */
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	if (triple == NULL)
2470Sstevel@tonic-gate 		return (-1);
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	p++;
2500Sstevel@tonic-gate 	syntax_err = 0;
2510Sstevel@tonic-gate 	for (i = 0; i < 3; i++) {
2520Sstevel@tonic-gate 		char	*start;
2530Sstevel@tonic-gate 		char	*limit;
2540Sstevel@tonic-gate 		const char	*terminators = ",) \t";
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 		if (i == 2) {
2570Sstevel@tonic-gate 			/* Don't allow comma */
2580Sstevel@tonic-gate 			terminators++;
2590Sstevel@tonic-gate 		}
2600Sstevel@tonic-gate 		while (isspace(*p)) {
2610Sstevel@tonic-gate 			p++;
2620Sstevel@tonic-gate 		}
2630Sstevel@tonic-gate 		start = p;
2640Sstevel@tonic-gate 		limit = strpbrk(start, terminators);
2650Sstevel@tonic-gate 		if (limit == 0) {
2660Sstevel@tonic-gate 			syntax_err++;
2670Sstevel@tonic-gate 			break;
2680Sstevel@tonic-gate 		}
2690Sstevel@tonic-gate 		p = limit;
2700Sstevel@tonic-gate 		while (isspace(*p)) {
2710Sstevel@tonic-gate 			p++;
2720Sstevel@tonic-gate 		}
2730Sstevel@tonic-gate 		if (*p == terminators[0]) {
2740Sstevel@tonic-gate 			/*
2750Sstevel@tonic-gate 			 * Successfully parsed this name and
2760Sstevel@tonic-gate 			 * the separator after it (comma or
2770Sstevel@tonic-gate 			 * right paren); leave p ready for
2780Sstevel@tonic-gate 			 * next parse.
2790Sstevel@tonic-gate 			 */
2800Sstevel@tonic-gate 			p++;
2810Sstevel@tonic-gate 			if (start == limit) {
2820Sstevel@tonic-gate 				/* Wildcard */
2830Sstevel@tonic-gate 				splittriple[i] = NULL;
2840Sstevel@tonic-gate 			} else {
2850Sstevel@tonic-gate 				*limit = '\0';
2860Sstevel@tonic-gate 				splittriple[i] = start;
2870Sstevel@tonic-gate 			}
2880Sstevel@tonic-gate 		} else {
2890Sstevel@tonic-gate 			syntax_err++;
2900Sstevel@tonic-gate 			break;
2910Sstevel@tonic-gate 		}
2920Sstevel@tonic-gate 	}
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	if (syntax_err != 0)
2950Sstevel@tonic-gate 		return (-1);
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate 	*hostname = splittriple[0];
2980Sstevel@tonic-gate 	*username = splittriple[1];
2990Sstevel@tonic-gate 	*domain = splittriple[2];
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	return (0);
3020Sstevel@tonic-gate }
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate /*
3052388Smj162486  * Test membership in triple
3062388Smj162486  *	return 0 = no match
3072388Smj162486  *	return 1 = match
3080Sstevel@tonic-gate  */
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate static int
match_triple_entry(struct nss_innetgr_args * ia,const ns_ldap_entry_t * entry)3110Sstevel@tonic-gate match_triple_entry(struct nss_innetgr_args *ia, const ns_ldap_entry_t *entry)
3120Sstevel@tonic-gate {
3130Sstevel@tonic-gate 	int	ndomains;
3140Sstevel@tonic-gate 	char	**pdomains;
3150Sstevel@tonic-gate 	int	nhost;
3160Sstevel@tonic-gate 	char	**phost;
3170Sstevel@tonic-gate 	int	nusers;
3180Sstevel@tonic-gate 	char	**pusers;
3190Sstevel@tonic-gate 	char	**attr;
3200Sstevel@tonic-gate 	char	triple[MAX_TRIPLE_LEN];
3210Sstevel@tonic-gate 	char	*tuser, *thost, *tdomain;
3220Sstevel@tonic-gate 	int	i;
3232388Smj162486 	char	*current, *limit;
3242388Smj162486 	int	pulen, phlen;
3252388Smj162486 	char	*pusers0, *phost0;
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 	nhost = ia->arg[NSS_NETGR_MACHINE].argc;
3280Sstevel@tonic-gate 	phost = (char **)ia->arg[NSS_NETGR_MACHINE].argv;
3292388Smj162486 	if (phost == NULL || *phost == NULL) {
3300Sstevel@tonic-gate 		nhost = 0;
3312388Smj162486 	} else {
3322388Smj162486 		phost0 = phost[0];
3332388Smj162486 		phlen = strlen(phost0);
334*8777SSerge.Dussud@Sun.COM #ifdef DEBUG
335*8777SSerge.Dussud@Sun.COM 		syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
336*8777SSerge.Dussud@Sun.COM 		    "entering with host: %s", phost0 ? phost0 : "");
337*8777SSerge.Dussud@Sun.COM #endif
3382388Smj162486 	}
3390Sstevel@tonic-gate 	nusers = ia->arg[NSS_NETGR_USER].argc;
3400Sstevel@tonic-gate 	pusers = (char **)ia->arg[NSS_NETGR_USER].argv;
3412388Smj162486 	if (pusers == NULL || *pusers == NULL) {
3420Sstevel@tonic-gate 		nusers = 0;
3432388Smj162486 	} else {
3442388Smj162486 		pusers0 = pusers[0];
3452388Smj162486 		pulen = strlen(pusers0);
346*8777SSerge.Dussud@Sun.COM #ifdef DEBUG
347*8777SSerge.Dussud@Sun.COM 		syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
348*8777SSerge.Dussud@Sun.COM 		    "entering with user: %s", pusers0 ? pusers0 : "");
349*8777SSerge.Dussud@Sun.COM #endif
3502388Smj162486 	}
3510Sstevel@tonic-gate 	ndomains = ia->arg[NSS_NETGR_DOMAIN].argc;
3520Sstevel@tonic-gate 	pdomains = (char **)ia->arg[NSS_NETGR_DOMAIN].argv;
3530Sstevel@tonic-gate 	if (pdomains == NULL || *pdomains == NULL)
3540Sstevel@tonic-gate 		ndomains = 0;
355*8777SSerge.Dussud@Sun.COM #ifdef DEBUG
356*8777SSerge.Dussud@Sun.COM 	else
357*8777SSerge.Dussud@Sun.COM 		syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
358*8777SSerge.Dussud@Sun.COM 		    "entering with domain: %s", pdomains[0] ? pdomains[0] : "");
359*8777SSerge.Dussud@Sun.COM #endif
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	attr = __ns_ldap_getAttr(entry, _N_TRIPLE);
3620Sstevel@tonic-gate 	if (attr == NULL || *attr == NULL)
3630Sstevel@tonic-gate 		return (0);
3640Sstevel@tonic-gate 
365*8777SSerge.Dussud@Sun.COM #ifdef DEBUG
366*8777SSerge.Dussud@Sun.COM 	syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
367*8777SSerge.Dussud@Sun.COM 	    "(nusers: %d, nhost:%d, ndomains: %d)",
368*8777SSerge.Dussud@Sun.COM 	    nusers, nhost, ndomains);
369*8777SSerge.Dussud@Sun.COM #endif
370*8777SSerge.Dussud@Sun.COM 
3712388Smj162486 	/* Special cases for speedup */
3722388Smj162486 	if (nusers == 1 && nhost == 0 && ndomains == 0) {
3732388Smj162486 		/* Special case for finding a single user in a netgroup */
3742388Smj162486 		for (; *attr; attr++) {
3752388Smj162486 			/* jump to first comma and check next character */
3762388Smj162486 			current = *attr;
377*8777SSerge.Dussud@Sun.COM #ifdef DEBUG
378*8777SSerge.Dussud@Sun.COM 			syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
379*8777SSerge.Dussud@Sun.COM 			    "current is: %s", current);
380*8777SSerge.Dussud@Sun.COM #endif
3812388Smj162486 			if ((current = strchr(current, COMMA)) == NULL)
3822388Smj162486 				continue;
3832388Smj162486 			current++;
3842388Smj162486 
3852388Smj162486 			/* skip whitespaces */
3862388Smj162486 			while (isspace(*current))
3872388Smj162486 				current++;
3882388Smj162486 
3892388Smj162486 			/* if user part is null, then treat as wildcard */
3902388Smj162486 			if (*current == COMMA)
3912388Smj162486 				return (1);
3922388Smj162486 
3932388Smj162486 			/* compare first character */
3942388Smj162486 			if (*pusers0 != *current)
3952388Smj162486 				continue;
3962388Smj162486 
3972388Smj162486 			/* limit username to COMMA */
3982388Smj162486 			if ((limit = strchr(current, COMMA)) == NULL)
3992388Smj162486 				continue;
4002388Smj162486 			*limit = '\0';
4012388Smj162486 
4022388Smj162486 			/* remove blanks before COMMA */
4032388Smj162486 			if ((limit = strpbrk(current, " \t")) != NULL)
4042388Smj162486 				*limit = '\0';
4052388Smj162486 
4062388Smj162486 			/* compare size of username */
4072388Smj162486 			if (pulen != strlen(current)) {
4082388Smj162486 				continue;
4092388Smj162486 			}
4102388Smj162486 
4112388Smj162486 			/* do actual compare */
4122388Smj162486 			if (strncmp(pusers0, current, pulen) == 0) {
4132388Smj162486 				return (1);
4142388Smj162486 			} else {
4152388Smj162486 				continue;
4162388Smj162486 			}
4172388Smj162486 		}
4182388Smj162486 	} else if (nusers == 0 && nhost == 1 && ndomains == 0) {
4192388Smj162486 		/* Special case for finding a single host in a netgroup */
4202388Smj162486 		for (; *attr; attr++) {
4212388Smj162486 
4222388Smj162486 			/* jump to first character and check */
4232388Smj162486 			current = *attr;
424*8777SSerge.Dussud@Sun.COM #ifdef DEBUG
425*8777SSerge.Dussud@Sun.COM 			syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
426*8777SSerge.Dussud@Sun.COM 			    "current is: %s", current);
427*8777SSerge.Dussud@Sun.COM #endif
4282388Smj162486 			current++;
4292388Smj162486 
4302388Smj162486 			/* skip whitespaces */
4312388Smj162486 			while (isspace(*current))
4322388Smj162486 				current++;
4332388Smj162486 
4342388Smj162486 			/* if host part is null, then treat as wildcard */
4352388Smj162486 			if (*current == COMMA)
4362388Smj162486 				return (1);
4372388Smj162486 
4382388Smj162486 			/* limit hostname to COMMA */
4392388Smj162486 			if ((limit = strchr(current, COMMA)) == NULL)
4402388Smj162486 				continue;
4412388Smj162486 			*limit = '\0';
4422388Smj162486 
4432388Smj162486 			/* remove blanks before COMMA */
4442388Smj162486 			if ((limit = strpbrk(current, " \t")) != NULL)
4452388Smj162486 				*limit = '\0';
4462388Smj162486 
4472388Smj162486 			/* compare size of hostname */
4482388Smj162486 			if (phlen != strlen(current)) {
4492388Smj162486 				continue;
4502388Smj162486 			}
4512388Smj162486 
4522388Smj162486 			/* do actual compare */
4532388Smj162486 			if (strncasecmp(phost0, current, phlen) == 0) {
4542388Smj162486 				return (1);
4552388Smj162486 			} else {
4562388Smj162486 				continue;
4572388Smj162486 			}
4582388Smj162486 		}
4592388Smj162486 	} else {
4602388Smj162486 		for (; *attr; attr++) {
4612388Smj162486 			if (strlcpy(triple, *attr,
4624953Smichen 			    sizeof (triple)) >= sizeof (triple))
4632388Smj162486 				continue;
464*8777SSerge.Dussud@Sun.COM #ifdef DEBUG
465*8777SSerge.Dussud@Sun.COM 			syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
466*8777SSerge.Dussud@Sun.COM 			    "triple is: %s", triple);
467*8777SSerge.Dussud@Sun.COM #endif
4682388Smj162486 			if (split_triple(triple, &thost, &tuser, &tdomain) != 0)
4692388Smj162486 				continue;
4702388Smj162486 			if (thost != NULL && *thost != '\0' && nhost != 0) {
4712388Smj162486 				for (i = 0; i < nhost; i++)
4722388Smj162486 					if (strcasecmp(thost, phost[i]) == 0)
4732388Smj162486 						break;
4742388Smj162486 				if (i == nhost)
4754953Smichen 					continue;
4762388Smj162486 			}
4772388Smj162486 			if (tuser != NULL && *tuser != '\0' && nusers != 0) {
4782388Smj162486 				for (i = 0; i < nusers; i++)
4792388Smj162486 					if (strcmp(tuser, pusers[i]) == 0)
4802388Smj162486 						break;
4812388Smj162486 				if (i == nusers)
4822388Smj162486 					continue;
4832388Smj162486 			}
4842388Smj162486 			if (tdomain != NULL && *tdomain != '\0' &&
4854953Smichen 			    ndomains != 0) {
4862388Smj162486 				for (i = 0; i < ndomains; i++)
4872388Smj162486 					if (domcmp(tdomain, pdomains[i]) == 0)
4882388Smj162486 						break;
4892388Smj162486 				if (i == ndomains)
4902388Smj162486 					continue;
4912388Smj162486 			}
4922388Smj162486 			return (1);
4932388Smj162486 		}
4940Sstevel@tonic-gate 	}
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 	return (0);
4970Sstevel@tonic-gate }
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate static int
match_triple(struct nss_innetgr_args * ia,ns_ldap_result_t * result)5000Sstevel@tonic-gate match_triple(struct nss_innetgr_args *ia, ns_ldap_result_t *result)
5010Sstevel@tonic-gate {
5020Sstevel@tonic-gate 	ns_ldap_entry_t	*entry;
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	for (entry = result->entry; entry != NULL; entry = entry->next)
5054953Smichen 		if (match_triple_entry(ia, entry) == 1)
5064953Smichen 			return (1);
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	return (0);
5090Sstevel@tonic-gate }
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate static int
add_netgroup_member_entry(ns_ldap_entry_t * entry,netgroup_table_t * tab)5120Sstevel@tonic-gate add_netgroup_member_entry(ns_ldap_entry_t *entry, netgroup_table_t *tab)
5130Sstevel@tonic-gate {
5140Sstevel@tonic-gate 	char		**attrs;
5150Sstevel@tonic-gate 	char		**a;
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	attrs = __ns_ldap_getAttr(entry, _N_MEMBER);
5180Sstevel@tonic-gate 	if (attrs == NULL || *attrs == NULL)
5190Sstevel@tonic-gate 		return (0);
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 	for (a = attrs; *a != NULL; a++) {}
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 	do {
5240Sstevel@tonic-gate 		a--;
5250Sstevel@tonic-gate 		if (add_netgroup_name(*a, tab) != 0)
5260Sstevel@tonic-gate 			return (-1);
5270Sstevel@tonic-gate 	} while (a > attrs);
5280Sstevel@tonic-gate 	return (0);
5290Sstevel@tonic-gate }
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate static int
add_netgroup_member(ns_ldap_result_t * result,netgroup_table_t * tab)5320Sstevel@tonic-gate add_netgroup_member(ns_ldap_result_t *result, netgroup_table_t *tab)
5330Sstevel@tonic-gate {
5340Sstevel@tonic-gate 	ns_ldap_entry_t	*entry;
5350Sstevel@tonic-gate 	int		ret = 0;
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 	for (entry = result->entry; entry != NULL; entry = entry->next) {
5384953Smichen 		ret = add_netgroup_member_entry(entry, tab);
5394953Smichen 		if (ret != 0)
5404953Smichen 			break;
5410Sstevel@tonic-gate 	}
5420Sstevel@tonic-gate 	return (ret);
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate /*
5460Sstevel@tonic-gate  * top_down_search checks only checks the netgroup specified in netgrname
5470Sstevel@tonic-gate  */
5480Sstevel@tonic-gate static nss_status_t
top_down_search(struct nss_innetgr_args * ia,char * netgrname)5490Sstevel@tonic-gate top_down_search(struct nss_innetgr_args *ia, char *netgrname)
5500Sstevel@tonic-gate {
5510Sstevel@tonic-gate 	char			searchfilter[SEARCHFILTERLEN];
5520Sstevel@tonic-gate 	char			name[SEARCHFILTERLEN];
5530Sstevel@tonic-gate 	char			userdata[SEARCHFILTERLEN];
5540Sstevel@tonic-gate 	ns_ldap_result_t	*result = NULL;
5550Sstevel@tonic-gate 	ns_ldap_error_t		*error = NULL;
5560Sstevel@tonic-gate 	int			rc;
5570Sstevel@tonic-gate 	nss_status_t		status = NSS_NOTFOUND;
5584953Smichen 	nss_status_t		status1;
5590Sstevel@tonic-gate 	netgroup_table_t	tab;
5600Sstevel@tonic-gate 	netgroup_name_t		*ng;
5610Sstevel@tonic-gate 	int			ret;
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	(void) memset(&tab, 0, sizeof (tab));
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 	if (add_netgroup_name(netgrname, &tab) != 0)
5664953Smichen 		return ((nss_status_t)NSS_NOTFOUND);
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 	while ((ng = get_next_netgroup(&tab)) != NULL) {
569*8777SSerge.Dussud@Sun.COM #ifdef DEBUG
570*8777SSerge.Dussud@Sun.COM 		syslog(LOG_DEBUG, "nss_ldap: top_down_search: netgroup  loop "
571*8777SSerge.Dussud@Sun.COM 		    "(ng->name: %s)", ng->name ? ng->name : "null !");
572*8777SSerge.Dussud@Sun.COM #endif
5734953Smichen 		if (_ldap_filter_name(name, ng->name, sizeof (name)) != 0)
5744953Smichen 			break;
5754953Smichen 		ret = snprintf(searchfilter, sizeof (searchfilter),
5764953Smichen 		    _F_SETMEMBER, name);
5774953Smichen 		if (ret >= sizeof (searchfilter) || ret < 0)
5784953Smichen 			break;
5794953Smichen 
5804953Smichen 		ret = snprintf(userdata, sizeof (userdata), _F_SETMEMBER_SSD,
5810Sstevel@tonic-gate 		    name);
5824953Smichen 		if (ret >= sizeof (userdata) || ret < 0)
5834953Smichen 			break;
5840Sstevel@tonic-gate 
585*8777SSerge.Dussud@Sun.COM 		/* searching for current netgroup name entry */
586*8777SSerge.Dussud@Sun.COM 		rc = __ns_ldap_list(_NETGROUP, searchfilter,
587*8777SSerge.Dussud@Sun.COM 		    _merge_SSD_filter, netgrent_attrs, NULL, 0, &result,
588*8777SSerge.Dussud@Sun.COM 		    &error, NULL, userdata);
5890Sstevel@tonic-gate 
5904953Smichen 		if (error != NULL) {
5914953Smichen 			status1 = switch_err(rc, error);
5924953Smichen 			if (status1 == NSS_TRYAGAIN) {
5934953Smichen 				(void) __ns_ldap_freeError(&error);
5944953Smichen 				free_netgroup_table(&tab);
5954953Smichen 				return (status1);
5964953Smichen 			}
5970Sstevel@tonic-gate 		}
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
600*8777SSerge.Dussud@Sun.COM 		if (rc == NS_LDAP_SUCCESS) {
6014953Smichen 			if (match_triple(ia, result) == 1) {
6024953Smichen 				/* We found a match */
6034953Smichen 				ia->status = NSS_NETGR_FOUND;
6044953Smichen 				status = NSS_SUCCESS;
605*8777SSerge.Dussud@Sun.COM #ifdef DEBUG
606*8777SSerge.Dussud@Sun.COM 				syslog(LOG_DEBUG, "nss_ldap: top_down_search: "
607*8777SSerge.Dussud@Sun.COM 				    "found match");
608*8777SSerge.Dussud@Sun.COM #endif
6094953Smichen 				break;
6104953Smichen 			}
6114953Smichen 
612*8777SSerge.Dussud@Sun.COM 			/*
613*8777SSerge.Dussud@Sun.COM 			 * No match found. Check for membernisnetgroup
614*8777SSerge.Dussud@Sun.COM 			 * in result and if yes, start again with those.
615*8777SSerge.Dussud@Sun.COM 			 */
6164953Smichen 			rc = add_netgroup_member(result, &tab);
617*8777SSerge.Dussud@Sun.COM 			if (rc != 0)
6184953Smichen 				break;
619*8777SSerge.Dussud@Sun.COM 		} else if (rc != NS_LDAP_NOTFOUND) {
620*8777SSerge.Dussud@Sun.COM 			break;
6214953Smichen 		}
6224953Smichen 		(void) __ns_ldap_freeResult(&result);
6230Sstevel@tonic-gate 	}
6240Sstevel@tonic-gate 
6250Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&result);
6260Sstevel@tonic-gate 	free_netgroup_table(&tab);
6270Sstevel@tonic-gate 	return (status);
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate /*
6310Sstevel@tonic-gate  * __netgr_in checks only checks the netgroup specified in ngroup
6320Sstevel@tonic-gate  */
6330Sstevel@tonic-gate static nss_status_t
__netgr_in(void * a,char * netgrname)6340Sstevel@tonic-gate __netgr_in(void *a, char *netgrname)
6350Sstevel@tonic-gate {
6360Sstevel@tonic-gate 	struct nss_innetgr_args	*ia = (struct nss_innetgr_args *)a;
6370Sstevel@tonic-gate 	nss_status_t		status = NSS_NOTFOUND;
6380Sstevel@tonic-gate 
6390Sstevel@tonic-gate #ifdef DEBUG
6400Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: netgr_in]\n");
6410Sstevel@tonic-gate 	(void) fprintf(stdout, "\tmachine: argc[%d]='%s' user: "
6424953Smichen 	    "argc[%d]='%s',\n\tdomain:argc[%d]='%s' "
6434953Smichen 	    "netgroup: argc[%d]='%s'\n",
6444953Smichen 	    NSS_NETGR_MACHINE,
6454953Smichen 	    PRINT_VAL(ia->arg[NSS_NETGR_MACHINE]),
6464953Smichen 	    NSS_NETGR_USER,
6474953Smichen 	    PRINT_VAL(ia->arg[NSS_NETGR_USER]),
6484953Smichen 	    NSS_NETGR_DOMAIN,
6494953Smichen 	    PRINT_VAL(ia->arg[NSS_NETGR_DOMAIN]),
6504953Smichen 	    NSS_NETGR_N,
6514953Smichen 	    PRINT_VAL(ia->arg[NSS_NETGR_N]));
6520Sstevel@tonic-gate 	(void) fprintf(stdout, "\tgroups='%s'\n", netgrname);
6530Sstevel@tonic-gate #endif	/* DEBUG */
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 	ia->status = NSS_NETGR_NO;
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate 	if (netgrname == NULL)
6580Sstevel@tonic-gate 		return (status);
6590Sstevel@tonic-gate 
6602388Smj162486 	return (top_down_search(ia, netgrname));
6610Sstevel@tonic-gate }
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate /*ARGSUSED0*/
6640Sstevel@tonic-gate static nss_status_t
netgr_in(ldap_backend_ptr be,void * a)6650Sstevel@tonic-gate netgr_in(ldap_backend_ptr be, void *a)
6660Sstevel@tonic-gate {
6670Sstevel@tonic-gate 	struct nss_innetgr_args	*ia = (struct nss_innetgr_args *)a;
6680Sstevel@tonic-gate 	int	i;
6690Sstevel@tonic-gate 	nss_status_t	rc = (nss_status_t)NSS_NOTFOUND;
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate 	ia->status = NSS_NETGR_NO;
6720Sstevel@tonic-gate 	for (i = 0; i < ia->groups.argc; i++) {
6730Sstevel@tonic-gate 		rc = __netgr_in(a, ia->groups.argv[i]);
6740Sstevel@tonic-gate 		if (ia->status == NSS_NETGR_FOUND)
6750Sstevel@tonic-gate 			return (NSS_SUCCESS);
6760Sstevel@tonic-gate 	}
6770Sstevel@tonic-gate 	return (rc);
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate /*
6810Sstevel@tonic-gate  *
6820Sstevel@tonic-gate  */
6830Sstevel@tonic-gate 
6840Sstevel@tonic-gate static nss_status_t
getnetgr_ldap_setent(ldap_backend_ptr be,void * a)6850Sstevel@tonic-gate getnetgr_ldap_setent(ldap_backend_ptr be, void *a)
6860Sstevel@tonic-gate {
6870Sstevel@tonic-gate 	const char	*netgroup = (const char *) a;
6880Sstevel@tonic-gate 	getnetgrent_cookie_t	*cookie;
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate #ifdef	DEBUG
6910Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_setent]\n");
6920Sstevel@tonic-gate #endif	/* DEBUG */
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 	cookie = (getnetgrent_cookie_t *)be->netgroup_cookie;
6950Sstevel@tonic-gate 	if (cookie != NULL && cookie->netgroup != NULL) {
6960Sstevel@tonic-gate 		/* is this another set on the same netgroup */
6970Sstevel@tonic-gate 		if (strcmp(cookie->netgroup, netgroup) == 0)
6980Sstevel@tonic-gate 			return ((nss_status_t)NSS_SUCCESS);
6990Sstevel@tonic-gate 	}
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 	return (NSS_NOTFOUND);
7020Sstevel@tonic-gate }
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate static void
free_getnetgrent_cookie(getnetgrent_cookie_t ** cookie)7050Sstevel@tonic-gate free_getnetgrent_cookie(getnetgrent_cookie_t **cookie)
7060Sstevel@tonic-gate {
7070Sstevel@tonic-gate 	getnetgrent_cookie_t *p = *cookie;
7080Sstevel@tonic-gate 
7090Sstevel@tonic-gate #ifdef DEBUG
7100Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: free_getnetgrent_cookie]\n");
7110Sstevel@tonic-gate #endif	/* DEBUG */
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate 	if (p == NULL)
7140Sstevel@tonic-gate 		return;
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&p->results);
7170Sstevel@tonic-gate 	free_netgroup_table(&p->tab);
7180Sstevel@tonic-gate 	free(p->netgroup);
7190Sstevel@tonic-gate 	free(p);
7200Sstevel@tonic-gate 	*cookie = NULL;
7210Sstevel@tonic-gate }
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate /*ARGSUSED1*/
7240Sstevel@tonic-gate static nss_status_t
getnetgr_ldap_endent(ldap_backend_ptr be,void * a)7250Sstevel@tonic-gate getnetgr_ldap_endent(ldap_backend_ptr be, void *a)
7260Sstevel@tonic-gate {
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate #ifdef	DEBUG
7290Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_endent]\n");
7300Sstevel@tonic-gate #endif	/* DEBUG */
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate 	free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 	return ((nss_status_t)NSS_NOTFOUND);
7350Sstevel@tonic-gate }
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate 
7380Sstevel@tonic-gate /*ARGSUSED1*/
7390Sstevel@tonic-gate static nss_status_t
getnetgr_ldap_destr(ldap_backend_ptr be,void * a)7400Sstevel@tonic-gate getnetgr_ldap_destr(ldap_backend_ptr be, void *a)
7410Sstevel@tonic-gate {
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate #ifdef	DEBUG
7440Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_destr]\n");
7450Sstevel@tonic-gate #endif	/* DEBUG */
7460Sstevel@tonic-gate 
7470Sstevel@tonic-gate 	free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
7480Sstevel@tonic-gate 	free(be);
7490Sstevel@tonic-gate 
7500Sstevel@tonic-gate 	return ((nss_status_t)NSS_NOTFOUND);
7510Sstevel@tonic-gate }
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate static nss_status_t
getnetgr_ldap_getent(ldap_backend_ptr be,void * a)7550Sstevel@tonic-gate getnetgr_ldap_getent(ldap_backend_ptr be, void *a)
7560Sstevel@tonic-gate {
7570Sstevel@tonic-gate 	struct nss_getnetgrent_args	*args;
7580Sstevel@tonic-gate 	getnetgrent_cookie_t	*p;
7590Sstevel@tonic-gate 	char			searchfilter[SEARCHFILTERLEN];
7600Sstevel@tonic-gate 	char			userdata[SEARCHFILTERLEN];
7610Sstevel@tonic-gate 	char			name[SEARCHFILTERLEN];
7620Sstevel@tonic-gate 	int			rc;
7630Sstevel@tonic-gate 	ns_ldap_result_t	*result = NULL;
7640Sstevel@tonic-gate 	ns_ldap_error_t		*error = NULL;
7650Sstevel@tonic-gate 	char			**attrs;
7660Sstevel@tonic-gate 	char			*hostname, *username, *domain;
7670Sstevel@tonic-gate 	char			*buffer;
7680Sstevel@tonic-gate 	nss_status_t		status = NSS_SUCCESS;
7690Sstevel@tonic-gate 	netgroup_name_t		*ng;
7700Sstevel@tonic-gate 	int			ret;
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate #ifdef	DEBUG
7730Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_getent]\n");
7740Sstevel@tonic-gate #endif	/* DEBUG */
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 	args = (struct nss_getnetgrent_args *)a;
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 	args->status = NSS_NETGR_NO;
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	p = (getnetgrent_cookie_t *)be->netgroup_cookie;
7810Sstevel@tonic-gate 	if (p == NULL)
7820Sstevel@tonic-gate 		return ((nss_status_t)NSS_SUCCESS);
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 	for (;;) {
785*8777SSerge.Dussud@Sun.COM 		/*
786*8777SSerge.Dussud@Sun.COM 		 * Search through each netgroup consecutively: only search
787*8777SSerge.Dussud@Sun.COM 		 * next netgroup when results from previous netgroup are
788*8777SSerge.Dussud@Sun.COM 		 * processed.
789*8777SSerge.Dussud@Sun.COM 		 * Needed for nested netgroup (memberNisNetgroup attributes).
790*8777SSerge.Dussud@Sun.COM 		 */
791*8777SSerge.Dussud@Sun.COM 		if (p->results == NULL) {
792*8777SSerge.Dussud@Sun.COM 			if ((ng = get_next_netgroup(&p->tab)) != NULL) {
793*8777SSerge.Dussud@Sun.COM 				if (_ldap_filter_name(name, ng->name,
794*8777SSerge.Dussud@Sun.COM 				    sizeof (name)) != 0)
795*8777SSerge.Dussud@Sun.COM 					break;
7960Sstevel@tonic-gate 
797*8777SSerge.Dussud@Sun.COM 				ret = snprintf(searchfilter,
798*8777SSerge.Dussud@Sun.COM 				    sizeof (searchfilter),
799*8777SSerge.Dussud@Sun.COM 				    _F_SETMEMBER, name);
800*8777SSerge.Dussud@Sun.COM 				if (ret >= sizeof (searchfilter) || ret < 0)
801*8777SSerge.Dussud@Sun.COM 					break;
8020Sstevel@tonic-gate 
803*8777SSerge.Dussud@Sun.COM #ifdef DEBUG
804*8777SSerge.Dussud@Sun.COM 				syslog(LOG_DEBUG, "nss_ldap: "
805*8777SSerge.Dussud@Sun.COM 				    "getnetgr_ldap_getent: "
806*8777SSerge.Dussud@Sun.COM 				    "netgroup name: %s", name);
807*8777SSerge.Dussud@Sun.COM #endif
808*8777SSerge.Dussud@Sun.COM 				ret = snprintf(userdata, sizeof (userdata),
809*8777SSerge.Dussud@Sun.COM 				    _F_SETMEMBER_SSD, name);
810*8777SSerge.Dussud@Sun.COM 				if (ret >= sizeof (userdata) || ret < 0)
811*8777SSerge.Dussud@Sun.COM 					break;
8120Sstevel@tonic-gate 
813*8777SSerge.Dussud@Sun.COM 				result = NULL;
814*8777SSerge.Dussud@Sun.COM 				rc = __ns_ldap_list(_NETGROUP, searchfilter,
815*8777SSerge.Dussud@Sun.COM 				    _merge_SSD_filter, netgrent_attrs, NULL,
816*8777SSerge.Dussud@Sun.COM 				    0, &result, &error, NULL, userdata);
817*8777SSerge.Dussud@Sun.COM 				(void) __ns_ldap_freeError(&error);
8180Sstevel@tonic-gate 
819*8777SSerge.Dussud@Sun.COM 				if (rc == NS_LDAP_SUCCESS && result != NULL) {
820*8777SSerge.Dussud@Sun.COM 					p->results = result;
821*8777SSerge.Dussud@Sun.COM 				} else {
822*8777SSerge.Dussud@Sun.COM #ifdef DEBUG
823*8777SSerge.Dussud@Sun.COM 					syslog(LOG_DEBUG, "nss_ldap: "
824*8777SSerge.Dussud@Sun.COM 					    "getnetgr_ldap_getent: "
825*8777SSerge.Dussud@Sun.COM 					    "__ns_ldap_list() returned %d "
826*8777SSerge.Dussud@Sun.COM 					    "(result: 0x%x)", rc, result);
827*8777SSerge.Dussud@Sun.COM #endif
828*8777SSerge.Dussud@Sun.COM 					/*
829*8777SSerge.Dussud@Sun.COM 					 * Will exit when no more netgroup
830*8777SSerge.Dussud@Sun.COM 					 * to search and no more p->results
831*8777SSerge.Dussud@Sun.COM 					 * to process.
832*8777SSerge.Dussud@Sun.COM 					 */
833*8777SSerge.Dussud@Sun.COM 					(void) __ns_ldap_freeResult(&result);
834*8777SSerge.Dussud@Sun.COM 				}
835*8777SSerge.Dussud@Sun.COM 			} else { /* no more netgroup to process */
836*8777SSerge.Dussud@Sun.COM 				/*
837*8777SSerge.Dussud@Sun.COM 				 * If no more results to process, and since
838*8777SSerge.Dussud@Sun.COM 				 * there's no more netgroup to process either,
839*8777SSerge.Dussud@Sun.COM 				 * then it's time to break and exit the for
840*8777SSerge.Dussud@Sun.COM 				 * loop.
841*8777SSerge.Dussud@Sun.COM 				 */
842*8777SSerge.Dussud@Sun.COM #ifdef DEBUG
843*8777SSerge.Dussud@Sun.COM 				syslog(LOG_DEBUG, "nss_ldap: "
844*8777SSerge.Dussud@Sun.COM 				    "getnetgr_ldap_getent: no more netgroup "
845*8777SSerge.Dussud@Sun.COM 				    "to process, p->results: 0x%x",
846*8777SSerge.Dussud@Sun.COM 				    p->results);
847*8777SSerge.Dussud@Sun.COM #endif
848*8777SSerge.Dussud@Sun.COM 				if (p->results == NULL)
849*8777SSerge.Dussud@Sun.COM 					break;
8504953Smichen 			}
8510Sstevel@tonic-gate 		}
8524953Smichen 		if (p->results == NULL)
8534953Smichen 			continue;
8540Sstevel@tonic-gate 
8554953Smichen 		if (p->entry == NULL)
8564953Smichen 			p->entry = p->results->entry;
8570Sstevel@tonic-gate 
8584953Smichen 		if (p->entry == NULL)
8594953Smichen 			continue;
8600Sstevel@tonic-gate 
8614953Smichen 		if (p->attrs == NULL) {
8624953Smichen 			attrs = __ns_ldap_getAttr(p->entry, _N_TRIPLE);
8634953Smichen 			if (attrs != NULL && *attrs != NULL)
8644953Smichen 				p->attrs = attrs;
8650Sstevel@tonic-gate 		}
8660Sstevel@tonic-gate 
8674953Smichen 		if (p->attrs != NULL) {
8684953Smichen 			attrs = p->attrs;
8694953Smichen 			buffer = args->buffer;
8704953Smichen 
8714953Smichen 			if (strlcpy(buffer, *attrs, args->buflen) >=
8724953Smichen 			    args->buflen) {
8734953Smichen 				status = NSS_STR_PARSE_ERANGE;
8744953Smichen 				break;
8754953Smichen 			}
8760Sstevel@tonic-gate 
8774953Smichen 			rc = split_triple(buffer, &hostname, &username,
8784953Smichen 			    &domain);
8794953Smichen 			attrs++;
8804953Smichen 			if (attrs != NULL && *attrs != NULL)
8814953Smichen 				p->attrs = attrs;
8824953Smichen 			else
8834953Smichen 				p->attrs = NULL;
8844953Smichen 			if (rc == 0) {
8854953Smichen 				args->retp[NSS_NETGR_MACHINE] = hostname;
8864953Smichen 				args->retp[NSS_NETGR_USER] = username;
8874953Smichen 				args->retp[NSS_NETGR_DOMAIN] = domain;
8884953Smichen 				args->status = NSS_NETGR_FOUND;
889*8777SSerge.Dussud@Sun.COM #ifdef DEBUG
890*8777SSerge.Dussud@Sun.COM 				syslog(LOG_DEBUG, "nss_ldap: "
891*8777SSerge.Dussud@Sun.COM 				    "getnetgr_ldap_getent: found triple "
892*8777SSerge.Dussud@Sun.COM 				    "(%s, %s, %s), 0x%x to process",
893*8777SSerge.Dussud@Sun.COM 				    hostname ? hostname : "",
894*8777SSerge.Dussud@Sun.COM 				    username ? username : "",
895*8777SSerge.Dussud@Sun.COM 				    domain ? domain : "",
896*8777SSerge.Dussud@Sun.COM 				    p->attrs);
897*8777SSerge.Dussud@Sun.COM #endif
8984953Smichen 				if (p->attrs != NULL)
8994953Smichen 					break;
9004953Smichen 			}
9010Sstevel@tonic-gate 		}
9020Sstevel@tonic-gate 
9034953Smichen 		if (p->attrs == NULL) {
9044953Smichen 			rc = add_netgroup_member_entry(p->entry, &p->tab);
9054953Smichen 			if (rc != 0) {
9064953Smichen 				args->status = NSS_NETGR_NO;
9074953Smichen 				break;
9084953Smichen 			}
9094953Smichen 
9104953Smichen 			p->entry = p->entry->next;
9114953Smichen 			if (p->entry == NULL)
9124953Smichen 				(void) __ns_ldap_freeResult(&p->results);
9134953Smichen 			if (args->status == NSS_NETGR_FOUND)
9144953Smichen 				break;
9154953Smichen 		}
9160Sstevel@tonic-gate 	}
9170Sstevel@tonic-gate 
9180Sstevel@tonic-gate 	return (status);
9190Sstevel@tonic-gate }
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate static ldap_backend_op_t getnetgroup_ops[] = {
9220Sstevel@tonic-gate 	getnetgr_ldap_destr,
9230Sstevel@tonic-gate 	getnetgr_ldap_endent,
9240Sstevel@tonic-gate 	getnetgr_ldap_setent,
9250Sstevel@tonic-gate 	getnetgr_ldap_getent,
9260Sstevel@tonic-gate };
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate /*
9290Sstevel@tonic-gate  *
9300Sstevel@tonic-gate  */
9310Sstevel@tonic-gate 
9320Sstevel@tonic-gate static nss_status_t
netgr_set(ldap_backend_ptr be,void * a)9330Sstevel@tonic-gate netgr_set(ldap_backend_ptr be, void *a)
9340Sstevel@tonic-gate {
9350Sstevel@tonic-gate 	struct nss_setnetgrent_args	*args =
9364953Smichen 	    (struct nss_setnetgrent_args *)a;
9370Sstevel@tonic-gate 	ldap_backend_ptr		get_be;
9380Sstevel@tonic-gate 	getnetgrent_cookie_t		*p;
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate #ifdef DEBUG
9410Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: netgr_set]\n");
9420Sstevel@tonic-gate 	(void) fprintf(stdout,
9434953Smichen 	    "\targs->netgroup: %s\n", ISNULL(args->netgroup));
9440Sstevel@tonic-gate #endif /* DEBUG */
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate 	if (args->netgroup == NULL)
9470Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
9480Sstevel@tonic-gate 
9490Sstevel@tonic-gate 	free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
9500Sstevel@tonic-gate 	p = (getnetgrent_cookie_t *)calloc(1, sizeof (getnetgrent_cookie_t));
9510Sstevel@tonic-gate 	if (p == NULL)
9520Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
9530Sstevel@tonic-gate 	p->netgroup = strdup(args->netgroup);
9540Sstevel@tonic-gate 	if (p->netgroup == NULL) {
9550Sstevel@tonic-gate 		free(p);
9560Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
9570Sstevel@tonic-gate 	}
9580Sstevel@tonic-gate 	if (add_netgroup_name(args->netgroup, &p->tab) == -1) {
9590Sstevel@tonic-gate 		free_getnetgrent_cookie(&p);
9600Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
9610Sstevel@tonic-gate 	}
9620Sstevel@tonic-gate 
9630Sstevel@tonic-gate 	/* now allocate and return iteration backend structure */
9640Sstevel@tonic-gate 	if ((get_be = (ldap_backend_ptr)malloc(sizeof (*get_be))) == NULL)
9650Sstevel@tonic-gate 		return (NSS_UNAVAIL);
9660Sstevel@tonic-gate 	get_be->ops = getnetgroup_ops;
9670Sstevel@tonic-gate 	get_be->nops = sizeof (getnetgroup_ops) / sizeof (getnetgroup_ops[0]);
9680Sstevel@tonic-gate 	get_be->tablename = NULL;
9690Sstevel@tonic-gate 	get_be->attrs = netgrent_attrs;
9700Sstevel@tonic-gate 	get_be->result = NULL;
9712830Sdjl 	get_be->ldapobj2str = NULL;
9720Sstevel@tonic-gate 	get_be->setcalled = 1;
9730Sstevel@tonic-gate 	get_be->filter = NULL;
9740Sstevel@tonic-gate 	get_be->toglue = NULL;
9750Sstevel@tonic-gate 	get_be->enumcookie = NULL;
9760Sstevel@tonic-gate 	get_be->netgroup_cookie = p;
9770Sstevel@tonic-gate 	args->iterator = (nss_backend_t *)get_be;
9780Sstevel@tonic-gate 
9790Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate 	return (NSS_SUCCESS);
9820Sstevel@tonic-gate }
9830Sstevel@tonic-gate 
9840Sstevel@tonic-gate 
9850Sstevel@tonic-gate /*ARGSUSED1*/
9860Sstevel@tonic-gate static nss_status_t
netgr_ldap_destr(ldap_backend_ptr be,void * a)9870Sstevel@tonic-gate netgr_ldap_destr(ldap_backend_ptr be, void *a)
9880Sstevel@tonic-gate {
9890Sstevel@tonic-gate 
9900Sstevel@tonic-gate #ifdef	DEBUG
9910Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getnetgrent.c: netgr_ldap_destr]\n");
9920Sstevel@tonic-gate #endif	/* DEBUG */
9930Sstevel@tonic-gate 
9940Sstevel@tonic-gate 	(void) _clean_ldap_backend(be);
9950Sstevel@tonic-gate 
9960Sstevel@tonic-gate 	return ((nss_status_t)NSS_NOTFOUND);
9970Sstevel@tonic-gate }
9980Sstevel@tonic-gate 
9990Sstevel@tonic-gate 
10000Sstevel@tonic-gate 
10010Sstevel@tonic-gate 
10020Sstevel@tonic-gate static ldap_backend_op_t netgroup_ops[] = {
10030Sstevel@tonic-gate 	netgr_ldap_destr,
10040Sstevel@tonic-gate 	0,
10050Sstevel@tonic-gate 	0,
10060Sstevel@tonic-gate 	0,
10070Sstevel@tonic-gate 	netgr_in,		/*	innetgr()	*/
10080Sstevel@tonic-gate 	netgr_set		/*	setnetgrent()	*/
10090Sstevel@tonic-gate };
10100Sstevel@tonic-gate 
10110Sstevel@tonic-gate 
10120Sstevel@tonic-gate /*
10130Sstevel@tonic-gate  * _nss_ldap_netgroup_constr is where life begins. This function calls the
10140Sstevel@tonic-gate  * generic ldap constructor function to define and build the abstract data
10150Sstevel@tonic-gate  * types required to support ldap operations.
10160Sstevel@tonic-gate  */
10170Sstevel@tonic-gate 
10180Sstevel@tonic-gate /*ARGSUSED0*/
10190Sstevel@tonic-gate nss_backend_t *
_nss_ldap_netgroup_constr(const char * dummy1,const char * dummy2,const char * dummy3)10200Sstevel@tonic-gate _nss_ldap_netgroup_constr(const char *dummy1, const char *dummy2,
10210Sstevel@tonic-gate 			const char *dummy3)
10220Sstevel@tonic-gate {
10230Sstevel@tonic-gate 
10240Sstevel@tonic-gate #ifdef	DEBUG
10250Sstevel@tonic-gate 	(void) fprintf(stdout,
10264953Smichen 	    "\n[getnetgrent.c: _nss_ldap_netgroup_constr]\n");
10270Sstevel@tonic-gate #endif	/* DEBUG */
10280Sstevel@tonic-gate 
10290Sstevel@tonic-gate 	return ((nss_backend_t *)_nss_ldap_constr(netgroup_ops,
10304953Smichen 	    sizeof (netgroup_ops)/sizeof (netgroup_ops[0]), _NETGROUP,
10314953Smichen 	    netgrent_attrs, NULL));
10320Sstevel@tonic-gate }
1033