xref: /titanic_44/usr/src/lib/libsldap/common/ns_reads.c (revision 9f2fd570dfad3c35512617ae887140b15e3ec4c5)
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
5f8f1c176Svt115884  * Common Development and Distribution License (the "License").
6f8f1c176Svt115884  * 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*9f2fd570SJulian Pullen  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #include <stdio.h>
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <libintl.h>
297c478bd9Sstevel@tonic-gate #include <ctype.h>
307c478bd9Sstevel@tonic-gate #include <syslog.h>
317c478bd9Sstevel@tonic-gate #include <sys/stat.h>
327c478bd9Sstevel@tonic-gate #include <fcntl.h>
337c478bd9Sstevel@tonic-gate #include <unistd.h>
347c478bd9Sstevel@tonic-gate #include <string.h>
357c478bd9Sstevel@tonic-gate #include <strings.h>
36b57459abSJulian Pullen #include <priv.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #include "ns_sldap.h"
397c478bd9Sstevel@tonic-gate #include "ns_internal.h"
407c478bd9Sstevel@tonic-gate #include "ns_cache_door.h"
41e1dd0a2fSth160488 #include "ns_connmgmt.h"
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #define	_NIS_FILTER	"nisdomain=*"
447c478bd9Sstevel@tonic-gate #define	_NIS_DOMAIN	"nisdomain"
457c478bd9Sstevel@tonic-gate static const char *nis_domain_attrs[] = {
467c478bd9Sstevel@tonic-gate 	_NIS_DOMAIN,
477c478bd9Sstevel@tonic-gate 	(char *)NULL
487c478bd9Sstevel@tonic-gate };
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate static int validate_filter(ns_ldap_cookie_t *cookie);
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate void
__ns_ldap_freeEntry(ns_ldap_entry_t * ep)537c478bd9Sstevel@tonic-gate __ns_ldap_freeEntry(ns_ldap_entry_t *ep)
547c478bd9Sstevel@tonic-gate {
557c478bd9Sstevel@tonic-gate 	int		j, k = 0;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate 	if (ep == NULL)
587c478bd9Sstevel@tonic-gate 		return;
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate 	if (ep->attr_pair == NULL) {
617c478bd9Sstevel@tonic-gate 		free(ep);
627c478bd9Sstevel@tonic-gate 		return;
637c478bd9Sstevel@tonic-gate 	}
647c478bd9Sstevel@tonic-gate 	for (j = 0; j < ep->attr_count; j++) {
657c478bd9Sstevel@tonic-gate 		if (ep->attr_pair[j] == NULL)
667c478bd9Sstevel@tonic-gate 			continue;
677c478bd9Sstevel@tonic-gate 		if (ep->attr_pair[j]->attrname)
687c478bd9Sstevel@tonic-gate 			free(ep->attr_pair[j]->attrname);
697c478bd9Sstevel@tonic-gate 		if (ep->attr_pair[j]->attrvalue) {
707c478bd9Sstevel@tonic-gate 			for (k = 0; (k < ep->attr_pair[j]->value_count) &&
717c478bd9Sstevel@tonic-gate 			    (ep->attr_pair[j]->attrvalue[k]); k++) {
727c478bd9Sstevel@tonic-gate 				free(ep->attr_pair[j]->attrvalue[k]);
737c478bd9Sstevel@tonic-gate 			}
747c478bd9Sstevel@tonic-gate 			free(ep->attr_pair[j]->attrvalue);
757c478bd9Sstevel@tonic-gate 		}
767c478bd9Sstevel@tonic-gate 		free(ep->attr_pair[j]);
777c478bd9Sstevel@tonic-gate 	}
787c478bd9Sstevel@tonic-gate 	free(ep->attr_pair);
797c478bd9Sstevel@tonic-gate 	free(ep);
807c478bd9Sstevel@tonic-gate }
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate static void
_freeControlList(LDAPControl *** ctrls)837c478bd9Sstevel@tonic-gate _freeControlList(LDAPControl ***ctrls)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 	LDAPControl	**ctrl;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	if (ctrls == NULL || *ctrls == NULL)
887c478bd9Sstevel@tonic-gate 		return;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	for (ctrl = *ctrls; *ctrl != NULL; ctrl++)
917c478bd9Sstevel@tonic-gate 		ldap_control_free(*ctrl);
927c478bd9Sstevel@tonic-gate 	free(*ctrls);
937c478bd9Sstevel@tonic-gate 	*ctrls = NULL;
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate  * Convert attribute type in a RDN that has an attribute mapping to the
977c478bd9Sstevel@tonic-gate  * original mappped type.
987c478bd9Sstevel@tonic-gate  * e.g.
997c478bd9Sstevel@tonic-gate  * cn<->cn-st and iphostnumber<->iphostnumber-st
1007c478bd9Sstevel@tonic-gate  * cn-st=aaa+iphostnumber-st=10.10.01.01
1017c478bd9Sstevel@tonic-gate  * is mapped to
1027c478bd9Sstevel@tonic-gate  * cn=aaa+iphostnumber=10.10.01.01
1037c478bd9Sstevel@tonic-gate  *
1047c478bd9Sstevel@tonic-gate  * Input - service: e.g. hosts, passwd etc.
1057c478bd9Sstevel@tonic-gate  *         rdn: RDN
1067c478bd9Sstevel@tonic-gate  * Return: NULL - No attribute mapping in the RDN
1077c478bd9Sstevel@tonic-gate  *         Non-NULL - The attribute type(s) in the RDN are mapped and
1087c478bd9Sstevel@tonic-gate  *                    the memory is allocated for the new rdn.
1097c478bd9Sstevel@tonic-gate  *
1107c478bd9Sstevel@tonic-gate  */
1117c478bd9Sstevel@tonic-gate static char *
_cvtRDN(const char * service,const char * rdn)1127c478bd9Sstevel@tonic-gate _cvtRDN(const char *service, const char *rdn) {
1137c478bd9Sstevel@tonic-gate 	char	**attrs, **mapped_attrs, **mapp, *type, *value, *attr;
1147c478bd9Sstevel@tonic-gate 	char	*new_rdn = NULL;
1157c478bd9Sstevel@tonic-gate 	int	nAttr = 0, i, attr_mapped, len = 0;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	/* Break down "type=value\0" pairs. Assume RDN is normalized */
1187c478bd9Sstevel@tonic-gate 	if ((attrs = ldap_explode_rdn(rdn, 0)) == NULL)
1197c478bd9Sstevel@tonic-gate 		return (NULL);
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	for (nAttr = 0; attrs[nAttr] != NULL; nAttr++);
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	if ((mapped_attrs = (char **)calloc(nAttr, sizeof (char *))) == NULL) {
1247c478bd9Sstevel@tonic-gate 		ldap_value_free(attrs);
1257c478bd9Sstevel@tonic-gate 		return (NULL);
1267c478bd9Sstevel@tonic-gate 	}
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	attr_mapped = 0;
1297c478bd9Sstevel@tonic-gate 	for (i = 0; i < nAttr; i++) {
1307c478bd9Sstevel@tonic-gate 		/* Parse type=value pair */
1317c478bd9Sstevel@tonic-gate 		if ((type = strtok_r(attrs[i], "=", &value)) == NULL ||
1327c478bd9Sstevel@tonic-gate 					value == NULL)
1337c478bd9Sstevel@tonic-gate 			goto cleanup;
1347c478bd9Sstevel@tonic-gate 		/* Reverse map: e.g. cn-sm -> cn */
1357c478bd9Sstevel@tonic-gate 		mapp = __ns_ldap_getOrigAttribute(service, type);
1367c478bd9Sstevel@tonic-gate 		if (mapp != NULL && mapp[0] != NULL) {
1377c478bd9Sstevel@tonic-gate 			/* The attribute mapping is found */
1387c478bd9Sstevel@tonic-gate 			type = mapp[0];
1397c478bd9Sstevel@tonic-gate 			attr_mapped = 1;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 			/* "type=value\0" */
1427c478bd9Sstevel@tonic-gate 			len = strlen(type) + strlen(value) + 2;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 			/* Reconstruct type=value pair. A string is allocated */
1457c478bd9Sstevel@tonic-gate 			if ((attr = (char *)calloc(1, len)) == NULL) {
1467c478bd9Sstevel@tonic-gate 				__s_api_free2dArray(mapp);
1477c478bd9Sstevel@tonic-gate 				goto cleanup;
1487c478bd9Sstevel@tonic-gate 			}
1497c478bd9Sstevel@tonic-gate 			(void) snprintf(attr, len, "%s=%s",
1507c478bd9Sstevel@tonic-gate 						type, value);
1517c478bd9Sstevel@tonic-gate 			mapped_attrs[i] = attr;
1527c478bd9Sstevel@tonic-gate 		} else {
1537c478bd9Sstevel@tonic-gate 			/*
1547c478bd9Sstevel@tonic-gate 			 * No attribute mapping. attrs[i] is going to be copied
1557c478bd9Sstevel@tonic-gate 			 * later. Restore "type\0value\0" back to
1567c478bd9Sstevel@tonic-gate 			 * "type=value\0".
1577c478bd9Sstevel@tonic-gate 			 */
1587c478bd9Sstevel@tonic-gate 			type[strlen(type)] = '=';
1597c478bd9Sstevel@tonic-gate 		}
1607c478bd9Sstevel@tonic-gate 		__s_api_free2dArray(mapp);
1617c478bd9Sstevel@tonic-gate 	}
1627c478bd9Sstevel@tonic-gate 	if (attr_mapped == 0)
1637c478bd9Sstevel@tonic-gate 		/* No attribute mapping. Don't bother to reconstruct RDN */
1647c478bd9Sstevel@tonic-gate 		goto cleanup;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	len = 0;
1677c478bd9Sstevel@tonic-gate 	/* Reconstruct RDN from type=value pairs */
1687c478bd9Sstevel@tonic-gate 	for (i = 0; i < nAttr; i++) {
1697c478bd9Sstevel@tonic-gate 		if (mapped_attrs[i])
1707c478bd9Sstevel@tonic-gate 			len += strlen(mapped_attrs[i]);
1717c478bd9Sstevel@tonic-gate 		else
1727c478bd9Sstevel@tonic-gate 			len += strlen(attrs[i]);
1737c478bd9Sstevel@tonic-gate 		/* Add 1 for "+" */
1747c478bd9Sstevel@tonic-gate 		len++;
1757c478bd9Sstevel@tonic-gate 	}
1767c478bd9Sstevel@tonic-gate 	if ((new_rdn = (char *)calloc(1, ++len)) == NULL)
1777c478bd9Sstevel@tonic-gate 		goto cleanup;
1787c478bd9Sstevel@tonic-gate 	for (i = 0; i < nAttr; i++) {
1797c478bd9Sstevel@tonic-gate 		if (i > 0)
1807c478bd9Sstevel@tonic-gate 			/* Add seperator */
1817c478bd9Sstevel@tonic-gate 			(void) strlcat(new_rdn, "+", len);
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 		if (mapped_attrs[i])
1847c478bd9Sstevel@tonic-gate 			(void) strlcat(new_rdn, mapped_attrs[i], len);
1857c478bd9Sstevel@tonic-gate 		else
1867c478bd9Sstevel@tonic-gate 			(void) strlcat(new_rdn, attrs[i], len);
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	}
1897c478bd9Sstevel@tonic-gate cleanup:
1907c478bd9Sstevel@tonic-gate 	ldap_value_free(attrs);
1917c478bd9Sstevel@tonic-gate 	if (mapped_attrs) {
1927c478bd9Sstevel@tonic-gate 		if (attr_mapped) {
1937c478bd9Sstevel@tonic-gate 			for (i = 0; i < nAttr; i++) {
1947c478bd9Sstevel@tonic-gate 				if (mapped_attrs[i])
1957c478bd9Sstevel@tonic-gate 					free(mapped_attrs[i]);
1967c478bd9Sstevel@tonic-gate 			}
1977c478bd9Sstevel@tonic-gate 		}
1987c478bd9Sstevel@tonic-gate 		free(mapped_attrs);
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	return (new_rdn);
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate  * Convert attribute type in a DN that has an attribute mapping to the
2057c478bd9Sstevel@tonic-gate  * original mappped type.
2067c478bd9Sstevel@tonic-gate  * e.g
2077c478bd9Sstevel@tonic-gate  * The mappings are cn<->cn-sm, iphostnumber<->iphostnumber-sm
2087c478bd9Sstevel@tonic-gate  *
2097c478bd9Sstevel@tonic-gate  * dn: cn-sm=aaa+iphostnumber-sm=9.9.9.9,dc=central,dc=sun,dc=com
2107c478bd9Sstevel@tonic-gate  * is converted to
2117c478bd9Sstevel@tonic-gate  * dn: cn=aaa+iphostnumber=9.9.9.9,dc=central,dc=sun,dc=com
2127c478bd9Sstevel@tonic-gate  *
2137c478bd9Sstevel@tonic-gate  * Input - service: e.g. hosts, passwd etc.
2147c478bd9Sstevel@tonic-gate  *         dn: the value of a distinguished name
2157c478bd9Sstevel@tonic-gate  * Return - NULL: error
2167c478bd9Sstevel@tonic-gate  *          non-NULL: A converted DN and the memory is allocated
2177c478bd9Sstevel@tonic-gate  */
2187c478bd9Sstevel@tonic-gate static char *
_cvtDN(const char * service,const char * dn)2197c478bd9Sstevel@tonic-gate _cvtDN(const char *service, const char *dn) {
2207c478bd9Sstevel@tonic-gate 	char	**mapped_rdns;
2217c478bd9Sstevel@tonic-gate 	char	**rdns, *new_rdn, *new_dn = NULL;
2227c478bd9Sstevel@tonic-gate 	int	nRdn = 0, i, len = 0, rdn_mapped;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	if (service == NULL || dn == NULL)
2257c478bd9Sstevel@tonic-gate 		return (NULL);
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	if ((rdns = ldap_explode_dn(dn, 0)) == NULL)
2287c478bd9Sstevel@tonic-gate 		return (NULL);
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	for (nRdn = 0; rdns[nRdn] != NULL; nRdn++);
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	if ((mapped_rdns = (char **)calloc(nRdn, sizeof (char *))) == NULL) {
2337c478bd9Sstevel@tonic-gate 		ldap_value_free(rdns);
2347c478bd9Sstevel@tonic-gate 		return (NULL);
2357c478bd9Sstevel@tonic-gate 	}
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	rdn_mapped = 0;
2387c478bd9Sstevel@tonic-gate 	/* Break down RDNs in a DN */
2397c478bd9Sstevel@tonic-gate 	for (i = 0; i < nRdn; i++) {
2407c478bd9Sstevel@tonic-gate 		if ((new_rdn = _cvtRDN(service, rdns[i])) != NULL) {
2417c478bd9Sstevel@tonic-gate 			mapped_rdns[i] = new_rdn;
2427c478bd9Sstevel@tonic-gate 			rdn_mapped = 1;
2437c478bd9Sstevel@tonic-gate 		}
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 	if (rdn_mapped == 0) {
2467c478bd9Sstevel@tonic-gate 		/*
2477c478bd9Sstevel@tonic-gate 		 * No RDN contains any attribute mapping.
2487c478bd9Sstevel@tonic-gate 		 * Don't bother to reconstruct DN from RDN. Copy DN directly.
2497c478bd9Sstevel@tonic-gate 		 */
2507c478bd9Sstevel@tonic-gate 		new_dn = strdup(dn);
2517c478bd9Sstevel@tonic-gate 		goto cleanup;
2527c478bd9Sstevel@tonic-gate 	}
2537c478bd9Sstevel@tonic-gate 	/*
2547c478bd9Sstevel@tonic-gate 	 * Reconstruct dn from RDNs.
2557c478bd9Sstevel@tonic-gate 	 * Calculate the length first.
2567c478bd9Sstevel@tonic-gate 	 */
2577c478bd9Sstevel@tonic-gate 	for (i = 0; i < nRdn; i++) {
2587c478bd9Sstevel@tonic-gate 		if (mapped_rdns[i])
2597c478bd9Sstevel@tonic-gate 			len += strlen(mapped_rdns[i]);
2607c478bd9Sstevel@tonic-gate 		else
2617c478bd9Sstevel@tonic-gate 			len += strlen(rdns[i]);
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 		/* add 1 for ',' */
2647c478bd9Sstevel@tonic-gate 		len ++;
2657c478bd9Sstevel@tonic-gate 	}
2667c478bd9Sstevel@tonic-gate 	if ((new_dn = (char *)calloc(1, ++len)) == NULL)
2677c478bd9Sstevel@tonic-gate 		goto cleanup;
2687c478bd9Sstevel@tonic-gate 	for (i = 0; i < nRdn; i++) {
2697c478bd9Sstevel@tonic-gate 		if (i > 0)
2707c478bd9Sstevel@tonic-gate 			/* Add seperator */
2717c478bd9Sstevel@tonic-gate 			(void) strlcat(new_dn, ",", len);
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 		if (mapped_rdns[i])
2747c478bd9Sstevel@tonic-gate 			(void) strlcat(new_dn, mapped_rdns[i], len);
2757c478bd9Sstevel@tonic-gate 		else
2767c478bd9Sstevel@tonic-gate 			(void) strlcat(new_dn, rdns[i], len);
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	}
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate cleanup:
2817c478bd9Sstevel@tonic-gate 	ldap_value_free(rdns);
2827c478bd9Sstevel@tonic-gate 	if (mapped_rdns) {
2837c478bd9Sstevel@tonic-gate 		if (rdn_mapped) {
2847c478bd9Sstevel@tonic-gate 			for (i = 0; i < nRdn; i++) {
2857c478bd9Sstevel@tonic-gate 				if (mapped_rdns[i])
2867c478bd9Sstevel@tonic-gate 					free(mapped_rdns[i]);
2877c478bd9Sstevel@tonic-gate 			}
2887c478bd9Sstevel@tonic-gate 		}
2897c478bd9Sstevel@tonic-gate 		free(mapped_rdns);
2907c478bd9Sstevel@tonic-gate 	}
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	return (new_dn);
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate /*
2957c478bd9Sstevel@tonic-gate  * Convert a single ldap entry from a LDAPMessage
2967c478bd9Sstevel@tonic-gate  * into an ns_ldap_entry structure.
2977c478bd9Sstevel@tonic-gate  * Schema map the entry if specified in flags
2987c478bd9Sstevel@tonic-gate  */
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate static int
__s_api_cvtEntry(LDAP * ld,const char * service,LDAPMessage * e,int flags,ns_ldap_entry_t ** ret,ns_ldap_error_t ** error)3017c478bd9Sstevel@tonic-gate __s_api_cvtEntry(LDAP	*ld,
3027c478bd9Sstevel@tonic-gate 	const char	*service,
3037c478bd9Sstevel@tonic-gate 	LDAPMessage	*e,
3047c478bd9Sstevel@tonic-gate 	int		flags,
3057c478bd9Sstevel@tonic-gate 	ns_ldap_entry_t	**ret,
3067c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	**error)
3077c478bd9Sstevel@tonic-gate {
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	ns_ldap_entry_t	*ep = NULL;
3107c478bd9Sstevel@tonic-gate 	ns_ldap_attr_t	**ap = NULL;
3117c478bd9Sstevel@tonic-gate 	BerElement	*ber;
3127c478bd9Sstevel@tonic-gate 	char		*attr = NULL;
3137c478bd9Sstevel@tonic-gate 	char		**vals = NULL;
3147c478bd9Sstevel@tonic-gate 	char		**mapping;
3157c478bd9Sstevel@tonic-gate 	char		*dn;
3167c478bd9Sstevel@tonic-gate 	int		nAttrs = 0;
3177c478bd9Sstevel@tonic-gate 	int		i, j, k = 0;
3187c478bd9Sstevel@tonic-gate 	char		**gecos_mapping = NULL;
3197c478bd9Sstevel@tonic-gate 	int		gecos_val_index[3] = { -1, -1, -1};
3207c478bd9Sstevel@tonic-gate 	char		errstr[MAXERROR];
3217c478bd9Sstevel@tonic-gate 	int		schema_mapping_existed = FALSE;
3227c478bd9Sstevel@tonic-gate 	int		gecos_mapping_existed = FALSE;
3237c478bd9Sstevel@tonic-gate 	int		gecos_attr_matched;
3247c478bd9Sstevel@tonic-gate 	int		auto_service = FALSE;
3257c478bd9Sstevel@tonic-gate 	int		rc = NS_LDAP_SUCCESS;
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	if (e == NULL || ret == NULL || error == NULL)
3287c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	*error = NULL;
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	ep = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t));
3337c478bd9Sstevel@tonic-gate 	if (ep == NULL)
3347c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	if (service != NULL &&
3377c478bd9Sstevel@tonic-gate 	    (strncasecmp(service, "auto_", 5) == 0 ||
3387c478bd9Sstevel@tonic-gate 	    strcasecmp(service, "automount") == 0))
3397c478bd9Sstevel@tonic-gate 		auto_service = TRUE;
3407c478bd9Sstevel@tonic-gate 	/*
3417c478bd9Sstevel@tonic-gate 	 * see if schema mapping existed for the given service
3427c478bd9Sstevel@tonic-gate 	 */
3437c478bd9Sstevel@tonic-gate 	mapping = __ns_ldap_getOrigAttribute(service,
3447c478bd9Sstevel@tonic-gate 	    NS_HASH_SCHEMA_MAPPING_EXISTED);
3457c478bd9Sstevel@tonic-gate 	if (mapping) {
3467c478bd9Sstevel@tonic-gate 		schema_mapping_existed = TRUE;
3477c478bd9Sstevel@tonic-gate 		__s_api_free2dArray(mapping);
3487c478bd9Sstevel@tonic-gate 		mapping = NULL;
3497c478bd9Sstevel@tonic-gate 	} else if (auto_service) {
3507c478bd9Sstevel@tonic-gate 		/*
3517c478bd9Sstevel@tonic-gate 		 * If service == auto_* and no
3527c478bd9Sstevel@tonic-gate 		 * schema mapping found
3537c478bd9Sstevel@tonic-gate 		 * then try automount
3547c478bd9Sstevel@tonic-gate 		 * There is certain case that schema mapping exist
3557c478bd9Sstevel@tonic-gate 		 * but __ns_ldap_getOrigAttribute(service,
3567c478bd9Sstevel@tonic-gate 		 *	NS_HASH_SCHEMA_MAPPING_EXISTED);
3577c478bd9Sstevel@tonic-gate 		 * returns NULL.
3587c478bd9Sstevel@tonic-gate 		 * e.g.
3597c478bd9Sstevel@tonic-gate 		 * NS_LDAP_ATTRIBUTEMAP = automount:automountMapName=AAA
3607c478bd9Sstevel@tonic-gate 		 * NS_LDAP_OBJECTCLASSMAP = automount:automountMap=MynisMap
3617c478bd9Sstevel@tonic-gate 		 * NS_LDAP_OBJECTCLASSMAP = automount:automount=MynisObject
3627c478bd9Sstevel@tonic-gate 		 *
3637c478bd9Sstevel@tonic-gate 		 * Make a check for schema_mapping_existed here
3647c478bd9Sstevel@tonic-gate 		 * so later on __s_api_convert_automountmapname won't be called
3657c478bd9Sstevel@tonic-gate 		 * unnecessarily. It is also used for attribute mapping
3667c478bd9Sstevel@tonic-gate 		 * and objectclass mapping.
3677c478bd9Sstevel@tonic-gate 		 */
3687c478bd9Sstevel@tonic-gate 		mapping = __ns_ldap_getOrigAttribute("automount",
3697c478bd9Sstevel@tonic-gate 		    NS_HASH_SCHEMA_MAPPING_EXISTED);
3707c478bd9Sstevel@tonic-gate 		if (mapping) {
3717c478bd9Sstevel@tonic-gate 			schema_mapping_existed = TRUE;
3727c478bd9Sstevel@tonic-gate 			__s_api_free2dArray(mapping);
3737c478bd9Sstevel@tonic-gate 			mapping = NULL;
3747c478bd9Sstevel@tonic-gate 		}
3757c478bd9Sstevel@tonic-gate 	}
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	nAttrs = 1;  /* start with 1 for the DN attr */
3787c478bd9Sstevel@tonic-gate 	for (attr = ldap_first_attribute(ld, e, &ber); attr != NULL;
3797c478bd9Sstevel@tonic-gate 	    attr = ldap_next_attribute(ld, e, ber)) {
3807c478bd9Sstevel@tonic-gate 		nAttrs++;
3817c478bd9Sstevel@tonic-gate 		ldap_memfree(attr);
3827c478bd9Sstevel@tonic-gate 		attr = NULL;
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate 	ber_free(ber, 0);
3857c478bd9Sstevel@tonic-gate 	ber = NULL;
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	ep->attr_count = nAttrs;
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	/*
3907c478bd9Sstevel@tonic-gate 	 * add 1 for "gecos" 1 to N attribute mapping,
3917c478bd9Sstevel@tonic-gate 	 * just in case it is needed.
3927c478bd9Sstevel@tonic-gate 	 * ep->attr_count will be updated later if that is true.
3937c478bd9Sstevel@tonic-gate 	 */
3947c478bd9Sstevel@tonic-gate 	ap = (ns_ldap_attr_t **)calloc(ep->attr_count + 1,
3957c478bd9Sstevel@tonic-gate 	    sizeof (ns_ldap_attr_t *));
3967c478bd9Sstevel@tonic-gate 	if (ap == NULL) {
3977c478bd9Sstevel@tonic-gate 		__ns_ldap_freeEntry(ep);
3987c478bd9Sstevel@tonic-gate 		ep = NULL;
3997c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
4007c478bd9Sstevel@tonic-gate 	}
4017c478bd9Sstevel@tonic-gate 	ep->attr_pair = ap;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	/* DN attribute */
4047c478bd9Sstevel@tonic-gate 	dn = ldap_get_dn(ld, e);
4057c478bd9Sstevel@tonic-gate 	ap[0] = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
4067c478bd9Sstevel@tonic-gate 	if (ap[0] == NULL) {
4077c478bd9Sstevel@tonic-gate 		ldap_memfree(dn);
4087c478bd9Sstevel@tonic-gate 		dn = NULL;
4097c478bd9Sstevel@tonic-gate 		__ns_ldap_freeEntry(ep);
4107c478bd9Sstevel@tonic-gate 		ep = NULL;
4117c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
4127c478bd9Sstevel@tonic-gate 	}
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	if ((ap[0]->attrname = strdup("dn")) == NULL) {
4157c478bd9Sstevel@tonic-gate 		ldap_memfree(dn);
4167c478bd9Sstevel@tonic-gate 		dn = NULL;
4177c478bd9Sstevel@tonic-gate 		__ns_ldap_freeEntry(ep);
4187c478bd9Sstevel@tonic-gate 		ep = NULL;
4197c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
4207c478bd9Sstevel@tonic-gate 	}
4217c478bd9Sstevel@tonic-gate 	ap[0]->value_count = 1;
4227c478bd9Sstevel@tonic-gate 	if ((ap[0]->attrvalue = (char **)
4237c478bd9Sstevel@tonic-gate 	    calloc(2, sizeof (char *))) == NULL) {
4247c478bd9Sstevel@tonic-gate 		ldap_memfree(dn);
4257c478bd9Sstevel@tonic-gate 		dn = NULL;
4267c478bd9Sstevel@tonic-gate 		__ns_ldap_freeEntry(ep);
4277c478bd9Sstevel@tonic-gate 		ep = NULL;
4287c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
4297c478bd9Sstevel@tonic-gate 	}
4307c478bd9Sstevel@tonic-gate 
431f5c3c7a7Ssdussud 	if (schema_mapping_existed && ((flags & NS_LDAP_NOT_CVT_DN) == 0))
4327c478bd9Sstevel@tonic-gate 		ap[0]->attrvalue[0] = _cvtDN(service, dn);
4337c478bd9Sstevel@tonic-gate 	else
4347c478bd9Sstevel@tonic-gate 		ap[0]->attrvalue[0] = strdup(dn);
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	if (ap[0]->attrvalue[0] == NULL) {
4377c478bd9Sstevel@tonic-gate 		ldap_memfree(dn);
4387c478bd9Sstevel@tonic-gate 		dn = NULL;
4397c478bd9Sstevel@tonic-gate 		__ns_ldap_freeEntry(ep);
4407c478bd9Sstevel@tonic-gate 		ep = NULL;
4417c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
4427c478bd9Sstevel@tonic-gate 	}
4437c478bd9Sstevel@tonic-gate 	ldap_memfree(dn);
4447c478bd9Sstevel@tonic-gate 	dn = NULL;
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	if ((flags & NS_LDAP_NOMAP) == 0 && auto_service &&
4477c478bd9Sstevel@tonic-gate 	    schema_mapping_existed) {
4487c478bd9Sstevel@tonic-gate 		rc = __s_api_convert_automountmapname(service,
4497c478bd9Sstevel@tonic-gate 		    &ap[0]->attrvalue[0],
4507c478bd9Sstevel@tonic-gate 		    error);
4517c478bd9Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
4527c478bd9Sstevel@tonic-gate 			__ns_ldap_freeEntry(ep);
4537c478bd9Sstevel@tonic-gate 			ep = NULL;
4547c478bd9Sstevel@tonic-gate 			return (rc);
4557c478bd9Sstevel@tonic-gate 		}
4567c478bd9Sstevel@tonic-gate 	}
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	/* other attributes */
4597c478bd9Sstevel@tonic-gate 	for (attr = ldap_first_attribute(ld, e, &ber), j = 1;
4607c478bd9Sstevel@tonic-gate 	    attr != NULL && j != nAttrs;
4617c478bd9Sstevel@tonic-gate 	    attr = ldap_next_attribute(ld, e, ber), j++) {
4627c478bd9Sstevel@tonic-gate 		/* allocate new attr name */
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 		if ((ap[j] = (ns_ldap_attr_t *)
4657c478bd9Sstevel@tonic-gate 		    calloc(1, sizeof (ns_ldap_attr_t))) == NULL) {
4667c478bd9Sstevel@tonic-gate 			ber_free(ber, 0);
4677c478bd9Sstevel@tonic-gate 			ber = NULL;
4687c478bd9Sstevel@tonic-gate 			__ns_ldap_freeEntry(ep);
4697c478bd9Sstevel@tonic-gate 			ep = NULL;
4707c478bd9Sstevel@tonic-gate 			if (gecos_mapping)
4717c478bd9Sstevel@tonic-gate 				__s_api_free2dArray(gecos_mapping);
4727c478bd9Sstevel@tonic-gate 			gecos_mapping = NULL;
4737c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
4747c478bd9Sstevel@tonic-gate 		}
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 		if ((flags & NS_LDAP_NOMAP) || schema_mapping_existed == FALSE)
4777c478bd9Sstevel@tonic-gate 			mapping = NULL;
4787c478bd9Sstevel@tonic-gate 		else
4797c478bd9Sstevel@tonic-gate 			mapping = __ns_ldap_getOrigAttribute(service, attr);
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 		if (mapping == NULL && auto_service &&
482699bceb8Smj162486 		    schema_mapping_existed && (flags & NS_LDAP_NOMAP) == 0)
4837c478bd9Sstevel@tonic-gate 			/*
484699bceb8Smj162486 			 * if service == auto_* and no schema mapping found
485699bceb8Smj162486 			 * and schema_mapping_existed is TRUE and NS_LDAP_NOMAP
486699bceb8Smj162486 			 * is not set then try automount e.g.
4877c478bd9Sstevel@tonic-gate 			 * NS_LDAP_ATTRIBUTEMAP = automount:automountMapName=AAA
4887c478bd9Sstevel@tonic-gate 			 */
489699bceb8Smj162486 			mapping = __ns_ldap_getOrigAttribute("automount",
490699bceb8Smj162486 			    attr);
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 		if (mapping == NULL) {
4937c478bd9Sstevel@tonic-gate 			if ((ap[j]->attrname = strdup(attr)) == NULL) {
4947c478bd9Sstevel@tonic-gate 				ber_free(ber, 0);
4957c478bd9Sstevel@tonic-gate 				ber = NULL;
4967c478bd9Sstevel@tonic-gate 				__ns_ldap_freeEntry(ep);
4977c478bd9Sstevel@tonic-gate 				ep = NULL;
4987c478bd9Sstevel@tonic-gate 				if (gecos_mapping)
4997c478bd9Sstevel@tonic-gate 					__s_api_free2dArray(gecos_mapping);
5007c478bd9Sstevel@tonic-gate 				gecos_mapping = NULL;
5017c478bd9Sstevel@tonic-gate 				return (NS_LDAP_MEMORY);
5027c478bd9Sstevel@tonic-gate 			}
5037c478bd9Sstevel@tonic-gate 		} else {
5047c478bd9Sstevel@tonic-gate 			/*
5057c478bd9Sstevel@tonic-gate 			 * for "gecos" 1 to N mapping,
5067c478bd9Sstevel@tonic-gate 			 * do not remove the mapped attribute,
5077c478bd9Sstevel@tonic-gate 			 * just create a new gecos attribute
5087c478bd9Sstevel@tonic-gate 			 * and append it to the end of the attribute list
5097c478bd9Sstevel@tonic-gate 			 */
5107c478bd9Sstevel@tonic-gate 			if (strcasecmp(mapping[0], "gecos") == 0) {
5117c478bd9Sstevel@tonic-gate 				ap[j]->attrname = strdup(attr);
5127c478bd9Sstevel@tonic-gate 				gecos_mapping_existed = TRUE;
5137c478bd9Sstevel@tonic-gate 			} else
5147c478bd9Sstevel@tonic-gate 				ap[j]->attrname = strdup(mapping[0]);
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 			if (ap[j]->attrname == NULL) {
5177c478bd9Sstevel@tonic-gate 				ber_free(ber, 0);
5187c478bd9Sstevel@tonic-gate 				ber = NULL;
5197c478bd9Sstevel@tonic-gate 				__ns_ldap_freeEntry(ep);
5207c478bd9Sstevel@tonic-gate 				ep = NULL;
5217c478bd9Sstevel@tonic-gate 				if (gecos_mapping)
5227c478bd9Sstevel@tonic-gate 					__s_api_free2dArray(gecos_mapping);
5237c478bd9Sstevel@tonic-gate 				gecos_mapping = NULL;
5247c478bd9Sstevel@tonic-gate 				return (NS_LDAP_MEMORY);
5257c478bd9Sstevel@tonic-gate 			}
5267c478bd9Sstevel@tonic-gate 			/*
5277c478bd9Sstevel@tonic-gate 			 * 1 to N attribute mapping processing
5287c478bd9Sstevel@tonic-gate 			 * is only done for "gecos"
5297c478bd9Sstevel@tonic-gate 			 */
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 			if (strcasecmp(mapping[0], "gecos") == 0) {
5327c478bd9Sstevel@tonic-gate 				/*
5337c478bd9Sstevel@tonic-gate 				 * get attribute mapping for "gecos",
5347c478bd9Sstevel@tonic-gate 				 * need to know the number and order of the
5357c478bd9Sstevel@tonic-gate 				 * mapped attributes
5367c478bd9Sstevel@tonic-gate 				 */
5377c478bd9Sstevel@tonic-gate 				if (gecos_mapping == NULL) {
5387c478bd9Sstevel@tonic-gate 					gecos_mapping =
539699bceb8Smj162486 					    __ns_ldap_getMappedAttributes(
540699bceb8Smj162486 					    service, mapping[0]);
5417c478bd9Sstevel@tonic-gate 					if (gecos_mapping == NULL ||
5427c478bd9Sstevel@tonic-gate 					    gecos_mapping[0] == NULL) {
5437c478bd9Sstevel@tonic-gate 						/*
5447c478bd9Sstevel@tonic-gate 						 * this should never happens,
5457c478bd9Sstevel@tonic-gate 						 * syslog the error
5467c478bd9Sstevel@tonic-gate 						 */
5477c478bd9Sstevel@tonic-gate 						(void) sprintf(errstr,
5487c478bd9Sstevel@tonic-gate 						    gettext(
5497c478bd9Sstevel@tonic-gate 						    "Attribute mapping "
5507c478bd9Sstevel@tonic-gate 						    "inconsistency "
5517c478bd9Sstevel@tonic-gate 						    "found for attributes "
5527c478bd9Sstevel@tonic-gate 						    "'%s' and '%s'."),
5537c478bd9Sstevel@tonic-gate 						    mapping[0], attr);
554699bceb8Smj162486 						syslog(LOG_ERR, "libsldap: %s",
555699bceb8Smj162486 						    errstr);
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 						ber_free(ber, 0);
5587c478bd9Sstevel@tonic-gate 						ber = NULL;
5597c478bd9Sstevel@tonic-gate 						__ns_ldap_freeEntry(ep);
5607c478bd9Sstevel@tonic-gate 						ep = NULL;
5617c478bd9Sstevel@tonic-gate 						__s_api_free2dArray(mapping);
5627c478bd9Sstevel@tonic-gate 						mapping = NULL;
5637c478bd9Sstevel@tonic-gate 						if (gecos_mapping)
5647c478bd9Sstevel@tonic-gate 							__s_api_free2dArray(
5657c478bd9Sstevel@tonic-gate 							    gecos_mapping);
5667c478bd9Sstevel@tonic-gate 						gecos_mapping = NULL;
5677c478bd9Sstevel@tonic-gate 						return (NS_LDAP_INTERNAL);
5687c478bd9Sstevel@tonic-gate 					}
5697c478bd9Sstevel@tonic-gate 				}
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 				/*
5727c478bd9Sstevel@tonic-gate 				 * is this attribute the 1st, 2nd, or
5737c478bd9Sstevel@tonic-gate 				 * 3rd attr in the mapping list?
5747c478bd9Sstevel@tonic-gate 				 */
5757c478bd9Sstevel@tonic-gate 				gecos_attr_matched = FALSE;
5767c478bd9Sstevel@tonic-gate 				for (i = 0; i < 3 && gecos_mapping[i]; i++) {
5777c478bd9Sstevel@tonic-gate 					if (gecos_mapping[i] &&
5787c478bd9Sstevel@tonic-gate 					    strcasecmp(gecos_mapping[i],
5797c478bd9Sstevel@tonic-gate 					    attr) == 0) {
5807c478bd9Sstevel@tonic-gate 						gecos_val_index[i] = j;
5817c478bd9Sstevel@tonic-gate 						gecos_attr_matched = TRUE;
5827c478bd9Sstevel@tonic-gate 						break;
5837c478bd9Sstevel@tonic-gate 					}
5847c478bd9Sstevel@tonic-gate 				}
5857c478bd9Sstevel@tonic-gate 				if (gecos_attr_matched == FALSE) {
5867c478bd9Sstevel@tonic-gate 					/*
5877c478bd9Sstevel@tonic-gate 					 * Not match found.
5887c478bd9Sstevel@tonic-gate 					 * This should never happens,
5897c478bd9Sstevel@tonic-gate 					 * syslog the error
5907c478bd9Sstevel@tonic-gate 					 */
5917c478bd9Sstevel@tonic-gate 					(void) sprintf(errstr,
5927c478bd9Sstevel@tonic-gate 					    gettext(
5937c478bd9Sstevel@tonic-gate 					    "Attribute mapping "
5947c478bd9Sstevel@tonic-gate 					    "inconsistency "
5957c478bd9Sstevel@tonic-gate 					    "found for attributes "
5967c478bd9Sstevel@tonic-gate 					    "'%s' and '%s'."),
5977c478bd9Sstevel@tonic-gate 					    mapping[0], attr);
5987c478bd9Sstevel@tonic-gate 					syslog(LOG_ERR, "libsldap: %s", errstr);
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 					ber_free(ber, 0);
6017c478bd9Sstevel@tonic-gate 					ber = NULL;
6027c478bd9Sstevel@tonic-gate 					__ns_ldap_freeEntry(ep);
6037c478bd9Sstevel@tonic-gate 					ep = NULL;
6047c478bd9Sstevel@tonic-gate 					__s_api_free2dArray(mapping);
6057c478bd9Sstevel@tonic-gate 					mapping = NULL;
6067c478bd9Sstevel@tonic-gate 					__s_api_free2dArray(gecos_mapping);
6077c478bd9Sstevel@tonic-gate 					gecos_mapping = NULL;
6087c478bd9Sstevel@tonic-gate 					return (NS_LDAP_INTERNAL);
6097c478bd9Sstevel@tonic-gate 				}
6107c478bd9Sstevel@tonic-gate 			}
6117c478bd9Sstevel@tonic-gate 			__s_api_free2dArray(mapping);
6127c478bd9Sstevel@tonic-gate 			mapping = NULL;
6137c478bd9Sstevel@tonic-gate 		}
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 		if ((vals = ldap_get_values(ld, e, attr)) != NULL) {
6167c478bd9Sstevel@tonic-gate 
617699bceb8Smj162486 			if ((ap[j]->value_count =
618699bceb8Smj162486 			    ldap_count_values(vals)) == 0) {
6197c478bd9Sstevel@tonic-gate 				ldap_value_free(vals);
6207c478bd9Sstevel@tonic-gate 				vals = NULL;
6217c478bd9Sstevel@tonic-gate 				continue;
6227c478bd9Sstevel@tonic-gate 			} else {
6237c478bd9Sstevel@tonic-gate 				ap[j]->attrvalue = (char **)
624699bceb8Smj162486 				    calloc(ap[j]->value_count+1,
625699bceb8Smj162486 				    sizeof (char *));
6267c478bd9Sstevel@tonic-gate 				if (ap[j]->attrvalue == NULL) {
6277c478bd9Sstevel@tonic-gate 					ber_free(ber, 0);
6287c478bd9Sstevel@tonic-gate 					ber = NULL;
6297c478bd9Sstevel@tonic-gate 					__ns_ldap_freeEntry(ep);
6307c478bd9Sstevel@tonic-gate 					ep = NULL;
6317c478bd9Sstevel@tonic-gate 					if (gecos_mapping)
632699bceb8Smj162486 						__s_api_free2dArray(
633699bceb8Smj162486 						    gecos_mapping);
6347c478bd9Sstevel@tonic-gate 					gecos_mapping = NULL;
6357c478bd9Sstevel@tonic-gate 					return (NS_LDAP_MEMORY);
6367c478bd9Sstevel@tonic-gate 				}
6377c478bd9Sstevel@tonic-gate 			}
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 			/* map object classes if necessary */
6407c478bd9Sstevel@tonic-gate 			if ((flags & NS_LDAP_NOMAP) == 0 &&
6417c478bd9Sstevel@tonic-gate 			    schema_mapping_existed && ap[j]->attrname &&
6427c478bd9Sstevel@tonic-gate 			    strcasecmp(ap[j]->attrname, "objectclass") == 0) {
6437c478bd9Sstevel@tonic-gate 				for (k = 0; k < ap[j]->value_count; k++) {
6447c478bd9Sstevel@tonic-gate 					mapping =
645699bceb8Smj162486 					    __ns_ldap_getOrigObjectClass(
646699bceb8Smj162486 					    service, vals[k]);
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 					if (mapping == NULL && auto_service)
6497c478bd9Sstevel@tonic-gate 						/*
6507c478bd9Sstevel@tonic-gate 						 * if service == auto_* and no
6517c478bd9Sstevel@tonic-gate 						 * schema mapping found
6527c478bd9Sstevel@tonic-gate 						 * then try automount
6537c478bd9Sstevel@tonic-gate 						 */
6547c478bd9Sstevel@tonic-gate 					mapping =
6557c478bd9Sstevel@tonic-gate 					    __ns_ldap_getOrigObjectClass(
6567c478bd9Sstevel@tonic-gate 					    "automount", vals[k]);
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 					if (mapping == NULL) {
659699bceb8Smj162486 						ap[j]->attrvalue[k] =
660699bceb8Smj162486 						    strdup(vals[k]);
6617c478bd9Sstevel@tonic-gate 					} else {
662699bceb8Smj162486 						ap[j]->attrvalue[k] =
663699bceb8Smj162486 						    strdup(mapping[0]);
6647c478bd9Sstevel@tonic-gate 						__s_api_free2dArray(mapping);
6657c478bd9Sstevel@tonic-gate 						mapping = NULL;
6667c478bd9Sstevel@tonic-gate 					}
6677c478bd9Sstevel@tonic-gate 					if (ap[j]->attrvalue[k] == NULL) {
6687c478bd9Sstevel@tonic-gate 						ber_free(ber, 0);
6697c478bd9Sstevel@tonic-gate 						ber = NULL;
6707c478bd9Sstevel@tonic-gate 						__ns_ldap_freeEntry(ep);
6717c478bd9Sstevel@tonic-gate 						ep = NULL;
6727c478bd9Sstevel@tonic-gate 						if (gecos_mapping)
673699bceb8Smj162486 							__s_api_free2dArray(
674699bceb8Smj162486 							    gecos_mapping);
6757c478bd9Sstevel@tonic-gate 						gecos_mapping = NULL;
6767c478bd9Sstevel@tonic-gate 						return (NS_LDAP_MEMORY);
6777c478bd9Sstevel@tonic-gate 					}
6787c478bd9Sstevel@tonic-gate 				}
6797c478bd9Sstevel@tonic-gate 			} else {
6807c478bd9Sstevel@tonic-gate 				for (k = 0; k < ap[j]->value_count; k++) {
681699bceb8Smj162486 					if ((ap[j]->attrvalue[k] =
682699bceb8Smj162486 					    strdup(vals[k])) == NULL) {
6837c478bd9Sstevel@tonic-gate 						ber_free(ber, 0);
6847c478bd9Sstevel@tonic-gate 						ber = NULL;
6857c478bd9Sstevel@tonic-gate 						__ns_ldap_freeEntry(ep);
6867c478bd9Sstevel@tonic-gate 						ep = NULL;
6877c478bd9Sstevel@tonic-gate 						if (gecos_mapping)
688699bceb8Smj162486 							__s_api_free2dArray(
689699bceb8Smj162486 							    gecos_mapping);
6907c478bd9Sstevel@tonic-gate 						gecos_mapping = NULL;
6917c478bd9Sstevel@tonic-gate 						return (NS_LDAP_MEMORY);
6927c478bd9Sstevel@tonic-gate 					}
6937c478bd9Sstevel@tonic-gate 				}
6947c478bd9Sstevel@tonic-gate 			}
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 			ap[j]->attrvalue[k] = NULL;
6977c478bd9Sstevel@tonic-gate 			ldap_value_free(vals);
6987c478bd9Sstevel@tonic-gate 			vals = NULL;
6997c478bd9Sstevel@tonic-gate 		}
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 		ldap_memfree(attr);
7027c478bd9Sstevel@tonic-gate 		attr = NULL;
7037c478bd9Sstevel@tonic-gate 	}
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 	ber_free(ber, 0);
7067c478bd9Sstevel@tonic-gate 	ber = NULL;
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	if (gecos_mapping) {
7097c478bd9Sstevel@tonic-gate 		__s_api_free2dArray(gecos_mapping);
7107c478bd9Sstevel@tonic-gate 		gecos_mapping = NULL;
7117c478bd9Sstevel@tonic-gate 	}
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 	/* special processing for gecos 1 to up to 3 attribute mapping */
7147c478bd9Sstevel@tonic-gate 	if (schema_mapping_existed && gecos_mapping_existed) {
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 		int	f = -1;
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 		for (i = 0; i < 3; i++) {
7197c478bd9Sstevel@tonic-gate 			k = gecos_val_index[i];
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 			/*
7227c478bd9Sstevel@tonic-gate 			 * f is the index of the first returned
7237c478bd9Sstevel@tonic-gate 			 * attribute which "gecos" attribute mapped to
7247c478bd9Sstevel@tonic-gate 			 */
7257c478bd9Sstevel@tonic-gate 			if (k != -1 && f == -1)
7267c478bd9Sstevel@tonic-gate 				f = k;
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 			if (k != -1 && ap[k]->value_count > 0 &&
7297c478bd9Sstevel@tonic-gate 			    ap[k]->attrvalue[0] &&
7307c478bd9Sstevel@tonic-gate 			    strlen(ap[k]->attrvalue[0]) > 0) {
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 				if (k == f) {
7337c478bd9Sstevel@tonic-gate 					/*
7347c478bd9Sstevel@tonic-gate 					 * Create and fill in the last reserved
7357c478bd9Sstevel@tonic-gate 					 * ap with the data from the "gecos"
7367c478bd9Sstevel@tonic-gate 					 * mapping attributes
7377c478bd9Sstevel@tonic-gate 					 */
7387c478bd9Sstevel@tonic-gate 					ap[nAttrs] = (ns_ldap_attr_t *)
7397c478bd9Sstevel@tonic-gate 					    calloc(1,
7407c478bd9Sstevel@tonic-gate 					    sizeof (ns_ldap_attr_t));
7417c478bd9Sstevel@tonic-gate 					if (ap[nAttrs] == NULL) {
7427c478bd9Sstevel@tonic-gate 						__ns_ldap_freeEntry(ep);
7437c478bd9Sstevel@tonic-gate 						ep = NULL;
7447c478bd9Sstevel@tonic-gate 						return (NS_LDAP_MEMORY);
7457c478bd9Sstevel@tonic-gate 					}
7467c478bd9Sstevel@tonic-gate 					ap[nAttrs]->attrvalue = (char **)calloc(
7477c478bd9Sstevel@tonic-gate 					    2, sizeof (char *));
7487c478bd9Sstevel@tonic-gate 					if (ap[nAttrs]->attrvalue == NULL) {
7497c478bd9Sstevel@tonic-gate 						__ns_ldap_freeEntry(ep);
7507c478bd9Sstevel@tonic-gate 						ep = NULL;
7517c478bd9Sstevel@tonic-gate 						return (NS_LDAP_MEMORY);
7527c478bd9Sstevel@tonic-gate 					}
7537c478bd9Sstevel@tonic-gate 					/* add 1 more for a possible "," */
7547c478bd9Sstevel@tonic-gate 					ap[nAttrs]->attrvalue[0] =
7557c478bd9Sstevel@tonic-gate 					    (char *)calloc(
7567c478bd9Sstevel@tonic-gate 					    strlen(ap[f]->attrvalue[0]) +
7577c478bd9Sstevel@tonic-gate 					    2, 1);
7587c478bd9Sstevel@tonic-gate 					if (ap[nAttrs]->attrvalue[0] == NULL) {
7597c478bd9Sstevel@tonic-gate 						__ns_ldap_freeEntry(ep);
7607c478bd9Sstevel@tonic-gate 						ep = NULL;
7617c478bd9Sstevel@tonic-gate 						return (NS_LDAP_MEMORY);
7627c478bd9Sstevel@tonic-gate 					}
7637c478bd9Sstevel@tonic-gate 					(void) strcpy(ap[nAttrs]->attrvalue[0],
7647c478bd9Sstevel@tonic-gate 					    ap[f]->attrvalue[0]);
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 					ap[nAttrs]->attrname = strdup("gecos");
7677c478bd9Sstevel@tonic-gate 					if (ap[nAttrs]->attrname == NULL) {
7687c478bd9Sstevel@tonic-gate 						__ns_ldap_freeEntry(ep);
7697c478bd9Sstevel@tonic-gate 						ep = NULL;
7707c478bd9Sstevel@tonic-gate 						return (NS_LDAP_MEMORY);
7717c478bd9Sstevel@tonic-gate 					}
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate 					ap[nAttrs]->value_count = 1;
7747c478bd9Sstevel@tonic-gate 					ep->attr_count = nAttrs + 1;
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 				} else {
7774142e9a2Ssdussud 					char	*tmp = NULL;
7784142e9a2Ssdussud 
7794142e9a2Ssdussud 					/*
7804142e9a2Ssdussud 					 * realloc to add "," and
7814142e9a2Ssdussud 					 * ap[k]->attrvalue[0]
7824142e9a2Ssdussud 					 */
7834142e9a2Ssdussud 					tmp = (char *)realloc(
7847c478bd9Sstevel@tonic-gate 					    ap[nAttrs]->attrvalue[0],
7857c478bd9Sstevel@tonic-gate 					    strlen(ap[nAttrs]->
7864142e9a2Ssdussud 					    attrvalue[0]) +
7874142e9a2Ssdussud 					    strlen(ap[k]->
7887c478bd9Sstevel@tonic-gate 					    attrvalue[0]) + 2);
7894142e9a2Ssdussud 					if (tmp == NULL) {
7907c478bd9Sstevel@tonic-gate 						__ns_ldap_freeEntry(ep);
7917c478bd9Sstevel@tonic-gate 						ep = NULL;
7927c478bd9Sstevel@tonic-gate 						return (NS_LDAP_MEMORY);
7937c478bd9Sstevel@tonic-gate 					}
7944142e9a2Ssdussud 					ap[nAttrs]->attrvalue[0] = tmp;
7954142e9a2Ssdussud 					(void) strcat(ap[nAttrs]->attrvalue[0],
7964142e9a2Ssdussud 					    ",");
7977c478bd9Sstevel@tonic-gate 					(void) strcat(ap[nAttrs]->attrvalue[0],
7987c478bd9Sstevel@tonic-gate 					    ap[k]->attrvalue[0]);
7997c478bd9Sstevel@tonic-gate 				}
8007c478bd9Sstevel@tonic-gate 			}
8017c478bd9Sstevel@tonic-gate 		}
8027c478bd9Sstevel@tonic-gate 	}
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 	*ret = ep;
8057c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
8067c478bd9Sstevel@tonic-gate }
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate static int
__s_api_getEntry(ns_ldap_cookie_t * cookie)8097c478bd9Sstevel@tonic-gate __s_api_getEntry(ns_ldap_cookie_t *cookie)
8107c478bd9Sstevel@tonic-gate {
8117c478bd9Sstevel@tonic-gate 	ns_ldap_entry_t	*curEntry = NULL;
8127c478bd9Sstevel@tonic-gate 	int		ret;
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate #ifdef DEBUG
8157c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "__s_api_getEntry START\n");
8167c478bd9Sstevel@tonic-gate #endif
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 	if (cookie->resultMsg == NULL) {
8197c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
8207c478bd9Sstevel@tonic-gate 	}
8217c478bd9Sstevel@tonic-gate 	ret = __s_api_cvtEntry(cookie->conn->ld, cookie->service,
8227c478bd9Sstevel@tonic-gate 	    cookie->resultMsg, cookie->i_flags,
8237c478bd9Sstevel@tonic-gate 	    &curEntry, &cookie->errorp);
8247c478bd9Sstevel@tonic-gate 	if (ret != NS_LDAP_SUCCESS) {
8257c478bd9Sstevel@tonic-gate 		return (ret);
8267c478bd9Sstevel@tonic-gate 	}
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 	if (cookie->result == NULL) {
8297c478bd9Sstevel@tonic-gate 		cookie->result = (ns_ldap_result_t *)
8307c478bd9Sstevel@tonic-gate 		    calloc(1, sizeof (ns_ldap_result_t));
8317c478bd9Sstevel@tonic-gate 		if (cookie->result == NULL) {
8327c478bd9Sstevel@tonic-gate 			__ns_ldap_freeEntry(curEntry);
8337c478bd9Sstevel@tonic-gate 			curEntry = NULL;
8347c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
8357c478bd9Sstevel@tonic-gate 		}
8367c478bd9Sstevel@tonic-gate 		cookie->result->entry = curEntry;
8377c478bd9Sstevel@tonic-gate 		cookie->nextEntry = curEntry;
8387c478bd9Sstevel@tonic-gate 	} else {
8397c478bd9Sstevel@tonic-gate 		cookie->nextEntry->next = curEntry;
8407c478bd9Sstevel@tonic-gate 		cookie->nextEntry = curEntry;
8417c478bd9Sstevel@tonic-gate 	}
8427c478bd9Sstevel@tonic-gate 	cookie->result->entries_count++;
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
8457c478bd9Sstevel@tonic-gate }
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate static int
__s_api_get_cachemgr_data(const char * type,const char * from,char ** to)8487c478bd9Sstevel@tonic-gate __s_api_get_cachemgr_data(const char *type,
8497c478bd9Sstevel@tonic-gate 		const char *from, char **to)
8507c478bd9Sstevel@tonic-gate {
8517c478bd9Sstevel@tonic-gate 	union {
8527c478bd9Sstevel@tonic-gate 		ldap_data_t	s_d;
8537c478bd9Sstevel@tonic-gate 		char		s_b[DOORBUFFERSIZE];
8547c478bd9Sstevel@tonic-gate 	} space;
8557c478bd9Sstevel@tonic-gate 	ldap_data_t	*sptr;
8567c478bd9Sstevel@tonic-gate 	int		ndata;
8577c478bd9Sstevel@tonic-gate 	int		adata;
8587c478bd9Sstevel@tonic-gate 	int		rc;
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate #ifdef DEBUG
8617c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "__s_api_get_cachemgr_data START\n");
8627c478bd9Sstevel@tonic-gate #endif
863e1dd0a2fSth160488 	/*
864e1dd0a2fSth160488 	 * We are not going to perform DN to domain mapping
865e1dd0a2fSth160488 	 * in the Standalone mode
866e1dd0a2fSth160488 	 */
867e1dd0a2fSth160488 	if (__s_api_isStandalone()) {
868e1dd0a2fSth160488 		return (-1);
869e1dd0a2fSth160488 	}
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 	if (from == NULL || from[0] == '\0' || to == NULL)
8727c478bd9Sstevel@tonic-gate 		return (-1);
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 	*to = NULL;
8757c478bd9Sstevel@tonic-gate 	(void) memset(space.s_b, 0, DOORBUFFERSIZE);
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 	space.s_d.ldap_call.ldap_callnumber = GETCACHE;
8787c478bd9Sstevel@tonic-gate 	(void) snprintf(space.s_d.ldap_call.ldap_u.domainname,
8797c478bd9Sstevel@tonic-gate 	    DOORBUFFERSIZE - sizeof (space.s_d.ldap_call.ldap_callnumber),
8807c478bd9Sstevel@tonic-gate 	    "%s%s%s",
8817c478bd9Sstevel@tonic-gate 	    type,
8827c478bd9Sstevel@tonic-gate 	    DOORLINESEP,
8837c478bd9Sstevel@tonic-gate 	    from);
8847c478bd9Sstevel@tonic-gate 	ndata = sizeof (space);
8857c478bd9Sstevel@tonic-gate 	adata = sizeof (ldap_call_t) +
8867c478bd9Sstevel@tonic-gate 	    strlen(space.s_d.ldap_call.ldap_u.domainname) + 1;
8877c478bd9Sstevel@tonic-gate 	sptr = &space.s_d;
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate 	rc = __ns_ldap_trydoorcall(&sptr, &ndata, &adata);
890e1dd0a2fSth160488 	if (rc != NS_CACHE_SUCCESS)
8917c478bd9Sstevel@tonic-gate 		return (-1);
8927c478bd9Sstevel@tonic-gate 	else
8937c478bd9Sstevel@tonic-gate 		*to = strdup(sptr->ldap_ret.ldap_u.buff);
8947c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
8957c478bd9Sstevel@tonic-gate }
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate static int
__s_api_set_cachemgr_data(const char * type,const char * from,const char * to)8987c478bd9Sstevel@tonic-gate __s_api_set_cachemgr_data(const char *type,
8997c478bd9Sstevel@tonic-gate 		const char *from, const char *to)
9007c478bd9Sstevel@tonic-gate {
9017c478bd9Sstevel@tonic-gate 	union {
9027c478bd9Sstevel@tonic-gate 		ldap_data_t	s_d;
9037c478bd9Sstevel@tonic-gate 		char		s_b[DOORBUFFERSIZE];
9047c478bd9Sstevel@tonic-gate 	} space;
9057c478bd9Sstevel@tonic-gate 	ldap_data_t	*sptr;
9067c478bd9Sstevel@tonic-gate 	int		ndata;
9077c478bd9Sstevel@tonic-gate 	int		adata;
9087c478bd9Sstevel@tonic-gate 	int		rc;
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate #ifdef DEBUG
9117c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "__s_api_set_cachemgr_data START\n");
9127c478bd9Sstevel@tonic-gate #endif
913e1dd0a2fSth160488 	/*
914e1dd0a2fSth160488 	 * We are not going to perform DN to domain mapping
915e1dd0a2fSth160488 	 * in the Standalone mode
916e1dd0a2fSth160488 	 */
917e1dd0a2fSth160488 	if (__s_api_isStandalone()) {
918e1dd0a2fSth160488 		return (-1);
919e1dd0a2fSth160488 	}
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 	if ((from == NULL) || (from[0] == '\0') ||
9227c478bd9Sstevel@tonic-gate 	    (to == NULL) || (to[0] == '\0'))
9237c478bd9Sstevel@tonic-gate 		return (-1);
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 	(void) memset(space.s_b, 0, DOORBUFFERSIZE);
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 	space.s_d.ldap_call.ldap_callnumber = SETCACHE;
9287c478bd9Sstevel@tonic-gate 	(void) snprintf(space.s_d.ldap_call.ldap_u.domainname,
9297c478bd9Sstevel@tonic-gate 	    DOORBUFFERSIZE - sizeof (space.s_d.ldap_call.ldap_callnumber),
9307c478bd9Sstevel@tonic-gate 	    "%s%s%s%s%s",
9317c478bd9Sstevel@tonic-gate 	    type,
9327c478bd9Sstevel@tonic-gate 	    DOORLINESEP,
9337c478bd9Sstevel@tonic-gate 	    from,
9347c478bd9Sstevel@tonic-gate 	    DOORLINESEP,
9357c478bd9Sstevel@tonic-gate 	    to);
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 	ndata = sizeof (space);
9387c478bd9Sstevel@tonic-gate 	adata = sizeof (ldap_call_t) +
9397c478bd9Sstevel@tonic-gate 	    strlen(space.s_d.ldap_call.ldap_u.domainname) + 1;
9407c478bd9Sstevel@tonic-gate 	sptr = &space.s_d;
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate 	rc = __ns_ldap_trydoorcall(&sptr, &ndata, &adata);
943e1dd0a2fSth160488 	if (rc != NS_CACHE_SUCCESS)
9447c478bd9Sstevel@tonic-gate 		return (-1);
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
9477c478bd9Sstevel@tonic-gate }
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate static char *
__s_api_remove_rdn_space(char * rdn)9517c478bd9Sstevel@tonic-gate __s_api_remove_rdn_space(char *rdn)
9527c478bd9Sstevel@tonic-gate {
9537c478bd9Sstevel@tonic-gate 	char	*tf, *tl, *vf, *vl, *eqsign;
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate 	/* if no space(s) to remove, return */
9567c478bd9Sstevel@tonic-gate 	if (strchr(rdn, SPACETOK) == NULL)
9577c478bd9Sstevel@tonic-gate 		return (rdn);
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate 	/* if no '=' separator, return */
9607c478bd9Sstevel@tonic-gate 	eqsign = strchr(rdn, '=');
9617c478bd9Sstevel@tonic-gate 	if (eqsign == NULL)
9627c478bd9Sstevel@tonic-gate 		return (rdn);
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 	tf = rdn;
9657c478bd9Sstevel@tonic-gate 	tl = eqsign - 1;
9667c478bd9Sstevel@tonic-gate 	vf = eqsign + 1;
9677c478bd9Sstevel@tonic-gate 	vl = rdn + strlen(rdn) - 1;
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate 	/* now two strings, type and value */
9707c478bd9Sstevel@tonic-gate 	*eqsign = '\0';
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate 	/* remove type's leading spaces */
9737c478bd9Sstevel@tonic-gate 	while (tf < tl && *tf == SPACETOK)
9747c478bd9Sstevel@tonic-gate 		tf++;
9757c478bd9Sstevel@tonic-gate 	/* remove type's trailing spaces */
9767c478bd9Sstevel@tonic-gate 	while (tf < tl && *tl == SPACETOK)
9777c478bd9Sstevel@tonic-gate 		tl--;
9787c478bd9Sstevel@tonic-gate 	/* add '=' separator back */
9797c478bd9Sstevel@tonic-gate 	*(++tl) = '=';
9807c478bd9Sstevel@tonic-gate 	/* remove value's leading spaces */
9817c478bd9Sstevel@tonic-gate 	while (vf < vl && *vf == SPACETOK)
9827c478bd9Sstevel@tonic-gate 		vf++;
9837c478bd9Sstevel@tonic-gate 	/* remove value's trailing spaces */
9847c478bd9Sstevel@tonic-gate 	while (vf < vl && *vl == SPACETOK)
9857c478bd9Sstevel@tonic-gate 		*vl-- = '\0';
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 	/* move value up if necessary */
9887c478bd9Sstevel@tonic-gate 	if (vf != tl + 1)
9897c478bd9Sstevel@tonic-gate 		(void) strcpy(tl + 1, vf);
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate 	return (tf);
9927c478bd9Sstevel@tonic-gate }
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate static
9957c478bd9Sstevel@tonic-gate ns_ldap_cookie_t *
init_search_state_machine()9967c478bd9Sstevel@tonic-gate init_search_state_machine()
9977c478bd9Sstevel@tonic-gate {
9987c478bd9Sstevel@tonic-gate 	ns_ldap_cookie_t	*cookie;
9997c478bd9Sstevel@tonic-gate 	ns_config_t		*cfg;
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 	cookie = (ns_ldap_cookie_t *)calloc(1, sizeof (ns_ldap_cookie_t));
10027c478bd9Sstevel@tonic-gate 	if (cookie == NULL)
10037c478bd9Sstevel@tonic-gate 		return (NULL);
10047c478bd9Sstevel@tonic-gate 	cookie->state = INIT;
10057c478bd9Sstevel@tonic-gate 	/* assign other state variables */
10067c478bd9Sstevel@tonic-gate 	cfg = __s_api_loadrefresh_config();
10077c478bd9Sstevel@tonic-gate 	cookie->connectionId = -1;
10087c478bd9Sstevel@tonic-gate 	if (cfg == NULL ||
10097c478bd9Sstevel@tonic-gate 	    cfg->paramList[NS_LDAP_SEARCH_TIME_P].ns_ptype == NS_UNKNOWN) {
10107c478bd9Sstevel@tonic-gate 		cookie->search_timeout.tv_sec = NS_DEFAULT_SEARCH_TIMEOUT;
10117c478bd9Sstevel@tonic-gate 	} else {
10127c478bd9Sstevel@tonic-gate 		cookie->search_timeout.tv_sec =
10137c478bd9Sstevel@tonic-gate 		    cfg->paramList[NS_LDAP_SEARCH_TIME_P].ns_i;
10147c478bd9Sstevel@tonic-gate 	}
10157c478bd9Sstevel@tonic-gate 	if (cfg != NULL)
10167c478bd9Sstevel@tonic-gate 		__s_api_release_config(cfg);
10177c478bd9Sstevel@tonic-gate 	cookie->search_timeout.tv_usec = 0;
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate 	return (cookie);
10207c478bd9Sstevel@tonic-gate }
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate static void
delete_search_cookie(ns_ldap_cookie_t * cookie)10237c478bd9Sstevel@tonic-gate delete_search_cookie(ns_ldap_cookie_t *cookie)
10247c478bd9Sstevel@tonic-gate {
10257c478bd9Sstevel@tonic-gate 	if (cookie == NULL)
10267c478bd9Sstevel@tonic-gate 		return;
10277c478bd9Sstevel@tonic-gate 	if (cookie->connectionId > -1)
10287c478bd9Sstevel@tonic-gate 		DropConnection(cookie->connectionId, cookie->i_flags);
10297c478bd9Sstevel@tonic-gate 	if (cookie->filter)
10307c478bd9Sstevel@tonic-gate 		free(cookie->filter);
10317c478bd9Sstevel@tonic-gate 	if (cookie->i_filter)
10327c478bd9Sstevel@tonic-gate 		free(cookie->i_filter);
10337c478bd9Sstevel@tonic-gate 	if (cookie->service)
10347c478bd9Sstevel@tonic-gate 		free(cookie->service);
10357c478bd9Sstevel@tonic-gate 	if (cookie->sdlist)
10367c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeSearchDescriptors(&(cookie->sdlist));
10377c478bd9Sstevel@tonic-gate 	if (cookie->result)
10387c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&cookie->result);
10397c478bd9Sstevel@tonic-gate 	if (cookie->attribute)
10407c478bd9Sstevel@tonic-gate 		__s_api_free2dArray(cookie->attribute);
10417c478bd9Sstevel@tonic-gate 	if (cookie->errorp)
10427c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&cookie->errorp);
10437c478bd9Sstevel@tonic-gate 	if (cookie->reflist)
10447c478bd9Sstevel@tonic-gate 		__s_api_deleteRefInfo(cookie->reflist);
10457c478bd9Sstevel@tonic-gate 	if (cookie->basedn)
10467c478bd9Sstevel@tonic-gate 		free(cookie->basedn);
10477c478bd9Sstevel@tonic-gate 	if (cookie->ctrlCookie)
10487c478bd9Sstevel@tonic-gate 		ber_bvfree(cookie->ctrlCookie);
10497c478bd9Sstevel@tonic-gate 	_freeControlList(&cookie->p_serverctrls);
105047789246Svv149972 	if (cookie->resultctrl)
105147789246Svv149972 		ldap_controls_free(cookie->resultctrl);
10527c478bd9Sstevel@tonic-gate 	free(cookie);
10537c478bd9Sstevel@tonic-gate }
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate static int
get_mapped_filter(ns_ldap_cookie_t * cookie,char ** new_filter)10567c478bd9Sstevel@tonic-gate get_mapped_filter(ns_ldap_cookie_t *cookie, char **new_filter)
10577c478bd9Sstevel@tonic-gate {
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate 	typedef	struct	filter_mapping_info {
10607c478bd9Sstevel@tonic-gate 		char	oc_or_attr;
10617c478bd9Sstevel@tonic-gate 		char	*name_start;
10627c478bd9Sstevel@tonic-gate 		char	*name_end;
10637c478bd9Sstevel@tonic-gate 		char	*veq_pos;
10647c478bd9Sstevel@tonic-gate 		char	*from_name;
10657c478bd9Sstevel@tonic-gate 		char	*to_name;
10667c478bd9Sstevel@tonic-gate 		char	**mapping;
10677c478bd9Sstevel@tonic-gate 	} filter_mapping_info_t;
10687c478bd9Sstevel@tonic-gate 
10697c478bd9Sstevel@tonic-gate 	char			*c, *last_copied;
10707c478bd9Sstevel@tonic-gate 	char			*filter_c, *filter_c_next;
10717c478bd9Sstevel@tonic-gate 	char			*key, *tail, *head;
10727c478bd9Sstevel@tonic-gate 	char			errstr[MAXERROR];
10737c478bd9Sstevel@tonic-gate 	int			num_eq = 0, num_veq = 0;
10747c478bd9Sstevel@tonic-gate 	int			in_quote = FALSE;
1075f8f1c176Svt115884 	int			is_value = FALSE;
10767c478bd9Sstevel@tonic-gate 	int			i, j, oc_len, len;
10777c478bd9Sstevel@tonic-gate 	int			at_least_one = FALSE;
10787c478bd9Sstevel@tonic-gate 	filter_mapping_info_t	**info, *info1;
10797c478bd9Sstevel@tonic-gate 	char			**mapping;
10807c478bd9Sstevel@tonic-gate 	char			*service, *filter, *err;
10817c478bd9Sstevel@tonic-gate 	int			auto_service = FALSE;
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate 	if (cookie == NULL || new_filter == NULL)
10847c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 	*new_filter = NULL;
10877c478bd9Sstevel@tonic-gate 	service = cookie->service;
10887c478bd9Sstevel@tonic-gate 	filter = cookie->filter;
10897c478bd9Sstevel@tonic-gate 
10907c478bd9Sstevel@tonic-gate 	/*
10917c478bd9Sstevel@tonic-gate 	 * count the number of '=' char
10927c478bd9Sstevel@tonic-gate 	 */
10937c478bd9Sstevel@tonic-gate 	for (c = filter; *c; c++) {
10947c478bd9Sstevel@tonic-gate 		if (*c == TOKENSEPARATOR)
10957c478bd9Sstevel@tonic-gate 			num_eq++;
10967c478bd9Sstevel@tonic-gate 	}
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate 	if (service != NULL && strncasecmp(service, "auto_", 5) == 0)
10997c478bd9Sstevel@tonic-gate 		auto_service = TRUE;
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate 	/*
11027c478bd9Sstevel@tonic-gate 	 * See if schema mapping existed for the given service.
11037c478bd9Sstevel@tonic-gate 	 * If not, just return success.
11047c478bd9Sstevel@tonic-gate 	 */
11057c478bd9Sstevel@tonic-gate 	mapping = __ns_ldap_getOrigAttribute(service,
11067c478bd9Sstevel@tonic-gate 	    NS_HASH_SCHEMA_MAPPING_EXISTED);
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 	if (mapping == NULL && auto_service)
11097c478bd9Sstevel@tonic-gate 		/*
11107c478bd9Sstevel@tonic-gate 		 * if service == auto_* and no
11117c478bd9Sstevel@tonic-gate 		 * schema mapping found
11127c478bd9Sstevel@tonic-gate 		 * then try automount
11137c478bd9Sstevel@tonic-gate 		 */
11147c478bd9Sstevel@tonic-gate 		mapping = __ns_ldap_getOrigAttribute(
11157c478bd9Sstevel@tonic-gate 		    "automount", NS_HASH_SCHEMA_MAPPING_EXISTED);
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 	if (mapping)
11187c478bd9Sstevel@tonic-gate 		__s_api_free2dArray(mapping);
11197c478bd9Sstevel@tonic-gate 	else
11207c478bd9Sstevel@tonic-gate 		return (NS_LDAP_SUCCESS);
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate 	/*
11237c478bd9Sstevel@tonic-gate 	 * no '=' sign, just say OK and return nothing
11247c478bd9Sstevel@tonic-gate 	 */
11257c478bd9Sstevel@tonic-gate 	if (num_eq == 0)
11267c478bd9Sstevel@tonic-gate 		return (NS_LDAP_SUCCESS);
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate 	/*
11297c478bd9Sstevel@tonic-gate 	 * Make a copy of the filter string
11307c478bd9Sstevel@tonic-gate 	 * for saving the name of the objectclasses or
11317c478bd9Sstevel@tonic-gate 	 * attributes that need to be passed to the
11327c478bd9Sstevel@tonic-gate 	 * objectclass or attribute mapping functions.
11337c478bd9Sstevel@tonic-gate 	 * pointer "info->from_name" points to the locations
11347c478bd9Sstevel@tonic-gate 	 * within this string.
11357c478bd9Sstevel@tonic-gate 	 *
11367c478bd9Sstevel@tonic-gate 	 * The input filter string, filter, will be used
11377c478bd9Sstevel@tonic-gate 	 * to indicate where these names start and end.
11387c478bd9Sstevel@tonic-gate 	 * pointers "info->name_start" and "info->name_end"
11397c478bd9Sstevel@tonic-gate 	 * point to locations within the input filter string,
11407c478bd9Sstevel@tonic-gate 	 * and are used at the end of this function to
11417c478bd9Sstevel@tonic-gate 	 * merge the original filter data with the
11427c478bd9Sstevel@tonic-gate 	 * mapped objectclass or attribute names.
11437c478bd9Sstevel@tonic-gate 	 */
11447c478bd9Sstevel@tonic-gate 	filter_c = strdup(filter);
11457c478bd9Sstevel@tonic-gate 	if (filter_c == NULL)
11467c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
11477c478bd9Sstevel@tonic-gate 	filter_c_next = filter_c;
11487c478bd9Sstevel@tonic-gate 
11497c478bd9Sstevel@tonic-gate 	/*
11507c478bd9Sstevel@tonic-gate 	 * get memory for info arrays
11517c478bd9Sstevel@tonic-gate 	 */
11527c478bd9Sstevel@tonic-gate 	info = (filter_mapping_info_t **)calloc(num_eq + 1,
11537c478bd9Sstevel@tonic-gate 	    sizeof (filter_mapping_info_t *));
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate 	if (info == NULL) {
11567c478bd9Sstevel@tonic-gate 		free(filter_c);
11577c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
11587c478bd9Sstevel@tonic-gate 	}
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 	/*
11617c478bd9Sstevel@tonic-gate 	 * find valid '=' for further processing,
11627c478bd9Sstevel@tonic-gate 	 * ignore the "escaped =" (.i.e. "\="), or
11637c478bd9Sstevel@tonic-gate 	 * "=" in quoted string
11647c478bd9Sstevel@tonic-gate 	 */
11657c478bd9Sstevel@tonic-gate 	for (c = filter_c; *c; c++) {
11667c478bd9Sstevel@tonic-gate 
11677c478bd9Sstevel@tonic-gate 		switch (*c) {
11687c478bd9Sstevel@tonic-gate 		case TOKENSEPARATOR:
1169f8f1c176Svt115884 			if (!in_quote && !is_value) {
11707c478bd9Sstevel@tonic-gate 				info1 = (filter_mapping_info_t *)calloc(1,
11717c478bd9Sstevel@tonic-gate 				    sizeof (filter_mapping_info_t));
11727c478bd9Sstevel@tonic-gate 				if (!info1) {
11737c478bd9Sstevel@tonic-gate 					free(filter_c);
11747c478bd9Sstevel@tonic-gate 					for (i = 0; i < num_veq; i++)
11757c478bd9Sstevel@tonic-gate 						free(info[i]);
11767c478bd9Sstevel@tonic-gate 					free(info);
11777c478bd9Sstevel@tonic-gate 					return (NS_LDAP_MEMORY);
11787c478bd9Sstevel@tonic-gate 				}
11797c478bd9Sstevel@tonic-gate 				info[num_veq] = info1;
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 				/*
11827c478bd9Sstevel@tonic-gate 				 * remember the location of this "="
11837c478bd9Sstevel@tonic-gate 				 */
11847c478bd9Sstevel@tonic-gate 				info[num_veq++]->veq_pos = c;
1185f8f1c176Svt115884 
1186f8f1c176Svt115884 				/*
1187f8f1c176Svt115884 				 * skip until the end of the attribute value
1188f8f1c176Svt115884 				 */
1189f8f1c176Svt115884 				is_value = TRUE;
11907c478bd9Sstevel@tonic-gate 			}
11917c478bd9Sstevel@tonic-gate 			break;
1192f8f1c176Svt115884 		case CPARATOK:
1193f8f1c176Svt115884 			/*
1194f8f1c176Svt115884 			 * mark the end of the attribute value
1195f8f1c176Svt115884 			 */
1196f8f1c176Svt115884 			if (!in_quote)
1197f8f1c176Svt115884 				is_value = FALSE;
1198f8f1c176Svt115884 			break;
11997c478bd9Sstevel@tonic-gate 		case QUOTETOK:
12007c478bd9Sstevel@tonic-gate 			/*
12017c478bd9Sstevel@tonic-gate 			 * switch on/off the in_quote mode
12027c478bd9Sstevel@tonic-gate 			 */
12037c478bd9Sstevel@tonic-gate 			in_quote = (in_quote == FALSE);
12047c478bd9Sstevel@tonic-gate 			break;
12057c478bd9Sstevel@tonic-gate 		case '\\':
12067c478bd9Sstevel@tonic-gate 			/*
12077c478bd9Sstevel@tonic-gate 			 * ignore escape characters
12087c478bd9Sstevel@tonic-gate 			 * don't skip if next char is '\0'
12097c478bd9Sstevel@tonic-gate 			 */
12107c478bd9Sstevel@tonic-gate 			if (!in_quote)
12117c478bd9Sstevel@tonic-gate 				if (*(++c) == '\0')
12127c478bd9Sstevel@tonic-gate 					c--;
12137c478bd9Sstevel@tonic-gate 			break;
12147c478bd9Sstevel@tonic-gate 		}
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate 	}
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 	/*
12197c478bd9Sstevel@tonic-gate 	 * for each valid "=" found, get the name to
12207c478bd9Sstevel@tonic-gate 	 * be mapped
12217c478bd9Sstevel@tonic-gate 	 */
12227c478bd9Sstevel@tonic-gate 	oc_len = strlen("objectclass");
12237c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_veq; i++) {
12247c478bd9Sstevel@tonic-gate 
12257c478bd9Sstevel@tonic-gate 		/*
12267c478bd9Sstevel@tonic-gate 		 * look at the left side of "=" to see
12277c478bd9Sstevel@tonic-gate 		 * if assertion is "objectclass=<ocname>"
12287c478bd9Sstevel@tonic-gate 		 * or "<attribute name>=<attribute value>"
12297c478bd9Sstevel@tonic-gate 		 *
12307c478bd9Sstevel@tonic-gate 		 * first skip spaces before "=".
12317c478bd9Sstevel@tonic-gate 		 * Note that filter_c_next may not point to the
12327c478bd9Sstevel@tonic-gate 		 * start of the filter string. For i > 0,
12337c478bd9Sstevel@tonic-gate 		 * it points to the end of the last name processed + 2
12347c478bd9Sstevel@tonic-gate 		 */
12357c478bd9Sstevel@tonic-gate 		for (tail = info[i]->veq_pos; (tail > filter_c_next) &&
1236699bceb8Smj162486 		    (*(tail - 1) == SPACETOK); tail--)
1237699bceb8Smj162486 			;
12387c478bd9Sstevel@tonic-gate 
12397c478bd9Sstevel@tonic-gate 		/*
12407c478bd9Sstevel@tonic-gate 		 * mark the end of the left side string (the key)
12417c478bd9Sstevel@tonic-gate 		 */
12427c478bd9Sstevel@tonic-gate 		*tail = '\0';
12437c478bd9Sstevel@tonic-gate 		info[i]->name_end = tail - filter_c - 1 + filter;
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate 		/*
12467c478bd9Sstevel@tonic-gate 		 * find the start of the key
12477c478bd9Sstevel@tonic-gate 		 */
12487c478bd9Sstevel@tonic-gate 		key = filter_c_next;
12497c478bd9Sstevel@tonic-gate 		for (c = tail; filter_c_next <= c; c--) {
12507c478bd9Sstevel@tonic-gate 			/* OPARATOK is '(' */
12517c478bd9Sstevel@tonic-gate 			if (*c == OPARATOK ||
12527c478bd9Sstevel@tonic-gate 			    *c == SPACETOK) {
12537c478bd9Sstevel@tonic-gate 				key = c + 1;
12547c478bd9Sstevel@tonic-gate 				break;
12557c478bd9Sstevel@tonic-gate 			}
12567c478bd9Sstevel@tonic-gate 		}
12577c478bd9Sstevel@tonic-gate 		info[i]->name_start = key - filter_c + filter;
12587c478bd9Sstevel@tonic-gate 
12597c478bd9Sstevel@tonic-gate 		if ((key + oc_len) <= tail) {
12607c478bd9Sstevel@tonic-gate 			if (strncasecmp(key, "objectclass",
12617c478bd9Sstevel@tonic-gate 			    oc_len) == 0) {
12627c478bd9Sstevel@tonic-gate 				/*
12637c478bd9Sstevel@tonic-gate 				 * assertion is "objectclass=ocname",
12647c478bd9Sstevel@tonic-gate 				 * ocname is the one needs to be mapped
12657c478bd9Sstevel@tonic-gate 				 *
12667c478bd9Sstevel@tonic-gate 				 * skip spaces after "=" to find start
12677c478bd9Sstevel@tonic-gate 				 * of the ocname
12687c478bd9Sstevel@tonic-gate 				 */
12697c478bd9Sstevel@tonic-gate 				head = info[i]->veq_pos;
12707c478bd9Sstevel@tonic-gate 				for (head = info[i]->veq_pos + 1;
1271699bceb8Smj162486 				    *head && *head == SPACETOK; head++)
1272699bceb8Smj162486 					;
12737c478bd9Sstevel@tonic-gate 
12747c478bd9Sstevel@tonic-gate 				/* ignore empty ocname */
12757c478bd9Sstevel@tonic-gate 				if (!(*head))
12767c478bd9Sstevel@tonic-gate 					continue;
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 				info[i]->name_start = head - filter_c +
12797c478bd9Sstevel@tonic-gate 				    filter;
12807c478bd9Sstevel@tonic-gate 
12817c478bd9Sstevel@tonic-gate 				/*
12827c478bd9Sstevel@tonic-gate 				 * now find the end of the ocname
12837c478bd9Sstevel@tonic-gate 				 */
12847c478bd9Sstevel@tonic-gate 				for (c = head; ; c++) {
12857c478bd9Sstevel@tonic-gate 					/* CPARATOK is ')' */
12867c478bd9Sstevel@tonic-gate 					if (*c == CPARATOK ||
12877c478bd9Sstevel@tonic-gate 					    *c == '\0' ||
12887c478bd9Sstevel@tonic-gate 					    *c == SPACETOK) {
12897c478bd9Sstevel@tonic-gate 						*c = '\0';
12907c478bd9Sstevel@tonic-gate 						info[i]->name_end =
12917c478bd9Sstevel@tonic-gate 						    c - filter_c - 1 +
12927c478bd9Sstevel@tonic-gate 						    filter;
12937c478bd9Sstevel@tonic-gate 						filter_c_next = c + 1;
12947c478bd9Sstevel@tonic-gate 						info[i]->oc_or_attr = 'o';
12957c478bd9Sstevel@tonic-gate 						info[i]->from_name = head;
12967c478bd9Sstevel@tonic-gate 						break;
12977c478bd9Sstevel@tonic-gate 					}
12987c478bd9Sstevel@tonic-gate 				}
12997c478bd9Sstevel@tonic-gate 			}
13007c478bd9Sstevel@tonic-gate 		}
13017c478bd9Sstevel@tonic-gate 
13027c478bd9Sstevel@tonic-gate 		/*
13037c478bd9Sstevel@tonic-gate 		 * assertion is not "objectclass=ocname",
13047c478bd9Sstevel@tonic-gate 		 * assume assertion is "<key> = <value>",
13057c478bd9Sstevel@tonic-gate 		 * <key> is the one needs to be mapped
13067c478bd9Sstevel@tonic-gate 		 */
13077c478bd9Sstevel@tonic-gate 		if (info[i]->from_name == NULL && strlen(key) > 0) {
13087c478bd9Sstevel@tonic-gate 			info[i]->oc_or_attr = 'a';
13097c478bd9Sstevel@tonic-gate 			info[i]->from_name = key;
13107c478bd9Sstevel@tonic-gate 		}
13117c478bd9Sstevel@tonic-gate 	}
13127c478bd9Sstevel@tonic-gate 
13137c478bd9Sstevel@tonic-gate 	/* perform schema mapping */
13147c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_veq; i++) {
13157c478bd9Sstevel@tonic-gate 		if (info[i]->from_name == NULL)
13167c478bd9Sstevel@tonic-gate 			continue;
13177c478bd9Sstevel@tonic-gate 
13187c478bd9Sstevel@tonic-gate 		if (info[i]->oc_or_attr == 'a')
13197c478bd9Sstevel@tonic-gate 			info[i]->mapping =
13207c478bd9Sstevel@tonic-gate 			    __ns_ldap_getMappedAttributes(service,
13217c478bd9Sstevel@tonic-gate 			    info[i]->from_name);
13227c478bd9Sstevel@tonic-gate 		else
13237c478bd9Sstevel@tonic-gate 			info[i]->mapping =
13247c478bd9Sstevel@tonic-gate 			    __ns_ldap_getMappedObjectClass(service,
13257c478bd9Sstevel@tonic-gate 			    info[i]->from_name);
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate 		if (info[i]->mapping == NULL && auto_service)  {
13287c478bd9Sstevel@tonic-gate 			/*
13297c478bd9Sstevel@tonic-gate 			 * If no mapped attribute/objectclass is found
13307c478bd9Sstevel@tonic-gate 			 * and service == auto*
13317c478bd9Sstevel@tonic-gate 			 * try to find automount's
13327c478bd9Sstevel@tonic-gate 			 * mapped attribute/objectclass
13337c478bd9Sstevel@tonic-gate 			 */
13347c478bd9Sstevel@tonic-gate 			if (info[i]->oc_or_attr == 'a')
13357c478bd9Sstevel@tonic-gate 				info[i]->mapping =
13367c478bd9Sstevel@tonic-gate 				    __ns_ldap_getMappedAttributes("automount",
13377c478bd9Sstevel@tonic-gate 				    info[i]->from_name);
13387c478bd9Sstevel@tonic-gate 			else
13397c478bd9Sstevel@tonic-gate 				info[i]->mapping =
13407c478bd9Sstevel@tonic-gate 				    __ns_ldap_getMappedObjectClass("automount",
13417c478bd9Sstevel@tonic-gate 				    info[i]->from_name);
13427c478bd9Sstevel@tonic-gate 		}
13437c478bd9Sstevel@tonic-gate 
13447c478bd9Sstevel@tonic-gate 		if (info[i]->mapping == NULL ||
13457c478bd9Sstevel@tonic-gate 		    info[i]->mapping[0] == NULL) {
13467c478bd9Sstevel@tonic-gate 			info[i]->to_name = NULL;
13477c478bd9Sstevel@tonic-gate 		} else if (info[i]->mapping[1] == NULL) {
13487c478bd9Sstevel@tonic-gate 			info[i]->to_name = info[i]->mapping[0];
13497c478bd9Sstevel@tonic-gate 			at_least_one = TRUE;
13507c478bd9Sstevel@tonic-gate 		} else {
13517c478bd9Sstevel@tonic-gate 			__s_api_free2dArray(info[i]->mapping);
13527c478bd9Sstevel@tonic-gate 			/*
13537c478bd9Sstevel@tonic-gate 			 * multiple mapping
13547c478bd9Sstevel@tonic-gate 			 * not allowed
13557c478bd9Sstevel@tonic-gate 			 */
13567c478bd9Sstevel@tonic-gate 			(void) sprintf(errstr,
13577c478bd9Sstevel@tonic-gate 			    gettext(
13587c478bd9Sstevel@tonic-gate 			    "Multiple attribute or objectclass "
13597c478bd9Sstevel@tonic-gate 			    "mapping for '%s' in filter "
13607c478bd9Sstevel@tonic-gate 			    "'%s' not allowed."),
13617c478bd9Sstevel@tonic-gate 			    info[i]->from_name, filter);
13627c478bd9Sstevel@tonic-gate 			err = strdup(errstr);
13637c478bd9Sstevel@tonic-gate 			if (err)
13647c478bd9Sstevel@tonic-gate 				MKERROR(LOG_WARNING, cookie->errorp,
13657c478bd9Sstevel@tonic-gate 				    NS_CONFIG_SYNTAX,
13667c478bd9Sstevel@tonic-gate 				    err, NULL);
13677c478bd9Sstevel@tonic-gate 
13687c478bd9Sstevel@tonic-gate 			free(filter_c);
13697c478bd9Sstevel@tonic-gate 			for (j = 0; j < num_veq; j++) {
13707c478bd9Sstevel@tonic-gate 				if (info[j]->mapping)
13717c478bd9Sstevel@tonic-gate 					__s_api_free2dArray(
13727c478bd9Sstevel@tonic-gate 					    info[j]->mapping);
13737c478bd9Sstevel@tonic-gate 				free(info[j]);
13747c478bd9Sstevel@tonic-gate 			}
13757c478bd9Sstevel@tonic-gate 			free(info);
13767c478bd9Sstevel@tonic-gate 			return (NS_LDAP_CONFIG);
13777c478bd9Sstevel@tonic-gate 		}
13787c478bd9Sstevel@tonic-gate 	}
13797c478bd9Sstevel@tonic-gate 
13807c478bd9Sstevel@tonic-gate 
13817c478bd9Sstevel@tonic-gate 	if (at_least_one) {
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate 		len = strlen(filter);
13847c478bd9Sstevel@tonic-gate 		last_copied = filter - 1;
13857c478bd9Sstevel@tonic-gate 
13867c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_veq; i++) {
13877c478bd9Sstevel@tonic-gate 			if (info[i]->to_name)
13887c478bd9Sstevel@tonic-gate 				len += strlen(info[i]->to_name);
13897c478bd9Sstevel@tonic-gate 		}
13907c478bd9Sstevel@tonic-gate 
13917c478bd9Sstevel@tonic-gate 		*new_filter = (char *)calloc(1, len);
13927c478bd9Sstevel@tonic-gate 		if (*new_filter == NULL) {
13937c478bd9Sstevel@tonic-gate 			free(filter_c);
13947c478bd9Sstevel@tonic-gate 			for (j = 0; j < num_veq; j++) {
13957c478bd9Sstevel@tonic-gate 				if (info[j]->mapping)
13967c478bd9Sstevel@tonic-gate 					__s_api_free2dArray(
13977c478bd9Sstevel@tonic-gate 					    info[j]->mapping);
13987c478bd9Sstevel@tonic-gate 				free(info[j]);
13997c478bd9Sstevel@tonic-gate 			}
14007c478bd9Sstevel@tonic-gate 			free(info);
14017c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
14027c478bd9Sstevel@tonic-gate 		}
14037c478bd9Sstevel@tonic-gate 
14047c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_veq; i++) {
14057c478bd9Sstevel@tonic-gate 			if (info[i]->to_name != NULL &&
14067c478bd9Sstevel@tonic-gate 			    info[i]->to_name != NULL) {
14077c478bd9Sstevel@tonic-gate 
14087c478bd9Sstevel@tonic-gate 				/*
14097c478bd9Sstevel@tonic-gate 				 * copy the original filter data
14107c478bd9Sstevel@tonic-gate 				 * between the last name and current
14117c478bd9Sstevel@tonic-gate 				 * name
14127c478bd9Sstevel@tonic-gate 				 */
14137c478bd9Sstevel@tonic-gate 				if ((last_copied + 1) != info[i]->name_start)
1414699bceb8Smj162486 					(void) strncat(*new_filter,
1415699bceb8Smj162486 					    last_copied + 1,
14167c478bd9Sstevel@tonic-gate 					    info[i]->name_start -
14177c478bd9Sstevel@tonic-gate 					    last_copied - 1);
14187c478bd9Sstevel@tonic-gate 
14197c478bd9Sstevel@tonic-gate 				/* the data is copied */
14207c478bd9Sstevel@tonic-gate 				last_copied = info[i]->name_end;
14217c478bd9Sstevel@tonic-gate 
14227c478bd9Sstevel@tonic-gate 				/*
14237c478bd9Sstevel@tonic-gate 				 * replace the name with
14247c478bd9Sstevel@tonic-gate 				 * the mapped name
14257c478bd9Sstevel@tonic-gate 				 */
14267c478bd9Sstevel@tonic-gate 				(void) strcat(*new_filter, info[i]->to_name);
14277c478bd9Sstevel@tonic-gate 			}
14287c478bd9Sstevel@tonic-gate 
14297c478bd9Sstevel@tonic-gate 			/* copy the filter data after the last name */
14307c478bd9Sstevel@tonic-gate 			if (i == (num_veq -1) &&
14317c478bd9Sstevel@tonic-gate 			    info[i]->name_end <
14327c478bd9Sstevel@tonic-gate 			    (filter + strlen(filter)))
14337c478bd9Sstevel@tonic-gate 				(void) strncat(*new_filter, last_copied + 1,
14347c478bd9Sstevel@tonic-gate 				    filter + strlen(filter) -
14357c478bd9Sstevel@tonic-gate 				    last_copied - 1);
14367c478bd9Sstevel@tonic-gate 		}
14377c478bd9Sstevel@tonic-gate 
14387c478bd9Sstevel@tonic-gate 	}
14397c478bd9Sstevel@tonic-gate 
14407c478bd9Sstevel@tonic-gate 	/* free memory */
14417c478bd9Sstevel@tonic-gate 	free(filter_c);
14427c478bd9Sstevel@tonic-gate 	for (j = 0; j < num_veq; j++) {
14437c478bd9Sstevel@tonic-gate 		if (info[j]->mapping)
14447c478bd9Sstevel@tonic-gate 			__s_api_free2dArray(info[j]->mapping);
14457c478bd9Sstevel@tonic-gate 		free(info[j]);
14467c478bd9Sstevel@tonic-gate 	}
14477c478bd9Sstevel@tonic-gate 	free(info);
14487c478bd9Sstevel@tonic-gate 
14497c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
14507c478bd9Sstevel@tonic-gate }
14517c478bd9Sstevel@tonic-gate 
14527c478bd9Sstevel@tonic-gate static int
setup_next_search(ns_ldap_cookie_t * cookie)14537c478bd9Sstevel@tonic-gate setup_next_search(ns_ldap_cookie_t *cookie)
14547c478bd9Sstevel@tonic-gate {
14557c478bd9Sstevel@tonic-gate 	ns_ldap_search_desc_t	*dptr;
14567c478bd9Sstevel@tonic-gate 	int			scope;
14577c478bd9Sstevel@tonic-gate 	char			*filter, *str;
14587c478bd9Sstevel@tonic-gate 	int			baselen;
14597c478bd9Sstevel@tonic-gate 	int			rc;
14607c478bd9Sstevel@tonic-gate 	void			**param;
14617c478bd9Sstevel@tonic-gate 
14627c478bd9Sstevel@tonic-gate 	dptr = *cookie->sdpos;
14637c478bd9Sstevel@tonic-gate 	scope = cookie->i_flags & (NS_LDAP_SCOPE_BASE |
14647c478bd9Sstevel@tonic-gate 	    NS_LDAP_SCOPE_ONELEVEL |
14657c478bd9Sstevel@tonic-gate 	    NS_LDAP_SCOPE_SUBTREE);
14667c478bd9Sstevel@tonic-gate 	if (scope)
14677c478bd9Sstevel@tonic-gate 		cookie->scope = scope;
14687c478bd9Sstevel@tonic-gate 	else
14697c478bd9Sstevel@tonic-gate 		cookie->scope = dptr->scope;
14707c478bd9Sstevel@tonic-gate 	switch (cookie->scope) {
14717c478bd9Sstevel@tonic-gate 	case NS_LDAP_SCOPE_BASE:
14727c478bd9Sstevel@tonic-gate 		cookie->scope = LDAP_SCOPE_BASE;
14737c478bd9Sstevel@tonic-gate 		break;
14747c478bd9Sstevel@tonic-gate 	case NS_LDAP_SCOPE_ONELEVEL:
14757c478bd9Sstevel@tonic-gate 		cookie->scope = LDAP_SCOPE_ONELEVEL;
14767c478bd9Sstevel@tonic-gate 		break;
14777c478bd9Sstevel@tonic-gate 	case NS_LDAP_SCOPE_SUBTREE:
14787c478bd9Sstevel@tonic-gate 		cookie->scope = LDAP_SCOPE_SUBTREE;
14797c478bd9Sstevel@tonic-gate 		break;
14807c478bd9Sstevel@tonic-gate 	}
14817c478bd9Sstevel@tonic-gate 
14827c478bd9Sstevel@tonic-gate 	filter = NULL;
14837c478bd9Sstevel@tonic-gate 	if (cookie->use_filtercb && cookie->init_filter_cb &&
14847c478bd9Sstevel@tonic-gate 	    dptr->filter && strlen(dptr->filter) > 0) {
14857c478bd9Sstevel@tonic-gate 		(*cookie->init_filter_cb)(dptr, &filter,
14867c478bd9Sstevel@tonic-gate 		    cookie->userdata);
14877c478bd9Sstevel@tonic-gate 	}
14887c478bd9Sstevel@tonic-gate 	if (filter == NULL) {
14897c478bd9Sstevel@tonic-gate 		if (cookie->i_filter == NULL) {
14907c478bd9Sstevel@tonic-gate 			cookie->err_rc = NS_LDAP_INVALID_PARAM;
14917c478bd9Sstevel@tonic-gate 			return (-1);
14927c478bd9Sstevel@tonic-gate 		} else {
149336cd58d3Srm88369 			if (cookie->filter)
149436cd58d3Srm88369 				free(cookie->filter);
14957c478bd9Sstevel@tonic-gate 			cookie->filter = strdup(cookie->i_filter);
14967c478bd9Sstevel@tonic-gate 			if (cookie->filter == NULL) {
14977c478bd9Sstevel@tonic-gate 				cookie->err_rc = NS_LDAP_MEMORY;
14987c478bd9Sstevel@tonic-gate 				return (-1);
14997c478bd9Sstevel@tonic-gate 			}
15007c478bd9Sstevel@tonic-gate 		}
15017c478bd9Sstevel@tonic-gate 	} else {
150236cd58d3Srm88369 		if (cookie->filter)
150336cd58d3Srm88369 			free(cookie->filter);
15047c478bd9Sstevel@tonic-gate 		cookie->filter = strdup(filter);
15057c478bd9Sstevel@tonic-gate 		free(filter);
15067c478bd9Sstevel@tonic-gate 		if (cookie->filter == NULL) {
15077c478bd9Sstevel@tonic-gate 			cookie->err_rc = NS_LDAP_MEMORY;
15087c478bd9Sstevel@tonic-gate 			return (-1);
15097c478bd9Sstevel@tonic-gate 		}
15107c478bd9Sstevel@tonic-gate 	}
15117c478bd9Sstevel@tonic-gate 
15127c478bd9Sstevel@tonic-gate 	/*
15137c478bd9Sstevel@tonic-gate 	 * perform attribute/objectclass mapping on filter
15147c478bd9Sstevel@tonic-gate 	 */
15157c478bd9Sstevel@tonic-gate 	filter = NULL;
15167c478bd9Sstevel@tonic-gate 
15177c478bd9Sstevel@tonic-gate 	if (cookie->service) {
15187c478bd9Sstevel@tonic-gate 		rc = get_mapped_filter(cookie, &filter);
15197c478bd9Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
15207c478bd9Sstevel@tonic-gate 			cookie->err_rc = rc;
15217c478bd9Sstevel@tonic-gate 			return (-1);
15227c478bd9Sstevel@tonic-gate 		} else {
15237c478bd9Sstevel@tonic-gate 			/*
15247c478bd9Sstevel@tonic-gate 			 * get_mapped_filter returns
15257c478bd9Sstevel@tonic-gate 			 * NULL filter pointer, if
15267c478bd9Sstevel@tonic-gate 			 * no mapping was done
15277c478bd9Sstevel@tonic-gate 			 */
15287c478bd9Sstevel@tonic-gate 			if (filter) {
15297c478bd9Sstevel@tonic-gate 				free(cookie->filter);
15307c478bd9Sstevel@tonic-gate 				cookie->filter = filter;
15317c478bd9Sstevel@tonic-gate 			}
15327c478bd9Sstevel@tonic-gate 		}
15337c478bd9Sstevel@tonic-gate 	}
15347c478bd9Sstevel@tonic-gate 
15357c478bd9Sstevel@tonic-gate 	/*
15367c478bd9Sstevel@tonic-gate 	 * validate filter to make sure it's legal
15377c478bd9Sstevel@tonic-gate 	 * [remove redundant ()'s]
15387c478bd9Sstevel@tonic-gate 	 */
15397c478bd9Sstevel@tonic-gate 	rc = validate_filter(cookie);
15407c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
15417c478bd9Sstevel@tonic-gate 		cookie->err_rc = rc;
15427c478bd9Sstevel@tonic-gate 		return (-1);
15437c478bd9Sstevel@tonic-gate 	}
15447c478bd9Sstevel@tonic-gate 
15457c478bd9Sstevel@tonic-gate 	baselen = strlen(dptr->basedn);
15467c478bd9Sstevel@tonic-gate 	if (baselen > 0 && dptr->basedn[baselen-1] == COMMATOK) {
15477c478bd9Sstevel@tonic-gate 		rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
15487c478bd9Sstevel@tonic-gate 		    (void ***)&param, &cookie->errorp);
15497c478bd9Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
15507c478bd9Sstevel@tonic-gate 			cookie->err_rc = rc;
15517c478bd9Sstevel@tonic-gate 			return (-1);
15527c478bd9Sstevel@tonic-gate 		}
15537c478bd9Sstevel@tonic-gate 		str = ((char **)param)[0];
15547c478bd9Sstevel@tonic-gate 		baselen += strlen(str)+1;
155536cd58d3Srm88369 		if (cookie->basedn)
155636cd58d3Srm88369 			free(cookie->basedn);
15577c478bd9Sstevel@tonic-gate 		cookie->basedn = (char *)malloc(baselen);
15587c478bd9Sstevel@tonic-gate 		if (cookie->basedn == NULL) {
15597c478bd9Sstevel@tonic-gate 			cookie->err_rc = NS_LDAP_MEMORY;
15607c478bd9Sstevel@tonic-gate 			return (-1);
15617c478bd9Sstevel@tonic-gate 		}
15627c478bd9Sstevel@tonic-gate 		(void) strcpy(cookie->basedn, dptr->basedn);
15637c478bd9Sstevel@tonic-gate 		(void) strcat(cookie->basedn, str);
15647c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeParam(&param);
15657c478bd9Sstevel@tonic-gate 	} else {
156636cd58d3Srm88369 		if (cookie->basedn)
156736cd58d3Srm88369 			free(cookie->basedn);
15687c478bd9Sstevel@tonic-gate 		cookie->basedn = strdup(dptr->basedn);
15697c478bd9Sstevel@tonic-gate 	}
15707c478bd9Sstevel@tonic-gate 	return (0);
15717c478bd9Sstevel@tonic-gate }
15727c478bd9Sstevel@tonic-gate 
15737c478bd9Sstevel@tonic-gate static int
setup_referral_search(ns_ldap_cookie_t * cookie)15747c478bd9Sstevel@tonic-gate setup_referral_search(ns_ldap_cookie_t *cookie)
15757c478bd9Sstevel@tonic-gate {
15767c478bd9Sstevel@tonic-gate 	ns_referral_info_t	*ref;
15777c478bd9Sstevel@tonic-gate 
15787c478bd9Sstevel@tonic-gate 	ref = cookie->refpos;
15797c478bd9Sstevel@tonic-gate 	cookie->scope = ref->refScope;
15807c478bd9Sstevel@tonic-gate 	if (cookie->filter) {
15817c478bd9Sstevel@tonic-gate 		free(cookie->filter);
15827c478bd9Sstevel@tonic-gate 	}
15837c478bd9Sstevel@tonic-gate 	cookie->filter = strdup(ref->refFilter);
15847c478bd9Sstevel@tonic-gate 	if (cookie->basedn) {
15857c478bd9Sstevel@tonic-gate 		free(cookie->basedn);
15867c478bd9Sstevel@tonic-gate 	}
15877c478bd9Sstevel@tonic-gate 	cookie->basedn = strdup(ref->refDN);
15887c478bd9Sstevel@tonic-gate 	if (cookie->filter == NULL || cookie->basedn == NULL) {
15897c478bd9Sstevel@tonic-gate 		cookie->err_rc = NS_LDAP_MEMORY;
15907c478bd9Sstevel@tonic-gate 		return (-1);
15917c478bd9Sstevel@tonic-gate 	}
15927c478bd9Sstevel@tonic-gate 	return (0);
15937c478bd9Sstevel@tonic-gate }
15947c478bd9Sstevel@tonic-gate 
15957c478bd9Sstevel@tonic-gate static int
get_current_session(ns_ldap_cookie_t * cookie)15967c478bd9Sstevel@tonic-gate get_current_session(ns_ldap_cookie_t *cookie)
15977c478bd9Sstevel@tonic-gate {
15987c478bd9Sstevel@tonic-gate 	ConnectionID	connectionId = -1;
15997c478bd9Sstevel@tonic-gate 	Connection	*conp = NULL;
16007c478bd9Sstevel@tonic-gate 	int		rc;
16017c478bd9Sstevel@tonic-gate 	int		fail_if_new_pwd_reqd = 1;
16027c478bd9Sstevel@tonic-gate 
16037c478bd9Sstevel@tonic-gate 	rc = __s_api_getConnection(NULL, cookie->i_flags,
16047c478bd9Sstevel@tonic-gate 	    cookie->i_auth, &connectionId, &conp,
160547789246Svv149972 	    &cookie->errorp, fail_if_new_pwd_reqd,
1606e1dd0a2fSth160488 	    cookie->nopasswd_acct_mgmt, cookie->conn_user);
16077c478bd9Sstevel@tonic-gate 
16087c478bd9Sstevel@tonic-gate 	/*
16097c478bd9Sstevel@tonic-gate 	 * If password control attached in *cookie->errorp,
16107c478bd9Sstevel@tonic-gate 	 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
16117c478bd9Sstevel@tonic-gate 	 * free the error structure (we do not need
16127c478bd9Sstevel@tonic-gate 	 * the sec_to_expired info).
16137c478bd9Sstevel@tonic-gate 	 * Reset rc to NS_LDAP_SUCCESS.
16147c478bd9Sstevel@tonic-gate 	 */
16157c478bd9Sstevel@tonic-gate 	if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
16167c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(
16177c478bd9Sstevel@tonic-gate 		    &cookie->errorp);
16187c478bd9Sstevel@tonic-gate 		cookie->errorp = NULL;
16197c478bd9Sstevel@tonic-gate 		rc = NS_LDAP_SUCCESS;
16207c478bd9Sstevel@tonic-gate 	}
16217c478bd9Sstevel@tonic-gate 
16227c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
16237c478bd9Sstevel@tonic-gate 		cookie->err_rc = rc;
16247c478bd9Sstevel@tonic-gate 		return (-1);
16257c478bd9Sstevel@tonic-gate 	}
16267c478bd9Sstevel@tonic-gate 	cookie->conn = conp;
16277c478bd9Sstevel@tonic-gate 	cookie->connectionId = connectionId;
16287c478bd9Sstevel@tonic-gate 
16297c478bd9Sstevel@tonic-gate 	return (0);
16307c478bd9Sstevel@tonic-gate }
16317c478bd9Sstevel@tonic-gate 
16327c478bd9Sstevel@tonic-gate static int
get_next_session(ns_ldap_cookie_t * cookie)16337c478bd9Sstevel@tonic-gate get_next_session(ns_ldap_cookie_t *cookie)
16347c478bd9Sstevel@tonic-gate {
16357c478bd9Sstevel@tonic-gate 	ConnectionID	connectionId = -1;
16367c478bd9Sstevel@tonic-gate 	Connection	*conp = NULL;
16377c478bd9Sstevel@tonic-gate 	int		rc;
16387c478bd9Sstevel@tonic-gate 	int		fail_if_new_pwd_reqd = 1;
16397c478bd9Sstevel@tonic-gate 
16403d047983Smichen 	if (cookie->connectionId > -1) {
16417c478bd9Sstevel@tonic-gate 		DropConnection(cookie->connectionId, cookie->i_flags);
16423d047983Smichen 		cookie->connectionId = -1;
16433d047983Smichen 	}
16447c478bd9Sstevel@tonic-gate 
1645e1dd0a2fSth160488 	/* If using a MT connection, return it. */
1646e1dd0a2fSth160488 	if (cookie->conn_user != NULL &&
1647e1dd0a2fSth160488 	    cookie->conn_user->conn_mt != NULL)
1648e1dd0a2fSth160488 		__s_api_conn_mt_return(cookie->conn_user);
1649e1dd0a2fSth160488 
16507c478bd9Sstevel@tonic-gate 	rc = __s_api_getConnection(NULL, cookie->i_flags,
16517c478bd9Sstevel@tonic-gate 	    cookie->i_auth, &connectionId, &conp,
165247789246Svv149972 	    &cookie->errorp, fail_if_new_pwd_reqd,
1653e1dd0a2fSth160488 	    cookie->nopasswd_acct_mgmt, cookie->conn_user);
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate 	/*
16567c478bd9Sstevel@tonic-gate 	 * If password control attached in *cookie->errorp,
16577c478bd9Sstevel@tonic-gate 	 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
16587c478bd9Sstevel@tonic-gate 	 * free the error structure (we do not need
16597c478bd9Sstevel@tonic-gate 	 * the sec_to_expired info).
16607c478bd9Sstevel@tonic-gate 	 * Reset rc to NS_LDAP_SUCCESS.
16617c478bd9Sstevel@tonic-gate 	 */
16627c478bd9Sstevel@tonic-gate 	if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
16637c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(
16647c478bd9Sstevel@tonic-gate 		    &cookie->errorp);
16657c478bd9Sstevel@tonic-gate 		cookie->errorp = NULL;
16667c478bd9Sstevel@tonic-gate 		rc = NS_LDAP_SUCCESS;
16677c478bd9Sstevel@tonic-gate 	}
16687c478bd9Sstevel@tonic-gate 
16697c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
16707c478bd9Sstevel@tonic-gate 		cookie->err_rc = rc;
16717c478bd9Sstevel@tonic-gate 		return (-1);
16727c478bd9Sstevel@tonic-gate 	}
16737c478bd9Sstevel@tonic-gate 	cookie->conn = conp;
16747c478bd9Sstevel@tonic-gate 	cookie->connectionId = connectionId;
16757c478bd9Sstevel@tonic-gate 	return (0);
16767c478bd9Sstevel@tonic-gate }
16777c478bd9Sstevel@tonic-gate 
16787c478bd9Sstevel@tonic-gate static int
get_referral_session(ns_ldap_cookie_t * cookie)16797c478bd9Sstevel@tonic-gate get_referral_session(ns_ldap_cookie_t *cookie)
16807c478bd9Sstevel@tonic-gate {
16817c478bd9Sstevel@tonic-gate 	ConnectionID	connectionId = -1;
16827c478bd9Sstevel@tonic-gate 	Connection	*conp = NULL;
16837c478bd9Sstevel@tonic-gate 	int		rc;
16847c478bd9Sstevel@tonic-gate 	int		fail_if_new_pwd_reqd = 1;
16857c478bd9Sstevel@tonic-gate 
16863d047983Smichen 	if (cookie->connectionId > -1) {
16877c478bd9Sstevel@tonic-gate 		DropConnection(cookie->connectionId, cookie->i_flags);
16883d047983Smichen 		cookie->connectionId = -1;
16893d047983Smichen 	}
16907c478bd9Sstevel@tonic-gate 
1691e1dd0a2fSth160488 	/* set it up to use a connection opened for referral */
1692e1dd0a2fSth160488 	if (cookie->conn_user != NULL) {
1693e1dd0a2fSth160488 		/* If using a MT connection, return it. */
1694e1dd0a2fSth160488 		if (cookie->conn_user->conn_mt != NULL)
1695e1dd0a2fSth160488 			__s_api_conn_mt_return(cookie->conn_user);
1696e1dd0a2fSth160488 		cookie->conn_user->referral = B_TRUE;
1697e1dd0a2fSth160488 	}
1698e1dd0a2fSth160488 
16997c478bd9Sstevel@tonic-gate 	rc = __s_api_getConnection(cookie->refpos->refHost, 0,
17007c478bd9Sstevel@tonic-gate 	    cookie->i_auth, &connectionId, &conp,
170147789246Svv149972 	    &cookie->errorp, fail_if_new_pwd_reqd,
1702e1dd0a2fSth160488 	    cookie->nopasswd_acct_mgmt, cookie->conn_user);
17037c478bd9Sstevel@tonic-gate 
17047c478bd9Sstevel@tonic-gate 	/*
17057c478bd9Sstevel@tonic-gate 	 * If password control attached in *cookie->errorp,
17067c478bd9Sstevel@tonic-gate 	 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
17077c478bd9Sstevel@tonic-gate 	 * free the error structure (we do not need
17087c478bd9Sstevel@tonic-gate 	 * the sec_to_expired info).
17097c478bd9Sstevel@tonic-gate 	 * Reset rc to NS_LDAP_SUCCESS.
17107c478bd9Sstevel@tonic-gate 	 */
17117c478bd9Sstevel@tonic-gate 	if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
17127c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(
17137c478bd9Sstevel@tonic-gate 		    &cookie->errorp);
17147c478bd9Sstevel@tonic-gate 		cookie->errorp = NULL;
17157c478bd9Sstevel@tonic-gate 		rc = NS_LDAP_SUCCESS;
17167c478bd9Sstevel@tonic-gate 	}
17177c478bd9Sstevel@tonic-gate 
17187c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
17197c478bd9Sstevel@tonic-gate 		cookie->err_rc = rc;
17207c478bd9Sstevel@tonic-gate 		return (-1);
17217c478bd9Sstevel@tonic-gate 	}
17227c478bd9Sstevel@tonic-gate 	cookie->conn = conp;
17237c478bd9Sstevel@tonic-gate 	cookie->connectionId = connectionId;
17247c478bd9Sstevel@tonic-gate 	return (0);
17257c478bd9Sstevel@tonic-gate }
17267c478bd9Sstevel@tonic-gate 
17277c478bd9Sstevel@tonic-gate static int
paging_supported(ns_ldap_cookie_t * cookie)17287c478bd9Sstevel@tonic-gate paging_supported(ns_ldap_cookie_t *cookie)
17297c478bd9Sstevel@tonic-gate {
17307c478bd9Sstevel@tonic-gate 	int		rc;
17317c478bd9Sstevel@tonic-gate 
17327c478bd9Sstevel@tonic-gate 	cookie->listType = 0;
17337c478bd9Sstevel@tonic-gate 	rc = __s_api_isCtrlSupported(cookie->conn,
17347c478bd9Sstevel@tonic-gate 	    LDAP_CONTROL_VLVREQUEST);
17357c478bd9Sstevel@tonic-gate 	if (rc == NS_LDAP_SUCCESS) {
17367c478bd9Sstevel@tonic-gate 		cookie->listType = VLVCTRLFLAG;
17377c478bd9Sstevel@tonic-gate 		return (1);
17387c478bd9Sstevel@tonic-gate 	}
17397c478bd9Sstevel@tonic-gate 	rc = __s_api_isCtrlSupported(cookie->conn,
17407c478bd9Sstevel@tonic-gate 	    LDAP_CONTROL_SIMPLE_PAGE);
17417c478bd9Sstevel@tonic-gate 	if (rc == NS_LDAP_SUCCESS) {
17427c478bd9Sstevel@tonic-gate 		cookie->listType = SIMPLEPAGECTRLFLAG;
17437c478bd9Sstevel@tonic-gate 		return (1);
17447c478bd9Sstevel@tonic-gate 	}
17457c478bd9Sstevel@tonic-gate 	return (0);
17467c478bd9Sstevel@tonic-gate }
17477c478bd9Sstevel@tonic-gate 
1748*9f2fd570SJulian Pullen typedef struct servicesorttype {
1749*9f2fd570SJulian Pullen 	char *service;
1750*9f2fd570SJulian Pullen 	ns_srvsidesort_t type;
1751*9f2fd570SJulian Pullen } servicesorttype_t;
1752*9f2fd570SJulian Pullen 
1753*9f2fd570SJulian Pullen static servicesorttype_t *sort_type = NULL;
1754*9f2fd570SJulian Pullen static int sort_type_size = 0;
1755*9f2fd570SJulian Pullen static int sort_type_hwm = 0;
1756*9f2fd570SJulian Pullen static mutex_t sort_type_mutex = DEFAULTMUTEX;
1757*9f2fd570SJulian Pullen 
1758*9f2fd570SJulian Pullen 
1759*9f2fd570SJulian Pullen static ns_srvsidesort_t
get_srvsidesort_type(char * service)1760*9f2fd570SJulian Pullen get_srvsidesort_type(char *service)
1761*9f2fd570SJulian Pullen {
1762*9f2fd570SJulian Pullen 	int i;
1763*9f2fd570SJulian Pullen 	ns_srvsidesort_t type = SSS_UNKNOWN;
1764*9f2fd570SJulian Pullen 
1765*9f2fd570SJulian Pullen 	if (service == NULL)
1766*9f2fd570SJulian Pullen 		return (type);
1767*9f2fd570SJulian Pullen 
1768*9f2fd570SJulian Pullen 	(void) mutex_lock(&sort_type_mutex);
1769*9f2fd570SJulian Pullen 	if (sort_type != NULL) {
1770*9f2fd570SJulian Pullen 		for (i = 0; i < sort_type_hwm; i++) {
1771*9f2fd570SJulian Pullen 			if (strcmp(sort_type[i].service, service) == 0) {
1772*9f2fd570SJulian Pullen 				type = sort_type[i].type;
1773*9f2fd570SJulian Pullen 				break;
1774*9f2fd570SJulian Pullen 			}
1775*9f2fd570SJulian Pullen 		}
1776*9f2fd570SJulian Pullen 	}
1777*9f2fd570SJulian Pullen 	(void) mutex_unlock(&sort_type_mutex);
1778*9f2fd570SJulian Pullen 	return (type);
1779*9f2fd570SJulian Pullen }
1780*9f2fd570SJulian Pullen 
1781*9f2fd570SJulian Pullen static void
update_srvsidesort_type(char * service,ns_srvsidesort_t type)1782*9f2fd570SJulian Pullen update_srvsidesort_type(char *service, ns_srvsidesort_t type)
1783*9f2fd570SJulian Pullen {
1784*9f2fd570SJulian Pullen 	int i, size;
1785*9f2fd570SJulian Pullen 	servicesorttype_t *tmp;
1786*9f2fd570SJulian Pullen 
1787*9f2fd570SJulian Pullen 	if (service == NULL)
1788*9f2fd570SJulian Pullen 		return;
1789*9f2fd570SJulian Pullen 
1790*9f2fd570SJulian Pullen 	(void) mutex_lock(&sort_type_mutex);
1791*9f2fd570SJulian Pullen 
1792*9f2fd570SJulian Pullen 	for (i = 0; i < sort_type_hwm; i++) {
1793*9f2fd570SJulian Pullen 		if (strcmp(sort_type[i].service, service) == 0) {
1794*9f2fd570SJulian Pullen 			sort_type[i].type = type;
1795*9f2fd570SJulian Pullen 			(void) mutex_unlock(&sort_type_mutex);
1796*9f2fd570SJulian Pullen 			return;
1797*9f2fd570SJulian Pullen 		}
1798*9f2fd570SJulian Pullen 	}
1799*9f2fd570SJulian Pullen 	if (sort_type == NULL) {
1800*9f2fd570SJulian Pullen 		size = 10;
1801*9f2fd570SJulian Pullen 		tmp = malloc(size * sizeof (servicesorttype_t));
1802*9f2fd570SJulian Pullen 		if (tmp == NULL) {
1803*9f2fd570SJulian Pullen 			(void) mutex_unlock(&sort_type_mutex);
1804*9f2fd570SJulian Pullen 			return;
1805*9f2fd570SJulian Pullen 		}
1806*9f2fd570SJulian Pullen 		sort_type = tmp;
1807*9f2fd570SJulian Pullen 		sort_type_size = size;
1808*9f2fd570SJulian Pullen 	} else if (sort_type_hwm >= sort_type_size) {
1809*9f2fd570SJulian Pullen 		size = sort_type_size + 10;
1810*9f2fd570SJulian Pullen 		tmp = realloc(sort_type, size * sizeof (servicesorttype_t));
1811*9f2fd570SJulian Pullen 		if (tmp == NULL) {
1812*9f2fd570SJulian Pullen 			(void) mutex_unlock(&sort_type_mutex);
1813*9f2fd570SJulian Pullen 			return;
1814*9f2fd570SJulian Pullen 		}
1815*9f2fd570SJulian Pullen 		sort_type = tmp;
1816*9f2fd570SJulian Pullen 		sort_type_size = size;
1817*9f2fd570SJulian Pullen 	}
1818*9f2fd570SJulian Pullen 	sort_type[sort_type_hwm].service = strdup(service);
1819*9f2fd570SJulian Pullen 	if (sort_type[sort_type_hwm].service == NULL) {
1820*9f2fd570SJulian Pullen 		(void) mutex_unlock(&sort_type_mutex);
1821*9f2fd570SJulian Pullen 		return;
1822*9f2fd570SJulian Pullen 	}
1823*9f2fd570SJulian Pullen 	sort_type[sort_type_hwm].type = type;
1824*9f2fd570SJulian Pullen 	sort_type_hwm++;
1825*9f2fd570SJulian Pullen 
1826*9f2fd570SJulian Pullen 	(void) mutex_unlock(&sort_type_mutex);
1827*9f2fd570SJulian Pullen }
1828*9f2fd570SJulian Pullen 
18297c478bd9Sstevel@tonic-gate static int
setup_vlv_params(ns_ldap_cookie_t * cookie)18307c478bd9Sstevel@tonic-gate setup_vlv_params(ns_ldap_cookie_t *cookie)
18317c478bd9Sstevel@tonic-gate {
18327c478bd9Sstevel@tonic-gate 	LDAPControl	**ctrls;
18337c478bd9Sstevel@tonic-gate 	LDAPsortkey	**sortkeylist;
18347c478bd9Sstevel@tonic-gate 	LDAPControl	*sortctrl = NULL;
18357c478bd9Sstevel@tonic-gate 	LDAPControl	*vlvctrl = NULL;
18367c478bd9Sstevel@tonic-gate 	LDAPVirtualList	vlist;
1837*9f2fd570SJulian Pullen 	char		*sortattr;
18387c478bd9Sstevel@tonic-gate 	int		rc;
1839*9f2fd570SJulian Pullen 	int		free_sort = FALSE;
18407c478bd9Sstevel@tonic-gate 
18417c478bd9Sstevel@tonic-gate 	_freeControlList(&cookie->p_serverctrls);
18427c478bd9Sstevel@tonic-gate 
1843*9f2fd570SJulian Pullen 	if (cookie->sortTypeTry == SSS_UNKNOWN)
1844*9f2fd570SJulian Pullen 		cookie->sortTypeTry = get_srvsidesort_type(cookie->service);
1845*9f2fd570SJulian Pullen 	if (cookie->sortTypeTry == SSS_UNKNOWN)
1846*9f2fd570SJulian Pullen 		cookie->sortTypeTry = SSS_SINGLE_ATTR;
1847*9f2fd570SJulian Pullen 
1848*9f2fd570SJulian Pullen 	if (cookie->sortTypeTry == SSS_SINGLE_ATTR) {
1849*9f2fd570SJulian Pullen 		if ((cookie->i_flags & NS_LDAP_NOMAP) == 0 &&
1850*9f2fd570SJulian Pullen 		    cookie->i_sortattr) {
1851*9f2fd570SJulian Pullen 			sortattr =  __ns_ldap_mapAttribute(cookie->service,
1852*9f2fd570SJulian Pullen 			    cookie->i_sortattr);
1853*9f2fd570SJulian Pullen 			free_sort = TRUE;
1854*9f2fd570SJulian Pullen 		} else if (cookie->i_sortattr) {
1855*9f2fd570SJulian Pullen 			sortattr = (char *)cookie->i_sortattr;
1856*9f2fd570SJulian Pullen 		} else {
1857*9f2fd570SJulian Pullen 			sortattr = "cn";
1858*9f2fd570SJulian Pullen 		}
1859*9f2fd570SJulian Pullen 	} else {
1860*9f2fd570SJulian Pullen 		sortattr = "cn uid";
1861*9f2fd570SJulian Pullen 	}
1862*9f2fd570SJulian Pullen 
1863*9f2fd570SJulian Pullen 	rc = ldap_create_sort_keylist(&sortkeylist, sortattr);
1864*9f2fd570SJulian Pullen 	if (free_sort)
1865*9f2fd570SJulian Pullen 		free(sortattr);
18667c478bd9Sstevel@tonic-gate 	if (rc != LDAP_SUCCESS) {
18677c478bd9Sstevel@tonic-gate 		(void) ldap_get_option(cookie->conn->ld,
18687c478bd9Sstevel@tonic-gate 		    LDAP_OPT_ERROR_NUMBER, &rc);
18697c478bd9Sstevel@tonic-gate 		return (rc);
18707c478bd9Sstevel@tonic-gate 	}
18717c478bd9Sstevel@tonic-gate 	rc = ldap_create_sort_control(cookie->conn->ld,
18727c478bd9Sstevel@tonic-gate 	    sortkeylist, 1, &sortctrl);
18737c478bd9Sstevel@tonic-gate 	ldap_free_sort_keylist(sortkeylist);
18747c478bd9Sstevel@tonic-gate 	if (rc != LDAP_SUCCESS) {
18757c478bd9Sstevel@tonic-gate 		(void) ldap_get_option(cookie->conn->ld,
18767c478bd9Sstevel@tonic-gate 		    LDAP_OPT_ERROR_NUMBER, &rc);
18777c478bd9Sstevel@tonic-gate 		return (rc);
18787c478bd9Sstevel@tonic-gate 	}
18797c478bd9Sstevel@tonic-gate 
18807c478bd9Sstevel@tonic-gate 	vlist.ldvlist_index = cookie->index;
18817c478bd9Sstevel@tonic-gate 	vlist.ldvlist_size = 0;
18827c478bd9Sstevel@tonic-gate 
18837c478bd9Sstevel@tonic-gate 	vlist.ldvlist_before_count = 0;
18847c478bd9Sstevel@tonic-gate 	vlist.ldvlist_after_count = LISTPAGESIZE-1;
18857c478bd9Sstevel@tonic-gate 	vlist.ldvlist_attrvalue = NULL;
18867c478bd9Sstevel@tonic-gate 	vlist.ldvlist_extradata = NULL;
18877c478bd9Sstevel@tonic-gate 
18887c478bd9Sstevel@tonic-gate 	rc = ldap_create_virtuallist_control(cookie->conn->ld,
18897c478bd9Sstevel@tonic-gate 	    &vlist, &vlvctrl);
18907c478bd9Sstevel@tonic-gate 	if (rc != LDAP_SUCCESS) {
18917c478bd9Sstevel@tonic-gate 		ldap_control_free(sortctrl);
18927c478bd9Sstevel@tonic-gate 		(void) ldap_get_option(cookie->conn->ld, LDAP_OPT_ERROR_NUMBER,
18937c478bd9Sstevel@tonic-gate 		    &rc);
18947c478bd9Sstevel@tonic-gate 		return (rc);
18957c478bd9Sstevel@tonic-gate 	}
18967c478bd9Sstevel@tonic-gate 
18977c478bd9Sstevel@tonic-gate 	ctrls = (LDAPControl **)calloc(3, sizeof (LDAPControl *));
18987c478bd9Sstevel@tonic-gate 	if (ctrls == NULL) {
18997c478bd9Sstevel@tonic-gate 		ldap_control_free(sortctrl);
19007c478bd9Sstevel@tonic-gate 		ldap_control_free(vlvctrl);
19017c478bd9Sstevel@tonic-gate 		return (LDAP_NO_MEMORY);
19027c478bd9Sstevel@tonic-gate 	}
19037c478bd9Sstevel@tonic-gate 
19047c478bd9Sstevel@tonic-gate 	ctrls[0] = sortctrl;
19057c478bd9Sstevel@tonic-gate 	ctrls[1] = vlvctrl;
19067c478bd9Sstevel@tonic-gate 
19077c478bd9Sstevel@tonic-gate 	cookie->p_serverctrls = ctrls;
19087c478bd9Sstevel@tonic-gate 	return (LDAP_SUCCESS);
19097c478bd9Sstevel@tonic-gate }
19107c478bd9Sstevel@tonic-gate 
19117c478bd9Sstevel@tonic-gate static int
setup_simplepg_params(ns_ldap_cookie_t * cookie)19127c478bd9Sstevel@tonic-gate setup_simplepg_params(ns_ldap_cookie_t *cookie)
19137c478bd9Sstevel@tonic-gate {
19147c478bd9Sstevel@tonic-gate 	LDAPControl	**ctrls;
19157c478bd9Sstevel@tonic-gate 	LDAPControl	*pgctrl = NULL;
19167c478bd9Sstevel@tonic-gate 	int		rc;
19177c478bd9Sstevel@tonic-gate 
19187c478bd9Sstevel@tonic-gate 	_freeControlList(&cookie->p_serverctrls);
19197c478bd9Sstevel@tonic-gate 
19207c478bd9Sstevel@tonic-gate 	rc = ldap_create_page_control(cookie->conn->ld, LISTPAGESIZE,
19217c478bd9Sstevel@tonic-gate 	    cookie->ctrlCookie, (char)0, &pgctrl);
19227c478bd9Sstevel@tonic-gate 	if (rc != LDAP_SUCCESS) {
19237c478bd9Sstevel@tonic-gate 		(void) ldap_get_option(cookie->conn->ld, LDAP_OPT_ERROR_NUMBER,
19247c478bd9Sstevel@tonic-gate 		    &rc);
19257c478bd9Sstevel@tonic-gate 		return (rc);
19267c478bd9Sstevel@tonic-gate 	}
19277c478bd9Sstevel@tonic-gate 
19287c478bd9Sstevel@tonic-gate 	ctrls = (LDAPControl **)calloc(2, sizeof (LDAPControl *));
19297c478bd9Sstevel@tonic-gate 	if (ctrls == NULL) {
19307c478bd9Sstevel@tonic-gate 		ldap_control_free(pgctrl);
19317c478bd9Sstevel@tonic-gate 		return (LDAP_NO_MEMORY);
19327c478bd9Sstevel@tonic-gate 	}
19337c478bd9Sstevel@tonic-gate 	ctrls[0] = pgctrl;
19347c478bd9Sstevel@tonic-gate 	cookie->p_serverctrls = ctrls;
19357c478bd9Sstevel@tonic-gate 	return (LDAP_SUCCESS);
19367c478bd9Sstevel@tonic-gate }
19377c478bd9Sstevel@tonic-gate 
19387c478bd9Sstevel@tonic-gate static void
proc_result_referrals(ns_ldap_cookie_t * cookie)19397c478bd9Sstevel@tonic-gate proc_result_referrals(ns_ldap_cookie_t *cookie)
19407c478bd9Sstevel@tonic-gate {
19417c478bd9Sstevel@tonic-gate 	int 		errCode, i, rc;
19427c478bd9Sstevel@tonic-gate 	char 		**referrals = NULL;
19437c478bd9Sstevel@tonic-gate 
19447c478bd9Sstevel@tonic-gate 	/*
19457c478bd9Sstevel@tonic-gate 	 * Only follow one level of referrals, i.e.
19467c478bd9Sstevel@tonic-gate 	 * if already in referral mode, do nothing
19477c478bd9Sstevel@tonic-gate 	 */
19487c478bd9Sstevel@tonic-gate 	if (cookie->refpos == NULL) {
19497c478bd9Sstevel@tonic-gate 		cookie->new_state = END_RESULT;
19507c478bd9Sstevel@tonic-gate 		rc = ldap_parse_result(cookie->conn->ld,
19517c478bd9Sstevel@tonic-gate 		    cookie->resultMsg,
19527c478bd9Sstevel@tonic-gate 		    &errCode, NULL,
19537c478bd9Sstevel@tonic-gate 		    NULL, &referrals,
19547c478bd9Sstevel@tonic-gate 		    NULL, 0);
19557c478bd9Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
19567c478bd9Sstevel@tonic-gate 			(void) ldap_get_option(cookie->conn->ld,
19577c478bd9Sstevel@tonic-gate 			    LDAP_OPT_ERROR_NUMBER,
19587c478bd9Sstevel@tonic-gate 			    &cookie->err_rc);
19597c478bd9Sstevel@tonic-gate 			cookie->new_state = LDAP_ERROR;
19607c478bd9Sstevel@tonic-gate 			return;
19617c478bd9Sstevel@tonic-gate 		}
19627c478bd9Sstevel@tonic-gate 		if (errCode == LDAP_REFERRAL) {
19637c478bd9Sstevel@tonic-gate 			for (i = 0; referrals[i] != NULL;
19647c478bd9Sstevel@tonic-gate 			    i++) {
19657c478bd9Sstevel@tonic-gate 				/* add to referral list */
19667c478bd9Sstevel@tonic-gate 				rc = __s_api_addRefInfo(
19677c478bd9Sstevel@tonic-gate 				    &cookie->reflist,
19687c478bd9Sstevel@tonic-gate 				    referrals[i],
19697c478bd9Sstevel@tonic-gate 				    cookie->basedn,
19707c478bd9Sstevel@tonic-gate 				    &cookie->scope,
19717c478bd9Sstevel@tonic-gate 				    cookie->filter,
19727c478bd9Sstevel@tonic-gate 				    cookie->conn->ld);
19737c478bd9Sstevel@tonic-gate 				if (rc != NS_LDAP_SUCCESS) {
19747c478bd9Sstevel@tonic-gate 					cookie->new_state =
19757c478bd9Sstevel@tonic-gate 					    ERROR;
19767c478bd9Sstevel@tonic-gate 					break;
19777c478bd9Sstevel@tonic-gate 				}
19787c478bd9Sstevel@tonic-gate 			}
19797c478bd9Sstevel@tonic-gate 			ldap_value_free(referrals);
19807c478bd9Sstevel@tonic-gate 		}
19817c478bd9Sstevel@tonic-gate 	}
19827c478bd9Sstevel@tonic-gate }
19837c478bd9Sstevel@tonic-gate 
19847c478bd9Sstevel@tonic-gate static void
proc_search_references(ns_ldap_cookie_t * cookie)19857c478bd9Sstevel@tonic-gate proc_search_references(ns_ldap_cookie_t *cookie)
19867c478bd9Sstevel@tonic-gate {
19877c478bd9Sstevel@tonic-gate 	char 		**refurls = NULL;
19887c478bd9Sstevel@tonic-gate 	int 		i, rc;
19897c478bd9Sstevel@tonic-gate 
19907c478bd9Sstevel@tonic-gate 	/*
19917c478bd9Sstevel@tonic-gate 	 * Only follow one level of referrals, i.e.
19927c478bd9Sstevel@tonic-gate 	 * if already in referral mode, do nothing
19937c478bd9Sstevel@tonic-gate 	 */
19947c478bd9Sstevel@tonic-gate 	if (cookie->refpos == NULL) {
19957c478bd9Sstevel@tonic-gate 		refurls = ldap_get_reference_urls(
19967c478bd9Sstevel@tonic-gate 		    cookie->conn->ld,
19977c478bd9Sstevel@tonic-gate 		    cookie->resultMsg);
19987c478bd9Sstevel@tonic-gate 		if (refurls == NULL) {
19997c478bd9Sstevel@tonic-gate 			(void) ldap_get_option(cookie->conn->ld,
20007c478bd9Sstevel@tonic-gate 			    LDAP_OPT_ERROR_NUMBER,
20017c478bd9Sstevel@tonic-gate 			    &cookie->err_rc);
20027c478bd9Sstevel@tonic-gate 			cookie->new_state = LDAP_ERROR;
20037c478bd9Sstevel@tonic-gate 			return;
20047c478bd9Sstevel@tonic-gate 		}
20057c478bd9Sstevel@tonic-gate 		for (i = 0; refurls[i] != NULL; i++) {
20067c478bd9Sstevel@tonic-gate 			/* add to referral list */
20077c478bd9Sstevel@tonic-gate 			rc = __s_api_addRefInfo(
20087c478bd9Sstevel@tonic-gate 			    &cookie->reflist,
20097c478bd9Sstevel@tonic-gate 			    refurls[i],
20107c478bd9Sstevel@tonic-gate 			    cookie->basedn,
20117c478bd9Sstevel@tonic-gate 			    &cookie->scope,
20127c478bd9Sstevel@tonic-gate 			    cookie->filter,
20137c478bd9Sstevel@tonic-gate 			    cookie->conn->ld);
20147c478bd9Sstevel@tonic-gate 			if (rc != NS_LDAP_SUCCESS) {
20157c478bd9Sstevel@tonic-gate 				cookie->new_state =
20167c478bd9Sstevel@tonic-gate 				    ERROR;
20177c478bd9Sstevel@tonic-gate 				break;
20187c478bd9Sstevel@tonic-gate 			}
20197c478bd9Sstevel@tonic-gate 		}
20207c478bd9Sstevel@tonic-gate 		/* free allocated storage */
20217c478bd9Sstevel@tonic-gate 		for (i = 0; refurls[i] != NULL; i++)
20227c478bd9Sstevel@tonic-gate 			free(refurls[i]);
20237c478bd9Sstevel@tonic-gate 	}
20247c478bd9Sstevel@tonic-gate }
20257c478bd9Sstevel@tonic-gate 
20267c478bd9Sstevel@tonic-gate static ns_state_t
multi_result(ns_ldap_cookie_t * cookie)20277c478bd9Sstevel@tonic-gate multi_result(ns_ldap_cookie_t *cookie)
20287c478bd9Sstevel@tonic-gate {
20297c478bd9Sstevel@tonic-gate 	char		errstr[MAXERROR];
20307c478bd9Sstevel@tonic-gate 	char		*err;
20317c478bd9Sstevel@tonic-gate 	ns_ldap_error_t **errorp = NULL;
20327c478bd9Sstevel@tonic-gate 	LDAPControl	**retCtrls = NULL;
20337c478bd9Sstevel@tonic-gate 	int		i, rc;
20347c478bd9Sstevel@tonic-gate 	int		errCode;
20357c478bd9Sstevel@tonic-gate 	int		finished = 0;
20367c478bd9Sstevel@tonic-gate 	unsigned long	target_posp = 0;
20377c478bd9Sstevel@tonic-gate 	unsigned long	list_size = 0;
20387c478bd9Sstevel@tonic-gate 	unsigned int	count = 0;
20397c478bd9Sstevel@tonic-gate 	char 		**referrals = NULL;
20407c478bd9Sstevel@tonic-gate 
20417c478bd9Sstevel@tonic-gate 	if (cookie->listType == VLVCTRLFLAG) {
20427c478bd9Sstevel@tonic-gate 		rc = ldap_parse_result(cookie->conn->ld, cookie->resultMsg,
20437c478bd9Sstevel@tonic-gate 		    &errCode, NULL, NULL, &referrals, &retCtrls, 0);
20447c478bd9Sstevel@tonic-gate 		if (rc != LDAP_SUCCESS) {
20457c478bd9Sstevel@tonic-gate 			(void) ldap_get_option(cookie->conn->ld,
20467c478bd9Sstevel@tonic-gate 			    LDAP_OPT_ERROR_NUMBER,
20477c478bd9Sstevel@tonic-gate 			    &cookie->err_rc);
20487c478bd9Sstevel@tonic-gate 			(void) sprintf(errstr,
20497c478bd9Sstevel@tonic-gate 			    gettext("LDAP ERROR (%d): %s.\n"),
20507c478bd9Sstevel@tonic-gate 			    cookie->err_rc,
20517c478bd9Sstevel@tonic-gate 			    gettext(ldap_err2string(cookie->err_rc)));
20527c478bd9Sstevel@tonic-gate 			err = strdup(errstr);
20537c478bd9Sstevel@tonic-gate 			MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
20547c478bd9Sstevel@tonic-gate 			    NULL);
20557c478bd9Sstevel@tonic-gate 			cookie->err_rc = NS_LDAP_INTERNAL;
20567c478bd9Sstevel@tonic-gate 			cookie->errorp = *errorp;
20577c478bd9Sstevel@tonic-gate 			return (LDAP_ERROR);
20587c478bd9Sstevel@tonic-gate 		}
20597c478bd9Sstevel@tonic-gate 		if (errCode == LDAP_REFERRAL) {
20607c478bd9Sstevel@tonic-gate 			for (i = 0; referrals[i] != NULL;
20617c478bd9Sstevel@tonic-gate 			    i++) {
20627c478bd9Sstevel@tonic-gate 				/* add to referral list */
20637c478bd9Sstevel@tonic-gate 				rc = __s_api_addRefInfo(
20647c478bd9Sstevel@tonic-gate 				    &cookie->reflist,
20657c478bd9Sstevel@tonic-gate 				    referrals[i],
20667c478bd9Sstevel@tonic-gate 				    cookie->basedn,
20677c478bd9Sstevel@tonic-gate 				    &cookie->scope,
20687c478bd9Sstevel@tonic-gate 				    cookie->filter,
20697c478bd9Sstevel@tonic-gate 				    cookie->conn->ld);
20707c478bd9Sstevel@tonic-gate 				if (rc != NS_LDAP_SUCCESS) {
20717c478bd9Sstevel@tonic-gate 					ldap_value_free(
20727c478bd9Sstevel@tonic-gate 					    referrals);
20737c478bd9Sstevel@tonic-gate 					if (retCtrls)
20747c478bd9Sstevel@tonic-gate 						ldap_controls_free(
20757c478bd9Sstevel@tonic-gate 						    retCtrls);
20767c478bd9Sstevel@tonic-gate 					return (ERROR);
20777c478bd9Sstevel@tonic-gate 				}
20787c478bd9Sstevel@tonic-gate 			}
20797c478bd9Sstevel@tonic-gate 			ldap_value_free(referrals);
20807c478bd9Sstevel@tonic-gate 			if (retCtrls)
20817c478bd9Sstevel@tonic-gate 				ldap_controls_free(retCtrls);
20827c478bd9Sstevel@tonic-gate 			return (END_RESULT);
20837c478bd9Sstevel@tonic-gate 		}
20847c478bd9Sstevel@tonic-gate 		if (retCtrls) {
20857c478bd9Sstevel@tonic-gate 			rc = ldap_parse_virtuallist_control(
20867c478bd9Sstevel@tonic-gate 			    cookie->conn->ld, retCtrls,
20877c478bd9Sstevel@tonic-gate 			    &target_posp, &list_size, &errCode);
20887c478bd9Sstevel@tonic-gate 			if (rc == LDAP_SUCCESS) {
2089*9f2fd570SJulian Pullen 				/*
2090*9f2fd570SJulian Pullen 				 * AD does not return valid target_posp
2091*9f2fd570SJulian Pullen 				 * and list_size
2092*9f2fd570SJulian Pullen 				 */
2093*9f2fd570SJulian Pullen 				if (target_posp != 0 && list_size != 0) {
2094*9f2fd570SJulian Pullen 					cookie->index =
2095*9f2fd570SJulian Pullen 					    target_posp + LISTPAGESIZE;
2096*9f2fd570SJulian Pullen 					if (cookie->index > list_size)
20977c478bd9Sstevel@tonic-gate 						finished = 1;
2098*9f2fd570SJulian Pullen 				} else {
2099*9f2fd570SJulian Pullen 					if (cookie->entryCount < LISTPAGESIZE)
2100*9f2fd570SJulian Pullen 						finished = 1;
2101*9f2fd570SJulian Pullen 					else
2102*9f2fd570SJulian Pullen 						cookie->index +=
2103*9f2fd570SJulian Pullen 						    cookie->entryCount;
21047c478bd9Sstevel@tonic-gate 				}
21057c478bd9Sstevel@tonic-gate 			}
21067c478bd9Sstevel@tonic-gate 			ldap_controls_free(retCtrls);
21077c478bd9Sstevel@tonic-gate 			retCtrls = NULL;
21087c478bd9Sstevel@tonic-gate 		}
21097c478bd9Sstevel@tonic-gate 		else
21107c478bd9Sstevel@tonic-gate 			finished = 1;
21117c478bd9Sstevel@tonic-gate 	} else if (cookie->listType == SIMPLEPAGECTRLFLAG) {
21127c478bd9Sstevel@tonic-gate 		rc = ldap_parse_result(cookie->conn->ld, cookie->resultMsg,
21137c478bd9Sstevel@tonic-gate 		    &errCode, NULL, NULL, &referrals, &retCtrls, 0);
21147c478bd9Sstevel@tonic-gate 		if (rc != LDAP_SUCCESS) {
21157c478bd9Sstevel@tonic-gate 			(void) ldap_get_option(cookie->conn->ld,
21167c478bd9Sstevel@tonic-gate 			    LDAP_OPT_ERROR_NUMBER,
21177c478bd9Sstevel@tonic-gate 			    &cookie->err_rc);
21187c478bd9Sstevel@tonic-gate 			(void) sprintf(errstr,
21197c478bd9Sstevel@tonic-gate 			    gettext("LDAP ERROR (%d): %s.\n"),
21207c478bd9Sstevel@tonic-gate 			    cookie->err_rc,
21217c478bd9Sstevel@tonic-gate 			    gettext(ldap_err2string(cookie->err_rc)));
21227c478bd9Sstevel@tonic-gate 			err = strdup(errstr);
21237c478bd9Sstevel@tonic-gate 			MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
21247c478bd9Sstevel@tonic-gate 			    NULL);
21257c478bd9Sstevel@tonic-gate 			cookie->err_rc = NS_LDAP_INTERNAL;
21267c478bd9Sstevel@tonic-gate 			cookie->errorp = *errorp;
21277c478bd9Sstevel@tonic-gate 			return (LDAP_ERROR);
21287c478bd9Sstevel@tonic-gate 		}
21297c478bd9Sstevel@tonic-gate 		if (errCode == LDAP_REFERRAL) {
21307c478bd9Sstevel@tonic-gate 			for (i = 0; referrals[i] != NULL;
21317c478bd9Sstevel@tonic-gate 			    i++) {
21327c478bd9Sstevel@tonic-gate 				/* add to referral list */
21337c478bd9Sstevel@tonic-gate 				rc = __s_api_addRefInfo(
21347c478bd9Sstevel@tonic-gate 				    &cookie->reflist,
21357c478bd9Sstevel@tonic-gate 				    referrals[i],
21367c478bd9Sstevel@tonic-gate 				    cookie->basedn,
21377c478bd9Sstevel@tonic-gate 				    &cookie->scope,
21387c478bd9Sstevel@tonic-gate 				    cookie->filter,
21397c478bd9Sstevel@tonic-gate 				    cookie->conn->ld);
21407c478bd9Sstevel@tonic-gate 				if (rc != NS_LDAP_SUCCESS) {
21417c478bd9Sstevel@tonic-gate 					ldap_value_free(
21427c478bd9Sstevel@tonic-gate 					    referrals);
21437c478bd9Sstevel@tonic-gate 					if (retCtrls)
21447c478bd9Sstevel@tonic-gate 						ldap_controls_free(
21457c478bd9Sstevel@tonic-gate 						    retCtrls);
21467c478bd9Sstevel@tonic-gate 					return (ERROR);
21477c478bd9Sstevel@tonic-gate 				}
21487c478bd9Sstevel@tonic-gate 			}
21497c478bd9Sstevel@tonic-gate 			ldap_value_free(referrals);
21507c478bd9Sstevel@tonic-gate 			if (retCtrls)
21517c478bd9Sstevel@tonic-gate 				ldap_controls_free(retCtrls);
21527c478bd9Sstevel@tonic-gate 			return (END_RESULT);
21537c478bd9Sstevel@tonic-gate 		}
21547c478bd9Sstevel@tonic-gate 		if (retCtrls) {
21557c478bd9Sstevel@tonic-gate 			if (cookie->ctrlCookie)
21567c478bd9Sstevel@tonic-gate 				ber_bvfree(cookie->ctrlCookie);
21577c478bd9Sstevel@tonic-gate 			cookie->ctrlCookie = NULL;
21587c478bd9Sstevel@tonic-gate 			rc = ldap_parse_page_control(
21597c478bd9Sstevel@tonic-gate 			    cookie->conn->ld, retCtrls,
21607c478bd9Sstevel@tonic-gate 			    &count, &cookie->ctrlCookie);
21617c478bd9Sstevel@tonic-gate 			if (rc == LDAP_SUCCESS) {
21627c478bd9Sstevel@tonic-gate 				if ((cookie->ctrlCookie == NULL) ||
21637c478bd9Sstevel@tonic-gate 				    (cookie->ctrlCookie->bv_val == NULL) ||
216470a09e7fSav147483 				    (cookie->ctrlCookie->bv_len == 0))
21657c478bd9Sstevel@tonic-gate 					finished = 1;
21667c478bd9Sstevel@tonic-gate 			}
21677c478bd9Sstevel@tonic-gate 			ldap_controls_free(retCtrls);
21687c478bd9Sstevel@tonic-gate 			retCtrls = NULL;
21697c478bd9Sstevel@tonic-gate 		}
21707c478bd9Sstevel@tonic-gate 		else
21717c478bd9Sstevel@tonic-gate 			finished = 1;
21727c478bd9Sstevel@tonic-gate 	}
21737c478bd9Sstevel@tonic-gate 	if (!finished && cookie->listType == VLVCTRLFLAG)
21747c478bd9Sstevel@tonic-gate 		return (NEXT_VLV);
21757c478bd9Sstevel@tonic-gate 	if (!finished && cookie->listType == SIMPLEPAGECTRLFLAG)
21767c478bd9Sstevel@tonic-gate 		return (NEXT_PAGE);
21777c478bd9Sstevel@tonic-gate 	if (finished)
21787c478bd9Sstevel@tonic-gate 		return (END_RESULT);
21797c478bd9Sstevel@tonic-gate 	return (ERROR);
21807c478bd9Sstevel@tonic-gate }
21817c478bd9Sstevel@tonic-gate 
21827c478bd9Sstevel@tonic-gate /*
2183b5d0e4ebSmj162486  * clear_results(ns_ldap_cookie_t):
2184b5d0e4ebSmj162486  *
2185b5d0e4ebSmj162486  * Attempt to obtain remnants of ldap responses and free them.  If remnants are
2186b5d0e4ebSmj162486  * not obtained within a certain time period tell the server we wish to abandon
2187b5d0e4ebSmj162486  * the request.
2188b5d0e4ebSmj162486  *
2189b5d0e4ebSmj162486  * Note that we do not initially tell the server to abandon the request as that
2190b5d0e4ebSmj162486  * can be an expensive operation for the server, while it is cheap for us to
2191b5d0e4ebSmj162486  * just flush the input.
2192b5d0e4ebSmj162486  *
2193b5d0e4ebSmj162486  * If something was to remain in libldap queue as a result of some error then
2194b5d0e4ebSmj162486  * it would be freed later during drop connection call or when no other
2195b5d0e4ebSmj162486  * requests share the connection.
2196b5d0e4ebSmj162486  */
2197b5d0e4ebSmj162486 static void
clear_results(ns_ldap_cookie_t * cookie)2198b5d0e4ebSmj162486 clear_results(ns_ldap_cookie_t *cookie)
2199b5d0e4ebSmj162486 {
2200b5d0e4ebSmj162486 	int rc;
2201b5d0e4ebSmj162486 	if (cookie->conn != NULL && cookie->conn->ld != NULL &&
2202e1dd0a2fSth160488 	    (cookie->connectionId != -1 ||
2203e1dd0a2fSth160488 	    (cookie->conn_user != NULL &&
2204e1dd0a2fSth160488 	    cookie->conn_user->conn_mt != NULL)) &&
2205e1dd0a2fSth160488 	    cookie->msgId != 0) {
2206b5d0e4ebSmj162486 		/*
2207b5d0e4ebSmj162486 		 * We need to cleanup the rest of response (if there is such)
2208b5d0e4ebSmj162486 		 * and LDAP abandon is too heavy for LDAP servers, so we will
2209b5d0e4ebSmj162486 		 * wait for the rest of response till timeout and "process" it.
2210b5d0e4ebSmj162486 		 */
2211b5d0e4ebSmj162486 		rc = ldap_result(cookie->conn->ld, cookie->msgId, LDAP_MSG_ALL,
2212b5d0e4ebSmj162486 		    (struct timeval *)&cookie->search_timeout,
2213b5d0e4ebSmj162486 		    &cookie->resultMsg);
2214*9f2fd570SJulian Pullen 		if (rc != -1 && rc != 0 && cookie->resultMsg != NULL) {
2215b5d0e4ebSmj162486 			(void) ldap_msgfree(cookie->resultMsg);
2216*9f2fd570SJulian Pullen 			cookie->resultMsg = NULL;
2217*9f2fd570SJulian Pullen 		}
2218*9f2fd570SJulian Pullen 
2219b5d0e4ebSmj162486 		/*
2220b5d0e4ebSmj162486 		 * If there was timeout then we will send  ABANDON request to
2221b5d0e4ebSmj162486 		 * LDAP server to decrease load.
2222b5d0e4ebSmj162486 		 */
2223b5d0e4ebSmj162486 		if (rc == 0)
2224b5d0e4ebSmj162486 			(void) ldap_abandon_ext(cookie->conn->ld, cookie->msgId,
2225b5d0e4ebSmj162486 			    NULL, NULL);
2226b5d0e4ebSmj162486 		/* Disassociate cookie with msgId */
2227b5d0e4ebSmj162486 		cookie->msgId = 0;
2228b5d0e4ebSmj162486 	}
2229b5d0e4ebSmj162486 }
2230b5d0e4ebSmj162486 
2231b5d0e4ebSmj162486 /*
22327c478bd9Sstevel@tonic-gate  * This state machine performs one or more LDAP searches to a given
22337c478bd9Sstevel@tonic-gate  * directory server using service search descriptors and schema
22347c478bd9Sstevel@tonic-gate  * mapping as appropriate.  The approximate pseudocode for
22357c478bd9Sstevel@tonic-gate  * this routine is the following:
22367c478bd9Sstevel@tonic-gate  *    Given the current configuration [set/reset connection etc.]
22377c478bd9Sstevel@tonic-gate  *    and the current service search descriptor list
22387c478bd9Sstevel@tonic-gate  *        or default search filter parameters
22397c478bd9Sstevel@tonic-gate  *    foreach (service search filter) {
22407c478bd9Sstevel@tonic-gate  *        initialize the filter [via filter_init if appropriate]
22417c478bd9Sstevel@tonic-gate  *		  get a valid session/connection (preferably the current one)
22427c478bd9Sstevel@tonic-gate  *					Recover if the connection is lost
22437c478bd9Sstevel@tonic-gate  *        perform the search
22447c478bd9Sstevel@tonic-gate  *        foreach (result entry) {
22457c478bd9Sstevel@tonic-gate  *            process result [via callback if appropriate]
22467c478bd9Sstevel@tonic-gate  *                save result for caller if accepted.
22477c478bd9Sstevel@tonic-gate  *                exit and return all collected if allResults found;
22487c478bd9Sstevel@tonic-gate  *        }
22497c478bd9Sstevel@tonic-gate  *    }
22507c478bd9Sstevel@tonic-gate  *    return collected results and exit
22517c478bd9Sstevel@tonic-gate  */
22527c478bd9Sstevel@tonic-gate 
22537c478bd9Sstevel@tonic-gate static
22547c478bd9Sstevel@tonic-gate ns_state_t
search_state_machine(ns_ldap_cookie_t * cookie,ns_state_t state,int cycle)22557c478bd9Sstevel@tonic-gate search_state_machine(ns_ldap_cookie_t *cookie, ns_state_t state, int cycle)
22567c478bd9Sstevel@tonic-gate {
22577c478bd9Sstevel@tonic-gate 	char		errstr[MAXERROR];
22587c478bd9Sstevel@tonic-gate 	char		*err;
2259e8ac3ceaSsdussud 	int		rc, ret;
2260e1dd0a2fSth160488 	int		rc_save;
22617c478bd9Sstevel@tonic-gate 	ns_ldap_entry_t	*nextEntry;
22627c478bd9Sstevel@tonic-gate 	ns_ldap_error_t *error = NULL;
22637c478bd9Sstevel@tonic-gate 	ns_ldap_error_t **errorp;
2264479ac375Sdm199847 	struct timeval	tv;
22657c478bd9Sstevel@tonic-gate 
22667c478bd9Sstevel@tonic-gate 	errorp = &error;
22677c478bd9Sstevel@tonic-gate 	cookie->state = state;
22688277a58bSchinlong 	errstr[0] = '\0';
22697c478bd9Sstevel@tonic-gate 
22707c478bd9Sstevel@tonic-gate 	for (;;) {
22717c478bd9Sstevel@tonic-gate 		switch (cookie->state) {
2272699bceb8Smj162486 		case CLEAR_RESULTS:
2273b5d0e4ebSmj162486 			clear_results(cookie);
2274699bceb8Smj162486 			cookie->new_state = EXIT;
2275699bceb8Smj162486 			break;
227647789246Svv149972 		case GET_ACCT_MGMT_INFO:
227747789246Svv149972 			/*
227847789246Svv149972 			 * Set the flag to get ldap account management controls.
227947789246Svv149972 			 */
228047789246Svv149972 			cookie->nopasswd_acct_mgmt = 1;
228147789246Svv149972 			cookie->new_state = INIT;
228247789246Svv149972 			break;
22837c478bd9Sstevel@tonic-gate 		case EXIT:
22847c478bd9Sstevel@tonic-gate 			/* state engine/connection cleaned up in delete */
22857c478bd9Sstevel@tonic-gate 			if (cookie->attribute) {
22867c478bd9Sstevel@tonic-gate 				__s_api_free2dArray(cookie->attribute);
22877c478bd9Sstevel@tonic-gate 				cookie->attribute = NULL;
22887c478bd9Sstevel@tonic-gate 			}
22897c478bd9Sstevel@tonic-gate 			if (cookie->reflist) {
22907c478bd9Sstevel@tonic-gate 				__s_api_deleteRefInfo(cookie->reflist);
22917c478bd9Sstevel@tonic-gate 				cookie->reflist = NULL;
22927c478bd9Sstevel@tonic-gate 			}
22937c478bd9Sstevel@tonic-gate 			return (EXIT);
22947c478bd9Sstevel@tonic-gate 		case INIT:
22957c478bd9Sstevel@tonic-gate 			cookie->sdpos = NULL;
22967c478bd9Sstevel@tonic-gate 			cookie->new_state = NEXT_SEARCH_DESCRIPTOR;
22977c478bd9Sstevel@tonic-gate 			if (cookie->attribute) {
22987c478bd9Sstevel@tonic-gate 				__s_api_free2dArray(cookie->attribute);
22997c478bd9Sstevel@tonic-gate 				cookie->attribute = NULL;
23007c478bd9Sstevel@tonic-gate 			}
23017c478bd9Sstevel@tonic-gate 			if ((cookie->i_flags & NS_LDAP_NOMAP) == 0 &&
23027c478bd9Sstevel@tonic-gate 			    cookie->i_attr) {
23037c478bd9Sstevel@tonic-gate 				cookie->attribute =
23047c478bd9Sstevel@tonic-gate 				    __ns_ldap_mapAttributeList(
23057c478bd9Sstevel@tonic-gate 				    cookie->service,
23067c478bd9Sstevel@tonic-gate 				    cookie->i_attr);
23077c478bd9Sstevel@tonic-gate 			}
23087c478bd9Sstevel@tonic-gate 			break;
2309e1dd0a2fSth160488 		case REINIT:
2310e1dd0a2fSth160488 			/* Check if we've reached MAX retries. */
2311e1dd0a2fSth160488 			cookie->retries++;
2312e1dd0a2fSth160488 			if (cookie->retries > NS_LIST_TRY_MAX - 1) {
2313e1dd0a2fSth160488 				cookie->new_state = LDAP_ERROR;
2314e1dd0a2fSth160488 				break;
2315e1dd0a2fSth160488 			}
2316e1dd0a2fSth160488 
2317e1dd0a2fSth160488 			/*
2318e1dd0a2fSth160488 			 * Even if we still have retries left, check
2319e1dd0a2fSth160488 			 * if retry is possible.
2320e1dd0a2fSth160488 			 */
2321e1dd0a2fSth160488 			if (cookie->conn_user != NULL) {
2322e1dd0a2fSth160488 				int		retry;
2323e1dd0a2fSth160488 				ns_conn_mgmt_t	*cmg;
2324e1dd0a2fSth160488 				cmg = cookie->conn_user->conn_mgmt;
2325e1dd0a2fSth160488 				retry = cookie->conn_user->retry;
2326e1dd0a2fSth160488 				if (cmg != NULL && cmg->cfg_reloaded == 1)
2327e1dd0a2fSth160488 					retry = 1;
2328e1dd0a2fSth160488 				if (retry == 0) {
2329e1dd0a2fSth160488 					cookie->new_state = LDAP_ERROR;
2330e1dd0a2fSth160488 					break;
2331e1dd0a2fSth160488 				}
2332e1dd0a2fSth160488 			}
2333e1dd0a2fSth160488 			/*
2334e1dd0a2fSth160488 			 * Free results if any, reset to the first
2335e1dd0a2fSth160488 			 * search descriptor and start a new session.
2336e1dd0a2fSth160488 			 */
2337e1dd0a2fSth160488 			if (cookie->resultMsg != NULL) {
2338e1dd0a2fSth160488 				(void) ldap_msgfree(cookie->resultMsg);
2339e1dd0a2fSth160488 				cookie->resultMsg = NULL;
2340e1dd0a2fSth160488 			}
2341e1dd0a2fSth160488 			(void) __ns_ldap_freeError(&cookie->errorp);
2342e1dd0a2fSth160488 			(void) __ns_ldap_freeResult(&cookie->result);
2343e1dd0a2fSth160488 			cookie->sdpos = cookie->sdlist;
2344e1dd0a2fSth160488 			cookie->err_from_result = 0;
2345e1dd0a2fSth160488 			cookie->err_rc = 0;
2346e1dd0a2fSth160488 			cookie->new_state = NEXT_SESSION;
2347e1dd0a2fSth160488 			break;
23487c478bd9Sstevel@tonic-gate 		case NEXT_SEARCH_DESCRIPTOR:
23497c478bd9Sstevel@tonic-gate 			/* get next search descriptor */
23507c478bd9Sstevel@tonic-gate 			if (cookie->sdpos == NULL) {
23517c478bd9Sstevel@tonic-gate 				cookie->sdpos = cookie->sdlist;
23527c478bd9Sstevel@tonic-gate 				cookie->new_state = GET_SESSION;
23537c478bd9Sstevel@tonic-gate 			} else {
23547c478bd9Sstevel@tonic-gate 				cookie->sdpos++;
23557c478bd9Sstevel@tonic-gate 				cookie->new_state = NEXT_SEARCH;
23567c478bd9Sstevel@tonic-gate 			}
23577c478bd9Sstevel@tonic-gate 			if (*cookie->sdpos == NULL)
23587c478bd9Sstevel@tonic-gate 				cookie->new_state = EXIT;
23597c478bd9Sstevel@tonic-gate 			break;
23607c478bd9Sstevel@tonic-gate 		case GET_SESSION:
23617c478bd9Sstevel@tonic-gate 			if (get_current_session(cookie) < 0)
23627c478bd9Sstevel@tonic-gate 				cookie->new_state = NEXT_SESSION;
23637c478bd9Sstevel@tonic-gate 			else
23647c478bd9Sstevel@tonic-gate 				cookie->new_state = NEXT_SEARCH;
23657c478bd9Sstevel@tonic-gate 			break;
23667c478bd9Sstevel@tonic-gate 		case NEXT_SESSION:
23677c478bd9Sstevel@tonic-gate 			if (get_next_session(cookie) < 0)
23687c478bd9Sstevel@tonic-gate 				cookie->new_state = RESTART_SESSION;
23697c478bd9Sstevel@tonic-gate 			else
23707c478bd9Sstevel@tonic-gate 				cookie->new_state = NEXT_SEARCH;
23717c478bd9Sstevel@tonic-gate 			break;
23727c478bd9Sstevel@tonic-gate 		case RESTART_SESSION:
23737c478bd9Sstevel@tonic-gate 			if (cookie->i_flags & NS_LDAP_HARD) {
23747c478bd9Sstevel@tonic-gate 				cookie->new_state = NEXT_SESSION;
23757c478bd9Sstevel@tonic-gate 				break;
23767c478bd9Sstevel@tonic-gate 			}
23777c478bd9Sstevel@tonic-gate 			(void) sprintf(errstr,
23787c478bd9Sstevel@tonic-gate 			    gettext("Session error no available conn.\n"),
23797c478bd9Sstevel@tonic-gate 			    state);
23807c478bd9Sstevel@tonic-gate 			err = strdup(errstr);
23817c478bd9Sstevel@tonic-gate 			MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
23827c478bd9Sstevel@tonic-gate 			    NULL);
23837c478bd9Sstevel@tonic-gate 			cookie->err_rc = NS_LDAP_INTERNAL;
23847c478bd9Sstevel@tonic-gate 			cookie->errorp = *errorp;
23857c478bd9Sstevel@tonic-gate 			cookie->new_state = EXIT;
23867c478bd9Sstevel@tonic-gate 			break;
23877c478bd9Sstevel@tonic-gate 		case NEXT_SEARCH:
23887c478bd9Sstevel@tonic-gate 			/* setup referrals search if necessary */
23897c478bd9Sstevel@tonic-gate 			if (cookie->refpos) {
23907c478bd9Sstevel@tonic-gate 				if (setup_referral_search(cookie) < 0) {
23917c478bd9Sstevel@tonic-gate 					cookie->new_state = EXIT;
23927c478bd9Sstevel@tonic-gate 					break;
23937c478bd9Sstevel@tonic-gate 				}
23947c478bd9Sstevel@tonic-gate 			} else if (setup_next_search(cookie) < 0) {
23957c478bd9Sstevel@tonic-gate 				cookie->new_state = EXIT;
23967c478bd9Sstevel@tonic-gate 				break;
23977c478bd9Sstevel@tonic-gate 			}
23987c478bd9Sstevel@tonic-gate 			/* only do VLV/PAGE on scopes onelevel/subtree */
23997c478bd9Sstevel@tonic-gate 			if (paging_supported(cookie)) {
24007c478bd9Sstevel@tonic-gate 				if (cookie->use_paging &&
24017c478bd9Sstevel@tonic-gate 				    (cookie->scope != LDAP_SCOPE_BASE)) {
24027c478bd9Sstevel@tonic-gate 					cookie->index = 1;
24037c478bd9Sstevel@tonic-gate 					if (cookie->listType == VLVCTRLFLAG)
24047c478bd9Sstevel@tonic-gate 						cookie->new_state = NEXT_VLV;
24057c478bd9Sstevel@tonic-gate 					else
24067c478bd9Sstevel@tonic-gate 						cookie->new_state = NEXT_PAGE;
24077c478bd9Sstevel@tonic-gate 					break;
24087c478bd9Sstevel@tonic-gate 				}
24097c478bd9Sstevel@tonic-gate 			}
24107c478bd9Sstevel@tonic-gate 			cookie->new_state = ONE_SEARCH;
24117c478bd9Sstevel@tonic-gate 			break;
24127c478bd9Sstevel@tonic-gate 		case NEXT_VLV:
24137c478bd9Sstevel@tonic-gate 			rc = setup_vlv_params(cookie);
24147c478bd9Sstevel@tonic-gate 			if (rc != LDAP_SUCCESS) {
24157c478bd9Sstevel@tonic-gate 				cookie->err_rc = rc;
24167c478bd9Sstevel@tonic-gate 				cookie->new_state = LDAP_ERROR;
24177c478bd9Sstevel@tonic-gate 				break;
24187c478bd9Sstevel@tonic-gate 			}
24197c478bd9Sstevel@tonic-gate 			cookie->next_state = MULTI_RESULT;
24207c478bd9Sstevel@tonic-gate 			cookie->new_state = DO_SEARCH;
24217c478bd9Sstevel@tonic-gate 			break;
24227c478bd9Sstevel@tonic-gate 		case NEXT_PAGE:
24237c478bd9Sstevel@tonic-gate 			rc = setup_simplepg_params(cookie);
24247c478bd9Sstevel@tonic-gate 			if (rc != LDAP_SUCCESS) {
24257c478bd9Sstevel@tonic-gate 				cookie->err_rc = rc;
24267c478bd9Sstevel@tonic-gate 				cookie->new_state = LDAP_ERROR;
24277c478bd9Sstevel@tonic-gate 				break;
24287c478bd9Sstevel@tonic-gate 			}
24297c478bd9Sstevel@tonic-gate 			cookie->next_state = MULTI_RESULT;
24307c478bd9Sstevel@tonic-gate 			cookie->new_state = DO_SEARCH;
24317c478bd9Sstevel@tonic-gate 			break;
24327c478bd9Sstevel@tonic-gate 		case ONE_SEARCH:
24337c478bd9Sstevel@tonic-gate 			cookie->next_state = NEXT_RESULT;
24347c478bd9Sstevel@tonic-gate 			cookie->new_state = DO_SEARCH;
24357c478bd9Sstevel@tonic-gate 			break;
24367c478bd9Sstevel@tonic-gate 		case DO_SEARCH:
2437*9f2fd570SJulian Pullen 			cookie->entryCount = 0;
24387c478bd9Sstevel@tonic-gate 			rc = ldap_search_ext(cookie->conn->ld,
24397c478bd9Sstevel@tonic-gate 			    cookie->basedn,
24407c478bd9Sstevel@tonic-gate 			    cookie->scope,
24417c478bd9Sstevel@tonic-gate 			    cookie->filter,
24427c478bd9Sstevel@tonic-gate 			    cookie->attribute,
24437c478bd9Sstevel@tonic-gate 			    0,
24447c478bd9Sstevel@tonic-gate 			    cookie->p_serverctrls,
24457c478bd9Sstevel@tonic-gate 			    NULL,
24467c478bd9Sstevel@tonic-gate 			    &cookie->search_timeout, 0,
24477c478bd9Sstevel@tonic-gate 			    &cookie->msgId);
24487c478bd9Sstevel@tonic-gate 			if (rc != LDAP_SUCCESS) {
24497c478bd9Sstevel@tonic-gate 				if (rc == LDAP_BUSY ||
24507c478bd9Sstevel@tonic-gate 				    rc == LDAP_UNAVAILABLE ||
24517c478bd9Sstevel@tonic-gate 				    rc == LDAP_UNWILLING_TO_PERFORM ||
24527c478bd9Sstevel@tonic-gate 				    rc == LDAP_CONNECT_ERROR ||
24537c478bd9Sstevel@tonic-gate 				    rc == LDAP_SERVER_DOWN) {
24547c478bd9Sstevel@tonic-gate 
2455e1dd0a2fSth160488 					if (cookie->reinit_on_retriable_err) {
2456e1dd0a2fSth160488 						cookie->err_rc = rc;
2457e1dd0a2fSth160488 						cookie->new_state = REINIT;
2458e1dd0a2fSth160488 					} else
2459e1dd0a2fSth160488 						cookie->new_state =
2460e1dd0a2fSth160488 						    NEXT_SESSION;
24617c478bd9Sstevel@tonic-gate 
24627c478bd9Sstevel@tonic-gate 					/*
24637c478bd9Sstevel@tonic-gate 					 * If not able to reach the
24647c478bd9Sstevel@tonic-gate 					 * server, inform the ldap
24657c478bd9Sstevel@tonic-gate 					 * cache manager that the
24667c478bd9Sstevel@tonic-gate 					 * server should be removed
24677c478bd9Sstevel@tonic-gate 					 * from it's server list.
24687c478bd9Sstevel@tonic-gate 					 * Thus, the manager will not
24697c478bd9Sstevel@tonic-gate 					 * return this server on the next
24707c478bd9Sstevel@tonic-gate 					 * get-server request and will
24717c478bd9Sstevel@tonic-gate 					 * also reduce the server list
24727c478bd9Sstevel@tonic-gate 					 * refresh TTL, so that it will
24737c478bd9Sstevel@tonic-gate 					 * find out sooner when the server
24747c478bd9Sstevel@tonic-gate 					 * is up again.
24757c478bd9Sstevel@tonic-gate 					 */
2476e1dd0a2fSth160488 					if ((rc == LDAP_CONNECT_ERROR ||
2477e1dd0a2fSth160488 					    rc == LDAP_SERVER_DOWN) &&
2478e1dd0a2fSth160488 					    (cookie->conn_user == NULL ||
2479e1dd0a2fSth160488 					    cookie->conn_user->conn_mt ==
2480e1dd0a2fSth160488 					    NULL)) {
2481e8ac3ceaSsdussud 						ret = __s_api_removeServer(
24827c478bd9Sstevel@tonic-gate 						    cookie->conn->serverAddr);
2483e1dd0a2fSth160488 						if (ret == NS_CACHE_NOSERVER &&
2484e8ac3ceaSsdussud 						    cookie->conn_auth_type
2485e8ac3ceaSsdussud 						    == NS_LDAP_AUTH_NONE) {
2486e8ac3ceaSsdussud 							/*
2487e8ac3ceaSsdussud 							 * Couldn't remove
2488e8ac3ceaSsdussud 							 * server from server
2489e8ac3ceaSsdussud 							 * list.
2490e8ac3ceaSsdussud 							 * Exit to avoid
2491e8ac3ceaSsdussud 							 * potential infinite
2492e8ac3ceaSsdussud 							 * loop.
2493e8ac3ceaSsdussud 							 */
2494e8ac3ceaSsdussud 							cookie->err_rc = rc;
2495e8ac3ceaSsdussud 							cookie->new_state =
2496e8ac3ceaSsdussud 							    LDAP_ERROR;
2497e8ac3ceaSsdussud 						}
24987c478bd9Sstevel@tonic-gate 						if (cookie->connectionId > -1) {
2499cb5caa98Sdjl 							/*
2500cb5caa98Sdjl 							 * NS_LDAP_NEW_CONN
2501cb5caa98Sdjl 							 * indicates that the
2502cb5caa98Sdjl 							 * connection should
2503cb5caa98Sdjl 							 * be deleted, not
2504cb5caa98Sdjl 							 * kept alive
2505cb5caa98Sdjl 							 */
25067c478bd9Sstevel@tonic-gate 							DropConnection(
2507699bceb8Smj162486 							    cookie->
2508699bceb8Smj162486 							    connectionId,
25097c478bd9Sstevel@tonic-gate 							    NS_LDAP_NEW_CONN);
2510cb5caa98Sdjl 							cookie->connectionId =
2511cb5caa98Sdjl 							    -1;
25127c478bd9Sstevel@tonic-gate 						}
2513e1dd0a2fSth160488 					} else if ((rc == LDAP_CONNECT_ERROR ||
2514e1dd0a2fSth160488 					    rc == LDAP_SERVER_DOWN) &&
2515ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 					    cookie->conn_user != NULL) {
2516ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 						if (cookie->
2517ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 						    reinit_on_retriable_err) {
2518e1dd0a2fSth160488 							/*
2519ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							 * MT connection not
2520ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							 * usable, close it
2521ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							 * before REINIT.
2522ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							 * rc has already
2523ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							 * been saved in
2524ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							 * cookie->err_rc above.
2525e1dd0a2fSth160488 							 */
2526e1dd0a2fSth160488 							__s_api_conn_mt_close(
2527e1dd0a2fSth160488 							    cookie->conn_user,
2528ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							    rc,
2529ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							    &cookie->errorp);
2530ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 						} else {
2531ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							/*
2532ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							 * MT connection not
2533ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							 * usable, close it in
2534ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							 * the LDAP_ERROR state.
2535ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							 * A retry will be done
2536ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							 * next if allowed.
2537ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							 */
2538ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							cookie->err_rc = rc;
2539ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							cookie->new_state =
2540ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 							    LDAP_ERROR;
2541ead6eed0SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 						}
25427c478bd9Sstevel@tonic-gate 					}
25437c478bd9Sstevel@tonic-gate 					break;
25447c478bd9Sstevel@tonic-gate 				}
25457c478bd9Sstevel@tonic-gate 				cookie->err_rc = rc;
25467c478bd9Sstevel@tonic-gate 				cookie->new_state = LDAP_ERROR;
25477c478bd9Sstevel@tonic-gate 				break;
25487c478bd9Sstevel@tonic-gate 			}
25497c478bd9Sstevel@tonic-gate 			cookie->new_state = cookie->next_state;
25507c478bd9Sstevel@tonic-gate 			break;
25517c478bd9Sstevel@tonic-gate 		case NEXT_RESULT:
2552479ac375Sdm199847 			/*
2553479ac375Sdm199847 			 * Caller (e.g. __ns_ldap_list_batch_add)
2554479ac375Sdm199847 			 * does not want to block on ldap_result().
2555479ac375Sdm199847 			 * Therefore we execute ldap_result() with
2556479ac375Sdm199847 			 * a zeroed timeval.
2557479ac375Sdm199847 			 */
2558479ac375Sdm199847 			if (cookie->no_wait == B_TRUE)
2559479ac375Sdm199847 				(void) memset(&tv, 0, sizeof (tv));
2560479ac375Sdm199847 			else
2561479ac375Sdm199847 				tv = cookie->search_timeout;
25627c478bd9Sstevel@tonic-gate 			rc = ldap_result(cookie->conn->ld, cookie->msgId,
25637c478bd9Sstevel@tonic-gate 			    LDAP_MSG_ONE,
2564479ac375Sdm199847 			    &tv,
25657c478bd9Sstevel@tonic-gate 			    &cookie->resultMsg);
25667c478bd9Sstevel@tonic-gate 			if (rc == LDAP_RES_SEARCH_RESULT) {
25677c478bd9Sstevel@tonic-gate 				cookie->new_state = END_RESULT;
25687c478bd9Sstevel@tonic-gate 				/* check and process referrals info */
25697c478bd9Sstevel@tonic-gate 				if (cookie->followRef)
25707c478bd9Sstevel@tonic-gate 					proc_result_referrals(
25717c478bd9Sstevel@tonic-gate 					    cookie);
25727c478bd9Sstevel@tonic-gate 				(void) ldap_msgfree(cookie->resultMsg);
25737c478bd9Sstevel@tonic-gate 				cookie->resultMsg = NULL;
25747c478bd9Sstevel@tonic-gate 				break;
25757c478bd9Sstevel@tonic-gate 			}
25767c478bd9Sstevel@tonic-gate 			/* handle referrals if necessary */
25777c478bd9Sstevel@tonic-gate 			if (rc == LDAP_RES_SEARCH_REFERENCE) {
25787c478bd9Sstevel@tonic-gate 				if (cookie->followRef)
25797c478bd9Sstevel@tonic-gate 					proc_search_references(cookie);
25807c478bd9Sstevel@tonic-gate 				(void) ldap_msgfree(cookie->resultMsg);
25817c478bd9Sstevel@tonic-gate 				cookie->resultMsg = NULL;
25827c478bd9Sstevel@tonic-gate 				break;
25837c478bd9Sstevel@tonic-gate 			}
25847c478bd9Sstevel@tonic-gate 			if (rc != LDAP_RES_SEARCH_ENTRY) {
25857c478bd9Sstevel@tonic-gate 				switch (rc) {
25867c478bd9Sstevel@tonic-gate 				case 0:
2587479ac375Sdm199847 					if (cookie->no_wait == B_TRUE) {
2588479ac375Sdm199847 						(void) ldap_msgfree(
2589479ac375Sdm199847 						    cookie->resultMsg);
2590479ac375Sdm199847 						cookie->resultMsg = NULL;
2591479ac375Sdm199847 						return (cookie->new_state);
2592479ac375Sdm199847 					}
25937c478bd9Sstevel@tonic-gate 					rc = LDAP_TIMEOUT;
25947c478bd9Sstevel@tonic-gate 					break;
25957c478bd9Sstevel@tonic-gate 				case -1:
25967c478bd9Sstevel@tonic-gate 					rc = ldap_get_lderrno(cookie->conn->ld,
25977c478bd9Sstevel@tonic-gate 					    NULL, NULL);
25987c478bd9Sstevel@tonic-gate 					break;
25997c478bd9Sstevel@tonic-gate 				default:
26007c478bd9Sstevel@tonic-gate 					rc = ldap_result2error(cookie->conn->ld,
26017c478bd9Sstevel@tonic-gate 					    cookie->resultMsg, 1);
26027c478bd9Sstevel@tonic-gate 					break;
26037c478bd9Sstevel@tonic-gate 				}
2604e1dd0a2fSth160488 				if ((rc == LDAP_TIMEOUT ||
2605e1dd0a2fSth160488 				    rc == LDAP_SERVER_DOWN) &&
2606e1dd0a2fSth160488 				    (cookie->conn_user == NULL ||
2607e1dd0a2fSth160488 				    cookie->conn_user->conn_mt == NULL)) {
26088277a58bSchinlong 					if (rc == LDAP_TIMEOUT)
26098277a58bSchinlong 						(void) __s_api_removeServer(
26108277a58bSchinlong 						    cookie->conn->serverAddr);
26118277a58bSchinlong 					if (cookie->connectionId > -1) {
26128277a58bSchinlong 						DropConnection(
26138277a58bSchinlong 						    cookie->connectionId,
26148277a58bSchinlong 						    NS_LDAP_NEW_CONN);
26158277a58bSchinlong 						cookie->connectionId = -1;
26168277a58bSchinlong 					}
26178277a58bSchinlong 					cookie->err_from_result = 1;
26188277a58bSchinlong 				}
26197c478bd9Sstevel@tonic-gate 				(void) ldap_msgfree(cookie->resultMsg);
26207c478bd9Sstevel@tonic-gate 				cookie->resultMsg = NULL;
26217c478bd9Sstevel@tonic-gate 				if (rc == LDAP_BUSY ||
26227c478bd9Sstevel@tonic-gate 				    rc == LDAP_UNAVAILABLE ||
26238277a58bSchinlong 				    rc == LDAP_UNWILLING_TO_PERFORM) {
2624e1dd0a2fSth160488 					if (cookie->reinit_on_retriable_err) {
2625e1dd0a2fSth160488 						cookie->err_rc = rc;
2626e1dd0a2fSth160488 						cookie->err_from_result = 1;
2627e1dd0a2fSth160488 						cookie->new_state = REINIT;
2628e1dd0a2fSth160488 					} else
2629e1dd0a2fSth160488 						cookie->new_state =
2630e1dd0a2fSth160488 						    NEXT_SESSION;
2631e1dd0a2fSth160488 					break;
2632e1dd0a2fSth160488 				}
2633e1dd0a2fSth160488 				if ((rc == LDAP_CONNECT_ERROR ||
2634e1dd0a2fSth160488 				    rc == LDAP_SERVER_DOWN) &&
2635e1dd0a2fSth160488 				    cookie->reinit_on_retriable_err) {
2636e1dd0a2fSth160488 					ns_ldap_error_t *errorp = NULL;
2637e1dd0a2fSth160488 					cookie->err_rc = rc;
2638e1dd0a2fSth160488 					cookie->err_from_result = 1;
2639e1dd0a2fSth160488 					cookie->new_state = REINIT;
2640e1dd0a2fSth160488 					if (cookie->conn_user != NULL)
2641e1dd0a2fSth160488 						__s_api_conn_mt_close(
2642e1dd0a2fSth160488 						    cookie->conn_user,
2643e1dd0a2fSth160488 						    rc, &errorp);
2644e1dd0a2fSth160488 					if (errorp != NULL) {
2645e1dd0a2fSth160488 						(void) __ns_ldap_freeError(
2646e1dd0a2fSth160488 						    &cookie->errorp);
2647e1dd0a2fSth160488 						cookie->errorp = errorp;
2648e1dd0a2fSth160488 					}
26497c478bd9Sstevel@tonic-gate 					break;
26507c478bd9Sstevel@tonic-gate 				}
26517c478bd9Sstevel@tonic-gate 				cookie->err_rc = rc;
26527c478bd9Sstevel@tonic-gate 				cookie->new_state = LDAP_ERROR;
26537c478bd9Sstevel@tonic-gate 				break;
26547c478bd9Sstevel@tonic-gate 			}
26557c478bd9Sstevel@tonic-gate 			/* else LDAP_RES_SEARCH_ENTRY */
265647789246Svv149972 			/* get account management response control */
265747789246Svv149972 			if (cookie->nopasswd_acct_mgmt == 1) {
265847789246Svv149972 				rc = ldap_get_entry_controls(cookie->conn->ld,
265947789246Svv149972 				    cookie->resultMsg,
266047789246Svv149972 				    &(cookie->resultctrl));
266147789246Svv149972 				if (rc != LDAP_SUCCESS) {
266247789246Svv149972 					cookie->new_state = LDAP_ERROR;
266347789246Svv149972 					cookie->err_rc = rc;
266447789246Svv149972 					break;
266547789246Svv149972 				}
266647789246Svv149972 			}
26677c478bd9Sstevel@tonic-gate 			rc = __s_api_getEntry(cookie);
26687c478bd9Sstevel@tonic-gate 			(void) ldap_msgfree(cookie->resultMsg);
26697c478bd9Sstevel@tonic-gate 			cookie->resultMsg = NULL;
26707c478bd9Sstevel@tonic-gate 			if (rc != NS_LDAP_SUCCESS) {
26717c478bd9Sstevel@tonic-gate 				cookie->new_state = LDAP_ERROR;
26727c478bd9Sstevel@tonic-gate 				break;
26737c478bd9Sstevel@tonic-gate 			}
26747c478bd9Sstevel@tonic-gate 			cookie->new_state = PROCESS_RESULT;
26757c478bd9Sstevel@tonic-gate 			cookie->next_state = NEXT_RESULT;
26767c478bd9Sstevel@tonic-gate 			break;
26777c478bd9Sstevel@tonic-gate 		case MULTI_RESULT:
2678479ac375Sdm199847 			if (cookie->no_wait == B_TRUE)
2679479ac375Sdm199847 				(void) memset(&tv, 0, sizeof (tv));
2680479ac375Sdm199847 			else
2681479ac375Sdm199847 				tv = cookie->search_timeout;
26827c478bd9Sstevel@tonic-gate 			rc = ldap_result(cookie->conn->ld, cookie->msgId,
26837c478bd9Sstevel@tonic-gate 			    LDAP_MSG_ONE,
2684479ac375Sdm199847 			    &tv,
26857c478bd9Sstevel@tonic-gate 			    &cookie->resultMsg);
26867c478bd9Sstevel@tonic-gate 			if (rc == LDAP_RES_SEARCH_RESULT) {
26877c478bd9Sstevel@tonic-gate 				rc = ldap_result2error(cookie->conn->ld,
26887c478bd9Sstevel@tonic-gate 				    cookie->resultMsg, 0);
2689*9f2fd570SJulian Pullen 				if (rc == LDAP_ADMINLIMIT_EXCEEDED &&
2690*9f2fd570SJulian Pullen 				    cookie->listType == VLVCTRLFLAG &&
2691*9f2fd570SJulian Pullen 				    cookie->sortTypeTry == SSS_SINGLE_ATTR) {
2692*9f2fd570SJulian Pullen 					/* Try old "cn uid" server side sort */
2693*9f2fd570SJulian Pullen 					cookie->sortTypeTry = SSS_CN_UID_ATTRS;
2694*9f2fd570SJulian Pullen 					cookie->new_state = NEXT_VLV;
2695*9f2fd570SJulian Pullen 					(void) ldap_msgfree(cookie->resultMsg);
2696*9f2fd570SJulian Pullen 					cookie->resultMsg = NULL;
2697*9f2fd570SJulian Pullen 					break;
2698*9f2fd570SJulian Pullen 				}
26997c478bd9Sstevel@tonic-gate 				if (rc != LDAP_SUCCESS) {
27007c478bd9Sstevel@tonic-gate 					cookie->err_rc = rc;
27017c478bd9Sstevel@tonic-gate 					cookie->new_state = LDAP_ERROR;
27027c478bd9Sstevel@tonic-gate 					(void) ldap_msgfree(cookie->resultMsg);
2703*9f2fd570SJulian Pullen 					cookie->resultMsg = NULL;
27047c478bd9Sstevel@tonic-gate 					break;
27057c478bd9Sstevel@tonic-gate 				}
27067c478bd9Sstevel@tonic-gate 				cookie->new_state = multi_result(cookie);
27077c478bd9Sstevel@tonic-gate 				(void) ldap_msgfree(cookie->resultMsg);
27087c478bd9Sstevel@tonic-gate 				cookie->resultMsg = NULL;
27097c478bd9Sstevel@tonic-gate 				break;
27107c478bd9Sstevel@tonic-gate 			}
27117c478bd9Sstevel@tonic-gate 			/* handle referrals if necessary */
27127c478bd9Sstevel@tonic-gate 			if (rc == LDAP_RES_SEARCH_REFERENCE &&
27137c478bd9Sstevel@tonic-gate 			    cookie->followRef) {
27147c478bd9Sstevel@tonic-gate 				proc_search_references(cookie);
27157c478bd9Sstevel@tonic-gate 				(void) ldap_msgfree(cookie->resultMsg);
27167c478bd9Sstevel@tonic-gate 				cookie->resultMsg = NULL;
27177c478bd9Sstevel@tonic-gate 				break;
27187c478bd9Sstevel@tonic-gate 			}
27197c478bd9Sstevel@tonic-gate 			if (rc != LDAP_RES_SEARCH_ENTRY) {
27207c478bd9Sstevel@tonic-gate 				switch (rc) {
27217c478bd9Sstevel@tonic-gate 				case 0:
2722479ac375Sdm199847 					if (cookie->no_wait == B_TRUE) {
2723479ac375Sdm199847 						(void) ldap_msgfree(
2724479ac375Sdm199847 						    cookie->resultMsg);
2725479ac375Sdm199847 						cookie->resultMsg = NULL;
2726479ac375Sdm199847 						return (cookie->new_state);
2727479ac375Sdm199847 					}
27287c478bd9Sstevel@tonic-gate 					rc = LDAP_TIMEOUT;
27297c478bd9Sstevel@tonic-gate 					break;
27307c478bd9Sstevel@tonic-gate 				case -1:
27317c478bd9Sstevel@tonic-gate 					rc = ldap_get_lderrno(cookie->conn->ld,
27327c478bd9Sstevel@tonic-gate 					    NULL, NULL);
27337c478bd9Sstevel@tonic-gate 					break;
27347c478bd9Sstevel@tonic-gate 				default:
27357c478bd9Sstevel@tonic-gate 					rc = ldap_result2error(cookie->conn->ld,
27367c478bd9Sstevel@tonic-gate 					    cookie->resultMsg, 1);
27377c478bd9Sstevel@tonic-gate 					break;
27387c478bd9Sstevel@tonic-gate 				}
2739e1dd0a2fSth160488 				if ((rc == LDAP_TIMEOUT ||
2740e1dd0a2fSth160488 				    rc == LDAP_SERVER_DOWN) &&
2741e1dd0a2fSth160488 				    (cookie->conn_user == NULL ||
2742e1dd0a2fSth160488 				    cookie->conn_user->conn_mt == NULL)) {
27438277a58bSchinlong 					if (rc == LDAP_TIMEOUT)
27448277a58bSchinlong 						(void) __s_api_removeServer(
27458277a58bSchinlong 						    cookie->conn->serverAddr);
27468277a58bSchinlong 					if (cookie->connectionId > -1) {
27478277a58bSchinlong 						DropConnection(
27488277a58bSchinlong 						    cookie->connectionId,
27498277a58bSchinlong 						    NS_LDAP_NEW_CONN);
27508277a58bSchinlong 						cookie->connectionId = -1;
27518277a58bSchinlong 					}
27528277a58bSchinlong 					cookie->err_from_result = 1;
27538277a58bSchinlong 				}
27547c478bd9Sstevel@tonic-gate 				(void) ldap_msgfree(cookie->resultMsg);
27557c478bd9Sstevel@tonic-gate 				cookie->resultMsg = NULL;
27567c478bd9Sstevel@tonic-gate 				if (rc == LDAP_BUSY ||
27577c478bd9Sstevel@tonic-gate 				    rc == LDAP_UNAVAILABLE ||
27588277a58bSchinlong 				    rc == LDAP_UNWILLING_TO_PERFORM) {
2759e1dd0a2fSth160488 					if (cookie->reinit_on_retriable_err) {
2760e1dd0a2fSth160488 						cookie->err_rc = rc;
2761e1dd0a2fSth160488 						cookie->err_from_result = 1;
2762e1dd0a2fSth160488 						cookie->new_state = REINIT;
2763e1dd0a2fSth160488 					} else
2764e1dd0a2fSth160488 						cookie->new_state =
2765e1dd0a2fSth160488 						    NEXT_SESSION;
2766e1dd0a2fSth160488 					break;
2767e1dd0a2fSth160488 				}
2768*9f2fd570SJulian Pullen 
2769e1dd0a2fSth160488 				if ((rc == LDAP_CONNECT_ERROR ||
2770e1dd0a2fSth160488 				    rc == LDAP_SERVER_DOWN) &&
2771e1dd0a2fSth160488 				    cookie->reinit_on_retriable_err) {
2772e1dd0a2fSth160488 					ns_ldap_error_t *errorp = NULL;
2773e1dd0a2fSth160488 					cookie->err_rc = rc;
2774e1dd0a2fSth160488 					cookie->err_from_result = 1;
2775e1dd0a2fSth160488 					cookie->new_state = REINIT;
2776e1dd0a2fSth160488 					if (cookie->conn_user != NULL)
2777e1dd0a2fSth160488 						__s_api_conn_mt_close(
2778e1dd0a2fSth160488 						    cookie->conn_user,
2779e1dd0a2fSth160488 						    rc, &errorp);
2780e1dd0a2fSth160488 					if (errorp != NULL) {
2781e1dd0a2fSth160488 						(void) __ns_ldap_freeError(
2782e1dd0a2fSth160488 						    &cookie->errorp);
2783e1dd0a2fSth160488 						cookie->errorp = errorp;
2784e1dd0a2fSth160488 					}
27857c478bd9Sstevel@tonic-gate 					break;
27867c478bd9Sstevel@tonic-gate 				}
27877c478bd9Sstevel@tonic-gate 				cookie->err_rc = rc;
27887c478bd9Sstevel@tonic-gate 				cookie->new_state = LDAP_ERROR;
27897c478bd9Sstevel@tonic-gate 				break;
27907c478bd9Sstevel@tonic-gate 			}
27917c478bd9Sstevel@tonic-gate 			/* else LDAP_RES_SEARCH_ENTRY */
2792*9f2fd570SJulian Pullen 			cookie->entryCount++;
27937c478bd9Sstevel@tonic-gate 			rc = __s_api_getEntry(cookie);
27947c478bd9Sstevel@tonic-gate 			(void) ldap_msgfree(cookie->resultMsg);
27957c478bd9Sstevel@tonic-gate 			cookie->resultMsg = NULL;
27967c478bd9Sstevel@tonic-gate 			if (rc != NS_LDAP_SUCCESS) {
27977c478bd9Sstevel@tonic-gate 				cookie->new_state = LDAP_ERROR;
27987c478bd9Sstevel@tonic-gate 				break;
27997c478bd9Sstevel@tonic-gate 			}
2800*9f2fd570SJulian Pullen 			/*
2801*9f2fd570SJulian Pullen 			 * If VLV search was successfull save the server
2802*9f2fd570SJulian Pullen 			 * side sort type tried.
2803*9f2fd570SJulian Pullen 			 */
2804*9f2fd570SJulian Pullen 			if (cookie->listType == VLVCTRLFLAG)
2805*9f2fd570SJulian Pullen 				update_srvsidesort_type(cookie->service,
2806*9f2fd570SJulian Pullen 				    cookie->sortTypeTry);
2807*9f2fd570SJulian Pullen 
28087c478bd9Sstevel@tonic-gate 			cookie->new_state = PROCESS_RESULT;
28097c478bd9Sstevel@tonic-gate 			cookie->next_state = MULTI_RESULT;
28107c478bd9Sstevel@tonic-gate 			break;
28117c478bd9Sstevel@tonic-gate 		case PROCESS_RESULT:
28127c478bd9Sstevel@tonic-gate 			/* NOTE THIS STATE MAY BE PROCESSED BY CALLER */
28137c478bd9Sstevel@tonic-gate 			if (cookie->use_usercb && cookie->callback) {
28147c478bd9Sstevel@tonic-gate 				rc = 0;
28157c478bd9Sstevel@tonic-gate 				for (nextEntry = cookie->result->entry;
28167c478bd9Sstevel@tonic-gate 				    nextEntry != NULL;
28177c478bd9Sstevel@tonic-gate 				    nextEntry = nextEntry->next) {
28187c478bd9Sstevel@tonic-gate 					rc = (*cookie->callback)(nextEntry,
28197c478bd9Sstevel@tonic-gate 					    cookie->userdata);
28207c478bd9Sstevel@tonic-gate 
28217c478bd9Sstevel@tonic-gate 					if (rc == NS_LDAP_CB_DONE) {
28227c478bd9Sstevel@tonic-gate 					/* cb doesn't want any more data */
28237c478bd9Sstevel@tonic-gate 						rc = NS_LDAP_PARTIAL;
28247c478bd9Sstevel@tonic-gate 						cookie->err_rc = rc;
28257c478bd9Sstevel@tonic-gate 						break;
28267c478bd9Sstevel@tonic-gate 					} else if (rc != NS_LDAP_CB_NEXT) {
28277c478bd9Sstevel@tonic-gate 					/* invalid return code */
28287c478bd9Sstevel@tonic-gate 						rc = NS_LDAP_OP_FAILED;
28297c478bd9Sstevel@tonic-gate 						cookie->err_rc = rc;
28307c478bd9Sstevel@tonic-gate 						break;
28317c478bd9Sstevel@tonic-gate 					}
28327c478bd9Sstevel@tonic-gate 				}
28337c478bd9Sstevel@tonic-gate 				(void) __ns_ldap_freeResult(&cookie->result);
28347c478bd9Sstevel@tonic-gate 				cookie->result = NULL;
28357c478bd9Sstevel@tonic-gate 			}
28367c478bd9Sstevel@tonic-gate 			if (rc != 0) {
28377c478bd9Sstevel@tonic-gate 				cookie->new_state = EXIT;
28387c478bd9Sstevel@tonic-gate 				break;
28397c478bd9Sstevel@tonic-gate 			}
28407c478bd9Sstevel@tonic-gate 			/* NOTE PREVIOUS STATE SPECIFIES NEXT STATE */
28417c478bd9Sstevel@tonic-gate 			cookie->new_state = cookie->next_state;
28427c478bd9Sstevel@tonic-gate 			break;
28437c478bd9Sstevel@tonic-gate 		case END_PROCESS_RESULT:
28447c478bd9Sstevel@tonic-gate 			cookie->new_state = cookie->next_state;
28457c478bd9Sstevel@tonic-gate 			break;
28467c478bd9Sstevel@tonic-gate 		case END_RESULT:
28477c478bd9Sstevel@tonic-gate 			/*
28487c478bd9Sstevel@tonic-gate 			 * XXX DO WE NEED THIS CASE?
28497c478bd9Sstevel@tonic-gate 			 * if (search is complete) {
28507c478bd9Sstevel@tonic-gate 			 * 	cookie->new_state = EXIT;
28517c478bd9Sstevel@tonic-gate 			 * } else
28527c478bd9Sstevel@tonic-gate 			 */
28537c478bd9Sstevel@tonic-gate 				/*
28547c478bd9Sstevel@tonic-gate 				 * entering referral mode if necessary
28557c478bd9Sstevel@tonic-gate 				 */
28567c478bd9Sstevel@tonic-gate 				if (cookie->followRef && cookie->reflist)
28577c478bd9Sstevel@tonic-gate 					cookie->new_state =
28587c478bd9Sstevel@tonic-gate 					    NEXT_REFERRAL;
28597c478bd9Sstevel@tonic-gate 				else
28607c478bd9Sstevel@tonic-gate 					cookie->new_state =
28617c478bd9Sstevel@tonic-gate 					    NEXT_SEARCH_DESCRIPTOR;
28627c478bd9Sstevel@tonic-gate 			break;
28637c478bd9Sstevel@tonic-gate 		case NEXT_REFERRAL:
28647c478bd9Sstevel@tonic-gate 			/* get next referral info */
28657c478bd9Sstevel@tonic-gate 			if (cookie->refpos == NULL)
28667c478bd9Sstevel@tonic-gate 				cookie->refpos =
28677c478bd9Sstevel@tonic-gate 				    cookie->reflist;
28687c478bd9Sstevel@tonic-gate 			else
28697c478bd9Sstevel@tonic-gate 				cookie->refpos =
28707c478bd9Sstevel@tonic-gate 				    cookie->refpos->next;
28717c478bd9Sstevel@tonic-gate 			/* check see if done with all referrals */
28727c478bd9Sstevel@tonic-gate 			if (cookie->refpos != NULL)
28737c478bd9Sstevel@tonic-gate 				cookie->new_state =
28747c478bd9Sstevel@tonic-gate 				    GET_REFERRAL_SESSION;
28757c478bd9Sstevel@tonic-gate 			else {
28767c478bd9Sstevel@tonic-gate 				__s_api_deleteRefInfo(cookie->reflist);
28777c478bd9Sstevel@tonic-gate 				cookie->reflist = NULL;
28787c478bd9Sstevel@tonic-gate 				cookie->new_state =
28797c478bd9Sstevel@tonic-gate 				    NEXT_SEARCH_DESCRIPTOR;
2880e1dd0a2fSth160488 				if (cookie->conn_user != NULL)
2881e1dd0a2fSth160488 					cookie->conn_user->referral = B_FALSE;
28827c478bd9Sstevel@tonic-gate 			}
28837c478bd9Sstevel@tonic-gate 			break;
28847c478bd9Sstevel@tonic-gate 		case GET_REFERRAL_SESSION:
28857c478bd9Sstevel@tonic-gate 			if (get_referral_session(cookie) < 0)
28867c478bd9Sstevel@tonic-gate 				cookie->new_state = EXIT;
28877c478bd9Sstevel@tonic-gate 			else {
28887c478bd9Sstevel@tonic-gate 				cookie->new_state = NEXT_SEARCH;
28897c478bd9Sstevel@tonic-gate 			}
28907c478bd9Sstevel@tonic-gate 			break;
28917c478bd9Sstevel@tonic-gate 		case LDAP_ERROR:
2892e1dd0a2fSth160488 			rc_save = cookie->err_rc;
28938277a58bSchinlong 			if (cookie->err_from_result) {
28948277a58bSchinlong 				if (cookie->err_rc == LDAP_SERVER_DOWN) {
28958277a58bSchinlong 					(void) sprintf(errstr,
28968277a58bSchinlong 					    gettext("LDAP ERROR (%d): "
28978277a58bSchinlong 					    "Error occurred during"
28988277a58bSchinlong 					    " receiving results. "
289910f9768dSmj162486 					    "Connection to server lost."),
29008277a58bSchinlong 					    cookie->err_rc);
29018277a58bSchinlong 				} else if (cookie->err_rc == LDAP_TIMEOUT) {
29028277a58bSchinlong 					(void) sprintf(errstr,
29038277a58bSchinlong 					    gettext("LDAP ERROR (%d): "
29048277a58bSchinlong 					    "Error occurred during"
29058277a58bSchinlong 					    " receiving results. %s"
29068277a58bSchinlong 					    "."), cookie->err_rc,
29078277a58bSchinlong 					    ldap_err2string(
29088277a58bSchinlong 					    cookie->err_rc));
29098277a58bSchinlong 				}
29108277a58bSchinlong 			} else
29117c478bd9Sstevel@tonic-gate 				(void) sprintf(errstr,
29127c478bd9Sstevel@tonic-gate 				    gettext("LDAP ERROR (%d): %s."),
29137c478bd9Sstevel@tonic-gate 				    cookie->err_rc,
29147c478bd9Sstevel@tonic-gate 				    ldap_err2string(cookie->err_rc));
29157c478bd9Sstevel@tonic-gate 			err = strdup(errstr);
29168277a58bSchinlong 			if (cookie->err_from_result) {
291710f9768dSmj162486 				if (cookie->err_rc == LDAP_SERVER_DOWN) {
291810f9768dSmj162486 					MKERROR(LOG_INFO, *errorp,
291910f9768dSmj162486 					    cookie->err_rc, err, NULL);
292010f9768dSmj162486 				} else {
292110f9768dSmj162486 					MKERROR(LOG_WARNING, *errorp,
292210f9768dSmj162486 					    cookie->err_rc, err, NULL);
292310f9768dSmj162486 				}
29248277a58bSchinlong 			} else {
29258277a58bSchinlong 				MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL,
29268277a58bSchinlong 				    err, NULL);
29278277a58bSchinlong 			}
29287c478bd9Sstevel@tonic-gate 			cookie->err_rc = NS_LDAP_INTERNAL;
29297c478bd9Sstevel@tonic-gate 			cookie->errorp = *errorp;
2930e1dd0a2fSth160488 			if (cookie->conn_user != NULL)  {
2931e1dd0a2fSth160488 				if (rc_save == LDAP_SERVER_DOWN ||
2932e1dd0a2fSth160488 				    rc_save == LDAP_CONNECT_ERROR) {
2933e1dd0a2fSth160488 					/*
2934e1dd0a2fSth160488 					 * MT connection is not usable,
2935e1dd0a2fSth160488 					 * close it.
2936e1dd0a2fSth160488 					 */
2937e1dd0a2fSth160488 					__s_api_conn_mt_close(cookie->conn_user,
2938e1dd0a2fSth160488 					    rc_save, &cookie->errorp);
2939e1dd0a2fSth160488 					return (ERROR);
2940e1dd0a2fSth160488 				}
2941e1dd0a2fSth160488 			}
29427c478bd9Sstevel@tonic-gate 			return (ERROR);
29437c478bd9Sstevel@tonic-gate 		default:
29447c478bd9Sstevel@tonic-gate 		case ERROR:
29457c478bd9Sstevel@tonic-gate 			(void) sprintf(errstr,
29467c478bd9Sstevel@tonic-gate 			    gettext("Internal State machine exit (%d).\n"),
29477c478bd9Sstevel@tonic-gate 			    cookie->state);
29487c478bd9Sstevel@tonic-gate 			err = strdup(errstr);
29497c478bd9Sstevel@tonic-gate 			MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
29507c478bd9Sstevel@tonic-gate 			    NULL);
29517c478bd9Sstevel@tonic-gate 			cookie->err_rc = NS_LDAP_INTERNAL;
29527c478bd9Sstevel@tonic-gate 			cookie->errorp = *errorp;
29537c478bd9Sstevel@tonic-gate 			return (ERROR);
29547c478bd9Sstevel@tonic-gate 		}
29557c478bd9Sstevel@tonic-gate 
2956e1dd0a2fSth160488 		if (cookie->conn_user != NULL &&
2957e1dd0a2fSth160488 		    cookie->conn_user->bad_mt_conn ==  B_TRUE) {
2958e1dd0a2fSth160488 			__s_api_conn_mt_close(cookie->conn_user, 0, NULL);
2959e1dd0a2fSth160488 			cookie->err_rc = cookie->conn_user->ns_rc;
2960e1dd0a2fSth160488 			cookie->errorp = cookie->conn_user->ns_error;
2961e1dd0a2fSth160488 			cookie->conn_user->ns_error = NULL;
2962e1dd0a2fSth160488 			return (ERROR);
2963e1dd0a2fSth160488 		}
2964e1dd0a2fSth160488 
29657c478bd9Sstevel@tonic-gate 		if (cycle == ONE_STEP) {
29667c478bd9Sstevel@tonic-gate 			return (cookie->new_state);
29677c478bd9Sstevel@tonic-gate 		}
29687c478bd9Sstevel@tonic-gate 		cookie->state = cookie->new_state;
29697c478bd9Sstevel@tonic-gate 	}
29707c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
29717c478bd9Sstevel@tonic-gate #if 0
29727c478bd9Sstevel@tonic-gate 	(void) sprintf(errstr,
29737c478bd9Sstevel@tonic-gate 	    gettext("Unexpected State machine error.\n"));
29747c478bd9Sstevel@tonic-gate 	err = strdup(errstr);
29757c478bd9Sstevel@tonic-gate 	MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err, NULL);
29767c478bd9Sstevel@tonic-gate 	cookie->err_rc = NS_LDAP_INTERNAL;
29777c478bd9Sstevel@tonic-gate 	cookie->errorp = *errorp;
29787c478bd9Sstevel@tonic-gate 	return (ERROR);
29797c478bd9Sstevel@tonic-gate #endif
29807c478bd9Sstevel@tonic-gate }
29817c478bd9Sstevel@tonic-gate 
29827c478bd9Sstevel@tonic-gate /*
2983b57459abSJulian Pullen  * For a lookup of shadow data, if shadow update is enabled,
2984b57459abSJulian Pullen  * check the calling process' privilege to ensure it's
2985b57459abSJulian Pullen  * allowed to perform such operation.
2986b57459abSJulian Pullen  */
2987b57459abSJulian Pullen static int
check_shadow(ns_ldap_cookie_t * cookie,const char * service)2988b57459abSJulian Pullen check_shadow(ns_ldap_cookie_t *cookie, const char *service)
2989b57459abSJulian Pullen {
2990b57459abSJulian Pullen 	char errstr[MAXERROR];
2991b57459abSJulian Pullen 	char *err;
2992b57459abSJulian Pullen 	boolean_t priv;
2993b57459abSJulian Pullen 	/* caller */
2994b57459abSJulian Pullen 	priv_set_t *ps;
2995b57459abSJulian Pullen 	/* zone */
2996b57459abSJulian Pullen 	priv_set_t *zs;
2997b57459abSJulian Pullen 
2998b57459abSJulian Pullen 	/*
2999b57459abSJulian Pullen 	 * If service is "shadow", we may need
3000b57459abSJulian Pullen 	 * to use privilege credentials.
3001b57459abSJulian Pullen 	 */
3002b57459abSJulian Pullen 	if ((strcmp(service, "shadow") == 0) &&
3003b57459abSJulian Pullen 	    __ns_ldap_is_shadow_update_enabled()) {
3004b57459abSJulian Pullen 		/*
3005b57459abSJulian Pullen 		 * Since we release admin credentials after
3006b57459abSJulian Pullen 		 * connection is closed and we do not cache
3007b57459abSJulian Pullen 		 * them, we allow any root or all zone
3008b57459abSJulian Pullen 		 * privilege process to read shadow data.
3009b57459abSJulian Pullen 		 */
3010b57459abSJulian Pullen 		priv = (geteuid() == 0);
3011b57459abSJulian Pullen 		if (!priv) {
3012b57459abSJulian Pullen 			/* caller */
3013b57459abSJulian Pullen 			ps = priv_allocset();
3014b57459abSJulian Pullen 
3015b57459abSJulian Pullen 			(void) getppriv(PRIV_EFFECTIVE, ps);
3016b57459abSJulian Pullen 			zs = priv_str_to_set("zone", ",", NULL);
3017b57459abSJulian Pullen 			priv = priv_isequalset(ps, zs);
3018b57459abSJulian Pullen 			priv_freeset(ps);
3019b57459abSJulian Pullen 			priv_freeset(zs);
3020b57459abSJulian Pullen 		}
3021b57459abSJulian Pullen 		if (!priv) {
3022b57459abSJulian Pullen 			(void) sprintf(errstr,
3023b57459abSJulian Pullen 			    gettext("Permission denied"));
3024b57459abSJulian Pullen 			err = strdup(errstr);
3025b57459abSJulian Pullen 			if (err == NULL)
3026b57459abSJulian Pullen 				return (NS_LDAP_MEMORY);
3027b57459abSJulian Pullen 			MKERROR(LOG_INFO, cookie->errorp, NS_LDAP_INTERNAL, err,
3028b57459abSJulian Pullen 			    NULL);
3029b57459abSJulian Pullen 			return (NS_LDAP_INTERNAL);
3030b57459abSJulian Pullen 		}
3031b57459abSJulian Pullen 		cookie->i_flags |= NS_LDAP_READ_SHADOW;
3032b57459abSJulian Pullen 		/*
3033b57459abSJulian Pullen 		 * We do not want to reuse connection (hence
3034b57459abSJulian Pullen 		 * keep it open) with admin credentials.
3035b57459abSJulian Pullen 		 * If NS_LDAP_KEEP_CONN is set, reject the
3036b57459abSJulian Pullen 		 * request.
3037b57459abSJulian Pullen 		 */
3038b57459abSJulian Pullen 		if (cookie->i_flags & NS_LDAP_KEEP_CONN)
3039b57459abSJulian Pullen 			return (NS_LDAP_INVALID_PARAM);
3040b57459abSJulian Pullen 		cookie->i_flags |= NS_LDAP_NEW_CONN;
3041b57459abSJulian Pullen 	}
3042b57459abSJulian Pullen 
3043b57459abSJulian Pullen 	return (NS_LDAP_SUCCESS);
3044b57459abSJulian Pullen }
3045b57459abSJulian Pullen 
3046b57459abSJulian Pullen /*
3047479ac375Sdm199847  * internal function for __ns_ldap_list
30487c478bd9Sstevel@tonic-gate  */
3049479ac375Sdm199847 static int
ldap_list(ns_ldap_list_batch_t * batch,const char * service,const char * filter,const char * sortattr,int (* init_filter_cb)(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata),const char * const * attribute,const ns_cred_t * auth,const int flags,ns_ldap_result_t ** rResult,ns_ldap_error_t ** errorp,int * rcp,int (* callback)(const ns_ldap_entry_t * entry,const void * userdata),const void * userdata,ns_conn_user_t * conn_user)3050479ac375Sdm199847 ldap_list(
3051479ac375Sdm199847 	ns_ldap_list_batch_t *batch,
30527c478bd9Sstevel@tonic-gate 	const char *service,
30537c478bd9Sstevel@tonic-gate 	const char *filter,
3054*9f2fd570SJulian Pullen 	const char *sortattr,
30557c478bd9Sstevel@tonic-gate 	int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
30567c478bd9Sstevel@tonic-gate 	char **realfilter, const void *userdata),
30577c478bd9Sstevel@tonic-gate 	const char * const *attribute,
30587c478bd9Sstevel@tonic-gate 	const ns_cred_t *auth,
30597c478bd9Sstevel@tonic-gate 	const int flags,
30607c478bd9Sstevel@tonic-gate 	ns_ldap_result_t **rResult, /* return result entries */
30617c478bd9Sstevel@tonic-gate 	ns_ldap_error_t **errorp,
3062479ac375Sdm199847 	int *rcp,
30637c478bd9Sstevel@tonic-gate 	int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
3064e1dd0a2fSth160488 	const void *userdata, ns_conn_user_t *conn_user)
30657c478bd9Sstevel@tonic-gate {
30667c478bd9Sstevel@tonic-gate 	ns_ldap_cookie_t	*cookie;
30677c478bd9Sstevel@tonic-gate 	ns_ldap_search_desc_t	**sdlist = NULL;
30687c478bd9Sstevel@tonic-gate 	ns_ldap_search_desc_t	*dptr;
30697c478bd9Sstevel@tonic-gate 	ns_ldap_error_t		*error = NULL;
30707c478bd9Sstevel@tonic-gate 	char			**dns = NULL;
30717c478bd9Sstevel@tonic-gate 	int			scope;
30727c478bd9Sstevel@tonic-gate 	int			rc;
30738277a58bSchinlong 	int			from_result;
30747c478bd9Sstevel@tonic-gate 
30757c478bd9Sstevel@tonic-gate 	*errorp = NULL;
3076479ac375Sdm199847 	*rResult = NULL;
3077479ac375Sdm199847 	*rcp = NS_LDAP_SUCCESS;
30787c478bd9Sstevel@tonic-gate 
3079b57459abSJulian Pullen 	/*
3080b57459abSJulian Pullen 	 * Sanity check - NS_LDAP_READ_SHADOW is for our
3081b57459abSJulian Pullen 	 * own internal use.
3082b57459abSJulian Pullen 	 */
3083b57459abSJulian Pullen 	if (flags & NS_LDAP_READ_SHADOW)
3084b57459abSJulian Pullen 		return (NS_LDAP_INVALID_PARAM);
3085b57459abSJulian Pullen 
30867c478bd9Sstevel@tonic-gate 	/* Initialize State machine cookie */
30877c478bd9Sstevel@tonic-gate 	cookie = init_search_state_machine();
30887c478bd9Sstevel@tonic-gate 	if (cookie == NULL) {
3089479ac375Sdm199847 		*rcp = NS_LDAP_MEMORY;
30907c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
30917c478bd9Sstevel@tonic-gate 	}
3092e1dd0a2fSth160488 	cookie->conn_user = conn_user;
30937c478bd9Sstevel@tonic-gate 
30947c478bd9Sstevel@tonic-gate 	/* see if need to follow referrals */
30957c478bd9Sstevel@tonic-gate 	rc = __s_api_toFollowReferrals(flags,
30967c478bd9Sstevel@tonic-gate 	    &cookie->followRef, errorp);
30977c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
30987c478bd9Sstevel@tonic-gate 		delete_search_cookie(cookie);
3099479ac375Sdm199847 		*rcp = rc;
31007c478bd9Sstevel@tonic-gate 		return (rc);
31017c478bd9Sstevel@tonic-gate 	}
31027c478bd9Sstevel@tonic-gate 
31037c478bd9Sstevel@tonic-gate 	/* get the service descriptor - or create a default one */
31047c478bd9Sstevel@tonic-gate 	rc = __s_api_get_SSD_from_SSDtoUse_service(service,
3105e84b06c3SMichen Chang 	    &sdlist, &error);
31067c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
31077c478bd9Sstevel@tonic-gate 		delete_search_cookie(cookie);
31087c478bd9Sstevel@tonic-gate 		*errorp = error;
3109479ac375Sdm199847 		*rcp = rc;
31107c478bd9Sstevel@tonic-gate 		return (rc);
31117c478bd9Sstevel@tonic-gate 	}
31127c478bd9Sstevel@tonic-gate 
31137c478bd9Sstevel@tonic-gate 	if (sdlist == NULL) {
31147c478bd9Sstevel@tonic-gate 		/* Create default service Desc */
31157c478bd9Sstevel@tonic-gate 		sdlist = (ns_ldap_search_desc_t **)calloc(2,
31167c478bd9Sstevel@tonic-gate 		    sizeof (ns_ldap_search_desc_t *));
31177c478bd9Sstevel@tonic-gate 		if (sdlist == NULL) {
31187c478bd9Sstevel@tonic-gate 			delete_search_cookie(cookie);
31197c478bd9Sstevel@tonic-gate 			cookie = NULL;
3120479ac375Sdm199847 			*rcp = NS_LDAP_MEMORY;
31217c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
31227c478bd9Sstevel@tonic-gate 		}
31237c478bd9Sstevel@tonic-gate 		dptr = (ns_ldap_search_desc_t *)
31247c478bd9Sstevel@tonic-gate 		    calloc(1, sizeof (ns_ldap_search_desc_t));
31257c478bd9Sstevel@tonic-gate 		if (dptr == NULL) {
31267c478bd9Sstevel@tonic-gate 			free(sdlist);
31277c478bd9Sstevel@tonic-gate 			delete_search_cookie(cookie);
31287c478bd9Sstevel@tonic-gate 			cookie = NULL;
3129479ac375Sdm199847 			*rcp = NS_LDAP_MEMORY;
31307c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
31317c478bd9Sstevel@tonic-gate 		}
31327c478bd9Sstevel@tonic-gate 		sdlist[0] = dptr;
31337c478bd9Sstevel@tonic-gate 
31347c478bd9Sstevel@tonic-gate 		/* default base */
31357c478bd9Sstevel@tonic-gate 		rc = __s_api_getDNs(&dns, service, &cookie->errorp);
31367c478bd9Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
31377c478bd9Sstevel@tonic-gate 			if (dns) {
31387c478bd9Sstevel@tonic-gate 				__s_api_free2dArray(dns);
31397c478bd9Sstevel@tonic-gate 				dns = NULL;
31407c478bd9Sstevel@tonic-gate 			}
31417c478bd9Sstevel@tonic-gate 			*errorp = cookie->errorp;
31427c478bd9Sstevel@tonic-gate 			cookie->errorp = NULL;
31437c478bd9Sstevel@tonic-gate 			delete_search_cookie(cookie);
31447c478bd9Sstevel@tonic-gate 			cookie = NULL;
3145479ac375Sdm199847 			*rcp = rc;
31467c478bd9Sstevel@tonic-gate 			return (rc);
31477c478bd9Sstevel@tonic-gate 		}
31487c478bd9Sstevel@tonic-gate 		dptr->basedn = strdup(dns[0]);
31497c478bd9Sstevel@tonic-gate 		__s_api_free2dArray(dns);
31507c478bd9Sstevel@tonic-gate 		dns = NULL;
31517c478bd9Sstevel@tonic-gate 
31527c478bd9Sstevel@tonic-gate 		/* default scope */
31537c478bd9Sstevel@tonic-gate 		scope = 0;
31547c478bd9Sstevel@tonic-gate 		rc = __s_api_getSearchScope(&scope, &cookie->errorp);
31557c478bd9Sstevel@tonic-gate 		dptr->scope = scope;
31567c478bd9Sstevel@tonic-gate 	}
31577c478bd9Sstevel@tonic-gate 
31587c478bd9Sstevel@tonic-gate 	cookie->sdlist = sdlist;
31597c478bd9Sstevel@tonic-gate 
31607c478bd9Sstevel@tonic-gate 	/*
31617c478bd9Sstevel@tonic-gate 	 * use VLV/PAGE control only if NS_LDAP_PAGE_CTRL is set
31627c478bd9Sstevel@tonic-gate 	 */
31637c478bd9Sstevel@tonic-gate 	if (flags & NS_LDAP_PAGE_CTRL)
31647c478bd9Sstevel@tonic-gate 		cookie->use_paging = TRUE;
31657c478bd9Sstevel@tonic-gate 	else
31667c478bd9Sstevel@tonic-gate 		cookie->use_paging = FALSE;
31677c478bd9Sstevel@tonic-gate 
31687c478bd9Sstevel@tonic-gate 	/* Set up other arguments */
31697c478bd9Sstevel@tonic-gate 	cookie->userdata = userdata;
31707c478bd9Sstevel@tonic-gate 	if (init_filter_cb != NULL) {
31717c478bd9Sstevel@tonic-gate 		cookie->init_filter_cb = init_filter_cb;
31727c478bd9Sstevel@tonic-gate 		cookie->use_filtercb = 1;
31737c478bd9Sstevel@tonic-gate 	}
31747c478bd9Sstevel@tonic-gate 	if (callback != NULL) {
31757c478bd9Sstevel@tonic-gate 		cookie->callback = callback;
31767c478bd9Sstevel@tonic-gate 		cookie->use_usercb = 1;
31777c478bd9Sstevel@tonic-gate 	}
3178b57459abSJulian Pullen 
3179b57459abSJulian Pullen 	/* check_shadow() may add extra value to cookie->i_flags */
3180b57459abSJulian Pullen 	cookie->i_flags = flags;
31817c478bd9Sstevel@tonic-gate 	if (service) {
31827c478bd9Sstevel@tonic-gate 		cookie->service = strdup(service);
31837c478bd9Sstevel@tonic-gate 		if (cookie->service == NULL) {
31847c478bd9Sstevel@tonic-gate 			delete_search_cookie(cookie);
31857c478bd9Sstevel@tonic-gate 			cookie = NULL;
3186479ac375Sdm199847 			*rcp = NS_LDAP_MEMORY;
31877c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
31887c478bd9Sstevel@tonic-gate 		}
3189b57459abSJulian Pullen 
3190b57459abSJulian Pullen 		/*
3191b57459abSJulian Pullen 		 * If given, use the credential given by the caller, and
3192b57459abSJulian Pullen 		 * skip the credential check required for shadow update.
3193b57459abSJulian Pullen 		 */
3194b57459abSJulian Pullen 		if (auth == NULL) {
3195b57459abSJulian Pullen 			rc = check_shadow(cookie, service);
3196b57459abSJulian Pullen 			if (rc != NS_LDAP_SUCCESS) {
3197b57459abSJulian Pullen 				*errorp = cookie->errorp;
3198b57459abSJulian Pullen 				cookie->errorp = NULL;
3199b57459abSJulian Pullen 				delete_search_cookie(cookie);
3200b57459abSJulian Pullen 				cookie = NULL;
3201b57459abSJulian Pullen 				*rcp = rc;
3202b57459abSJulian Pullen 				return (rc);
3203b57459abSJulian Pullen 			}
3204b57459abSJulian Pullen 		}
32057c478bd9Sstevel@tonic-gate 	}
32067c478bd9Sstevel@tonic-gate 
32077c478bd9Sstevel@tonic-gate 	cookie->i_filter = strdup(filter);
32087c478bd9Sstevel@tonic-gate 	cookie->i_attr = attribute;
32097c478bd9Sstevel@tonic-gate 	cookie->i_auth = auth;
3210*9f2fd570SJulian Pullen 	cookie->i_sortattr = sortattr;
32117c478bd9Sstevel@tonic-gate 
3212479ac375Sdm199847 	if (batch != NULL) {
3213479ac375Sdm199847 		cookie->batch = batch;
3214e1dd0a2fSth160488 		cookie->reinit_on_retriable_err = B_TRUE;
3215479ac375Sdm199847 		cookie->no_wait = B_TRUE;
3216479ac375Sdm199847 		(void) search_state_machine(cookie, INIT, 0);
3217479ac375Sdm199847 		cookie->no_wait = B_FALSE;
3218479ac375Sdm199847 		rc = cookie->err_rc;
3219479ac375Sdm199847 
3220479ac375Sdm199847 		if (rc == NS_LDAP_SUCCESS) {
3221479ac375Sdm199847 			/*
3222479ac375Sdm199847 			 * Here rc == NS_LDAP_SUCCESS means that the state
3223479ac375Sdm199847 			 * machine init'ed successfully. The actual status
3224479ac375Sdm199847 			 * of the search will be determined by
3225479ac375Sdm199847 			 * __ns_ldap_list_batch_end(). Add the cookie to our
3226479ac375Sdm199847 			 * batch.
3227479ac375Sdm199847 			 */
3228479ac375Sdm199847 			cookie->caller_result = rResult;
3229479ac375Sdm199847 			cookie->caller_errorp = errorp;
3230479ac375Sdm199847 			cookie->caller_rc = rcp;
3231479ac375Sdm199847 			cookie->next_cookie_in_batch = batch->cookie_list;
3232479ac375Sdm199847 			batch->cookie_list = cookie;
3233479ac375Sdm199847 			batch->nactive++;
3234479ac375Sdm199847 			return (rc);
3235479ac375Sdm199847 		}
3236479ac375Sdm199847 		/*
3237479ac375Sdm199847 		 * If state machine init failed then copy error to the caller
3238479ac375Sdm199847 		 * and delete the cookie.
3239479ac375Sdm199847 		 */
3240479ac375Sdm199847 	} else {
3241479ac375Sdm199847 		(void) search_state_machine(cookie, INIT, 0);
3242479ac375Sdm199847 	}
32437c478bd9Sstevel@tonic-gate 
32447c478bd9Sstevel@tonic-gate 	/* Copy results back to user */
32457c478bd9Sstevel@tonic-gate 	rc = cookie->err_rc;
3246e1dd0a2fSth160488 	if (rc != NS_LDAP_SUCCESS) {
3247e1dd0a2fSth160488 		if (conn_user != NULL && conn_user->ns_error != NULL) {
3248e1dd0a2fSth160488 			*errorp = conn_user->ns_error;
3249e1dd0a2fSth160488 			conn_user->ns_error = NULL;
3250e1dd0a2fSth160488 		} else
32517c478bd9Sstevel@tonic-gate 			*errorp = cookie->errorp;
3252e1dd0a2fSth160488 	}
32537c478bd9Sstevel@tonic-gate 	*rResult = cookie->result;
32548277a58bSchinlong 	from_result = cookie->err_from_result;
32557c478bd9Sstevel@tonic-gate 
32567c478bd9Sstevel@tonic-gate 	cookie->errorp = NULL;
32577c478bd9Sstevel@tonic-gate 	cookie->result = NULL;
32587c478bd9Sstevel@tonic-gate 	delete_search_cookie(cookie);
32597c478bd9Sstevel@tonic-gate 	cookie = NULL;
32607c478bd9Sstevel@tonic-gate 
32618277a58bSchinlong 	if (from_result == 0 && *rResult == NULL)
32627c478bd9Sstevel@tonic-gate 		rc = NS_LDAP_NOTFOUND;
3263479ac375Sdm199847 	*rcp = rc;
32647c478bd9Sstevel@tonic-gate 	return (rc);
32657c478bd9Sstevel@tonic-gate }
32667c478bd9Sstevel@tonic-gate 
3267479ac375Sdm199847 
3268479ac375Sdm199847 /*
3269479ac375Sdm199847  * __ns_ldap_list performs one or more LDAP searches to a given
3270479ac375Sdm199847  * directory server using service search descriptors and schema
3271e1dd0a2fSth160488  * mapping as appropriate. The operation may be retried a
3272e1dd0a2fSth160488  * couple of times in error situations.
3273479ac375Sdm199847  */
3274479ac375Sdm199847 int
__ns_ldap_list(const char * service,const char * filter,int (* init_filter_cb)(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata),const char * const * attribute,const ns_cred_t * auth,const int flags,ns_ldap_result_t ** rResult,ns_ldap_error_t ** errorp,int (* callback)(const ns_ldap_entry_t * entry,const void * userdata),const void * userdata)3275479ac375Sdm199847 __ns_ldap_list(
3276479ac375Sdm199847 	const char *service,
3277479ac375Sdm199847 	const char *filter,
3278479ac375Sdm199847 	int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
3279479ac375Sdm199847 	char **realfilter, const void *userdata),
3280479ac375Sdm199847 	const char * const *attribute,
3281479ac375Sdm199847 	const ns_cred_t *auth,
3282479ac375Sdm199847 	const int flags,
3283479ac375Sdm199847 	ns_ldap_result_t **rResult, /* return result entries */
3284479ac375Sdm199847 	ns_ldap_error_t **errorp,
3285479ac375Sdm199847 	int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
3286479ac375Sdm199847 	const void *userdata)
3287479ac375Sdm199847 {
3288*9f2fd570SJulian Pullen 	int mod_flags;
3289*9f2fd570SJulian Pullen 	/*
3290*9f2fd570SJulian Pullen 	 * Strip the NS_LDAP_PAGE_CTRL option as this interface does not
3291*9f2fd570SJulian Pullen 	 * support this. If you want to use this option call the API
3292*9f2fd570SJulian Pullen 	 * __ns_ldap_list_sort() with has the sort attribute.
3293*9f2fd570SJulian Pullen 	 */
3294*9f2fd570SJulian Pullen 	mod_flags = flags & (~NS_LDAP_PAGE_CTRL);
3295*9f2fd570SJulian Pullen 
3296*9f2fd570SJulian Pullen 	return (__ns_ldap_list_sort(service, filter, NULL, init_filter_cb,
3297*9f2fd570SJulian Pullen 	    attribute, auth, mod_flags, rResult, errorp,
3298*9f2fd570SJulian Pullen 	    callback, userdata));
3299*9f2fd570SJulian Pullen }
3300*9f2fd570SJulian Pullen 
3301*9f2fd570SJulian Pullen /*
3302*9f2fd570SJulian Pullen  * __ns_ldap_list_sort performs one or more LDAP searches to a given
3303*9f2fd570SJulian Pullen  * directory server using service search descriptors and schema
3304*9f2fd570SJulian Pullen  * mapping as appropriate. The operation may be retried a
3305*9f2fd570SJulian Pullen  * couple of times in error situations.
3306*9f2fd570SJulian Pullen  */
3307*9f2fd570SJulian Pullen int
__ns_ldap_list_sort(const char * service,const char * filter,const char * sortattr,int (* init_filter_cb)(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata),const char * const * attribute,const ns_cred_t * auth,const int flags,ns_ldap_result_t ** rResult,ns_ldap_error_t ** errorp,int (* callback)(const ns_ldap_entry_t * entry,const void * userdata),const void * userdata)3308*9f2fd570SJulian Pullen __ns_ldap_list_sort(
3309*9f2fd570SJulian Pullen 	const char *service,
3310*9f2fd570SJulian Pullen 	const char *filter,
3311*9f2fd570SJulian Pullen 	const char *sortattr,
3312*9f2fd570SJulian Pullen 	int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
3313*9f2fd570SJulian Pullen 	char **realfilter, const void *userdata),
3314*9f2fd570SJulian Pullen 	const char * const *attribute,
3315*9f2fd570SJulian Pullen 	const ns_cred_t *auth,
3316*9f2fd570SJulian Pullen 	const int flags,
3317*9f2fd570SJulian Pullen 	ns_ldap_result_t **rResult, /* return result entries */
3318*9f2fd570SJulian Pullen 	ns_ldap_error_t **errorp,
3319*9f2fd570SJulian Pullen 	int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
3320*9f2fd570SJulian Pullen 	const void *userdata)
3321*9f2fd570SJulian Pullen {
3322e1dd0a2fSth160488 	ns_conn_user_t	*cu = NULL;
3323e1dd0a2fSth160488 	int		try_cnt = 0;
3324e1dd0a2fSth160488 	int		rc = NS_LDAP_SUCCESS, trc;
3325e1dd0a2fSth160488 
3326e1dd0a2fSth160488 	for (;;) {
3327e1dd0a2fSth160488 		if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
3328e1dd0a2fSth160488 		    &try_cnt, &rc, errorp) == 0)
3329e1dd0a2fSth160488 			break;
3330*9f2fd570SJulian Pullen 		rc = ldap_list(NULL, service, filter, sortattr, init_filter_cb,
3331*9f2fd570SJulian Pullen 		    attribute, auth, flags, rResult, errorp, &trc, callback,
3332*9f2fd570SJulian Pullen 		    userdata, cu);
3333479ac375Sdm199847 	}
3334479ac375Sdm199847 
3335e1dd0a2fSth160488 	return (rc);
3336e1dd0a2fSth160488 }
3337479ac375Sdm199847 
3338479ac375Sdm199847 /*
3339479ac375Sdm199847  * Create and initialize batch for native LDAP lookups
3340479ac375Sdm199847  */
3341479ac375Sdm199847 int
__ns_ldap_list_batch_start(ns_ldap_list_batch_t ** batch)3342479ac375Sdm199847 __ns_ldap_list_batch_start(ns_ldap_list_batch_t **batch)
3343479ac375Sdm199847 {
3344479ac375Sdm199847 	*batch = calloc(1, sizeof (ns_ldap_list_batch_t));
3345479ac375Sdm199847 	if (*batch == NULL)
3346479ac375Sdm199847 		return (NS_LDAP_MEMORY);
3347479ac375Sdm199847 	return (NS_LDAP_SUCCESS);
3348479ac375Sdm199847 }
3349479ac375Sdm199847 
3350479ac375Sdm199847 
3351479ac375Sdm199847 /*
3352479ac375Sdm199847  * Add a LDAP search request to the batch.
3353479ac375Sdm199847  */
3354479ac375Sdm199847 int
__ns_ldap_list_batch_add(ns_ldap_list_batch_t * batch,const char * service,const char * filter,int (* init_filter_cb)(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata),const char * const * attribute,const ns_cred_t * auth,const int flags,ns_ldap_result_t ** rResult,ns_ldap_error_t ** errorp,int * rcp,int (* callback)(const ns_ldap_entry_t * entry,const void * userdata),const void * userdata)3355479ac375Sdm199847 __ns_ldap_list_batch_add(
3356479ac375Sdm199847 	ns_ldap_list_batch_t *batch,
3357479ac375Sdm199847 	const char *service,
3358479ac375Sdm199847 	const char *filter,
3359479ac375Sdm199847 	int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
3360479ac375Sdm199847 	char **realfilter, const void *userdata),
3361479ac375Sdm199847 	const char * const *attribute,
3362479ac375Sdm199847 	const ns_cred_t *auth,
3363479ac375Sdm199847 	const int flags,
3364479ac375Sdm199847 	ns_ldap_result_t **rResult, /* return result entries */
3365479ac375Sdm199847 	ns_ldap_error_t **errorp,
3366479ac375Sdm199847 	int *rcp,
3367479ac375Sdm199847 	int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
3368479ac375Sdm199847 	const void *userdata)
3369479ac375Sdm199847 {
3370e1dd0a2fSth160488 	ns_conn_user_t	*cu;
3371e1dd0a2fSth160488 	int		rc;
3372*9f2fd570SJulian Pullen 	int		mod_flags;
3373e1dd0a2fSth160488 
3374e1dd0a2fSth160488 	cu =  __s_api_conn_user_init(NS_CONN_USER_SEARCH, NULL, 0);
3375e1dd0a2fSth160488 	if (cu == NULL) {
3376e1dd0a2fSth160488 		if (rcp != NULL)
3377e1dd0a2fSth160488 			*rcp = NS_LDAP_MEMORY;
3378e1dd0a2fSth160488 		return (NS_LDAP_MEMORY);
3379e1dd0a2fSth160488 	}
3380e1dd0a2fSth160488 
3381*9f2fd570SJulian Pullen 	/*
3382*9f2fd570SJulian Pullen 	 * Strip the NS_LDAP_PAGE_CTRL option as the batch interface does not
3383*9f2fd570SJulian Pullen 	 * support this.
3384*9f2fd570SJulian Pullen 	 */
3385*9f2fd570SJulian Pullen 	mod_flags = flags & (~NS_LDAP_PAGE_CTRL);
3386*9f2fd570SJulian Pullen 
3387*9f2fd570SJulian Pullen 	rc = ldap_list(batch, service, filter, NULL, init_filter_cb, attribute,
3388*9f2fd570SJulian Pullen 	    auth, mod_flags, rResult, errorp, rcp, callback, userdata, cu);
3389e1dd0a2fSth160488 
3390e1dd0a2fSth160488 	/*
3391e1dd0a2fSth160488 	 * Free the conn_user if the cookie was not batched. If the cookie
3392e1dd0a2fSth160488 	 * was batched then __ns_ldap_list_batch_end or release will free the
3393e1dd0a2fSth160488 	 * conn_user. The batch API instructs the search_state_machine
3394e1dd0a2fSth160488 	 * to reinit and retry (max 3 times) on retriable LDAP errors.
3395e1dd0a2fSth160488 	 */
3396e1dd0a2fSth160488 	if (rc != NS_LDAP_SUCCESS && cu != NULL) {
3397e1dd0a2fSth160488 		if (cu->conn_mt != NULL)
3398e1dd0a2fSth160488 			__s_api_conn_mt_return(cu);
3399e1dd0a2fSth160488 		__s_api_conn_user_free(cu);
3400e1dd0a2fSth160488 	}
3401e1dd0a2fSth160488 	return (rc);
3402479ac375Sdm199847 }
3403479ac375Sdm199847 
3404479ac375Sdm199847 
3405479ac375Sdm199847 /*
3406479ac375Sdm199847  * Free batch.
3407479ac375Sdm199847  */
3408479ac375Sdm199847 void
__ns_ldap_list_batch_release(ns_ldap_list_batch_t * batch)3409479ac375Sdm199847 __ns_ldap_list_batch_release(ns_ldap_list_batch_t *batch)
3410479ac375Sdm199847 {
3411479ac375Sdm199847 	ns_ldap_cookie_t	*c, *next;
3412479ac375Sdm199847 
3413479ac375Sdm199847 	for (c = batch->cookie_list; c != NULL; c = next) {
3414479ac375Sdm199847 		next = c->next_cookie_in_batch;
3415e1dd0a2fSth160488 		if (c->conn_user != NULL) {
3416e1dd0a2fSth160488 			if (c->conn_user->conn_mt != NULL)
3417e1dd0a2fSth160488 				__s_api_conn_mt_return(c->conn_user);
3418e1dd0a2fSth160488 			__s_api_conn_user_free(c->conn_user);
3419e1dd0a2fSth160488 			c->conn_user = NULL;
3420e1dd0a2fSth160488 		}
3421479ac375Sdm199847 		delete_search_cookie(c);
3422479ac375Sdm199847 	}
3423479ac375Sdm199847 	free(batch);
3424479ac375Sdm199847 }
3425479ac375Sdm199847 
3426e1dd0a2fSth160488 #define	LD_USING_STATE(st) \
3427e1dd0a2fSth160488 	((st == DO_SEARCH) || (st == MULTI_RESULT) || (st == NEXT_RESULT))
3428479ac375Sdm199847 
3429479ac375Sdm199847 /*
3430479ac375Sdm199847  * Process batch. Everytime this function is called it selects an
3431479ac375Sdm199847  * active cookie from the batch and single steps through the
3432479ac375Sdm199847  * search_state_machine for the selected cookie. If lookup associated
3433479ac375Sdm199847  * with the cookie is complete (success or error) then the cookie is
3434479ac375Sdm199847  * removed from the batch and its memory freed.
3435479ac375Sdm199847  *
3436479ac375Sdm199847  * Returns 1 (if batch still has active cookies)
3437479ac375Sdm199847  *         0 (if batch has no more active cookies)
3438479ac375Sdm199847  *        -1 (on errors, *rcp will contain the error code)
3439479ac375Sdm199847  *
3440479ac375Sdm199847  * The caller should call this function in a loop as long as it returns 1
3441479ac375Sdm199847  * to process all the requests added to the batch. The results (and errors)
3442479ac375Sdm199847  * will be available in the locations provided by the caller at the time of
3443479ac375Sdm199847  * __ns_ldap_list_batch_add().
3444479ac375Sdm199847  */
3445479ac375Sdm199847 static
3446479ac375Sdm199847 int
__ns_ldap_list_batch_process(ns_ldap_list_batch_t * batch,int * rcp)3447479ac375Sdm199847 __ns_ldap_list_batch_process(ns_ldap_list_batch_t *batch, int *rcp)
3448479ac375Sdm199847 {
3449479ac375Sdm199847 	ns_ldap_cookie_t	*c, *ptr, **prev;
3450479ac375Sdm199847 	ns_state_t		state;
3451e1dd0a2fSth160488 	ns_ldap_error_t		*errorp = NULL;
3452479ac375Sdm199847 	int			rc;
3453479ac375Sdm199847 
3454479ac375Sdm199847 	/* Check if are already done */
3455479ac375Sdm199847 	if (batch->nactive == 0)
3456479ac375Sdm199847 		return (0);
3457479ac375Sdm199847 
3458479ac375Sdm199847 	/* Get the next cookie from the batch */
3459479ac375Sdm199847 	c = (batch->next_cookie == NULL) ?
3460479ac375Sdm199847 	    batch->cookie_list : batch->next_cookie;
3461479ac375Sdm199847 
3462479ac375Sdm199847 	batch->next_cookie = c->next_cookie_in_batch;
3463479ac375Sdm199847 
3464e1dd0a2fSth160488 	/*
3465e1dd0a2fSth160488 	 * Checks the status of the cookie's connection if it needs
3466e1dd0a2fSth160488 	 * to use that connection for ldap_search_ext or ldap_result.
3467e1dd0a2fSth160488 	 * If the connection is no longer good but worth retrying
3468e1dd0a2fSth160488 	 * then reinit the search_state_machine for this cookie
3469e1dd0a2fSth160488 	 * starting from the first search descriptor. REINIT will
3470e1dd0a2fSth160488 	 * clear any leftover results if max retries have not been
3471e1dd0a2fSth160488 	 * reached and redo the search (which may also involve
3472e1dd0a2fSth160488 	 * following referrals again).
3473e1dd0a2fSth160488 	 *
3474e1dd0a2fSth160488 	 * Note that each cookie in the batch will make this
3475e1dd0a2fSth160488 	 * determination when it reaches one of the LD_USING_STATES.
3476e1dd0a2fSth160488 	 */
3477e1dd0a2fSth160488 	if (LD_USING_STATE(c->new_state) && c->conn_user != NULL) {
3478e1dd0a2fSth160488 		rc = __s_api_setup_getnext(c->conn_user, &c->err_rc, &errorp);
3479e1dd0a2fSth160488 		if (rc == LDAP_BUSY || rc == LDAP_UNAVAILABLE ||
3480e1dd0a2fSth160488 		    rc == LDAP_UNWILLING_TO_PERFORM) {
3481e1dd0a2fSth160488 			if (errorp != NULL) {
3482e1dd0a2fSth160488 				(void) __ns_ldap_freeError(&c->errorp);
3483e1dd0a2fSth160488 				c->errorp = errorp;
3484e1dd0a2fSth160488 			}
3485e1dd0a2fSth160488 			c->new_state = REINIT;
3486e1dd0a2fSth160488 		} else if (rc == LDAP_CONNECT_ERROR ||
3487e1dd0a2fSth160488 		    rc == LDAP_SERVER_DOWN) {
3488e1dd0a2fSth160488 			if (errorp != NULL) {
3489e1dd0a2fSth160488 				(void) __ns_ldap_freeError(&c->errorp);
3490e1dd0a2fSth160488 				c->errorp = errorp;
3491e1dd0a2fSth160488 			}
3492e1dd0a2fSth160488 			c->new_state = REINIT;
3493e1dd0a2fSth160488 			/*
3494e1dd0a2fSth160488 			 * MT connection is not usable,
3495e1dd0a2fSth160488 			 * close it before REINIT.
3496e1dd0a2fSth160488 			 */
3497e1dd0a2fSth160488 			__s_api_conn_mt_close(
3498e1dd0a2fSth160488 			    c->conn_user, rc, NULL);
3499e1dd0a2fSth160488 		} else if (rc != NS_LDAP_SUCCESS) {
3500479ac375Sdm199847 			if (rcp != NULL)
3501479ac375Sdm199847 				*rcp = rc;
3502e1dd0a2fSth160488 			*c->caller_result = NULL;
3503e1dd0a2fSth160488 			*c->caller_errorp = errorp;
3504e1dd0a2fSth160488 			*c->caller_rc = rc;
3505479ac375Sdm199847 			return (-1);
3506479ac375Sdm199847 		}
3507479ac375Sdm199847 	}
3508479ac375Sdm199847 
3509479ac375Sdm199847 	for (;;) {
3510479ac375Sdm199847 		/* Single step through the search_state_machine */
3511479ac375Sdm199847 		state = search_state_machine(c, c->new_state, ONE_STEP);
3512479ac375Sdm199847 		switch (state) {
3513479ac375Sdm199847 		case LDAP_ERROR:
3514479ac375Sdm199847 			(void) search_state_machine(c, state, ONE_STEP);
3515479ac375Sdm199847 			(void) search_state_machine(c, CLEAR_RESULTS, ONE_STEP);
3516479ac375Sdm199847 			/* FALLTHROUGH */
3517479ac375Sdm199847 		case ERROR:
3518479ac375Sdm199847 		case EXIT:
3519479ac375Sdm199847 			*c->caller_result = c->result;
3520479ac375Sdm199847 			*c->caller_errorp = c->errorp;
3521479ac375Sdm199847 			*c->caller_rc =
3522479ac375Sdm199847 			    (c->result == NULL && c->err_from_result == 0)
3523479ac375Sdm199847 			    ? NS_LDAP_NOTFOUND : c->err_rc;
3524479ac375Sdm199847 			c->result = NULL;
3525479ac375Sdm199847 			c->errorp = NULL;
3526479ac375Sdm199847 			/* Remove the cookie from the batch */
3527479ac375Sdm199847 			ptr = batch->cookie_list;
3528479ac375Sdm199847 			prev = &batch->cookie_list;
3529479ac375Sdm199847 			while (ptr != NULL) {
3530479ac375Sdm199847 				if (ptr == c) {
3531479ac375Sdm199847 					*prev = ptr->next_cookie_in_batch;
3532479ac375Sdm199847 					break;
3533479ac375Sdm199847 				}
3534479ac375Sdm199847 				prev = &ptr->next_cookie_in_batch;
3535479ac375Sdm199847 				ptr = ptr->next_cookie_in_batch;
3536479ac375Sdm199847 			}
3537479ac375Sdm199847 			/* Delete cookie and decrement active cookie count */
3538e1dd0a2fSth160488 			if (c->conn_user != NULL) {
3539e1dd0a2fSth160488 				if (c->conn_user->conn_mt != NULL)
3540e1dd0a2fSth160488 					__s_api_conn_mt_return(c->conn_user);
3541e1dd0a2fSth160488 				__s_api_conn_user_free(c->conn_user);
3542e1dd0a2fSth160488 				c->conn_user = NULL;
3543e1dd0a2fSth160488 			}
3544479ac375Sdm199847 			delete_search_cookie(c);
3545479ac375Sdm199847 			batch->nactive--;
3546479ac375Sdm199847 			break;
3547479ac375Sdm199847 		case NEXT_RESULT:
3548479ac375Sdm199847 		case MULTI_RESULT:
3549479ac375Sdm199847 			/*
3550479ac375Sdm199847 			 * This means that search_state_machine needs to do
3551479ac375Sdm199847 			 * another ldap_result() for the cookie in question.
3552479ac375Sdm199847 			 * We only do at most one ldap_result() per call in
3553479ac375Sdm199847 			 * this function and therefore we return. This allows
3554479ac375Sdm199847 			 * the caller to process results from other cookies
3555479ac375Sdm199847 			 * in the batch without getting tied up on just one
3556479ac375Sdm199847 			 * cookie.
3557479ac375Sdm199847 			 */
3558479ac375Sdm199847 			break;
3559479ac375Sdm199847 		default:
3560479ac375Sdm199847 			/*
3561479ac375Sdm199847 			 * This includes states that follow NEXT_RESULT or
3562479ac375Sdm199847 			 * MULTI_RESULT such as PROCESS_RESULT and
3563479ac375Sdm199847 			 * END_PROCESS_RESULT. We continue processing
3564479ac375Sdm199847 			 * this cookie till we reach either the error, exit
3565479ac375Sdm199847 			 * or the result states.
3566479ac375Sdm199847 			 */
3567479ac375Sdm199847 			continue;
3568479ac375Sdm199847 		}
3569479ac375Sdm199847 		break;
3570479ac375Sdm199847 	}
3571479ac375Sdm199847 
3572479ac375Sdm199847 	/* Return 0 if no more cookies left otherwise 1 */
3573479ac375Sdm199847 	return ((batch->nactive > 0) ? 1 : 0);
3574479ac375Sdm199847 }
3575479ac375Sdm199847 
3576479ac375Sdm199847 
3577479ac375Sdm199847 /*
3578479ac375Sdm199847  * Process all the active cookies in the batch and when none
3579479ac375Sdm199847  * remains finalize the batch.
3580479ac375Sdm199847  */
3581479ac375Sdm199847 int
__ns_ldap_list_batch_end(ns_ldap_list_batch_t * batch)3582479ac375Sdm199847 __ns_ldap_list_batch_end(ns_ldap_list_batch_t *batch)
3583479ac375Sdm199847 {
3584479ac375Sdm199847 	int rc = NS_LDAP_SUCCESS;
3585479ac375Sdm199847 	while (__ns_ldap_list_batch_process(batch, &rc) > 0)
3586479ac375Sdm199847 		;
3587479ac375Sdm199847 	__ns_ldap_list_batch_release(batch);
3588479ac375Sdm199847 	return (rc);
3589479ac375Sdm199847 }
3590479ac375Sdm199847 
35917c478bd9Sstevel@tonic-gate /*
3592e1dd0a2fSth160488  * find_domainname performs one or more LDAP searches to
35937c478bd9Sstevel@tonic-gate  * find the value of the nisdomain attribute associated with
3594e1dd0a2fSth160488  * the input DN (with no retry).
35957c478bd9Sstevel@tonic-gate  */
35967c478bd9Sstevel@tonic-gate 
35977c478bd9Sstevel@tonic-gate static int
find_domainname(const char * dn,char ** domainname,const ns_cred_t * cred,ns_ldap_error_t ** errorp,ns_conn_user_t * conn_user)3598e1dd0a2fSth160488 find_domainname(const char *dn, char **domainname, const ns_cred_t *cred,
3599e1dd0a2fSth160488     ns_ldap_error_t **errorp, ns_conn_user_t *conn_user)
36007c478bd9Sstevel@tonic-gate {
36017c478bd9Sstevel@tonic-gate 
36027c478bd9Sstevel@tonic-gate 	ns_ldap_cookie_t	*cookie;
36037c478bd9Sstevel@tonic-gate 	ns_ldap_search_desc_t	**sdlist;
36047c478bd9Sstevel@tonic-gate 	ns_ldap_search_desc_t	*dptr;
36057c478bd9Sstevel@tonic-gate 	int			rc;
36067c478bd9Sstevel@tonic-gate 	char			**value;
36077c478bd9Sstevel@tonic-gate 	int			flags = 0;
36087c478bd9Sstevel@tonic-gate 
36097c478bd9Sstevel@tonic-gate 	*domainname = NULL;
36107c478bd9Sstevel@tonic-gate 	*errorp = NULL;
36117c478bd9Sstevel@tonic-gate 
36127c478bd9Sstevel@tonic-gate 	/* Initialize State machine cookie */
36137c478bd9Sstevel@tonic-gate 	cookie = init_search_state_machine();
36147c478bd9Sstevel@tonic-gate 	if (cookie == NULL) {
36157c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
36167c478bd9Sstevel@tonic-gate 	}
3617e1dd0a2fSth160488 	cookie->conn_user = conn_user;
36187c478bd9Sstevel@tonic-gate 
36197c478bd9Sstevel@tonic-gate 	/* see if need to follow referrals */
36207c478bd9Sstevel@tonic-gate 	rc = __s_api_toFollowReferrals(flags,
36217c478bd9Sstevel@tonic-gate 	    &cookie->followRef, errorp);
36227c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
36237c478bd9Sstevel@tonic-gate 		delete_search_cookie(cookie);
36247c478bd9Sstevel@tonic-gate 		return (rc);
36257c478bd9Sstevel@tonic-gate 	}
36267c478bd9Sstevel@tonic-gate 
36277c478bd9Sstevel@tonic-gate 	/* Create default service Desc */
36287c478bd9Sstevel@tonic-gate 	sdlist = (ns_ldap_search_desc_t **)calloc(2,
36297c478bd9Sstevel@tonic-gate 	    sizeof (ns_ldap_search_desc_t *));
36307c478bd9Sstevel@tonic-gate 	if (sdlist == NULL) {
36317c478bd9Sstevel@tonic-gate 		delete_search_cookie(cookie);
36327c478bd9Sstevel@tonic-gate 		cookie = NULL;
36337c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
36347c478bd9Sstevel@tonic-gate 	}
36357c478bd9Sstevel@tonic-gate 	dptr = (ns_ldap_search_desc_t *)
36367c478bd9Sstevel@tonic-gate 	    calloc(1, sizeof (ns_ldap_search_desc_t));
36377c478bd9Sstevel@tonic-gate 	if (dptr == NULL) {
36387c478bd9Sstevel@tonic-gate 		free(sdlist);
36397c478bd9Sstevel@tonic-gate 		delete_search_cookie(cookie);
36407c478bd9Sstevel@tonic-gate 		cookie = NULL;
36417c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
36427c478bd9Sstevel@tonic-gate 	}
36437c478bd9Sstevel@tonic-gate 	sdlist[0] = dptr;
36447c478bd9Sstevel@tonic-gate 
36457c478bd9Sstevel@tonic-gate 	/* search base is dn */
36467c478bd9Sstevel@tonic-gate 	dptr->basedn = strdup(dn);
36477c478bd9Sstevel@tonic-gate 
36487c478bd9Sstevel@tonic-gate 	/* search scope is base */
36497c478bd9Sstevel@tonic-gate 	dptr->scope = NS_LDAP_SCOPE_BASE;
36507c478bd9Sstevel@tonic-gate 
36517c478bd9Sstevel@tonic-gate 	/* search filter is "nisdomain=*" */
36527c478bd9Sstevel@tonic-gate 	dptr->filter = strdup(_NIS_FILTER);
36537c478bd9Sstevel@tonic-gate 
36547c478bd9Sstevel@tonic-gate 	cookie->sdlist = sdlist;
36557c478bd9Sstevel@tonic-gate 	cookie->i_filter = strdup(dptr->filter);
36567c478bd9Sstevel@tonic-gate 	cookie->i_attr = nis_domain_attrs;
36577c478bd9Sstevel@tonic-gate 	cookie->i_auth = cred;
36587c478bd9Sstevel@tonic-gate 	cookie->i_flags = 0;
36597c478bd9Sstevel@tonic-gate 
36607c478bd9Sstevel@tonic-gate 	/* Process search */
36617c478bd9Sstevel@tonic-gate 	rc = search_state_machine(cookie, INIT, 0);
36627c478bd9Sstevel@tonic-gate 
36637c478bd9Sstevel@tonic-gate 	/* Copy domain name if found */
36647c478bd9Sstevel@tonic-gate 	rc = cookie->err_rc;
3665e1dd0a2fSth160488 	if (rc != NS_LDAP_SUCCESS) {
3666e1dd0a2fSth160488 		if (conn_user != NULL && conn_user->ns_error != NULL) {
3667e1dd0a2fSth160488 			*errorp = conn_user->ns_error;
3668e1dd0a2fSth160488 			conn_user->ns_error = NULL;
3669e1dd0a2fSth160488 		} else
36707c478bd9Sstevel@tonic-gate 			*errorp = cookie->errorp;
3671e1dd0a2fSth160488 	}
36727c478bd9Sstevel@tonic-gate 	if (cookie->result == NULL)
36737c478bd9Sstevel@tonic-gate 		rc = NS_LDAP_NOTFOUND;
36747c478bd9Sstevel@tonic-gate 	if (rc == NS_LDAP_SUCCESS) {
36757c478bd9Sstevel@tonic-gate 		value = __ns_ldap_getAttr(cookie->result->entry,
36767c478bd9Sstevel@tonic-gate 		    _NIS_DOMAIN);
36777c478bd9Sstevel@tonic-gate 		if (value[0])
36787c478bd9Sstevel@tonic-gate 			*domainname = strdup(value[0]);
36797c478bd9Sstevel@tonic-gate 		else
36807c478bd9Sstevel@tonic-gate 			rc = NS_LDAP_NOTFOUND;
36817c478bd9Sstevel@tonic-gate 	}
36827c478bd9Sstevel@tonic-gate 	if (cookie->result != NULL)
36837c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&cookie->result);
36847c478bd9Sstevel@tonic-gate 	cookie->errorp = NULL;
36857c478bd9Sstevel@tonic-gate 	delete_search_cookie(cookie);
36867c478bd9Sstevel@tonic-gate 	cookie = NULL;
36877c478bd9Sstevel@tonic-gate 	return (rc);
36887c478bd9Sstevel@tonic-gate }
36897c478bd9Sstevel@tonic-gate 
3690e1dd0a2fSth160488 /*
3691e1dd0a2fSth160488  * __s_api_find_domainname performs one or more LDAP searches to
3692e1dd0a2fSth160488  * find the value of the nisdomain attribute associated with
3693e1dd0a2fSth160488  * the input DN (with retry).
3694e1dd0a2fSth160488  */
3695e1dd0a2fSth160488 
3696e1dd0a2fSth160488 static int
__s_api_find_domainname(const char * dn,char ** domainname,const ns_cred_t * cred,ns_ldap_error_t ** errorp)3697e1dd0a2fSth160488 __s_api_find_domainname(const char *dn, char **domainname,
3698e1dd0a2fSth160488     const ns_cred_t *cred, ns_ldap_error_t **errorp)
3699e1dd0a2fSth160488 {
3700e1dd0a2fSth160488 	ns_conn_user_t	*cu = NULL;
3701e1dd0a2fSth160488 	int		try_cnt = 0;
3702e1dd0a2fSth160488 	int		rc = NS_LDAP_SUCCESS;
3703e1dd0a2fSth160488 
3704e1dd0a2fSth160488 	for (;;) {
3705e1dd0a2fSth160488 		if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
3706e1dd0a2fSth160488 		    &try_cnt, &rc, errorp) == 0)
3707e1dd0a2fSth160488 			break;
3708e1dd0a2fSth160488 		rc = find_domainname(dn, domainname, cred, errorp, cu);
3709e1dd0a2fSth160488 	}
3710e1dd0a2fSth160488 
3711e1dd0a2fSth160488 	return (rc);
3712e1dd0a2fSth160488 }
3713e1dd0a2fSth160488 
3714e1dd0a2fSth160488 static int
firstEntry(const char * service,const char * filter,const char * sortattr,int (* init_filter_cb)(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata),const char * const * attribute,const ns_cred_t * auth,const int flags,void ** vcookie,ns_ldap_result_t ** result,ns_ldap_error_t ** errorp,const void * userdata,ns_conn_user_t * conn_user)3715e1dd0a2fSth160488 firstEntry(
37167c478bd9Sstevel@tonic-gate     const char *service,
37177c478bd9Sstevel@tonic-gate     const char *filter,
3718*9f2fd570SJulian Pullen     const char *sortattr,
37197c478bd9Sstevel@tonic-gate     int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
37207c478bd9Sstevel@tonic-gate     char **realfilter, const void *userdata),
37217c478bd9Sstevel@tonic-gate     const char * const *attribute,
37227c478bd9Sstevel@tonic-gate     const ns_cred_t *auth,
37237c478bd9Sstevel@tonic-gate     const int flags,
37247c478bd9Sstevel@tonic-gate     void **vcookie,
37257c478bd9Sstevel@tonic-gate     ns_ldap_result_t **result,
37267c478bd9Sstevel@tonic-gate     ns_ldap_error_t ** errorp,
3727e1dd0a2fSth160488     const void *userdata,
3728e1dd0a2fSth160488     ns_conn_user_t *conn_user)
37297c478bd9Sstevel@tonic-gate {
37307c478bd9Sstevel@tonic-gate 	ns_ldap_cookie_t	*cookie = NULL;
37317c478bd9Sstevel@tonic-gate 	ns_ldap_error_t		*error = NULL;
37327c478bd9Sstevel@tonic-gate 	ns_state_t		state;
37337c478bd9Sstevel@tonic-gate 	ns_ldap_search_desc_t	**sdlist;
37347c478bd9Sstevel@tonic-gate 	ns_ldap_search_desc_t	*dptr;
37357c478bd9Sstevel@tonic-gate 	char			**dns = NULL;
37367c478bd9Sstevel@tonic-gate 	int			scope;
37377c478bd9Sstevel@tonic-gate 	int			rc;
37387c478bd9Sstevel@tonic-gate 
37397c478bd9Sstevel@tonic-gate 	*errorp = NULL;
37407c478bd9Sstevel@tonic-gate 	*result = NULL;
37417c478bd9Sstevel@tonic-gate 
3742b57459abSJulian Pullen 	/*
3743b57459abSJulian Pullen 	 * Sanity check - NS_LDAP_READ_SHADOW is for our
3744b57459abSJulian Pullen 	 * own internal use.
3745b57459abSJulian Pullen 	 */
3746b57459abSJulian Pullen 	if (flags & NS_LDAP_READ_SHADOW)
3747b57459abSJulian Pullen 		return (NS_LDAP_INVALID_PARAM);
3748b57459abSJulian Pullen 
37497c478bd9Sstevel@tonic-gate 	/* get the service descriptor - or create a default one */
37507c478bd9Sstevel@tonic-gate 	rc = __s_api_get_SSD_from_SSDtoUse_service(service,
3751e84b06c3SMichen Chang 	    &sdlist, &error);
37527c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
37537c478bd9Sstevel@tonic-gate 		*errorp = error;
37547c478bd9Sstevel@tonic-gate 		return (rc);
37557c478bd9Sstevel@tonic-gate 	}
37567c478bd9Sstevel@tonic-gate 	if (sdlist == NULL) {
37577c478bd9Sstevel@tonic-gate 		/* Create default service Desc */
37587c478bd9Sstevel@tonic-gate 		sdlist = (ns_ldap_search_desc_t **)calloc(2,
37597c478bd9Sstevel@tonic-gate 		    sizeof (ns_ldap_search_desc_t *));
37607c478bd9Sstevel@tonic-gate 		if (sdlist == NULL) {
37617c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
37627c478bd9Sstevel@tonic-gate 		}
37637c478bd9Sstevel@tonic-gate 		dptr = (ns_ldap_search_desc_t *)
37647c478bd9Sstevel@tonic-gate 		    calloc(1, sizeof (ns_ldap_search_desc_t));
37657c478bd9Sstevel@tonic-gate 		if (dptr == NULL) {
37667c478bd9Sstevel@tonic-gate 			free(sdlist);
37677c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
37687c478bd9Sstevel@tonic-gate 		}
37697c478bd9Sstevel@tonic-gate 		sdlist[0] = dptr;
37707c478bd9Sstevel@tonic-gate 
37717c478bd9Sstevel@tonic-gate 		/* default base */
37727c478bd9Sstevel@tonic-gate 		rc = __s_api_getDNs(&dns, service, &error);
37737c478bd9Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
37747c478bd9Sstevel@tonic-gate 			if (dns) {
37757c478bd9Sstevel@tonic-gate 				__s_api_free2dArray(dns);
37767c478bd9Sstevel@tonic-gate 				dns = NULL;
37777c478bd9Sstevel@tonic-gate 			}
37787c478bd9Sstevel@tonic-gate 			if (sdlist) {
37797c478bd9Sstevel@tonic-gate 				(void) __ns_ldap_freeSearchDescriptors(
37807c478bd9Sstevel@tonic-gate 				    &sdlist);
37817c478bd9Sstevel@tonic-gate 
37827c478bd9Sstevel@tonic-gate 				sdlist = NULL;
37837c478bd9Sstevel@tonic-gate 			}
37847c478bd9Sstevel@tonic-gate 			*errorp = error;
37857c478bd9Sstevel@tonic-gate 			return (rc);
37867c478bd9Sstevel@tonic-gate 		}
37877c478bd9Sstevel@tonic-gate 		dptr->basedn = strdup(dns[0]);
37887c478bd9Sstevel@tonic-gate 		__s_api_free2dArray(dns);
37897c478bd9Sstevel@tonic-gate 		dns = NULL;
37907c478bd9Sstevel@tonic-gate 
37917c478bd9Sstevel@tonic-gate 		/* default scope */
37927c478bd9Sstevel@tonic-gate 		scope = 0;
37937c478bd9Sstevel@tonic-gate 		cookie = init_search_state_machine();
37947c478bd9Sstevel@tonic-gate 		if (cookie == NULL) {
37957c478bd9Sstevel@tonic-gate 			if (sdlist) {
37967c478bd9Sstevel@tonic-gate 				(void) __ns_ldap_freeSearchDescriptors(&sdlist);
37977c478bd9Sstevel@tonic-gate 				sdlist = NULL;
37987c478bd9Sstevel@tonic-gate 			}
37997c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
38007c478bd9Sstevel@tonic-gate 		}
38017c478bd9Sstevel@tonic-gate 		rc = __s_api_getSearchScope(&scope, &cookie->errorp);
38027c478bd9Sstevel@tonic-gate 		dptr->scope = scope;
38037c478bd9Sstevel@tonic-gate 	}
38047c478bd9Sstevel@tonic-gate 
38057c478bd9Sstevel@tonic-gate 	/* Initialize State machine cookie */
38067c478bd9Sstevel@tonic-gate 	if (cookie == NULL)
38077c478bd9Sstevel@tonic-gate 		cookie = init_search_state_machine();
38087c478bd9Sstevel@tonic-gate 	if (cookie == NULL) {
38097c478bd9Sstevel@tonic-gate 		if (sdlist) {
38107c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeSearchDescriptors(&sdlist);
38117c478bd9Sstevel@tonic-gate 			sdlist = NULL;
38127c478bd9Sstevel@tonic-gate 		}
38137c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
38147c478bd9Sstevel@tonic-gate 	}
38157c478bd9Sstevel@tonic-gate 
3816e1dd0a2fSth160488 	/* identify self as a getent user */
3817e1dd0a2fSth160488 	cookie->conn_user = conn_user;
3818e1dd0a2fSth160488 
38197c478bd9Sstevel@tonic-gate 	cookie->sdlist = sdlist;
38207c478bd9Sstevel@tonic-gate 
38217c478bd9Sstevel@tonic-gate 	/* see if need to follow referrals */
38227c478bd9Sstevel@tonic-gate 	rc = __s_api_toFollowReferrals(flags,
38237c478bd9Sstevel@tonic-gate 	    &cookie->followRef, errorp);
38247c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
38257c478bd9Sstevel@tonic-gate 		delete_search_cookie(cookie);
38267c478bd9Sstevel@tonic-gate 		return (rc);
38277c478bd9Sstevel@tonic-gate 	}
38287c478bd9Sstevel@tonic-gate 
38297c478bd9Sstevel@tonic-gate 	/*
38307c478bd9Sstevel@tonic-gate 	 * use VLV/PAGE control only if NS_LDAP_NO_PAGE_CTRL is not set
38317c478bd9Sstevel@tonic-gate 	 */
38327c478bd9Sstevel@tonic-gate 	if (flags & NS_LDAP_NO_PAGE_CTRL)
38337c478bd9Sstevel@tonic-gate 		cookie->use_paging = FALSE;
38347c478bd9Sstevel@tonic-gate 	else
38357c478bd9Sstevel@tonic-gate 		cookie->use_paging = TRUE;
38367c478bd9Sstevel@tonic-gate 
38377c478bd9Sstevel@tonic-gate 	/* Set up other arguments */
38387c478bd9Sstevel@tonic-gate 	cookie->userdata = userdata;
38397c478bd9Sstevel@tonic-gate 	if (init_filter_cb != NULL) {
38407c478bd9Sstevel@tonic-gate 		cookie->init_filter_cb = init_filter_cb;
38417c478bd9Sstevel@tonic-gate 		cookie->use_filtercb = 1;
38427c478bd9Sstevel@tonic-gate 	}
38437c478bd9Sstevel@tonic-gate 	cookie->use_usercb = 0;
3844b57459abSJulian Pullen 	/* check_shadow() may add extra value to cookie->i_flags */
3845b57459abSJulian Pullen 	cookie->i_flags = flags;
38467c478bd9Sstevel@tonic-gate 	if (service) {
38477c478bd9Sstevel@tonic-gate 		cookie->service = strdup(service);
38487c478bd9Sstevel@tonic-gate 		if (cookie->service == NULL) {
38497c478bd9Sstevel@tonic-gate 			delete_search_cookie(cookie);
38507c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
38517c478bd9Sstevel@tonic-gate 		}
3852b57459abSJulian Pullen 
3853b57459abSJulian Pullen 		/*
3854b57459abSJulian Pullen 		 * If given, use the credential given by the caller, and
3855b57459abSJulian Pullen 		 * skip the credential check required for shadow update.
3856b57459abSJulian Pullen 		 */
3857b57459abSJulian Pullen 		if (auth == NULL) {
3858b57459abSJulian Pullen 			rc = check_shadow(cookie, service);
3859b57459abSJulian Pullen 			if (rc != NS_LDAP_SUCCESS) {
3860b57459abSJulian Pullen 				*errorp = cookie->errorp;
3861b57459abSJulian Pullen 				cookie->errorp = NULL;
3862b57459abSJulian Pullen 				delete_search_cookie(cookie);
3863b57459abSJulian Pullen 				cookie = NULL;
3864b57459abSJulian Pullen 				return (rc);
3865b57459abSJulian Pullen 			}
3866b57459abSJulian Pullen 		}
38677c478bd9Sstevel@tonic-gate 	}
38687c478bd9Sstevel@tonic-gate 
38697c478bd9Sstevel@tonic-gate 	cookie->i_filter = strdup(filter);
38707c478bd9Sstevel@tonic-gate 	cookie->i_attr = attribute;
3871*9f2fd570SJulian Pullen 	cookie->i_sortattr = sortattr;
38727c478bd9Sstevel@tonic-gate 	cookie->i_auth = auth;
38737c478bd9Sstevel@tonic-gate 
38747c478bd9Sstevel@tonic-gate 	state = INIT;
38757c478bd9Sstevel@tonic-gate 	for (;;) {
38767c478bd9Sstevel@tonic-gate 		state = search_state_machine(cookie, state, ONE_STEP);
38777c478bd9Sstevel@tonic-gate 		switch (state) {
38787c478bd9Sstevel@tonic-gate 		case PROCESS_RESULT:
38797c478bd9Sstevel@tonic-gate 			*result = cookie->result;
38807c478bd9Sstevel@tonic-gate 			cookie->result = NULL;
38817c478bd9Sstevel@tonic-gate 			*vcookie = (void *)cookie;
38827c478bd9Sstevel@tonic-gate 			return (NS_LDAP_SUCCESS);
38837c478bd9Sstevel@tonic-gate 		case LDAP_ERROR:
38843d047983Smichen 			state = search_state_machine(cookie, state, ONE_STEP);
38853d047983Smichen 			state = search_state_machine(cookie, CLEAR_RESULTS,
38863d047983Smichen 			    ONE_STEP);
38873d047983Smichen 			/* FALLTHROUGH */
38883d047983Smichen 		case ERROR:
38897c478bd9Sstevel@tonic-gate 			rc = cookie->err_rc;
3890e1dd0a2fSth160488 			if (conn_user != NULL && conn_user->ns_error != NULL) {
3891e1dd0a2fSth160488 				*errorp = conn_user->ns_error;
3892e1dd0a2fSth160488 				conn_user->ns_error = NULL;
3893e1dd0a2fSth160488 			} else {
38947c478bd9Sstevel@tonic-gate 				*errorp = cookie->errorp;
38957c478bd9Sstevel@tonic-gate 				cookie->errorp = NULL;
3896e1dd0a2fSth160488 			}
38977c478bd9Sstevel@tonic-gate 			delete_search_cookie(cookie);
38987c478bd9Sstevel@tonic-gate 			return (rc);
38997c478bd9Sstevel@tonic-gate 		case EXIT:
39007c478bd9Sstevel@tonic-gate 			rc = cookie->err_rc;
39017c478bd9Sstevel@tonic-gate 			if (rc != NS_LDAP_SUCCESS) {
39027c478bd9Sstevel@tonic-gate 				*errorp = cookie->errorp;
39037c478bd9Sstevel@tonic-gate 				cookie->errorp = NULL;
39047c478bd9Sstevel@tonic-gate 			} else {
39057c478bd9Sstevel@tonic-gate 				rc = NS_LDAP_NOTFOUND;
39067c478bd9Sstevel@tonic-gate 			}
39077c478bd9Sstevel@tonic-gate 
39087c478bd9Sstevel@tonic-gate 			delete_search_cookie(cookie);
39097c478bd9Sstevel@tonic-gate 			return (rc);
39107c478bd9Sstevel@tonic-gate 
39117c478bd9Sstevel@tonic-gate 		default:
39127c478bd9Sstevel@tonic-gate 			break;
39137c478bd9Sstevel@tonic-gate 		}
39147c478bd9Sstevel@tonic-gate 	}
39157c478bd9Sstevel@tonic-gate }
39167c478bd9Sstevel@tonic-gate 
3917e1dd0a2fSth160488 int
__ns_ldap_firstEntry(const char * service,const char * filter,const char * vlv_sort,int (* init_filter_cb)(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata),const char * const * attribute,const ns_cred_t * auth,const int flags,void ** vcookie,ns_ldap_result_t ** result,ns_ldap_error_t ** errorp,const void * userdata)3918e1dd0a2fSth160488 __ns_ldap_firstEntry(
3919e1dd0a2fSth160488     const char *service,
3920e1dd0a2fSth160488     const char *filter,
3921*9f2fd570SJulian Pullen     const char *vlv_sort,
3922e1dd0a2fSth160488     int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
3923e1dd0a2fSth160488     char **realfilter, const void *userdata),
3924e1dd0a2fSth160488     const char * const *attribute,
3925e1dd0a2fSth160488     const ns_cred_t *auth,
3926e1dd0a2fSth160488     const int flags,
3927e1dd0a2fSth160488     void **vcookie,
3928e1dd0a2fSth160488     ns_ldap_result_t **result,
3929e1dd0a2fSth160488     ns_ldap_error_t ** errorp,
3930e1dd0a2fSth160488     const void *userdata)
3931e1dd0a2fSth160488 {
3932e1dd0a2fSth160488 	ns_conn_user_t	*cu = NULL;
3933e1dd0a2fSth160488 	int		try_cnt = 0;
3934e1dd0a2fSth160488 	int		rc = NS_LDAP_SUCCESS;
3935e1dd0a2fSth160488 
3936e1dd0a2fSth160488 	for (;;) {
3937e1dd0a2fSth160488 		if (__s_api_setup_retry_search(&cu, NS_CONN_USER_GETENT,
3938e1dd0a2fSth160488 		    &try_cnt, &rc, errorp) == 0)
3939e1dd0a2fSth160488 			break;
3940*9f2fd570SJulian Pullen 		rc = firstEntry(service, filter, vlv_sort, init_filter_cb,
3941*9f2fd570SJulian Pullen 		    attribute, auth, flags, vcookie, result, errorp, userdata,
3942*9f2fd570SJulian Pullen 		    cu);
3943e1dd0a2fSth160488 	}
3944e1dd0a2fSth160488 	return (rc);
3945e1dd0a2fSth160488 }
3946e1dd0a2fSth160488 
39477c478bd9Sstevel@tonic-gate /*ARGSUSED2*/
39487c478bd9Sstevel@tonic-gate int
__ns_ldap_nextEntry(void * vcookie,ns_ldap_result_t ** result,ns_ldap_error_t ** errorp)3949e1dd0a2fSth160488 __ns_ldap_nextEntry(void *vcookie, ns_ldap_result_t **result,
39507c478bd9Sstevel@tonic-gate     ns_ldap_error_t ** errorp)
39517c478bd9Sstevel@tonic-gate {
39527c478bd9Sstevel@tonic-gate 	ns_ldap_cookie_t	*cookie;
39537c478bd9Sstevel@tonic-gate 	ns_state_t		state;
39547c478bd9Sstevel@tonic-gate 	int			rc;
39557c478bd9Sstevel@tonic-gate 
39567c478bd9Sstevel@tonic-gate 	cookie = (ns_ldap_cookie_t *)vcookie;
39577c478bd9Sstevel@tonic-gate 	cookie->result = NULL;
39587c478bd9Sstevel@tonic-gate 	*result = NULL;
39597c478bd9Sstevel@tonic-gate 
3960e1dd0a2fSth160488 	if (cookie->conn_user != NULL) {
3961e1dd0a2fSth160488 		rc = __s_api_setup_getnext(cookie->conn_user,
3962e1dd0a2fSth160488 		    &cookie->err_rc, errorp);
39638277a58bSchinlong 		if (rc != NS_LDAP_SUCCESS)
39648277a58bSchinlong 			return (rc);
39658277a58bSchinlong 	}
39668277a58bSchinlong 
3967e1dd0a2fSth160488 	state = END_PROCESS_RESULT;
3968e1dd0a2fSth160488 	for (;;) {
39697c478bd9Sstevel@tonic-gate 		state = search_state_machine(cookie, state, ONE_STEP);
39707c478bd9Sstevel@tonic-gate 		switch (state) {
39717c478bd9Sstevel@tonic-gate 		case PROCESS_RESULT:
39727c478bd9Sstevel@tonic-gate 			*result = cookie->result;
39737c478bd9Sstevel@tonic-gate 			cookie->result = NULL;
39747c478bd9Sstevel@tonic-gate 			return (NS_LDAP_SUCCESS);
39757c478bd9Sstevel@tonic-gate 		case LDAP_ERROR:
39763d047983Smichen 			state = search_state_machine(cookie, state, ONE_STEP);
39773d047983Smichen 			state = search_state_machine(cookie, CLEAR_RESULTS,
39783d047983Smichen 			    ONE_STEP);
39793d047983Smichen 			/* FALLTHROUGH */
39803d047983Smichen 		case ERROR:
39817c478bd9Sstevel@tonic-gate 			rc = cookie->err_rc;
39827c478bd9Sstevel@tonic-gate 			*errorp = cookie->errorp;
39837c478bd9Sstevel@tonic-gate 			cookie->errorp = NULL;
39847c478bd9Sstevel@tonic-gate 			return (rc);
39857c478bd9Sstevel@tonic-gate 		case EXIT:
39867c478bd9Sstevel@tonic-gate 			return (NS_LDAP_SUCCESS);
39877c478bd9Sstevel@tonic-gate 		}
39887c478bd9Sstevel@tonic-gate 	}
39897c478bd9Sstevel@tonic-gate }
39907c478bd9Sstevel@tonic-gate 
39917c478bd9Sstevel@tonic-gate int
__ns_ldap_endEntry(void ** vcookie,ns_ldap_error_t ** errorp)39927c478bd9Sstevel@tonic-gate __ns_ldap_endEntry(
39937c478bd9Sstevel@tonic-gate 	void **vcookie,
39947c478bd9Sstevel@tonic-gate 	ns_ldap_error_t ** errorp)
39957c478bd9Sstevel@tonic-gate {
39967c478bd9Sstevel@tonic-gate 	ns_ldap_cookie_t	*cookie;
39977c478bd9Sstevel@tonic-gate 	int			rc;
39987c478bd9Sstevel@tonic-gate 
39997c478bd9Sstevel@tonic-gate 	if (*vcookie == NULL)
40007c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
40017c478bd9Sstevel@tonic-gate 
40027c478bd9Sstevel@tonic-gate 	cookie = (ns_ldap_cookie_t *)(*vcookie);
40037c478bd9Sstevel@tonic-gate 	cookie->result = NULL;
40047c478bd9Sstevel@tonic-gate 
40057c478bd9Sstevel@tonic-gate 	/* Complete search */
4006699bceb8Smj162486 	rc = search_state_machine(cookie, CLEAR_RESULTS, 0);
40077c478bd9Sstevel@tonic-gate 
40087c478bd9Sstevel@tonic-gate 	/* Copy results back to user */
40097c478bd9Sstevel@tonic-gate 	rc = cookie->err_rc;
40107c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS)
40117c478bd9Sstevel@tonic-gate 		*errorp = cookie->errorp;
40127c478bd9Sstevel@tonic-gate 
40137c478bd9Sstevel@tonic-gate 	cookie->errorp = NULL;
4014e1dd0a2fSth160488 	if (cookie->conn_user != NULL) {
4015e1dd0a2fSth160488 		if (cookie->conn_user->conn_mt != NULL)
4016e1dd0a2fSth160488 			__s_api_conn_mt_return(cookie->conn_user);
4017e1dd0a2fSth160488 		__s_api_conn_user_free(cookie->conn_user);
4018e1dd0a2fSth160488 	}
40197c478bd9Sstevel@tonic-gate 	delete_search_cookie(cookie);
40207c478bd9Sstevel@tonic-gate 	cookie = NULL;
40217c478bd9Sstevel@tonic-gate 	*vcookie = NULL;
40227c478bd9Sstevel@tonic-gate 
40237c478bd9Sstevel@tonic-gate 	return (rc);
40247c478bd9Sstevel@tonic-gate }
40257c478bd9Sstevel@tonic-gate 
40267c478bd9Sstevel@tonic-gate 
40277c478bd9Sstevel@tonic-gate int
__ns_ldap_freeResult(ns_ldap_result_t ** result)40287c478bd9Sstevel@tonic-gate __ns_ldap_freeResult(ns_ldap_result_t **result)
40297c478bd9Sstevel@tonic-gate {
40307c478bd9Sstevel@tonic-gate 
40317c478bd9Sstevel@tonic-gate 	ns_ldap_entry_t	*curEntry = NULL;
40327c478bd9Sstevel@tonic-gate 	ns_ldap_entry_t	*delEntry = NULL;
40337c478bd9Sstevel@tonic-gate 	int		i;
40347c478bd9Sstevel@tonic-gate 	ns_ldap_result_t	*res = *result;
40357c478bd9Sstevel@tonic-gate 
40367c478bd9Sstevel@tonic-gate #ifdef DEBUG
40377c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "__ns_ldap_freeResult START\n");
40387c478bd9Sstevel@tonic-gate #endif
40397c478bd9Sstevel@tonic-gate 	if (res == NULL)
40407c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
40417c478bd9Sstevel@tonic-gate 
40427c478bd9Sstevel@tonic-gate 	if (res->entry != NULL)
40437c478bd9Sstevel@tonic-gate 		curEntry = res->entry;
40447c478bd9Sstevel@tonic-gate 
40457c478bd9Sstevel@tonic-gate 	for (i = 0; i < res->entries_count; i++) {
40467c478bd9Sstevel@tonic-gate 		if (curEntry != NULL) {
40477c478bd9Sstevel@tonic-gate 			delEntry = curEntry;
40487c478bd9Sstevel@tonic-gate 			curEntry = curEntry->next;
40497c478bd9Sstevel@tonic-gate 			__ns_ldap_freeEntry(delEntry);
40507c478bd9Sstevel@tonic-gate 		}
40517c478bd9Sstevel@tonic-gate 	}
40527c478bd9Sstevel@tonic-gate 
40537c478bd9Sstevel@tonic-gate 	free(res);
40547c478bd9Sstevel@tonic-gate 	*result = NULL;
40557c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
40567c478bd9Sstevel@tonic-gate }
40577c478bd9Sstevel@tonic-gate 
40587c478bd9Sstevel@tonic-gate /*ARGSUSED*/
40597c478bd9Sstevel@tonic-gate int
__ns_ldap_auth(const ns_cred_t * auth,const int flags,ns_ldap_error_t ** errorp,LDAPControl ** serverctrls,LDAPControl ** clientctrls)40607c478bd9Sstevel@tonic-gate __ns_ldap_auth(const ns_cred_t *auth,
40617c478bd9Sstevel@tonic-gate 		    const int flags,
40627c478bd9Sstevel@tonic-gate 		    ns_ldap_error_t **errorp,
40637c478bd9Sstevel@tonic-gate 		    LDAPControl **serverctrls,
40647c478bd9Sstevel@tonic-gate 		    LDAPControl **clientctrls)
40657c478bd9Sstevel@tonic-gate {
40667c478bd9Sstevel@tonic-gate 
40677c478bd9Sstevel@tonic-gate 	ConnectionID	connectionId = -1;
40687c478bd9Sstevel@tonic-gate 	Connection	*conp;
40697c478bd9Sstevel@tonic-gate 	int		rc = 0;
40707c478bd9Sstevel@tonic-gate 	int		do_not_fail_if_new_pwd_reqd = 0;
407147789246Svv149972 	int		nopasswd_acct_mgmt = 0;
4072e1dd0a2fSth160488 	ns_conn_user_t	*conn_user;
40737c478bd9Sstevel@tonic-gate 
40747c478bd9Sstevel@tonic-gate 
40757c478bd9Sstevel@tonic-gate #ifdef DEBUG
40767c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "__ns_ldap_auth START\n");
40777c478bd9Sstevel@tonic-gate #endif
40787c478bd9Sstevel@tonic-gate 
40797c478bd9Sstevel@tonic-gate 	*errorp = NULL;
40807c478bd9Sstevel@tonic-gate 	if (!auth)
40817c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
40827c478bd9Sstevel@tonic-gate 
4083e1dd0a2fSth160488 	conn_user = __s_api_conn_user_init(NS_CONN_USER_AUTH,
4084e1dd0a2fSth160488 	    NULL, B_FALSE);
4085e1dd0a2fSth160488 
4086cb5caa98Sdjl 	rc = __s_api_getConnection(NULL, flags | NS_LDAP_NEW_CONN,
40877c478bd9Sstevel@tonic-gate 	    auth, &connectionId, &conp, errorp,
4088e1dd0a2fSth160488 	    do_not_fail_if_new_pwd_reqd, nopasswd_acct_mgmt,
4089e1dd0a2fSth160488 	    conn_user);
4090e1dd0a2fSth160488 
4091e1dd0a2fSth160488 	if (conn_user != NULL)
4092e1dd0a2fSth160488 		__s_api_conn_user_free(conn_user);
4093e1dd0a2fSth160488 
40947c478bd9Sstevel@tonic-gate 	if (rc == NS_LDAP_OP_FAILED && *errorp)
40957c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(errorp);
40967c478bd9Sstevel@tonic-gate 
40977c478bd9Sstevel@tonic-gate 	if (connectionId > -1)
40987c478bd9Sstevel@tonic-gate 		DropConnection(connectionId, flags);
40997c478bd9Sstevel@tonic-gate 	return (rc);
41007c478bd9Sstevel@tonic-gate }
41017c478bd9Sstevel@tonic-gate 
41027c478bd9Sstevel@tonic-gate char **
__ns_ldap_getAttr(const ns_ldap_entry_t * entry,const char * attrname)41037c478bd9Sstevel@tonic-gate __ns_ldap_getAttr(const ns_ldap_entry_t *entry, const char *attrname)
41047c478bd9Sstevel@tonic-gate {
41057c478bd9Sstevel@tonic-gate 	int	i;
41067c478bd9Sstevel@tonic-gate 
41077c478bd9Sstevel@tonic-gate 	if (entry == NULL)
41087c478bd9Sstevel@tonic-gate 		return (NULL);
41097c478bd9Sstevel@tonic-gate 	for (i = 0; i < entry->attr_count; i++) {
41107c478bd9Sstevel@tonic-gate 		if (strcasecmp(entry->attr_pair[i]->attrname, attrname) == NULL)
41117c478bd9Sstevel@tonic-gate 			return (entry->attr_pair[i]->attrvalue);
41127c478bd9Sstevel@tonic-gate 	}
41137c478bd9Sstevel@tonic-gate 	return (NULL);
41147c478bd9Sstevel@tonic-gate }
41157c478bd9Sstevel@tonic-gate 
4116cb5caa98Sdjl ns_ldap_attr_t *
__ns_ldap_getAttrStruct(const ns_ldap_entry_t * entry,const char * attrname)4117cb5caa98Sdjl __ns_ldap_getAttrStruct(const ns_ldap_entry_t *entry, const char *attrname)
4118cb5caa98Sdjl {
4119cb5caa98Sdjl 	int	i;
4120cb5caa98Sdjl 
4121cb5caa98Sdjl 	if (entry == NULL)
4122cb5caa98Sdjl 		return (NULL);
4123cb5caa98Sdjl 	for (i = 0; i < entry->attr_count; i++) {
4124cb5caa98Sdjl 		if (strcasecmp(entry->attr_pair[i]->attrname, attrname) == NULL)
4125cb5caa98Sdjl 			return (entry->attr_pair[i]);
4126cb5caa98Sdjl 	}
4127cb5caa98Sdjl 	return (NULL);
4128cb5caa98Sdjl }
4129cb5caa98Sdjl 
41307c478bd9Sstevel@tonic-gate 
41317c478bd9Sstevel@tonic-gate /*ARGSUSED*/
41327c478bd9Sstevel@tonic-gate int
__ns_ldap_uid2dn(const char * uid,char ** userDN,const ns_cred_t * cred,ns_ldap_error_t ** errorp)41337c478bd9Sstevel@tonic-gate __ns_ldap_uid2dn(const char *uid,
41347c478bd9Sstevel@tonic-gate 		char **userDN,
41357c478bd9Sstevel@tonic-gate 		const ns_cred_t *cred,	/* cred is ignored */
41367c478bd9Sstevel@tonic-gate 		ns_ldap_error_t **errorp)
41377c478bd9Sstevel@tonic-gate {
41387c478bd9Sstevel@tonic-gate 	ns_ldap_result_t	*result = NULL;
41397c478bd9Sstevel@tonic-gate 	char		*filter, *userdata;
41407c478bd9Sstevel@tonic-gate 	char		errstr[MAXERROR];
41417c478bd9Sstevel@tonic-gate 	char		**value;
41427c478bd9Sstevel@tonic-gate 	int		rc = 0;
41437c478bd9Sstevel@tonic-gate 	int		i = 0;
41447c478bd9Sstevel@tonic-gate 	size_t		len;
41457c478bd9Sstevel@tonic-gate 
41467c478bd9Sstevel@tonic-gate 	*errorp = NULL;
41477c478bd9Sstevel@tonic-gate 	*userDN = NULL;
41487c478bd9Sstevel@tonic-gate 	if ((uid == NULL) || (uid[0] == '\0'))
41497c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
41507c478bd9Sstevel@tonic-gate 
41517c478bd9Sstevel@tonic-gate 	while (uid[i] != '\0') {
41527c478bd9Sstevel@tonic-gate 		if (uid[i] == '=') {
41537c478bd9Sstevel@tonic-gate 			*userDN = strdup(uid);
41547c478bd9Sstevel@tonic-gate 			return (NS_LDAP_SUCCESS);
41557c478bd9Sstevel@tonic-gate 		}
41567c478bd9Sstevel@tonic-gate 		i++;
41577c478bd9Sstevel@tonic-gate 	}
41587c478bd9Sstevel@tonic-gate 	i = 0;
41597c478bd9Sstevel@tonic-gate 	while ((uid[i] != '\0') && (isdigit(uid[i])))
41607c478bd9Sstevel@tonic-gate 		i++;
41617c478bd9Sstevel@tonic-gate 	if (uid[i] == '\0') {
41627c478bd9Sstevel@tonic-gate 		len = strlen(UIDNUMFILTER) + strlen(uid) + 1;
41637c478bd9Sstevel@tonic-gate 		filter = (char *)malloc(len);
41647c478bd9Sstevel@tonic-gate 		if (filter == NULL) {
41657c478bd9Sstevel@tonic-gate 			*userDN = NULL;
41667c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
41677c478bd9Sstevel@tonic-gate 		}
41687c478bd9Sstevel@tonic-gate 		(void) snprintf(filter, len, UIDNUMFILTER, uid);
41697c478bd9Sstevel@tonic-gate 
41707c478bd9Sstevel@tonic-gate 		len = strlen(UIDNUMFILTER_SSD) + strlen(uid) + 1;
41717c478bd9Sstevel@tonic-gate 		userdata = (char *)malloc(len);
41727c478bd9Sstevel@tonic-gate 		if (userdata == NULL) {
41737c478bd9Sstevel@tonic-gate 			*userDN = NULL;
41747c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
41757c478bd9Sstevel@tonic-gate 		}
41767c478bd9Sstevel@tonic-gate 		(void) snprintf(userdata, len, UIDNUMFILTER_SSD, uid);
41777c478bd9Sstevel@tonic-gate 	} else {
41787c478bd9Sstevel@tonic-gate 		len = strlen(UIDFILTER) + strlen(uid) + 1;
41797c478bd9Sstevel@tonic-gate 		filter = (char *)malloc(len);
41807c478bd9Sstevel@tonic-gate 		if (filter == NULL) {
41817c478bd9Sstevel@tonic-gate 			*userDN = NULL;
41827c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
41837c478bd9Sstevel@tonic-gate 		}
41847c478bd9Sstevel@tonic-gate 		(void) snprintf(filter, len, UIDFILTER, uid);
41857c478bd9Sstevel@tonic-gate 
41867c478bd9Sstevel@tonic-gate 		len = strlen(UIDFILTER_SSD) + strlen(uid) + 1;
41877c478bd9Sstevel@tonic-gate 		userdata = (char *)malloc(len);
41887c478bd9Sstevel@tonic-gate 		if (userdata == NULL) {
41897c478bd9Sstevel@tonic-gate 			*userDN = NULL;
41907c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
41917c478bd9Sstevel@tonic-gate 		}
41927c478bd9Sstevel@tonic-gate 		(void) snprintf(userdata, len, UIDFILTER_SSD, uid);
41937c478bd9Sstevel@tonic-gate 	}
41947c478bd9Sstevel@tonic-gate 
4195f5c3c7a7Ssdussud 	/*
4196f5c3c7a7Ssdussud 	 * we want to retrieve the DN as it appears in LDAP
4197f5c3c7a7Ssdussud 	 * hence the use of NS_LDAP_NOT_CVT_DN in flags
4198f5c3c7a7Ssdussud 	 */
41997c478bd9Sstevel@tonic-gate 	rc = __ns_ldap_list("passwd", filter,
42007c478bd9Sstevel@tonic-gate 	    __s_api_merge_SSD_filter,
4201f5c3c7a7Ssdussud 	    NULL, cred, NS_LDAP_NOT_CVT_DN,
42027c478bd9Sstevel@tonic-gate 	    &result, errorp, NULL,
42037c478bd9Sstevel@tonic-gate 	    userdata);
42047c478bd9Sstevel@tonic-gate 	free(filter);
42057c478bd9Sstevel@tonic-gate 	filter = NULL;
42067c478bd9Sstevel@tonic-gate 	free(userdata);
42077c478bd9Sstevel@tonic-gate 	userdata = NULL;
42087c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
42097c478bd9Sstevel@tonic-gate 		if (result) {
42107c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeResult(&result);
42117c478bd9Sstevel@tonic-gate 			result = NULL;
42127c478bd9Sstevel@tonic-gate 		}
42137c478bd9Sstevel@tonic-gate 		return (rc);
42147c478bd9Sstevel@tonic-gate 	}
42157c478bd9Sstevel@tonic-gate 	if (result->entries_count > 1) {
42167c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&result);
42177c478bd9Sstevel@tonic-gate 		result = NULL;
42187c478bd9Sstevel@tonic-gate 		*userDN = NULL;
42197c478bd9Sstevel@tonic-gate 		(void) sprintf(errstr,
42207c478bd9Sstevel@tonic-gate 		    gettext("Too many entries are returned for %s"), uid);
42217c478bd9Sstevel@tonic-gate 		MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr),
42227c478bd9Sstevel@tonic-gate 		    NULL);
42237c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INTERNAL);
42247c478bd9Sstevel@tonic-gate 	}
42257c478bd9Sstevel@tonic-gate 
42267c478bd9Sstevel@tonic-gate 	value = __ns_ldap_getAttr(result->entry, "dn");
42277c478bd9Sstevel@tonic-gate 	*userDN = strdup(value[0]);
42287c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&result);
42297c478bd9Sstevel@tonic-gate 	result = NULL;
42307c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
42317c478bd9Sstevel@tonic-gate }
42327c478bd9Sstevel@tonic-gate 
42337c478bd9Sstevel@tonic-gate 
42347c478bd9Sstevel@tonic-gate /*ARGSUSED*/
42357c478bd9Sstevel@tonic-gate int
__ns_ldap_host2dn(const char * host,const char * domain,char ** hostDN,const ns_cred_t * cred,ns_ldap_error_t ** errorp)42367c478bd9Sstevel@tonic-gate __ns_ldap_host2dn(const char *host,
42377c478bd9Sstevel@tonic-gate 		const char *domain,
42387c478bd9Sstevel@tonic-gate 		char **hostDN,
42397c478bd9Sstevel@tonic-gate 		const ns_cred_t *cred,	/* cred is ignored */
42407c478bd9Sstevel@tonic-gate 		ns_ldap_error_t **errorp)
42417c478bd9Sstevel@tonic-gate {
42427c478bd9Sstevel@tonic-gate 	ns_ldap_result_t	*result = NULL;
42437c478bd9Sstevel@tonic-gate 	char		*filter, *userdata;
42447c478bd9Sstevel@tonic-gate 	char		errstr[MAXERROR];
42457c478bd9Sstevel@tonic-gate 	char		**value;
42467c478bd9Sstevel@tonic-gate 	int		rc;
42477c478bd9Sstevel@tonic-gate 	size_t		len;
42487c478bd9Sstevel@tonic-gate 
42497c478bd9Sstevel@tonic-gate /*
42507c478bd9Sstevel@tonic-gate  * XXX
42517c478bd9Sstevel@tonic-gate  * the domain parameter needs to be used in case domain is not local, if
42527c478bd9Sstevel@tonic-gate  * this routine is to support multi domain setups, it needs lots of work...
42537c478bd9Sstevel@tonic-gate  */
42547c478bd9Sstevel@tonic-gate 	*errorp = NULL;
42557c478bd9Sstevel@tonic-gate 	*hostDN = NULL;
42567c478bd9Sstevel@tonic-gate 	if ((host == NULL) || (host[0] == '\0'))
42577c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
42587c478bd9Sstevel@tonic-gate 
42597c478bd9Sstevel@tonic-gate 	len = strlen(HOSTFILTER) + strlen(host) + 1;
42607c478bd9Sstevel@tonic-gate 	filter = (char *)malloc(len);
42617c478bd9Sstevel@tonic-gate 	if (filter == NULL) {
42627c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
42637c478bd9Sstevel@tonic-gate 	}
42647c478bd9Sstevel@tonic-gate 	(void) snprintf(filter,	len, HOSTFILTER, host);
42657c478bd9Sstevel@tonic-gate 
42667c478bd9Sstevel@tonic-gate 	len = strlen(HOSTFILTER_SSD) + strlen(host) + 1;
42677c478bd9Sstevel@tonic-gate 	userdata = (char *)malloc(len);
42687c478bd9Sstevel@tonic-gate 	if (userdata == NULL) {
42697c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
42707c478bd9Sstevel@tonic-gate 	}
42717c478bd9Sstevel@tonic-gate 	(void) snprintf(userdata, len, HOSTFILTER_SSD, host);
42727c478bd9Sstevel@tonic-gate 
4273f5c3c7a7Ssdussud 	/*
4274f5c3c7a7Ssdussud 	 * we want to retrieve the DN as it appears in LDAP
4275f5c3c7a7Ssdussud 	 * hence the use of NS_LDAP_NOT_CVT_DN in flags
4276f5c3c7a7Ssdussud 	 */
42777c478bd9Sstevel@tonic-gate 	rc = __ns_ldap_list("hosts", filter,
42787c478bd9Sstevel@tonic-gate 	    __s_api_merge_SSD_filter,
4279f5c3c7a7Ssdussud 	    NULL, cred, NS_LDAP_NOT_CVT_DN, &result,
42807c478bd9Sstevel@tonic-gate 	    errorp, NULL,
42817c478bd9Sstevel@tonic-gate 	    userdata);
42827c478bd9Sstevel@tonic-gate 	free(filter);
42837c478bd9Sstevel@tonic-gate 	filter = NULL;
42847c478bd9Sstevel@tonic-gate 	free(userdata);
42857c478bd9Sstevel@tonic-gate 	userdata = NULL;
42867c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
42877c478bd9Sstevel@tonic-gate 		if (result) {
42887c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeResult(&result);
42897c478bd9Sstevel@tonic-gate 			result = NULL;
42907c478bd9Sstevel@tonic-gate 		}
42917c478bd9Sstevel@tonic-gate 		return (rc);
42927c478bd9Sstevel@tonic-gate 	}
42937c478bd9Sstevel@tonic-gate 
42947c478bd9Sstevel@tonic-gate 	if (result->entries_count > 1) {
42957c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&result);
42967c478bd9Sstevel@tonic-gate 		result = NULL;
42977c478bd9Sstevel@tonic-gate 		*hostDN = NULL;
42987c478bd9Sstevel@tonic-gate 		(void) sprintf(errstr,
42997c478bd9Sstevel@tonic-gate 		    gettext("Too many entries are returned for %s"), host);
43007c478bd9Sstevel@tonic-gate 		MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr),
43017c478bd9Sstevel@tonic-gate 		    NULL);
43027c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INTERNAL);
43037c478bd9Sstevel@tonic-gate 	}
43047c478bd9Sstevel@tonic-gate 
43057c478bd9Sstevel@tonic-gate 	value = __ns_ldap_getAttr(result->entry, "dn");
43067c478bd9Sstevel@tonic-gate 	*hostDN = strdup(value[0]);
43077c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&result);
43087c478bd9Sstevel@tonic-gate 	result = NULL;
43097c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
43107c478bd9Sstevel@tonic-gate }
43117c478bd9Sstevel@tonic-gate 
43127c478bd9Sstevel@tonic-gate /*ARGSUSED*/
43137c478bd9Sstevel@tonic-gate int
__ns_ldap_dn2domain(const char * dn,char ** domain,const ns_cred_t * cred,ns_ldap_error_t ** errorp)43147c478bd9Sstevel@tonic-gate __ns_ldap_dn2domain(const char *dn,
43157c478bd9Sstevel@tonic-gate 			char **domain,
43167c478bd9Sstevel@tonic-gate 			const ns_cred_t *cred,
43177c478bd9Sstevel@tonic-gate 			ns_ldap_error_t **errorp)
43187c478bd9Sstevel@tonic-gate {
43197c478bd9Sstevel@tonic-gate 	int		rc, pnum, i, j, len = 0;
43207c478bd9Sstevel@tonic-gate 	char		*newdn, **rdns = NULL;
43217c478bd9Sstevel@tonic-gate 	char		**dns, *dn1;
43227c478bd9Sstevel@tonic-gate 
43237c478bd9Sstevel@tonic-gate 	*errorp = NULL;
43247c478bd9Sstevel@tonic-gate 
43257c478bd9Sstevel@tonic-gate 	if (domain == NULL)
43267c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
43277c478bd9Sstevel@tonic-gate 	else
43287c478bd9Sstevel@tonic-gate 		*domain = NULL;
43297c478bd9Sstevel@tonic-gate 
43307c478bd9Sstevel@tonic-gate 	if ((dn == NULL) || (dn[0] == '\0'))
43317c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
43327c478bd9Sstevel@tonic-gate 
43337c478bd9Sstevel@tonic-gate 	/*
43347c478bd9Sstevel@tonic-gate 	 * break dn into rdns
43357c478bd9Sstevel@tonic-gate 	 */
43367c478bd9Sstevel@tonic-gate 	dn1 = strdup(dn);
43377c478bd9Sstevel@tonic-gate 	if (dn1 == NULL)
43387c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
43397c478bd9Sstevel@tonic-gate 	rdns = ldap_explode_dn(dn1, 0);
43407c478bd9Sstevel@tonic-gate 	free(dn1);
43417c478bd9Sstevel@tonic-gate 	if (rdns == NULL || *rdns == NULL)
43427c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
43437c478bd9Sstevel@tonic-gate 
43447c478bd9Sstevel@tonic-gate 	for (i = 0; rdns[i]; i++)
43457c478bd9Sstevel@tonic-gate 		len += strlen(rdns[i]) + 1;
43467c478bd9Sstevel@tonic-gate 	pnum = i;
43477c478bd9Sstevel@tonic-gate 
43487c478bd9Sstevel@tonic-gate 	newdn = (char *)malloc(len + 1);
43497c478bd9Sstevel@tonic-gate 	dns = (char **)calloc(pnum, sizeof (char *));
43507c478bd9Sstevel@tonic-gate 	if (newdn == NULL || dns == NULL) {
43517c478bd9Sstevel@tonic-gate 		if (newdn)
43527c478bd9Sstevel@tonic-gate 			free(newdn);
43537c478bd9Sstevel@tonic-gate 		ldap_value_free(rdns);
43547c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
43557c478bd9Sstevel@tonic-gate 	}
43567c478bd9Sstevel@tonic-gate 
43577c478bd9Sstevel@tonic-gate 	/* construct a semi-normalized dn, newdn */
43587c478bd9Sstevel@tonic-gate 	*newdn = '\0';
43597c478bd9Sstevel@tonic-gate 	for (i = 0; rdns[i]; i++) {
43607c478bd9Sstevel@tonic-gate 		dns[i] = newdn + strlen(newdn);
43617c478bd9Sstevel@tonic-gate 		(void) strcat(newdn,
43627c478bd9Sstevel@tonic-gate 		    __s_api_remove_rdn_space(rdns[i]));
43637c478bd9Sstevel@tonic-gate 		(void) strcat(newdn, ",");
43647c478bd9Sstevel@tonic-gate 	}
43657c478bd9Sstevel@tonic-gate 	/* remove the last ',' */
43667c478bd9Sstevel@tonic-gate 	newdn[strlen(newdn) - 1] = '\0';
43677c478bd9Sstevel@tonic-gate 	ldap_value_free(rdns);
43687c478bd9Sstevel@tonic-gate 
43697c478bd9Sstevel@tonic-gate 	/*
43707c478bd9Sstevel@tonic-gate 	 * loop and find the domain name associated with newdn,
43717c478bd9Sstevel@tonic-gate 	 * removing rdn one by one from left to right
43727c478bd9Sstevel@tonic-gate 	 */
43737c478bd9Sstevel@tonic-gate 	for (i = 0; i < pnum; i++) {
43747c478bd9Sstevel@tonic-gate 
43757c478bd9Sstevel@tonic-gate 		if (*errorp)
43767c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeError(errorp);
43777c478bd9Sstevel@tonic-gate 
43787c478bd9Sstevel@tonic-gate 		/*
43797c478bd9Sstevel@tonic-gate 		 *  try cache manager first
43807c478bd9Sstevel@tonic-gate 		 */
43817c478bd9Sstevel@tonic-gate 		rc = __s_api_get_cachemgr_data(NS_CACHE_DN2DOMAIN,
43827c478bd9Sstevel@tonic-gate 		    dns[i], domain);
43837c478bd9Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
43847c478bd9Sstevel@tonic-gate 			/*
43857c478bd9Sstevel@tonic-gate 			 *  try ldap server second
43867c478bd9Sstevel@tonic-gate 			 */
43877c478bd9Sstevel@tonic-gate 			rc = __s_api_find_domainname(dns[i], domain,
43887c478bd9Sstevel@tonic-gate 			    cred, errorp);
43897c478bd9Sstevel@tonic-gate 		} else {
43907c478bd9Sstevel@tonic-gate 			/*
43917c478bd9Sstevel@tonic-gate 			 * skip the last one,
43927c478bd9Sstevel@tonic-gate 			 * since it is already cached by ldap_cachemgr
43937c478bd9Sstevel@tonic-gate 			 */
43947c478bd9Sstevel@tonic-gate 			i--;
43957c478bd9Sstevel@tonic-gate 		}
43967c478bd9Sstevel@tonic-gate 		if (rc == NS_LDAP_SUCCESS) {
43978142c2b2Schinlong 			if (__s_api_nscd_proc()) {
43987c478bd9Sstevel@tonic-gate 				/*
43998142c2b2Schinlong 				 * If it's nscd, ask cache manager to save the
44007c478bd9Sstevel@tonic-gate 				 * dn to domain mapping(s)
44017c478bd9Sstevel@tonic-gate 				 */
44027c478bd9Sstevel@tonic-gate 				for (j = 0; j <= i; j++) {
44037c478bd9Sstevel@tonic-gate 					(void) __s_api_set_cachemgr_data(
44047c478bd9Sstevel@tonic-gate 					    NS_CACHE_DN2DOMAIN,
44057c478bd9Sstevel@tonic-gate 					    dns[j],
44067c478bd9Sstevel@tonic-gate 					    *domain);
44077c478bd9Sstevel@tonic-gate 				}
44088142c2b2Schinlong 			}
44097c478bd9Sstevel@tonic-gate 			break;
44107c478bd9Sstevel@tonic-gate 		}
44117c478bd9Sstevel@tonic-gate 	}
44127c478bd9Sstevel@tonic-gate 
44137c478bd9Sstevel@tonic-gate 	free(dns);
44147c478bd9Sstevel@tonic-gate 	free(newdn);
44157c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS)
44167c478bd9Sstevel@tonic-gate 		rc = NS_LDAP_NOTFOUND;
44177c478bd9Sstevel@tonic-gate 	return (rc);
44187c478bd9Sstevel@tonic-gate }
44197c478bd9Sstevel@tonic-gate 
44207c478bd9Sstevel@tonic-gate /*ARGSUSED*/
44217c478bd9Sstevel@tonic-gate int
__ns_ldap_getServiceAuthMethods(const char * service,ns_auth_t *** auth,ns_ldap_error_t ** errorp)44227c478bd9Sstevel@tonic-gate __ns_ldap_getServiceAuthMethods(const char *service,
44237c478bd9Sstevel@tonic-gate 		ns_auth_t ***auth,
44247c478bd9Sstevel@tonic-gate 		ns_ldap_error_t **errorp)
44257c478bd9Sstevel@tonic-gate {
44267c478bd9Sstevel@tonic-gate 	char		errstr[MAXERROR];
44277c478bd9Sstevel@tonic-gate 	int		rc, i, done = 0;
44287c478bd9Sstevel@tonic-gate 	int		slen;
44297c478bd9Sstevel@tonic-gate 	void		**param;
44307c478bd9Sstevel@tonic-gate 	char		**sam, *srv, *send;
44317c478bd9Sstevel@tonic-gate 	ns_auth_t	**authpp = NULL, *ap;
44327c478bd9Sstevel@tonic-gate 	int		cnt, max;
44337c478bd9Sstevel@tonic-gate 	ns_config_t	*cfg;
44347c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
44357c478bd9Sstevel@tonic-gate 
44367c478bd9Sstevel@tonic-gate 	if (errorp == NULL)
44377c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
44387c478bd9Sstevel@tonic-gate 	*errorp = NULL;
44397c478bd9Sstevel@tonic-gate 
44407c478bd9Sstevel@tonic-gate 	if ((service == NULL) || (service[0] == '\0') ||
44417c478bd9Sstevel@tonic-gate 	    (auth == NULL))
44427c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
44437c478bd9Sstevel@tonic-gate 
44447c478bd9Sstevel@tonic-gate 	*auth = NULL;
44457c478bd9Sstevel@tonic-gate 	rc = __ns_ldap_getParam(NS_LDAP_SERVICE_AUTH_METHOD_P, &param, &error);
44467c478bd9Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS || param == NULL) {
44477c478bd9Sstevel@tonic-gate 		*errorp = error;
44487c478bd9Sstevel@tonic-gate 		return (rc);
44497c478bd9Sstevel@tonic-gate 	}
44507c478bd9Sstevel@tonic-gate 	sam = (char **)param;
44517c478bd9Sstevel@tonic-gate 
44527c478bd9Sstevel@tonic-gate 	cfg = __s_api_get_default_config();
44537c478bd9Sstevel@tonic-gate 	cnt = 0;
44547c478bd9Sstevel@tonic-gate 
44557c478bd9Sstevel@tonic-gate 	slen = strlen(service);
44567c478bd9Sstevel@tonic-gate 
44577c478bd9Sstevel@tonic-gate 	for (; *sam; sam++) {
44587c478bd9Sstevel@tonic-gate 		srv = *sam;
44597c478bd9Sstevel@tonic-gate 		if (strncasecmp(service, srv, slen) != 0)
44607c478bd9Sstevel@tonic-gate 			continue;
44617c478bd9Sstevel@tonic-gate 		srv += slen;
44627c478bd9Sstevel@tonic-gate 		if (*srv != COLONTOK)
44637c478bd9Sstevel@tonic-gate 			continue;
44647c478bd9Sstevel@tonic-gate 		send = srv;
44657c478bd9Sstevel@tonic-gate 		srv++;
44667c478bd9Sstevel@tonic-gate 		for (max = 1; (send = strchr(++send, SEMITOK)) != NULL;
44677c478bd9Sstevel@tonic-gate 		    max++) {}
44687c478bd9Sstevel@tonic-gate 		authpp = (ns_auth_t **)calloc(++max, sizeof (ns_auth_t *));
44697c478bd9Sstevel@tonic-gate 		if (authpp == NULL) {
44707c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeParam(&param);
44717c478bd9Sstevel@tonic-gate 			__s_api_release_config(cfg);
44727c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
44737c478bd9Sstevel@tonic-gate 		}
44747c478bd9Sstevel@tonic-gate 		while (!done) {
44757c478bd9Sstevel@tonic-gate 			send = strchr(srv, SEMITOK);
44767c478bd9Sstevel@tonic-gate 			if (send != NULL) {
44777c478bd9Sstevel@tonic-gate 				*send = '\0';
44787c478bd9Sstevel@tonic-gate 				send++;
44797c478bd9Sstevel@tonic-gate 			}
44807c478bd9Sstevel@tonic-gate 			i = __s_get_enum_value(cfg, srv, NS_LDAP_AUTH_P);
44817c478bd9Sstevel@tonic-gate 			if (i == -1) {
44827c478bd9Sstevel@tonic-gate 				(void) __ns_ldap_freeParam(&param);
44837c478bd9Sstevel@tonic-gate 				(void) sprintf(errstr,
4484699bceb8Smj162486 				gettext("Unsupported "
4485699bceb8Smj162486 				    "serviceAuthenticationMethod: %s.\n"), srv);
44867c478bd9Sstevel@tonic-gate 				MKERROR(LOG_WARNING, *errorp, NS_CONFIG_SYNTAX,
44877c478bd9Sstevel@tonic-gate 				    strdup(errstr), NULL);
44887c478bd9Sstevel@tonic-gate 				__s_api_release_config(cfg);
44897c478bd9Sstevel@tonic-gate 				return (NS_LDAP_CONFIG);
44907c478bd9Sstevel@tonic-gate 			}
44917c478bd9Sstevel@tonic-gate 			ap = __s_api_AuthEnumtoStruct((EnumAuthType_t)i);
44927c478bd9Sstevel@tonic-gate 			if (ap == NULL) {
44937c478bd9Sstevel@tonic-gate 				(void) __ns_ldap_freeParam(&param);
44947c478bd9Sstevel@tonic-gate 				__s_api_release_config(cfg);
44957c478bd9Sstevel@tonic-gate 				return (NS_LDAP_MEMORY);
44967c478bd9Sstevel@tonic-gate 			}
44977c478bd9Sstevel@tonic-gate 			authpp[cnt++] = ap;
44987c478bd9Sstevel@tonic-gate 			if (send == NULL)
44997c478bd9Sstevel@tonic-gate 				done = TRUE;
45007c478bd9Sstevel@tonic-gate 			else
45017c478bd9Sstevel@tonic-gate 				srv = send;
45027c478bd9Sstevel@tonic-gate 		}
45037c478bd9Sstevel@tonic-gate 	}
45047c478bd9Sstevel@tonic-gate 
45057c478bd9Sstevel@tonic-gate 	*auth = authpp;
45067c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeParam(&param);
45077c478bd9Sstevel@tonic-gate 	__s_api_release_config(cfg);
45087c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
45097c478bd9Sstevel@tonic-gate }
45107c478bd9Sstevel@tonic-gate 
45117c478bd9Sstevel@tonic-gate /*
45127c478bd9Sstevel@tonic-gate  * This routine is called when certain scenario occurs
45137c478bd9Sstevel@tonic-gate  * e.g.
45147c478bd9Sstevel@tonic-gate  * service == auto_home
45157c478bd9Sstevel@tonic-gate  * SSD = automount: ou = mytest,
45167c478bd9Sstevel@tonic-gate  * NS_LDAP_MAPATTRIBUTE= auto_home: automountMapName=AAA
45177c478bd9Sstevel@tonic-gate  * NS_LDAP_OBJECTCLASSMAP= auto_home:automountMap=MynisMap
45187c478bd9Sstevel@tonic-gate  * NS_LDAP_OBJECTCLASSMAP= auto_home:automount=MynisObject
45197c478bd9Sstevel@tonic-gate  *
45207c478bd9Sstevel@tonic-gate  * The automountMapName is prepended implicitely but is mapped
45217c478bd9Sstevel@tonic-gate  * to AAA. So dn could appers as
45227c478bd9Sstevel@tonic-gate  * dn: AAA=auto_home,ou=bar,dc=foo,dc=com
45237c478bd9Sstevel@tonic-gate  * dn: automountKey=user_01,AAA=auto_home,ou=bar,dc=foo,dc=com
45247c478bd9Sstevel@tonic-gate  * dn: automountKey=user_02,AAA=auto_home,ou=bar,dc=foo,dc=com
45257c478bd9Sstevel@tonic-gate  * in the directory.
45267c478bd9Sstevel@tonic-gate  * This function is called to covert the mapped attr back to
45277c478bd9Sstevel@tonic-gate  * orig attr when the entries are searched and returned
45287c478bd9Sstevel@tonic-gate  */
45297c478bd9Sstevel@tonic-gate 
45307c478bd9Sstevel@tonic-gate int
__s_api_convert_automountmapname(const char * service,char ** dn,ns_ldap_error_t ** errp)45317c478bd9Sstevel@tonic-gate __s_api_convert_automountmapname(const char *service, char **dn,
45327c478bd9Sstevel@tonic-gate 		ns_ldap_error_t **errp) {
45337c478bd9Sstevel@tonic-gate 
45347c478bd9Sstevel@tonic-gate 	char	**mapping = NULL;
45357c478bd9Sstevel@tonic-gate 	char	*mapped_attr = NULL;
45367c478bd9Sstevel@tonic-gate 	char	*automountmapname = "automountMapName";
45377c478bd9Sstevel@tonic-gate 	char	*buffer = NULL;
45387c478bd9Sstevel@tonic-gate 	int	rc = NS_LDAP_SUCCESS;
45397c478bd9Sstevel@tonic-gate 	char	errstr[MAXERROR];
45407c478bd9Sstevel@tonic-gate 
45417c478bd9Sstevel@tonic-gate 	/*
45427c478bd9Sstevel@tonic-gate 	 * dn is an input/out parameter, check it first
45437c478bd9Sstevel@tonic-gate 	 */
45447c478bd9Sstevel@tonic-gate 
45457c478bd9Sstevel@tonic-gate 	if (service == NULL || dn == NULL || *dn == NULL)
45467c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
45477c478bd9Sstevel@tonic-gate 
45487c478bd9Sstevel@tonic-gate 	/*
45497c478bd9Sstevel@tonic-gate 	 * Check to see if there is a mapped attribute for auto_xxx
45507c478bd9Sstevel@tonic-gate 	 */
45517c478bd9Sstevel@tonic-gate 
45527c478bd9Sstevel@tonic-gate 	mapping = __ns_ldap_getMappedAttributes(service, automountmapname);
45537c478bd9Sstevel@tonic-gate 
45547c478bd9Sstevel@tonic-gate 	/*
45557c478bd9Sstevel@tonic-gate 	 * if no mapped attribute for auto_xxx, try automount
45567c478bd9Sstevel@tonic-gate 	 */
45577c478bd9Sstevel@tonic-gate 
45587c478bd9Sstevel@tonic-gate 	if (mapping == NULL)
45597c478bd9Sstevel@tonic-gate 		mapping = __ns_ldap_getMappedAttributes(
45607c478bd9Sstevel@tonic-gate 			"automount", automountmapname);
45617c478bd9Sstevel@tonic-gate 
45627c478bd9Sstevel@tonic-gate 	/*
45637c478bd9Sstevel@tonic-gate 	 * if no mapped attribute is found, return SUCCESS (no op)
45647c478bd9Sstevel@tonic-gate 	 */
45657c478bd9Sstevel@tonic-gate 
45667c478bd9Sstevel@tonic-gate 	if (mapping == NULL)
45677c478bd9Sstevel@tonic-gate 		return (NS_LDAP_SUCCESS);
45687c478bd9Sstevel@tonic-gate 
45697c478bd9Sstevel@tonic-gate 	/*
45707c478bd9Sstevel@tonic-gate 	 * if the mapped attribute is found and attr is not empty,
45717c478bd9Sstevel@tonic-gate 	 * copy it
45727c478bd9Sstevel@tonic-gate 	 */
45737c478bd9Sstevel@tonic-gate 
45747c478bd9Sstevel@tonic-gate 	if (mapping[0] != NULL) {
45757c478bd9Sstevel@tonic-gate 		mapped_attr = strdup(mapping[0]);
45767c478bd9Sstevel@tonic-gate 		__s_api_free2dArray(mapping);
45777c478bd9Sstevel@tonic-gate 		if (mapped_attr == NULL) {
45787c478bd9Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
45797c478bd9Sstevel@tonic-gate 		}
45807c478bd9Sstevel@tonic-gate 	} else {
45817c478bd9Sstevel@tonic-gate 		__s_api_free2dArray(mapping);
45827c478bd9Sstevel@tonic-gate 
45837c478bd9Sstevel@tonic-gate 		(void) snprintf(errstr, (2 * MAXERROR),
45847c478bd9Sstevel@tonic-gate 			gettext(
45857c478bd9Sstevel@tonic-gate 			"Attribute nisMapName is mapped to an "
45867c478bd9Sstevel@tonic-gate 			"empty string.\n"));
45877c478bd9Sstevel@tonic-gate 
45887c478bd9Sstevel@tonic-gate 		MKERROR(LOG_ERR, *errp, NS_CONFIG_SYNTAX,
45897c478bd9Sstevel@tonic-gate 			strdup(errstr), NULL);
45907c478bd9Sstevel@tonic-gate 
45917c478bd9Sstevel@tonic-gate 		return (NS_LDAP_CONFIG);
45927c478bd9Sstevel@tonic-gate 	}
45937c478bd9Sstevel@tonic-gate 
45947c478bd9Sstevel@tonic-gate 	/*
45957c478bd9Sstevel@tonic-gate 	 * Locate the mapped attribute in the dn
45967c478bd9Sstevel@tonic-gate 	 * and replace it if it exists
45977c478bd9Sstevel@tonic-gate 	 */
45987c478bd9Sstevel@tonic-gate 
45997c478bd9Sstevel@tonic-gate 	rc = __s_api_replace_mapped_attr_in_dn(
46007c478bd9Sstevel@tonic-gate 		(const char *) automountmapname, (const char *) mapped_attr,
46017c478bd9Sstevel@tonic-gate 		(const char *) *dn, &buffer);
46027c478bd9Sstevel@tonic-gate 
46037c478bd9Sstevel@tonic-gate 	/* clean up */
46047c478bd9Sstevel@tonic-gate 
46057c478bd9Sstevel@tonic-gate 	free(mapped_attr);
46067c478bd9Sstevel@tonic-gate 
46077c478bd9Sstevel@tonic-gate 	/*
46087c478bd9Sstevel@tonic-gate 	 * If mapped attr is found(buffer != NULL)
46097c478bd9Sstevel@tonic-gate 	 *	a new dn is returned
46107c478bd9Sstevel@tonic-gate 	 * If no mapped attribute is in dn,
46117c478bd9Sstevel@tonic-gate 	 *	return NS_LDAP_SUCCESS (no op)
46127c478bd9Sstevel@tonic-gate 	 * If no memory,
46137c478bd9Sstevel@tonic-gate 	 *	return NS_LDAP_MEMORY (no op)
46147c478bd9Sstevel@tonic-gate 	 */
46157c478bd9Sstevel@tonic-gate 
46167c478bd9Sstevel@tonic-gate 	if (buffer != NULL) {
46177c478bd9Sstevel@tonic-gate 		free(*dn);
46187c478bd9Sstevel@tonic-gate 		*dn = buffer;
46197c478bd9Sstevel@tonic-gate 	}
46207c478bd9Sstevel@tonic-gate 
46217c478bd9Sstevel@tonic-gate 	return (rc);
46227c478bd9Sstevel@tonic-gate }
46237c478bd9Sstevel@tonic-gate 
46247c478bd9Sstevel@tonic-gate /*
46257c478bd9Sstevel@tonic-gate  * If the mapped attr is found in the dn,
46267c478bd9Sstevel@tonic-gate  * 	return NS_LDAP_SUCCESS and a new_dn.
46277c478bd9Sstevel@tonic-gate  * If no mapped attr is found,
46287c478bd9Sstevel@tonic-gate  * 	return NS_LDAP_SUCCESS and *new_dn == NULL
46297c478bd9Sstevel@tonic-gate  * If there is not enough memory,
46307c478bd9Sstevel@tonic-gate  * 	return NS_LDAP_MEMORY and *new_dn == NULL
46317c478bd9Sstevel@tonic-gate  */
46327c478bd9Sstevel@tonic-gate 
46337c478bd9Sstevel@tonic-gate int
__s_api_replace_mapped_attr_in_dn(const char * orig_attr,const char * mapped_attr,const char * dn,char ** new_dn)46347c478bd9Sstevel@tonic-gate __s_api_replace_mapped_attr_in_dn(
46357c478bd9Sstevel@tonic-gate 	const char *orig_attr, const char *mapped_attr,
46367c478bd9Sstevel@tonic-gate 	const char *dn, char **new_dn) {
46377c478bd9Sstevel@tonic-gate 
46387c478bd9Sstevel@tonic-gate 	char	**dnArray = NULL;
46397c478bd9Sstevel@tonic-gate 	char	*cur = NULL, *start = NULL;
46407c478bd9Sstevel@tonic-gate 	int	i = 0, found = 0;
46417c478bd9Sstevel@tonic-gate 	int	len = 0, orig_len = 0, mapped_len = 0;
46427c478bd9Sstevel@tonic-gate 	int	dn_len = 0, tmp_len = 0;
46437c478bd9Sstevel@tonic-gate 
46447c478bd9Sstevel@tonic-gate 	*new_dn = NULL;
46457c478bd9Sstevel@tonic-gate 
46467c478bd9Sstevel@tonic-gate 	/*
46477c478bd9Sstevel@tonic-gate 	 * seperate dn into individual componets
46487c478bd9Sstevel@tonic-gate 	 * e.g.
46497c478bd9Sstevel@tonic-gate 	 * "automountKey=user_01" , "automountMapName_test=auto_home", ...
46507c478bd9Sstevel@tonic-gate 	 */
46517c478bd9Sstevel@tonic-gate 	dnArray = ldap_explode_dn(dn, 0);
46527c478bd9Sstevel@tonic-gate 
46537c478bd9Sstevel@tonic-gate 	/*
46547c478bd9Sstevel@tonic-gate 	 * This will find "mapped attr=value" in dn.
46557c478bd9Sstevel@tonic-gate 	 * It won't find match if mapped attr appears
46567c478bd9Sstevel@tonic-gate 	 * in the value.
46577c478bd9Sstevel@tonic-gate 	 */
46587c478bd9Sstevel@tonic-gate 	for (i = 0; dnArray[i] != NULL; i++) {
46597c478bd9Sstevel@tonic-gate 		/*
46607c478bd9Sstevel@tonic-gate 		 * This function is called when reading from
46617c478bd9Sstevel@tonic-gate 		 * the directory so assume each component has "=".
46627c478bd9Sstevel@tonic-gate 		 * Any ill formatted dn should be rejected
46637c478bd9Sstevel@tonic-gate 		 * before adding to the directory
46647c478bd9Sstevel@tonic-gate 		 */
46657c478bd9Sstevel@tonic-gate 		cur = strchr(dnArray[i], '=');
46667c478bd9Sstevel@tonic-gate 		*cur = '\0';
46677c478bd9Sstevel@tonic-gate 		if (strcasecmp(mapped_attr, dnArray[i]) == 0)
46687c478bd9Sstevel@tonic-gate 			found = 1;
46697c478bd9Sstevel@tonic-gate 		*cur = '=';
46707c478bd9Sstevel@tonic-gate 		if (found) break;
46717c478bd9Sstevel@tonic-gate 	}
46727c478bd9Sstevel@tonic-gate 
46737c478bd9Sstevel@tonic-gate 	if (!found) {
46747c478bd9Sstevel@tonic-gate 		__s_api_free2dArray(dnArray);
46757c478bd9Sstevel@tonic-gate 		*new_dn = NULL;
46767c478bd9Sstevel@tonic-gate 		return (NS_LDAP_SUCCESS);
46777c478bd9Sstevel@tonic-gate 	}
46787c478bd9Sstevel@tonic-gate 	/*
46797c478bd9Sstevel@tonic-gate 	 * The new length is *dn length + (difference between
46807c478bd9Sstevel@tonic-gate 	 * orig attr and mapped attr) + 1 ;
46817c478bd9Sstevel@tonic-gate 	 * e.g.
46827c478bd9Sstevel@tonic-gate 	 * automountKey=aa,automountMapName_test=auto_home,dc=foo,dc=com
46837c478bd9Sstevel@tonic-gate 	 * ==>
46847c478bd9Sstevel@tonic-gate 	 * automountKey=aa,automountMapName=auto_home,dc=foo,dc=com
46857c478bd9Sstevel@tonic-gate 	 */
46867c478bd9Sstevel@tonic-gate 	mapped_len = strlen(mapped_attr);
46877c478bd9Sstevel@tonic-gate 	orig_len = strlen(orig_attr);
46887c478bd9Sstevel@tonic-gate 	dn_len = strlen(dn);
46897c478bd9Sstevel@tonic-gate 	len = dn_len + orig_len - mapped_len + 1;
46907c478bd9Sstevel@tonic-gate 	*new_dn = (char *)calloc(1, len);
46917c478bd9Sstevel@tonic-gate 	if (*new_dn == NULL) {
46927c478bd9Sstevel@tonic-gate 		__s_api_free2dArray(dnArray);
46937c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
46947c478bd9Sstevel@tonic-gate 	}
46957c478bd9Sstevel@tonic-gate 
46967c478bd9Sstevel@tonic-gate 	/*
46977c478bd9Sstevel@tonic-gate 	 * Locate the mapped attr in the dn.
46987c478bd9Sstevel@tonic-gate 	 * Use dnArray[i] instead of mapped_attr
46997c478bd9Sstevel@tonic-gate 	 * because mapped_attr could appear in
47007c478bd9Sstevel@tonic-gate 	 * the value
47017c478bd9Sstevel@tonic-gate 	 */
47027c478bd9Sstevel@tonic-gate 
47037c478bd9Sstevel@tonic-gate 	cur = strstr(dn, dnArray[i]);
47047c478bd9Sstevel@tonic-gate 	__s_api_free2dArray(dnArray);
47057c478bd9Sstevel@tonic-gate 	/* copy the portion before mapped attr in dn  */
47067c478bd9Sstevel@tonic-gate 	start = *new_dn;
47077c478bd9Sstevel@tonic-gate 	tmp_len = cur - dn;
47087c478bd9Sstevel@tonic-gate 	(void) memcpy((void *) start, (const void*) dn, tmp_len);
47097c478bd9Sstevel@tonic-gate 
47107c478bd9Sstevel@tonic-gate 	/*
47117c478bd9Sstevel@tonic-gate 	 * Copy the orig_attr. e.g. automountMapName
47127c478bd9Sstevel@tonic-gate 	 * This replaces mapped attr with orig attr
47137c478bd9Sstevel@tonic-gate 	 */
47147c478bd9Sstevel@tonic-gate 	start = start + (cur - dn); /* move cursor in buffer */
47157c478bd9Sstevel@tonic-gate 	(void) memcpy((void *) start, (const void*) orig_attr, orig_len);
47167c478bd9Sstevel@tonic-gate 
47177c478bd9Sstevel@tonic-gate 	/*
47187c478bd9Sstevel@tonic-gate 	 * Copy the portion after mapped attr in dn
47197c478bd9Sstevel@tonic-gate 	 */
47207c478bd9Sstevel@tonic-gate 	cur = cur + mapped_len; /* move cursor in  dn  */
47217c478bd9Sstevel@tonic-gate 	start = start + orig_len; /* move cursor in buffer */
47227c478bd9Sstevel@tonic-gate 	(void) strcpy(start, cur);
47237c478bd9Sstevel@tonic-gate 
47247c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
47257c478bd9Sstevel@tonic-gate }
47267c478bd9Sstevel@tonic-gate 
47277c478bd9Sstevel@tonic-gate /*
47287c478bd9Sstevel@tonic-gate  * Validate Filter functions
47297c478bd9Sstevel@tonic-gate  */
47307c478bd9Sstevel@tonic-gate 
47317c478bd9Sstevel@tonic-gate /* ***** Start of modified libldap.so.5 filter parser ***** */
47327c478bd9Sstevel@tonic-gate 
47337c478bd9Sstevel@tonic-gate /* filter parsing routine forward references */
47347c478bd9Sstevel@tonic-gate static int adj_filter_list(char *str);
47357c478bd9Sstevel@tonic-gate static int adj_simple_filter(char *str);
47367c478bd9Sstevel@tonic-gate static int unescape_filterval(char *val);
47377c478bd9Sstevel@tonic-gate static int hexchar2int(char c);
47387c478bd9Sstevel@tonic-gate static int adj_substring_filter(char *val);
47397c478bd9Sstevel@tonic-gate 
47407c478bd9Sstevel@tonic-gate 
47417c478bd9Sstevel@tonic-gate /*
47427c478bd9Sstevel@tonic-gate  * assumes string manipulation is in-line
47437c478bd9Sstevel@tonic-gate  * and all strings are sufficient in size
47447c478bd9Sstevel@tonic-gate  * return value is the position after 'c'
47457c478bd9Sstevel@tonic-gate  */
47467c478bd9Sstevel@tonic-gate 
47477c478bd9Sstevel@tonic-gate static char *
resync_str(char * str,char * next,char c)47487c478bd9Sstevel@tonic-gate resync_str(char *str, char *next, char c)
47497c478bd9Sstevel@tonic-gate {
47507c478bd9Sstevel@tonic-gate 	char	*ret;
47517c478bd9Sstevel@tonic-gate 
47527c478bd9Sstevel@tonic-gate 	ret = str + strlen(str);
47537c478bd9Sstevel@tonic-gate 	*next = c;
47547c478bd9Sstevel@tonic-gate 	if (ret == next)
47557c478bd9Sstevel@tonic-gate 		return (ret);
47567c478bd9Sstevel@tonic-gate 	(void) strcat(str, next);
47577c478bd9Sstevel@tonic-gate 	return (ret);
47587c478bd9Sstevel@tonic-gate }
47597c478bd9Sstevel@tonic-gate 
47607c478bd9Sstevel@tonic-gate static char *
find_right_paren(char * s)47617c478bd9Sstevel@tonic-gate find_right_paren(char *s)
47627c478bd9Sstevel@tonic-gate {
47637c478bd9Sstevel@tonic-gate 	int	balance, escape;
47647c478bd9Sstevel@tonic-gate 
47657c478bd9Sstevel@tonic-gate 	balance = 1;
47667c478bd9Sstevel@tonic-gate 	escape = 0;
47677c478bd9Sstevel@tonic-gate 	while (*s && balance) {
47687c478bd9Sstevel@tonic-gate 		if (escape == 0) {
47697c478bd9Sstevel@tonic-gate 			if (*s == '(')
47707c478bd9Sstevel@tonic-gate 				balance++;
47717c478bd9Sstevel@tonic-gate 			else if (*s == ')')
47727c478bd9Sstevel@tonic-gate 				balance--;
47737c478bd9Sstevel@tonic-gate 		}
47747c478bd9Sstevel@tonic-gate 		if (*s == '\\' && ! escape)
47757c478bd9Sstevel@tonic-gate 			escape = 1;
47767c478bd9Sstevel@tonic-gate 		else
47777c478bd9Sstevel@tonic-gate 			escape = 0;
47787c478bd9Sstevel@tonic-gate 		if (balance)
47797c478bd9Sstevel@tonic-gate 			s++;
47807c478bd9Sstevel@tonic-gate 	}
47817c478bd9Sstevel@tonic-gate 
47827c478bd9Sstevel@tonic-gate 	return (*s ? s : NULL);
47837c478bd9Sstevel@tonic-gate }
47847c478bd9Sstevel@tonic-gate 
47857c478bd9Sstevel@tonic-gate static char *
adj_complex_filter(char * str)47867c478bd9Sstevel@tonic-gate adj_complex_filter(char	*str)
47877c478bd9Sstevel@tonic-gate {
47887c478bd9Sstevel@tonic-gate 	char	*next;
47897c478bd9Sstevel@tonic-gate 
47907c478bd9Sstevel@tonic-gate 	/*
47917c478bd9Sstevel@tonic-gate 	 * We have (x(filter)...) with str sitting on
47927c478bd9Sstevel@tonic-gate 	 * the x.  We have to find the paren matching
47937c478bd9Sstevel@tonic-gate 	 * the one before the x and put the intervening
47947c478bd9Sstevel@tonic-gate 	 * filters by calling adj_filter_list().
47957c478bd9Sstevel@tonic-gate 	 */
47967c478bd9Sstevel@tonic-gate 
47977c478bd9Sstevel@tonic-gate 	str++;
47987c478bd9Sstevel@tonic-gate 	if ((next = find_right_paren(str)) == NULL)
47997c478bd9Sstevel@tonic-gate 		return (NULL);
48007c478bd9Sstevel@tonic-gate 
48017c478bd9Sstevel@tonic-gate 	*next = '\0';
48027c478bd9Sstevel@tonic-gate 	if (adj_filter_list(str) == -1)
48037c478bd9Sstevel@tonic-gate 		return (NULL);
48047c478bd9Sstevel@tonic-gate 	next = resync_str(str, next, ')');
48057c478bd9Sstevel@tonic-gate 	next++;
48067c478bd9Sstevel@tonic-gate 
48077c478bd9Sstevel@tonic-gate 	return (next);
48087c478bd9Sstevel@tonic-gate }
48097c478bd9Sstevel@tonic-gate 
48107c478bd9Sstevel@tonic-gate static int
adj_filter(char * str)48117c478bd9Sstevel@tonic-gate adj_filter(char *str)
48127c478bd9Sstevel@tonic-gate {
48137c478bd9Sstevel@tonic-gate 	char	*next;
48147c478bd9Sstevel@tonic-gate 	int	parens, balance, escape;
48157c478bd9Sstevel@tonic-gate 	char	*np, *cp,  *dp;
48167c478bd9Sstevel@tonic-gate 
48177c478bd9Sstevel@tonic-gate 	parens = 0;
48187c478bd9Sstevel@tonic-gate 	while (*str) {
48197c478bd9Sstevel@tonic-gate 		switch (*str) {
48207c478bd9Sstevel@tonic-gate 		case '(':
48217c478bd9Sstevel@tonic-gate 			str++;
48227c478bd9Sstevel@tonic-gate 			parens++;
48237c478bd9Sstevel@tonic-gate 			switch (*str) {
48247c478bd9Sstevel@tonic-gate 			case '&':
48257c478bd9Sstevel@tonic-gate 				if ((str = adj_complex_filter(str)) == NULL)
48267c478bd9Sstevel@tonic-gate 					return (-1);
48277c478bd9Sstevel@tonic-gate 
48287c478bd9Sstevel@tonic-gate 				parens--;
48297c478bd9Sstevel@tonic-gate 				break;
48307c478bd9Sstevel@tonic-gate 
48317c478bd9Sstevel@tonic-gate 			case '|':
48327c478bd9Sstevel@tonic-gate 				if ((str = adj_complex_filter(str)) == NULL)
48337c478bd9Sstevel@tonic-gate 					return (-1);
48347c478bd9Sstevel@tonic-gate 
48357c478bd9Sstevel@tonic-gate 				parens--;
48367c478bd9Sstevel@tonic-gate 				break;
48377c478bd9Sstevel@tonic-gate 
48387c478bd9Sstevel@tonic-gate 			case '!':
48397c478bd9Sstevel@tonic-gate 				if ((str = adj_complex_filter(str)) == NULL)
48407c478bd9Sstevel@tonic-gate 					return (-1);
48417c478bd9Sstevel@tonic-gate 
48427c478bd9Sstevel@tonic-gate 				parens--;
48437c478bd9Sstevel@tonic-gate 				break;
48447c478bd9Sstevel@tonic-gate 
48457c478bd9Sstevel@tonic-gate 			case '(':
48467c478bd9Sstevel@tonic-gate 				/* illegal ((case - generated by conversion */
48477c478bd9Sstevel@tonic-gate 
48487c478bd9Sstevel@tonic-gate 				/* find missing close) */
48497c478bd9Sstevel@tonic-gate 				np = find_right_paren(str+1);
48507c478bd9Sstevel@tonic-gate 
48517c478bd9Sstevel@tonic-gate 				/* error if not found */
48527c478bd9Sstevel@tonic-gate 				if (np == NULL)
48537c478bd9Sstevel@tonic-gate 					return (-1);
48547c478bd9Sstevel@tonic-gate 
48557c478bd9Sstevel@tonic-gate 				/* remove redundant (and) */
48567c478bd9Sstevel@tonic-gate 				for (dp = str, cp = str+1; cp < np; ) {
48577c478bd9Sstevel@tonic-gate 					*dp++ = *cp++;
48587c478bd9Sstevel@tonic-gate 				}
48597c478bd9Sstevel@tonic-gate 				cp++;
48607c478bd9Sstevel@tonic-gate 				while (*cp)
48617c478bd9Sstevel@tonic-gate 					*dp++ = *cp++;
48627c478bd9Sstevel@tonic-gate 				*dp = '\0';
48637c478bd9Sstevel@tonic-gate 
48647c478bd9Sstevel@tonic-gate 				/* re-start test at original ( */
48657c478bd9Sstevel@tonic-gate 				parens--;
48667c478bd9Sstevel@tonic-gate 				str--;
48677c478bd9Sstevel@tonic-gate 				break;
48687c478bd9Sstevel@tonic-gate 
48697c478bd9Sstevel@tonic-gate 			default:
48707c478bd9Sstevel@tonic-gate 				balance = 1;
48717c478bd9Sstevel@tonic-gate 				escape = 0;
48727c478bd9Sstevel@tonic-gate 				next = str;
48737c478bd9Sstevel@tonic-gate 				while (*next && balance) {
48747c478bd9Sstevel@tonic-gate 					if (escape == 0) {
48757c478bd9Sstevel@tonic-gate 						if (*next == '(')
48767c478bd9Sstevel@tonic-gate 							balance++;
48777c478bd9Sstevel@tonic-gate 						else if (*next == ')')
48787c478bd9Sstevel@tonic-gate 							balance--;
48797c478bd9Sstevel@tonic-gate 					}
48807c478bd9Sstevel@tonic-gate 					if (*next == '\\' && ! escape)
48817c478bd9Sstevel@tonic-gate 						escape = 1;
48827c478bd9Sstevel@tonic-gate 					else
48837c478bd9Sstevel@tonic-gate 						escape = 0;
48847c478bd9Sstevel@tonic-gate 					if (balance)
48857c478bd9Sstevel@tonic-gate 						next++;
48867c478bd9Sstevel@tonic-gate 				}
48877c478bd9Sstevel@tonic-gate 				if (balance != 0)
48887c478bd9Sstevel@tonic-gate 					return (-1);
48897c478bd9Sstevel@tonic-gate 
48907c478bd9Sstevel@tonic-gate 				*next = '\0';
48917c478bd9Sstevel@tonic-gate 				if (adj_simple_filter(str) == -1) {
48927c478bd9Sstevel@tonic-gate 					return (-1);
48937c478bd9Sstevel@tonic-gate 				}
48947c478bd9Sstevel@tonic-gate 				next = resync_str(str, next, ')');
48957c478bd9Sstevel@tonic-gate 				next++;
48967c478bd9Sstevel@tonic-gate 				str = next;
48977c478bd9Sstevel@tonic-gate 				parens--;
48987c478bd9Sstevel@tonic-gate 				break;
48997c478bd9Sstevel@tonic-gate 			}
49007c478bd9Sstevel@tonic-gate 			break;
49017c478bd9Sstevel@tonic-gate 
49027c478bd9Sstevel@tonic-gate 		case ')':
49037c478bd9Sstevel@tonic-gate 			str++;
49047c478bd9Sstevel@tonic-gate 			parens--;
49057c478bd9Sstevel@tonic-gate 			break;
49067c478bd9Sstevel@tonic-gate 
49077c478bd9Sstevel@tonic-gate 		case ' ':
49087c478bd9Sstevel@tonic-gate 			str++;
49097c478bd9Sstevel@tonic-gate 			break;
49107c478bd9Sstevel@tonic-gate 
49117c478bd9Sstevel@tonic-gate 		default:	/* assume it's a simple type=value filter */
49127c478bd9Sstevel@tonic-gate 			next = strchr(str, '\0');
49137c478bd9Sstevel@tonic-gate 			if (adj_simple_filter(str) == -1) {
49147c478bd9Sstevel@tonic-gate 				return (-1);
49157c478bd9Sstevel@tonic-gate 			}
49167c478bd9Sstevel@tonic-gate 			str = next;
49177c478bd9Sstevel@tonic-gate 			break;
49187c478bd9Sstevel@tonic-gate 		}
49197c478bd9Sstevel@tonic-gate 	}
49207c478bd9Sstevel@tonic-gate 
49217c478bd9Sstevel@tonic-gate 	return (parens ? -1 : 0);
49227c478bd9Sstevel@tonic-gate }
49237c478bd9Sstevel@tonic-gate 
49247c478bd9Sstevel@tonic-gate 
49257c478bd9Sstevel@tonic-gate /*
49267c478bd9Sstevel@tonic-gate  * Put a list of filters like this "(filter1)(filter2)..."
49277c478bd9Sstevel@tonic-gate  */
49287c478bd9Sstevel@tonic-gate 
49297c478bd9Sstevel@tonic-gate static int
adj_filter_list(char * str)49307c478bd9Sstevel@tonic-gate adj_filter_list(char *str)
49317c478bd9Sstevel@tonic-gate {
49327c478bd9Sstevel@tonic-gate 	char	*next;
49337c478bd9Sstevel@tonic-gate 	char	save;
49347c478bd9Sstevel@tonic-gate 
49357c478bd9Sstevel@tonic-gate 	while (*str) {
49367c478bd9Sstevel@tonic-gate 		while (*str && isspace(*str))
49377c478bd9Sstevel@tonic-gate 			str++;
49387c478bd9Sstevel@tonic-gate 		if (*str == '\0')
49397c478bd9Sstevel@tonic-gate 			break;
49407c478bd9Sstevel@tonic-gate 
49417c478bd9Sstevel@tonic-gate 		if ((next = find_right_paren(str + 1)) == NULL)
49427c478bd9Sstevel@tonic-gate 			return (-1);
49437c478bd9Sstevel@tonic-gate 		save = *++next;
49447c478bd9Sstevel@tonic-gate 
49457c478bd9Sstevel@tonic-gate 		/* now we have "(filter)" with str pointing to it */
49467c478bd9Sstevel@tonic-gate 		*next = '\0';
49477c478bd9Sstevel@tonic-gate 		if (adj_filter(str) == -1)
49487c478bd9Sstevel@tonic-gate 			return (-1);
49497c478bd9Sstevel@tonic-gate 		next = resync_str(str, next, save);
49507c478bd9Sstevel@tonic-gate 
49517c478bd9Sstevel@tonic-gate 		str = next;
49527c478bd9Sstevel@tonic-gate 	}
49537c478bd9Sstevel@tonic-gate 
49547c478bd9Sstevel@tonic-gate 	return (0);
49557c478bd9Sstevel@tonic-gate }
49567c478bd9Sstevel@tonic-gate 
49577c478bd9Sstevel@tonic-gate 
49587c478bd9Sstevel@tonic-gate /*
49597c478bd9Sstevel@tonic-gate  * is_valid_attr - returns 1 if a is a syntactically valid left-hand side
49607c478bd9Sstevel@tonic-gate  * of a filter expression, 0 otherwise.  A valid string may contain only
49617c478bd9Sstevel@tonic-gate  * letters, numbers, hyphens, semi-colons, colons and periods. examples:
49627c478bd9Sstevel@tonic-gate  *	cn
49637c478bd9Sstevel@tonic-gate  *	cn;lang-fr
49647c478bd9Sstevel@tonic-gate  *	1.2.3.4;binary;dynamic
49657c478bd9Sstevel@tonic-gate  *	mail;dynamic
49667c478bd9Sstevel@tonic-gate  *	cn:dn:1.2.3.4
49677c478bd9Sstevel@tonic-gate  *
49687c478bd9Sstevel@tonic-gate  * For compatibility with older servers, we also allow underscores in
49697c478bd9Sstevel@tonic-gate  * attribute types, even through they are not allowed by the LDAPv3 RFCs.
49707c478bd9Sstevel@tonic-gate  */
49717c478bd9Sstevel@tonic-gate static int
is_valid_attr(char * a)49727c478bd9Sstevel@tonic-gate is_valid_attr(char *a)
49737c478bd9Sstevel@tonic-gate {
49747c478bd9Sstevel@tonic-gate 	for (; *a; a++) {
49757c478bd9Sstevel@tonic-gate 		if (!isascii(*a)) {
49767c478bd9Sstevel@tonic-gate 			return (0);
49777c478bd9Sstevel@tonic-gate 		} else if (!isalnum(*a)) {
49787c478bd9Sstevel@tonic-gate 			switch (*a) {
49797c478bd9Sstevel@tonic-gate 			case '-':
49807c478bd9Sstevel@tonic-gate 			case '.':
49817c478bd9Sstevel@tonic-gate 			case ';':
49827c478bd9Sstevel@tonic-gate 			case ':':
49837c478bd9Sstevel@tonic-gate 			case '_':
49847c478bd9Sstevel@tonic-gate 				break; /* valid */
49857c478bd9Sstevel@tonic-gate 			default:
49867c478bd9Sstevel@tonic-gate 				return (0);
49877c478bd9Sstevel@tonic-gate 			}
49887c478bd9Sstevel@tonic-gate 		}
49897c478bd9Sstevel@tonic-gate 	}
49907c478bd9Sstevel@tonic-gate 	return (1);
49917c478bd9Sstevel@tonic-gate }
49927c478bd9Sstevel@tonic-gate 
49937c478bd9Sstevel@tonic-gate static char *
find_star(char * s)49947c478bd9Sstevel@tonic-gate find_star(char *s)
49957c478bd9Sstevel@tonic-gate {
49967c478bd9Sstevel@tonic-gate 	for (; *s; ++s) {
49977c478bd9Sstevel@tonic-gate 		switch (*s) {
49987c478bd9Sstevel@tonic-gate 		case '*':
49997c478bd9Sstevel@tonic-gate 			return (s);
50007c478bd9Sstevel@tonic-gate 		case '\\':
50017c478bd9Sstevel@tonic-gate 			++s;
50027c478bd9Sstevel@tonic-gate 			if (hexchar2int(s[0]) >= 0 && hexchar2int(s[1]) >= 0)
50037c478bd9Sstevel@tonic-gate 				++s;
50047c478bd9Sstevel@tonic-gate 		default:
50057c478bd9Sstevel@tonic-gate 			break;
50067c478bd9Sstevel@tonic-gate 		}
50077c478bd9Sstevel@tonic-gate 	}
50087c478bd9Sstevel@tonic-gate 	return (NULL);
50097c478bd9Sstevel@tonic-gate }
50107c478bd9Sstevel@tonic-gate 
50117c478bd9Sstevel@tonic-gate static int
adj_simple_filter(char * str)50127c478bd9Sstevel@tonic-gate adj_simple_filter(char *str)
50137c478bd9Sstevel@tonic-gate {
50147c478bd9Sstevel@tonic-gate 	char		*s, *s2, *s3, filterop;
50157c478bd9Sstevel@tonic-gate 	char		*value;
50167c478bd9Sstevel@tonic-gate 	int		ftype = 0;
50177c478bd9Sstevel@tonic-gate 	int		rc;
50187c478bd9Sstevel@tonic-gate 
50197c478bd9Sstevel@tonic-gate 	rc = -1;	/* pessimistic */
50207c478bd9Sstevel@tonic-gate 
50217c478bd9Sstevel@tonic-gate 	if ((str = strdup(str)) == NULL) {
50227c478bd9Sstevel@tonic-gate 		return (rc);
50237c478bd9Sstevel@tonic-gate 	}
50247c478bd9Sstevel@tonic-gate 
50257c478bd9Sstevel@tonic-gate 	if ((s = strchr(str, '=')) == NULL) {
50267c478bd9Sstevel@tonic-gate 		goto free_and_return;
50277c478bd9Sstevel@tonic-gate 	}
50287c478bd9Sstevel@tonic-gate 	value = s + 1;
50297c478bd9Sstevel@tonic-gate 	*s-- = '\0';
50307c478bd9Sstevel@tonic-gate 	filterop = *s;
50317c478bd9Sstevel@tonic-gate 	if (filterop == '<' || filterop == '>' || filterop == '~' ||
50327c478bd9Sstevel@tonic-gate 	    filterop == ':') {
50337c478bd9Sstevel@tonic-gate 		*s = '\0';
50347c478bd9Sstevel@tonic-gate 	}
50357c478bd9Sstevel@tonic-gate 
50367c478bd9Sstevel@tonic-gate 	if (! is_valid_attr(str)) {
50377c478bd9Sstevel@tonic-gate 		goto free_and_return;
50387c478bd9Sstevel@tonic-gate 	}
50397c478bd9Sstevel@tonic-gate 
50407c478bd9Sstevel@tonic-gate 	switch (filterop) {
50417c478bd9Sstevel@tonic-gate 	case '<': /* LDAP_FILTER_LE */
50427c478bd9Sstevel@tonic-gate 	case '>': /* LDAP_FILTER_GE */
50437c478bd9Sstevel@tonic-gate 	case '~': /* LDAP_FILTER_APPROX */
50447c478bd9Sstevel@tonic-gate 		break;
50457c478bd9Sstevel@tonic-gate 	case ':':	/* extended filter - v3 only */
50467c478bd9Sstevel@tonic-gate 		/*
50477c478bd9Sstevel@tonic-gate 		 * extended filter looks like this:
50487c478bd9Sstevel@tonic-gate 		 *
50497c478bd9Sstevel@tonic-gate 		 *	[type][':dn'][':'oid]':='value
50507c478bd9Sstevel@tonic-gate 		 *
50517c478bd9Sstevel@tonic-gate 		 * where one of type or :oid is required.
50527c478bd9Sstevel@tonic-gate 		 *
50537c478bd9Sstevel@tonic-gate 		 */
50547c478bd9Sstevel@tonic-gate 		s2 = s3 = NULL;
50557c478bd9Sstevel@tonic-gate 		if ((s2 = strrchr(str, ':')) == NULL) {
50567c478bd9Sstevel@tonic-gate 			goto free_and_return;
50577c478bd9Sstevel@tonic-gate 		}
50587c478bd9Sstevel@tonic-gate 		if (strcasecmp(s2, ":dn") == 0) {
50597c478bd9Sstevel@tonic-gate 			*s2 = '\0';
50607c478bd9Sstevel@tonic-gate 		} else {
50617c478bd9Sstevel@tonic-gate 			*s2 = '\0';
50627c478bd9Sstevel@tonic-gate 			if ((s3 = strrchr(str, ':')) != NULL) {
50637c478bd9Sstevel@tonic-gate 				if (strcasecmp(s3, ":dn") != 0) {
50647c478bd9Sstevel@tonic-gate 					goto free_and_return;
50657c478bd9Sstevel@tonic-gate 				}
50667c478bd9Sstevel@tonic-gate 				*s3 = '\0';
50677c478bd9Sstevel@tonic-gate 			}
50687c478bd9Sstevel@tonic-gate 		}
50697c478bd9Sstevel@tonic-gate 		if (unescape_filterval(value) < 0) {
50707c478bd9Sstevel@tonic-gate 			goto free_and_return;
50717c478bd9Sstevel@tonic-gate 		}
50727c478bd9Sstevel@tonic-gate 		rc = 0;
50737c478bd9Sstevel@tonic-gate 		goto free_and_return;
50747c478bd9Sstevel@tonic-gate 		/* break; */
50757c478bd9Sstevel@tonic-gate 	default:
50767c478bd9Sstevel@tonic-gate 		if (find_star(value) == NULL) {
50777c478bd9Sstevel@tonic-gate 			ftype = 0; /* LDAP_FILTER_EQUALITY */
50787c478bd9Sstevel@tonic-gate 		} else if (strcmp(value, "*") == 0) {
50797c478bd9Sstevel@tonic-gate 			ftype = 1; /* LDAP_FILTER_PRESENT */
50807c478bd9Sstevel@tonic-gate 		} else {
50817c478bd9Sstevel@tonic-gate 			rc = adj_substring_filter(value);
50827c478bd9Sstevel@tonic-gate 			goto free_and_return;
50837c478bd9Sstevel@tonic-gate 		}
50847c478bd9Sstevel@tonic-gate 		break;
50857c478bd9Sstevel@tonic-gate 	}
50867c478bd9Sstevel@tonic-gate 
50877c478bd9Sstevel@tonic-gate 	if (ftype != 0) {	/* == LDAP_FILTER_PRESENT */
50887c478bd9Sstevel@tonic-gate 		rc = 0;
50897c478bd9Sstevel@tonic-gate 	} else if (unescape_filterval(value) >= 0) {
50907c478bd9Sstevel@tonic-gate 		rc = 0;
50917c478bd9Sstevel@tonic-gate 	}
50927c478bd9Sstevel@tonic-gate 	if (rc != -1) {
50937c478bd9Sstevel@tonic-gate 		rc = 0;
50947c478bd9Sstevel@tonic-gate 	}
50957c478bd9Sstevel@tonic-gate 
50967c478bd9Sstevel@tonic-gate free_and_return:
50977c478bd9Sstevel@tonic-gate 	free(str);
50987c478bd9Sstevel@tonic-gate 	return (rc);
50997c478bd9Sstevel@tonic-gate }
51007c478bd9Sstevel@tonic-gate 
51017c478bd9Sstevel@tonic-gate 
51027c478bd9Sstevel@tonic-gate /*
51037c478bd9Sstevel@tonic-gate  * Check in place both LDAPv2 (RFC-1960) and LDAPv3 (hexadecimal) escape
51047c478bd9Sstevel@tonic-gate  * sequences within the null-terminated string 'val'.
51057c478bd9Sstevel@tonic-gate  *
51067c478bd9Sstevel@tonic-gate  * If 'val' contains invalid escape sequences we return -1.
51077c478bd9Sstevel@tonic-gate  * Otherwise return 1
51087c478bd9Sstevel@tonic-gate  */
51097c478bd9Sstevel@tonic-gate static int
unescape_filterval(char * val)51107c478bd9Sstevel@tonic-gate unescape_filterval(char *val)
51117c478bd9Sstevel@tonic-gate {
51127c478bd9Sstevel@tonic-gate 	int	escape, firstdigit;
51137c478bd9Sstevel@tonic-gate 	char	*s;
51147c478bd9Sstevel@tonic-gate 
51157c478bd9Sstevel@tonic-gate 	firstdigit = 0;
51167c478bd9Sstevel@tonic-gate 	escape = 0;
51177c478bd9Sstevel@tonic-gate 	for (s = val; *s; s++) {
51187c478bd9Sstevel@tonic-gate 		if (escape) {
51197c478bd9Sstevel@tonic-gate 			/*
51207c478bd9Sstevel@tonic-gate 			 * first try LDAPv3 escape (hexadecimal) sequence
51217c478bd9Sstevel@tonic-gate 			 */
51227c478bd9Sstevel@tonic-gate 			if (hexchar2int(*s) < 0) {
51237c478bd9Sstevel@tonic-gate 				if (firstdigit) {
51247c478bd9Sstevel@tonic-gate 					/*
51257c478bd9Sstevel@tonic-gate 					 * LDAPv2 (RFC1960) escape sequence
51267c478bd9Sstevel@tonic-gate 					 */
51277c478bd9Sstevel@tonic-gate 					escape = 0;
51287c478bd9Sstevel@tonic-gate 				} else {
51297c478bd9Sstevel@tonic-gate 					return (-1);
51307c478bd9Sstevel@tonic-gate 				}
51317c478bd9Sstevel@tonic-gate 			}
51327c478bd9Sstevel@tonic-gate 			if (firstdigit) {
51337c478bd9Sstevel@tonic-gate 				firstdigit = 0;
51347c478bd9Sstevel@tonic-gate 			} else {
51357c478bd9Sstevel@tonic-gate 				escape = 0;
51367c478bd9Sstevel@tonic-gate 			}
51377c478bd9Sstevel@tonic-gate 
51387c478bd9Sstevel@tonic-gate 		} else if (*s != '\\') {
51397c478bd9Sstevel@tonic-gate 			escape = 0;
51407c478bd9Sstevel@tonic-gate 
51417c478bd9Sstevel@tonic-gate 		} else {
51427c478bd9Sstevel@tonic-gate 			escape = 1;
51437c478bd9Sstevel@tonic-gate 			firstdigit = 1;
51447c478bd9Sstevel@tonic-gate 		}
51457c478bd9Sstevel@tonic-gate 	}
51467c478bd9Sstevel@tonic-gate 
51477c478bd9Sstevel@tonic-gate 	return (1);
51487c478bd9Sstevel@tonic-gate }
51497c478bd9Sstevel@tonic-gate 
51507c478bd9Sstevel@tonic-gate 
51517c478bd9Sstevel@tonic-gate /*
51527c478bd9Sstevel@tonic-gate  * convert character 'c' that represents a hexadecimal digit to an integer.
51537c478bd9Sstevel@tonic-gate  * if 'c' is not a hexidecimal digit [0-9A-Fa-f], -1 is returned.
51547c478bd9Sstevel@tonic-gate  * otherwise the converted value is returned.
51557c478bd9Sstevel@tonic-gate  */
51567c478bd9Sstevel@tonic-gate static int
hexchar2int(char c)51577c478bd9Sstevel@tonic-gate hexchar2int(char c)
51587c478bd9Sstevel@tonic-gate {
51597c478bd9Sstevel@tonic-gate 	if (c >= '0' && c <= '9') {
51607c478bd9Sstevel@tonic-gate 		return (c - '0');
51617c478bd9Sstevel@tonic-gate 	}
51627c478bd9Sstevel@tonic-gate 	if (c >= 'A' && c <= 'F') {
51637c478bd9Sstevel@tonic-gate 		return (c - 'A' + 10);
51647c478bd9Sstevel@tonic-gate 	}
51657c478bd9Sstevel@tonic-gate 	if (c >= 'a' && c <= 'f') {
51667c478bd9Sstevel@tonic-gate 		return (c - 'a' + 10);
51677c478bd9Sstevel@tonic-gate 	}
51687c478bd9Sstevel@tonic-gate 	return (-1);
51697c478bd9Sstevel@tonic-gate }
51707c478bd9Sstevel@tonic-gate 
51717c478bd9Sstevel@tonic-gate static int
adj_substring_filter(char * val)51727c478bd9Sstevel@tonic-gate adj_substring_filter(char *val)
51737c478bd9Sstevel@tonic-gate {
51747c478bd9Sstevel@tonic-gate 	char		*nextstar;
51757c478bd9Sstevel@tonic-gate 
51767c478bd9Sstevel@tonic-gate 	for (; val != NULL; val = nextstar) {
51777c478bd9Sstevel@tonic-gate 		if ((nextstar = find_star(val)) != NULL) {
51787c478bd9Sstevel@tonic-gate 			*nextstar++ = '\0';
51797c478bd9Sstevel@tonic-gate 		}
51807c478bd9Sstevel@tonic-gate 
51817c478bd9Sstevel@tonic-gate 		if (*val != '\0') {
51827c478bd9Sstevel@tonic-gate 			if (unescape_filterval(val) < 0) {
51837c478bd9Sstevel@tonic-gate 				return (-1);
51847c478bd9Sstevel@tonic-gate 			}
51857c478bd9Sstevel@tonic-gate 		}
51867c478bd9Sstevel@tonic-gate 	}
51877c478bd9Sstevel@tonic-gate 
51887c478bd9Sstevel@tonic-gate 	return (0);
51897c478bd9Sstevel@tonic-gate }
51907c478bd9Sstevel@tonic-gate 
51917c478bd9Sstevel@tonic-gate /* ***** End of modified libldap.so.5 filter parser ***** */
51927c478bd9Sstevel@tonic-gate 
51937c478bd9Sstevel@tonic-gate 
51947c478bd9Sstevel@tonic-gate /*
51957c478bd9Sstevel@tonic-gate  * Walk filter, remove redundant parentheses in-line
51967c478bd9Sstevel@tonic-gate  * verify that the filter is reasonable
51977c478bd9Sstevel@tonic-gate  */
51987c478bd9Sstevel@tonic-gate static int
validate_filter(ns_ldap_cookie_t * cookie)51997c478bd9Sstevel@tonic-gate validate_filter(ns_ldap_cookie_t *cookie)
52007c478bd9Sstevel@tonic-gate {
52017c478bd9Sstevel@tonic-gate 	char			*filter = cookie->filter;
52027c478bd9Sstevel@tonic-gate 	int			rc;
52037c478bd9Sstevel@tonic-gate 
52047c478bd9Sstevel@tonic-gate 	/* Parse filter looking for illegal values */
52057c478bd9Sstevel@tonic-gate 
52067c478bd9Sstevel@tonic-gate 	rc = adj_filter(filter);
52077c478bd9Sstevel@tonic-gate 	if (rc != 0) {
52087c478bd9Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
52097c478bd9Sstevel@tonic-gate 	}
52107c478bd9Sstevel@tonic-gate 
52117c478bd9Sstevel@tonic-gate 	/* end of filter checking */
52127c478bd9Sstevel@tonic-gate 
52137c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
52147c478bd9Sstevel@tonic-gate }
521547789246Svv149972 
521647789246Svv149972 /*
521747789246Svv149972  * Set the account management request control that needs to be sent to server.
521847789246Svv149972  * This control is required to get the account management information of
521947789246Svv149972  * a user to do local account checking.
522047789246Svv149972  */
522147789246Svv149972 static int
setup_acctmgmt_params(ns_ldap_cookie_t * cookie)522247789246Svv149972 setup_acctmgmt_params(ns_ldap_cookie_t *cookie)
522347789246Svv149972 {
522447789246Svv149972 	LDAPControl	*req = NULL, **requestctrls;
522547789246Svv149972 
522647789246Svv149972 	req = (LDAPControl *)malloc(sizeof (LDAPControl));
522747789246Svv149972 
522847789246Svv149972 	if (req == NULL)
522947789246Svv149972 		return (NS_LDAP_MEMORY);
523047789246Svv149972 
523147789246Svv149972 	/* fill in the fields of this new control */
523247789246Svv149972 	req->ldctl_iscritical = 1;
523347789246Svv149972 	req->ldctl_oid = strdup(NS_LDAP_ACCOUNT_USABLE_CONTROL);
523447789246Svv149972 	if (req->ldctl_oid == NULL) {
523547789246Svv149972 		free(req);
523647789246Svv149972 		return (NS_LDAP_MEMORY);
523747789246Svv149972 	}
523847789246Svv149972 	req->ldctl_value.bv_len = 0;
523947789246Svv149972 	req->ldctl_value.bv_val = NULL;
524047789246Svv149972 
524147789246Svv149972 	requestctrls = (LDAPControl **)calloc(2, sizeof (LDAPControl *));
524247789246Svv149972 	if (requestctrls == NULL) {
524347789246Svv149972 		ldap_control_free(req);
524447789246Svv149972 		return (NS_LDAP_MEMORY);
524547789246Svv149972 	}
524647789246Svv149972 
524747789246Svv149972 	requestctrls[0] = req;
524847789246Svv149972 
524947789246Svv149972 	cookie->p_serverctrls = requestctrls;
525047789246Svv149972 
525147789246Svv149972 	return (NS_LDAP_SUCCESS);
525247789246Svv149972 }
525347789246Svv149972 
525447789246Svv149972 /*
5255f47dc443Ssdussud  * int get_new_acct_more_info(BerElement *ber,
5256f47dc443Ssdussud  *     AcctUsableResponse_t *acctResp)
5257f47dc443Ssdussud  *
5258f47dc443Ssdussud  * Decode the more_info data from an Account Management control response,
5259f47dc443Ssdussud  * when the account is not usable and when code style is from recent LDAP
5260f47dc443Ssdussud  * servers (see below comments for parse_acct_cont_resp_msg() to get more
5261f47dc443Ssdussud  * details on coding styles and ASN1 description).
5262f47dc443Ssdussud  *
5263f47dc443Ssdussud  * Expected BER encoding: {tbtbtbtiti}
526447789246Svv149972  *      +t: tag is 0
526547789246Svv149972  *	+b: TRUE if inactive due to account inactivation
5266f47dc443Ssdussud  *      +t: tag is 1
526747789246Svv149972  * 	+b: TRUE if password has been reset
5268f47dc443Ssdussud  *      +t: tag is 2
526947789246Svv149972  * 	+b: TRUE if password is expired
5270f47dc443Ssdussud  *	+t: tag is 3
5271f47dc443Ssdussud  *	+i: contains num of remaining grace, 0 means no grace
5272f47dc443Ssdussud  *	+t: tag is 4
5273f47dc443Ssdussud  *	+i: contains num of seconds before auto-unlock. -1 means acct is locked
5274f47dc443Ssdussud  *		forever (i.e. until reset)
5275f47dc443Ssdussud  *
5276f47dc443Ssdussud  * Asumptions:
5277f47dc443Ssdussud  * - ber is not null
5278f47dc443Ssdussud  * - acctResp is not null and is initialized with default values for the
5279f47dc443Ssdussud  *   fields in its AcctUsableResp.more_info structure
5280f47dc443Ssdussud  * - the ber stream is received in the correct order, per the ASN1 description.
5281f47dc443Ssdussud  *   We do not check this order and make the asumption that it is correct.
5282f47dc443Ssdussud  *   Note that the ber stream may not (and will not in most cases) contain
5283f47dc443Ssdussud  *   all fields.
5284f47dc443Ssdussud  */
5285f47dc443Ssdussud static int
get_new_acct_more_info(BerElement * ber,AcctUsableResponse_t * acctResp)5286f47dc443Ssdussud get_new_acct_more_info(BerElement *ber, AcctUsableResponse_t *acctResp)
5287f47dc443Ssdussud {
5288f47dc443Ssdussud 	int		rc = NS_LDAP_SUCCESS;
5289f47dc443Ssdussud 	char		errstr[MAXERROR];
5290f47dc443Ssdussud 	ber_tag_t	rTag = LBER_DEFAULT;
5291f47dc443Ssdussud 	ber_len_t	rLen = 0;
5292f47dc443Ssdussud 	ber_int_t	rValue;
5293f47dc443Ssdussud 	char		*last;
5294f47dc443Ssdussud 	int		berRC = 0;
5295f47dc443Ssdussud 
5296f47dc443Ssdussud 	/*
5297f47dc443Ssdussud 	 * Look at what more_info BER element is/are left to be decoded.
5298f47dc443Ssdussud 	 * look at each of them 1 by 1, without checking on their order
5299f47dc443Ssdussud 	 * and possible multi values.
5300f47dc443Ssdussud 	 */
5301f47dc443Ssdussud 	for (rTag = ber_first_element(ber, &rLen, &last);
5302f47dc443Ssdussud 	    rTag != LBER_END_OF_SEQORSET;
5303f47dc443Ssdussud 	    rTag = ber_next_element(ber, &rLen, last)) {
5304f47dc443Ssdussud 
5305f47dc443Ssdussud 		berRC = 0;
5306f47dc443Ssdussud 		switch (rTag) {
5307f47dc443Ssdussud 		case 0 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
5308f47dc443Ssdussud 			/* inactive */
5309f47dc443Ssdussud 			berRC = ber_scanf(ber, "b", &rValue);
5310f47dc443Ssdussud 			if (berRC != LBER_ERROR) {
5311f47dc443Ssdussud 				(acctResp->AcctUsableResp).more_info.
5312f47dc443Ssdussud 				    inactive = (rValue != 0) ? 1 : 0;
5313f47dc443Ssdussud 			}
5314f47dc443Ssdussud 			break;
5315f47dc443Ssdussud 
5316f47dc443Ssdussud 		case 1 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
5317f47dc443Ssdussud 			/* reset */
5318f47dc443Ssdussud 			berRC = ber_scanf(ber, "b", &rValue);
5319f47dc443Ssdussud 			if (berRC != LBER_ERROR) {
5320f47dc443Ssdussud 				(acctResp->AcctUsableResp).more_info.reset
5321f47dc443Ssdussud 				    = (rValue != 0) ? 1 : 0;
5322f47dc443Ssdussud 			}
5323f47dc443Ssdussud 			break;
5324f47dc443Ssdussud 
5325f47dc443Ssdussud 		case 2 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
5326f47dc443Ssdussud 			/* expired */
5327f47dc443Ssdussud 			berRC = ber_scanf(ber, "b", &rValue);
5328f47dc443Ssdussud 			if (berRC != LBER_ERROR) {
5329f47dc443Ssdussud 				(acctResp->AcctUsableResp).more_info.expired
5330f47dc443Ssdussud 				    = (rValue != 0) ? 1 : 0;
5331f47dc443Ssdussud 			}
5332f47dc443Ssdussud 			break;
5333f47dc443Ssdussud 
5334f47dc443Ssdussud 		case 3 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
5335f47dc443Ssdussud 			/* remaining grace */
5336f47dc443Ssdussud 			berRC = ber_scanf(ber, "i", &rValue);
5337f47dc443Ssdussud 			if (berRC != LBER_ERROR) {
5338f47dc443Ssdussud 				(acctResp->AcctUsableResp).more_info.rem_grace
5339f47dc443Ssdussud 				    = rValue;
5340f47dc443Ssdussud 			}
5341f47dc443Ssdussud 			break;
5342f47dc443Ssdussud 
5343f47dc443Ssdussud 		case 4 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
5344f47dc443Ssdussud 			/* seconds before unlock */
5345f47dc443Ssdussud 			berRC = ber_scanf(ber, "i", &rValue);
5346f47dc443Ssdussud 			if (berRC != LBER_ERROR) {
5347f47dc443Ssdussud 				(acctResp->AcctUsableResp).more_info.
5348f47dc443Ssdussud 				    sec_b4_unlock = rValue;
5349f47dc443Ssdussud 			}
5350f47dc443Ssdussud 			break;
5351f47dc443Ssdussud 
5352f47dc443Ssdussud 		default :
5353f47dc443Ssdussud 			(void) sprintf(errstr,
5354f47dc443Ssdussud 			    gettext("invalid reason tag 0x%x"), rTag);
5355f47dc443Ssdussud 			syslog(LOG_DEBUG, "libsldap: %s", errstr);
5356f47dc443Ssdussud 			rc = NS_LDAP_INTERNAL;
5357f47dc443Ssdussud 			break;
5358f47dc443Ssdussud 		}
5359f47dc443Ssdussud 		if (berRC == LBER_ERROR) {
5360f47dc443Ssdussud 			(void) sprintf(errstr,
5361f47dc443Ssdussud 			    gettext("error 0x%x decoding value for "
5362f47dc443Ssdussud 			    "tag 0x%x"), berRC, rTag);
5363f47dc443Ssdussud 			syslog(LOG_DEBUG, "libsldap: %s", errstr);
5364f47dc443Ssdussud 			rc = NS_LDAP_INTERNAL;
5365f47dc443Ssdussud 		}
5366f47dc443Ssdussud 		if (rc != NS_LDAP_SUCCESS) {
5367f47dc443Ssdussud 			/* exit the for loop */
5368f47dc443Ssdussud 			break;
5369f47dc443Ssdussud 		}
5370f47dc443Ssdussud 	}
5371f47dc443Ssdussud 
5372f47dc443Ssdussud 	return (rc);
5373f47dc443Ssdussud }
5374f47dc443Ssdussud 
5375f47dc443Ssdussud /*
5376f47dc443Ssdussud  * int get_old_acct_opt_more_info(BerElement *ber,
5377f47dc443Ssdussud  *     AcctUsableResponse_t *acctResp)
5378f47dc443Ssdussud  *
5379f47dc443Ssdussud  * Decode the optional more_info data from an Account Management control
5380f47dc443Ssdussud  * response, when the account is not usable and when code style is from LDAP
5381f47dc443Ssdussud  * server 5.2p4 (see below comments for parse_acct_cont_resp_msg() to get more
5382f47dc443Ssdussud  * details on coding styles and ASN1 description).
5383f47dc443Ssdussud  *
5384f47dc443Ssdussud  * Expected BER encoding: titi}
538547789246Svv149972  *	+t: tag is 2
538647789246Svv149972  *	+i: contains num of remaining grace, 0 means no grace
538747789246Svv149972  *	+t: tag is 3
538847789246Svv149972  *	+i: contains num of seconds before auto-unlock. -1 means acct is locked
538947789246Svv149972  *		forever (i.e. until reset)
5390f47dc443Ssdussud  *
5391f47dc443Ssdussud  * Asumptions:
5392f47dc443Ssdussud  * - ber is a valid BER element
5393f47dc443Ssdussud  * - acctResp is initialized for the fields in its AcctUsableResp.more_info
5394f47dc443Ssdussud  *   structure
539547789246Svv149972  */
539647789246Svv149972 static int
get_old_acct_opt_more_info(ber_tag_t tag,BerElement * ber,AcctUsableResponse_t * acctResp)5397f47dc443Ssdussud get_old_acct_opt_more_info(ber_tag_t tag, BerElement *ber,
5398f47dc443Ssdussud     AcctUsableResponse_t *acctResp)
5399f47dc443Ssdussud {
5400f47dc443Ssdussud 	int		rc = NS_LDAP_SUCCESS;
5401f47dc443Ssdussud 	char		errstr[MAXERROR];
5402f47dc443Ssdussud 	ber_len_t	len;
5403f47dc443Ssdussud 	int		rem_grace, sec_b4_unlock;
5404f47dc443Ssdussud 
5405f47dc443Ssdussud 	switch (tag) {
5406f47dc443Ssdussud 	case 2:
5407f47dc443Ssdussud 		/* decode and maybe 3 is following */
5408f47dc443Ssdussud 		if ((tag = ber_scanf(ber, "i", &rem_grace)) == LBER_ERROR) {
5409f47dc443Ssdussud 			(void) sprintf(errstr, gettext("Can not get "
5410f47dc443Ssdussud 			    "rem_grace"));
5411f47dc443Ssdussud 			syslog(LOG_DEBUG, "libsldap: %s", errstr);
5412f47dc443Ssdussud 			rc = NS_LDAP_INTERNAL;
5413f47dc443Ssdussud 			break;
5414f47dc443Ssdussud 		}
5415f47dc443Ssdussud 		(acctResp->AcctUsableResp).more_info.rem_grace = rem_grace;
5416f47dc443Ssdussud 
5417f47dc443Ssdussud 		if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) {
5418f47dc443Ssdussud 			/* this is a success case, break to exit */
5419f47dc443Ssdussud 			(void) sprintf(errstr, gettext("No more "
5420f47dc443Ssdussud 			    "optional data"));
5421f47dc443Ssdussud 			syslog(LOG_DEBUG, "libsldap: %s", errstr);
5422f47dc443Ssdussud 			break;
5423f47dc443Ssdussud 		}
5424f47dc443Ssdussud 
5425f47dc443Ssdussud 		if (tag == 3) {
5426f47dc443Ssdussud 			if (ber_scanf(ber, "i", &sec_b4_unlock) == LBER_ERROR) {
5427f47dc443Ssdussud 				(void) sprintf(errstr,
5428f47dc443Ssdussud 				    gettext("Can not get sec_b4_unlock "
5429f47dc443Ssdussud 				    "- 1st case"));
5430f47dc443Ssdussud 				syslog(LOG_DEBUG, "libsldap: %s", errstr);
5431f47dc443Ssdussud 				rc = NS_LDAP_INTERNAL;
5432f47dc443Ssdussud 				break;
5433f47dc443Ssdussud 			}
5434f47dc443Ssdussud 			(acctResp->AcctUsableResp).more_info.sec_b4_unlock =
5435f47dc443Ssdussud 			    sec_b4_unlock;
5436f47dc443Ssdussud 		} else { /* unknown tag */
5437f47dc443Ssdussud 			(void) sprintf(errstr, gettext("Unknown tag "
5438f47dc443Ssdussud 			    "- 1st case"));
5439f47dc443Ssdussud 			syslog(LOG_DEBUG, "libsldap: %s", errstr);
5440f47dc443Ssdussud 			rc = NS_LDAP_INTERNAL;
5441f47dc443Ssdussud 			break;
5442f47dc443Ssdussud 		}
5443f47dc443Ssdussud 		break;
5444f47dc443Ssdussud 
5445f47dc443Ssdussud 	case 3:
5446f47dc443Ssdussud 		if (ber_scanf(ber, "i", &sec_b4_unlock) == LBER_ERROR) {
5447f47dc443Ssdussud 			(void) sprintf(errstr, gettext("Can not get "
5448f47dc443Ssdussud 			    "sec_b4_unlock - 2nd case"));
5449f47dc443Ssdussud 			syslog(LOG_DEBUG, "libsldap: %s", errstr);
5450f47dc443Ssdussud 			rc = NS_LDAP_INTERNAL;
5451f47dc443Ssdussud 			break;
5452f47dc443Ssdussud 		}
5453f47dc443Ssdussud 		(acctResp->AcctUsableResp).more_info.sec_b4_unlock =
5454f47dc443Ssdussud 		    sec_b4_unlock;
5455f47dc443Ssdussud 		break;
5456f47dc443Ssdussud 
5457f47dc443Ssdussud 	default: /* unknown tag */
5458f47dc443Ssdussud 		(void) sprintf(errstr, gettext("Unknown tag - 2nd case"));
5459f47dc443Ssdussud 		syslog(LOG_DEBUG, "libsldap: %s", errstr);
5460f47dc443Ssdussud 		rc = NS_LDAP_INTERNAL;
5461f47dc443Ssdussud 		break;
5462f47dc443Ssdussud 	}
5463f47dc443Ssdussud 
5464f47dc443Ssdussud 	return (rc);
5465f47dc443Ssdussud }
5466f47dc443Ssdussud 
5467f47dc443Ssdussud /*
5468f47dc443Ssdussud  * **** This function needs to be moved to libldap library ****
5469f47dc443Ssdussud  * parse_acct_cont_resp_msg() parses the message received by server according to
5470f47dc443Ssdussud  * following format (ASN1 notation):
5471f47dc443Ssdussud  *
5472f47dc443Ssdussud  *	ACCOUNT_USABLE_RESPONSE::= CHOICE {
5473f47dc443Ssdussud  *		is_available		[0] INTEGER,
5474f47dc443Ssdussud  *				** seconds before expiration **
5475f47dc443Ssdussud  *		is_not_available	[1] more_info
5476f47dc443Ssdussud  *	}
5477f47dc443Ssdussud  *	more_info::= SEQUENCE {
5478f47dc443Ssdussud  *		inactive		[0] BOOLEAN DEFAULT FALSE,
5479f47dc443Ssdussud  *		reset			[1] BOOLEAN DEFAULT FALSE,
5480f47dc443Ssdussud  *		expired			[2] BOOLEAN DEFAULT FALSE,
5481f47dc443Ssdussud  *		remaining_grace		[3] INTEGER OPTIONAL,
5482f47dc443Ssdussud  *		seconds_before_unlock	[4] INTEGER OPTIONAL
5483f47dc443Ssdussud  *	}
5484f47dc443Ssdussud  */
5485f47dc443Ssdussud /*
5486f47dc443Ssdussud  * #define used to make the difference between coding style as done
5487f47dc443Ssdussud  * by LDAP server 5.2p4 and newer LDAP servers. There are 4 values:
5488f47dc443Ssdussud  * - DS52p4_USABLE: 5.2p4 coding style, account is usable
5489f47dc443Ssdussud  * - DS52p4_NOT_USABLE: 5.2p4 coding style, account is not usable
5490f47dc443Ssdussud  * - NEW_USABLE: newer LDAP servers coding style, account is usable
5491f47dc443Ssdussud  * - NEW_NOT_USABLE: newer LDAP servers coding style, account is not usable
5492f47dc443Ssdussud  *
5493f47dc443Ssdussud  * An account would be considered not usable if for instance:
5494f47dc443Ssdussud  * - it's been made inactive in the LDAP server
5495f47dc443Ssdussud  * - or its password was reset in the LDAP server database
5496f47dc443Ssdussud  * - or its password expired
5497f47dc443Ssdussud  * - or the account has been locked, possibly forever
5498f47dc443Ssdussud  */
5499f47dc443Ssdussud #define	DS52p4_USABLE		0x00
5500f47dc443Ssdussud #define	DS52p4_NOT_USABLE	0x01
5501f47dc443Ssdussud #define	NEW_USABLE		0x00 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE
5502f47dc443Ssdussud #define	NEW_NOT_USABLE		0x01 | LBER_CLASS_CONTEXT | LBER_CONSTRUCTED
5503f47dc443Ssdussud static int
parse_acct_cont_resp_msg(LDAPControl ** ectrls,AcctUsableResponse_t * acctResp)550447789246Svv149972 parse_acct_cont_resp_msg(LDAPControl **ectrls, AcctUsableResponse_t *acctResp)
550547789246Svv149972 {
5506f47dc443Ssdussud 	int		rc = NS_LDAP_SUCCESS;
550747789246Svv149972 	BerElement	*ber;
5508f47dc443Ssdussud 	ber_tag_t 	tag;
550947789246Svv149972 	ber_len_t	len;
5510f47dc443Ssdussud 	int		i;
5511f47dc443Ssdussud 	char		errstr[MAXERROR];
5512f47dc443Ssdussud 	/* used for any coding style when account is usable */
5513f47dc443Ssdussud 	int		seconds_before_expiry;
5514f47dc443Ssdussud 	/* used for 5.2p4 coding style when account is not usable */
5515f47dc443Ssdussud 	int		inactive, reset, expired;
551647789246Svv149972 
5517f47dc443Ssdussud 	if (ectrls == NULL) {
5518f47dc443Ssdussud 		(void) sprintf(errstr, gettext("Invalid ectrls parameter"));
5519f47dc443Ssdussud 		syslog(LOG_DEBUG, "libsldap: %s", errstr);
552047789246Svv149972 		return (NS_LDAP_INVALID_PARAM);
5521f47dc443Ssdussud 	}
552247789246Svv149972 
552347789246Svv149972 	for (i = 0; ectrls[i] != NULL; i++) {
552447789246Svv149972 		if (strcmp(ectrls[i]->ldctl_oid, NS_LDAP_ACCOUNT_USABLE_CONTROL)
5525f47dc443Ssdussud 		    == 0) {
5526f47dc443Ssdussud 			break;
552747789246Svv149972 		}
5528f47dc443Ssdussud 	}
552947789246Svv149972 
5530f47dc443Ssdussud 	if (ectrls[i] == NULL) {
5531f47dc443Ssdussud 		/* Ldap control is not found */
5532f47dc443Ssdussud 		(void) sprintf(errstr, gettext("Account Usable Control "
5533f47dc443Ssdussud 		    "not found"));
5534f47dc443Ssdussud 		syslog(LOG_DEBUG, "libsldap: %s", errstr);
5535f47dc443Ssdussud 		return (NS_LDAP_NOTFOUND);
5536f47dc443Ssdussud 	}
5537f47dc443Ssdussud 
5538f47dc443Ssdussud 	/* Allocate a BER element from the control value and parse it. */
553947789246Svv149972 	if ((ber = ber_init(&ectrls[i]->ldctl_value)) == NULL)
554047789246Svv149972 		return (NS_LDAP_MEMORY);
554147789246Svv149972 
554247789246Svv149972 	if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) {
554347789246Svv149972 		/* Ldap decoding error */
5544f47dc443Ssdussud 		(void) sprintf(errstr, gettext("Error decoding 1st tag"));
5545f47dc443Ssdussud 		syslog(LOG_DEBUG, "libsldap: %s", errstr);
554647789246Svv149972 		ber_free(ber, 1);
554747789246Svv149972 		return (NS_LDAP_INTERNAL);
554847789246Svv149972 	}
554947789246Svv149972 
555047789246Svv149972 	switch (tag) {
5551f47dc443Ssdussud 	case DS52p4_USABLE:
5552f47dc443Ssdussud 	case NEW_USABLE:
5553f47dc443Ssdussud 		acctResp->choice = 0;
555447789246Svv149972 		if (ber_scanf(ber, "i", &seconds_before_expiry)
555547789246Svv149972 		    == LBER_ERROR) {
555647789246Svv149972 			/* Ldap decoding error */
5557f47dc443Ssdussud 			(void) sprintf(errstr, gettext("Can not get "
5558f47dc443Ssdussud 			    "seconds_before_expiry"));
5559f47dc443Ssdussud 			syslog(LOG_DEBUG, "libsldap: %s", errstr);
5560f47dc443Ssdussud 			rc = NS_LDAP_INTERNAL;
5561f47dc443Ssdussud 			break;
556247789246Svv149972 		}
5563f47dc443Ssdussud 		/* ber_scanf() succeeded */
556447789246Svv149972 		(acctResp->AcctUsableResp).seconds_before_expiry =
556547789246Svv149972 		    seconds_before_expiry;
5566f47dc443Ssdussud 		break;
5567f47dc443Ssdussud 
5568f47dc443Ssdussud 	case DS52p4_NOT_USABLE:
5569f47dc443Ssdussud 		acctResp->choice = 1;
557047789246Svv149972 		if (ber_scanf(ber, "{bbb", &inactive, &reset, &expired)
557147789246Svv149972 		    == LBER_ERROR) {
557247789246Svv149972 			/* Ldap decoding error */
5573f47dc443Ssdussud 			(void) sprintf(errstr, gettext("Can not get "
5574f47dc443Ssdussud 			    "inactive/reset/expired"));
5575f47dc443Ssdussud 			syslog(LOG_DEBUG, "libsldap: %s", errstr);
5576f47dc443Ssdussud 			rc = NS_LDAP_INTERNAL;
5577f47dc443Ssdussud 			break;
557847789246Svv149972 		}
5579f47dc443Ssdussud 		/* ber_scanf() succeeded */
558047789246Svv149972 		(acctResp->AcctUsableResp).more_info.inactive =
5581f47dc443Ssdussud 		    ((inactive == 0) ? 0 : 1);
558247789246Svv149972 		(acctResp->AcctUsableResp).more_info.reset =
5583f47dc443Ssdussud 		    ((reset == 0) ? 0 : 1);
558447789246Svv149972 		(acctResp->AcctUsableResp).more_info.expired =
5585f47dc443Ssdussud 		    ((expired == 0) ? 0 : 1);
5586f47dc443Ssdussud 		(acctResp->AcctUsableResp).more_info.rem_grace = 0;
5587f47dc443Ssdussud 		(acctResp->AcctUsableResp).more_info.sec_b4_unlock = 0;
558847789246Svv149972 
558947789246Svv149972 		if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) {
5590f47dc443Ssdussud 			/* this is a success case, break to exit */
5591f47dc443Ssdussud 			(void) sprintf(errstr, gettext("No optional data"));
5592f47dc443Ssdussud 			syslog(LOG_DEBUG, "libsldap: %s", errstr);
5593f47dc443Ssdussud 			break;
559447789246Svv149972 		}
559547789246Svv149972 
5596f47dc443Ssdussud 		/*
5597f47dc443Ssdussud 		 * Look at what optional more_info BER element is/are
5598f47dc443Ssdussud 		 * left to be decoded.
5599f47dc443Ssdussud 		 */
5600f47dc443Ssdussud 		rc = get_old_acct_opt_more_info(tag, ber, acctResp);
560147789246Svv149972 		break;
5602f47dc443Ssdussud 
5603f47dc443Ssdussud 	case NEW_NOT_USABLE:
5604f47dc443Ssdussud 		acctResp->choice = 1;
5605f47dc443Ssdussud 		/*
5606f47dc443Ssdussud 		 * Recent LDAP servers won't code more_info data for default
5607f47dc443Ssdussud 		 * values (see above comments on ASN1 description for what
5608f47dc443Ssdussud 		 * fields have default values & what fields are optional).
5609f47dc443Ssdussud 		 */
5610f47dc443Ssdussud 		(acctResp->AcctUsableResp).more_info.inactive = 0;
5611f47dc443Ssdussud 		(acctResp->AcctUsableResp).more_info.reset = 0;
5612f47dc443Ssdussud 		(acctResp->AcctUsableResp).more_info.expired = 0;
5613f47dc443Ssdussud 		(acctResp->AcctUsableResp).more_info.rem_grace = 0;
5614f47dc443Ssdussud 		(acctResp->AcctUsableResp).more_info.sec_b4_unlock = 0;
5615f47dc443Ssdussud 
5616f47dc443Ssdussud 		if (len == 0) {
5617f47dc443Ssdussud 			/*
5618f47dc443Ssdussud 			 * Nothing else to decode; this is valid and we
5619f47dc443Ssdussud 			 * use default values set above.
5620f47dc443Ssdussud 			 */
5621f47dc443Ssdussud 			(void) sprintf(errstr, gettext("more_info is "
5622f47dc443Ssdussud 			    "empty, using default values"));
5623f47dc443Ssdussud 			syslog(LOG_DEBUG, "libsldap: %s", errstr);
5624f47dc443Ssdussud 			break;
5625f47dc443Ssdussud 		}
5626f47dc443Ssdussud 
5627f47dc443Ssdussud 		/*
5628f47dc443Ssdussud 		 * Look at what more_info BER element is/are left to
5629f47dc443Ssdussud 		 * be decoded.
5630f47dc443Ssdussud 		 */
5631f47dc443Ssdussud 		rc = get_new_acct_more_info(ber, acctResp);
5632f47dc443Ssdussud 		break;
5633f47dc443Ssdussud 
563447789246Svv149972 	default:
5635f47dc443Ssdussud 		(void) sprintf(errstr, gettext("unknwon coding style "
5636f47dc443Ssdussud 		    "(tag: 0x%x)"), tag);
5637f47dc443Ssdussud 		syslog(LOG_DEBUG, "libsldap: %s", errstr);
5638f47dc443Ssdussud 		rc = NS_LDAP_INTERNAL;
5639f47dc443Ssdussud 		break;
564047789246Svv149972 	}
564147789246Svv149972 
564247789246Svv149972 	ber_free(ber, 1);
5643f47dc443Ssdussud 	return (rc);
564447789246Svv149972 }
564547789246Svv149972 
564647789246Svv149972 /*
5647e1dd0a2fSth160488  * internal function for __ns_ldap_getAcctMgmt()
564847789246Svv149972  */
5649e1dd0a2fSth160488 static int
getAcctMgmt(const char * user,AcctUsableResponse_t * acctResp,ns_conn_user_t * conn_user)5650e1dd0a2fSth160488 getAcctMgmt(const char *user, AcctUsableResponse_t *acctResp,
5651e1dd0a2fSth160488 	ns_conn_user_t *conn_user)
565247789246Svv149972 {
565347789246Svv149972 	int		scope, rc;
565447789246Svv149972 	char		ldapfilter[1024];
565547789246Svv149972 	ns_ldap_cookie_t	*cookie;
565647789246Svv149972 	ns_ldap_search_desc_t	**sdlist = NULL;
565747789246Svv149972 	ns_ldap_search_desc_t	*dptr;
565847789246Svv149972 	ns_ldap_error_t		*error = NULL;
565947789246Svv149972 	char			**dns = NULL;
566047789246Svv149972 	char		service[] = "shadow";
566147789246Svv149972 
566247789246Svv149972 	if (user == NULL || acctResp == NULL)
566347789246Svv149972 		return (NS_LDAP_INVALID_PARAM);
566447789246Svv149972 
566547789246Svv149972 	/* Initialize State machine cookie */
566647789246Svv149972 	cookie = init_search_state_machine();
566747789246Svv149972 	if (cookie == NULL)
566847789246Svv149972 		return (NS_LDAP_MEMORY);
5669e1dd0a2fSth160488 	cookie->conn_user = conn_user;
567047789246Svv149972 
567147789246Svv149972 	/* see if need to follow referrals */
567247789246Svv149972 	rc = __s_api_toFollowReferrals(0,
567347789246Svv149972 	    &cookie->followRef, &error);
567447789246Svv149972 	if (rc != NS_LDAP_SUCCESS) {
567547789246Svv149972 		(void) __ns_ldap_freeError(&error);
567647789246Svv149972 		goto out;
567747789246Svv149972 	}
567847789246Svv149972 
567947789246Svv149972 	/* get the service descriptor - or create a default one */
568047789246Svv149972 	rc = __s_api_get_SSD_from_SSDtoUse_service(service,
568147789246Svv149972 	    &sdlist, &error);
568247789246Svv149972 	if (rc != NS_LDAP_SUCCESS) {
568347789246Svv149972 		(void) __ns_ldap_freeError(&error);
568447789246Svv149972 		goto out;
568547789246Svv149972 	}
568647789246Svv149972 
568747789246Svv149972 	if (sdlist == NULL) {
568847789246Svv149972 		/* Create default service Desc */
568947789246Svv149972 		sdlist = (ns_ldap_search_desc_t **)calloc(2,
569047789246Svv149972 		    sizeof (ns_ldap_search_desc_t *));
569147789246Svv149972 		if (sdlist == NULL) {
569247789246Svv149972 			rc = NS_LDAP_MEMORY;
569347789246Svv149972 			goto out;
569447789246Svv149972 		}
569547789246Svv149972 		dptr = (ns_ldap_search_desc_t *)
569647789246Svv149972 		    calloc(1, sizeof (ns_ldap_search_desc_t));
569747789246Svv149972 		if (dptr == NULL) {
569847789246Svv149972 			free(sdlist);
569947789246Svv149972 			rc = NS_LDAP_MEMORY;
570047789246Svv149972 			goto out;
570147789246Svv149972 		}
570247789246Svv149972 		sdlist[0] = dptr;
570347789246Svv149972 
570447789246Svv149972 		/* default base */
570547789246Svv149972 		rc = __s_api_getDNs(&dns, service, &cookie->errorp);
570647789246Svv149972 		if (rc != NS_LDAP_SUCCESS) {
570747789246Svv149972 			if (dns) {
570847789246Svv149972 				__s_api_free2dArray(dns);
570947789246Svv149972 				dns = NULL;
571047789246Svv149972 			}
571147789246Svv149972 			(void) __ns_ldap_freeError(&(cookie->errorp));
571247789246Svv149972 			cookie->errorp = NULL;
571347789246Svv149972 			goto out;
571447789246Svv149972 		}
571547789246Svv149972 		dptr->basedn = strdup(dns[0]);
571647789246Svv149972 		if (dptr->basedn == NULL) {
571747789246Svv149972 			free(sdlist);
571847789246Svv149972 			free(dptr);
571947789246Svv149972 			if (dns) {
572047789246Svv149972 				__s_api_free2dArray(dns);
572147789246Svv149972 				dns = NULL;
572247789246Svv149972 			}
572347789246Svv149972 			rc = NS_LDAP_MEMORY;
572447789246Svv149972 			goto out;
572547789246Svv149972 		}
572647789246Svv149972 		__s_api_free2dArray(dns);
572747789246Svv149972 		dns = NULL;
572847789246Svv149972 
572947789246Svv149972 		/* default scope */
573047789246Svv149972 		scope = 0;
573147789246Svv149972 		rc = __s_api_getSearchScope(&scope, &cookie->errorp);
573247789246Svv149972 		dptr->scope = scope;
573347789246Svv149972 	}
573447789246Svv149972 
573547789246Svv149972 	cookie->sdlist = sdlist;
573647789246Svv149972 
573747789246Svv149972 	cookie->service = strdup(service);
573847789246Svv149972 	if (cookie->service == NULL) {
573947789246Svv149972 		rc = NS_LDAP_MEMORY;
574047789246Svv149972 		goto out;
574147789246Svv149972 	}
574247789246Svv149972 
574347789246Svv149972 	/* search for entries for this particular uid */
574447789246Svv149972 	(void) snprintf(ldapfilter, sizeof (ldapfilter), "(uid=%s)", user);
574547789246Svv149972 	cookie->i_filter = strdup(ldapfilter);
574647789246Svv149972 	if (cookie->i_filter == NULL) {
574747789246Svv149972 		rc = NS_LDAP_MEMORY;
574847789246Svv149972 		goto out;
574947789246Svv149972 	}
575047789246Svv149972 
575147789246Svv149972 	/* create the control request */
575247789246Svv149972 	if ((rc = setup_acctmgmt_params(cookie)) != NS_LDAP_SUCCESS)
575347789246Svv149972 		goto out;
575447789246Svv149972 
575547789246Svv149972 	/* Process search */
575647789246Svv149972 	rc = search_state_machine(cookie, GET_ACCT_MGMT_INFO, 0);
575747789246Svv149972 
575847789246Svv149972 	/* Copy results back to user */
575947789246Svv149972 	rc = cookie->err_rc;
576047789246Svv149972 	if (rc != NS_LDAP_SUCCESS)
576147789246Svv149972 			(void) __ns_ldap_freeError(&(cookie->errorp));
576247789246Svv149972 
576347789246Svv149972 	if (cookie->result == NULL)
576447789246Svv149972 			goto out;
576547789246Svv149972 
576647789246Svv149972 	if ((rc = parse_acct_cont_resp_msg(cookie->resultctrl, acctResp))
576747789246Svv149972 	    != NS_LDAP_SUCCESS)
576847789246Svv149972 		goto out;
576947789246Svv149972 
577047789246Svv149972 	rc = NS_LDAP_SUCCESS;
577147789246Svv149972 
577247789246Svv149972 out:
577347789246Svv149972 	delete_search_cookie(cookie);
577447789246Svv149972 
577547789246Svv149972 	return (rc);
577647789246Svv149972 }
5777e1dd0a2fSth160488 
5778e1dd0a2fSth160488 /*
5779e1dd0a2fSth160488  * __ns_ldap_getAcctMgmt() is called from pam account management stack
5780e1dd0a2fSth160488  * for retrieving accounting information of users with no user password -
5781e1dd0a2fSth160488  * eg. rlogin, rsh, etc. This function uses the account management control
5782e1dd0a2fSth160488  * request to do a search on the server for the user in question. The
5783e1dd0a2fSth160488  * response control returned from the server is got from the cookie.
5784e1dd0a2fSth160488  * Input params: username of whose account mgmt information is to be got
5785e1dd0a2fSth160488  *		 pointer to hold the parsed account management information
5786e1dd0a2fSth160488  * Return values: NS_LDAP_SUCCESS on success or appropriate error
5787e1dd0a2fSth160488  *		code on failure
5788e1dd0a2fSth160488  */
5789e1dd0a2fSth160488 int
__ns_ldap_getAcctMgmt(const char * user,AcctUsableResponse_t * acctResp)5790e1dd0a2fSth160488 __ns_ldap_getAcctMgmt(const char *user, AcctUsableResponse_t *acctResp)
5791e1dd0a2fSth160488 {
5792e1dd0a2fSth160488 	ns_conn_user_t	*cu = NULL;
5793e1dd0a2fSth160488 	int		try_cnt = 0;
5794e1dd0a2fSth160488 	int		rc = NS_LDAP_SUCCESS;
5795e1dd0a2fSth160488 	ns_ldap_error_t	*error = NULL;
5796e1dd0a2fSth160488 
5797e1dd0a2fSth160488 	for (;;) {
5798e1dd0a2fSth160488 		if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
5799e1dd0a2fSth160488 		    &try_cnt, &rc, &error) == 0)
5800e1dd0a2fSth160488 			break;
5801e1dd0a2fSth160488 		rc = getAcctMgmt(user, acctResp, cu);
5802e1dd0a2fSth160488 	}
5803e1dd0a2fSth160488 	return (rc);
5804e1dd0a2fSth160488 }
5805