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 ***)¶m, &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(¶m);
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, ¶m, &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(¶m);
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(¶m);
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(¶m);
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(¶m);
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