10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52031Svt115884 * Common Development and Distribution License (the "License").
62031Svt115884 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*12758SJulian.Pullen@Sun.COM * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate #include <stdio.h>
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <stdlib.h>
280Sstevel@tonic-gate #include <libintl.h>
290Sstevel@tonic-gate #include <ctype.h>
300Sstevel@tonic-gate #include <syslog.h>
310Sstevel@tonic-gate #include <sys/stat.h>
320Sstevel@tonic-gate #include <fcntl.h>
330Sstevel@tonic-gate #include <unistd.h>
340Sstevel@tonic-gate #include <string.h>
350Sstevel@tonic-gate #include <strings.h>
369576SJulian.Pullen@Sun.COM #include <priv.h>
370Sstevel@tonic-gate
380Sstevel@tonic-gate #include "ns_sldap.h"
390Sstevel@tonic-gate #include "ns_internal.h"
400Sstevel@tonic-gate #include "ns_cache_door.h"
416842Sth160488 #include "ns_connmgmt.h"
420Sstevel@tonic-gate
430Sstevel@tonic-gate #define _NIS_FILTER "nisdomain=*"
440Sstevel@tonic-gate #define _NIS_DOMAIN "nisdomain"
450Sstevel@tonic-gate static const char *nis_domain_attrs[] = {
460Sstevel@tonic-gate _NIS_DOMAIN,
470Sstevel@tonic-gate (char *)NULL
480Sstevel@tonic-gate };
490Sstevel@tonic-gate
500Sstevel@tonic-gate static int validate_filter(ns_ldap_cookie_t *cookie);
510Sstevel@tonic-gate
520Sstevel@tonic-gate void
__ns_ldap_freeEntry(ns_ldap_entry_t * ep)530Sstevel@tonic-gate __ns_ldap_freeEntry(ns_ldap_entry_t *ep)
540Sstevel@tonic-gate {
550Sstevel@tonic-gate int j, k = 0;
560Sstevel@tonic-gate
570Sstevel@tonic-gate if (ep == NULL)
580Sstevel@tonic-gate return;
590Sstevel@tonic-gate
600Sstevel@tonic-gate if (ep->attr_pair == NULL) {
610Sstevel@tonic-gate free(ep);
620Sstevel@tonic-gate return;
630Sstevel@tonic-gate }
640Sstevel@tonic-gate for (j = 0; j < ep->attr_count; j++) {
650Sstevel@tonic-gate if (ep->attr_pair[j] == NULL)
660Sstevel@tonic-gate continue;
670Sstevel@tonic-gate if (ep->attr_pair[j]->attrname)
680Sstevel@tonic-gate free(ep->attr_pair[j]->attrname);
690Sstevel@tonic-gate if (ep->attr_pair[j]->attrvalue) {
700Sstevel@tonic-gate for (k = 0; (k < ep->attr_pair[j]->value_count) &&
714765Smj162486 (ep->attr_pair[j]->attrvalue[k]); k++) {
720Sstevel@tonic-gate free(ep->attr_pair[j]->attrvalue[k]);
730Sstevel@tonic-gate }
740Sstevel@tonic-gate free(ep->attr_pair[j]->attrvalue);
750Sstevel@tonic-gate }
760Sstevel@tonic-gate free(ep->attr_pair[j]);
770Sstevel@tonic-gate }
780Sstevel@tonic-gate free(ep->attr_pair);
790Sstevel@tonic-gate free(ep);
800Sstevel@tonic-gate }
810Sstevel@tonic-gate
820Sstevel@tonic-gate static void
_freeControlList(LDAPControl *** ctrls)830Sstevel@tonic-gate _freeControlList(LDAPControl ***ctrls)
840Sstevel@tonic-gate {
850Sstevel@tonic-gate LDAPControl **ctrl;
860Sstevel@tonic-gate
870Sstevel@tonic-gate if (ctrls == NULL || *ctrls == NULL)
880Sstevel@tonic-gate return;
890Sstevel@tonic-gate
900Sstevel@tonic-gate for (ctrl = *ctrls; *ctrl != NULL; ctrl++)
910Sstevel@tonic-gate ldap_control_free(*ctrl);
920Sstevel@tonic-gate free(*ctrls);
930Sstevel@tonic-gate *ctrls = NULL;
940Sstevel@tonic-gate }
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate * Convert attribute type in a RDN that has an attribute mapping to the
970Sstevel@tonic-gate * original mappped type.
980Sstevel@tonic-gate * e.g.
990Sstevel@tonic-gate * cn<->cn-st and iphostnumber<->iphostnumber-st
1000Sstevel@tonic-gate * cn-st=aaa+iphostnumber-st=10.10.01.01
1010Sstevel@tonic-gate * is mapped to
1020Sstevel@tonic-gate * cn=aaa+iphostnumber=10.10.01.01
1030Sstevel@tonic-gate *
1040Sstevel@tonic-gate * Input - service: e.g. hosts, passwd etc.
1050Sstevel@tonic-gate * rdn: RDN
1060Sstevel@tonic-gate * Return: NULL - No attribute mapping in the RDN
1070Sstevel@tonic-gate * Non-NULL - The attribute type(s) in the RDN are mapped and
1080Sstevel@tonic-gate * the memory is allocated for the new rdn.
1090Sstevel@tonic-gate *
1100Sstevel@tonic-gate */
1110Sstevel@tonic-gate static char *
_cvtRDN(const char * service,const char * rdn)1120Sstevel@tonic-gate _cvtRDN(const char *service, const char *rdn) {
1130Sstevel@tonic-gate char **attrs, **mapped_attrs, **mapp, *type, *value, *attr;
1140Sstevel@tonic-gate char *new_rdn = NULL;
1150Sstevel@tonic-gate int nAttr = 0, i, attr_mapped, len = 0;
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate /* Break down "type=value\0" pairs. Assume RDN is normalized */
1180Sstevel@tonic-gate if ((attrs = ldap_explode_rdn(rdn, 0)) == NULL)
1190Sstevel@tonic-gate return (NULL);
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate for (nAttr = 0; attrs[nAttr] != NULL; nAttr++);
1220Sstevel@tonic-gate
1230Sstevel@tonic-gate if ((mapped_attrs = (char **)calloc(nAttr, sizeof (char *))) == NULL) {
1240Sstevel@tonic-gate ldap_value_free(attrs);
1250Sstevel@tonic-gate return (NULL);
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate attr_mapped = 0;
1290Sstevel@tonic-gate for (i = 0; i < nAttr; i++) {
1300Sstevel@tonic-gate /* Parse type=value pair */
1310Sstevel@tonic-gate if ((type = strtok_r(attrs[i], "=", &value)) == NULL ||
1320Sstevel@tonic-gate value == NULL)
1330Sstevel@tonic-gate goto cleanup;
1340Sstevel@tonic-gate /* Reverse map: e.g. cn-sm -> cn */
1350Sstevel@tonic-gate mapp = __ns_ldap_getOrigAttribute(service, type);
1360Sstevel@tonic-gate if (mapp != NULL && mapp[0] != NULL) {
1370Sstevel@tonic-gate /* The attribute mapping is found */
1380Sstevel@tonic-gate type = mapp[0];
1390Sstevel@tonic-gate attr_mapped = 1;
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate /* "type=value\0" */
1420Sstevel@tonic-gate len = strlen(type) + strlen(value) + 2;
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate /* Reconstruct type=value pair. A string is allocated */
1450Sstevel@tonic-gate if ((attr = (char *)calloc(1, len)) == NULL) {
1460Sstevel@tonic-gate __s_api_free2dArray(mapp);
1470Sstevel@tonic-gate goto cleanup;
1480Sstevel@tonic-gate }
1490Sstevel@tonic-gate (void) snprintf(attr, len, "%s=%s",
1500Sstevel@tonic-gate type, value);
1510Sstevel@tonic-gate mapped_attrs[i] = attr;
1520Sstevel@tonic-gate } else {
1530Sstevel@tonic-gate /*
1540Sstevel@tonic-gate * No attribute mapping. attrs[i] is going to be copied
1550Sstevel@tonic-gate * later. Restore "type\0value\0" back to
1560Sstevel@tonic-gate * "type=value\0".
1570Sstevel@tonic-gate */
1580Sstevel@tonic-gate type[strlen(type)] = '=';
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate __s_api_free2dArray(mapp);
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate if (attr_mapped == 0)
1630Sstevel@tonic-gate /* No attribute mapping. Don't bother to reconstruct RDN */
1640Sstevel@tonic-gate goto cleanup;
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate len = 0;
1670Sstevel@tonic-gate /* Reconstruct RDN from type=value pairs */
1680Sstevel@tonic-gate for (i = 0; i < nAttr; i++) {
1690Sstevel@tonic-gate if (mapped_attrs[i])
1700Sstevel@tonic-gate len += strlen(mapped_attrs[i]);
1710Sstevel@tonic-gate else
1720Sstevel@tonic-gate len += strlen(attrs[i]);
1730Sstevel@tonic-gate /* Add 1 for "+" */
1740Sstevel@tonic-gate len++;
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate if ((new_rdn = (char *)calloc(1, ++len)) == NULL)
1770Sstevel@tonic-gate goto cleanup;
1780Sstevel@tonic-gate for (i = 0; i < nAttr; i++) {
1790Sstevel@tonic-gate if (i > 0)
1800Sstevel@tonic-gate /* Add seperator */
1810Sstevel@tonic-gate (void) strlcat(new_rdn, "+", len);
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate if (mapped_attrs[i])
1840Sstevel@tonic-gate (void) strlcat(new_rdn, mapped_attrs[i], len);
1850Sstevel@tonic-gate else
1860Sstevel@tonic-gate (void) strlcat(new_rdn, attrs[i], len);
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate cleanup:
1900Sstevel@tonic-gate ldap_value_free(attrs);
1910Sstevel@tonic-gate if (mapped_attrs) {
1920Sstevel@tonic-gate if (attr_mapped) {
1930Sstevel@tonic-gate for (i = 0; i < nAttr; i++) {
1940Sstevel@tonic-gate if (mapped_attrs[i])
1950Sstevel@tonic-gate free(mapped_attrs[i]);
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate free(mapped_attrs);
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate return (new_rdn);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate /*
2040Sstevel@tonic-gate * Convert attribute type in a DN that has an attribute mapping to the
2050Sstevel@tonic-gate * original mappped type.
2060Sstevel@tonic-gate * e.g
2070Sstevel@tonic-gate * The mappings are cn<->cn-sm, iphostnumber<->iphostnumber-sm
2080Sstevel@tonic-gate *
2090Sstevel@tonic-gate * dn: cn-sm=aaa+iphostnumber-sm=9.9.9.9,dc=central,dc=sun,dc=com
2100Sstevel@tonic-gate * is converted to
2110Sstevel@tonic-gate * dn: cn=aaa+iphostnumber=9.9.9.9,dc=central,dc=sun,dc=com
2120Sstevel@tonic-gate *
2130Sstevel@tonic-gate * Input - service: e.g. hosts, passwd etc.
2140Sstevel@tonic-gate * dn: the value of a distinguished name
2150Sstevel@tonic-gate * Return - NULL: error
2160Sstevel@tonic-gate * non-NULL: A converted DN and the memory is allocated
2170Sstevel@tonic-gate */
2180Sstevel@tonic-gate static char *
_cvtDN(const char * service,const char * dn)2190Sstevel@tonic-gate _cvtDN(const char *service, const char *dn) {
2200Sstevel@tonic-gate char **mapped_rdns;
2210Sstevel@tonic-gate char **rdns, *new_rdn, *new_dn = NULL;
2220Sstevel@tonic-gate int nRdn = 0, i, len = 0, rdn_mapped;
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate if (service == NULL || dn == NULL)
2250Sstevel@tonic-gate return (NULL);
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate if ((rdns = ldap_explode_dn(dn, 0)) == NULL)
2280Sstevel@tonic-gate return (NULL);
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate for (nRdn = 0; rdns[nRdn] != NULL; nRdn++);
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate if ((mapped_rdns = (char **)calloc(nRdn, sizeof (char *))) == NULL) {
2330Sstevel@tonic-gate ldap_value_free(rdns);
2340Sstevel@tonic-gate return (NULL);
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate rdn_mapped = 0;
2380Sstevel@tonic-gate /* Break down RDNs in a DN */
2390Sstevel@tonic-gate for (i = 0; i < nRdn; i++) {
2400Sstevel@tonic-gate if ((new_rdn = _cvtRDN(service, rdns[i])) != NULL) {
2410Sstevel@tonic-gate mapped_rdns[i] = new_rdn;
2420Sstevel@tonic-gate rdn_mapped = 1;
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate if (rdn_mapped == 0) {
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate * No RDN contains any attribute mapping.
2480Sstevel@tonic-gate * Don't bother to reconstruct DN from RDN. Copy DN directly.
2490Sstevel@tonic-gate */
2500Sstevel@tonic-gate new_dn = strdup(dn);
2510Sstevel@tonic-gate goto cleanup;
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate /*
2540Sstevel@tonic-gate * Reconstruct dn from RDNs.
2550Sstevel@tonic-gate * Calculate the length first.
2560Sstevel@tonic-gate */
2570Sstevel@tonic-gate for (i = 0; i < nRdn; i++) {
2580Sstevel@tonic-gate if (mapped_rdns[i])
2590Sstevel@tonic-gate len += strlen(mapped_rdns[i]);
2600Sstevel@tonic-gate else
2610Sstevel@tonic-gate len += strlen(rdns[i]);
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate /* add 1 for ',' */
2640Sstevel@tonic-gate len ++;
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate if ((new_dn = (char *)calloc(1, ++len)) == NULL)
2670Sstevel@tonic-gate goto cleanup;
2680Sstevel@tonic-gate for (i = 0; i < nRdn; i++) {
2690Sstevel@tonic-gate if (i > 0)
2700Sstevel@tonic-gate /* Add seperator */
2710Sstevel@tonic-gate (void) strlcat(new_dn, ",", len);
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate if (mapped_rdns[i])
2740Sstevel@tonic-gate (void) strlcat(new_dn, mapped_rdns[i], len);
2750Sstevel@tonic-gate else
2760Sstevel@tonic-gate (void) strlcat(new_dn, rdns[i], len);
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate cleanup:
2810Sstevel@tonic-gate ldap_value_free(rdns);
2820Sstevel@tonic-gate if (mapped_rdns) {
2830Sstevel@tonic-gate if (rdn_mapped) {
2840Sstevel@tonic-gate for (i = 0; i < nRdn; i++) {
2850Sstevel@tonic-gate if (mapped_rdns[i])
2860Sstevel@tonic-gate free(mapped_rdns[i]);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate }
2890Sstevel@tonic-gate free(mapped_rdns);
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate return (new_dn);
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate /*
2950Sstevel@tonic-gate * Convert a single ldap entry from a LDAPMessage
2960Sstevel@tonic-gate * into an ns_ldap_entry structure.
2970Sstevel@tonic-gate * Schema map the entry if specified in flags
2980Sstevel@tonic-gate */
2990Sstevel@tonic-gate
3000Sstevel@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)3010Sstevel@tonic-gate __s_api_cvtEntry(LDAP *ld,
3020Sstevel@tonic-gate const char *service,
3030Sstevel@tonic-gate LDAPMessage *e,
3040Sstevel@tonic-gate int flags,
3050Sstevel@tonic-gate ns_ldap_entry_t **ret,
3060Sstevel@tonic-gate ns_ldap_error_t **error)
3070Sstevel@tonic-gate {
3080Sstevel@tonic-gate
3090Sstevel@tonic-gate ns_ldap_entry_t *ep = NULL;
3100Sstevel@tonic-gate ns_ldap_attr_t **ap = NULL;
3110Sstevel@tonic-gate BerElement *ber;
3120Sstevel@tonic-gate char *attr = NULL;
3130Sstevel@tonic-gate char **vals = NULL;
3140Sstevel@tonic-gate char **mapping;
3150Sstevel@tonic-gate char *dn;
3160Sstevel@tonic-gate int nAttrs = 0;
3170Sstevel@tonic-gate int i, j, k = 0;
3180Sstevel@tonic-gate char **gecos_mapping = NULL;
3190Sstevel@tonic-gate int gecos_val_index[3] = { -1, -1, -1};
3200Sstevel@tonic-gate char errstr[MAXERROR];
3210Sstevel@tonic-gate int schema_mapping_existed = FALSE;
3220Sstevel@tonic-gate int gecos_mapping_existed = FALSE;
3230Sstevel@tonic-gate int gecos_attr_matched;
3240Sstevel@tonic-gate int auto_service = FALSE;
3250Sstevel@tonic-gate int rc = NS_LDAP_SUCCESS;
3260Sstevel@tonic-gate
3270Sstevel@tonic-gate if (e == NULL || ret == NULL || error == NULL)
3280Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate *error = NULL;
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate ep = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t));
3330Sstevel@tonic-gate if (ep == NULL)
3340Sstevel@tonic-gate return (NS_LDAP_MEMORY);
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate if (service != NULL &&
3374765Smj162486 (strncasecmp(service, "auto_", 5) == 0 ||
3384765Smj162486 strcasecmp(service, "automount") == 0))
3390Sstevel@tonic-gate auto_service = TRUE;
3400Sstevel@tonic-gate /*
3410Sstevel@tonic-gate * see if schema mapping existed for the given service
3420Sstevel@tonic-gate */
3430Sstevel@tonic-gate mapping = __ns_ldap_getOrigAttribute(service,
3444765Smj162486 NS_HASH_SCHEMA_MAPPING_EXISTED);
3450Sstevel@tonic-gate if (mapping) {
3460Sstevel@tonic-gate schema_mapping_existed = TRUE;
3470Sstevel@tonic-gate __s_api_free2dArray(mapping);
3480Sstevel@tonic-gate mapping = NULL;
3490Sstevel@tonic-gate } else if (auto_service) {
3500Sstevel@tonic-gate /*
3510Sstevel@tonic-gate * If service == auto_* and no
3520Sstevel@tonic-gate * schema mapping found
3530Sstevel@tonic-gate * then try automount
3540Sstevel@tonic-gate * There is certain case that schema mapping exist
3550Sstevel@tonic-gate * but __ns_ldap_getOrigAttribute(service,
3560Sstevel@tonic-gate * NS_HASH_SCHEMA_MAPPING_EXISTED);
3570Sstevel@tonic-gate * returns NULL.
3580Sstevel@tonic-gate * e.g.
3590Sstevel@tonic-gate * NS_LDAP_ATTRIBUTEMAP = automount:automountMapName=AAA
3600Sstevel@tonic-gate * NS_LDAP_OBJECTCLASSMAP = automount:automountMap=MynisMap
3610Sstevel@tonic-gate * NS_LDAP_OBJECTCLASSMAP = automount:automount=MynisObject
3620Sstevel@tonic-gate *
3630Sstevel@tonic-gate * Make a check for schema_mapping_existed here
3640Sstevel@tonic-gate * so later on __s_api_convert_automountmapname won't be called
3650Sstevel@tonic-gate * unnecessarily. It is also used for attribute mapping
3660Sstevel@tonic-gate * and objectclass mapping.
3670Sstevel@tonic-gate */
3680Sstevel@tonic-gate mapping = __ns_ldap_getOrigAttribute("automount",
3694765Smj162486 NS_HASH_SCHEMA_MAPPING_EXISTED);
3700Sstevel@tonic-gate if (mapping) {
3710Sstevel@tonic-gate schema_mapping_existed = TRUE;
3720Sstevel@tonic-gate __s_api_free2dArray(mapping);
3730Sstevel@tonic-gate mapping = NULL;
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate
3770Sstevel@tonic-gate nAttrs = 1; /* start with 1 for the DN attr */
3780Sstevel@tonic-gate for (attr = ldap_first_attribute(ld, e, &ber); attr != NULL;
3794765Smj162486 attr = ldap_next_attribute(ld, e, ber)) {
3800Sstevel@tonic-gate nAttrs++;
3810Sstevel@tonic-gate ldap_memfree(attr);
3820Sstevel@tonic-gate attr = NULL;
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate ber_free(ber, 0);
3850Sstevel@tonic-gate ber = NULL;
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate ep->attr_count = nAttrs;
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate /*
3900Sstevel@tonic-gate * add 1 for "gecos" 1 to N attribute mapping,
3910Sstevel@tonic-gate * just in case it is needed.
3920Sstevel@tonic-gate * ep->attr_count will be updated later if that is true.
3930Sstevel@tonic-gate */
3940Sstevel@tonic-gate ap = (ns_ldap_attr_t **)calloc(ep->attr_count + 1,
3954765Smj162486 sizeof (ns_ldap_attr_t *));
3960Sstevel@tonic-gate if (ap == NULL) {
3970Sstevel@tonic-gate __ns_ldap_freeEntry(ep);
3980Sstevel@tonic-gate ep = NULL;
3990Sstevel@tonic-gate return (NS_LDAP_MEMORY);
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate ep->attr_pair = ap;
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate /* DN attribute */
4040Sstevel@tonic-gate dn = ldap_get_dn(ld, e);
4050Sstevel@tonic-gate ap[0] = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
4060Sstevel@tonic-gate if (ap[0] == NULL) {
4070Sstevel@tonic-gate ldap_memfree(dn);
4080Sstevel@tonic-gate dn = NULL;
4090Sstevel@tonic-gate __ns_ldap_freeEntry(ep);
4100Sstevel@tonic-gate ep = NULL;
4110Sstevel@tonic-gate return (NS_LDAP_MEMORY);
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate if ((ap[0]->attrname = strdup("dn")) == NULL) {
4150Sstevel@tonic-gate ldap_memfree(dn);
4160Sstevel@tonic-gate dn = NULL;
4170Sstevel@tonic-gate __ns_ldap_freeEntry(ep);
4180Sstevel@tonic-gate ep = NULL;
4190Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
4200Sstevel@tonic-gate }
4210Sstevel@tonic-gate ap[0]->value_count = 1;
4220Sstevel@tonic-gate if ((ap[0]->attrvalue = (char **)
4234765Smj162486 calloc(2, sizeof (char *))) == NULL) {
4240Sstevel@tonic-gate ldap_memfree(dn);
4250Sstevel@tonic-gate dn = NULL;
4260Sstevel@tonic-gate __ns_ldap_freeEntry(ep);
4270Sstevel@tonic-gate ep = NULL;
4280Sstevel@tonic-gate return (NS_LDAP_MEMORY);
4290Sstevel@tonic-gate }
4300Sstevel@tonic-gate
431699Ssdussud if (schema_mapping_existed && ((flags & NS_LDAP_NOT_CVT_DN) == 0))
4320Sstevel@tonic-gate ap[0]->attrvalue[0] = _cvtDN(service, dn);
4330Sstevel@tonic-gate else
4340Sstevel@tonic-gate ap[0]->attrvalue[0] = strdup(dn);
4350Sstevel@tonic-gate
4360Sstevel@tonic-gate if (ap[0]->attrvalue[0] == NULL) {
4370Sstevel@tonic-gate ldap_memfree(dn);
4380Sstevel@tonic-gate dn = NULL;
4390Sstevel@tonic-gate __ns_ldap_freeEntry(ep);
4400Sstevel@tonic-gate ep = NULL;
4410Sstevel@tonic-gate return (NS_LDAP_MEMORY);
4420Sstevel@tonic-gate }
4430Sstevel@tonic-gate ldap_memfree(dn);
4440Sstevel@tonic-gate dn = NULL;
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate if ((flags & NS_LDAP_NOMAP) == 0 && auto_service &&
4474765Smj162486 schema_mapping_existed) {
4480Sstevel@tonic-gate rc = __s_api_convert_automountmapname(service,
4494765Smj162486 &ap[0]->attrvalue[0],
4504765Smj162486 error);
4510Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
4520Sstevel@tonic-gate __ns_ldap_freeEntry(ep);
4530Sstevel@tonic-gate ep = NULL;
4540Sstevel@tonic-gate return (rc);
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate /* other attributes */
4590Sstevel@tonic-gate for (attr = ldap_first_attribute(ld, e, &ber), j = 1;
4604765Smj162486 attr != NULL && j != nAttrs;
4614765Smj162486 attr = ldap_next_attribute(ld, e, ber), j++) {
4624765Smj162486 /* allocate new attr name */
4634765Smj162486
4644765Smj162486 if ((ap[j] = (ns_ldap_attr_t *)
4654765Smj162486 calloc(1, sizeof (ns_ldap_attr_t))) == NULL) {
4664765Smj162486 ber_free(ber, 0);
4674765Smj162486 ber = NULL;
4684765Smj162486 __ns_ldap_freeEntry(ep);
4694765Smj162486 ep = NULL;
4704765Smj162486 if (gecos_mapping)
4714765Smj162486 __s_api_free2dArray(gecos_mapping);
4724765Smj162486 gecos_mapping = NULL;
4734765Smj162486 return (NS_LDAP_MEMORY);
4740Sstevel@tonic-gate }
4754765Smj162486
4764765Smj162486 if ((flags & NS_LDAP_NOMAP) || schema_mapping_existed == FALSE)
4774765Smj162486 mapping = NULL;
4784765Smj162486 else
4794765Smj162486 mapping = __ns_ldap_getOrigAttribute(service, attr);
4804765Smj162486
4814765Smj162486 if (mapping == NULL && auto_service &&
4824765Smj162486 schema_mapping_existed && (flags & NS_LDAP_NOMAP) == 0)
4830Sstevel@tonic-gate /*
4844765Smj162486 * if service == auto_* and no schema mapping found
4854765Smj162486 * and schema_mapping_existed is TRUE and NS_LDAP_NOMAP
4864765Smj162486 * is not set then try automount e.g.
4874765Smj162486 * NS_LDAP_ATTRIBUTEMAP = automount:automountMapName=AAA
4880Sstevel@tonic-gate */
4894765Smj162486 mapping = __ns_ldap_getOrigAttribute("automount",
4904765Smj162486 attr);
4914765Smj162486
4924765Smj162486 if (mapping == NULL) {
4934765Smj162486 if ((ap[j]->attrname = strdup(attr)) == NULL) {
4940Sstevel@tonic-gate ber_free(ber, 0);
4950Sstevel@tonic-gate ber = NULL;
4960Sstevel@tonic-gate __ns_ldap_freeEntry(ep);
4970Sstevel@tonic-gate ep = NULL;
4984765Smj162486 if (gecos_mapping)
4994765Smj162486 __s_api_free2dArray(gecos_mapping);
5000Sstevel@tonic-gate gecos_mapping = NULL;
5014765Smj162486 return (NS_LDAP_MEMORY);
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate } else {
5044765Smj162486 /*
5054765Smj162486 * for "gecos" 1 to N mapping,
5064765Smj162486 * do not remove the mapped attribute,
5074765Smj162486 * just create a new gecos attribute
5084765Smj162486 * and append it to the end of the attribute list
5094765Smj162486 */
5104765Smj162486 if (strcasecmp(mapping[0], "gecos") == 0) {
5114765Smj162486 ap[j]->attrname = strdup(attr);
5124765Smj162486 gecos_mapping_existed = TRUE;
5134765Smj162486 } else
5144765Smj162486 ap[j]->attrname = strdup(mapping[0]);
5154765Smj162486
5164765Smj162486 if (ap[j]->attrname == NULL) {
5170Sstevel@tonic-gate ber_free(ber, 0);
5180Sstevel@tonic-gate ber = NULL;
5190Sstevel@tonic-gate __ns_ldap_freeEntry(ep);
5200Sstevel@tonic-gate ep = NULL;
5210Sstevel@tonic-gate if (gecos_mapping)
5220Sstevel@tonic-gate __s_api_free2dArray(gecos_mapping);
5230Sstevel@tonic-gate gecos_mapping = NULL;
5240Sstevel@tonic-gate return (NS_LDAP_MEMORY);
5250Sstevel@tonic-gate }
5264765Smj162486 /*
5274765Smj162486 * 1 to N attribute mapping processing
5284765Smj162486 * is only done for "gecos"
5294765Smj162486 */
5304765Smj162486
5314765Smj162486 if (strcasecmp(mapping[0], "gecos") == 0) {
5324765Smj162486 /*
5334765Smj162486 * get attribute mapping for "gecos",
5344765Smj162486 * need to know the number and order of the
5354765Smj162486 * mapped attributes
5364765Smj162486 */
5374765Smj162486 if (gecos_mapping == NULL) {
5384765Smj162486 gecos_mapping =
5394765Smj162486 __ns_ldap_getMappedAttributes(
5404765Smj162486 service, mapping[0]);
5414765Smj162486 if (gecos_mapping == NULL ||
5424765Smj162486 gecos_mapping[0] == NULL) {
5434765Smj162486 /*
5444765Smj162486 * this should never happens,
5454765Smj162486 * syslog the error
5464765Smj162486 */
5474765Smj162486 (void) sprintf(errstr,
5484765Smj162486 gettext(
5494765Smj162486 "Attribute mapping "
5504765Smj162486 "inconsistency "
5514765Smj162486 "found for attributes "
5524765Smj162486 "'%s' and '%s'."),
5534765Smj162486 mapping[0], attr);
5544765Smj162486 syslog(LOG_ERR, "libsldap: %s",
5554765Smj162486 errstr);
5564765Smj162486
5574765Smj162486 ber_free(ber, 0);
5584765Smj162486 ber = NULL;
5594765Smj162486 __ns_ldap_freeEntry(ep);
5604765Smj162486 ep = NULL;
5614765Smj162486 __s_api_free2dArray(mapping);
5624765Smj162486 mapping = NULL;
5634765Smj162486 if (gecos_mapping)
5644765Smj162486 __s_api_free2dArray(
5654765Smj162486 gecos_mapping);
5664765Smj162486 gecos_mapping = NULL;
5674765Smj162486 return (NS_LDAP_INTERNAL);
5684765Smj162486 }
5694765Smj162486 }
5704765Smj162486
5714765Smj162486 /*
5724765Smj162486 * is this attribute the 1st, 2nd, or
5734765Smj162486 * 3rd attr in the mapping list?
5744765Smj162486 */
5754765Smj162486 gecos_attr_matched = FALSE;
5764765Smj162486 for (i = 0; i < 3 && gecos_mapping[i]; i++) {
5774765Smj162486 if (gecos_mapping[i] &&
5784765Smj162486 strcasecmp(gecos_mapping[i],
5794765Smj162486 attr) == 0) {
5804765Smj162486 gecos_val_index[i] = j;
5814765Smj162486 gecos_attr_matched = TRUE;
5824765Smj162486 break;
5834765Smj162486 }
5844765Smj162486 }
5854765Smj162486 if (gecos_attr_matched == FALSE) {
5864765Smj162486 /*
5874765Smj162486 * Not match found.
5884765Smj162486 * This should never happens,
5894765Smj162486 * syslog the error
5904765Smj162486 */
5914765Smj162486 (void) sprintf(errstr,
5924765Smj162486 gettext(
5934765Smj162486 "Attribute mapping "
5944765Smj162486 "inconsistency "
5954765Smj162486 "found for attributes "
5964765Smj162486 "'%s' and '%s'."),
5974765Smj162486 mapping[0], attr);
5984765Smj162486 syslog(LOG_ERR, "libsldap: %s", errstr);
5994765Smj162486
6004765Smj162486 ber_free(ber, 0);
6014765Smj162486 ber = NULL;
6024765Smj162486 __ns_ldap_freeEntry(ep);
6034765Smj162486 ep = NULL;
6044765Smj162486 __s_api_free2dArray(mapping);
6054765Smj162486 mapping = NULL;
6060Sstevel@tonic-gate __s_api_free2dArray(gecos_mapping);
6074765Smj162486 gecos_mapping = NULL;
6084765Smj162486 return (NS_LDAP_INTERNAL);
6094765Smj162486 }
6100Sstevel@tonic-gate }
6114765Smj162486 __s_api_free2dArray(mapping);
6124765Smj162486 mapping = NULL;
6130Sstevel@tonic-gate }
6140Sstevel@tonic-gate
6154765Smj162486 if ((vals = ldap_get_values(ld, e, attr)) != NULL) {
6164765Smj162486
6174765Smj162486 if ((ap[j]->value_count =
6184765Smj162486 ldap_count_values(vals)) == 0) {
6194765Smj162486 ldap_value_free(vals);
6204765Smj162486 vals = NULL;
6214765Smj162486 continue;
6224765Smj162486 } else {
6234765Smj162486 ap[j]->attrvalue = (char **)
6244765Smj162486 calloc(ap[j]->value_count+1,
6254765Smj162486 sizeof (char *));
6264765Smj162486 if (ap[j]->attrvalue == NULL) {
6274765Smj162486 ber_free(ber, 0);
6284765Smj162486 ber = NULL;
6294765Smj162486 __ns_ldap_freeEntry(ep);
6304765Smj162486 ep = NULL;
6314765Smj162486 if (gecos_mapping)
6324765Smj162486 __s_api_free2dArray(
6334765Smj162486 gecos_mapping);
6344765Smj162486 gecos_mapping = NULL;
6354765Smj162486 return (NS_LDAP_MEMORY);
6364765Smj162486 }
6374765Smj162486 }
6384765Smj162486
6394765Smj162486 /* map object classes if necessary */
6404765Smj162486 if ((flags & NS_LDAP_NOMAP) == 0 &&
6414765Smj162486 schema_mapping_existed && ap[j]->attrname &&
6424765Smj162486 strcasecmp(ap[j]->attrname, "objectclass") == 0) {
6434765Smj162486 for (k = 0; k < ap[j]->value_count; k++) {
6444765Smj162486 mapping =
6454765Smj162486 __ns_ldap_getOrigObjectClass(
6464765Smj162486 service, vals[k]);
6474765Smj162486
6484765Smj162486 if (mapping == NULL && auto_service)
6494765Smj162486 /*
6504765Smj162486 * if service == auto_* and no
6514765Smj162486 * schema mapping found
6524765Smj162486 * then try automount
6534765Smj162486 */
6544790Ssdussud mapping =
6554790Ssdussud __ns_ldap_getOrigObjectClass(
6564790Ssdussud "automount", vals[k]);
6574765Smj162486
6584765Smj162486 if (mapping == NULL) {
6594765Smj162486 ap[j]->attrvalue[k] =
6604765Smj162486 strdup(vals[k]);
6614765Smj162486 } else {
6624765Smj162486 ap[j]->attrvalue[k] =
6634765Smj162486 strdup(mapping[0]);
6644765Smj162486 __s_api_free2dArray(mapping);
6654765Smj162486 mapping = NULL;
6664765Smj162486 }
6674765Smj162486 if (ap[j]->attrvalue[k] == NULL) {
6684765Smj162486 ber_free(ber, 0);
6694765Smj162486 ber = NULL;
6704765Smj162486 __ns_ldap_freeEntry(ep);
6714765Smj162486 ep = NULL;
6724765Smj162486 if (gecos_mapping)
6734765Smj162486 __s_api_free2dArray(
6744765Smj162486 gecos_mapping);
6754765Smj162486 gecos_mapping = NULL;
6764765Smj162486 return (NS_LDAP_MEMORY);
6774765Smj162486 }
6784765Smj162486 }
6794765Smj162486 } else {
6804765Smj162486 for (k = 0; k < ap[j]->value_count; k++) {
6814765Smj162486 if ((ap[j]->attrvalue[k] =
6824765Smj162486 strdup(vals[k])) == NULL) {
6834765Smj162486 ber_free(ber, 0);
6844765Smj162486 ber = NULL;
6854765Smj162486 __ns_ldap_freeEntry(ep);
6864765Smj162486 ep = NULL;
6874765Smj162486 if (gecos_mapping)
6884765Smj162486 __s_api_free2dArray(
6894765Smj162486 gecos_mapping);
6904765Smj162486 gecos_mapping = NULL;
6914765Smj162486 return (NS_LDAP_MEMORY);
6924765Smj162486 }
6934765Smj162486 }
6944765Smj162486 }
6954765Smj162486
6964765Smj162486 ap[j]->attrvalue[k] = NULL;
6974765Smj162486 ldap_value_free(vals);
6984765Smj162486 vals = NULL;
6994765Smj162486 }
7004765Smj162486
7014765Smj162486 ldap_memfree(attr);
7024765Smj162486 attr = NULL;
7030Sstevel@tonic-gate }
7040Sstevel@tonic-gate
7050Sstevel@tonic-gate ber_free(ber, 0);
7060Sstevel@tonic-gate ber = NULL;
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate if (gecos_mapping) {
7090Sstevel@tonic-gate __s_api_free2dArray(gecos_mapping);
7100Sstevel@tonic-gate gecos_mapping = NULL;
7110Sstevel@tonic-gate }
7120Sstevel@tonic-gate
7130Sstevel@tonic-gate /* special processing for gecos 1 to up to 3 attribute mapping */
7140Sstevel@tonic-gate if (schema_mapping_existed && gecos_mapping_existed) {
7150Sstevel@tonic-gate
7160Sstevel@tonic-gate int f = -1;
7170Sstevel@tonic-gate
7180Sstevel@tonic-gate for (i = 0; i < 3; i++) {
7190Sstevel@tonic-gate k = gecos_val_index[i];
7200Sstevel@tonic-gate
7210Sstevel@tonic-gate /*
7220Sstevel@tonic-gate * f is the index of the first returned
7230Sstevel@tonic-gate * attribute which "gecos" attribute mapped to
7240Sstevel@tonic-gate */
7250Sstevel@tonic-gate if (k != -1 && f == -1)
7260Sstevel@tonic-gate f = k;
7270Sstevel@tonic-gate
7280Sstevel@tonic-gate if (k != -1 && ap[k]->value_count > 0 &&
7294765Smj162486 ap[k]->attrvalue[0] &&
7304765Smj162486 strlen(ap[k]->attrvalue[0]) > 0) {
7310Sstevel@tonic-gate
7320Sstevel@tonic-gate if (k == f) {
7330Sstevel@tonic-gate /*
7340Sstevel@tonic-gate * Create and fill in the last reserved
7350Sstevel@tonic-gate * ap with the data from the "gecos"
7360Sstevel@tonic-gate * mapping attributes
7370Sstevel@tonic-gate */
7380Sstevel@tonic-gate ap[nAttrs] = (ns_ldap_attr_t *)
7394765Smj162486 calloc(1,
7404765Smj162486 sizeof (ns_ldap_attr_t));
7410Sstevel@tonic-gate if (ap[nAttrs] == NULL) {
7420Sstevel@tonic-gate __ns_ldap_freeEntry(ep);
7430Sstevel@tonic-gate ep = NULL;
7440Sstevel@tonic-gate return (NS_LDAP_MEMORY);
7450Sstevel@tonic-gate }
7460Sstevel@tonic-gate ap[nAttrs]->attrvalue = (char **)calloc(
7474765Smj162486 2, sizeof (char *));
7480Sstevel@tonic-gate if (ap[nAttrs]->attrvalue == NULL) {
7490Sstevel@tonic-gate __ns_ldap_freeEntry(ep);
7500Sstevel@tonic-gate ep = NULL;
7510Sstevel@tonic-gate return (NS_LDAP_MEMORY);
7520Sstevel@tonic-gate }
7530Sstevel@tonic-gate /* add 1 more for a possible "," */
7540Sstevel@tonic-gate ap[nAttrs]->attrvalue[0] =
7554765Smj162486 (char *)calloc(
7564765Smj162486 strlen(ap[f]->attrvalue[0]) +
7574765Smj162486 2, 1);
7580Sstevel@tonic-gate if (ap[nAttrs]->attrvalue[0] == NULL) {
7590Sstevel@tonic-gate __ns_ldap_freeEntry(ep);
7600Sstevel@tonic-gate ep = NULL;
7610Sstevel@tonic-gate return (NS_LDAP_MEMORY);
7620Sstevel@tonic-gate }
7630Sstevel@tonic-gate (void) strcpy(ap[nAttrs]->attrvalue[0],
7644765Smj162486 ap[f]->attrvalue[0]);
7650Sstevel@tonic-gate
7660Sstevel@tonic-gate ap[nAttrs]->attrname = strdup("gecos");
7670Sstevel@tonic-gate if (ap[nAttrs]->attrname == NULL) {
7680Sstevel@tonic-gate __ns_ldap_freeEntry(ep);
7690Sstevel@tonic-gate ep = NULL;
7700Sstevel@tonic-gate return (NS_LDAP_MEMORY);
7710Sstevel@tonic-gate }
7720Sstevel@tonic-gate
7730Sstevel@tonic-gate ap[nAttrs]->value_count = 1;
7740Sstevel@tonic-gate ep->attr_count = nAttrs + 1;
7750Sstevel@tonic-gate
7760Sstevel@tonic-gate } else {
7774288Ssdussud char *tmp = NULL;
7784288Ssdussud
7794288Ssdussud /*
7804288Ssdussud * realloc to add "," and
7814288Ssdussud * ap[k]->attrvalue[0]
7824288Ssdussud */
7834288Ssdussud tmp = (char *)realloc(
7844765Smj162486 ap[nAttrs]->attrvalue[0],
7854765Smj162486 strlen(ap[nAttrs]->
7864765Smj162486 attrvalue[0]) +
7874765Smj162486 strlen(ap[k]->
7884765Smj162486 attrvalue[0]) + 2);
7894288Ssdussud if (tmp == NULL) {
7900Sstevel@tonic-gate __ns_ldap_freeEntry(ep);
7910Sstevel@tonic-gate ep = NULL;
7920Sstevel@tonic-gate return (NS_LDAP_MEMORY);
7930Sstevel@tonic-gate }
7944288Ssdussud ap[nAttrs]->attrvalue[0] = tmp;
7954288Ssdussud (void) strcat(ap[nAttrs]->attrvalue[0],
7964765Smj162486 ",");
7970Sstevel@tonic-gate (void) strcat(ap[nAttrs]->attrvalue[0],
7984765Smj162486 ap[k]->attrvalue[0]);
7990Sstevel@tonic-gate }
8000Sstevel@tonic-gate }
8010Sstevel@tonic-gate }
8020Sstevel@tonic-gate }
8030Sstevel@tonic-gate
8040Sstevel@tonic-gate *ret = ep;
8050Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
8060Sstevel@tonic-gate }
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate static int
__s_api_getEntry(ns_ldap_cookie_t * cookie)8090Sstevel@tonic-gate __s_api_getEntry(ns_ldap_cookie_t *cookie)
8100Sstevel@tonic-gate {
8110Sstevel@tonic-gate ns_ldap_entry_t *curEntry = NULL;
8120Sstevel@tonic-gate int ret;
8130Sstevel@tonic-gate
8140Sstevel@tonic-gate #ifdef DEBUG
8150Sstevel@tonic-gate (void) fprintf(stderr, "__s_api_getEntry START\n");
8160Sstevel@tonic-gate #endif
8170Sstevel@tonic-gate
8180Sstevel@tonic-gate if (cookie->resultMsg == NULL) {
8190Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
8200Sstevel@tonic-gate }
8210Sstevel@tonic-gate ret = __s_api_cvtEntry(cookie->conn->ld, cookie->service,
8224765Smj162486 cookie->resultMsg, cookie->i_flags,
8234765Smj162486 &curEntry, &cookie->errorp);
8240Sstevel@tonic-gate if (ret != NS_LDAP_SUCCESS) {
8250Sstevel@tonic-gate return (ret);
8260Sstevel@tonic-gate }
8270Sstevel@tonic-gate
8280Sstevel@tonic-gate if (cookie->result == NULL) {
8290Sstevel@tonic-gate cookie->result = (ns_ldap_result_t *)
8304765Smj162486 calloc(1, sizeof (ns_ldap_result_t));
8310Sstevel@tonic-gate if (cookie->result == NULL) {
8320Sstevel@tonic-gate __ns_ldap_freeEntry(curEntry);
8330Sstevel@tonic-gate curEntry = NULL;
8340Sstevel@tonic-gate return (NS_LDAP_MEMORY);
8350Sstevel@tonic-gate }
8360Sstevel@tonic-gate cookie->result->entry = curEntry;
8370Sstevel@tonic-gate cookie->nextEntry = curEntry;
8380Sstevel@tonic-gate } else {
8390Sstevel@tonic-gate cookie->nextEntry->next = curEntry;
8400Sstevel@tonic-gate cookie->nextEntry = curEntry;
8410Sstevel@tonic-gate }
8420Sstevel@tonic-gate cookie->result->entries_count++;
8430Sstevel@tonic-gate
8440Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
8450Sstevel@tonic-gate }
8460Sstevel@tonic-gate
8470Sstevel@tonic-gate static int
__s_api_get_cachemgr_data(const char * type,const char * from,char ** to)8480Sstevel@tonic-gate __s_api_get_cachemgr_data(const char *type,
8490Sstevel@tonic-gate const char *from, char **to)
8500Sstevel@tonic-gate {
8510Sstevel@tonic-gate union {
8520Sstevel@tonic-gate ldap_data_t s_d;
8530Sstevel@tonic-gate char s_b[DOORBUFFERSIZE];
8540Sstevel@tonic-gate } space;
8550Sstevel@tonic-gate ldap_data_t *sptr;
8560Sstevel@tonic-gate int ndata;
8570Sstevel@tonic-gate int adata;
8580Sstevel@tonic-gate int rc;
8590Sstevel@tonic-gate
8600Sstevel@tonic-gate #ifdef DEBUG
8610Sstevel@tonic-gate (void) fprintf(stderr, "__s_api_get_cachemgr_data START\n");
8620Sstevel@tonic-gate #endif
8636842Sth160488 /*
8646842Sth160488 * We are not going to perform DN to domain mapping
8656842Sth160488 * in the Standalone mode
8666842Sth160488 */
8676842Sth160488 if (__s_api_isStandalone()) {
8686842Sth160488 return (-1);
8696842Sth160488 }
8700Sstevel@tonic-gate
8710Sstevel@tonic-gate if (from == NULL || from[0] == '\0' || to == NULL)
8720Sstevel@tonic-gate return (-1);
8730Sstevel@tonic-gate
8740Sstevel@tonic-gate *to = NULL;
8750Sstevel@tonic-gate (void) memset(space.s_b, 0, DOORBUFFERSIZE);
8760Sstevel@tonic-gate
8770Sstevel@tonic-gate space.s_d.ldap_call.ldap_callnumber = GETCACHE;
8780Sstevel@tonic-gate (void) snprintf(space.s_d.ldap_call.ldap_u.domainname,
8794765Smj162486 DOORBUFFERSIZE - sizeof (space.s_d.ldap_call.ldap_callnumber),
8804765Smj162486 "%s%s%s",
8814765Smj162486 type,
8824765Smj162486 DOORLINESEP,
8834765Smj162486 from);
8840Sstevel@tonic-gate ndata = sizeof (space);
8850Sstevel@tonic-gate adata = sizeof (ldap_call_t) +
8864765Smj162486 strlen(space.s_d.ldap_call.ldap_u.domainname) + 1;
8870Sstevel@tonic-gate sptr = &space.s_d;
8880Sstevel@tonic-gate
8890Sstevel@tonic-gate rc = __ns_ldap_trydoorcall(&sptr, &ndata, &adata);
8906842Sth160488 if (rc != NS_CACHE_SUCCESS)
8910Sstevel@tonic-gate return (-1);
8920Sstevel@tonic-gate else
8930Sstevel@tonic-gate *to = strdup(sptr->ldap_ret.ldap_u.buff);
8940Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
8950Sstevel@tonic-gate }
8960Sstevel@tonic-gate
8970Sstevel@tonic-gate static int
__s_api_set_cachemgr_data(const char * type,const char * from,const char * to)8980Sstevel@tonic-gate __s_api_set_cachemgr_data(const char *type,
8990Sstevel@tonic-gate const char *from, const char *to)
9000Sstevel@tonic-gate {
9010Sstevel@tonic-gate union {
9020Sstevel@tonic-gate ldap_data_t s_d;
9030Sstevel@tonic-gate char s_b[DOORBUFFERSIZE];
9040Sstevel@tonic-gate } space;
9050Sstevel@tonic-gate ldap_data_t *sptr;
9060Sstevel@tonic-gate int ndata;
9070Sstevel@tonic-gate int adata;
9080Sstevel@tonic-gate int rc;
9090Sstevel@tonic-gate
9100Sstevel@tonic-gate #ifdef DEBUG
9110Sstevel@tonic-gate (void) fprintf(stderr, "__s_api_set_cachemgr_data START\n");
9120Sstevel@tonic-gate #endif
9136842Sth160488 /*
9146842Sth160488 * We are not going to perform DN to domain mapping
9156842Sth160488 * in the Standalone mode
9166842Sth160488 */
9176842Sth160488 if (__s_api_isStandalone()) {
9186842Sth160488 return (-1);
9196842Sth160488 }
9200Sstevel@tonic-gate
9210Sstevel@tonic-gate if ((from == NULL) || (from[0] == '\0') ||
9224765Smj162486 (to == NULL) || (to[0] == '\0'))
9230Sstevel@tonic-gate return (-1);
9240Sstevel@tonic-gate
9250Sstevel@tonic-gate (void) memset(space.s_b, 0, DOORBUFFERSIZE);
9260Sstevel@tonic-gate
9270Sstevel@tonic-gate space.s_d.ldap_call.ldap_callnumber = SETCACHE;
9280Sstevel@tonic-gate (void) snprintf(space.s_d.ldap_call.ldap_u.domainname,
9294765Smj162486 DOORBUFFERSIZE - sizeof (space.s_d.ldap_call.ldap_callnumber),
9304765Smj162486 "%s%s%s%s%s",
9314765Smj162486 type,
9324765Smj162486 DOORLINESEP,
9334765Smj162486 from,
9344765Smj162486 DOORLINESEP,
9354765Smj162486 to);
9360Sstevel@tonic-gate
9370Sstevel@tonic-gate ndata = sizeof (space);
9380Sstevel@tonic-gate adata = sizeof (ldap_call_t) +
9394765Smj162486 strlen(space.s_d.ldap_call.ldap_u.domainname) + 1;
9400Sstevel@tonic-gate sptr = &space.s_d;
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate rc = __ns_ldap_trydoorcall(&sptr, &ndata, &adata);
9436842Sth160488 if (rc != NS_CACHE_SUCCESS)
9440Sstevel@tonic-gate return (-1);
9450Sstevel@tonic-gate
9460Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
9470Sstevel@tonic-gate }
9480Sstevel@tonic-gate
9490Sstevel@tonic-gate
9500Sstevel@tonic-gate static char *
__s_api_remove_rdn_space(char * rdn)9510Sstevel@tonic-gate __s_api_remove_rdn_space(char *rdn)
9520Sstevel@tonic-gate {
9530Sstevel@tonic-gate char *tf, *tl, *vf, *vl, *eqsign;
9540Sstevel@tonic-gate
9550Sstevel@tonic-gate /* if no space(s) to remove, return */
9560Sstevel@tonic-gate if (strchr(rdn, SPACETOK) == NULL)
9570Sstevel@tonic-gate return (rdn);
9580Sstevel@tonic-gate
9590Sstevel@tonic-gate /* if no '=' separator, return */
9600Sstevel@tonic-gate eqsign = strchr(rdn, '=');
9610Sstevel@tonic-gate if (eqsign == NULL)
9620Sstevel@tonic-gate return (rdn);
9630Sstevel@tonic-gate
9640Sstevel@tonic-gate tf = rdn;
9650Sstevel@tonic-gate tl = eqsign - 1;
9660Sstevel@tonic-gate vf = eqsign + 1;
9670Sstevel@tonic-gate vl = rdn + strlen(rdn) - 1;
9680Sstevel@tonic-gate
9690Sstevel@tonic-gate /* now two strings, type and value */
9700Sstevel@tonic-gate *eqsign = '\0';
9710Sstevel@tonic-gate
9720Sstevel@tonic-gate /* remove type's leading spaces */
9730Sstevel@tonic-gate while (tf < tl && *tf == SPACETOK)
9740Sstevel@tonic-gate tf++;
9750Sstevel@tonic-gate /* remove type's trailing spaces */
9760Sstevel@tonic-gate while (tf < tl && *tl == SPACETOK)
9770Sstevel@tonic-gate tl--;
9780Sstevel@tonic-gate /* add '=' separator back */
9790Sstevel@tonic-gate *(++tl) = '=';
9800Sstevel@tonic-gate /* remove value's leading spaces */
9810Sstevel@tonic-gate while (vf < vl && *vf == SPACETOK)
9820Sstevel@tonic-gate vf++;
9830Sstevel@tonic-gate /* remove value's trailing spaces */
9840Sstevel@tonic-gate while (vf < vl && *vl == SPACETOK)
9850Sstevel@tonic-gate *vl-- = '\0';
9860Sstevel@tonic-gate
9870Sstevel@tonic-gate /* move value up if necessary */
9880Sstevel@tonic-gate if (vf != tl + 1)
9890Sstevel@tonic-gate (void) strcpy(tl + 1, vf);
9900Sstevel@tonic-gate
9910Sstevel@tonic-gate return (tf);
9920Sstevel@tonic-gate }
9930Sstevel@tonic-gate
9940Sstevel@tonic-gate static
9950Sstevel@tonic-gate ns_ldap_cookie_t *
init_search_state_machine()9960Sstevel@tonic-gate init_search_state_machine()
9970Sstevel@tonic-gate {
9980Sstevel@tonic-gate ns_ldap_cookie_t *cookie;
9990Sstevel@tonic-gate ns_config_t *cfg;
10000Sstevel@tonic-gate
10010Sstevel@tonic-gate cookie = (ns_ldap_cookie_t *)calloc(1, sizeof (ns_ldap_cookie_t));
10020Sstevel@tonic-gate if (cookie == NULL)
10030Sstevel@tonic-gate return (NULL);
10040Sstevel@tonic-gate cookie->state = INIT;
10050Sstevel@tonic-gate /* assign other state variables */
10060Sstevel@tonic-gate cfg = __s_api_loadrefresh_config();
10070Sstevel@tonic-gate cookie->connectionId = -1;
10080Sstevel@tonic-gate if (cfg == NULL ||
10094765Smj162486 cfg->paramList[NS_LDAP_SEARCH_TIME_P].ns_ptype == NS_UNKNOWN) {
10100Sstevel@tonic-gate cookie->search_timeout.tv_sec = NS_DEFAULT_SEARCH_TIMEOUT;
10110Sstevel@tonic-gate } else {
10120Sstevel@tonic-gate cookie->search_timeout.tv_sec =
10134765Smj162486 cfg->paramList[NS_LDAP_SEARCH_TIME_P].ns_i;
10140Sstevel@tonic-gate }
10150Sstevel@tonic-gate if (cfg != NULL)
10160Sstevel@tonic-gate __s_api_release_config(cfg);
10170Sstevel@tonic-gate cookie->search_timeout.tv_usec = 0;
10180Sstevel@tonic-gate
10190Sstevel@tonic-gate return (cookie);
10200Sstevel@tonic-gate }
10210Sstevel@tonic-gate
10220Sstevel@tonic-gate static void
delete_search_cookie(ns_ldap_cookie_t * cookie)10230Sstevel@tonic-gate delete_search_cookie(ns_ldap_cookie_t *cookie)
10240Sstevel@tonic-gate {
10250Sstevel@tonic-gate if (cookie == NULL)
10260Sstevel@tonic-gate return;
10270Sstevel@tonic-gate if (cookie->connectionId > -1)
10280Sstevel@tonic-gate DropConnection(cookie->connectionId, cookie->i_flags);
10290Sstevel@tonic-gate if (cookie->filter)
10300Sstevel@tonic-gate free(cookie->filter);
10310Sstevel@tonic-gate if (cookie->i_filter)
10320Sstevel@tonic-gate free(cookie->i_filter);
10330Sstevel@tonic-gate if (cookie->service)
10340Sstevel@tonic-gate free(cookie->service);
10350Sstevel@tonic-gate if (cookie->sdlist)
10360Sstevel@tonic-gate (void) __ns_ldap_freeSearchDescriptors(&(cookie->sdlist));
10370Sstevel@tonic-gate if (cookie->result)
10380Sstevel@tonic-gate (void) __ns_ldap_freeResult(&cookie->result);
10390Sstevel@tonic-gate if (cookie->attribute)
10400Sstevel@tonic-gate __s_api_free2dArray(cookie->attribute);
10410Sstevel@tonic-gate if (cookie->errorp)
10420Sstevel@tonic-gate (void) __ns_ldap_freeError(&cookie->errorp);
10430Sstevel@tonic-gate if (cookie->reflist)
10440Sstevel@tonic-gate __s_api_deleteRefInfo(cookie->reflist);
10450Sstevel@tonic-gate if (cookie->basedn)
10460Sstevel@tonic-gate free(cookie->basedn);
10470Sstevel@tonic-gate if (cookie->ctrlCookie)
10480Sstevel@tonic-gate ber_bvfree(cookie->ctrlCookie);
10490Sstevel@tonic-gate _freeControlList(&cookie->p_serverctrls);
10501179Svv149972 if (cookie->resultctrl)
10511179Svv149972 ldap_controls_free(cookie->resultctrl);
10520Sstevel@tonic-gate free(cookie);
10530Sstevel@tonic-gate }
10540Sstevel@tonic-gate
10550Sstevel@tonic-gate static int
get_mapped_filter(ns_ldap_cookie_t * cookie,char ** new_filter)10560Sstevel@tonic-gate get_mapped_filter(ns_ldap_cookie_t *cookie, char **new_filter)
10570Sstevel@tonic-gate {
10580Sstevel@tonic-gate
10590Sstevel@tonic-gate typedef struct filter_mapping_info {
10600Sstevel@tonic-gate char oc_or_attr;
10610Sstevel@tonic-gate char *name_start;
10620Sstevel@tonic-gate char *name_end;
10630Sstevel@tonic-gate char *veq_pos;
10640Sstevel@tonic-gate char *from_name;
10650Sstevel@tonic-gate char *to_name;
10660Sstevel@tonic-gate char **mapping;
10670Sstevel@tonic-gate } filter_mapping_info_t;
10680Sstevel@tonic-gate
10690Sstevel@tonic-gate char *c, *last_copied;
10700Sstevel@tonic-gate char *filter_c, *filter_c_next;
10710Sstevel@tonic-gate char *key, *tail, *head;
10720Sstevel@tonic-gate char errstr[MAXERROR];
10730Sstevel@tonic-gate int num_eq = 0, num_veq = 0;
10740Sstevel@tonic-gate int in_quote = FALSE;
10752031Svt115884 int is_value = FALSE;
10760Sstevel@tonic-gate int i, j, oc_len, len;
10770Sstevel@tonic-gate int at_least_one = FALSE;
10780Sstevel@tonic-gate filter_mapping_info_t **info, *info1;
10790Sstevel@tonic-gate char **mapping;
10800Sstevel@tonic-gate char *service, *filter, *err;
10810Sstevel@tonic-gate int auto_service = FALSE;
10820Sstevel@tonic-gate
10830Sstevel@tonic-gate if (cookie == NULL || new_filter == NULL)
10840Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
10850Sstevel@tonic-gate
10860Sstevel@tonic-gate *new_filter = NULL;
10870Sstevel@tonic-gate service = cookie->service;
10880Sstevel@tonic-gate filter = cookie->filter;
10890Sstevel@tonic-gate
10900Sstevel@tonic-gate /*
10910Sstevel@tonic-gate * count the number of '=' char
10920Sstevel@tonic-gate */
10930Sstevel@tonic-gate for (c = filter; *c; c++) {
10940Sstevel@tonic-gate if (*c == TOKENSEPARATOR)
10950Sstevel@tonic-gate num_eq++;
10960Sstevel@tonic-gate }
10970Sstevel@tonic-gate
10980Sstevel@tonic-gate if (service != NULL && strncasecmp(service, "auto_", 5) == 0)
10990Sstevel@tonic-gate auto_service = TRUE;
11000Sstevel@tonic-gate
11010Sstevel@tonic-gate /*
11020Sstevel@tonic-gate * See if schema mapping existed for the given service.
11030Sstevel@tonic-gate * If not, just return success.
11040Sstevel@tonic-gate */
11050Sstevel@tonic-gate mapping = __ns_ldap_getOrigAttribute(service,
11064765Smj162486 NS_HASH_SCHEMA_MAPPING_EXISTED);
11070Sstevel@tonic-gate
11080Sstevel@tonic-gate if (mapping == NULL && auto_service)
11090Sstevel@tonic-gate /*
11100Sstevel@tonic-gate * if service == auto_* and no
11110Sstevel@tonic-gate * schema mapping found
11120Sstevel@tonic-gate * then try automount
11130Sstevel@tonic-gate */
11140Sstevel@tonic-gate mapping = __ns_ldap_getOrigAttribute(
11154765Smj162486 "automount", NS_HASH_SCHEMA_MAPPING_EXISTED);
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate if (mapping)
11180Sstevel@tonic-gate __s_api_free2dArray(mapping);
11190Sstevel@tonic-gate else
11200Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
11210Sstevel@tonic-gate
11220Sstevel@tonic-gate /*
11230Sstevel@tonic-gate * no '=' sign, just say OK and return nothing
11240Sstevel@tonic-gate */
11250Sstevel@tonic-gate if (num_eq == 0)
11260Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
11270Sstevel@tonic-gate
11280Sstevel@tonic-gate /*
11290Sstevel@tonic-gate * Make a copy of the filter string
11300Sstevel@tonic-gate * for saving the name of the objectclasses or
11310Sstevel@tonic-gate * attributes that need to be passed to the
11320Sstevel@tonic-gate * objectclass or attribute mapping functions.
11330Sstevel@tonic-gate * pointer "info->from_name" points to the locations
11340Sstevel@tonic-gate * within this string.
11350Sstevel@tonic-gate *
11360Sstevel@tonic-gate * The input filter string, filter, will be used
11370Sstevel@tonic-gate * to indicate where these names start and end.
11380Sstevel@tonic-gate * pointers "info->name_start" and "info->name_end"
11390Sstevel@tonic-gate * point to locations within the input filter string,
11400Sstevel@tonic-gate * and are used at the end of this function to
11410Sstevel@tonic-gate * merge the original filter data with the
11420Sstevel@tonic-gate * mapped objectclass or attribute names.
11430Sstevel@tonic-gate */
11440Sstevel@tonic-gate filter_c = strdup(filter);
11450Sstevel@tonic-gate if (filter_c == NULL)
11460Sstevel@tonic-gate return (NS_LDAP_MEMORY);
11470Sstevel@tonic-gate filter_c_next = filter_c;
11480Sstevel@tonic-gate
11490Sstevel@tonic-gate /*
11500Sstevel@tonic-gate * get memory for info arrays
11510Sstevel@tonic-gate */
11520Sstevel@tonic-gate info = (filter_mapping_info_t **)calloc(num_eq + 1,
11534765Smj162486 sizeof (filter_mapping_info_t *));
11540Sstevel@tonic-gate
11550Sstevel@tonic-gate if (info == NULL) {
11560Sstevel@tonic-gate free(filter_c);
11570Sstevel@tonic-gate return (NS_LDAP_MEMORY);
11580Sstevel@tonic-gate }
11590Sstevel@tonic-gate
11600Sstevel@tonic-gate /*
11610Sstevel@tonic-gate * find valid '=' for further processing,
11620Sstevel@tonic-gate * ignore the "escaped =" (.i.e. "\="), or
11630Sstevel@tonic-gate * "=" in quoted string
11640Sstevel@tonic-gate */
11650Sstevel@tonic-gate for (c = filter_c; *c; c++) {
11660Sstevel@tonic-gate
11670Sstevel@tonic-gate switch (*c) {
11680Sstevel@tonic-gate case TOKENSEPARATOR:
11692031Svt115884 if (!in_quote && !is_value) {
11700Sstevel@tonic-gate info1 = (filter_mapping_info_t *)calloc(1,
11714765Smj162486 sizeof (filter_mapping_info_t));
11720Sstevel@tonic-gate if (!info1) {
11730Sstevel@tonic-gate free(filter_c);
11740Sstevel@tonic-gate for (i = 0; i < num_veq; i++)
11750Sstevel@tonic-gate free(info[i]);
11760Sstevel@tonic-gate free(info);
11770Sstevel@tonic-gate return (NS_LDAP_MEMORY);
11780Sstevel@tonic-gate }
11790Sstevel@tonic-gate info[num_veq] = info1;
11800Sstevel@tonic-gate
11810Sstevel@tonic-gate /*
11820Sstevel@tonic-gate * remember the location of this "="
11830Sstevel@tonic-gate */
11840Sstevel@tonic-gate info[num_veq++]->veq_pos = c;
11852031Svt115884
11862031Svt115884 /*
11872031Svt115884 * skip until the end of the attribute value
11882031Svt115884 */
11892031Svt115884 is_value = TRUE;
11900Sstevel@tonic-gate }
11910Sstevel@tonic-gate break;
11922031Svt115884 case CPARATOK:
11932031Svt115884 /*
11942031Svt115884 * mark the end of the attribute value
11952031Svt115884 */
11962031Svt115884 if (!in_quote)
11972031Svt115884 is_value = FALSE;
11982031Svt115884 break;
11990Sstevel@tonic-gate case QUOTETOK:
12000Sstevel@tonic-gate /*
12010Sstevel@tonic-gate * switch on/off the in_quote mode
12020Sstevel@tonic-gate */
12030Sstevel@tonic-gate in_quote = (in_quote == FALSE);
12040Sstevel@tonic-gate break;
12050Sstevel@tonic-gate case '\\':
12060Sstevel@tonic-gate /*
12070Sstevel@tonic-gate * ignore escape characters
12080Sstevel@tonic-gate * don't skip if next char is '\0'
12090Sstevel@tonic-gate */
12100Sstevel@tonic-gate if (!in_quote)
12110Sstevel@tonic-gate if (*(++c) == '\0')
12120Sstevel@tonic-gate c--;
12130Sstevel@tonic-gate break;
12140Sstevel@tonic-gate }
12150Sstevel@tonic-gate
12160Sstevel@tonic-gate }
12170Sstevel@tonic-gate
12180Sstevel@tonic-gate /*
12190Sstevel@tonic-gate * for each valid "=" found, get the name to
12200Sstevel@tonic-gate * be mapped
12210Sstevel@tonic-gate */
12220Sstevel@tonic-gate oc_len = strlen("objectclass");
12230Sstevel@tonic-gate for (i = 0; i < num_veq; i++) {
12240Sstevel@tonic-gate
12250Sstevel@tonic-gate /*
12260Sstevel@tonic-gate * look at the left side of "=" to see
12270Sstevel@tonic-gate * if assertion is "objectclass=<ocname>"
12280Sstevel@tonic-gate * or "<attribute name>=<attribute value>"
12290Sstevel@tonic-gate *
12300Sstevel@tonic-gate * first skip spaces before "=".
12310Sstevel@tonic-gate * Note that filter_c_next may not point to the
12320Sstevel@tonic-gate * start of the filter string. For i > 0,
12330Sstevel@tonic-gate * it points to the end of the last name processed + 2
12340Sstevel@tonic-gate */
12350Sstevel@tonic-gate for (tail = info[i]->veq_pos; (tail > filter_c_next) &&
12364765Smj162486 (*(tail - 1) == SPACETOK); tail--)
12374765Smj162486 ;
12380Sstevel@tonic-gate
12390Sstevel@tonic-gate /*
12400Sstevel@tonic-gate * mark the end of the left side string (the key)
12410Sstevel@tonic-gate */
12420Sstevel@tonic-gate *tail = '\0';
12430Sstevel@tonic-gate info[i]->name_end = tail - filter_c - 1 + filter;
12440Sstevel@tonic-gate
12450Sstevel@tonic-gate /*
12460Sstevel@tonic-gate * find the start of the key
12470Sstevel@tonic-gate */
12480Sstevel@tonic-gate key = filter_c_next;
12490Sstevel@tonic-gate for (c = tail; filter_c_next <= c; c--) {
12500Sstevel@tonic-gate /* OPARATOK is '(' */
12510Sstevel@tonic-gate if (*c == OPARATOK ||
12524765Smj162486 *c == SPACETOK) {
12530Sstevel@tonic-gate key = c + 1;
12540Sstevel@tonic-gate break;
12550Sstevel@tonic-gate }
12560Sstevel@tonic-gate }
12570Sstevel@tonic-gate info[i]->name_start = key - filter_c + filter;
12580Sstevel@tonic-gate
12590Sstevel@tonic-gate if ((key + oc_len) <= tail) {
12600Sstevel@tonic-gate if (strncasecmp(key, "objectclass",
12614765Smj162486 oc_len) == 0) {
12620Sstevel@tonic-gate /*
12630Sstevel@tonic-gate * assertion is "objectclass=ocname",
12640Sstevel@tonic-gate * ocname is the one needs to be mapped
12650Sstevel@tonic-gate *
12660Sstevel@tonic-gate * skip spaces after "=" to find start
12670Sstevel@tonic-gate * of the ocname
12680Sstevel@tonic-gate */
12690Sstevel@tonic-gate head = info[i]->veq_pos;
12700Sstevel@tonic-gate for (head = info[i]->veq_pos + 1;
12714765Smj162486 *head && *head == SPACETOK; head++)
12724765Smj162486 ;
12730Sstevel@tonic-gate
12740Sstevel@tonic-gate /* ignore empty ocname */
12750Sstevel@tonic-gate if (!(*head))
12760Sstevel@tonic-gate continue;
12770Sstevel@tonic-gate
12780Sstevel@tonic-gate info[i]->name_start = head - filter_c +
12794765Smj162486 filter;
12800Sstevel@tonic-gate
12810Sstevel@tonic-gate /*
12820Sstevel@tonic-gate * now find the end of the ocname
12830Sstevel@tonic-gate */
12840Sstevel@tonic-gate for (c = head; ; c++) {
12850Sstevel@tonic-gate /* CPARATOK is ')' */
12860Sstevel@tonic-gate if (*c == CPARATOK ||
12874765Smj162486 *c == '\0' ||
12884765Smj162486 *c == SPACETOK) {
12890Sstevel@tonic-gate *c = '\0';
12900Sstevel@tonic-gate info[i]->name_end =
12914765Smj162486 c - filter_c - 1 +
12924765Smj162486 filter;
12930Sstevel@tonic-gate filter_c_next = c + 1;
12940Sstevel@tonic-gate info[i]->oc_or_attr = 'o';
12950Sstevel@tonic-gate info[i]->from_name = head;
12960Sstevel@tonic-gate break;
12970Sstevel@tonic-gate }
12980Sstevel@tonic-gate }
12990Sstevel@tonic-gate }
13000Sstevel@tonic-gate }
13010Sstevel@tonic-gate
13020Sstevel@tonic-gate /*
13030Sstevel@tonic-gate * assertion is not "objectclass=ocname",
13040Sstevel@tonic-gate * assume assertion is "<key> = <value>",
13050Sstevel@tonic-gate * <key> is the one needs to be mapped
13060Sstevel@tonic-gate */
13070Sstevel@tonic-gate if (info[i]->from_name == NULL && strlen(key) > 0) {
13080Sstevel@tonic-gate info[i]->oc_or_attr = 'a';
13090Sstevel@tonic-gate info[i]->from_name = key;
13100Sstevel@tonic-gate }
13110Sstevel@tonic-gate }
13120Sstevel@tonic-gate
13130Sstevel@tonic-gate /* perform schema mapping */
13140Sstevel@tonic-gate for (i = 0; i < num_veq; i++) {
13150Sstevel@tonic-gate if (info[i]->from_name == NULL)
13160Sstevel@tonic-gate continue;
13170Sstevel@tonic-gate
13180Sstevel@tonic-gate if (info[i]->oc_or_attr == 'a')
13190Sstevel@tonic-gate info[i]->mapping =
13204765Smj162486 __ns_ldap_getMappedAttributes(service,
13214765Smj162486 info[i]->from_name);
13220Sstevel@tonic-gate else
13230Sstevel@tonic-gate info[i]->mapping =
13244765Smj162486 __ns_ldap_getMappedObjectClass(service,
13254765Smj162486 info[i]->from_name);
13260Sstevel@tonic-gate
13270Sstevel@tonic-gate if (info[i]->mapping == NULL && auto_service) {
13280Sstevel@tonic-gate /*
13290Sstevel@tonic-gate * If no mapped attribute/objectclass is found
13300Sstevel@tonic-gate * and service == auto*
13310Sstevel@tonic-gate * try to find automount's
13320Sstevel@tonic-gate * mapped attribute/objectclass
13330Sstevel@tonic-gate */
13340Sstevel@tonic-gate if (info[i]->oc_or_attr == 'a')
13350Sstevel@tonic-gate info[i]->mapping =
13364765Smj162486 __ns_ldap_getMappedAttributes("automount",
13374765Smj162486 info[i]->from_name);
13380Sstevel@tonic-gate else
13390Sstevel@tonic-gate info[i]->mapping =
13404765Smj162486 __ns_ldap_getMappedObjectClass("automount",
13414765Smj162486 info[i]->from_name);
13420Sstevel@tonic-gate }
13430Sstevel@tonic-gate
13440Sstevel@tonic-gate if (info[i]->mapping == NULL ||
13454765Smj162486 info[i]->mapping[0] == NULL) {
13460Sstevel@tonic-gate info[i]->to_name = NULL;
13470Sstevel@tonic-gate } else if (info[i]->mapping[1] == NULL) {
13480Sstevel@tonic-gate info[i]->to_name = info[i]->mapping[0];
13490Sstevel@tonic-gate at_least_one = TRUE;
13500Sstevel@tonic-gate } else {
13510Sstevel@tonic-gate __s_api_free2dArray(info[i]->mapping);
13520Sstevel@tonic-gate /*
13530Sstevel@tonic-gate * multiple mapping
13540Sstevel@tonic-gate * not allowed
13550Sstevel@tonic-gate */
13560Sstevel@tonic-gate (void) sprintf(errstr,
13574765Smj162486 gettext(
13584765Smj162486 "Multiple attribute or objectclass "
13594765Smj162486 "mapping for '%s' in filter "
13604765Smj162486 "'%s' not allowed."),
13614765Smj162486 info[i]->from_name, filter);
13620Sstevel@tonic-gate err = strdup(errstr);
13630Sstevel@tonic-gate if (err)
13640Sstevel@tonic-gate MKERROR(LOG_WARNING, cookie->errorp,
13654765Smj162486 NS_CONFIG_SYNTAX,
13664765Smj162486 err, NULL);
13670Sstevel@tonic-gate
13680Sstevel@tonic-gate free(filter_c);
13690Sstevel@tonic-gate for (j = 0; j < num_veq; j++) {
13700Sstevel@tonic-gate if (info[j]->mapping)
13710Sstevel@tonic-gate __s_api_free2dArray(
13724765Smj162486 info[j]->mapping);
13730Sstevel@tonic-gate free(info[j]);
13740Sstevel@tonic-gate }
13750Sstevel@tonic-gate free(info);
13760Sstevel@tonic-gate return (NS_LDAP_CONFIG);
13770Sstevel@tonic-gate }
13780Sstevel@tonic-gate }
13790Sstevel@tonic-gate
13800Sstevel@tonic-gate
13810Sstevel@tonic-gate if (at_least_one) {
13820Sstevel@tonic-gate
13830Sstevel@tonic-gate len = strlen(filter);
13840Sstevel@tonic-gate last_copied = filter - 1;
13850Sstevel@tonic-gate
13860Sstevel@tonic-gate for (i = 0; i < num_veq; i++) {
13870Sstevel@tonic-gate if (info[i]->to_name)
13880Sstevel@tonic-gate len += strlen(info[i]->to_name);
13890Sstevel@tonic-gate }
13900Sstevel@tonic-gate
13910Sstevel@tonic-gate *new_filter = (char *)calloc(1, len);
13920Sstevel@tonic-gate if (*new_filter == NULL) {
13930Sstevel@tonic-gate free(filter_c);
13940Sstevel@tonic-gate for (j = 0; j < num_veq; j++) {
13950Sstevel@tonic-gate if (info[j]->mapping)
13960Sstevel@tonic-gate __s_api_free2dArray(
13974765Smj162486 info[j]->mapping);
13980Sstevel@tonic-gate free(info[j]);
13990Sstevel@tonic-gate }
14000Sstevel@tonic-gate free(info);
14010Sstevel@tonic-gate return (NS_LDAP_MEMORY);
14020Sstevel@tonic-gate }
14030Sstevel@tonic-gate
14040Sstevel@tonic-gate for (i = 0; i < num_veq; i++) {
14050Sstevel@tonic-gate if (info[i]->to_name != NULL &&
14064765Smj162486 info[i]->to_name != NULL) {
14074765Smj162486
14084765Smj162486 /*
14094765Smj162486 * copy the original filter data
14104765Smj162486 * between the last name and current
14114765Smj162486 * name
14124765Smj162486 */
14134765Smj162486 if ((last_copied + 1) != info[i]->name_start)
14144765Smj162486 (void) strncat(*new_filter,
14154765Smj162486 last_copied + 1,
14164765Smj162486 info[i]->name_start -
14174765Smj162486 last_copied - 1);
14180Sstevel@tonic-gate
14190Sstevel@tonic-gate /* the data is copied */
14200Sstevel@tonic-gate last_copied = info[i]->name_end;
14210Sstevel@tonic-gate
14220Sstevel@tonic-gate /*
14230Sstevel@tonic-gate * replace the name with
14240Sstevel@tonic-gate * the mapped name
14250Sstevel@tonic-gate */
14260Sstevel@tonic-gate (void) strcat(*new_filter, info[i]->to_name);
14270Sstevel@tonic-gate }
14280Sstevel@tonic-gate
14290Sstevel@tonic-gate /* copy the filter data after the last name */
14300Sstevel@tonic-gate if (i == (num_veq -1) &&
14314765Smj162486 info[i]->name_end <
14324765Smj162486 (filter + strlen(filter)))
14330Sstevel@tonic-gate (void) strncat(*new_filter, last_copied + 1,
14344765Smj162486 filter + strlen(filter) -
14354765Smj162486 last_copied - 1);
14360Sstevel@tonic-gate }
14370Sstevel@tonic-gate
14380Sstevel@tonic-gate }
14390Sstevel@tonic-gate
14400Sstevel@tonic-gate /* free memory */
14410Sstevel@tonic-gate free(filter_c);
14420Sstevel@tonic-gate for (j = 0; j < num_veq; j++) {
14430Sstevel@tonic-gate if (info[j]->mapping)
14440Sstevel@tonic-gate __s_api_free2dArray(info[j]->mapping);
14450Sstevel@tonic-gate free(info[j]);
14460Sstevel@tonic-gate }
14470Sstevel@tonic-gate free(info);
14480Sstevel@tonic-gate
14490Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
14500Sstevel@tonic-gate }
14510Sstevel@tonic-gate
14520Sstevel@tonic-gate static int
setup_next_search(ns_ldap_cookie_t * cookie)14530Sstevel@tonic-gate setup_next_search(ns_ldap_cookie_t *cookie)
14540Sstevel@tonic-gate {
14550Sstevel@tonic-gate ns_ldap_search_desc_t *dptr;
14560Sstevel@tonic-gate int scope;
14570Sstevel@tonic-gate char *filter, *str;
14580Sstevel@tonic-gate int baselen;
14590Sstevel@tonic-gate int rc;
14600Sstevel@tonic-gate void **param;
14610Sstevel@tonic-gate
14620Sstevel@tonic-gate dptr = *cookie->sdpos;
14630Sstevel@tonic-gate scope = cookie->i_flags & (NS_LDAP_SCOPE_BASE |
14644765Smj162486 NS_LDAP_SCOPE_ONELEVEL |
14654765Smj162486 NS_LDAP_SCOPE_SUBTREE);
14660Sstevel@tonic-gate if (scope)
14670Sstevel@tonic-gate cookie->scope = scope;
14680Sstevel@tonic-gate else
14690Sstevel@tonic-gate cookie->scope = dptr->scope;
14700Sstevel@tonic-gate switch (cookie->scope) {
14710Sstevel@tonic-gate case NS_LDAP_SCOPE_BASE:
14720Sstevel@tonic-gate cookie->scope = LDAP_SCOPE_BASE;
14730Sstevel@tonic-gate break;
14740Sstevel@tonic-gate case NS_LDAP_SCOPE_ONELEVEL:
14750Sstevel@tonic-gate cookie->scope = LDAP_SCOPE_ONELEVEL;
14760Sstevel@tonic-gate break;
14770Sstevel@tonic-gate case NS_LDAP_SCOPE_SUBTREE:
14780Sstevel@tonic-gate cookie->scope = LDAP_SCOPE_SUBTREE;
14790Sstevel@tonic-gate break;
14800Sstevel@tonic-gate }
14810Sstevel@tonic-gate
14820Sstevel@tonic-gate filter = NULL;
14830Sstevel@tonic-gate if (cookie->use_filtercb && cookie->init_filter_cb &&
14844765Smj162486 dptr->filter && strlen(dptr->filter) > 0) {
14850Sstevel@tonic-gate (*cookie->init_filter_cb)(dptr, &filter,
14864765Smj162486 cookie->userdata);
14870Sstevel@tonic-gate }
14880Sstevel@tonic-gate if (filter == NULL) {
14890Sstevel@tonic-gate if (cookie->i_filter == NULL) {
14900Sstevel@tonic-gate cookie->err_rc = NS_LDAP_INVALID_PARAM;
14910Sstevel@tonic-gate return (-1);
14920Sstevel@tonic-gate } else {
14933762Srm88369 if (cookie->filter)
14943762Srm88369 free(cookie->filter);
14950Sstevel@tonic-gate cookie->filter = strdup(cookie->i_filter);
14960Sstevel@tonic-gate if (cookie->filter == NULL) {
14970Sstevel@tonic-gate cookie->err_rc = NS_LDAP_MEMORY;
14980Sstevel@tonic-gate return (-1);
14990Sstevel@tonic-gate }
15000Sstevel@tonic-gate }
15010Sstevel@tonic-gate } else {
15023762Srm88369 if (cookie->filter)
15033762Srm88369 free(cookie->filter);
15040Sstevel@tonic-gate cookie->filter = strdup(filter);
15050Sstevel@tonic-gate free(filter);
15060Sstevel@tonic-gate if (cookie->filter == NULL) {
15070Sstevel@tonic-gate cookie->err_rc = NS_LDAP_MEMORY;
15080Sstevel@tonic-gate return (-1);
15090Sstevel@tonic-gate }
15100Sstevel@tonic-gate }
15110Sstevel@tonic-gate
15120Sstevel@tonic-gate /*
15130Sstevel@tonic-gate * perform attribute/objectclass mapping on filter
15140Sstevel@tonic-gate */
15150Sstevel@tonic-gate filter = NULL;
15160Sstevel@tonic-gate
15170Sstevel@tonic-gate if (cookie->service) {
15180Sstevel@tonic-gate rc = get_mapped_filter(cookie, &filter);
15190Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
15200Sstevel@tonic-gate cookie->err_rc = rc;
15210Sstevel@tonic-gate return (-1);
15220Sstevel@tonic-gate } else {
15230Sstevel@tonic-gate /*
15240Sstevel@tonic-gate * get_mapped_filter returns
15250Sstevel@tonic-gate * NULL filter pointer, if
15260Sstevel@tonic-gate * no mapping was done
15270Sstevel@tonic-gate */
15280Sstevel@tonic-gate if (filter) {
15290Sstevel@tonic-gate free(cookie->filter);
15300Sstevel@tonic-gate cookie->filter = filter;
15310Sstevel@tonic-gate }
15320Sstevel@tonic-gate }
15330Sstevel@tonic-gate }
15340Sstevel@tonic-gate
15350Sstevel@tonic-gate /*
15360Sstevel@tonic-gate * validate filter to make sure it's legal
15370Sstevel@tonic-gate * [remove redundant ()'s]
15380Sstevel@tonic-gate */
15390Sstevel@tonic-gate rc = validate_filter(cookie);
15400Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
15410Sstevel@tonic-gate cookie->err_rc = rc;
15420Sstevel@tonic-gate return (-1);
15430Sstevel@tonic-gate }
15440Sstevel@tonic-gate
15450Sstevel@tonic-gate baselen = strlen(dptr->basedn);
15460Sstevel@tonic-gate if (baselen > 0 && dptr->basedn[baselen-1] == COMMATOK) {
15470Sstevel@tonic-gate rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
15484765Smj162486 (void ***)¶m, &cookie->errorp);
15490Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
15500Sstevel@tonic-gate cookie->err_rc = rc;
15510Sstevel@tonic-gate return (-1);
15520Sstevel@tonic-gate }
15530Sstevel@tonic-gate str = ((char **)param)[0];
15540Sstevel@tonic-gate baselen += strlen(str)+1;
15553762Srm88369 if (cookie->basedn)
15563762Srm88369 free(cookie->basedn);
15570Sstevel@tonic-gate cookie->basedn = (char *)malloc(baselen);
15580Sstevel@tonic-gate if (cookie->basedn == NULL) {
15590Sstevel@tonic-gate cookie->err_rc = NS_LDAP_MEMORY;
15600Sstevel@tonic-gate return (-1);
15610Sstevel@tonic-gate }
15620Sstevel@tonic-gate (void) strcpy(cookie->basedn, dptr->basedn);
15630Sstevel@tonic-gate (void) strcat(cookie->basedn, str);
15640Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶m);
15650Sstevel@tonic-gate } else {
15663762Srm88369 if (cookie->basedn)
15673762Srm88369 free(cookie->basedn);
15680Sstevel@tonic-gate cookie->basedn = strdup(dptr->basedn);
15690Sstevel@tonic-gate }
15700Sstevel@tonic-gate return (0);
15710Sstevel@tonic-gate }
15720Sstevel@tonic-gate
15730Sstevel@tonic-gate static int
setup_referral_search(ns_ldap_cookie_t * cookie)15740Sstevel@tonic-gate setup_referral_search(ns_ldap_cookie_t *cookie)
15750Sstevel@tonic-gate {
15760Sstevel@tonic-gate ns_referral_info_t *ref;
15770Sstevel@tonic-gate
15780Sstevel@tonic-gate ref = cookie->refpos;
15790Sstevel@tonic-gate cookie->scope = ref->refScope;
15800Sstevel@tonic-gate if (cookie->filter) {
15810Sstevel@tonic-gate free(cookie->filter);
15820Sstevel@tonic-gate }
15830Sstevel@tonic-gate cookie->filter = strdup(ref->refFilter);
15840Sstevel@tonic-gate if (cookie->basedn) {
15850Sstevel@tonic-gate free(cookie->basedn);
15860Sstevel@tonic-gate }
15870Sstevel@tonic-gate cookie->basedn = strdup(ref->refDN);
15880Sstevel@tonic-gate if (cookie->filter == NULL || cookie->basedn == NULL) {
15890Sstevel@tonic-gate cookie->err_rc = NS_LDAP_MEMORY;
15900Sstevel@tonic-gate return (-1);
15910Sstevel@tonic-gate }
15920Sstevel@tonic-gate return (0);
15930Sstevel@tonic-gate }
15940Sstevel@tonic-gate
15950Sstevel@tonic-gate static int
get_current_session(ns_ldap_cookie_t * cookie)15960Sstevel@tonic-gate get_current_session(ns_ldap_cookie_t *cookie)
15970Sstevel@tonic-gate {
15980Sstevel@tonic-gate ConnectionID connectionId = -1;
15990Sstevel@tonic-gate Connection *conp = NULL;
16000Sstevel@tonic-gate int rc;
16010Sstevel@tonic-gate int fail_if_new_pwd_reqd = 1;
16020Sstevel@tonic-gate
16030Sstevel@tonic-gate rc = __s_api_getConnection(NULL, cookie->i_flags,
16044765Smj162486 cookie->i_auth, &connectionId, &conp,
16054765Smj162486 &cookie->errorp, fail_if_new_pwd_reqd,
16066842Sth160488 cookie->nopasswd_acct_mgmt, cookie->conn_user);
16070Sstevel@tonic-gate
16080Sstevel@tonic-gate /*
16090Sstevel@tonic-gate * If password control attached in *cookie->errorp,
16100Sstevel@tonic-gate * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
16110Sstevel@tonic-gate * free the error structure (we do not need
16120Sstevel@tonic-gate * the sec_to_expired info).
16130Sstevel@tonic-gate * Reset rc to NS_LDAP_SUCCESS.
16140Sstevel@tonic-gate */
16150Sstevel@tonic-gate if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
16160Sstevel@tonic-gate (void) __ns_ldap_freeError(
16174765Smj162486 &cookie->errorp);
16180Sstevel@tonic-gate cookie->errorp = NULL;
16190Sstevel@tonic-gate rc = NS_LDAP_SUCCESS;
16200Sstevel@tonic-gate }
16210Sstevel@tonic-gate
16220Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
16230Sstevel@tonic-gate cookie->err_rc = rc;
16240Sstevel@tonic-gate return (-1);
16250Sstevel@tonic-gate }
16260Sstevel@tonic-gate cookie->conn = conp;
16270Sstevel@tonic-gate cookie->connectionId = connectionId;
16280Sstevel@tonic-gate
16290Sstevel@tonic-gate return (0);
16300Sstevel@tonic-gate }
16310Sstevel@tonic-gate
16320Sstevel@tonic-gate static int
get_next_session(ns_ldap_cookie_t * cookie)16330Sstevel@tonic-gate get_next_session(ns_ldap_cookie_t *cookie)
16340Sstevel@tonic-gate {
16350Sstevel@tonic-gate ConnectionID connectionId = -1;
16360Sstevel@tonic-gate Connection *conp = NULL;
16370Sstevel@tonic-gate int rc;
16380Sstevel@tonic-gate int fail_if_new_pwd_reqd = 1;
16390Sstevel@tonic-gate
16404953Smichen if (cookie->connectionId > -1) {
16410Sstevel@tonic-gate DropConnection(cookie->connectionId, cookie->i_flags);
16424953Smichen cookie->connectionId = -1;
16434953Smichen }
16440Sstevel@tonic-gate
16456842Sth160488 /* If using a MT connection, return it. */
16466842Sth160488 if (cookie->conn_user != NULL &&
16476842Sth160488 cookie->conn_user->conn_mt != NULL)
16486842Sth160488 __s_api_conn_mt_return(cookie->conn_user);
16496842Sth160488
16500Sstevel@tonic-gate rc = __s_api_getConnection(NULL, cookie->i_flags,
16514765Smj162486 cookie->i_auth, &connectionId, &conp,
16524765Smj162486 &cookie->errorp, fail_if_new_pwd_reqd,
16536842Sth160488 cookie->nopasswd_acct_mgmt, cookie->conn_user);
16540Sstevel@tonic-gate
16550Sstevel@tonic-gate /*
16560Sstevel@tonic-gate * If password control attached in *cookie->errorp,
16570Sstevel@tonic-gate * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
16580Sstevel@tonic-gate * free the error structure (we do not need
16590Sstevel@tonic-gate * the sec_to_expired info).
16600Sstevel@tonic-gate * Reset rc to NS_LDAP_SUCCESS.
16610Sstevel@tonic-gate */
16620Sstevel@tonic-gate if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
16630Sstevel@tonic-gate (void) __ns_ldap_freeError(
16644765Smj162486 &cookie->errorp);
16650Sstevel@tonic-gate cookie->errorp = NULL;
16660Sstevel@tonic-gate rc = NS_LDAP_SUCCESS;
16670Sstevel@tonic-gate }
16680Sstevel@tonic-gate
16690Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
16700Sstevel@tonic-gate cookie->err_rc = rc;
16710Sstevel@tonic-gate return (-1);
16720Sstevel@tonic-gate }
16730Sstevel@tonic-gate cookie->conn = conp;
16740Sstevel@tonic-gate cookie->connectionId = connectionId;
16750Sstevel@tonic-gate return (0);
16760Sstevel@tonic-gate }
16770Sstevel@tonic-gate
16780Sstevel@tonic-gate static int
get_referral_session(ns_ldap_cookie_t * cookie)16790Sstevel@tonic-gate get_referral_session(ns_ldap_cookie_t *cookie)
16800Sstevel@tonic-gate {
16810Sstevel@tonic-gate ConnectionID connectionId = -1;
16820Sstevel@tonic-gate Connection *conp = NULL;
16830Sstevel@tonic-gate int rc;
16840Sstevel@tonic-gate int fail_if_new_pwd_reqd = 1;
16850Sstevel@tonic-gate
16864953Smichen if (cookie->connectionId > -1) {
16870Sstevel@tonic-gate DropConnection(cookie->connectionId, cookie->i_flags);
16884953Smichen cookie->connectionId = -1;
16894953Smichen }
16900Sstevel@tonic-gate
16916842Sth160488 /* set it up to use a connection opened for referral */
16926842Sth160488 if (cookie->conn_user != NULL) {
16936842Sth160488 /* If using a MT connection, return it. */
16946842Sth160488 if (cookie->conn_user->conn_mt != NULL)
16956842Sth160488 __s_api_conn_mt_return(cookie->conn_user);
16966842Sth160488 cookie->conn_user->referral = B_TRUE;
16976842Sth160488 }
16986842Sth160488
16990Sstevel@tonic-gate rc = __s_api_getConnection(cookie->refpos->refHost, 0,
17004765Smj162486 cookie->i_auth, &connectionId, &conp,
17014765Smj162486 &cookie->errorp, fail_if_new_pwd_reqd,
17026842Sth160488 cookie->nopasswd_acct_mgmt, cookie->conn_user);
17030Sstevel@tonic-gate
17040Sstevel@tonic-gate /*
17050Sstevel@tonic-gate * If password control attached in *cookie->errorp,
17060Sstevel@tonic-gate * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
17070Sstevel@tonic-gate * free the error structure (we do not need
17080Sstevel@tonic-gate * the sec_to_expired info).
17090Sstevel@tonic-gate * Reset rc to NS_LDAP_SUCCESS.
17100Sstevel@tonic-gate */
17110Sstevel@tonic-gate if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
17120Sstevel@tonic-gate (void) __ns_ldap_freeError(
17134765Smj162486 &cookie->errorp);
17140Sstevel@tonic-gate cookie->errorp = NULL;
17150Sstevel@tonic-gate rc = NS_LDAP_SUCCESS;
17160Sstevel@tonic-gate }
17170Sstevel@tonic-gate
17180Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
17190Sstevel@tonic-gate cookie->err_rc = rc;
17200Sstevel@tonic-gate return (-1);
17210Sstevel@tonic-gate }
17220Sstevel@tonic-gate cookie->conn = conp;
17230Sstevel@tonic-gate cookie->connectionId = connectionId;
17240Sstevel@tonic-gate return (0);
17250Sstevel@tonic-gate }
17260Sstevel@tonic-gate
17270Sstevel@tonic-gate static int
paging_supported(ns_ldap_cookie_t * cookie)17280Sstevel@tonic-gate paging_supported(ns_ldap_cookie_t *cookie)
17290Sstevel@tonic-gate {
17300Sstevel@tonic-gate int rc;
17310Sstevel@tonic-gate
17320Sstevel@tonic-gate cookie->listType = 0;
17330Sstevel@tonic-gate rc = __s_api_isCtrlSupported(cookie->conn,
17344765Smj162486 LDAP_CONTROL_VLVREQUEST);
17350Sstevel@tonic-gate if (rc == NS_LDAP_SUCCESS) {
17360Sstevel@tonic-gate cookie->listType = VLVCTRLFLAG;
17370Sstevel@tonic-gate return (1);
17380Sstevel@tonic-gate }
17390Sstevel@tonic-gate rc = __s_api_isCtrlSupported(cookie->conn,
17404765Smj162486 LDAP_CONTROL_SIMPLE_PAGE);
17410Sstevel@tonic-gate if (rc == NS_LDAP_SUCCESS) {
17420Sstevel@tonic-gate cookie->listType = SIMPLEPAGECTRLFLAG;
17430Sstevel@tonic-gate return (1);
17440Sstevel@tonic-gate }
17450Sstevel@tonic-gate return (0);
17460Sstevel@tonic-gate }
17470Sstevel@tonic-gate
1748*12758SJulian.Pullen@Sun.COM typedef struct servicesorttype {
1749*12758SJulian.Pullen@Sun.COM char *service;
1750*12758SJulian.Pullen@Sun.COM ns_srvsidesort_t type;
1751*12758SJulian.Pullen@Sun.COM } servicesorttype_t;
1752*12758SJulian.Pullen@Sun.COM
1753*12758SJulian.Pullen@Sun.COM static servicesorttype_t *sort_type = NULL;
1754*12758SJulian.Pullen@Sun.COM static int sort_type_size = 0;
1755*12758SJulian.Pullen@Sun.COM static int sort_type_hwm = 0;
1756*12758SJulian.Pullen@Sun.COM static mutex_t sort_type_mutex = DEFAULTMUTEX;
1757*12758SJulian.Pullen@Sun.COM
1758*12758SJulian.Pullen@Sun.COM
1759*12758SJulian.Pullen@Sun.COM static ns_srvsidesort_t
get_srvsidesort_type(char * service)1760*12758SJulian.Pullen@Sun.COM get_srvsidesort_type(char *service)
1761*12758SJulian.Pullen@Sun.COM {
1762*12758SJulian.Pullen@Sun.COM int i;
1763*12758SJulian.Pullen@Sun.COM ns_srvsidesort_t type = SSS_UNKNOWN;
1764*12758SJulian.Pullen@Sun.COM
1765*12758SJulian.Pullen@Sun.COM if (service == NULL)
1766*12758SJulian.Pullen@Sun.COM return (type);
1767*12758SJulian.Pullen@Sun.COM
1768*12758SJulian.Pullen@Sun.COM (void) mutex_lock(&sort_type_mutex);
1769*12758SJulian.Pullen@Sun.COM if (sort_type != NULL) {
1770*12758SJulian.Pullen@Sun.COM for (i = 0; i < sort_type_hwm; i++) {
1771*12758SJulian.Pullen@Sun.COM if (strcmp(sort_type[i].service, service) == 0) {
1772*12758SJulian.Pullen@Sun.COM type = sort_type[i].type;
1773*12758SJulian.Pullen@Sun.COM break;
1774*12758SJulian.Pullen@Sun.COM }
1775*12758SJulian.Pullen@Sun.COM }
1776*12758SJulian.Pullen@Sun.COM }
1777*12758SJulian.Pullen@Sun.COM (void) mutex_unlock(&sort_type_mutex);
1778*12758SJulian.Pullen@Sun.COM return (type);
1779*12758SJulian.Pullen@Sun.COM }
1780*12758SJulian.Pullen@Sun.COM
1781*12758SJulian.Pullen@Sun.COM static void
update_srvsidesort_type(char * service,ns_srvsidesort_t type)1782*12758SJulian.Pullen@Sun.COM update_srvsidesort_type(char *service, ns_srvsidesort_t type)
1783*12758SJulian.Pullen@Sun.COM {
1784*12758SJulian.Pullen@Sun.COM int i, size;
1785*12758SJulian.Pullen@Sun.COM servicesorttype_t *tmp;
1786*12758SJulian.Pullen@Sun.COM
1787*12758SJulian.Pullen@Sun.COM if (service == NULL)
1788*12758SJulian.Pullen@Sun.COM return;
1789*12758SJulian.Pullen@Sun.COM
1790*12758SJulian.Pullen@Sun.COM (void) mutex_lock(&sort_type_mutex);
1791*12758SJulian.Pullen@Sun.COM
1792*12758SJulian.Pullen@Sun.COM for (i = 0; i < sort_type_hwm; i++) {
1793*12758SJulian.Pullen@Sun.COM if (strcmp(sort_type[i].service, service) == 0) {
1794*12758SJulian.Pullen@Sun.COM sort_type[i].type = type;
1795*12758SJulian.Pullen@Sun.COM (void) mutex_unlock(&sort_type_mutex);
1796*12758SJulian.Pullen@Sun.COM return;
1797*12758SJulian.Pullen@Sun.COM }
1798*12758SJulian.Pullen@Sun.COM }
1799*12758SJulian.Pullen@Sun.COM if (sort_type == NULL) {
1800*12758SJulian.Pullen@Sun.COM size = 10;
1801*12758SJulian.Pullen@Sun.COM tmp = malloc(size * sizeof (servicesorttype_t));
1802*12758SJulian.Pullen@Sun.COM if (tmp == NULL) {
1803*12758SJulian.Pullen@Sun.COM (void) mutex_unlock(&sort_type_mutex);
1804*12758SJulian.Pullen@Sun.COM return;
1805*12758SJulian.Pullen@Sun.COM }
1806*12758SJulian.Pullen@Sun.COM sort_type = tmp;
1807*12758SJulian.Pullen@Sun.COM sort_type_size = size;
1808*12758SJulian.Pullen@Sun.COM } else if (sort_type_hwm >= sort_type_size) {
1809*12758SJulian.Pullen@Sun.COM size = sort_type_size + 10;
1810*12758SJulian.Pullen@Sun.COM tmp = realloc(sort_type, size * sizeof (servicesorttype_t));
1811*12758SJulian.Pullen@Sun.COM if (tmp == NULL) {
1812*12758SJulian.Pullen@Sun.COM (void) mutex_unlock(&sort_type_mutex);
1813*12758SJulian.Pullen@Sun.COM return;
1814*12758SJulian.Pullen@Sun.COM }
1815*12758SJulian.Pullen@Sun.COM sort_type = tmp;
1816*12758SJulian.Pullen@Sun.COM sort_type_size = size;
1817*12758SJulian.Pullen@Sun.COM }
1818*12758SJulian.Pullen@Sun.COM sort_type[sort_type_hwm].service = strdup(service);
1819*12758SJulian.Pullen@Sun.COM if (sort_type[sort_type_hwm].service == NULL) {
1820*12758SJulian.Pullen@Sun.COM (void) mutex_unlock(&sort_type_mutex);
1821*12758SJulian.Pullen@Sun.COM return;
1822*12758SJulian.Pullen@Sun.COM }
1823*12758SJulian.Pullen@Sun.COM sort_type[sort_type_hwm].type = type;
1824*12758SJulian.Pullen@Sun.COM sort_type_hwm++;
1825*12758SJulian.Pullen@Sun.COM
1826*12758SJulian.Pullen@Sun.COM (void) mutex_unlock(&sort_type_mutex);
1827*12758SJulian.Pullen@Sun.COM }
1828*12758SJulian.Pullen@Sun.COM
18290Sstevel@tonic-gate static int
setup_vlv_params(ns_ldap_cookie_t * cookie)18300Sstevel@tonic-gate setup_vlv_params(ns_ldap_cookie_t *cookie)
18310Sstevel@tonic-gate {
18320Sstevel@tonic-gate LDAPControl **ctrls;
18330Sstevel@tonic-gate LDAPsortkey **sortkeylist;
18340Sstevel@tonic-gate LDAPControl *sortctrl = NULL;
18350Sstevel@tonic-gate LDAPControl *vlvctrl = NULL;
18360Sstevel@tonic-gate LDAPVirtualList vlist;
1837*12758SJulian.Pullen@Sun.COM char *sortattr;
18380Sstevel@tonic-gate int rc;
1839*12758SJulian.Pullen@Sun.COM int free_sort = FALSE;
18400Sstevel@tonic-gate
18410Sstevel@tonic-gate _freeControlList(&cookie->p_serverctrls);
18420Sstevel@tonic-gate
1843*12758SJulian.Pullen@Sun.COM if (cookie->sortTypeTry == SSS_UNKNOWN)
1844*12758SJulian.Pullen@Sun.COM cookie->sortTypeTry = get_srvsidesort_type(cookie->service);
1845*12758SJulian.Pullen@Sun.COM if (cookie->sortTypeTry == SSS_UNKNOWN)
1846*12758SJulian.Pullen@Sun.COM cookie->sortTypeTry = SSS_SINGLE_ATTR;
1847*12758SJulian.Pullen@Sun.COM
1848*12758SJulian.Pullen@Sun.COM if (cookie->sortTypeTry == SSS_SINGLE_ATTR) {
1849*12758SJulian.Pullen@Sun.COM if ((cookie->i_flags & NS_LDAP_NOMAP) == 0 &&
1850*12758SJulian.Pullen@Sun.COM cookie->i_sortattr) {
1851*12758SJulian.Pullen@Sun.COM sortattr = __ns_ldap_mapAttribute(cookie->service,
1852*12758SJulian.Pullen@Sun.COM cookie->i_sortattr);
1853*12758SJulian.Pullen@Sun.COM free_sort = TRUE;
1854*12758SJulian.Pullen@Sun.COM } else if (cookie->i_sortattr) {
1855*12758SJulian.Pullen@Sun.COM sortattr = (char *)cookie->i_sortattr;
1856*12758SJulian.Pullen@Sun.COM } else {
1857*12758SJulian.Pullen@Sun.COM sortattr = "cn";
1858*12758SJulian.Pullen@Sun.COM }
1859*12758SJulian.Pullen@Sun.COM } else {
1860*12758SJulian.Pullen@Sun.COM sortattr = "cn uid";
1861*12758SJulian.Pullen@Sun.COM }
1862*12758SJulian.Pullen@Sun.COM
1863*12758SJulian.Pullen@Sun.COM rc = ldap_create_sort_keylist(&sortkeylist, sortattr);
1864*12758SJulian.Pullen@Sun.COM if (free_sort)
1865*12758SJulian.Pullen@Sun.COM free(sortattr);
18660Sstevel@tonic-gate if (rc != LDAP_SUCCESS) {
18670Sstevel@tonic-gate (void) ldap_get_option(cookie->conn->ld,
18684765Smj162486 LDAP_OPT_ERROR_NUMBER, &rc);
18690Sstevel@tonic-gate return (rc);
18700Sstevel@tonic-gate }
18710Sstevel@tonic-gate rc = ldap_create_sort_control(cookie->conn->ld,
18724765Smj162486 sortkeylist, 1, &sortctrl);
18730Sstevel@tonic-gate ldap_free_sort_keylist(sortkeylist);
18740Sstevel@tonic-gate if (rc != LDAP_SUCCESS) {
18750Sstevel@tonic-gate (void) ldap_get_option(cookie->conn->ld,
18764765Smj162486 LDAP_OPT_ERROR_NUMBER, &rc);
18770Sstevel@tonic-gate return (rc);
18780Sstevel@tonic-gate }
18790Sstevel@tonic-gate
18800Sstevel@tonic-gate vlist.ldvlist_index = cookie->index;
18810Sstevel@tonic-gate vlist.ldvlist_size = 0;
18820Sstevel@tonic-gate
18830Sstevel@tonic-gate vlist.ldvlist_before_count = 0;
18840Sstevel@tonic-gate vlist.ldvlist_after_count = LISTPAGESIZE-1;
18850Sstevel@tonic-gate vlist.ldvlist_attrvalue = NULL;
18860Sstevel@tonic-gate vlist.ldvlist_extradata = NULL;
18870Sstevel@tonic-gate
18880Sstevel@tonic-gate rc = ldap_create_virtuallist_control(cookie->conn->ld,
18894765Smj162486 &vlist, &vlvctrl);
18900Sstevel@tonic-gate if (rc != LDAP_SUCCESS) {
18910Sstevel@tonic-gate ldap_control_free(sortctrl);
18920Sstevel@tonic-gate (void) ldap_get_option(cookie->conn->ld, LDAP_OPT_ERROR_NUMBER,
18934765Smj162486 &rc);
18940Sstevel@tonic-gate return (rc);
18950Sstevel@tonic-gate }
18960Sstevel@tonic-gate
18970Sstevel@tonic-gate ctrls = (LDAPControl **)calloc(3, sizeof (LDAPControl *));
18980Sstevel@tonic-gate if (ctrls == NULL) {
18990Sstevel@tonic-gate ldap_control_free(sortctrl);
19000Sstevel@tonic-gate ldap_control_free(vlvctrl);
19010Sstevel@tonic-gate return (LDAP_NO_MEMORY);
19020Sstevel@tonic-gate }
19030Sstevel@tonic-gate
19040Sstevel@tonic-gate ctrls[0] = sortctrl;
19050Sstevel@tonic-gate ctrls[1] = vlvctrl;
19060Sstevel@tonic-gate
19070Sstevel@tonic-gate cookie->p_serverctrls = ctrls;
19080Sstevel@tonic-gate return (LDAP_SUCCESS);
19090Sstevel@tonic-gate }
19100Sstevel@tonic-gate
19110Sstevel@tonic-gate static int
setup_simplepg_params(ns_ldap_cookie_t * cookie)19120Sstevel@tonic-gate setup_simplepg_params(ns_ldap_cookie_t *cookie)
19130Sstevel@tonic-gate {
19140Sstevel@tonic-gate LDAPControl **ctrls;
19150Sstevel@tonic-gate LDAPControl *pgctrl = NULL;
19160Sstevel@tonic-gate int rc;
19170Sstevel@tonic-gate
19180Sstevel@tonic-gate _freeControlList(&cookie->p_serverctrls);
19190Sstevel@tonic-gate
19200Sstevel@tonic-gate rc = ldap_create_page_control(cookie->conn->ld, LISTPAGESIZE,
19214765Smj162486 cookie->ctrlCookie, (char)0, &pgctrl);
19220Sstevel@tonic-gate if (rc != LDAP_SUCCESS) {
19230Sstevel@tonic-gate (void) ldap_get_option(cookie->conn->ld, LDAP_OPT_ERROR_NUMBER,
19244765Smj162486 &rc);
19250Sstevel@tonic-gate return (rc);
19260Sstevel@tonic-gate }
19270Sstevel@tonic-gate
19280Sstevel@tonic-gate ctrls = (LDAPControl **)calloc(2, sizeof (LDAPControl *));
19290Sstevel@tonic-gate if (ctrls == NULL) {
19300Sstevel@tonic-gate ldap_control_free(pgctrl);
19310Sstevel@tonic-gate return (LDAP_NO_MEMORY);
19320Sstevel@tonic-gate }
19330Sstevel@tonic-gate ctrls[0] = pgctrl;
19340Sstevel@tonic-gate cookie->p_serverctrls = ctrls;
19350Sstevel@tonic-gate return (LDAP_SUCCESS);
19360Sstevel@tonic-gate }
19370Sstevel@tonic-gate
19380Sstevel@tonic-gate static void
proc_result_referrals(ns_ldap_cookie_t * cookie)19390Sstevel@tonic-gate proc_result_referrals(ns_ldap_cookie_t *cookie)
19400Sstevel@tonic-gate {
19410Sstevel@tonic-gate int errCode, i, rc;
19420Sstevel@tonic-gate char **referrals = NULL;
19430Sstevel@tonic-gate
19440Sstevel@tonic-gate /*
19450Sstevel@tonic-gate * Only follow one level of referrals, i.e.
19460Sstevel@tonic-gate * if already in referral mode, do nothing
19470Sstevel@tonic-gate */
19480Sstevel@tonic-gate if (cookie->refpos == NULL) {
19490Sstevel@tonic-gate cookie->new_state = END_RESULT;
19500Sstevel@tonic-gate rc = ldap_parse_result(cookie->conn->ld,
19514765Smj162486 cookie->resultMsg,
19524765Smj162486 &errCode, NULL,
19534765Smj162486 NULL, &referrals,
19544765Smj162486 NULL, 0);
19550Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
19560Sstevel@tonic-gate (void) ldap_get_option(cookie->conn->ld,
19574765Smj162486 LDAP_OPT_ERROR_NUMBER,
19584765Smj162486 &cookie->err_rc);
19590Sstevel@tonic-gate cookie->new_state = LDAP_ERROR;
19600Sstevel@tonic-gate return;
19610Sstevel@tonic-gate }
19620Sstevel@tonic-gate if (errCode == LDAP_REFERRAL) {
19630Sstevel@tonic-gate for (i = 0; referrals[i] != NULL;
19644765Smj162486 i++) {
19650Sstevel@tonic-gate /* add to referral list */
19660Sstevel@tonic-gate rc = __s_api_addRefInfo(
19674765Smj162486 &cookie->reflist,
19684765Smj162486 referrals[i],
19694765Smj162486 cookie->basedn,
19704765Smj162486 &cookie->scope,
19714765Smj162486 cookie->filter,
19724765Smj162486 cookie->conn->ld);
19730Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
19740Sstevel@tonic-gate cookie->new_state =
19754765Smj162486 ERROR;
19760Sstevel@tonic-gate break;
19770Sstevel@tonic-gate }
19780Sstevel@tonic-gate }
19790Sstevel@tonic-gate ldap_value_free(referrals);
19800Sstevel@tonic-gate }
19810Sstevel@tonic-gate }
19820Sstevel@tonic-gate }
19830Sstevel@tonic-gate
19840Sstevel@tonic-gate static void
proc_search_references(ns_ldap_cookie_t * cookie)19850Sstevel@tonic-gate proc_search_references(ns_ldap_cookie_t *cookie)
19860Sstevel@tonic-gate {
19870Sstevel@tonic-gate char **refurls = NULL;
19880Sstevel@tonic-gate int i, rc;
19890Sstevel@tonic-gate
19900Sstevel@tonic-gate /*
19910Sstevel@tonic-gate * Only follow one level of referrals, i.e.
19920Sstevel@tonic-gate * if already in referral mode, do nothing
19930Sstevel@tonic-gate */
19940Sstevel@tonic-gate if (cookie->refpos == NULL) {
19950Sstevel@tonic-gate refurls = ldap_get_reference_urls(
19964765Smj162486 cookie->conn->ld,
19974765Smj162486 cookie->resultMsg);
19980Sstevel@tonic-gate if (refurls == NULL) {
19990Sstevel@tonic-gate (void) ldap_get_option(cookie->conn->ld,
20004765Smj162486 LDAP_OPT_ERROR_NUMBER,
20014765Smj162486 &cookie->err_rc);
20020Sstevel@tonic-gate cookie->new_state = LDAP_ERROR;
20030Sstevel@tonic-gate return;
20040Sstevel@tonic-gate }
20050Sstevel@tonic-gate for (i = 0; refurls[i] != NULL; i++) {
20060Sstevel@tonic-gate /* add to referral list */
20070Sstevel@tonic-gate rc = __s_api_addRefInfo(
20084765Smj162486 &cookie->reflist,
20094765Smj162486 refurls[i],
20104765Smj162486 cookie->basedn,
20114765Smj162486 &cookie->scope,
20124765Smj162486 cookie->filter,
20134765Smj162486 cookie->conn->ld);
20140Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
20150Sstevel@tonic-gate cookie->new_state =
20164765Smj162486 ERROR;
20170Sstevel@tonic-gate break;
20180Sstevel@tonic-gate }
20190Sstevel@tonic-gate }
20200Sstevel@tonic-gate /* free allocated storage */
20210Sstevel@tonic-gate for (i = 0; refurls[i] != NULL; i++)
20220Sstevel@tonic-gate free(refurls[i]);
20230Sstevel@tonic-gate }
20240Sstevel@tonic-gate }
20250Sstevel@tonic-gate
20260Sstevel@tonic-gate static ns_state_t
multi_result(ns_ldap_cookie_t * cookie)20270Sstevel@tonic-gate multi_result(ns_ldap_cookie_t *cookie)
20280Sstevel@tonic-gate {
20290Sstevel@tonic-gate char errstr[MAXERROR];
20300Sstevel@tonic-gate char *err;
20310Sstevel@tonic-gate ns_ldap_error_t **errorp = NULL;
20320Sstevel@tonic-gate LDAPControl **retCtrls = NULL;
20330Sstevel@tonic-gate int i, rc;
20340Sstevel@tonic-gate int errCode;
20350Sstevel@tonic-gate int finished = 0;
20360Sstevel@tonic-gate unsigned long target_posp = 0;
20370Sstevel@tonic-gate unsigned long list_size = 0;
20380Sstevel@tonic-gate unsigned int count = 0;
20390Sstevel@tonic-gate char **referrals = NULL;
20400Sstevel@tonic-gate
20410Sstevel@tonic-gate if (cookie->listType == VLVCTRLFLAG) {
20420Sstevel@tonic-gate rc = ldap_parse_result(cookie->conn->ld, cookie->resultMsg,
20434765Smj162486 &errCode, NULL, NULL, &referrals, &retCtrls, 0);
20440Sstevel@tonic-gate if (rc != LDAP_SUCCESS) {
20450Sstevel@tonic-gate (void) ldap_get_option(cookie->conn->ld,
20464765Smj162486 LDAP_OPT_ERROR_NUMBER,
20474765Smj162486 &cookie->err_rc);
20480Sstevel@tonic-gate (void) sprintf(errstr,
20494765Smj162486 gettext("LDAP ERROR (%d): %s.\n"),
20504765Smj162486 cookie->err_rc,
20514765Smj162486 gettext(ldap_err2string(cookie->err_rc)));
20520Sstevel@tonic-gate err = strdup(errstr);
20530Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
20544765Smj162486 NULL);
20550Sstevel@tonic-gate cookie->err_rc = NS_LDAP_INTERNAL;
20560Sstevel@tonic-gate cookie->errorp = *errorp;
20570Sstevel@tonic-gate return (LDAP_ERROR);
20580Sstevel@tonic-gate }
20590Sstevel@tonic-gate if (errCode == LDAP_REFERRAL) {
20600Sstevel@tonic-gate for (i = 0; referrals[i] != NULL;
20614765Smj162486 i++) {
20620Sstevel@tonic-gate /* add to referral list */
20630Sstevel@tonic-gate rc = __s_api_addRefInfo(
20644765Smj162486 &cookie->reflist,
20654765Smj162486 referrals[i],
20664765Smj162486 cookie->basedn,
20674765Smj162486 &cookie->scope,
20684765Smj162486 cookie->filter,
20694765Smj162486 cookie->conn->ld);
20700Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
20714765Smj162486 ldap_value_free(
20724765Smj162486 referrals);
20730Sstevel@tonic-gate if (retCtrls)
20740Sstevel@tonic-gate ldap_controls_free(
20754765Smj162486 retCtrls);
20760Sstevel@tonic-gate return (ERROR);
20770Sstevel@tonic-gate }
20780Sstevel@tonic-gate }
20790Sstevel@tonic-gate ldap_value_free(referrals);
20800Sstevel@tonic-gate if (retCtrls)
20810Sstevel@tonic-gate ldap_controls_free(retCtrls);
20820Sstevel@tonic-gate return (END_RESULT);
20830Sstevel@tonic-gate }
20840Sstevel@tonic-gate if (retCtrls) {
20850Sstevel@tonic-gate rc = ldap_parse_virtuallist_control(
20864765Smj162486 cookie->conn->ld, retCtrls,
20874765Smj162486 &target_posp, &list_size, &errCode);
20880Sstevel@tonic-gate if (rc == LDAP_SUCCESS) {
2089*12758SJulian.Pullen@Sun.COM /*
2090*12758SJulian.Pullen@Sun.COM * AD does not return valid target_posp
2091*12758SJulian.Pullen@Sun.COM * and list_size
2092*12758SJulian.Pullen@Sun.COM */
2093*12758SJulian.Pullen@Sun.COM if (target_posp != 0 && list_size != 0) {
2094*12758SJulian.Pullen@Sun.COM cookie->index =
2095*12758SJulian.Pullen@Sun.COM target_posp + LISTPAGESIZE;
2096*12758SJulian.Pullen@Sun.COM if (cookie->index > list_size)
2097*12758SJulian.Pullen@Sun.COM finished = 1;
2098*12758SJulian.Pullen@Sun.COM } else {
2099*12758SJulian.Pullen@Sun.COM if (cookie->entryCount < LISTPAGESIZE)
2100*12758SJulian.Pullen@Sun.COM finished = 1;
2101*12758SJulian.Pullen@Sun.COM else
2102*12758SJulian.Pullen@Sun.COM cookie->index +=
2103*12758SJulian.Pullen@Sun.COM cookie->entryCount;
21040Sstevel@tonic-gate }
21050Sstevel@tonic-gate }
21060Sstevel@tonic-gate ldap_controls_free(retCtrls);
21070Sstevel@tonic-gate retCtrls = NULL;
21080Sstevel@tonic-gate }
21090Sstevel@tonic-gate else
21100Sstevel@tonic-gate finished = 1;
21110Sstevel@tonic-gate } else if (cookie->listType == SIMPLEPAGECTRLFLAG) {
21120Sstevel@tonic-gate rc = ldap_parse_result(cookie->conn->ld, cookie->resultMsg,
21134765Smj162486 &errCode, NULL, NULL, &referrals, &retCtrls, 0);
21140Sstevel@tonic-gate if (rc != LDAP_SUCCESS) {
21150Sstevel@tonic-gate (void) ldap_get_option(cookie->conn->ld,
21164765Smj162486 LDAP_OPT_ERROR_NUMBER,
21174765Smj162486 &cookie->err_rc);
21180Sstevel@tonic-gate (void) sprintf(errstr,
21194765Smj162486 gettext("LDAP ERROR (%d): %s.\n"),
21204765Smj162486 cookie->err_rc,
21214765Smj162486 gettext(ldap_err2string(cookie->err_rc)));
21220Sstevel@tonic-gate err = strdup(errstr);
21230Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
21244765Smj162486 NULL);
21250Sstevel@tonic-gate cookie->err_rc = NS_LDAP_INTERNAL;
21260Sstevel@tonic-gate cookie->errorp = *errorp;
21270Sstevel@tonic-gate return (LDAP_ERROR);
21280Sstevel@tonic-gate }
21290Sstevel@tonic-gate if (errCode == LDAP_REFERRAL) {
21300Sstevel@tonic-gate for (i = 0; referrals[i] != NULL;
21314765Smj162486 i++) {
21320Sstevel@tonic-gate /* add to referral list */
21330Sstevel@tonic-gate rc = __s_api_addRefInfo(
21344765Smj162486 &cookie->reflist,
21354765Smj162486 referrals[i],
21364765Smj162486 cookie->basedn,
21374765Smj162486 &cookie->scope,
21384765Smj162486 cookie->filter,
21394765Smj162486 cookie->conn->ld);
21400Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
21414765Smj162486 ldap_value_free(
21424765Smj162486 referrals);
21430Sstevel@tonic-gate if (retCtrls)
21440Sstevel@tonic-gate ldap_controls_free(
21454765Smj162486 retCtrls);
21460Sstevel@tonic-gate return (ERROR);
21470Sstevel@tonic-gate }
21480Sstevel@tonic-gate }
21490Sstevel@tonic-gate ldap_value_free(referrals);
21500Sstevel@tonic-gate if (retCtrls)
21510Sstevel@tonic-gate ldap_controls_free(retCtrls);
21520Sstevel@tonic-gate return (END_RESULT);
21530Sstevel@tonic-gate }
21540Sstevel@tonic-gate if (retCtrls) {
21550Sstevel@tonic-gate if (cookie->ctrlCookie)
21560Sstevel@tonic-gate ber_bvfree(cookie->ctrlCookie);
21570Sstevel@tonic-gate cookie->ctrlCookie = NULL;
21580Sstevel@tonic-gate rc = ldap_parse_page_control(
21594765Smj162486 cookie->conn->ld, retCtrls,
21604765Smj162486 &count, &cookie->ctrlCookie);
21610Sstevel@tonic-gate if (rc == LDAP_SUCCESS) {
21620Sstevel@tonic-gate if ((cookie->ctrlCookie == NULL) ||
21634765Smj162486 (cookie->ctrlCookie->bv_val == NULL) ||
21644765Smj162486 (cookie->ctrlCookie->bv_len == 0))
21650Sstevel@tonic-gate finished = 1;
21660Sstevel@tonic-gate }
21670Sstevel@tonic-gate ldap_controls_free(retCtrls);
21680Sstevel@tonic-gate retCtrls = NULL;
21690Sstevel@tonic-gate }
21700Sstevel@tonic-gate else
21710Sstevel@tonic-gate finished = 1;
21720Sstevel@tonic-gate }
21730Sstevel@tonic-gate if (!finished && cookie->listType == VLVCTRLFLAG)
21740Sstevel@tonic-gate return (NEXT_VLV);
21750Sstevel@tonic-gate if (!finished && cookie->listType == SIMPLEPAGECTRLFLAG)
21760Sstevel@tonic-gate return (NEXT_PAGE);
21770Sstevel@tonic-gate if (finished)
21780Sstevel@tonic-gate return (END_RESULT);
21790Sstevel@tonic-gate return (ERROR);
21800Sstevel@tonic-gate }
21810Sstevel@tonic-gate
21820Sstevel@tonic-gate /*
21836722Smj162486 * clear_results(ns_ldap_cookie_t):
21846722Smj162486 *
21856722Smj162486 * Attempt to obtain remnants of ldap responses and free them. If remnants are
21866722Smj162486 * not obtained within a certain time period tell the server we wish to abandon
21876722Smj162486 * the request.
21886722Smj162486 *
21896722Smj162486 * Note that we do not initially tell the server to abandon the request as that
21906722Smj162486 * can be an expensive operation for the server, while it is cheap for us to
21916722Smj162486 * just flush the input.
21926722Smj162486 *
21936722Smj162486 * If something was to remain in libldap queue as a result of some error then
21946722Smj162486 * it would be freed later during drop connection call or when no other
21956722Smj162486 * requests share the connection.
21966722Smj162486 */
21976722Smj162486 static void
clear_results(ns_ldap_cookie_t * cookie)21986722Smj162486 clear_results(ns_ldap_cookie_t *cookie)
21996722Smj162486 {
22006722Smj162486 int rc;
22016722Smj162486 if (cookie->conn != NULL && cookie->conn->ld != NULL &&
22026842Sth160488 (cookie->connectionId != -1 ||
22036842Sth160488 (cookie->conn_user != NULL &&
22046842Sth160488 cookie->conn_user->conn_mt != NULL)) &&
22056842Sth160488 cookie->msgId != 0) {
22066722Smj162486 /*
22076722Smj162486 * We need to cleanup the rest of response (if there is such)
22086722Smj162486 * and LDAP abandon is too heavy for LDAP servers, so we will
22096722Smj162486 * wait for the rest of response till timeout and "process" it.
22106722Smj162486 */
22116722Smj162486 rc = ldap_result(cookie->conn->ld, cookie->msgId, LDAP_MSG_ALL,
22126722Smj162486 (struct timeval *)&cookie->search_timeout,
22136722Smj162486 &cookie->resultMsg);
2214*12758SJulian.Pullen@Sun.COM if (rc != -1 && rc != 0 && cookie->resultMsg != NULL) {
22156722Smj162486 (void) ldap_msgfree(cookie->resultMsg);
2216*12758SJulian.Pullen@Sun.COM cookie->resultMsg = NULL;
2217*12758SJulian.Pullen@Sun.COM }
2218*12758SJulian.Pullen@Sun.COM
22196722Smj162486 /*
22206722Smj162486 * If there was timeout then we will send ABANDON request to
22216722Smj162486 * LDAP server to decrease load.
22226722Smj162486 */
22236722Smj162486 if (rc == 0)
22246722Smj162486 (void) ldap_abandon_ext(cookie->conn->ld, cookie->msgId,
22256722Smj162486 NULL, NULL);
22266722Smj162486 /* Disassociate cookie with msgId */
22276722Smj162486 cookie->msgId = 0;
22286722Smj162486 }
22296722Smj162486 }
22306722Smj162486
22316722Smj162486 /*
22320Sstevel@tonic-gate * This state machine performs one or more LDAP searches to a given
22330Sstevel@tonic-gate * directory server using service search descriptors and schema
22340Sstevel@tonic-gate * mapping as appropriate. The approximate pseudocode for
22350Sstevel@tonic-gate * this routine is the following:
22360Sstevel@tonic-gate * Given the current configuration [set/reset connection etc.]
22370Sstevel@tonic-gate * and the current service search descriptor list
22380Sstevel@tonic-gate * or default search filter parameters
22390Sstevel@tonic-gate * foreach (service search filter) {
22400Sstevel@tonic-gate * initialize the filter [via filter_init if appropriate]
22410Sstevel@tonic-gate * get a valid session/connection (preferably the current one)
22420Sstevel@tonic-gate * Recover if the connection is lost
22430Sstevel@tonic-gate * perform the search
22440Sstevel@tonic-gate * foreach (result entry) {
22450Sstevel@tonic-gate * process result [via callback if appropriate]
22460Sstevel@tonic-gate * save result for caller if accepted.
22470Sstevel@tonic-gate * exit and return all collected if allResults found;
22480Sstevel@tonic-gate * }
22490Sstevel@tonic-gate * }
22500Sstevel@tonic-gate * return collected results and exit
22510Sstevel@tonic-gate */
22520Sstevel@tonic-gate
22530Sstevel@tonic-gate static
22540Sstevel@tonic-gate ns_state_t
search_state_machine(ns_ldap_cookie_t * cookie,ns_state_t state,int cycle)22550Sstevel@tonic-gate search_state_machine(ns_ldap_cookie_t *cookie, ns_state_t state, int cycle)
22560Sstevel@tonic-gate {
22570Sstevel@tonic-gate char errstr[MAXERROR];
22580Sstevel@tonic-gate char *err;
2259493Ssdussud int rc, ret;
22606842Sth160488 int rc_save;
22610Sstevel@tonic-gate ns_ldap_entry_t *nextEntry;
22620Sstevel@tonic-gate ns_ldap_error_t *error = NULL;
22630Sstevel@tonic-gate ns_ldap_error_t **errorp;
22646616Sdm199847 struct timeval tv;
22650Sstevel@tonic-gate
22660Sstevel@tonic-gate errorp = &error;
22670Sstevel@tonic-gate cookie->state = state;
22683387Schinlong errstr[0] = '\0';
22690Sstevel@tonic-gate
22700Sstevel@tonic-gate for (;;) {
22710Sstevel@tonic-gate switch (cookie->state) {
22724765Smj162486 case CLEAR_RESULTS:
22736722Smj162486 clear_results(cookie);
22744765Smj162486 cookie->new_state = EXIT;
22754765Smj162486 break;
22761179Svv149972 case GET_ACCT_MGMT_INFO:
22771179Svv149972 /*
22781179Svv149972 * Set the flag to get ldap account management controls.
22791179Svv149972 */
22801179Svv149972 cookie->nopasswd_acct_mgmt = 1;
22811179Svv149972 cookie->new_state = INIT;
22821179Svv149972 break;
22830Sstevel@tonic-gate case EXIT:
22840Sstevel@tonic-gate /* state engine/connection cleaned up in delete */
22850Sstevel@tonic-gate if (cookie->attribute) {
22860Sstevel@tonic-gate __s_api_free2dArray(cookie->attribute);
22870Sstevel@tonic-gate cookie->attribute = NULL;
22880Sstevel@tonic-gate }
22890Sstevel@tonic-gate if (cookie->reflist) {
22900Sstevel@tonic-gate __s_api_deleteRefInfo(cookie->reflist);
22910Sstevel@tonic-gate cookie->reflist = NULL;
22920Sstevel@tonic-gate }
22930Sstevel@tonic-gate return (EXIT);
22940Sstevel@tonic-gate case INIT:
22950Sstevel@tonic-gate cookie->sdpos = NULL;
22960Sstevel@tonic-gate cookie->new_state = NEXT_SEARCH_DESCRIPTOR;
22970Sstevel@tonic-gate if (cookie->attribute) {
22980Sstevel@tonic-gate __s_api_free2dArray(cookie->attribute);
22990Sstevel@tonic-gate cookie->attribute = NULL;
23000Sstevel@tonic-gate }
23010Sstevel@tonic-gate if ((cookie->i_flags & NS_LDAP_NOMAP) == 0 &&
23024765Smj162486 cookie->i_attr) {
23030Sstevel@tonic-gate cookie->attribute =
23044765Smj162486 __ns_ldap_mapAttributeList(
23054765Smj162486 cookie->service,
23064765Smj162486 cookie->i_attr);
23070Sstevel@tonic-gate }
23080Sstevel@tonic-gate break;
23096842Sth160488 case REINIT:
23106842Sth160488 /* Check if we've reached MAX retries. */
23116842Sth160488 cookie->retries++;
23126842Sth160488 if (cookie->retries > NS_LIST_TRY_MAX - 1) {
23136842Sth160488 cookie->new_state = LDAP_ERROR;
23146842Sth160488 break;
23156842Sth160488 }
23166842Sth160488
23176842Sth160488 /*
23186842Sth160488 * Even if we still have retries left, check
23196842Sth160488 * if retry is possible.
23206842Sth160488 */
23216842Sth160488 if (cookie->conn_user != NULL) {
23226842Sth160488 int retry;
23236842Sth160488 ns_conn_mgmt_t *cmg;
23246842Sth160488 cmg = cookie->conn_user->conn_mgmt;
23256842Sth160488 retry = cookie->conn_user->retry;
23266842Sth160488 if (cmg != NULL && cmg->cfg_reloaded == 1)
23276842Sth160488 retry = 1;
23286842Sth160488 if (retry == 0) {
23296842Sth160488 cookie->new_state = LDAP_ERROR;
23306842Sth160488 break;
23316842Sth160488 }
23326842Sth160488 }
23336842Sth160488 /*
23346842Sth160488 * Free results if any, reset to the first
23356842Sth160488 * search descriptor and start a new session.
23366842Sth160488 */
23376842Sth160488 if (cookie->resultMsg != NULL) {
23386842Sth160488 (void) ldap_msgfree(cookie->resultMsg);
23396842Sth160488 cookie->resultMsg = NULL;
23406842Sth160488 }
23416842Sth160488 (void) __ns_ldap_freeError(&cookie->errorp);
23426842Sth160488 (void) __ns_ldap_freeResult(&cookie->result);
23436842Sth160488 cookie->sdpos = cookie->sdlist;
23446842Sth160488 cookie->err_from_result = 0;
23456842Sth160488 cookie->err_rc = 0;
23466842Sth160488 cookie->new_state = NEXT_SESSION;
23476842Sth160488 break;
23480Sstevel@tonic-gate case NEXT_SEARCH_DESCRIPTOR:
23490Sstevel@tonic-gate /* get next search descriptor */
23500Sstevel@tonic-gate if (cookie->sdpos == NULL) {
23510Sstevel@tonic-gate cookie->sdpos = cookie->sdlist;
23520Sstevel@tonic-gate cookie->new_state = GET_SESSION;
23530Sstevel@tonic-gate } else {
23540Sstevel@tonic-gate cookie->sdpos++;
23550Sstevel@tonic-gate cookie->new_state = NEXT_SEARCH;
23560Sstevel@tonic-gate }
23570Sstevel@tonic-gate if (*cookie->sdpos == NULL)
23580Sstevel@tonic-gate cookie->new_state = EXIT;
23590Sstevel@tonic-gate break;
23600Sstevel@tonic-gate case GET_SESSION:
23610Sstevel@tonic-gate if (get_current_session(cookie) < 0)
23620Sstevel@tonic-gate cookie->new_state = NEXT_SESSION;
23630Sstevel@tonic-gate else
23640Sstevel@tonic-gate cookie->new_state = NEXT_SEARCH;
23650Sstevel@tonic-gate break;
23660Sstevel@tonic-gate case NEXT_SESSION:
23670Sstevel@tonic-gate if (get_next_session(cookie) < 0)
23680Sstevel@tonic-gate cookie->new_state = RESTART_SESSION;
23690Sstevel@tonic-gate else
23700Sstevel@tonic-gate cookie->new_state = NEXT_SEARCH;
23710Sstevel@tonic-gate break;
23720Sstevel@tonic-gate case RESTART_SESSION:
23730Sstevel@tonic-gate if (cookie->i_flags & NS_LDAP_HARD) {
23740Sstevel@tonic-gate cookie->new_state = NEXT_SESSION;
23750Sstevel@tonic-gate break;
23760Sstevel@tonic-gate }
23770Sstevel@tonic-gate (void) sprintf(errstr,
23784765Smj162486 gettext("Session error no available conn.\n"),
23794765Smj162486 state);
23800Sstevel@tonic-gate err = strdup(errstr);
23810Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
23824765Smj162486 NULL);
23830Sstevel@tonic-gate cookie->err_rc = NS_LDAP_INTERNAL;
23840Sstevel@tonic-gate cookie->errorp = *errorp;
23850Sstevel@tonic-gate cookie->new_state = EXIT;
23860Sstevel@tonic-gate break;
23870Sstevel@tonic-gate case NEXT_SEARCH:
23880Sstevel@tonic-gate /* setup referrals search if necessary */
23890Sstevel@tonic-gate if (cookie->refpos) {
23900Sstevel@tonic-gate if (setup_referral_search(cookie) < 0) {
23910Sstevel@tonic-gate cookie->new_state = EXIT;
23920Sstevel@tonic-gate break;
23930Sstevel@tonic-gate }
23940Sstevel@tonic-gate } else if (setup_next_search(cookie) < 0) {
23950Sstevel@tonic-gate cookie->new_state = EXIT;
23960Sstevel@tonic-gate break;
23970Sstevel@tonic-gate }
23980Sstevel@tonic-gate /* only do VLV/PAGE on scopes onelevel/subtree */
23990Sstevel@tonic-gate if (paging_supported(cookie)) {
24000Sstevel@tonic-gate if (cookie->use_paging &&
24010Sstevel@tonic-gate (cookie->scope != LDAP_SCOPE_BASE)) {
24020Sstevel@tonic-gate cookie->index = 1;
24030Sstevel@tonic-gate if (cookie->listType == VLVCTRLFLAG)
24040Sstevel@tonic-gate cookie->new_state = NEXT_VLV;
24050Sstevel@tonic-gate else
24060Sstevel@tonic-gate cookie->new_state = NEXT_PAGE;
24070Sstevel@tonic-gate break;
24080Sstevel@tonic-gate }
24090Sstevel@tonic-gate }
24100Sstevel@tonic-gate cookie->new_state = ONE_SEARCH;
24110Sstevel@tonic-gate break;
24120Sstevel@tonic-gate case NEXT_VLV:
24130Sstevel@tonic-gate rc = setup_vlv_params(cookie);
24140Sstevel@tonic-gate if (rc != LDAP_SUCCESS) {
24150Sstevel@tonic-gate cookie->err_rc = rc;
24160Sstevel@tonic-gate cookie->new_state = LDAP_ERROR;
24170Sstevel@tonic-gate break;
24180Sstevel@tonic-gate }
24190Sstevel@tonic-gate cookie->next_state = MULTI_RESULT;
24200Sstevel@tonic-gate cookie->new_state = DO_SEARCH;
24210Sstevel@tonic-gate break;
24220Sstevel@tonic-gate case NEXT_PAGE:
24230Sstevel@tonic-gate rc = setup_simplepg_params(cookie);
24240Sstevel@tonic-gate if (rc != LDAP_SUCCESS) {
24250Sstevel@tonic-gate cookie->err_rc = rc;
24260Sstevel@tonic-gate cookie->new_state = LDAP_ERROR;
24270Sstevel@tonic-gate break;
24280Sstevel@tonic-gate }
24290Sstevel@tonic-gate cookie->next_state = MULTI_RESULT;
24300Sstevel@tonic-gate cookie->new_state = DO_SEARCH;
24310Sstevel@tonic-gate break;
24320Sstevel@tonic-gate case ONE_SEARCH:
24330Sstevel@tonic-gate cookie->next_state = NEXT_RESULT;
24340Sstevel@tonic-gate cookie->new_state = DO_SEARCH;
24350Sstevel@tonic-gate break;
24360Sstevel@tonic-gate case DO_SEARCH:
2437*12758SJulian.Pullen@Sun.COM cookie->entryCount = 0;
24380Sstevel@tonic-gate rc = ldap_search_ext(cookie->conn->ld,
24394765Smj162486 cookie->basedn,
24404765Smj162486 cookie->scope,
24414765Smj162486 cookie->filter,
24424765Smj162486 cookie->attribute,
24434765Smj162486 0,
24444765Smj162486 cookie->p_serverctrls,
24454765Smj162486 NULL,
24464765Smj162486 &cookie->search_timeout, 0,
24474765Smj162486 &cookie->msgId);
24480Sstevel@tonic-gate if (rc != LDAP_SUCCESS) {
24490Sstevel@tonic-gate if (rc == LDAP_BUSY ||
24500Sstevel@tonic-gate rc == LDAP_UNAVAILABLE ||
24510Sstevel@tonic-gate rc == LDAP_UNWILLING_TO_PERFORM ||
24520Sstevel@tonic-gate rc == LDAP_CONNECT_ERROR ||
24530Sstevel@tonic-gate rc == LDAP_SERVER_DOWN) {
24540Sstevel@tonic-gate
24556842Sth160488 if (cookie->reinit_on_retriable_err) {
24566842Sth160488 cookie->err_rc = rc;
24576842Sth160488 cookie->new_state = REINIT;
24586842Sth160488 } else
24596842Sth160488 cookie->new_state =
24606842Sth160488 NEXT_SESSION;
24610Sstevel@tonic-gate
24620Sstevel@tonic-gate /*
24630Sstevel@tonic-gate * If not able to reach the
24640Sstevel@tonic-gate * server, inform the ldap
24650Sstevel@tonic-gate * cache manager that the
24660Sstevel@tonic-gate * server should be removed
24670Sstevel@tonic-gate * from it's server list.
24680Sstevel@tonic-gate * Thus, the manager will not
24690Sstevel@tonic-gate * return this server on the next
24700Sstevel@tonic-gate * get-server request and will
24710Sstevel@tonic-gate * also reduce the server list
24720Sstevel@tonic-gate * refresh TTL, so that it will
24730Sstevel@tonic-gate * find out sooner when the server
24740Sstevel@tonic-gate * is up again.
24750Sstevel@tonic-gate */
24766842Sth160488 if ((rc == LDAP_CONNECT_ERROR ||
24776842Sth160488 rc == LDAP_SERVER_DOWN) &&
24786842Sth160488 (cookie->conn_user == NULL ||
24796842Sth160488 cookie->conn_user->conn_mt ==
24806842Sth160488 NULL)) {
2481493Ssdussud ret = __s_api_removeServer(
24820Sstevel@tonic-gate cookie->conn->serverAddr);
24836842Sth160488 if (ret == NS_CACHE_NOSERVER &&
2484493Ssdussud cookie->conn_auth_type
24854765Smj162486 == NS_LDAP_AUTH_NONE) {
2486493Ssdussud /*
2487493Ssdussud * Couldn't remove
2488493Ssdussud * server from server
2489493Ssdussud * list.
2490493Ssdussud * Exit to avoid
2491493Ssdussud * potential infinite
2492493Ssdussud * loop.
2493493Ssdussud */
2494493Ssdussud cookie->err_rc = rc;
2495493Ssdussud cookie->new_state =
2496493Ssdussud LDAP_ERROR;
2497493Ssdussud }
24980Sstevel@tonic-gate if (cookie->connectionId > -1) {
24992830Sdjl /*
25002830Sdjl * NS_LDAP_NEW_CONN
25012830Sdjl * indicates that the
25022830Sdjl * connection should
25032830Sdjl * be deleted, not
25042830Sdjl * kept alive
25052830Sdjl */
25062830Sdjl DropConnection(
25074765Smj162486 cookie->
25084765Smj162486 connectionId,
25094765Smj162486 NS_LDAP_NEW_CONN);
25102830Sdjl cookie->connectionId =
25114765Smj162486 -1;
25120Sstevel@tonic-gate }
25136842Sth160488 } else if ((rc == LDAP_CONNECT_ERROR ||
25146842Sth160488 rc == LDAP_SERVER_DOWN) &&
25159944SSreedhar.Chalamalasetti@Sun.COM cookie->conn_user != NULL) {
25169944SSreedhar.Chalamalasetti@Sun.COM if (cookie->
25179944SSreedhar.Chalamalasetti@Sun.COM reinit_on_retriable_err) {
25189944SSreedhar.Chalamalasetti@Sun.COM /*
25199944SSreedhar.Chalamalasetti@Sun.COM * MT connection not
25209944SSreedhar.Chalamalasetti@Sun.COM * usable, close it
25219944SSreedhar.Chalamalasetti@Sun.COM * before REINIT.
25229944SSreedhar.Chalamalasetti@Sun.COM * rc has already
25239944SSreedhar.Chalamalasetti@Sun.COM * been saved in
25249944SSreedhar.Chalamalasetti@Sun.COM * cookie->err_rc above.
25259944SSreedhar.Chalamalasetti@Sun.COM */
25269944SSreedhar.Chalamalasetti@Sun.COM __s_api_conn_mt_close(
25279944SSreedhar.Chalamalasetti@Sun.COM cookie->conn_user,
25289944SSreedhar.Chalamalasetti@Sun.COM rc,
25299944SSreedhar.Chalamalasetti@Sun.COM &cookie->errorp);
25309944SSreedhar.Chalamalasetti@Sun.COM } else {
25319944SSreedhar.Chalamalasetti@Sun.COM /*
25329944SSreedhar.Chalamalasetti@Sun.COM * MT connection not
25339944SSreedhar.Chalamalasetti@Sun.COM * usable, close it in
25349944SSreedhar.Chalamalasetti@Sun.COM * the LDAP_ERROR state.
25359944SSreedhar.Chalamalasetti@Sun.COM * A retry will be done
25369944SSreedhar.Chalamalasetti@Sun.COM * next if allowed.
25379944SSreedhar.Chalamalasetti@Sun.COM */
25389944SSreedhar.Chalamalasetti@Sun.COM cookie->err_rc = rc;
25399944SSreedhar.Chalamalasetti@Sun.COM cookie->new_state =
25409944SSreedhar.Chalamalasetti@Sun.COM LDAP_ERROR;
25419944SSreedhar.Chalamalasetti@Sun.COM }
25420Sstevel@tonic-gate }
25430Sstevel@tonic-gate break;
25440Sstevel@tonic-gate }
25450Sstevel@tonic-gate cookie->err_rc = rc;
25460Sstevel@tonic-gate cookie->new_state = LDAP_ERROR;
25470Sstevel@tonic-gate break;
25480Sstevel@tonic-gate }
25490Sstevel@tonic-gate cookie->new_state = cookie->next_state;
25500Sstevel@tonic-gate break;
25510Sstevel@tonic-gate case NEXT_RESULT:
25526616Sdm199847 /*
25536616Sdm199847 * Caller (e.g. __ns_ldap_list_batch_add)
25546616Sdm199847 * does not want to block on ldap_result().
25556616Sdm199847 * Therefore we execute ldap_result() with
25566616Sdm199847 * a zeroed timeval.
25576616Sdm199847 */
25586616Sdm199847 if (cookie->no_wait == B_TRUE)
25596616Sdm199847 (void) memset(&tv, 0, sizeof (tv));
25606616Sdm199847 else
25616616Sdm199847 tv = cookie->search_timeout;
25620Sstevel@tonic-gate rc = ldap_result(cookie->conn->ld, cookie->msgId,
25634765Smj162486 LDAP_MSG_ONE,
25646616Sdm199847 &tv,
25654765Smj162486 &cookie->resultMsg);
25660Sstevel@tonic-gate if (rc == LDAP_RES_SEARCH_RESULT) {
25670Sstevel@tonic-gate cookie->new_state = END_RESULT;
25680Sstevel@tonic-gate /* check and process referrals info */
25690Sstevel@tonic-gate if (cookie->followRef)
25700Sstevel@tonic-gate proc_result_referrals(
25714765Smj162486 cookie);
25720Sstevel@tonic-gate (void) ldap_msgfree(cookie->resultMsg);
25730Sstevel@tonic-gate cookie->resultMsg = NULL;
25740Sstevel@tonic-gate break;
25750Sstevel@tonic-gate }
25760Sstevel@tonic-gate /* handle referrals if necessary */
25770Sstevel@tonic-gate if (rc == LDAP_RES_SEARCH_REFERENCE) {
25780Sstevel@tonic-gate if (cookie->followRef)
25790Sstevel@tonic-gate proc_search_references(cookie);
25800Sstevel@tonic-gate (void) ldap_msgfree(cookie->resultMsg);
25810Sstevel@tonic-gate cookie->resultMsg = NULL;
25820Sstevel@tonic-gate break;
25830Sstevel@tonic-gate }
25840Sstevel@tonic-gate if (rc != LDAP_RES_SEARCH_ENTRY) {
25850Sstevel@tonic-gate switch (rc) {
25860Sstevel@tonic-gate case 0:
25876616Sdm199847 if (cookie->no_wait == B_TRUE) {
25886616Sdm199847 (void) ldap_msgfree(
25896616Sdm199847 cookie->resultMsg);
25906616Sdm199847 cookie->resultMsg = NULL;
25916616Sdm199847 return (cookie->new_state);
25926616Sdm199847 }
25930Sstevel@tonic-gate rc = LDAP_TIMEOUT;
25940Sstevel@tonic-gate break;
25950Sstevel@tonic-gate case -1:
25960Sstevel@tonic-gate rc = ldap_get_lderrno(cookie->conn->ld,
25974765Smj162486 NULL, NULL);
25980Sstevel@tonic-gate break;
25990Sstevel@tonic-gate default:
26000Sstevel@tonic-gate rc = ldap_result2error(cookie->conn->ld,
26014765Smj162486 cookie->resultMsg, 1);
26020Sstevel@tonic-gate break;
26030Sstevel@tonic-gate }
26046842Sth160488 if ((rc == LDAP_TIMEOUT ||
26056842Sth160488 rc == LDAP_SERVER_DOWN) &&
26066842Sth160488 (cookie->conn_user == NULL ||
26076842Sth160488 cookie->conn_user->conn_mt == NULL)) {
26083387Schinlong if (rc == LDAP_TIMEOUT)
26093387Schinlong (void) __s_api_removeServer(
26103387Schinlong cookie->conn->serverAddr);
26113387Schinlong if (cookie->connectionId > -1) {
26124765Smj162486 DropConnection(
26134765Smj162486 cookie->connectionId,
26144765Smj162486 NS_LDAP_NEW_CONN);
26153387Schinlong cookie->connectionId = -1;
26163387Schinlong }
26173387Schinlong cookie->err_from_result = 1;
26183387Schinlong }
26190Sstevel@tonic-gate (void) ldap_msgfree(cookie->resultMsg);
26200Sstevel@tonic-gate cookie->resultMsg = NULL;
26210Sstevel@tonic-gate if (rc == LDAP_BUSY ||
26220Sstevel@tonic-gate rc == LDAP_UNAVAILABLE ||
26233387Schinlong rc == LDAP_UNWILLING_TO_PERFORM) {
26246842Sth160488 if (cookie->reinit_on_retriable_err) {
26256842Sth160488 cookie->err_rc = rc;
26266842Sth160488 cookie->err_from_result = 1;
26276842Sth160488 cookie->new_state = REINIT;
26286842Sth160488 } else
26296842Sth160488 cookie->new_state =
26306842Sth160488 NEXT_SESSION;
26316842Sth160488 break;
26326842Sth160488 }
26336842Sth160488 if ((rc == LDAP_CONNECT_ERROR ||
26346842Sth160488 rc == LDAP_SERVER_DOWN) &&
26356842Sth160488 cookie->reinit_on_retriable_err) {
26366842Sth160488 ns_ldap_error_t *errorp = NULL;
26376842Sth160488 cookie->err_rc = rc;
26386842Sth160488 cookie->err_from_result = 1;
26396842Sth160488 cookie->new_state = REINIT;
26406842Sth160488 if (cookie->conn_user != NULL)
26416842Sth160488 __s_api_conn_mt_close(
26426842Sth160488 cookie->conn_user,
26436842Sth160488 rc, &errorp);
26446842Sth160488 if (errorp != NULL) {
26456842Sth160488 (void) __ns_ldap_freeError(
26466842Sth160488 &cookie->errorp);
26476842Sth160488 cookie->errorp = errorp;
26486842Sth160488 }
26490Sstevel@tonic-gate break;
26500Sstevel@tonic-gate }
26510Sstevel@tonic-gate cookie->err_rc = rc;
26520Sstevel@tonic-gate cookie->new_state = LDAP_ERROR;
26530Sstevel@tonic-gate break;
26540Sstevel@tonic-gate }
26550Sstevel@tonic-gate /* else LDAP_RES_SEARCH_ENTRY */
26561179Svv149972 /* get account management response control */
26571179Svv149972 if (cookie->nopasswd_acct_mgmt == 1) {
26581179Svv149972 rc = ldap_get_entry_controls(cookie->conn->ld,
26594765Smj162486 cookie->resultMsg,
26604765Smj162486 &(cookie->resultctrl));
26611179Svv149972 if (rc != LDAP_SUCCESS) {
26621179Svv149972 cookie->new_state = LDAP_ERROR;
26631179Svv149972 cookie->err_rc = rc;
26641179Svv149972 break;
26651179Svv149972 }
26661179Svv149972 }
26670Sstevel@tonic-gate rc = __s_api_getEntry(cookie);
26680Sstevel@tonic-gate (void) ldap_msgfree(cookie->resultMsg);
26690Sstevel@tonic-gate cookie->resultMsg = NULL;
26700Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
26710Sstevel@tonic-gate cookie->new_state = LDAP_ERROR;
26720Sstevel@tonic-gate break;
26730Sstevel@tonic-gate }
26740Sstevel@tonic-gate cookie->new_state = PROCESS_RESULT;
26750Sstevel@tonic-gate cookie->next_state = NEXT_RESULT;
26760Sstevel@tonic-gate break;
26770Sstevel@tonic-gate case MULTI_RESULT:
26786616Sdm199847 if (cookie->no_wait == B_TRUE)
26796616Sdm199847 (void) memset(&tv, 0, sizeof (tv));
26806616Sdm199847 else
26816616Sdm199847 tv = cookie->search_timeout;
26820Sstevel@tonic-gate rc = ldap_result(cookie->conn->ld, cookie->msgId,
26834765Smj162486 LDAP_MSG_ONE,
26846616Sdm199847 &tv,
26854765Smj162486 &cookie->resultMsg);
26860Sstevel@tonic-gate if (rc == LDAP_RES_SEARCH_RESULT) {
26870Sstevel@tonic-gate rc = ldap_result2error(cookie->conn->ld,
26884765Smj162486 cookie->resultMsg, 0);
2689*12758SJulian.Pullen@Sun.COM if (rc == LDAP_ADMINLIMIT_EXCEEDED &&
2690*12758SJulian.Pullen@Sun.COM cookie->listType == VLVCTRLFLAG &&
2691*12758SJulian.Pullen@Sun.COM cookie->sortTypeTry == SSS_SINGLE_ATTR) {
2692*12758SJulian.Pullen@Sun.COM /* Try old "cn uid" server side sort */
2693*12758SJulian.Pullen@Sun.COM cookie->sortTypeTry = SSS_CN_UID_ATTRS;
2694*12758SJulian.Pullen@Sun.COM cookie->new_state = NEXT_VLV;
2695*12758SJulian.Pullen@Sun.COM (void) ldap_msgfree(cookie->resultMsg);
2696*12758SJulian.Pullen@Sun.COM cookie->resultMsg = NULL;
2697*12758SJulian.Pullen@Sun.COM break;
2698*12758SJulian.Pullen@Sun.COM }
26990Sstevel@tonic-gate if (rc != LDAP_SUCCESS) {
27000Sstevel@tonic-gate cookie->err_rc = rc;
27010Sstevel@tonic-gate cookie->new_state = LDAP_ERROR;
27020Sstevel@tonic-gate (void) ldap_msgfree(cookie->resultMsg);
2703*12758SJulian.Pullen@Sun.COM cookie->resultMsg = NULL;
27040Sstevel@tonic-gate break;
27050Sstevel@tonic-gate }
27060Sstevel@tonic-gate cookie->new_state = multi_result(cookie);
27070Sstevel@tonic-gate (void) ldap_msgfree(cookie->resultMsg);
27080Sstevel@tonic-gate cookie->resultMsg = NULL;
27090Sstevel@tonic-gate break;
27100Sstevel@tonic-gate }
27110Sstevel@tonic-gate /* handle referrals if necessary */
27120Sstevel@tonic-gate if (rc == LDAP_RES_SEARCH_REFERENCE &&
27134765Smj162486 cookie->followRef) {
27140Sstevel@tonic-gate proc_search_references(cookie);
27150Sstevel@tonic-gate (void) ldap_msgfree(cookie->resultMsg);
27160Sstevel@tonic-gate cookie->resultMsg = NULL;
27170Sstevel@tonic-gate break;
27180Sstevel@tonic-gate }
27190Sstevel@tonic-gate if (rc != LDAP_RES_SEARCH_ENTRY) {
27200Sstevel@tonic-gate switch (rc) {
27210Sstevel@tonic-gate case 0:
27226616Sdm199847 if (cookie->no_wait == B_TRUE) {
27236616Sdm199847 (void) ldap_msgfree(
27246616Sdm199847 cookie->resultMsg);
27256616Sdm199847 cookie->resultMsg = NULL;
27266616Sdm199847 return (cookie->new_state);
27276616Sdm199847 }
27280Sstevel@tonic-gate rc = LDAP_TIMEOUT;
27290Sstevel@tonic-gate break;
27300Sstevel@tonic-gate case -1:
27310Sstevel@tonic-gate rc = ldap_get_lderrno(cookie->conn->ld,
27324765Smj162486 NULL, NULL);
27330Sstevel@tonic-gate break;
27340Sstevel@tonic-gate default:
27350Sstevel@tonic-gate rc = ldap_result2error(cookie->conn->ld,
27364765Smj162486 cookie->resultMsg, 1);
27370Sstevel@tonic-gate break;
27380Sstevel@tonic-gate }
27396842Sth160488 if ((rc == LDAP_TIMEOUT ||
27406842Sth160488 rc == LDAP_SERVER_DOWN) &&
27416842Sth160488 (cookie->conn_user == NULL ||
27426842Sth160488 cookie->conn_user->conn_mt == NULL)) {
27433387Schinlong if (rc == LDAP_TIMEOUT)
27443387Schinlong (void) __s_api_removeServer(
27453387Schinlong cookie->conn->serverAddr);
27463387Schinlong if (cookie->connectionId > -1) {
27474765Smj162486 DropConnection(
27484765Smj162486 cookie->connectionId,
27494765Smj162486 NS_LDAP_NEW_CONN);
27503387Schinlong cookie->connectionId = -1;
27513387Schinlong }
27523387Schinlong cookie->err_from_result = 1;
27533387Schinlong }
27540Sstevel@tonic-gate (void) ldap_msgfree(cookie->resultMsg);
27550Sstevel@tonic-gate cookie->resultMsg = NULL;
27560Sstevel@tonic-gate if (rc == LDAP_BUSY ||
27570Sstevel@tonic-gate rc == LDAP_UNAVAILABLE ||
27583387Schinlong rc == LDAP_UNWILLING_TO_PERFORM) {
27596842Sth160488 if (cookie->reinit_on_retriable_err) {
27606842Sth160488 cookie->err_rc = rc;
27616842Sth160488 cookie->err_from_result = 1;
27626842Sth160488 cookie->new_state = REINIT;
27636842Sth160488 } else
27646842Sth160488 cookie->new_state =
27656842Sth160488 NEXT_SESSION;
27666842Sth160488 break;
27676842Sth160488 }
2768*12758SJulian.Pullen@Sun.COM
27696842Sth160488 if ((rc == LDAP_CONNECT_ERROR ||
27706842Sth160488 rc == LDAP_SERVER_DOWN) &&
27716842Sth160488 cookie->reinit_on_retriable_err) {
27726842Sth160488 ns_ldap_error_t *errorp = NULL;
27736842Sth160488 cookie->err_rc = rc;
27746842Sth160488 cookie->err_from_result = 1;
27756842Sth160488 cookie->new_state = REINIT;
27766842Sth160488 if (cookie->conn_user != NULL)
27776842Sth160488 __s_api_conn_mt_close(
27786842Sth160488 cookie->conn_user,
27796842Sth160488 rc, &errorp);
27806842Sth160488 if (errorp != NULL) {
27816842Sth160488 (void) __ns_ldap_freeError(
27826842Sth160488 &cookie->errorp);
27836842Sth160488 cookie->errorp = errorp;
27846842Sth160488 }
27850Sstevel@tonic-gate break;
27860Sstevel@tonic-gate }
27870Sstevel@tonic-gate cookie->err_rc = rc;
27880Sstevel@tonic-gate cookie->new_state = LDAP_ERROR;
27890Sstevel@tonic-gate break;
27900Sstevel@tonic-gate }
27910Sstevel@tonic-gate /* else LDAP_RES_SEARCH_ENTRY */
2792*12758SJulian.Pullen@Sun.COM cookie->entryCount++;
27930Sstevel@tonic-gate rc = __s_api_getEntry(cookie);
27940Sstevel@tonic-gate (void) ldap_msgfree(cookie->resultMsg);
27950Sstevel@tonic-gate cookie->resultMsg = NULL;
27960Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
27970Sstevel@tonic-gate cookie->new_state = LDAP_ERROR;
27980Sstevel@tonic-gate break;
27990Sstevel@tonic-gate }
2800*12758SJulian.Pullen@Sun.COM /*
2801*12758SJulian.Pullen@Sun.COM * If VLV search was successfull save the server
2802*12758SJulian.Pullen@Sun.COM * side sort type tried.
2803*12758SJulian.Pullen@Sun.COM */
2804*12758SJulian.Pullen@Sun.COM if (cookie->listType == VLVCTRLFLAG)
2805*12758SJulian.Pullen@Sun.COM update_srvsidesort_type(cookie->service,
2806*12758SJulian.Pullen@Sun.COM cookie->sortTypeTry);
2807*12758SJulian.Pullen@Sun.COM
28080Sstevel@tonic-gate cookie->new_state = PROCESS_RESULT;
28090Sstevel@tonic-gate cookie->next_state = MULTI_RESULT;
28100Sstevel@tonic-gate break;
28110Sstevel@tonic-gate case PROCESS_RESULT:
28120Sstevel@tonic-gate /* NOTE THIS STATE MAY BE PROCESSED BY CALLER */
28130Sstevel@tonic-gate if (cookie->use_usercb && cookie->callback) {
28140Sstevel@tonic-gate rc = 0;
28150Sstevel@tonic-gate for (nextEntry = cookie->result->entry;
28164765Smj162486 nextEntry != NULL;
28174765Smj162486 nextEntry = nextEntry->next) {
28180Sstevel@tonic-gate rc = (*cookie->callback)(nextEntry,
28194765Smj162486 cookie->userdata);
28200Sstevel@tonic-gate
28210Sstevel@tonic-gate if (rc == NS_LDAP_CB_DONE) {
28220Sstevel@tonic-gate /* cb doesn't want any more data */
28230Sstevel@tonic-gate rc = NS_LDAP_PARTIAL;
28240Sstevel@tonic-gate cookie->err_rc = rc;
28250Sstevel@tonic-gate break;
28260Sstevel@tonic-gate } else if (rc != NS_LDAP_CB_NEXT) {
28270Sstevel@tonic-gate /* invalid return code */
28280Sstevel@tonic-gate rc = NS_LDAP_OP_FAILED;
28290Sstevel@tonic-gate cookie->err_rc = rc;
28300Sstevel@tonic-gate break;
28310Sstevel@tonic-gate }
28320Sstevel@tonic-gate }
28330Sstevel@tonic-gate (void) __ns_ldap_freeResult(&cookie->result);
28340Sstevel@tonic-gate cookie->result = NULL;
28350Sstevel@tonic-gate }
28360Sstevel@tonic-gate if (rc != 0) {
28370Sstevel@tonic-gate cookie->new_state = EXIT;
28380Sstevel@tonic-gate break;
28390Sstevel@tonic-gate }
28400Sstevel@tonic-gate /* NOTE PREVIOUS STATE SPECIFIES NEXT STATE */
28410Sstevel@tonic-gate cookie->new_state = cookie->next_state;
28420Sstevel@tonic-gate break;
28430Sstevel@tonic-gate case END_PROCESS_RESULT:
28440Sstevel@tonic-gate cookie->new_state = cookie->next_state;
28450Sstevel@tonic-gate break;
28460Sstevel@tonic-gate case END_RESULT:
28470Sstevel@tonic-gate /*
28480Sstevel@tonic-gate * XXX DO WE NEED THIS CASE?
28490Sstevel@tonic-gate * if (search is complete) {
28500Sstevel@tonic-gate * cookie->new_state = EXIT;
28510Sstevel@tonic-gate * } else
28520Sstevel@tonic-gate */
28530Sstevel@tonic-gate /*
28540Sstevel@tonic-gate * entering referral mode if necessary
28550Sstevel@tonic-gate */
28560Sstevel@tonic-gate if (cookie->followRef && cookie->reflist)
28570Sstevel@tonic-gate cookie->new_state =
28584765Smj162486 NEXT_REFERRAL;
28590Sstevel@tonic-gate else
28600Sstevel@tonic-gate cookie->new_state =
28614765Smj162486 NEXT_SEARCH_DESCRIPTOR;
28620Sstevel@tonic-gate break;
28630Sstevel@tonic-gate case NEXT_REFERRAL:
28640Sstevel@tonic-gate /* get next referral info */
28650Sstevel@tonic-gate if (cookie->refpos == NULL)
28660Sstevel@tonic-gate cookie->refpos =
28674765Smj162486 cookie->reflist;
28680Sstevel@tonic-gate else
28690Sstevel@tonic-gate cookie->refpos =
28704765Smj162486 cookie->refpos->next;
28710Sstevel@tonic-gate /* check see if done with all referrals */
28720Sstevel@tonic-gate if (cookie->refpos != NULL)
28730Sstevel@tonic-gate cookie->new_state =
28744765Smj162486 GET_REFERRAL_SESSION;
28750Sstevel@tonic-gate else {
28760Sstevel@tonic-gate __s_api_deleteRefInfo(cookie->reflist);
28770Sstevel@tonic-gate cookie->reflist = NULL;
28780Sstevel@tonic-gate cookie->new_state =
28794765Smj162486 NEXT_SEARCH_DESCRIPTOR;
28806842Sth160488 if (cookie->conn_user != NULL)
28816842Sth160488 cookie->conn_user->referral = B_FALSE;
28820Sstevel@tonic-gate }
28830Sstevel@tonic-gate break;
28840Sstevel@tonic-gate case GET_REFERRAL_SESSION:
28850Sstevel@tonic-gate if (get_referral_session(cookie) < 0)
28860Sstevel@tonic-gate cookie->new_state = EXIT;
28870Sstevel@tonic-gate else {
28880Sstevel@tonic-gate cookie->new_state = NEXT_SEARCH;
28890Sstevel@tonic-gate }
28900Sstevel@tonic-gate break;
28910Sstevel@tonic-gate case LDAP_ERROR:
28926842Sth160488 rc_save = cookie->err_rc;
28933387Schinlong if (cookie->err_from_result) {
28943387Schinlong if (cookie->err_rc == LDAP_SERVER_DOWN) {
28953387Schinlong (void) sprintf(errstr,
28964765Smj162486 gettext("LDAP ERROR (%d): "
28974765Smj162486 "Error occurred during"
28984765Smj162486 " receiving results. "
28995671Smj162486 "Connection to server lost."),
29004765Smj162486 cookie->err_rc);
29013387Schinlong } else if (cookie->err_rc == LDAP_TIMEOUT) {
29023387Schinlong (void) sprintf(errstr,
29034765Smj162486 gettext("LDAP ERROR (%d): "
29044765Smj162486 "Error occurred during"
29054765Smj162486 " receiving results. %s"
29064765Smj162486 "."), cookie->err_rc,
29074765Smj162486 ldap_err2string(
29084765Smj162486 cookie->err_rc));
29093387Schinlong }
29103387Schinlong } else
29113387Schinlong (void) sprintf(errstr,
29124765Smj162486 gettext("LDAP ERROR (%d): %s."),
29134765Smj162486 cookie->err_rc,
29144765Smj162486 ldap_err2string(cookie->err_rc));
29150Sstevel@tonic-gate err = strdup(errstr);
29163387Schinlong if (cookie->err_from_result) {
29175671Smj162486 if (cookie->err_rc == LDAP_SERVER_DOWN) {
29185671Smj162486 MKERROR(LOG_INFO, *errorp,
29195671Smj162486 cookie->err_rc, err, NULL);
29205671Smj162486 } else {
29215671Smj162486 MKERROR(LOG_WARNING, *errorp,
29225671Smj162486 cookie->err_rc, err, NULL);
29235671Smj162486 }
29243387Schinlong } else {
29253387Schinlong MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL,
29264765Smj162486 err, NULL);
29273387Schinlong }
29280Sstevel@tonic-gate cookie->err_rc = NS_LDAP_INTERNAL;
29290Sstevel@tonic-gate cookie->errorp = *errorp;
29306842Sth160488 if (cookie->conn_user != NULL) {
29316842Sth160488 if (rc_save == LDAP_SERVER_DOWN ||
29326842Sth160488 rc_save == LDAP_CONNECT_ERROR) {
29336842Sth160488 /*
29346842Sth160488 * MT connection is not usable,
29356842Sth160488 * close it.
29366842Sth160488 */
29376842Sth160488 __s_api_conn_mt_close(cookie->conn_user,
29386842Sth160488 rc_save, &cookie->errorp);
29396842Sth160488 return (ERROR);
29406842Sth160488 }
29416842Sth160488 }
29420Sstevel@tonic-gate return (ERROR);
29430Sstevel@tonic-gate default:
29440Sstevel@tonic-gate case ERROR:
29450Sstevel@tonic-gate (void) sprintf(errstr,
29464765Smj162486 gettext("Internal State machine exit (%d).\n"),
29474765Smj162486 cookie->state);
29480Sstevel@tonic-gate err = strdup(errstr);
29490Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
29504765Smj162486 NULL);
29510Sstevel@tonic-gate cookie->err_rc = NS_LDAP_INTERNAL;
29520Sstevel@tonic-gate cookie->errorp = *errorp;
29530Sstevel@tonic-gate return (ERROR);
29540Sstevel@tonic-gate }
29550Sstevel@tonic-gate
29566842Sth160488 if (cookie->conn_user != NULL &&
29576842Sth160488 cookie->conn_user->bad_mt_conn == B_TRUE) {
29586842Sth160488 __s_api_conn_mt_close(cookie->conn_user, 0, NULL);
29596842Sth160488 cookie->err_rc = cookie->conn_user->ns_rc;
29606842Sth160488 cookie->errorp = cookie->conn_user->ns_error;
29616842Sth160488 cookie->conn_user->ns_error = NULL;
29626842Sth160488 return (ERROR);
29636842Sth160488 }
29646842Sth160488
29650Sstevel@tonic-gate if (cycle == ONE_STEP) {
29660Sstevel@tonic-gate return (cookie->new_state);
29670Sstevel@tonic-gate }
29680Sstevel@tonic-gate cookie->state = cookie->new_state;
29690Sstevel@tonic-gate }
29700Sstevel@tonic-gate /*NOTREACHED*/
29710Sstevel@tonic-gate #if 0
29720Sstevel@tonic-gate (void) sprintf(errstr,
29734765Smj162486 gettext("Unexpected State machine error.\n"));
29740Sstevel@tonic-gate err = strdup(errstr);
29750Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err, NULL);
29760Sstevel@tonic-gate cookie->err_rc = NS_LDAP_INTERNAL;
29770Sstevel@tonic-gate cookie->errorp = *errorp;
29780Sstevel@tonic-gate return (ERROR);
29790Sstevel@tonic-gate #endif
29800Sstevel@tonic-gate }
29810Sstevel@tonic-gate
29820Sstevel@tonic-gate /*
29839576SJulian.Pullen@Sun.COM * For a lookup of shadow data, if shadow update is enabled,
29849576SJulian.Pullen@Sun.COM * check the calling process' privilege to ensure it's
29859576SJulian.Pullen@Sun.COM * allowed to perform such operation.
29869576SJulian.Pullen@Sun.COM */
29879576SJulian.Pullen@Sun.COM static int
check_shadow(ns_ldap_cookie_t * cookie,const char * service)29889576SJulian.Pullen@Sun.COM check_shadow(ns_ldap_cookie_t *cookie, const char *service)
29899576SJulian.Pullen@Sun.COM {
29909576SJulian.Pullen@Sun.COM char errstr[MAXERROR];
29919576SJulian.Pullen@Sun.COM char *err;
29929576SJulian.Pullen@Sun.COM boolean_t priv;
29939576SJulian.Pullen@Sun.COM /* caller */
29949576SJulian.Pullen@Sun.COM priv_set_t *ps;
29959576SJulian.Pullen@Sun.COM /* zone */
29969576SJulian.Pullen@Sun.COM priv_set_t *zs;
29979576SJulian.Pullen@Sun.COM
29989576SJulian.Pullen@Sun.COM /*
29999576SJulian.Pullen@Sun.COM * If service is "shadow", we may need
30009576SJulian.Pullen@Sun.COM * to use privilege credentials.
30019576SJulian.Pullen@Sun.COM */
30029576SJulian.Pullen@Sun.COM if ((strcmp(service, "shadow") == 0) &&
30039576SJulian.Pullen@Sun.COM __ns_ldap_is_shadow_update_enabled()) {
30049576SJulian.Pullen@Sun.COM /*
30059576SJulian.Pullen@Sun.COM * Since we release admin credentials after
30069576SJulian.Pullen@Sun.COM * connection is closed and we do not cache
30079576SJulian.Pullen@Sun.COM * them, we allow any root or all zone
30089576SJulian.Pullen@Sun.COM * privilege process to read shadow data.
30099576SJulian.Pullen@Sun.COM */
30109576SJulian.Pullen@Sun.COM priv = (geteuid() == 0);
30119576SJulian.Pullen@Sun.COM if (!priv) {
30129576SJulian.Pullen@Sun.COM /* caller */
30139576SJulian.Pullen@Sun.COM ps = priv_allocset();
30149576SJulian.Pullen@Sun.COM
30159576SJulian.Pullen@Sun.COM (void) getppriv(PRIV_EFFECTIVE, ps);
30169576SJulian.Pullen@Sun.COM zs = priv_str_to_set("zone", ",", NULL);
30179576SJulian.Pullen@Sun.COM priv = priv_isequalset(ps, zs);
30189576SJulian.Pullen@Sun.COM priv_freeset(ps);
30199576SJulian.Pullen@Sun.COM priv_freeset(zs);
30209576SJulian.Pullen@Sun.COM }
30219576SJulian.Pullen@Sun.COM if (!priv) {
30229576SJulian.Pullen@Sun.COM (void) sprintf(errstr,
30239576SJulian.Pullen@Sun.COM gettext("Permission denied"));
30249576SJulian.Pullen@Sun.COM err = strdup(errstr);
30259576SJulian.Pullen@Sun.COM if (err == NULL)
30269576SJulian.Pullen@Sun.COM return (NS_LDAP_MEMORY);
30279576SJulian.Pullen@Sun.COM MKERROR(LOG_INFO, cookie->errorp, NS_LDAP_INTERNAL, err,
30289576SJulian.Pullen@Sun.COM NULL);
30299576SJulian.Pullen@Sun.COM return (NS_LDAP_INTERNAL);
30309576SJulian.Pullen@Sun.COM }
30319576SJulian.Pullen@Sun.COM cookie->i_flags |= NS_LDAP_READ_SHADOW;
30329576SJulian.Pullen@Sun.COM /*
30339576SJulian.Pullen@Sun.COM * We do not want to reuse connection (hence
30349576SJulian.Pullen@Sun.COM * keep it open) with admin credentials.
30359576SJulian.Pullen@Sun.COM * If NS_LDAP_KEEP_CONN is set, reject the
30369576SJulian.Pullen@Sun.COM * request.
30379576SJulian.Pullen@Sun.COM */
30389576SJulian.Pullen@Sun.COM if (cookie->i_flags & NS_LDAP_KEEP_CONN)
30399576SJulian.Pullen@Sun.COM return (NS_LDAP_INVALID_PARAM);
30409576SJulian.Pullen@Sun.COM cookie->i_flags |= NS_LDAP_NEW_CONN;
30419576SJulian.Pullen@Sun.COM }
30429576SJulian.Pullen@Sun.COM
30439576SJulian.Pullen@Sun.COM return (NS_LDAP_SUCCESS);
30449576SJulian.Pullen@Sun.COM }
30459576SJulian.Pullen@Sun.COM
30469576SJulian.Pullen@Sun.COM /*
30476616Sdm199847 * internal function for __ns_ldap_list
30480Sstevel@tonic-gate */
30496616Sdm199847 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)30506616Sdm199847 ldap_list(
30516616Sdm199847 ns_ldap_list_batch_t *batch,
30520Sstevel@tonic-gate const char *service,
30530Sstevel@tonic-gate const char *filter,
3054*12758SJulian.Pullen@Sun.COM const char *sortattr,
30550Sstevel@tonic-gate int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
30560Sstevel@tonic-gate char **realfilter, const void *userdata),
30570Sstevel@tonic-gate const char * const *attribute,
30580Sstevel@tonic-gate const ns_cred_t *auth,
30590Sstevel@tonic-gate const int flags,
30600Sstevel@tonic-gate ns_ldap_result_t **rResult, /* return result entries */
30610Sstevel@tonic-gate ns_ldap_error_t **errorp,
30626616Sdm199847 int *rcp,
30630Sstevel@tonic-gate int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
30646842Sth160488 const void *userdata, ns_conn_user_t *conn_user)
30650Sstevel@tonic-gate {
30660Sstevel@tonic-gate ns_ldap_cookie_t *cookie;
30670Sstevel@tonic-gate ns_ldap_search_desc_t **sdlist = NULL;
30680Sstevel@tonic-gate ns_ldap_search_desc_t *dptr;
30690Sstevel@tonic-gate ns_ldap_error_t *error = NULL;
30700Sstevel@tonic-gate char **dns = NULL;
30710Sstevel@tonic-gate int scope;
30720Sstevel@tonic-gate int rc;
30733387Schinlong int from_result;
30740Sstevel@tonic-gate
30750Sstevel@tonic-gate *errorp = NULL;
30766616Sdm199847 *rResult = NULL;
30776616Sdm199847 *rcp = NS_LDAP_SUCCESS;
30780Sstevel@tonic-gate
30799576SJulian.Pullen@Sun.COM /*
30809576SJulian.Pullen@Sun.COM * Sanity check - NS_LDAP_READ_SHADOW is for our
30819576SJulian.Pullen@Sun.COM * own internal use.
30829576SJulian.Pullen@Sun.COM */
30839576SJulian.Pullen@Sun.COM if (flags & NS_LDAP_READ_SHADOW)
30849576SJulian.Pullen@Sun.COM return (NS_LDAP_INVALID_PARAM);
30859576SJulian.Pullen@Sun.COM
30860Sstevel@tonic-gate /* Initialize State machine cookie */
30870Sstevel@tonic-gate cookie = init_search_state_machine();
30880Sstevel@tonic-gate if (cookie == NULL) {
30896616Sdm199847 *rcp = NS_LDAP_MEMORY;
30900Sstevel@tonic-gate return (NS_LDAP_MEMORY);
30910Sstevel@tonic-gate }
30926842Sth160488 cookie->conn_user = conn_user;
30930Sstevel@tonic-gate
30940Sstevel@tonic-gate /* see if need to follow referrals */
30950Sstevel@tonic-gate rc = __s_api_toFollowReferrals(flags,
30964765Smj162486 &cookie->followRef, errorp);
30970Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
30980Sstevel@tonic-gate delete_search_cookie(cookie);
30996616Sdm199847 *rcp = rc;
31000Sstevel@tonic-gate return (rc);
31010Sstevel@tonic-gate }
31020Sstevel@tonic-gate
31030Sstevel@tonic-gate /* get the service descriptor - or create a default one */
31040Sstevel@tonic-gate rc = __s_api_get_SSD_from_SSDtoUse_service(service,
310512022SMichen.Chang@Sun.COM &sdlist, &error);
31060Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
31070Sstevel@tonic-gate delete_search_cookie(cookie);
31080Sstevel@tonic-gate *errorp = error;
31096616Sdm199847 *rcp = rc;
31100Sstevel@tonic-gate return (rc);
31110Sstevel@tonic-gate }
31120Sstevel@tonic-gate
31130Sstevel@tonic-gate if (sdlist == NULL) {
31140Sstevel@tonic-gate /* Create default service Desc */
31150Sstevel@tonic-gate sdlist = (ns_ldap_search_desc_t **)calloc(2,
31164765Smj162486 sizeof (ns_ldap_search_desc_t *));
31170Sstevel@tonic-gate if (sdlist == NULL) {
31180Sstevel@tonic-gate delete_search_cookie(cookie);
31190Sstevel@tonic-gate cookie = NULL;
31206616Sdm199847 *rcp = NS_LDAP_MEMORY;
31210Sstevel@tonic-gate return (NS_LDAP_MEMORY);
31220Sstevel@tonic-gate }
31230Sstevel@tonic-gate dptr = (ns_ldap_search_desc_t *)
31244765Smj162486 calloc(1, sizeof (ns_ldap_search_desc_t));
31250Sstevel@tonic-gate if (dptr == NULL) {
31260Sstevel@tonic-gate free(sdlist);
31270Sstevel@tonic-gate delete_search_cookie(cookie);
31280Sstevel@tonic-gate cookie = NULL;
31296616Sdm199847 *rcp = NS_LDAP_MEMORY;
31300Sstevel@tonic-gate return (NS_LDAP_MEMORY);
31310Sstevel@tonic-gate }
31320Sstevel@tonic-gate sdlist[0] = dptr;
31330Sstevel@tonic-gate
31340Sstevel@tonic-gate /* default base */
31350Sstevel@tonic-gate rc = __s_api_getDNs(&dns, service, &cookie->errorp);
31360Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
31370Sstevel@tonic-gate if (dns) {
31380Sstevel@tonic-gate __s_api_free2dArray(dns);
31390Sstevel@tonic-gate dns = NULL;
31400Sstevel@tonic-gate }
31410Sstevel@tonic-gate *errorp = cookie->errorp;
31420Sstevel@tonic-gate cookie->errorp = NULL;
31430Sstevel@tonic-gate delete_search_cookie(cookie);
31440Sstevel@tonic-gate cookie = NULL;
31456616Sdm199847 *rcp = rc;
31460Sstevel@tonic-gate return (rc);
31470Sstevel@tonic-gate }
31480Sstevel@tonic-gate dptr->basedn = strdup(dns[0]);
31490Sstevel@tonic-gate __s_api_free2dArray(dns);
31500Sstevel@tonic-gate dns = NULL;
31510Sstevel@tonic-gate
31520Sstevel@tonic-gate /* default scope */
31530Sstevel@tonic-gate scope = 0;
31540Sstevel@tonic-gate rc = __s_api_getSearchScope(&scope, &cookie->errorp);
31550Sstevel@tonic-gate dptr->scope = scope;
31560Sstevel@tonic-gate }
31570Sstevel@tonic-gate
31580Sstevel@tonic-gate cookie->sdlist = sdlist;
31590Sstevel@tonic-gate
31600Sstevel@tonic-gate /*
31610Sstevel@tonic-gate * use VLV/PAGE control only if NS_LDAP_PAGE_CTRL is set
31620Sstevel@tonic-gate */
31630Sstevel@tonic-gate if (flags & NS_LDAP_PAGE_CTRL)
31640Sstevel@tonic-gate cookie->use_paging = TRUE;
31650Sstevel@tonic-gate else
31660Sstevel@tonic-gate cookie->use_paging = FALSE;
31670Sstevel@tonic-gate
31680Sstevel@tonic-gate /* Set up other arguments */
31690Sstevel@tonic-gate cookie->userdata = userdata;
31700Sstevel@tonic-gate if (init_filter_cb != NULL) {
31710Sstevel@tonic-gate cookie->init_filter_cb = init_filter_cb;
31720Sstevel@tonic-gate cookie->use_filtercb = 1;
31730Sstevel@tonic-gate }
31740Sstevel@tonic-gate if (callback != NULL) {
31750Sstevel@tonic-gate cookie->callback = callback;
31760Sstevel@tonic-gate cookie->use_usercb = 1;
31770Sstevel@tonic-gate }
31789576SJulian.Pullen@Sun.COM
31799576SJulian.Pullen@Sun.COM /* check_shadow() may add extra value to cookie->i_flags */
31809576SJulian.Pullen@Sun.COM cookie->i_flags = flags;
31810Sstevel@tonic-gate if (service) {
31820Sstevel@tonic-gate cookie->service = strdup(service);
31830Sstevel@tonic-gate if (cookie->service == NULL) {
31840Sstevel@tonic-gate delete_search_cookie(cookie);
31850Sstevel@tonic-gate cookie = NULL;
31866616Sdm199847 *rcp = NS_LDAP_MEMORY;
31870Sstevel@tonic-gate return (NS_LDAP_MEMORY);
31880Sstevel@tonic-gate }
31899576SJulian.Pullen@Sun.COM
31909576SJulian.Pullen@Sun.COM /*
31919576SJulian.Pullen@Sun.COM * If given, use the credential given by the caller, and
31929576SJulian.Pullen@Sun.COM * skip the credential check required for shadow update.
31939576SJulian.Pullen@Sun.COM */
31949576SJulian.Pullen@Sun.COM if (auth == NULL) {
31959576SJulian.Pullen@Sun.COM rc = check_shadow(cookie, service);
31969576SJulian.Pullen@Sun.COM if (rc != NS_LDAP_SUCCESS) {
31979576SJulian.Pullen@Sun.COM *errorp = cookie->errorp;
31989576SJulian.Pullen@Sun.COM cookie->errorp = NULL;
31999576SJulian.Pullen@Sun.COM delete_search_cookie(cookie);
32009576SJulian.Pullen@Sun.COM cookie = NULL;
32019576SJulian.Pullen@Sun.COM *rcp = rc;
32029576SJulian.Pullen@Sun.COM return (rc);
32039576SJulian.Pullen@Sun.COM }
32049576SJulian.Pullen@Sun.COM }
32050Sstevel@tonic-gate }
32060Sstevel@tonic-gate
32070Sstevel@tonic-gate cookie->i_filter = strdup(filter);
32080Sstevel@tonic-gate cookie->i_attr = attribute;
32090Sstevel@tonic-gate cookie->i_auth = auth;
3210*12758SJulian.Pullen@Sun.COM cookie->i_sortattr = sortattr;
32110Sstevel@tonic-gate
32126616Sdm199847 if (batch != NULL) {
32136616Sdm199847 cookie->batch = batch;
32146842Sth160488 cookie->reinit_on_retriable_err = B_TRUE;
32156616Sdm199847 cookie->no_wait = B_TRUE;
32166616Sdm199847 (void) search_state_machine(cookie, INIT, 0);
32176616Sdm199847 cookie->no_wait = B_FALSE;
32186616Sdm199847 rc = cookie->err_rc;
32196616Sdm199847
32206616Sdm199847 if (rc == NS_LDAP_SUCCESS) {
32216616Sdm199847 /*
32226616Sdm199847 * Here rc == NS_LDAP_SUCCESS means that the state
32236616Sdm199847 * machine init'ed successfully. The actual status
32246616Sdm199847 * of the search will be determined by
32256616Sdm199847 * __ns_ldap_list_batch_end(). Add the cookie to our
32266616Sdm199847 * batch.
32276616Sdm199847 */
32286616Sdm199847 cookie->caller_result = rResult;
32296616Sdm199847 cookie->caller_errorp = errorp;
32306616Sdm199847 cookie->caller_rc = rcp;
32316616Sdm199847 cookie->next_cookie_in_batch = batch->cookie_list;
32326616Sdm199847 batch->cookie_list = cookie;
32336616Sdm199847 batch->nactive++;
32346616Sdm199847 return (rc);
32356616Sdm199847 }
32366616Sdm199847 /*
32376616Sdm199847 * If state machine init failed then copy error to the caller
32386616Sdm199847 * and delete the cookie.
32396616Sdm199847 */
32406616Sdm199847 } else {
32416616Sdm199847 (void) search_state_machine(cookie, INIT, 0);
32426616Sdm199847 }
32430Sstevel@tonic-gate
32440Sstevel@tonic-gate /* Copy results back to user */
32450Sstevel@tonic-gate rc = cookie->err_rc;
32466842Sth160488 if (rc != NS_LDAP_SUCCESS) {
32476842Sth160488 if (conn_user != NULL && conn_user->ns_error != NULL) {
32486842Sth160488 *errorp = conn_user->ns_error;
32496842Sth160488 conn_user->ns_error = NULL;
32506842Sth160488 } else
32516842Sth160488 *errorp = cookie->errorp;
32526842Sth160488 }
32530Sstevel@tonic-gate *rResult = cookie->result;
32543387Schinlong from_result = cookie->err_from_result;
32550Sstevel@tonic-gate
32560Sstevel@tonic-gate cookie->errorp = NULL;
32570Sstevel@tonic-gate cookie->result = NULL;
32580Sstevel@tonic-gate delete_search_cookie(cookie);
32590Sstevel@tonic-gate cookie = NULL;
32600Sstevel@tonic-gate
32613387Schinlong if (from_result == 0 && *rResult == NULL)
32620Sstevel@tonic-gate rc = NS_LDAP_NOTFOUND;
32636616Sdm199847 *rcp = rc;
32640Sstevel@tonic-gate return (rc);
32650Sstevel@tonic-gate }
32660Sstevel@tonic-gate
32676616Sdm199847
32686616Sdm199847 /*
32696616Sdm199847 * __ns_ldap_list performs one or more LDAP searches to a given
32706616Sdm199847 * directory server using service search descriptors and schema
32716842Sth160488 * mapping as appropriate. The operation may be retried a
32726842Sth160488 * couple of times in error situations.
32736616Sdm199847 */
32746616Sdm199847 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)32756616Sdm199847 __ns_ldap_list(
32766616Sdm199847 const char *service,
32776616Sdm199847 const char *filter,
32786616Sdm199847 int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
32796616Sdm199847 char **realfilter, const void *userdata),
32806616Sdm199847 const char * const *attribute,
32816616Sdm199847 const ns_cred_t *auth,
32826616Sdm199847 const int flags,
32836616Sdm199847 ns_ldap_result_t **rResult, /* return result entries */
32846616Sdm199847 ns_ldap_error_t **errorp,
32856616Sdm199847 int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
32866616Sdm199847 const void *userdata)
32876616Sdm199847 {
3288*12758SJulian.Pullen@Sun.COM int mod_flags;
3289*12758SJulian.Pullen@Sun.COM /*
3290*12758SJulian.Pullen@Sun.COM * Strip the NS_LDAP_PAGE_CTRL option as this interface does not
3291*12758SJulian.Pullen@Sun.COM * support this. If you want to use this option call the API
3292*12758SJulian.Pullen@Sun.COM * __ns_ldap_list_sort() with has the sort attribute.
3293*12758SJulian.Pullen@Sun.COM */
3294*12758SJulian.Pullen@Sun.COM mod_flags = flags & (~NS_LDAP_PAGE_CTRL);
3295*12758SJulian.Pullen@Sun.COM
3296*12758SJulian.Pullen@Sun.COM return (__ns_ldap_list_sort(service, filter, NULL, init_filter_cb,
3297*12758SJulian.Pullen@Sun.COM attribute, auth, mod_flags, rResult, errorp,
3298*12758SJulian.Pullen@Sun.COM callback, userdata));
3299*12758SJulian.Pullen@Sun.COM }
3300*12758SJulian.Pullen@Sun.COM
3301*12758SJulian.Pullen@Sun.COM /*
3302*12758SJulian.Pullen@Sun.COM * __ns_ldap_list_sort performs one or more LDAP searches to a given
3303*12758SJulian.Pullen@Sun.COM * directory server using service search descriptors and schema
3304*12758SJulian.Pullen@Sun.COM * mapping as appropriate. The operation may be retried a
3305*12758SJulian.Pullen@Sun.COM * couple of times in error situations.
3306*12758SJulian.Pullen@Sun.COM */
3307*12758SJulian.Pullen@Sun.COM 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*12758SJulian.Pullen@Sun.COM __ns_ldap_list_sort(
3309*12758SJulian.Pullen@Sun.COM const char *service,
3310*12758SJulian.Pullen@Sun.COM const char *filter,
3311*12758SJulian.Pullen@Sun.COM const char *sortattr,
3312*12758SJulian.Pullen@Sun.COM int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
3313*12758SJulian.Pullen@Sun.COM char **realfilter, const void *userdata),
3314*12758SJulian.Pullen@Sun.COM const char * const *attribute,
3315*12758SJulian.Pullen@Sun.COM const ns_cred_t *auth,
3316*12758SJulian.Pullen@Sun.COM const int flags,
3317*12758SJulian.Pullen@Sun.COM ns_ldap_result_t **rResult, /* return result entries */
3318*12758SJulian.Pullen@Sun.COM ns_ldap_error_t **errorp,
3319*12758SJulian.Pullen@Sun.COM int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
3320*12758SJulian.Pullen@Sun.COM const void *userdata)
3321*12758SJulian.Pullen@Sun.COM {
33226842Sth160488 ns_conn_user_t *cu = NULL;
33236842Sth160488 int try_cnt = 0;
33246842Sth160488 int rc = NS_LDAP_SUCCESS, trc;
33256842Sth160488
33266842Sth160488 for (;;) {
33276842Sth160488 if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
33286842Sth160488 &try_cnt, &rc, errorp) == 0)
33296842Sth160488 break;
3330*12758SJulian.Pullen@Sun.COM rc = ldap_list(NULL, service, filter, sortattr, init_filter_cb,
3331*12758SJulian.Pullen@Sun.COM attribute, auth, flags, rResult, errorp, &trc, callback,
3332*12758SJulian.Pullen@Sun.COM userdata, cu);
33336842Sth160488 }
33346842Sth160488
33356842Sth160488 return (rc);
33366616Sdm199847 }
33376616Sdm199847
33386616Sdm199847 /*
33396616Sdm199847 * Create and initialize batch for native LDAP lookups
33406616Sdm199847 */
33416616Sdm199847 int
__ns_ldap_list_batch_start(ns_ldap_list_batch_t ** batch)33426616Sdm199847 __ns_ldap_list_batch_start(ns_ldap_list_batch_t **batch)
33436616Sdm199847 {
33446616Sdm199847 *batch = calloc(1, sizeof (ns_ldap_list_batch_t));
33456616Sdm199847 if (*batch == NULL)
33466616Sdm199847 return (NS_LDAP_MEMORY);
33476616Sdm199847 return (NS_LDAP_SUCCESS);
33486616Sdm199847 }
33496616Sdm199847
33506616Sdm199847
33516616Sdm199847 /*
33526616Sdm199847 * Add a LDAP search request to the batch.
33536616Sdm199847 */
33546616Sdm199847 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)33556616Sdm199847 __ns_ldap_list_batch_add(
33566616Sdm199847 ns_ldap_list_batch_t *batch,
33576616Sdm199847 const char *service,
33586616Sdm199847 const char *filter,
33596616Sdm199847 int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
33606616Sdm199847 char **realfilter, const void *userdata),
33616616Sdm199847 const char * const *attribute,
33626616Sdm199847 const ns_cred_t *auth,
33636616Sdm199847 const int flags,
33646616Sdm199847 ns_ldap_result_t **rResult, /* return result entries */
33656616Sdm199847 ns_ldap_error_t **errorp,
33666616Sdm199847 int *rcp,
33676616Sdm199847 int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
33686616Sdm199847 const void *userdata)
33696616Sdm199847 {
33706842Sth160488 ns_conn_user_t *cu;
33716842Sth160488 int rc;
3372*12758SJulian.Pullen@Sun.COM int mod_flags;
33736842Sth160488
33746842Sth160488 cu = __s_api_conn_user_init(NS_CONN_USER_SEARCH, NULL, 0);
33756842Sth160488 if (cu == NULL) {
33766842Sth160488 if (rcp != NULL)
33776842Sth160488 *rcp = NS_LDAP_MEMORY;
33786842Sth160488 return (NS_LDAP_MEMORY);
33796842Sth160488 }
33806842Sth160488
3381*12758SJulian.Pullen@Sun.COM /*
3382*12758SJulian.Pullen@Sun.COM * Strip the NS_LDAP_PAGE_CTRL option as the batch interface does not
3383*12758SJulian.Pullen@Sun.COM * support this.
3384*12758SJulian.Pullen@Sun.COM */
3385*12758SJulian.Pullen@Sun.COM mod_flags = flags & (~NS_LDAP_PAGE_CTRL);
3386*12758SJulian.Pullen@Sun.COM
3387*12758SJulian.Pullen@Sun.COM rc = ldap_list(batch, service, filter, NULL, init_filter_cb, attribute,
3388*12758SJulian.Pullen@Sun.COM auth, mod_flags, rResult, errorp, rcp, callback, userdata, cu);
33896842Sth160488
33906842Sth160488 /*
33916842Sth160488 * Free the conn_user if the cookie was not batched. If the cookie
33926842Sth160488 * was batched then __ns_ldap_list_batch_end or release will free the
33936842Sth160488 * conn_user. The batch API instructs the search_state_machine
33946842Sth160488 * to reinit and retry (max 3 times) on retriable LDAP errors.
33956842Sth160488 */
33966842Sth160488 if (rc != NS_LDAP_SUCCESS && cu != NULL) {
33976842Sth160488 if (cu->conn_mt != NULL)
33986842Sth160488 __s_api_conn_mt_return(cu);
33996842Sth160488 __s_api_conn_user_free(cu);
34006842Sth160488 }
34016842Sth160488 return (rc);
34026616Sdm199847 }
34036616Sdm199847
34046616Sdm199847
34056616Sdm199847 /*
34066616Sdm199847 * Free batch.
34076616Sdm199847 */
34086616Sdm199847 void
__ns_ldap_list_batch_release(ns_ldap_list_batch_t * batch)34096616Sdm199847 __ns_ldap_list_batch_release(ns_ldap_list_batch_t *batch)
34106616Sdm199847 {
34116616Sdm199847 ns_ldap_cookie_t *c, *next;
34126616Sdm199847
34136616Sdm199847 for (c = batch->cookie_list; c != NULL; c = next) {
34146616Sdm199847 next = c->next_cookie_in_batch;
34156842Sth160488 if (c->conn_user != NULL) {
34166842Sth160488 if (c->conn_user->conn_mt != NULL)
34176842Sth160488 __s_api_conn_mt_return(c->conn_user);
34186842Sth160488 __s_api_conn_user_free(c->conn_user);
34196842Sth160488 c->conn_user = NULL;
34206842Sth160488 }
34216616Sdm199847 delete_search_cookie(c);
34226616Sdm199847 }
34236616Sdm199847 free(batch);
34246616Sdm199847 }
34256616Sdm199847
34266842Sth160488 #define LD_USING_STATE(st) \
34276842Sth160488 ((st == DO_SEARCH) || (st == MULTI_RESULT) || (st == NEXT_RESULT))
34286616Sdm199847
34296616Sdm199847 /*
34306616Sdm199847 * Process batch. Everytime this function is called it selects an
34316616Sdm199847 * active cookie from the batch and single steps through the
34326616Sdm199847 * search_state_machine for the selected cookie. If lookup associated
34336616Sdm199847 * with the cookie is complete (success or error) then the cookie is
34346616Sdm199847 * removed from the batch and its memory freed.
34356616Sdm199847 *
34366616Sdm199847 * Returns 1 (if batch still has active cookies)
34376616Sdm199847 * 0 (if batch has no more active cookies)
34386616Sdm199847 * -1 (on errors, *rcp will contain the error code)
34396616Sdm199847 *
34406616Sdm199847 * The caller should call this function in a loop as long as it returns 1
34416616Sdm199847 * to process all the requests added to the batch. The results (and errors)
34426616Sdm199847 * will be available in the locations provided by the caller at the time of
34436616Sdm199847 * __ns_ldap_list_batch_add().
34446616Sdm199847 */
34456616Sdm199847 static
34466616Sdm199847 int
__ns_ldap_list_batch_process(ns_ldap_list_batch_t * batch,int * rcp)34476616Sdm199847 __ns_ldap_list_batch_process(ns_ldap_list_batch_t *batch, int *rcp)
34486616Sdm199847 {
34496616Sdm199847 ns_ldap_cookie_t *c, *ptr, **prev;
34506616Sdm199847 ns_state_t state;
34516842Sth160488 ns_ldap_error_t *errorp = NULL;
34526616Sdm199847 int rc;
34536616Sdm199847
34546616Sdm199847 /* Check if are already done */
34556616Sdm199847 if (batch->nactive == 0)
34566616Sdm199847 return (0);
34576616Sdm199847
34586616Sdm199847 /* Get the next cookie from the batch */
34596616Sdm199847 c = (batch->next_cookie == NULL) ?
34606616Sdm199847 batch->cookie_list : batch->next_cookie;
34616616Sdm199847
34626616Sdm199847 batch->next_cookie = c->next_cookie_in_batch;
34636616Sdm199847
34646842Sth160488 /*
34656842Sth160488 * Checks the status of the cookie's connection if it needs
34666842Sth160488 * to use that connection for ldap_search_ext or ldap_result.
34676842Sth160488 * If the connection is no longer good but worth retrying
34686842Sth160488 * then reinit the search_state_machine for this cookie
34696842Sth160488 * starting from the first search descriptor. REINIT will
34706842Sth160488 * clear any leftover results if max retries have not been
34716842Sth160488 * reached and redo the search (which may also involve
34726842Sth160488 * following referrals again).
34736842Sth160488 *
34746842Sth160488 * Note that each cookie in the batch will make this
34756842Sth160488 * determination when it reaches one of the LD_USING_STATES.
34766842Sth160488 */
34776842Sth160488 if (LD_USING_STATE(c->new_state) && c->conn_user != NULL) {
34786842Sth160488 rc = __s_api_setup_getnext(c->conn_user, &c->err_rc, &errorp);
34796842Sth160488 if (rc == LDAP_BUSY || rc == LDAP_UNAVAILABLE ||
34806842Sth160488 rc == LDAP_UNWILLING_TO_PERFORM) {
34816842Sth160488 if (errorp != NULL) {
34826842Sth160488 (void) __ns_ldap_freeError(&c->errorp);
34836842Sth160488 c->errorp = errorp;
34846842Sth160488 }
34856842Sth160488 c->new_state = REINIT;
34866842Sth160488 } else if (rc == LDAP_CONNECT_ERROR ||
34876842Sth160488 rc == LDAP_SERVER_DOWN) {
34886842Sth160488 if (errorp != NULL) {
34896842Sth160488 (void) __ns_ldap_freeError(&c->errorp);
34906842Sth160488 c->errorp = errorp;
34916842Sth160488 }
34926842Sth160488 c->new_state = REINIT;
34936842Sth160488 /*
34946842Sth160488 * MT connection is not usable,
34956842Sth160488 * close it before REINIT.
34966842Sth160488 */
34976842Sth160488 __s_api_conn_mt_close(
34986842Sth160488 c->conn_user, rc, NULL);
34996842Sth160488 } else if (rc != NS_LDAP_SUCCESS) {
35006616Sdm199847 if (rcp != NULL)
35016616Sdm199847 *rcp = rc;
35026842Sth160488 *c->caller_result = NULL;
35036842Sth160488 *c->caller_errorp = errorp;
35046842Sth160488 *c->caller_rc = rc;
35056616Sdm199847 return (-1);
35066616Sdm199847 }
35076616Sdm199847 }
35086616Sdm199847
35096616Sdm199847 for (;;) {
35106616Sdm199847 /* Single step through the search_state_machine */
35116616Sdm199847 state = search_state_machine(c, c->new_state, ONE_STEP);
35126616Sdm199847 switch (state) {
35136616Sdm199847 case LDAP_ERROR:
35146616Sdm199847 (void) search_state_machine(c, state, ONE_STEP);
35156616Sdm199847 (void) search_state_machine(c, CLEAR_RESULTS, ONE_STEP);
35166616Sdm199847 /* FALLTHROUGH */
35176616Sdm199847 case ERROR:
35186616Sdm199847 case EXIT:
35196616Sdm199847 *c->caller_result = c->result;
35206616Sdm199847 *c->caller_errorp = c->errorp;
35216616Sdm199847 *c->caller_rc =
35226616Sdm199847 (c->result == NULL && c->err_from_result == 0)
35236616Sdm199847 ? NS_LDAP_NOTFOUND : c->err_rc;
35246616Sdm199847 c->result = NULL;
35256616Sdm199847 c->errorp = NULL;
35266616Sdm199847 /* Remove the cookie from the batch */
35276616Sdm199847 ptr = batch->cookie_list;
35286616Sdm199847 prev = &batch->cookie_list;
35296616Sdm199847 while (ptr != NULL) {
35306616Sdm199847 if (ptr == c) {
35316616Sdm199847 *prev = ptr->next_cookie_in_batch;
35326616Sdm199847 break;
35336616Sdm199847 }
35346616Sdm199847 prev = &ptr->next_cookie_in_batch;
35356616Sdm199847 ptr = ptr->next_cookie_in_batch;
35366616Sdm199847 }
35376616Sdm199847 /* Delete cookie and decrement active cookie count */
35386842Sth160488 if (c->conn_user != NULL) {
35396842Sth160488 if (c->conn_user->conn_mt != NULL)
35406842Sth160488 __s_api_conn_mt_return(c->conn_user);
35416842Sth160488 __s_api_conn_user_free(c->conn_user);
35426842Sth160488 c->conn_user = NULL;
35436842Sth160488 }
35446616Sdm199847 delete_search_cookie(c);
35456616Sdm199847 batch->nactive--;
35466616Sdm199847 break;
35476616Sdm199847 case NEXT_RESULT:
35486616Sdm199847 case MULTI_RESULT:
35496616Sdm199847 /*
35506616Sdm199847 * This means that search_state_machine needs to do
35516616Sdm199847 * another ldap_result() for the cookie in question.
35526616Sdm199847 * We only do at most one ldap_result() per call in
35536616Sdm199847 * this function and therefore we return. This allows
35546616Sdm199847 * the caller to process results from other cookies
35556616Sdm199847 * in the batch without getting tied up on just one
35566616Sdm199847 * cookie.
35576616Sdm199847 */
35586616Sdm199847 break;
35596616Sdm199847 default:
35606616Sdm199847 /*
35616616Sdm199847 * This includes states that follow NEXT_RESULT or
35626616Sdm199847 * MULTI_RESULT such as PROCESS_RESULT and
35636616Sdm199847 * END_PROCESS_RESULT. We continue processing
35646616Sdm199847 * this cookie till we reach either the error, exit
35656616Sdm199847 * or the result states.
35666616Sdm199847 */
35676616Sdm199847 continue;
35686616Sdm199847 }
35696616Sdm199847 break;
35706616Sdm199847 }
35716616Sdm199847
35726616Sdm199847 /* Return 0 if no more cookies left otherwise 1 */
35736616Sdm199847 return ((batch->nactive > 0) ? 1 : 0);
35746616Sdm199847 }
35756616Sdm199847
35766616Sdm199847
35776616Sdm199847 /*
35786616Sdm199847 * Process all the active cookies in the batch and when none
35796616Sdm199847 * remains finalize the batch.
35806616Sdm199847 */
35816616Sdm199847 int
__ns_ldap_list_batch_end(ns_ldap_list_batch_t * batch)35826616Sdm199847 __ns_ldap_list_batch_end(ns_ldap_list_batch_t *batch)
35836616Sdm199847 {
35846616Sdm199847 int rc = NS_LDAP_SUCCESS;
35856616Sdm199847 while (__ns_ldap_list_batch_process(batch, &rc) > 0)
35866616Sdm199847 ;
35876616Sdm199847 __ns_ldap_list_batch_release(batch);
35886616Sdm199847 return (rc);
35896616Sdm199847 }
35906616Sdm199847
35910Sstevel@tonic-gate /*
35926842Sth160488 * find_domainname performs one or more LDAP searches to
35930Sstevel@tonic-gate * find the value of the nisdomain attribute associated with
35946842Sth160488 * the input DN (with no retry).
35950Sstevel@tonic-gate */
35960Sstevel@tonic-gate
35970Sstevel@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)35986842Sth160488 find_domainname(const char *dn, char **domainname, const ns_cred_t *cred,
35996842Sth160488 ns_ldap_error_t **errorp, ns_conn_user_t *conn_user)
36000Sstevel@tonic-gate {
36010Sstevel@tonic-gate
36020Sstevel@tonic-gate ns_ldap_cookie_t *cookie;
36030Sstevel@tonic-gate ns_ldap_search_desc_t **sdlist;
36040Sstevel@tonic-gate ns_ldap_search_desc_t *dptr;
36050Sstevel@tonic-gate int rc;
36060Sstevel@tonic-gate char **value;
36070Sstevel@tonic-gate int flags = 0;
36080Sstevel@tonic-gate
36090Sstevel@tonic-gate *domainname = NULL;
36100Sstevel@tonic-gate *errorp = NULL;
36110Sstevel@tonic-gate
36120Sstevel@tonic-gate /* Initialize State machine cookie */
36130Sstevel@tonic-gate cookie = init_search_state_machine();
36140Sstevel@tonic-gate if (cookie == NULL) {
36150Sstevel@tonic-gate return (NS_LDAP_MEMORY);
36160Sstevel@tonic-gate }
36176842Sth160488 cookie->conn_user = conn_user;
36180Sstevel@tonic-gate
36190Sstevel@tonic-gate /* see if need to follow referrals */
36200Sstevel@tonic-gate rc = __s_api_toFollowReferrals(flags,
36214765Smj162486 &cookie->followRef, errorp);
36220Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
36230Sstevel@tonic-gate delete_search_cookie(cookie);
36240Sstevel@tonic-gate return (rc);
36250Sstevel@tonic-gate }
36260Sstevel@tonic-gate
36270Sstevel@tonic-gate /* Create default service Desc */
36280Sstevel@tonic-gate sdlist = (ns_ldap_search_desc_t **)calloc(2,
36294765Smj162486 sizeof (ns_ldap_search_desc_t *));
36300Sstevel@tonic-gate if (sdlist == NULL) {
36310Sstevel@tonic-gate delete_search_cookie(cookie);
36320Sstevel@tonic-gate cookie = NULL;
36330Sstevel@tonic-gate return (NS_LDAP_MEMORY);
36340Sstevel@tonic-gate }
36350Sstevel@tonic-gate dptr = (ns_ldap_search_desc_t *)
36364765Smj162486 calloc(1, sizeof (ns_ldap_search_desc_t));
36370Sstevel@tonic-gate if (dptr == NULL) {
36380Sstevel@tonic-gate free(sdlist);
36390Sstevel@tonic-gate delete_search_cookie(cookie);
36400Sstevel@tonic-gate cookie = NULL;
36410Sstevel@tonic-gate return (NS_LDAP_MEMORY);
36420Sstevel@tonic-gate }
36430Sstevel@tonic-gate sdlist[0] = dptr;
36440Sstevel@tonic-gate
36450Sstevel@tonic-gate /* search base is dn */
36460Sstevel@tonic-gate dptr->basedn = strdup(dn);
36470Sstevel@tonic-gate
36480Sstevel@tonic-gate /* search scope is base */
36490Sstevel@tonic-gate dptr->scope = NS_LDAP_SCOPE_BASE;
36500Sstevel@tonic-gate
36510Sstevel@tonic-gate /* search filter is "nisdomain=*" */
36520Sstevel@tonic-gate dptr->filter = strdup(_NIS_FILTER);
36530Sstevel@tonic-gate
36540Sstevel@tonic-gate cookie->sdlist = sdlist;
36550Sstevel@tonic-gate cookie->i_filter = strdup(dptr->filter);
36560Sstevel@tonic-gate cookie->i_attr = nis_domain_attrs;
36570Sstevel@tonic-gate cookie->i_auth = cred;
36580Sstevel@tonic-gate cookie->i_flags = 0;
36590Sstevel@tonic-gate
36600Sstevel@tonic-gate /* Process search */
36610Sstevel@tonic-gate rc = search_state_machine(cookie, INIT, 0);
36620Sstevel@tonic-gate
36630Sstevel@tonic-gate /* Copy domain name if found */
36640Sstevel@tonic-gate rc = cookie->err_rc;
36656842Sth160488 if (rc != NS_LDAP_SUCCESS) {
36666842Sth160488 if (conn_user != NULL && conn_user->ns_error != NULL) {
36676842Sth160488 *errorp = conn_user->ns_error;
36686842Sth160488 conn_user->ns_error = NULL;
36696842Sth160488 } else
36706842Sth160488 *errorp = cookie->errorp;
36716842Sth160488 }
36720Sstevel@tonic-gate if (cookie->result == NULL)
36730Sstevel@tonic-gate rc = NS_LDAP_NOTFOUND;
36740Sstevel@tonic-gate if (rc == NS_LDAP_SUCCESS) {
36750Sstevel@tonic-gate value = __ns_ldap_getAttr(cookie->result->entry,
36764765Smj162486 _NIS_DOMAIN);
36770Sstevel@tonic-gate if (value[0])
36780Sstevel@tonic-gate *domainname = strdup(value[0]);
36790Sstevel@tonic-gate else
36800Sstevel@tonic-gate rc = NS_LDAP_NOTFOUND;
36810Sstevel@tonic-gate }
36820Sstevel@tonic-gate if (cookie->result != NULL)
36830Sstevel@tonic-gate (void) __ns_ldap_freeResult(&cookie->result);
36840Sstevel@tonic-gate cookie->errorp = NULL;
36850Sstevel@tonic-gate delete_search_cookie(cookie);
36860Sstevel@tonic-gate cookie = NULL;
36870Sstevel@tonic-gate return (rc);
36880Sstevel@tonic-gate }
36890Sstevel@tonic-gate
36906842Sth160488 /*
36916842Sth160488 * __s_api_find_domainname performs one or more LDAP searches to
36926842Sth160488 * find the value of the nisdomain attribute associated with
36936842Sth160488 * the input DN (with retry).
36946842Sth160488 */
36956842Sth160488
36966842Sth160488 static int
__s_api_find_domainname(const char * dn,char ** domainname,const ns_cred_t * cred,ns_ldap_error_t ** errorp)36976842Sth160488 __s_api_find_domainname(const char *dn, char **domainname,
36986842Sth160488 const ns_cred_t *cred, ns_ldap_error_t **errorp)
36996842Sth160488 {
37006842Sth160488 ns_conn_user_t *cu = NULL;
37016842Sth160488 int try_cnt = 0;
37026842Sth160488 int rc = NS_LDAP_SUCCESS;
37036842Sth160488
37046842Sth160488 for (;;) {
37056842Sth160488 if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
37066842Sth160488 &try_cnt, &rc, errorp) == 0)
37076842Sth160488 break;
37086842Sth160488 rc = find_domainname(dn, domainname, cred, errorp, cu);
37096842Sth160488 }
37106842Sth160488
37116842Sth160488 return (rc);
37126842Sth160488 }
37136842Sth160488
37146842Sth160488 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)37156842Sth160488 firstEntry(
37166842Sth160488 const char *service,
37176842Sth160488 const char *filter,
3718*12758SJulian.Pullen@Sun.COM const char *sortattr,
37196842Sth160488 int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
37206842Sth160488 char **realfilter, const void *userdata),
37216842Sth160488 const char * const *attribute,
37226842Sth160488 const ns_cred_t *auth,
37236842Sth160488 const int flags,
37246842Sth160488 void **vcookie,
37256842Sth160488 ns_ldap_result_t **result,
37266842Sth160488 ns_ldap_error_t ** errorp,
37276842Sth160488 const void *userdata,
37286842Sth160488 ns_conn_user_t *conn_user)
37290Sstevel@tonic-gate {
37300Sstevel@tonic-gate ns_ldap_cookie_t *cookie = NULL;
37310Sstevel@tonic-gate ns_ldap_error_t *error = NULL;
37320Sstevel@tonic-gate ns_state_t state;
37330Sstevel@tonic-gate ns_ldap_search_desc_t **sdlist;
37340Sstevel@tonic-gate ns_ldap_search_desc_t *dptr;
37350Sstevel@tonic-gate char **dns = NULL;
37360Sstevel@tonic-gate int scope;
37370Sstevel@tonic-gate int rc;
37380Sstevel@tonic-gate
37390Sstevel@tonic-gate *errorp = NULL;
37400Sstevel@tonic-gate *result = NULL;
37410Sstevel@tonic-gate
37429576SJulian.Pullen@Sun.COM /*
37439576SJulian.Pullen@Sun.COM * Sanity check - NS_LDAP_READ_SHADOW is for our
37449576SJulian.Pullen@Sun.COM * own internal use.
37459576SJulian.Pullen@Sun.COM */
37469576SJulian.Pullen@Sun.COM if (flags & NS_LDAP_READ_SHADOW)
37479576SJulian.Pullen@Sun.COM return (NS_LDAP_INVALID_PARAM);
37489576SJulian.Pullen@Sun.COM
37490Sstevel@tonic-gate /* get the service descriptor - or create a default one */
37500Sstevel@tonic-gate rc = __s_api_get_SSD_from_SSDtoUse_service(service,
375112022SMichen.Chang@Sun.COM &sdlist, &error);
37520Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
37530Sstevel@tonic-gate *errorp = error;
37540Sstevel@tonic-gate return (rc);
37550Sstevel@tonic-gate }
37560Sstevel@tonic-gate if (sdlist == NULL) {
37570Sstevel@tonic-gate /* Create default service Desc */
37580Sstevel@tonic-gate sdlist = (ns_ldap_search_desc_t **)calloc(2,
37594765Smj162486 sizeof (ns_ldap_search_desc_t *));
37600Sstevel@tonic-gate if (sdlist == NULL) {
37610Sstevel@tonic-gate return (NS_LDAP_MEMORY);
37620Sstevel@tonic-gate }
37630Sstevel@tonic-gate dptr = (ns_ldap_search_desc_t *)
37644765Smj162486 calloc(1, sizeof (ns_ldap_search_desc_t));
37650Sstevel@tonic-gate if (dptr == NULL) {
37660Sstevel@tonic-gate free(sdlist);
37670Sstevel@tonic-gate return (NS_LDAP_MEMORY);
37680Sstevel@tonic-gate }
37690Sstevel@tonic-gate sdlist[0] = dptr;
37700Sstevel@tonic-gate
37710Sstevel@tonic-gate /* default base */
37720Sstevel@tonic-gate rc = __s_api_getDNs(&dns, service, &error);
37730Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
37740Sstevel@tonic-gate if (dns) {
37750Sstevel@tonic-gate __s_api_free2dArray(dns);
37760Sstevel@tonic-gate dns = NULL;
37770Sstevel@tonic-gate }
37780Sstevel@tonic-gate if (sdlist) {
37790Sstevel@tonic-gate (void) __ns_ldap_freeSearchDescriptors(
37804765Smj162486 &sdlist);
37810Sstevel@tonic-gate
37820Sstevel@tonic-gate sdlist = NULL;
37830Sstevel@tonic-gate }
37840Sstevel@tonic-gate *errorp = error;
37850Sstevel@tonic-gate return (rc);
37860Sstevel@tonic-gate }
37870Sstevel@tonic-gate dptr->basedn = strdup(dns[0]);
37880Sstevel@tonic-gate __s_api_free2dArray(dns);
37890Sstevel@tonic-gate dns = NULL;
37900Sstevel@tonic-gate
37910Sstevel@tonic-gate /* default scope */
37920Sstevel@tonic-gate scope = 0;
37930Sstevel@tonic-gate cookie = init_search_state_machine();
37940Sstevel@tonic-gate if (cookie == NULL) {
37950Sstevel@tonic-gate if (sdlist) {
37960Sstevel@tonic-gate (void) __ns_ldap_freeSearchDescriptors(&sdlist);
37970Sstevel@tonic-gate sdlist = NULL;
37980Sstevel@tonic-gate }
37990Sstevel@tonic-gate return (NS_LDAP_MEMORY);
38000Sstevel@tonic-gate }
38010Sstevel@tonic-gate rc = __s_api_getSearchScope(&scope, &cookie->errorp);
38020Sstevel@tonic-gate dptr->scope = scope;
38030Sstevel@tonic-gate }
38040Sstevel@tonic-gate
38050Sstevel@tonic-gate /* Initialize State machine cookie */
38060Sstevel@tonic-gate if (cookie == NULL)
38070Sstevel@tonic-gate cookie = init_search_state_machine();
38080Sstevel@tonic-gate if (cookie == NULL) {
38090Sstevel@tonic-gate if (sdlist) {
38100Sstevel@tonic-gate (void) __ns_ldap_freeSearchDescriptors(&sdlist);
38110Sstevel@tonic-gate sdlist = NULL;
38120Sstevel@tonic-gate }
38130Sstevel@tonic-gate return (NS_LDAP_MEMORY);
38140Sstevel@tonic-gate }
38150Sstevel@tonic-gate
38166842Sth160488 /* identify self as a getent user */
38176842Sth160488 cookie->conn_user = conn_user;
38186842Sth160488
38190Sstevel@tonic-gate cookie->sdlist = sdlist;
38200Sstevel@tonic-gate
38210Sstevel@tonic-gate /* see if need to follow referrals */
38220Sstevel@tonic-gate rc = __s_api_toFollowReferrals(flags,
38234765Smj162486 &cookie->followRef, errorp);
38240Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
38250Sstevel@tonic-gate delete_search_cookie(cookie);
38260Sstevel@tonic-gate return (rc);
38270Sstevel@tonic-gate }
38280Sstevel@tonic-gate
38290Sstevel@tonic-gate /*
38300Sstevel@tonic-gate * use VLV/PAGE control only if NS_LDAP_NO_PAGE_CTRL is not set
38310Sstevel@tonic-gate */
38320Sstevel@tonic-gate if (flags & NS_LDAP_NO_PAGE_CTRL)
38330Sstevel@tonic-gate cookie->use_paging = FALSE;
38340Sstevel@tonic-gate else
38350Sstevel@tonic-gate cookie->use_paging = TRUE;
38360Sstevel@tonic-gate
38370Sstevel@tonic-gate /* Set up other arguments */
38380Sstevel@tonic-gate cookie->userdata = userdata;
38390Sstevel@tonic-gate if (init_filter_cb != NULL) {
38400Sstevel@tonic-gate cookie->init_filter_cb = init_filter_cb;
38410Sstevel@tonic-gate cookie->use_filtercb = 1;
38420Sstevel@tonic-gate }
38430Sstevel@tonic-gate cookie->use_usercb = 0;
38449576SJulian.Pullen@Sun.COM /* check_shadow() may add extra value to cookie->i_flags */
38459576SJulian.Pullen@Sun.COM cookie->i_flags = flags;
38460Sstevel@tonic-gate if (service) {
38470Sstevel@tonic-gate cookie->service = strdup(service);
38480Sstevel@tonic-gate if (cookie->service == NULL) {
38490Sstevel@tonic-gate delete_search_cookie(cookie);
38500Sstevel@tonic-gate return (NS_LDAP_MEMORY);
38510Sstevel@tonic-gate }
38529576SJulian.Pullen@Sun.COM
38539576SJulian.Pullen@Sun.COM /*
38549576SJulian.Pullen@Sun.COM * If given, use the credential given by the caller, and
38559576SJulian.Pullen@Sun.COM * skip the credential check required for shadow update.
38569576SJulian.Pullen@Sun.COM */
38579576SJulian.Pullen@Sun.COM if (auth == NULL) {
38589576SJulian.Pullen@Sun.COM rc = check_shadow(cookie, service);
38599576SJulian.Pullen@Sun.COM if (rc != NS_LDAP_SUCCESS) {
38609576SJulian.Pullen@Sun.COM *errorp = cookie->errorp;
38619576SJulian.Pullen@Sun.COM cookie->errorp = NULL;
38629576SJulian.Pullen@Sun.COM delete_search_cookie(cookie);
38639576SJulian.Pullen@Sun.COM cookie = NULL;
38649576SJulian.Pullen@Sun.COM return (rc);
38659576SJulian.Pullen@Sun.COM }
38669576SJulian.Pullen@Sun.COM }
38670Sstevel@tonic-gate }
38680Sstevel@tonic-gate
38690Sstevel@tonic-gate cookie->i_filter = strdup(filter);
38700Sstevel@tonic-gate cookie->i_attr = attribute;
3871*12758SJulian.Pullen@Sun.COM cookie->i_sortattr = sortattr;
38720Sstevel@tonic-gate cookie->i_auth = auth;
38730Sstevel@tonic-gate
38740Sstevel@tonic-gate state = INIT;
38750Sstevel@tonic-gate for (;;) {
38760Sstevel@tonic-gate state = search_state_machine(cookie, state, ONE_STEP);
38770Sstevel@tonic-gate switch (state) {
38780Sstevel@tonic-gate case PROCESS_RESULT:
38790Sstevel@tonic-gate *result = cookie->result;
38800Sstevel@tonic-gate cookie->result = NULL;
38810Sstevel@tonic-gate *vcookie = (void *)cookie;
38820Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
38834953Smichen case LDAP_ERROR:
38844953Smichen state = search_state_machine(cookie, state, ONE_STEP);
38854953Smichen state = search_state_machine(cookie, CLEAR_RESULTS,
38864953Smichen ONE_STEP);
38874953Smichen /* FALLTHROUGH */
38880Sstevel@tonic-gate case ERROR:
38890Sstevel@tonic-gate rc = cookie->err_rc;
38906842Sth160488 if (conn_user != NULL && conn_user->ns_error != NULL) {
38916842Sth160488 *errorp = conn_user->ns_error;
38926842Sth160488 conn_user->ns_error = NULL;
38936842Sth160488 } else {
38946842Sth160488 *errorp = cookie->errorp;
38956842Sth160488 cookie->errorp = NULL;
38966842Sth160488 }
38970Sstevel@tonic-gate delete_search_cookie(cookie);
38980Sstevel@tonic-gate return (rc);
38990Sstevel@tonic-gate case EXIT:
39000Sstevel@tonic-gate rc = cookie->err_rc;
39010Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
39020Sstevel@tonic-gate *errorp = cookie->errorp;
39030Sstevel@tonic-gate cookie->errorp = NULL;
39040Sstevel@tonic-gate } else {
39050Sstevel@tonic-gate rc = NS_LDAP_NOTFOUND;
39060Sstevel@tonic-gate }
39070Sstevel@tonic-gate
39080Sstevel@tonic-gate delete_search_cookie(cookie);
39090Sstevel@tonic-gate return (rc);
39100Sstevel@tonic-gate
39110Sstevel@tonic-gate default:
39120Sstevel@tonic-gate break;
39130Sstevel@tonic-gate }
39140Sstevel@tonic-gate }
39150Sstevel@tonic-gate }
39160Sstevel@tonic-gate
39176842Sth160488 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)39186842Sth160488 __ns_ldap_firstEntry(
39196842Sth160488 const char *service,
39206842Sth160488 const char *filter,
3921*12758SJulian.Pullen@Sun.COM const char *vlv_sort,
39226842Sth160488 int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
39236842Sth160488 char **realfilter, const void *userdata),
39246842Sth160488 const char * const *attribute,
39256842Sth160488 const ns_cred_t *auth,
39266842Sth160488 const int flags,
39276842Sth160488 void **vcookie,
39286842Sth160488 ns_ldap_result_t **result,
39296842Sth160488 ns_ldap_error_t ** errorp,
39306842Sth160488 const void *userdata)
39316842Sth160488 {
39326842Sth160488 ns_conn_user_t *cu = NULL;
39336842Sth160488 int try_cnt = 0;
39346842Sth160488 int rc = NS_LDAP_SUCCESS;
39356842Sth160488
39366842Sth160488 for (;;) {
39376842Sth160488 if (__s_api_setup_retry_search(&cu, NS_CONN_USER_GETENT,
39386842Sth160488 &try_cnt, &rc, errorp) == 0)
39396842Sth160488 break;
3940*12758SJulian.Pullen@Sun.COM rc = firstEntry(service, filter, vlv_sort, init_filter_cb,
3941*12758SJulian.Pullen@Sun.COM attribute, auth, flags, vcookie, result, errorp, userdata,
3942*12758SJulian.Pullen@Sun.COM cu);
39436842Sth160488 }
39446842Sth160488 return (rc);
39456842Sth160488 }
39466842Sth160488
39470Sstevel@tonic-gate /*ARGSUSED2*/
39480Sstevel@tonic-gate int
__ns_ldap_nextEntry(void * vcookie,ns_ldap_result_t ** result,ns_ldap_error_t ** errorp)39496842Sth160488 __ns_ldap_nextEntry(void *vcookie, ns_ldap_result_t **result,
39506842Sth160488 ns_ldap_error_t ** errorp)
39510Sstevel@tonic-gate {
39520Sstevel@tonic-gate ns_ldap_cookie_t *cookie;
39530Sstevel@tonic-gate ns_state_t state;
39540Sstevel@tonic-gate int rc;
39550Sstevel@tonic-gate
39560Sstevel@tonic-gate cookie = (ns_ldap_cookie_t *)vcookie;
39570Sstevel@tonic-gate cookie->result = NULL;
39580Sstevel@tonic-gate *result = NULL;
39590Sstevel@tonic-gate
39606842Sth160488 if (cookie->conn_user != NULL) {
39616842Sth160488 rc = __s_api_setup_getnext(cookie->conn_user,
39626842Sth160488 &cookie->err_rc, errorp);
39636842Sth160488 if (rc != NS_LDAP_SUCCESS)
39646842Sth160488 return (rc);
39656842Sth160488 }
39666842Sth160488
39670Sstevel@tonic-gate state = END_PROCESS_RESULT;
39680Sstevel@tonic-gate for (;;) {
39690Sstevel@tonic-gate state = search_state_machine(cookie, state, ONE_STEP);
39700Sstevel@tonic-gate switch (state) {
39710Sstevel@tonic-gate case PROCESS_RESULT:
39720Sstevel@tonic-gate *result = cookie->result;
39730Sstevel@tonic-gate cookie->result = NULL;
39740Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
39754953Smichen case LDAP_ERROR:
39764953Smichen state = search_state_machine(cookie, state, ONE_STEP);
39774953Smichen state = search_state_machine(cookie, CLEAR_RESULTS,
39784953Smichen ONE_STEP);
39794953Smichen /* FALLTHROUGH */
39800Sstevel@tonic-gate case ERROR:
39810Sstevel@tonic-gate rc = cookie->err_rc;
39820Sstevel@tonic-gate *errorp = cookie->errorp;
39830Sstevel@tonic-gate cookie->errorp = NULL;
39840Sstevel@tonic-gate return (rc);
39850Sstevel@tonic-gate case EXIT:
39860Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
39870Sstevel@tonic-gate }
39880Sstevel@tonic-gate }
39890Sstevel@tonic-gate }
39900Sstevel@tonic-gate
39910Sstevel@tonic-gate int
__ns_ldap_endEntry(void ** vcookie,ns_ldap_error_t ** errorp)39920Sstevel@tonic-gate __ns_ldap_endEntry(
39930Sstevel@tonic-gate void **vcookie,
39940Sstevel@tonic-gate ns_ldap_error_t ** errorp)
39950Sstevel@tonic-gate {
39960Sstevel@tonic-gate ns_ldap_cookie_t *cookie;
39970Sstevel@tonic-gate int rc;
39980Sstevel@tonic-gate
39990Sstevel@tonic-gate if (*vcookie == NULL)
40000Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
40010Sstevel@tonic-gate
40020Sstevel@tonic-gate cookie = (ns_ldap_cookie_t *)(*vcookie);
40030Sstevel@tonic-gate cookie->result = NULL;
40040Sstevel@tonic-gate
40050Sstevel@tonic-gate /* Complete search */
40064765Smj162486 rc = search_state_machine(cookie, CLEAR_RESULTS, 0);
40070Sstevel@tonic-gate
40080Sstevel@tonic-gate /* Copy results back to user */
40090Sstevel@tonic-gate rc = cookie->err_rc;
40100Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS)
40110Sstevel@tonic-gate *errorp = cookie->errorp;
40120Sstevel@tonic-gate
40130Sstevel@tonic-gate cookie->errorp = NULL;
40146842Sth160488 if (cookie->conn_user != NULL) {
40156842Sth160488 if (cookie->conn_user->conn_mt != NULL)
40166842Sth160488 __s_api_conn_mt_return(cookie->conn_user);
40176842Sth160488 __s_api_conn_user_free(cookie->conn_user);
40186842Sth160488 }
40190Sstevel@tonic-gate delete_search_cookie(cookie);
40200Sstevel@tonic-gate cookie = NULL;
40210Sstevel@tonic-gate *vcookie = NULL;
40220Sstevel@tonic-gate
40230Sstevel@tonic-gate return (rc);
40240Sstevel@tonic-gate }
40250Sstevel@tonic-gate
40260Sstevel@tonic-gate
40270Sstevel@tonic-gate int
__ns_ldap_freeResult(ns_ldap_result_t ** result)40280Sstevel@tonic-gate __ns_ldap_freeResult(ns_ldap_result_t **result)
40290Sstevel@tonic-gate {
40300Sstevel@tonic-gate
40310Sstevel@tonic-gate ns_ldap_entry_t *curEntry = NULL;
40320Sstevel@tonic-gate ns_ldap_entry_t *delEntry = NULL;
40330Sstevel@tonic-gate int i;
40340Sstevel@tonic-gate ns_ldap_result_t *res = *result;
40350Sstevel@tonic-gate
40360Sstevel@tonic-gate #ifdef DEBUG
40370Sstevel@tonic-gate (void) fprintf(stderr, "__ns_ldap_freeResult START\n");
40380Sstevel@tonic-gate #endif
40390Sstevel@tonic-gate if (res == NULL)
40400Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
40410Sstevel@tonic-gate
40420Sstevel@tonic-gate if (res->entry != NULL)
40430Sstevel@tonic-gate curEntry = res->entry;
40440Sstevel@tonic-gate
40450Sstevel@tonic-gate for (i = 0; i < res->entries_count; i++) {
40460Sstevel@tonic-gate if (curEntry != NULL) {
40470Sstevel@tonic-gate delEntry = curEntry;
40480Sstevel@tonic-gate curEntry = curEntry->next;
40490Sstevel@tonic-gate __ns_ldap_freeEntry(delEntry);
40500Sstevel@tonic-gate }
40510Sstevel@tonic-gate }
40520Sstevel@tonic-gate
40530Sstevel@tonic-gate free(res);
40540Sstevel@tonic-gate *result = NULL;
40550Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
40560Sstevel@tonic-gate }
40570Sstevel@tonic-gate
40580Sstevel@tonic-gate /*ARGSUSED*/
40590Sstevel@tonic-gate int
__ns_ldap_auth(const ns_cred_t * auth,const int flags,ns_ldap_error_t ** errorp,LDAPControl ** serverctrls,LDAPControl ** clientctrls)40600Sstevel@tonic-gate __ns_ldap_auth(const ns_cred_t *auth,
40610Sstevel@tonic-gate const int flags,
40620Sstevel@tonic-gate ns_ldap_error_t **errorp,
40630Sstevel@tonic-gate LDAPControl **serverctrls,
40640Sstevel@tonic-gate LDAPControl **clientctrls)
40650Sstevel@tonic-gate {
40660Sstevel@tonic-gate
40670Sstevel@tonic-gate ConnectionID connectionId = -1;
40680Sstevel@tonic-gate Connection *conp;
40690Sstevel@tonic-gate int rc = 0;
40700Sstevel@tonic-gate int do_not_fail_if_new_pwd_reqd = 0;
40711179Svv149972 int nopasswd_acct_mgmt = 0;
40726842Sth160488 ns_conn_user_t *conn_user;
40730Sstevel@tonic-gate
40740Sstevel@tonic-gate
40750Sstevel@tonic-gate #ifdef DEBUG
40760Sstevel@tonic-gate (void) fprintf(stderr, "__ns_ldap_auth START\n");
40770Sstevel@tonic-gate #endif
40780Sstevel@tonic-gate
40790Sstevel@tonic-gate *errorp = NULL;
40800Sstevel@tonic-gate if (!auth)
40810Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
40820Sstevel@tonic-gate
40836842Sth160488 conn_user = __s_api_conn_user_init(NS_CONN_USER_AUTH,
40846842Sth160488 NULL, B_FALSE);
40856842Sth160488
40862830Sdjl rc = __s_api_getConnection(NULL, flags | NS_LDAP_NEW_CONN,
40874765Smj162486 auth, &connectionId, &conp, errorp,
40886842Sth160488 do_not_fail_if_new_pwd_reqd, nopasswd_acct_mgmt,
40896842Sth160488 conn_user);
40906842Sth160488
40916842Sth160488 if (conn_user != NULL)
40926842Sth160488 __s_api_conn_user_free(conn_user);
40936842Sth160488
40940Sstevel@tonic-gate if (rc == NS_LDAP_OP_FAILED && *errorp)
40950Sstevel@tonic-gate (void) __ns_ldap_freeError(errorp);
40960Sstevel@tonic-gate
40970Sstevel@tonic-gate if (connectionId > -1)
40980Sstevel@tonic-gate DropConnection(connectionId, flags);
40990Sstevel@tonic-gate return (rc);
41000Sstevel@tonic-gate }
41010Sstevel@tonic-gate
41020Sstevel@tonic-gate char **
__ns_ldap_getAttr(const ns_ldap_entry_t * entry,const char * attrname)41030Sstevel@tonic-gate __ns_ldap_getAttr(const ns_ldap_entry_t *entry, const char *attrname)
41040Sstevel@tonic-gate {
41050Sstevel@tonic-gate int i;
41060Sstevel@tonic-gate
41070Sstevel@tonic-gate if (entry == NULL)
41080Sstevel@tonic-gate return (NULL);
41090Sstevel@tonic-gate for (i = 0; i < entry->attr_count; i++) {
41100Sstevel@tonic-gate if (strcasecmp(entry->attr_pair[i]->attrname, attrname) == NULL)
41110Sstevel@tonic-gate return (entry->attr_pair[i]->attrvalue);
41120Sstevel@tonic-gate }
41130Sstevel@tonic-gate return (NULL);
41140Sstevel@tonic-gate }
41150Sstevel@tonic-gate
41162830Sdjl ns_ldap_attr_t *
__ns_ldap_getAttrStruct(const ns_ldap_entry_t * entry,const char * attrname)41172830Sdjl __ns_ldap_getAttrStruct(const ns_ldap_entry_t *entry, const char *attrname)
41182830Sdjl {
41192830Sdjl int i;
41202830Sdjl
41212830Sdjl if (entry == NULL)
41222830Sdjl return (NULL);
41232830Sdjl for (i = 0; i < entry->attr_count; i++) {
41242830Sdjl if (strcasecmp(entry->attr_pair[i]->attrname, attrname) == NULL)
41252830Sdjl return (entry->attr_pair[i]);
41262830Sdjl }
41272830Sdjl return (NULL);
41282830Sdjl }
41292830Sdjl
41300Sstevel@tonic-gate
41310Sstevel@tonic-gate /*ARGSUSED*/
41320Sstevel@tonic-gate int
__ns_ldap_uid2dn(const char * uid,char ** userDN,const ns_cred_t * cred,ns_ldap_error_t ** errorp)41330Sstevel@tonic-gate __ns_ldap_uid2dn(const char *uid,
41340Sstevel@tonic-gate char **userDN,
41350Sstevel@tonic-gate const ns_cred_t *cred, /* cred is ignored */
41360Sstevel@tonic-gate ns_ldap_error_t **errorp)
41370Sstevel@tonic-gate {
41380Sstevel@tonic-gate ns_ldap_result_t *result = NULL;
41390Sstevel@tonic-gate char *filter, *userdata;
41400Sstevel@tonic-gate char errstr[MAXERROR];
41410Sstevel@tonic-gate char **value;
41420Sstevel@tonic-gate int rc = 0;
41430Sstevel@tonic-gate int i = 0;
41440Sstevel@tonic-gate size_t len;
41450Sstevel@tonic-gate
41460Sstevel@tonic-gate *errorp = NULL;
41470Sstevel@tonic-gate *userDN = NULL;
41480Sstevel@tonic-gate if ((uid == NULL) || (uid[0] == '\0'))
41490Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
41500Sstevel@tonic-gate
41510Sstevel@tonic-gate while (uid[i] != '\0') {
41520Sstevel@tonic-gate if (uid[i] == '=') {
41530Sstevel@tonic-gate *userDN = strdup(uid);
41540Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
41550Sstevel@tonic-gate }
41560Sstevel@tonic-gate i++;
41570Sstevel@tonic-gate }
41580Sstevel@tonic-gate i = 0;
41590Sstevel@tonic-gate while ((uid[i] != '\0') && (isdigit(uid[i])))
41600Sstevel@tonic-gate i++;
41610Sstevel@tonic-gate if (uid[i] == '\0') {
41620Sstevel@tonic-gate len = strlen(UIDNUMFILTER) + strlen(uid) + 1;
41630Sstevel@tonic-gate filter = (char *)malloc(len);
41640Sstevel@tonic-gate if (filter == NULL) {
41650Sstevel@tonic-gate *userDN = NULL;
41660Sstevel@tonic-gate return (NS_LDAP_MEMORY);
41670Sstevel@tonic-gate }
41680Sstevel@tonic-gate (void) snprintf(filter, len, UIDNUMFILTER, uid);
41690Sstevel@tonic-gate
41700Sstevel@tonic-gate len = strlen(UIDNUMFILTER_SSD) + strlen(uid) + 1;
41710Sstevel@tonic-gate userdata = (char *)malloc(len);
41720Sstevel@tonic-gate if (userdata == NULL) {
41730Sstevel@tonic-gate *userDN = NULL;
41740Sstevel@tonic-gate return (NS_LDAP_MEMORY);
41750Sstevel@tonic-gate }
41760Sstevel@tonic-gate (void) snprintf(userdata, len, UIDNUMFILTER_SSD, uid);
41770Sstevel@tonic-gate } else {
41780Sstevel@tonic-gate len = strlen(UIDFILTER) + strlen(uid) + 1;
41790Sstevel@tonic-gate filter = (char *)malloc(len);
41800Sstevel@tonic-gate if (filter == NULL) {
41810Sstevel@tonic-gate *userDN = NULL;
41820Sstevel@tonic-gate return (NS_LDAP_MEMORY);
41830Sstevel@tonic-gate }
41840Sstevel@tonic-gate (void) snprintf(filter, len, UIDFILTER, uid);
41850Sstevel@tonic-gate
41860Sstevel@tonic-gate len = strlen(UIDFILTER_SSD) + strlen(uid) + 1;
41870Sstevel@tonic-gate userdata = (char *)malloc(len);
41880Sstevel@tonic-gate if (userdata == NULL) {
41890Sstevel@tonic-gate *userDN = NULL;
41900Sstevel@tonic-gate return (NS_LDAP_MEMORY);
41910Sstevel@tonic-gate }
41920Sstevel@tonic-gate (void) snprintf(userdata, len, UIDFILTER_SSD, uid);
41930Sstevel@tonic-gate }
41940Sstevel@tonic-gate
4195699Ssdussud /*
4196699Ssdussud * we want to retrieve the DN as it appears in LDAP
4197699Ssdussud * hence the use of NS_LDAP_NOT_CVT_DN in flags
4198699Ssdussud */
41990Sstevel@tonic-gate rc = __ns_ldap_list("passwd", filter,
42004765Smj162486 __s_api_merge_SSD_filter,
42014765Smj162486 NULL, cred, NS_LDAP_NOT_CVT_DN,
42024765Smj162486 &result, errorp, NULL,
42034765Smj162486 userdata);
42040Sstevel@tonic-gate free(filter);
42050Sstevel@tonic-gate filter = NULL;
42060Sstevel@tonic-gate free(userdata);
42070Sstevel@tonic-gate userdata = NULL;
42080Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
42090Sstevel@tonic-gate if (result) {
42100Sstevel@tonic-gate (void) __ns_ldap_freeResult(&result);
42110Sstevel@tonic-gate result = NULL;
42120Sstevel@tonic-gate }
42130Sstevel@tonic-gate return (rc);
42140Sstevel@tonic-gate }
42150Sstevel@tonic-gate if (result->entries_count > 1) {
42160Sstevel@tonic-gate (void) __ns_ldap_freeResult(&result);
42170Sstevel@tonic-gate result = NULL;
42180Sstevel@tonic-gate *userDN = NULL;
42190Sstevel@tonic-gate (void) sprintf(errstr,
42204765Smj162486 gettext("Too many entries are returned for %s"), uid);
42210Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr),
42224765Smj162486 NULL);
42230Sstevel@tonic-gate return (NS_LDAP_INTERNAL);
42240Sstevel@tonic-gate }
42250Sstevel@tonic-gate
42260Sstevel@tonic-gate value = __ns_ldap_getAttr(result->entry, "dn");
42270Sstevel@tonic-gate *userDN = strdup(value[0]);
42280Sstevel@tonic-gate (void) __ns_ldap_freeResult(&result);
42290Sstevel@tonic-gate result = NULL;
42300Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
42310Sstevel@tonic-gate }
42320Sstevel@tonic-gate
42330Sstevel@tonic-gate
42340Sstevel@tonic-gate /*ARGSUSED*/
42350Sstevel@tonic-gate int
__ns_ldap_host2dn(const char * host,const char * domain,char ** hostDN,const ns_cred_t * cred,ns_ldap_error_t ** errorp)42360Sstevel@tonic-gate __ns_ldap_host2dn(const char *host,
42370Sstevel@tonic-gate const char *domain,
42380Sstevel@tonic-gate char **hostDN,
42390Sstevel@tonic-gate const ns_cred_t *cred, /* cred is ignored */
42400Sstevel@tonic-gate ns_ldap_error_t **errorp)
42410Sstevel@tonic-gate {
42420Sstevel@tonic-gate ns_ldap_result_t *result = NULL;
42430Sstevel@tonic-gate char *filter, *userdata;
42440Sstevel@tonic-gate char errstr[MAXERROR];
42450Sstevel@tonic-gate char **value;
42460Sstevel@tonic-gate int rc;
42470Sstevel@tonic-gate size_t len;
42480Sstevel@tonic-gate
42490Sstevel@tonic-gate /*
42500Sstevel@tonic-gate * XXX
42510Sstevel@tonic-gate * the domain parameter needs to be used in case domain is not local, if
42520Sstevel@tonic-gate * this routine is to support multi domain setups, it needs lots of work...
42530Sstevel@tonic-gate */
42540Sstevel@tonic-gate *errorp = NULL;
42550Sstevel@tonic-gate *hostDN = NULL;
42560Sstevel@tonic-gate if ((host == NULL) || (host[0] == '\0'))
42570Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
42580Sstevel@tonic-gate
42590Sstevel@tonic-gate len = strlen(HOSTFILTER) + strlen(host) + 1;
42600Sstevel@tonic-gate filter = (char *)malloc(len);
42610Sstevel@tonic-gate if (filter == NULL) {
42620Sstevel@tonic-gate return (NS_LDAP_MEMORY);
42630Sstevel@tonic-gate }
42640Sstevel@tonic-gate (void) snprintf(filter, len, HOSTFILTER, host);
42650Sstevel@tonic-gate
42660Sstevel@tonic-gate len = strlen(HOSTFILTER_SSD) + strlen(host) + 1;
42670Sstevel@tonic-gate userdata = (char *)malloc(len);
42680Sstevel@tonic-gate if (userdata == NULL) {
42690Sstevel@tonic-gate return (NS_LDAP_MEMORY);
42700Sstevel@tonic-gate }
42710Sstevel@tonic-gate (void) snprintf(userdata, len, HOSTFILTER_SSD, host);
42720Sstevel@tonic-gate
4273699Ssdussud /*
4274699Ssdussud * we want to retrieve the DN as it appears in LDAP
4275699Ssdussud * hence the use of NS_LDAP_NOT_CVT_DN in flags
4276699Ssdussud */
42770Sstevel@tonic-gate rc = __ns_ldap_list("hosts", filter,
42784765Smj162486 __s_api_merge_SSD_filter,
42794765Smj162486 NULL, cred, NS_LDAP_NOT_CVT_DN, &result,
42804765Smj162486 errorp, NULL,
42814765Smj162486 userdata);
42820Sstevel@tonic-gate free(filter);
42830Sstevel@tonic-gate filter = NULL;
42840Sstevel@tonic-gate free(userdata);
42850Sstevel@tonic-gate userdata = NULL;
42860Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
42870Sstevel@tonic-gate if (result) {
42880Sstevel@tonic-gate (void) __ns_ldap_freeResult(&result);
42890Sstevel@tonic-gate result = NULL;
42900Sstevel@tonic-gate }
42910Sstevel@tonic-gate return (rc);
42920Sstevel@tonic-gate }
42930Sstevel@tonic-gate
42940Sstevel@tonic-gate if (result->entries_count > 1) {
42950Sstevel@tonic-gate (void) __ns_ldap_freeResult(&result);
42960Sstevel@tonic-gate result = NULL;
42970Sstevel@tonic-gate *hostDN = NULL;
42980Sstevel@tonic-gate (void) sprintf(errstr,
42994765Smj162486 gettext("Too many entries are returned for %s"), host);
43000Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr),
43014765Smj162486 NULL);
43020Sstevel@tonic-gate return (NS_LDAP_INTERNAL);
43030Sstevel@tonic-gate }
43040Sstevel@tonic-gate
43050Sstevel@tonic-gate value = __ns_ldap_getAttr(result->entry, "dn");
43060Sstevel@tonic-gate *hostDN = strdup(value[0]);
43070Sstevel@tonic-gate (void) __ns_ldap_freeResult(&result);
43080Sstevel@tonic-gate result = NULL;
43090Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
43100Sstevel@tonic-gate }
43110Sstevel@tonic-gate
43120Sstevel@tonic-gate /*ARGSUSED*/
43130Sstevel@tonic-gate int
__ns_ldap_dn2domain(const char * dn,char ** domain,const ns_cred_t * cred,ns_ldap_error_t ** errorp)43140Sstevel@tonic-gate __ns_ldap_dn2domain(const char *dn,
43150Sstevel@tonic-gate char **domain,
43160Sstevel@tonic-gate const ns_cred_t *cred,
43170Sstevel@tonic-gate ns_ldap_error_t **errorp)
43180Sstevel@tonic-gate {
43190Sstevel@tonic-gate int rc, pnum, i, j, len = 0;
43200Sstevel@tonic-gate char *newdn, **rdns = NULL;
43210Sstevel@tonic-gate char **dns, *dn1;
43220Sstevel@tonic-gate
43230Sstevel@tonic-gate *errorp = NULL;
43240Sstevel@tonic-gate
43250Sstevel@tonic-gate if (domain == NULL)
43260Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
43270Sstevel@tonic-gate else
43280Sstevel@tonic-gate *domain = NULL;
43290Sstevel@tonic-gate
43300Sstevel@tonic-gate if ((dn == NULL) || (dn[0] == '\0'))
43310Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
43320Sstevel@tonic-gate
43330Sstevel@tonic-gate /*
43340Sstevel@tonic-gate * break dn into rdns
43350Sstevel@tonic-gate */
43360Sstevel@tonic-gate dn1 = strdup(dn);
43370Sstevel@tonic-gate if (dn1 == NULL)
43380Sstevel@tonic-gate return (NS_LDAP_MEMORY);
43390Sstevel@tonic-gate rdns = ldap_explode_dn(dn1, 0);
43400Sstevel@tonic-gate free(dn1);
43410Sstevel@tonic-gate if (rdns == NULL || *rdns == NULL)
43420Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
43430Sstevel@tonic-gate
43440Sstevel@tonic-gate for (i = 0; rdns[i]; i++)
43450Sstevel@tonic-gate len += strlen(rdns[i]) + 1;
43460Sstevel@tonic-gate pnum = i;
43470Sstevel@tonic-gate
43480Sstevel@tonic-gate newdn = (char *)malloc(len + 1);
43490Sstevel@tonic-gate dns = (char **)calloc(pnum, sizeof (char *));
43500Sstevel@tonic-gate if (newdn == NULL || dns == NULL) {
43510Sstevel@tonic-gate if (newdn)
43520Sstevel@tonic-gate free(newdn);
43530Sstevel@tonic-gate ldap_value_free(rdns);
43540Sstevel@tonic-gate return (NS_LDAP_MEMORY);
43550Sstevel@tonic-gate }
43560Sstevel@tonic-gate
43570Sstevel@tonic-gate /* construct a semi-normalized dn, newdn */
43580Sstevel@tonic-gate *newdn = '\0';
43590Sstevel@tonic-gate for (i = 0; rdns[i]; i++) {
43600Sstevel@tonic-gate dns[i] = newdn + strlen(newdn);
43610Sstevel@tonic-gate (void) strcat(newdn,
43624765Smj162486 __s_api_remove_rdn_space(rdns[i]));
43630Sstevel@tonic-gate (void) strcat(newdn, ",");
43640Sstevel@tonic-gate }
43650Sstevel@tonic-gate /* remove the last ',' */
43660Sstevel@tonic-gate newdn[strlen(newdn) - 1] = '\0';
43670Sstevel@tonic-gate ldap_value_free(rdns);
43680Sstevel@tonic-gate
43690Sstevel@tonic-gate /*
43700Sstevel@tonic-gate * loop and find the domain name associated with newdn,
43710Sstevel@tonic-gate * removing rdn one by one from left to right
43720Sstevel@tonic-gate */
43730Sstevel@tonic-gate for (i = 0; i < pnum; i++) {
43740Sstevel@tonic-gate
43750Sstevel@tonic-gate if (*errorp)
43760Sstevel@tonic-gate (void) __ns_ldap_freeError(errorp);
43770Sstevel@tonic-gate
43780Sstevel@tonic-gate /*
43790Sstevel@tonic-gate * try cache manager first
43800Sstevel@tonic-gate */
43810Sstevel@tonic-gate rc = __s_api_get_cachemgr_data(NS_CACHE_DN2DOMAIN,
43824765Smj162486 dns[i], domain);
43830Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) {
43840Sstevel@tonic-gate /*
43850Sstevel@tonic-gate * try ldap server second
43860Sstevel@tonic-gate */
43870Sstevel@tonic-gate rc = __s_api_find_domainname(dns[i], domain,
43884765Smj162486 cred, errorp);
43890Sstevel@tonic-gate } else {
43900Sstevel@tonic-gate /*
43910Sstevel@tonic-gate * skip the last one,
43920Sstevel@tonic-gate * since it is already cached by ldap_cachemgr
43930Sstevel@tonic-gate */
43940Sstevel@tonic-gate i--;
43950Sstevel@tonic-gate }
43960Sstevel@tonic-gate if (rc == NS_LDAP_SUCCESS) {
43975399Schinlong if (__s_api_nscd_proc()) {
43985399Schinlong /*
43995399Schinlong * If it's nscd, ask cache manager to save the
44005399Schinlong * dn to domain mapping(s)
44015399Schinlong */
44025399Schinlong for (j = 0; j <= i; j++) {
44035399Schinlong (void) __s_api_set_cachemgr_data(
44045399Schinlong NS_CACHE_DN2DOMAIN,
44055399Schinlong dns[j],
44065399Schinlong *domain);
44075399Schinlong }
44080Sstevel@tonic-gate }
44090Sstevel@tonic-gate break;
44100Sstevel@tonic-gate }
44110Sstevel@tonic-gate }
44120Sstevel@tonic-gate
44130Sstevel@tonic-gate free(dns);
44140Sstevel@tonic-gate free(newdn);
44150Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS)
44160Sstevel@tonic-gate rc = NS_LDAP_NOTFOUND;
44170Sstevel@tonic-gate return (rc);
44180Sstevel@tonic-gate }
44190Sstevel@tonic-gate
44200Sstevel@tonic-gate /*ARGSUSED*/
44210Sstevel@tonic-gate int
__ns_ldap_getServiceAuthMethods(const char * service,ns_auth_t *** auth,ns_ldap_error_t ** errorp)44220Sstevel@tonic-gate __ns_ldap_getServiceAuthMethods(const char *service,
44230Sstevel@tonic-gate ns_auth_t ***auth,
44240Sstevel@tonic-gate ns_ldap_error_t **errorp)
44250Sstevel@tonic-gate {
44260Sstevel@tonic-gate char errstr[MAXERROR];
44270Sstevel@tonic-gate int rc, i, done = 0;
44280Sstevel@tonic-gate int slen;
44290Sstevel@tonic-gate void **param;
44300Sstevel@tonic-gate char **sam, *srv, *send;
44310Sstevel@tonic-gate ns_auth_t **authpp = NULL, *ap;
44320Sstevel@tonic-gate int cnt, max;
44330Sstevel@tonic-gate ns_config_t *cfg;
44340Sstevel@tonic-gate ns_ldap_error_t *error = NULL;
44350Sstevel@tonic-gate
44360Sstevel@tonic-gate if (errorp == NULL)
44370Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
44380Sstevel@tonic-gate *errorp = NULL;
44390Sstevel@tonic-gate
44400Sstevel@tonic-gate if ((service == NULL) || (service[0] == '\0') ||
44414765Smj162486 (auth == NULL))
44420Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
44430Sstevel@tonic-gate
44440Sstevel@tonic-gate *auth = NULL;
44450Sstevel@tonic-gate rc = __ns_ldap_getParam(NS_LDAP_SERVICE_AUTH_METHOD_P, ¶m, &error);
44460Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS || param == NULL) {
44470Sstevel@tonic-gate *errorp = error;
44480Sstevel@tonic-gate return (rc);
44490Sstevel@tonic-gate }
44500Sstevel@tonic-gate sam = (char **)param;
44510Sstevel@tonic-gate
44520Sstevel@tonic-gate cfg = __s_api_get_default_config();
44530Sstevel@tonic-gate cnt = 0;
44540Sstevel@tonic-gate
44550Sstevel@tonic-gate slen = strlen(service);
44560Sstevel@tonic-gate
44570Sstevel@tonic-gate for (; *sam; sam++) {
44580Sstevel@tonic-gate srv = *sam;
44590Sstevel@tonic-gate if (strncasecmp(service, srv, slen) != 0)
44600Sstevel@tonic-gate continue;
44610Sstevel@tonic-gate srv += slen;
44620Sstevel@tonic-gate if (*srv != COLONTOK)
44630Sstevel@tonic-gate continue;
44640Sstevel@tonic-gate send = srv;
44650Sstevel@tonic-gate srv++;
44660Sstevel@tonic-gate for (max = 1; (send = strchr(++send, SEMITOK)) != NULL;
44674765Smj162486 max++) {}
44680Sstevel@tonic-gate authpp = (ns_auth_t **)calloc(++max, sizeof (ns_auth_t *));
44690Sstevel@tonic-gate if (authpp == NULL) {
44700Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶m);
44710Sstevel@tonic-gate __s_api_release_config(cfg);
44720Sstevel@tonic-gate return (NS_LDAP_MEMORY);
44730Sstevel@tonic-gate }
44740Sstevel@tonic-gate while (!done) {
44750Sstevel@tonic-gate send = strchr(srv, SEMITOK);
44760Sstevel@tonic-gate if (send != NULL) {
44770Sstevel@tonic-gate *send = '\0';
44780Sstevel@tonic-gate send++;
44790Sstevel@tonic-gate }
44800Sstevel@tonic-gate i = __s_get_enum_value(cfg, srv, NS_LDAP_AUTH_P);
44810Sstevel@tonic-gate if (i == -1) {
44820Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶m);
44830Sstevel@tonic-gate (void) sprintf(errstr,
44844765Smj162486 gettext("Unsupported "
44854765Smj162486 "serviceAuthenticationMethod: %s.\n"), srv);
44860Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, NS_CONFIG_SYNTAX,
44874765Smj162486 strdup(errstr), NULL);
44880Sstevel@tonic-gate __s_api_release_config(cfg);
44890Sstevel@tonic-gate return (NS_LDAP_CONFIG);
44900Sstevel@tonic-gate }
44910Sstevel@tonic-gate ap = __s_api_AuthEnumtoStruct((EnumAuthType_t)i);
44920Sstevel@tonic-gate if (ap == NULL) {
44930Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶m);
44940Sstevel@tonic-gate __s_api_release_config(cfg);
44950Sstevel@tonic-gate return (NS_LDAP_MEMORY);
44960Sstevel@tonic-gate }
44970Sstevel@tonic-gate authpp[cnt++] = ap;
44980Sstevel@tonic-gate if (send == NULL)
44990Sstevel@tonic-gate done = TRUE;
45000Sstevel@tonic-gate else
45010Sstevel@tonic-gate srv = send;
45020Sstevel@tonic-gate }
45030Sstevel@tonic-gate }
45040Sstevel@tonic-gate
45050Sstevel@tonic-gate *auth = authpp;
45060Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶m);
45070Sstevel@tonic-gate __s_api_release_config(cfg);
45080Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
45090Sstevel@tonic-gate }
45100Sstevel@tonic-gate
45110Sstevel@tonic-gate /*
45120Sstevel@tonic-gate * This routine is called when certain scenario occurs
45130Sstevel@tonic-gate * e.g.
45140Sstevel@tonic-gate * service == auto_home
45150Sstevel@tonic-gate * SSD = automount: ou = mytest,
45160Sstevel@tonic-gate * NS_LDAP_MAPATTRIBUTE= auto_home: automountMapName=AAA
45170Sstevel@tonic-gate * NS_LDAP_OBJECTCLASSMAP= auto_home:automountMap=MynisMap
45180Sstevel@tonic-gate * NS_LDAP_OBJECTCLASSMAP= auto_home:automount=MynisObject
45190Sstevel@tonic-gate *
45200Sstevel@tonic-gate * The automountMapName is prepended implicitely but is mapped
45210Sstevel@tonic-gate * to AAA. So dn could appers as
45220Sstevel@tonic-gate * dn: AAA=auto_home,ou=bar,dc=foo,dc=com
45230Sstevel@tonic-gate * dn: automountKey=user_01,AAA=auto_home,ou=bar,dc=foo,dc=com
45240Sstevel@tonic-gate * dn: automountKey=user_02,AAA=auto_home,ou=bar,dc=foo,dc=com
45250Sstevel@tonic-gate * in the directory.
45260Sstevel@tonic-gate * This function is called to covert the mapped attr back to
45270Sstevel@tonic-gate * orig attr when the entries are searched and returned
45280Sstevel@tonic-gate */
45290Sstevel@tonic-gate
45300Sstevel@tonic-gate int
__s_api_convert_automountmapname(const char * service,char ** dn,ns_ldap_error_t ** errp)45310Sstevel@tonic-gate __s_api_convert_automountmapname(const char *service, char **dn,
45320Sstevel@tonic-gate ns_ldap_error_t **errp) {
45330Sstevel@tonic-gate
45340Sstevel@tonic-gate char **mapping = NULL;
45350Sstevel@tonic-gate char *mapped_attr = NULL;
45360Sstevel@tonic-gate char *automountmapname = "automountMapName";
45370Sstevel@tonic-gate char *buffer = NULL;
45380Sstevel@tonic-gate int rc = NS_LDAP_SUCCESS;
45390Sstevel@tonic-gate char errstr[MAXERROR];
45400Sstevel@tonic-gate
45410Sstevel@tonic-gate /*
45420Sstevel@tonic-gate * dn is an input/out parameter, check it first
45430Sstevel@tonic-gate */
45440Sstevel@tonic-gate
45450Sstevel@tonic-gate if (service == NULL || dn == NULL || *dn == NULL)
45460Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM);
45470Sstevel@tonic-gate
45480Sstevel@tonic-gate /*
45490Sstevel@tonic-gate * Check to see if there is a mapped attribute for auto_xxx
45500Sstevel@tonic-gate */
45510Sstevel@tonic-gate
45520Sstevel@tonic-gate mapping = __ns_ldap_getMappedAttributes(service, automountmapname);
45530Sstevel@tonic-gate
45540Sstevel@tonic-gate /*
45550Sstevel@tonic-gate * if no mapped attribute for auto_xxx, try automount
45560Sstevel@tonic-gate */
45570Sstevel@tonic-gate
45580Sstevel@tonic-gate if (mapping == NULL)
45590Sstevel@tonic-gate mapping = __ns_ldap_getMappedAttributes(
45600Sstevel@tonic-gate "automount", automountmapname);
45610Sstevel@tonic-gate
45620Sstevel@tonic-gate /*
45630Sstevel@tonic-gate * if no mapped attribute is found, return SUCCESS (no op)
45640Sstevel@tonic-gate */
45650Sstevel@tonic-gate
45660Sstevel@tonic-gate if (mapping == NULL)
45670Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
45680Sstevel@tonic-gate
45690Sstevel@tonic-gate /*
45700Sstevel@tonic-gate * if the mapped attribute is found and attr is not empty,
45710Sstevel@tonic-gate * copy it
45720Sstevel@tonic-gate */
45730Sstevel@tonic-gate
45740Sstevel@tonic-gate if (mapping[0] != NULL) {
45750Sstevel@tonic-gate mapped_attr = strdup(mapping[0]);
45760Sstevel@tonic-gate __s_api_free2dArray(mapping);
45770Sstevel@tonic-gate if (mapped_attr == NULL) {
45780Sstevel@tonic-gate return (NS_LDAP_MEMORY);
45790Sstevel@tonic-gate }
45800Sstevel@tonic-gate } else {
45810Sstevel@tonic-gate __s_api_free2dArray(mapping);
45820Sstevel@tonic-gate
45830Sstevel@tonic-gate (void) snprintf(errstr, (2 * MAXERROR),
45840Sstevel@tonic-gate gettext(
45850Sstevel@tonic-gate "Attribute nisMapName is mapped to an "
45860Sstevel@tonic-gate "empty string.\n"));
45870Sstevel@tonic-gate
45880Sstevel@tonic-gate MKERROR(LOG_ERR, *errp, NS_CONFIG_SYNTAX,
45890Sstevel@tonic-gate strdup(errstr), NULL);
45900Sstevel@tonic-gate
45910Sstevel@tonic-gate return (NS_LDAP_CONFIG);
45920Sstevel@tonic-gate }
45930Sstevel@tonic-gate
45940Sstevel@tonic-gate /*
45950Sstevel@tonic-gate * Locate the mapped attribute in the dn
45960Sstevel@tonic-gate * and replace it if it exists
45970Sstevel@tonic-gate */
45980Sstevel@tonic-gate
45990Sstevel@tonic-gate rc = __s_api_replace_mapped_attr_in_dn(
46000Sstevel@tonic-gate (const char *) automountmapname, (const char *) mapped_attr,
46010Sstevel@tonic-gate (const char *) *dn, &buffer);
46020Sstevel@tonic-gate
46030Sstevel@tonic-gate /* clean up */
46040Sstevel@tonic-gate
46050Sstevel@tonic-gate free(mapped_attr);
46060Sstevel@tonic-gate
46070Sstevel@tonic-gate /*
46080Sstevel@tonic-gate * If mapped attr is found(buffer != NULL)
46090Sstevel@tonic-gate * a new dn is returned
46100Sstevel@tonic-gate * If no mapped attribute is in dn,
46110Sstevel@tonic-gate * return NS_LDAP_SUCCESS (no op)
46120Sstevel@tonic-gate * If no memory,
46130Sstevel@tonic-gate * return NS_LDAP_MEMORY (no op)
46140Sstevel@tonic-gate */
46150Sstevel@tonic-gate
46160Sstevel@tonic-gate if (buffer != NULL) {
46170Sstevel@tonic-gate free(*dn);
46180Sstevel@tonic-gate *dn = buffer;
46190Sstevel@tonic-gate }
46200Sstevel@tonic-gate
46210Sstevel@tonic-gate return (rc);
46220Sstevel@tonic-gate }
46230Sstevel@tonic-gate
46240Sstevel@tonic-gate /*
46250Sstevel@tonic-gate * If the mapped attr is found in the dn,
46260Sstevel@tonic-gate * return NS_LDAP_SUCCESS and a new_dn.
46270Sstevel@tonic-gate * If no mapped attr is found,
46280Sstevel@tonic-gate * return NS_LDAP_SUCCESS and *new_dn == NULL
46290Sstevel@tonic-gate * If there is not enough memory,
46300Sstevel@tonic-gate * return NS_LDAP_MEMORY and *new_dn == NULL
46310Sstevel@tonic-gate */
46320Sstevel@tonic-gate
46330Sstevel@tonic-gate int
__s_api_replace_mapped_attr_in_dn(const char * orig_attr,const char * mapped_attr,const char * dn,char ** new_dn)46340Sstevel@tonic-gate __s_api_replace_mapped_attr_in_dn(
46350Sstevel@tonic-gate const char *orig_attr, const char *mapped_attr,
46360Sstevel@tonic-gate const char *dn, char **new_dn) {
46370Sstevel@tonic-gate
46380Sstevel@tonic-gate char **dnArray = NULL;
46390Sstevel@tonic-gate char *cur = NULL, *start = NULL;
46400Sstevel@tonic-gate int i = 0, found = 0;
46410Sstevel@tonic-gate int len = 0, orig_len = 0, mapped_len = 0;
46420Sstevel@tonic-gate int dn_len = 0, tmp_len = 0;
46430Sstevel@tonic-gate
46440Sstevel@tonic-gate *new_dn = NULL;
46450Sstevel@tonic-gate
46460Sstevel@tonic-gate /*
46470Sstevel@tonic-gate * seperate dn into individual componets
46480Sstevel@tonic-gate * e.g.
46490Sstevel@tonic-gate * "automountKey=user_01" , "automountMapName_test=auto_home", ...
46500Sstevel@tonic-gate */
46510Sstevel@tonic-gate dnArray = ldap_explode_dn(dn, 0);
46520Sstevel@tonic-gate
46530Sstevel@tonic-gate /*
46540Sstevel@tonic-gate * This will find "mapped attr=value" in dn.
46550Sstevel@tonic-gate * It won't find match if mapped attr appears
46560Sstevel@tonic-gate * in the value.
46570Sstevel@tonic-gate */
46580Sstevel@tonic-gate for (i = 0; dnArray[i] != NULL; i++) {
46590Sstevel@tonic-gate /*
46600Sstevel@tonic-gate * This function is called when reading from
46610Sstevel@tonic-gate * the directory so assume each component has "=".
46620Sstevel@tonic-gate * Any ill formatted dn should be rejected
46630Sstevel@tonic-gate * before adding to the directory
46640Sstevel@tonic-gate */
46650Sstevel@tonic-gate cur = strchr(dnArray[i], '=');
46660Sstevel@tonic-gate *cur = '\0';
46670Sstevel@tonic-gate if (strcasecmp(mapped_attr, dnArray[i]) == 0)
46680Sstevel@tonic-gate found = 1;
46690Sstevel@tonic-gate *cur = '=';
46700Sstevel@tonic-gate if (found) break;
46710Sstevel@tonic-gate }
46720Sstevel@tonic-gate
46730Sstevel@tonic-gate if (!found) {
46740Sstevel@tonic-gate __s_api_free2dArray(dnArray);
46750Sstevel@tonic-gate *new_dn = NULL;
46760Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
46770Sstevel@tonic-gate }
46780Sstevel@tonic-gate /*
46790Sstevel@tonic-gate * The new length is *dn length + (difference between
46800Sstevel@tonic-gate * orig attr and mapped attr) + 1 ;
46810Sstevel@tonic-gate * e.g.
46820Sstevel@tonic-gate * automountKey=aa,automountMapName_test=auto_home,dc=foo,dc=com
46830Sstevel@tonic-gate * ==>
46840Sstevel@tonic-gate * automountKey=aa,automountMapName=auto_home,dc=foo,dc=com
46850Sstevel@tonic-gate */
46860Sstevel@tonic-gate mapped_len = strlen(mapped_attr);
46870Sstevel@tonic-gate orig_len = strlen(orig_attr);
46880Sstevel@tonic-gate dn_len = strlen(dn);
46890Sstevel@tonic-gate len = dn_len + orig_len - mapped_len + 1;
46900Sstevel@tonic-gate *new_dn = (char *)calloc(1, len);
46910Sstevel@tonic-gate if (*new_dn == NULL) {
46920Sstevel@tonic-gate __s_api_free2dArray(dnArray);
46930Sstevel@tonic-gate return (NS_LDAP_MEMORY);
46940Sstevel@tonic-gate }
46950Sstevel@tonic-gate
46960Sstevel@tonic-gate /*
46970Sstevel@tonic-gate * Locate the mapped attr in the dn.
46980Sstevel@tonic-gate * Use dnArray[i] instead of mapped_attr
46990Sstevel@tonic-gate * because mapped_attr could appear in
47000Sstevel@tonic-gate * the value
47010Sstevel@tonic-gate */
47020Sstevel@tonic-gate
47030Sstevel@tonic-gate cur = strstr(dn, dnArray[i]);
47040Sstevel@tonic-gate __s_api_free2dArray(dnArray);
47050Sstevel@tonic-gate /* copy the portion before mapped attr in dn */
47060Sstevel@tonic-gate start = *new_dn;
47070Sstevel@tonic-gate tmp_len = cur - dn;
47080Sstevel@tonic-gate (void) memcpy((void *) start, (const void*) dn, tmp_len);
47090Sstevel@tonic-gate
47100Sstevel@tonic-gate /*
47110Sstevel@tonic-gate * Copy the orig_attr. e.g. automountMapName
47120Sstevel@tonic-gate * This replaces mapped attr with orig attr
47130Sstevel@tonic-gate */
47140Sstevel@tonic-gate start = start + (cur - dn); /* move cursor in buffer */
47150Sstevel@tonic-gate (void) memcpy((void *) start, (const void*) orig_attr, orig_len);
47160Sstevel@tonic-gate
47170Sstevel@tonic-gate /*
47180Sstevel@tonic-gate * Copy the portion after mapped attr in dn
47190Sstevel@tonic-gate */
47200Sstevel@tonic-gate cur = cur + mapped_len; /* move cursor in dn */
47210Sstevel@tonic-gate start = start + orig_len; /* move cursor in buffer */
47220Sstevel@tonic-gate (void) strcpy(start, cur);
47230Sstevel@tonic-gate
47240Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
47250Sstevel@tonic-gate }
47260Sstevel@tonic-gate
47270Sstevel@tonic-gate /*
47280Sstevel@tonic-gate * Validate Filter functions
47290Sstevel@tonic-gate */
47300Sstevel@tonic-gate
47310Sstevel@tonic-gate /* ***** Start of modified libldap.so.5 filter parser ***** */
47320Sstevel@tonic-gate
47330Sstevel@tonic-gate /* filter parsing routine forward references */
47340Sstevel@tonic-gate static int adj_filter_list(char *str);
47350Sstevel@tonic-gate static int adj_simple_filter(char *str);
47360Sstevel@tonic-gate static int unescape_filterval(char *val);
47370Sstevel@tonic-gate static int hexchar2int(char c);
47380Sstevel@tonic-gate static int adj_substring_filter(char *val);
47390Sstevel@tonic-gate
47400Sstevel@tonic-gate
47410Sstevel@tonic-gate /*
47420Sstevel@tonic-gate * assumes string manipulation is in-line
47430Sstevel@tonic-gate * and all strings are sufficient in size
47440Sstevel@tonic-gate * return value is the position after 'c'
47450Sstevel@tonic-gate */
47460Sstevel@tonic-gate
47470Sstevel@tonic-gate static char *
resync_str(char * str,char * next,char c)47480Sstevel@tonic-gate resync_str(char *str, char *next, char c)
47490Sstevel@tonic-gate {
47500Sstevel@tonic-gate char *ret;
47510Sstevel@tonic-gate
47520Sstevel@tonic-gate ret = str + strlen(str);
47530Sstevel@tonic-gate *next = c;
47540Sstevel@tonic-gate if (ret == next)
47550Sstevel@tonic-gate return (ret);
47560Sstevel@tonic-gate (void) strcat(str, next);
47570Sstevel@tonic-gate return (ret);
47580Sstevel@tonic-gate }
47590Sstevel@tonic-gate
47600Sstevel@tonic-gate static char *
find_right_paren(char * s)47610Sstevel@tonic-gate find_right_paren(char *s)
47620Sstevel@tonic-gate {
47630Sstevel@tonic-gate int balance, escape;
47640Sstevel@tonic-gate
47650Sstevel@tonic-gate balance = 1;
47660Sstevel@tonic-gate escape = 0;
47670Sstevel@tonic-gate while (*s && balance) {
47680Sstevel@tonic-gate if (escape == 0) {
47690Sstevel@tonic-gate if (*s == '(')
47700Sstevel@tonic-gate balance++;
47710Sstevel@tonic-gate else if (*s == ')')
47720Sstevel@tonic-gate balance--;
47730Sstevel@tonic-gate }
47740Sstevel@tonic-gate if (*s == '\\' && ! escape)
47750Sstevel@tonic-gate escape = 1;
47760Sstevel@tonic-gate else
47770Sstevel@tonic-gate escape = 0;
47780Sstevel@tonic-gate if (balance)
47790Sstevel@tonic-gate s++;
47800Sstevel@tonic-gate }
47810Sstevel@tonic-gate
47820Sstevel@tonic-gate return (*s ? s : NULL);
47830Sstevel@tonic-gate }
47840Sstevel@tonic-gate
47850Sstevel@tonic-gate static char *
adj_complex_filter(char * str)47860Sstevel@tonic-gate adj_complex_filter(char *str)
47870Sstevel@tonic-gate {
47880Sstevel@tonic-gate char *next;
47890Sstevel@tonic-gate
47900Sstevel@tonic-gate /*
47910Sstevel@tonic-gate * We have (x(filter)...) with str sitting on
47920Sstevel@tonic-gate * the x. We have to find the paren matching
47930Sstevel@tonic-gate * the one before the x and put the intervening
47940Sstevel@tonic-gate * filters by calling adj_filter_list().
47950Sstevel@tonic-gate */
47960Sstevel@tonic-gate
47970Sstevel@tonic-gate str++;
47980Sstevel@tonic-gate if ((next = find_right_paren(str)) == NULL)
47990Sstevel@tonic-gate return (NULL);
48000Sstevel@tonic-gate
48010Sstevel@tonic-gate *next = '\0';
48020Sstevel@tonic-gate if (adj_filter_list(str) == -1)
48030Sstevel@tonic-gate return (NULL);
48040Sstevel@tonic-gate next = resync_str(str, next, ')');
48050Sstevel@tonic-gate next++;
48060Sstevel@tonic-gate
48070Sstevel@tonic-gate return (next);
48080Sstevel@tonic-gate }
48090Sstevel@tonic-gate
48100Sstevel@tonic-gate static int
adj_filter(char * str)48110Sstevel@tonic-gate adj_filter(char *str)
48120Sstevel@tonic-gate {
48130Sstevel@tonic-gate char *next;
48140Sstevel@tonic-gate int parens, balance, escape;
48150Sstevel@tonic-gate char *np, *cp, *dp;
48160Sstevel@tonic-gate
48170Sstevel@tonic-gate parens = 0;
48180Sstevel@tonic-gate while (*str) {
48190Sstevel@tonic-gate switch (*str) {
48200Sstevel@tonic-gate case '(':
48210Sstevel@tonic-gate str++;
48220Sstevel@tonic-gate parens++;
48230Sstevel@tonic-gate switch (*str) {
48240Sstevel@tonic-gate case '&':
48250Sstevel@tonic-gate if ((str = adj_complex_filter(str)) == NULL)
48260Sstevel@tonic-gate return (-1);
48270Sstevel@tonic-gate
48280Sstevel@tonic-gate parens--;
48290Sstevel@tonic-gate break;
48300Sstevel@tonic-gate
48310Sstevel@tonic-gate case '|':
48320Sstevel@tonic-gate if ((str = adj_complex_filter(str)) == NULL)
48330Sstevel@tonic-gate return (-1);
48340Sstevel@tonic-gate
48350Sstevel@tonic-gate parens--;
48360Sstevel@tonic-gate break;
48370Sstevel@tonic-gate
48380Sstevel@tonic-gate case '!':
48390Sstevel@tonic-gate if ((str = adj_complex_filter(str)) == NULL)
48400Sstevel@tonic-gate return (-1);
48410Sstevel@tonic-gate
48420Sstevel@tonic-gate parens--;
48430Sstevel@tonic-gate break;
48440Sstevel@tonic-gate
48450Sstevel@tonic-gate case '(':
48460Sstevel@tonic-gate /* illegal ((case - generated by conversion */
48470Sstevel@tonic-gate
48480Sstevel@tonic-gate /* find missing close) */
48490Sstevel@tonic-gate np = find_right_paren(str+1);
48500Sstevel@tonic-gate
48510Sstevel@tonic-gate /* error if not found */
48520Sstevel@tonic-gate if (np == NULL)
48530Sstevel@tonic-gate return (-1);
48540Sstevel@tonic-gate
48550Sstevel@tonic-gate /* remove redundant (and) */
48560Sstevel@tonic-gate for (dp = str, cp = str+1; cp < np; ) {
48570Sstevel@tonic-gate *dp++ = *cp++;
48580Sstevel@tonic-gate }
48590Sstevel@tonic-gate cp++;
48600Sstevel@tonic-gate while (*cp)
48610Sstevel@tonic-gate *dp++ = *cp++;
48620Sstevel@tonic-gate *dp = '\0';
48630Sstevel@tonic-gate
48640Sstevel@tonic-gate /* re-start test at original ( */
48650Sstevel@tonic-gate parens--;
48660Sstevel@tonic-gate str--;
48670Sstevel@tonic-gate break;
48680Sstevel@tonic-gate
48690Sstevel@tonic-gate default:
48700Sstevel@tonic-gate balance = 1;
48710Sstevel@tonic-gate escape = 0;
48720Sstevel@tonic-gate next = str;
48730Sstevel@tonic-gate while (*next && balance) {
48740Sstevel@tonic-gate if (escape == 0) {
48750Sstevel@tonic-gate if (*next == '(')
48760Sstevel@tonic-gate balance++;
48770Sstevel@tonic-gate else if (*next == ')')
48780Sstevel@tonic-gate balance--;
48790Sstevel@tonic-gate }
48800Sstevel@tonic-gate if (*next == '\\' && ! escape)
48810Sstevel@tonic-gate escape = 1;
48820Sstevel@tonic-gate else
48830Sstevel@tonic-gate escape = 0;
48840Sstevel@tonic-gate if (balance)
48850Sstevel@tonic-gate next++;
48860Sstevel@tonic-gate }
48870Sstevel@tonic-gate if (balance != 0)
48880Sstevel@tonic-gate return (-1);
48890Sstevel@tonic-gate
48900Sstevel@tonic-gate *next = '\0';
48910Sstevel@tonic-gate if (adj_simple_filter(str) == -1) {
48920Sstevel@tonic-gate return (-1);
48930Sstevel@tonic-gate }
48940Sstevel@tonic-gate next = resync_str(str, next, ')');
48950Sstevel@tonic-gate next++;
48960Sstevel@tonic-gate str = next;
48970Sstevel@tonic-gate parens--;
48980Sstevel@tonic-gate break;
48990Sstevel@tonic-gate }
49000Sstevel@tonic-gate break;
49010Sstevel@tonic-gate
49020Sstevel@tonic-gate case ')':
49030Sstevel@tonic-gate str++;
49040Sstevel@tonic-gate parens--;
49050Sstevel@tonic-gate break;
49060Sstevel@tonic-gate
49070Sstevel@tonic-gate case ' ':
49080Sstevel@tonic-gate str++;
49090Sstevel@tonic-gate break;
49100Sstevel@tonic-gate
49110Sstevel@tonic-gate default: /* assume it's a simple type=value filter */
49120Sstevel@tonic-gate next = strchr(str, '\0');
49130Sstevel@tonic-gate if (adj_simple_filter(str) == -1) {
49140Sstevel@tonic-gate return (-1);
49150Sstevel@tonic-gate }
49160Sstevel@tonic-gate str = next;
49170Sstevel@tonic-gate break;
49180Sstevel@tonic-gate }
49190Sstevel@tonic-gate }
49200Sstevel@tonic-gate
49210Sstevel@tonic-gate return (parens ? -1 : 0);
49220Sstevel@tonic-gate }
49230Sstevel@tonic-gate
49240Sstevel@tonic-gate
49250Sstevel@tonic-gate /*
49260Sstevel@tonic-gate * Put a list of filters like this "(filter1)(filter2)..."
49270Sstevel@tonic-gate */
49280Sstevel@tonic-gate
49290Sstevel@tonic-gate static int
adj_filter_list(char * str)49300Sstevel@tonic-gate adj_filter_list(char *str)
49310Sstevel@tonic-gate {
49320Sstevel@tonic-gate char *next;
49330Sstevel@tonic-gate char save;
49340Sstevel@tonic-gate
49350Sstevel@tonic-gate while (*str) {
49360Sstevel@tonic-gate while (*str && isspace(*str))
49370Sstevel@tonic-gate str++;
49380Sstevel@tonic-gate if (*str == '\0')
49390Sstevel@tonic-gate break;
49400Sstevel@tonic-gate
49410Sstevel@tonic-gate if ((next = find_right_paren(str + 1)) == NULL)
49420Sstevel@tonic-gate return (-1);
49430Sstevel@tonic-gate save = *++next;
49440Sstevel@tonic-gate
49450Sstevel@tonic-gate /* now we have "(filter)" with str pointing to it */
49460Sstevel@tonic-gate *next = '\0';
49470Sstevel@tonic-gate if (adj_filter(str) == -1)
49480Sstevel@tonic-gate return (-1);
49490Sstevel@tonic-gate next = resync_str(str, next, save);
49500Sstevel@tonic-gate
49510Sstevel@tonic-gate str = next;
49520Sstevel@tonic-gate }
49530Sstevel@tonic-gate
49540Sstevel@tonic-gate return (0);
49550Sstevel@tonic-gate }
49560Sstevel@tonic-gate
49570Sstevel@tonic-gate
49580Sstevel@tonic-gate /*
49590Sstevel@tonic-gate * is_valid_attr - returns 1 if a is a syntactically valid left-hand side
49600Sstevel@tonic-gate * of a filter expression, 0 otherwise. A valid string may contain only
49610Sstevel@tonic-gate * letters, numbers, hyphens, semi-colons, colons and periods. examples:
49620Sstevel@tonic-gate * cn
49630Sstevel@tonic-gate * cn;lang-fr
49640Sstevel@tonic-gate * 1.2.3.4;binary;dynamic
49650Sstevel@tonic-gate * mail;dynamic
49660Sstevel@tonic-gate * cn:dn:1.2.3.4
49670Sstevel@tonic-gate *
49680Sstevel@tonic-gate * For compatibility with older servers, we also allow underscores in
49690Sstevel@tonic-gate * attribute types, even through they are not allowed by the LDAPv3 RFCs.
49700Sstevel@tonic-gate */
49710Sstevel@tonic-gate static int
is_valid_attr(char * a)49720Sstevel@tonic-gate is_valid_attr(char *a)
49730Sstevel@tonic-gate {
49740Sstevel@tonic-gate for (; *a; a++) {
49750Sstevel@tonic-gate if (!isascii(*a)) {
49760Sstevel@tonic-gate return (0);
49770Sstevel@tonic-gate } else if (!isalnum(*a)) {
49780Sstevel@tonic-gate switch (*a) {
49790Sstevel@tonic-gate case '-':
49800Sstevel@tonic-gate case '.':
49810Sstevel@tonic-gate case ';':
49820Sstevel@tonic-gate case ':':
49830Sstevel@tonic-gate case '_':
49840Sstevel@tonic-gate break; /* valid */
49850Sstevel@tonic-gate default:
49860Sstevel@tonic-gate return (0);
49870Sstevel@tonic-gate }
49880Sstevel@tonic-gate }
49890Sstevel@tonic-gate }
49900Sstevel@tonic-gate return (1);
49910Sstevel@tonic-gate }
49920Sstevel@tonic-gate
49930Sstevel@tonic-gate static char *
find_star(char * s)49940Sstevel@tonic-gate find_star(char *s)
49950Sstevel@tonic-gate {
49960Sstevel@tonic-gate for (; *s; ++s) {
49970Sstevel@tonic-gate switch (*s) {
49980Sstevel@tonic-gate case '*':
49990Sstevel@tonic-gate return (s);
50000Sstevel@tonic-gate case '\\':
50010Sstevel@tonic-gate ++s;
50020Sstevel@tonic-gate if (hexchar2int(s[0]) >= 0 && hexchar2int(s[1]) >= 0)
50030Sstevel@tonic-gate ++s;
50040Sstevel@tonic-gate default:
50050Sstevel@tonic-gate break;
50060Sstevel@tonic-gate }
50070Sstevel@tonic-gate }
50080Sstevel@tonic-gate return (NULL);
50090Sstevel@tonic-gate }
50100Sstevel@tonic-gate
50110Sstevel@tonic-gate static int
adj_simple_filter(char * str)50120Sstevel@tonic-gate adj_simple_filter(char *str)
50130Sstevel@tonic-gate {
50140Sstevel@tonic-gate char *s, *s2, *s3, filterop;
50150Sstevel@tonic-gate char *value;
50160Sstevel@tonic-gate int ftype = 0;
50170Sstevel@tonic-gate int rc;
50180Sstevel@tonic-gate
50190Sstevel@tonic-gate rc = -1; /* pessimistic */
50200Sstevel@tonic-gate
50210Sstevel@tonic-gate if ((str = strdup(str)) == NULL) {
50220Sstevel@tonic-gate return (rc);
50230Sstevel@tonic-gate }
50240Sstevel@tonic-gate
50250Sstevel@tonic-gate if ((s = strchr(str, '=')) == NULL) {
50260Sstevel@tonic-gate goto free_and_return;
50270Sstevel@tonic-gate }
50280Sstevel@tonic-gate value = s + 1;
50290Sstevel@tonic-gate *s-- = '\0';
50300Sstevel@tonic-gate filterop = *s;
50310Sstevel@tonic-gate if (filterop == '<' || filterop == '>' || filterop == '~' ||
50320Sstevel@tonic-gate filterop == ':') {
50330Sstevel@tonic-gate *s = '\0';
50340Sstevel@tonic-gate }
50350Sstevel@tonic-gate
50360Sstevel@tonic-gate if (! is_valid_attr(str)) {
50370Sstevel@tonic-gate goto free_and_return;
50380Sstevel@tonic-gate }
50390Sstevel@tonic-gate
50400Sstevel@tonic-gate switch (filterop) {
50410Sstevel@tonic-gate case '<': /* LDAP_FILTER_LE */
50420Sstevel@tonic-gate case '>': /* LDAP_FILTER_GE */
50430Sstevel@tonic-gate case '~': /* LDAP_FILTER_APPROX */
50440Sstevel@tonic-gate break;
50450Sstevel@tonic-gate case ':': /* extended filter - v3 only */
50460Sstevel@tonic-gate /*
50470Sstevel@tonic-gate * extended filter looks like this:
50480Sstevel@tonic-gate *
50490Sstevel@tonic-gate * [type][':dn'][':'oid]':='value
50500Sstevel@tonic-gate *
50510Sstevel@tonic-gate * where one of type or :oid is required.
50520Sstevel@tonic-gate *
50530Sstevel@tonic-gate */
50540Sstevel@tonic-gate s2 = s3 = NULL;
50550Sstevel@tonic-gate if ((s2 = strrchr(str, ':')) == NULL) {
50560Sstevel@tonic-gate goto free_and_return;
50570Sstevel@tonic-gate }
50580Sstevel@tonic-gate if (strcasecmp(s2, ":dn") == 0) {
50590Sstevel@tonic-gate *s2 = '\0';
50600Sstevel@tonic-gate } else {
50610Sstevel@tonic-gate *s2 = '\0';
50620Sstevel@tonic-gate if ((s3 = strrchr(str, ':')) != NULL) {
50630Sstevel@tonic-gate if (strcasecmp(s3, ":dn") != 0) {
50640Sstevel@tonic-gate goto free_and_return;
50650Sstevel@tonic-gate }
50660Sstevel@tonic-gate *s3 = '\0';
50670Sstevel@tonic-gate }
50680Sstevel@tonic-gate }
50690Sstevel@tonic-gate if (unescape_filterval(value) < 0) {
50700Sstevel@tonic-gate goto free_and_return;
50710Sstevel@tonic-gate }
50720Sstevel@tonic-gate rc = 0;
50730Sstevel@tonic-gate goto free_and_return;
50740Sstevel@tonic-gate /* break; */
50750Sstevel@tonic-gate default:
50760Sstevel@tonic-gate if (find_star(value) == NULL) {
50770Sstevel@tonic-gate ftype = 0; /* LDAP_FILTER_EQUALITY */
50780Sstevel@tonic-gate } else if (strcmp(value, "*") == 0) {
50790Sstevel@tonic-gate ftype = 1; /* LDAP_FILTER_PRESENT */
50800Sstevel@tonic-gate } else {
50810Sstevel@tonic-gate rc = adj_substring_filter(value);
50820Sstevel@tonic-gate goto free_and_return;
50830Sstevel@tonic-gate }
50840Sstevel@tonic-gate break;
50850Sstevel@tonic-gate }
50860Sstevel@tonic-gate
50870Sstevel@tonic-gate if (ftype != 0) { /* == LDAP_FILTER_PRESENT */
50880Sstevel@tonic-gate rc = 0;
50890Sstevel@tonic-gate } else if (unescape_filterval(value) >= 0) {
50900Sstevel@tonic-gate rc = 0;
50910Sstevel@tonic-gate }
50920Sstevel@tonic-gate if (rc != -1) {
50930Sstevel@tonic-gate rc = 0;
50940Sstevel@tonic-gate }
50950Sstevel@tonic-gate
50960Sstevel@tonic-gate free_and_return:
50970Sstevel@tonic-gate free(str);
50980Sstevel@tonic-gate return (rc);
50990Sstevel@tonic-gate }
51000Sstevel@tonic-gate
51010Sstevel@tonic-gate
51020Sstevel@tonic-gate /*
51030Sstevel@tonic-gate * Check in place both LDAPv2 (RFC-1960) and LDAPv3 (hexadecimal) escape
51040Sstevel@tonic-gate * sequences within the null-terminated string 'val'.
51050Sstevel@tonic-gate *
51060Sstevel@tonic-gate * If 'val' contains invalid escape sequences we return -1.
51070Sstevel@tonic-gate * Otherwise return 1
51080Sstevel@tonic-gate */
51090Sstevel@tonic-gate static int
unescape_filterval(char * val)51100Sstevel@tonic-gate unescape_filterval(char *val)
51110Sstevel@tonic-gate {
51120Sstevel@tonic-gate int escape, firstdigit;
51130Sstevel@tonic-gate char *s;
51140Sstevel@tonic-gate
51150Sstevel@tonic-gate firstdigit = 0;
51160Sstevel@tonic-gate escape = 0;
51170Sstevel@tonic-gate for (s = val; *s; s++) {
51180Sstevel@tonic-gate if (escape) {
51190Sstevel@tonic-gate /*
51200Sstevel@tonic-gate * first try LDAPv3 escape (hexadecimal) sequence
51210Sstevel@tonic-gate */
51220Sstevel@tonic-gate if (hexchar2int(*s) < 0) {
51230Sstevel@tonic-gate if (firstdigit) {
51240Sstevel@tonic-gate /*
51250Sstevel@tonic-gate * LDAPv2 (RFC1960) escape sequence
51260Sstevel@tonic-gate */
51270Sstevel@tonic-gate escape = 0;
51280Sstevel@tonic-gate } else {
51290Sstevel@tonic-gate return (-1);
51300Sstevel@tonic-gate }
51310Sstevel@tonic-gate }
51320Sstevel@tonic-gate if (firstdigit) {
51334765Smj162486 firstdigit = 0;
51340Sstevel@tonic-gate } else {
51354765Smj162486 escape = 0;
51360Sstevel@tonic-gate }
51370Sstevel@tonic-gate
51380Sstevel@tonic-gate } else if (*s != '\\') {
51390Sstevel@tonic-gate escape = 0;
51400Sstevel@tonic-gate
51410Sstevel@tonic-gate } else {
51420Sstevel@tonic-gate escape = 1;
51430Sstevel@tonic-gate firstdigit = 1;
51440Sstevel@tonic-gate }
51450Sstevel@tonic-gate }
51460Sstevel@tonic-gate
51470Sstevel@tonic-gate return (1);
51480Sstevel@tonic-gate }
51490Sstevel@tonic-gate
51500Sstevel@tonic-gate
51510Sstevel@tonic-gate /*
51520Sstevel@tonic-gate * convert character 'c' that represents a hexadecimal digit to an integer.
51530Sstevel@tonic-gate * if 'c' is not a hexidecimal digit [0-9A-Fa-f], -1 is returned.
51540Sstevel@tonic-gate * otherwise the converted value is returned.
51550Sstevel@tonic-gate */
51560Sstevel@tonic-gate static int
hexchar2int(char c)51570Sstevel@tonic-gate hexchar2int(char c)
51580Sstevel@tonic-gate {
51590Sstevel@tonic-gate if (c >= '0' && c <= '9') {
51600Sstevel@tonic-gate return (c - '0');
51610Sstevel@tonic-gate }
51620Sstevel@tonic-gate if (c >= 'A' && c <= 'F') {
51630Sstevel@tonic-gate return (c - 'A' + 10);
51640Sstevel@tonic-gate }
51650Sstevel@tonic-gate if (c >= 'a' && c <= 'f') {
51660Sstevel@tonic-gate return (c - 'a' + 10);
51670Sstevel@tonic-gate }
51680Sstevel@tonic-gate return (-1);
51690Sstevel@tonic-gate }
51700Sstevel@tonic-gate
51710Sstevel@tonic-gate static int
adj_substring_filter(char * val)51720Sstevel@tonic-gate adj_substring_filter(char *val)
51730Sstevel@tonic-gate {
51740Sstevel@tonic-gate char *nextstar;
51750Sstevel@tonic-gate
51760Sstevel@tonic-gate for (; val != NULL; val = nextstar) {
51770Sstevel@tonic-gate if ((nextstar = find_star(val)) != NULL) {
51780Sstevel@tonic-gate *nextstar++ = '\0';
51790Sstevel@tonic-gate }
51800Sstevel@tonic-gate
51810Sstevel@tonic-gate if (*val != '\0') {
51820Sstevel@tonic-gate if (unescape_filterval(val) < 0) {
51830Sstevel@tonic-gate return (-1);
51840Sstevel@tonic-gate }
51850Sstevel@tonic-gate }
51860Sstevel@tonic-gate }
51870Sstevel@tonic-gate
51880Sstevel@tonic-gate return (0);
51890Sstevel@tonic-gate }
51900Sstevel@tonic-gate
51910Sstevel@tonic-gate /* ***** End of modified libldap.so.5 filter parser ***** */
51920Sstevel@tonic-gate
51930Sstevel@tonic-gate
51940Sstevel@tonic-gate /*
51950Sstevel@tonic-gate * Walk filter, remove redundant parentheses in-line
51960Sstevel@tonic-gate * verify that the filter is reasonable
51970Sstevel@tonic-gate */
51980Sstevel@tonic-gate static int
validate_filter(ns_ldap_cookie_t * cookie)51990Sstevel@tonic-gate validate_filter(ns_ldap_cookie_t *cookie)
52000Sstevel@tonic-gate {
52010Sstevel@tonic-gate char *filter = cookie->filter;
52020Sstevel@tonic-gate int rc;
52030Sstevel@tonic-gate
52040Sstevel@tonic-gate /* Parse filter looking for illegal values */
52050Sstevel@tonic-gate
52060Sstevel@tonic-gate rc = adj_filter(filter);
52070Sstevel@tonic-gate if (rc != 0) {
52080Sstevel@tonic-gate return (NS_LDAP_OP_FAILED);
52090Sstevel@tonic-gate }
52100Sstevel@tonic-gate
52110Sstevel@tonic-gate /* end of filter checking */
52120Sstevel@tonic-gate
52130Sstevel@tonic-gate return (NS_LDAP_SUCCESS);
52140Sstevel@tonic-gate }
52151179Svv149972
52161179Svv149972 /*
52171179Svv149972 * Set the account management request control that needs to be sent to server.
52181179Svv149972 * This control is required to get the account management information of
52191179Svv149972 * a user to do local account checking.
52201179Svv149972 */
52211179Svv149972 static int
setup_acctmgmt_params(ns_ldap_cookie_t * cookie)52221179Svv149972 setup_acctmgmt_params(ns_ldap_cookie_t *cookie)
52231179Svv149972 {
52241179Svv149972 LDAPControl *req = NULL, **requestctrls;
52251179Svv149972
52261179Svv149972 req = (LDAPControl *)malloc(sizeof (LDAPControl));
52271179Svv149972
52281179Svv149972 if (req == NULL)
52291179Svv149972 return (NS_LDAP_MEMORY);
52301179Svv149972
52311179Svv149972 /* fill in the fields of this new control */
52321179Svv149972 req->ldctl_iscritical = 1;
52331179Svv149972 req->ldctl_oid = strdup(NS_LDAP_ACCOUNT_USABLE_CONTROL);
52341179Svv149972 if (req->ldctl_oid == NULL) {
52351179Svv149972 free(req);
52361179Svv149972 return (NS_LDAP_MEMORY);
52371179Svv149972 }
52381179Svv149972 req->ldctl_value.bv_len = 0;
52391179Svv149972 req->ldctl_value.bv_val = NULL;
52401179Svv149972
52411179Svv149972 requestctrls = (LDAPControl **)calloc(2, sizeof (LDAPControl *));
52421179Svv149972 if (requestctrls == NULL) {
52431179Svv149972 ldap_control_free(req);
52441179Svv149972 return (NS_LDAP_MEMORY);
52451179Svv149972 }
52461179Svv149972
52471179Svv149972 requestctrls[0] = req;
52481179Svv149972
52491179Svv149972 cookie->p_serverctrls = requestctrls;
52501179Svv149972
52511179Svv149972 return (NS_LDAP_SUCCESS);
52521179Svv149972 }
52531179Svv149972
52541179Svv149972 /*
52554790Ssdussud * int get_new_acct_more_info(BerElement *ber,
52564790Ssdussud * AcctUsableResponse_t *acctResp)
52574790Ssdussud *
52584790Ssdussud * Decode the more_info data from an Account Management control response,
52594790Ssdussud * when the account is not usable and when code style is from recent LDAP
52604790Ssdussud * servers (see below comments for parse_acct_cont_resp_msg() to get more
52614790Ssdussud * details on coding styles and ASN1 description).
52624790Ssdussud *
52634790Ssdussud * Expected BER encoding: {tbtbtbtiti}
52644790Ssdussud * +t: tag is 0
52651179Svv149972 * +b: TRUE if inactive due to account inactivation
52664790Ssdussud * +t: tag is 1
52671179Svv149972 * +b: TRUE if password has been reset
52684790Ssdussud * +t: tag is 2
52691179Svv149972 * +b: TRUE if password is expired
52704790Ssdussud * +t: tag is 3
52714790Ssdussud * +i: contains num of remaining grace, 0 means no grace
52724790Ssdussud * +t: tag is 4
52734790Ssdussud * +i: contains num of seconds before auto-unlock. -1 means acct is locked
52744790Ssdussud * forever (i.e. until reset)
52754790Ssdussud *
52764790Ssdussud * Asumptions:
52774790Ssdussud * - ber is not null
52784790Ssdussud * - acctResp is not null and is initialized with default values for the
52794790Ssdussud * fields in its AcctUsableResp.more_info structure
52804790Ssdussud * - the ber stream is received in the correct order, per the ASN1 description.
52814790Ssdussud * We do not check this order and make the asumption that it is correct.
52824790Ssdussud * Note that the ber stream may not (and will not in most cases) contain
52834790Ssdussud * all fields.
52844790Ssdussud */
52854790Ssdussud static int
get_new_acct_more_info(BerElement * ber,AcctUsableResponse_t * acctResp)52864790Ssdussud get_new_acct_more_info(BerElement *ber, AcctUsableResponse_t *acctResp)
52874790Ssdussud {
52884790Ssdussud int rc = NS_LDAP_SUCCESS;
52894790Ssdussud char errstr[MAXERROR];
52904790Ssdussud ber_tag_t rTag = LBER_DEFAULT;
52914790Ssdussud ber_len_t rLen = 0;
52924790Ssdussud ber_int_t rValue;
52934790Ssdussud char *last;
52944790Ssdussud int berRC = 0;
52954790Ssdussud
52964790Ssdussud /*
52974790Ssdussud * Look at what more_info BER element is/are left to be decoded.
52984790Ssdussud * look at each of them 1 by 1, without checking on their order
52994790Ssdussud * and possible multi values.
53004790Ssdussud */
53014790Ssdussud for (rTag = ber_first_element(ber, &rLen, &last);
53024790Ssdussud rTag != LBER_END_OF_SEQORSET;
53034790Ssdussud rTag = ber_next_element(ber, &rLen, last)) {
53044790Ssdussud
53054790Ssdussud berRC = 0;
53064790Ssdussud switch (rTag) {
53074790Ssdussud case 0 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
53084790Ssdussud /* inactive */
53094790Ssdussud berRC = ber_scanf(ber, "b", &rValue);
53104790Ssdussud if (berRC != LBER_ERROR) {
53114790Ssdussud (acctResp->AcctUsableResp).more_info.
53124790Ssdussud inactive = (rValue != 0) ? 1 : 0;
53134790Ssdussud }
53144790Ssdussud break;
53154790Ssdussud
53164790Ssdussud case 1 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
53174790Ssdussud /* reset */
53184790Ssdussud berRC = ber_scanf(ber, "b", &rValue);
53194790Ssdussud if (berRC != LBER_ERROR) {
53204790Ssdussud (acctResp->AcctUsableResp).more_info.reset
53214790Ssdussud = (rValue != 0) ? 1 : 0;
53224790Ssdussud }
53234790Ssdussud break;
53244790Ssdussud
53254790Ssdussud case 2 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
53264790Ssdussud /* expired */
53274790Ssdussud berRC = ber_scanf(ber, "b", &rValue);
53284790Ssdussud if (berRC != LBER_ERROR) {
53294790Ssdussud (acctResp->AcctUsableResp).more_info.expired
53304790Ssdussud = (rValue != 0) ? 1 : 0;
53314790Ssdussud }
53324790Ssdussud break;
53334790Ssdussud
53344790Ssdussud case 3 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
53354790Ssdussud /* remaining grace */
53364790Ssdussud berRC = ber_scanf(ber, "i", &rValue);
53374790Ssdussud if (berRC != LBER_ERROR) {
53384790Ssdussud (acctResp->AcctUsableResp).more_info.rem_grace
53394790Ssdussud = rValue;
53404790Ssdussud }
53414790Ssdussud break;
53424790Ssdussud
53434790Ssdussud case 4 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
53444790Ssdussud /* seconds before unlock */
53454790Ssdussud berRC = ber_scanf(ber, "i", &rValue);
53464790Ssdussud if (berRC != LBER_ERROR) {
53474790Ssdussud (acctResp->AcctUsableResp).more_info.
53484790Ssdussud sec_b4_unlock = rValue;
53494790Ssdussud }
53504790Ssdussud break;
53514790Ssdussud
53524790Ssdussud default :
53534790Ssdussud (void) sprintf(errstr,
53544790Ssdussud gettext("invalid reason tag 0x%x"), rTag);
53554790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
53564790Ssdussud rc = NS_LDAP_INTERNAL;
53574790Ssdussud break;
53584790Ssdussud }
53594790Ssdussud if (berRC == LBER_ERROR) {
53604790Ssdussud (void) sprintf(errstr,
53614790Ssdussud gettext("error 0x%x decoding value for "
53624790Ssdussud "tag 0x%x"), berRC, rTag);
53634790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
53644790Ssdussud rc = NS_LDAP_INTERNAL;
53654790Ssdussud }
53664790Ssdussud if (rc != NS_LDAP_SUCCESS) {
53674790Ssdussud /* exit the for loop */
53684790Ssdussud break;
53694790Ssdussud }
53704790Ssdussud }
53714790Ssdussud
53724790Ssdussud return (rc);
53734790Ssdussud }
53744790Ssdussud
53754790Ssdussud /*
53764790Ssdussud * int get_old_acct_opt_more_info(BerElement *ber,
53774790Ssdussud * AcctUsableResponse_t *acctResp)
53784790Ssdussud *
53794790Ssdussud * Decode the optional more_info data from an Account Management control
53804790Ssdussud * response, when the account is not usable and when code style is from LDAP
53814790Ssdussud * server 5.2p4 (see below comments for parse_acct_cont_resp_msg() to get more
53824790Ssdussud * details on coding styles and ASN1 description).
53834790Ssdussud *
53844790Ssdussud * Expected BER encoding: titi}
53851179Svv149972 * +t: tag is 2
53861179Svv149972 * +i: contains num of remaining grace, 0 means no grace
53871179Svv149972 * +t: tag is 3
53881179Svv149972 * +i: contains num of seconds before auto-unlock. -1 means acct is locked
53891179Svv149972 * forever (i.e. until reset)
53904790Ssdussud *
53914790Ssdussud * Asumptions:
53924790Ssdussud * - ber is a valid BER element
53934790Ssdussud * - acctResp is initialized for the fields in its AcctUsableResp.more_info
53944790Ssdussud * structure
53951179Svv149972 */
53961179Svv149972 static int
get_old_acct_opt_more_info(ber_tag_t tag,BerElement * ber,AcctUsableResponse_t * acctResp)53974790Ssdussud get_old_acct_opt_more_info(ber_tag_t tag, BerElement *ber,
53984790Ssdussud AcctUsableResponse_t *acctResp)
53994790Ssdussud {
54004790Ssdussud int rc = NS_LDAP_SUCCESS;
54014790Ssdussud char errstr[MAXERROR];
54024790Ssdussud ber_len_t len;
54034790Ssdussud int rem_grace, sec_b4_unlock;
54044790Ssdussud
54054790Ssdussud switch (tag) {
54064790Ssdussud case 2:
54074790Ssdussud /* decode and maybe 3 is following */
54084790Ssdussud if ((tag = ber_scanf(ber, "i", &rem_grace)) == LBER_ERROR) {
54094790Ssdussud (void) sprintf(errstr, gettext("Can not get "
54104790Ssdussud "rem_grace"));
54114790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
54124790Ssdussud rc = NS_LDAP_INTERNAL;
54134790Ssdussud break;
54144790Ssdussud }
54154790Ssdussud (acctResp->AcctUsableResp).more_info.rem_grace = rem_grace;
54164790Ssdussud
54174790Ssdussud if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) {
54184790Ssdussud /* this is a success case, break to exit */
54194790Ssdussud (void) sprintf(errstr, gettext("No more "
54204790Ssdussud "optional data"));
54214790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
54224790Ssdussud break;
54234790Ssdussud }
54244790Ssdussud
54254790Ssdussud if (tag == 3) {
54264790Ssdussud if (ber_scanf(ber, "i", &sec_b4_unlock) == LBER_ERROR) {
54274790Ssdussud (void) sprintf(errstr,
54284790Ssdussud gettext("Can not get sec_b4_unlock "
54294790Ssdussud "- 1st case"));
54304790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
54314790Ssdussud rc = NS_LDAP_INTERNAL;
54324790Ssdussud break;
54334790Ssdussud }
54344790Ssdussud (acctResp->AcctUsableResp).more_info.sec_b4_unlock =
54354790Ssdussud sec_b4_unlock;
54364790Ssdussud } else { /* unknown tag */
54374790Ssdussud (void) sprintf(errstr, gettext("Unknown tag "
54384790Ssdussud "- 1st case"));
54394790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
54404790Ssdussud rc = NS_LDAP_INTERNAL;
54414790Ssdussud break;
54424790Ssdussud }
54434790Ssdussud break;
54444790Ssdussud
54454790Ssdussud case 3:
54464790Ssdussud if (ber_scanf(ber, "i", &sec_b4_unlock) == LBER_ERROR) {
54474790Ssdussud (void) sprintf(errstr, gettext("Can not get "
54484790Ssdussud "sec_b4_unlock - 2nd case"));
54494790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
54504790Ssdussud rc = NS_LDAP_INTERNAL;
54514790Ssdussud break;
54524790Ssdussud }
54534790Ssdussud (acctResp->AcctUsableResp).more_info.sec_b4_unlock =
54544790Ssdussud sec_b4_unlock;
54554790Ssdussud break;
54564790Ssdussud
54574790Ssdussud default: /* unknown tag */
54584790Ssdussud (void) sprintf(errstr, gettext("Unknown tag - 2nd case"));
54594790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
54604790Ssdussud rc = NS_LDAP_INTERNAL;
54614790Ssdussud break;
54624790Ssdussud }
54634790Ssdussud
54644790Ssdussud return (rc);
54654790Ssdussud }
54664790Ssdussud
54674790Ssdussud /*
54684790Ssdussud * **** This function needs to be moved to libldap library ****
54694790Ssdussud * parse_acct_cont_resp_msg() parses the message received by server according to
54704790Ssdussud * following format (ASN1 notation):
54714790Ssdussud *
54724790Ssdussud * ACCOUNT_USABLE_RESPONSE::= CHOICE {
54734790Ssdussud * is_available [0] INTEGER,
54744790Ssdussud * ** seconds before expiration **
54754790Ssdussud * is_not_available [1] more_info
54764790Ssdussud * }
54774790Ssdussud * more_info::= SEQUENCE {
54784790Ssdussud * inactive [0] BOOLEAN DEFAULT FALSE,
54794790Ssdussud * reset [1] BOOLEAN DEFAULT FALSE,
54804790Ssdussud * expired [2] BOOLEAN DEFAULT FALSE,
54814790Ssdussud * remaining_grace [3] INTEGER OPTIONAL,
54824790Ssdussud * seconds_before_unlock [4] INTEGER OPTIONAL
54834790Ssdussud * }
54844790Ssdussud */
54854790Ssdussud /*
54864790Ssdussud * #define used to make the difference between coding style as done
54874790Ssdussud * by LDAP server 5.2p4 and newer LDAP servers. There are 4 values:
54884790Ssdussud * - DS52p4_USABLE: 5.2p4 coding style, account is usable
54894790Ssdussud * - DS52p4_NOT_USABLE: 5.2p4 coding style, account is not usable
54904790Ssdussud * - NEW_USABLE: newer LDAP servers coding style, account is usable
54914790Ssdussud * - NEW_NOT_USABLE: newer LDAP servers coding style, account is not usable
54924790Ssdussud *
54934790Ssdussud * An account would be considered not usable if for instance:
54944790Ssdussud * - it's been made inactive in the LDAP server
54954790Ssdussud * - or its password was reset in the LDAP server database
54964790Ssdussud * - or its password expired
54974790Ssdussud * - or the account has been locked, possibly forever
54984790Ssdussud */
54994790Ssdussud #define DS52p4_USABLE 0x00
55004790Ssdussud #define DS52p4_NOT_USABLE 0x01
55014790Ssdussud #define NEW_USABLE 0x00 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE
55024790Ssdussud #define NEW_NOT_USABLE 0x01 | LBER_CLASS_CONTEXT | LBER_CONSTRUCTED
55034790Ssdussud static int
parse_acct_cont_resp_msg(LDAPControl ** ectrls,AcctUsableResponse_t * acctResp)55041179Svv149972 parse_acct_cont_resp_msg(LDAPControl **ectrls, AcctUsableResponse_t *acctResp)
55051179Svv149972 {
55064790Ssdussud int rc = NS_LDAP_SUCCESS;
55071179Svv149972 BerElement *ber;
55084790Ssdussud ber_tag_t tag;
55091179Svv149972 ber_len_t len;
55104790Ssdussud int i;
55114790Ssdussud char errstr[MAXERROR];
55124790Ssdussud /* used for any coding style when account is usable */
55134790Ssdussud int seconds_before_expiry;
55144790Ssdussud /* used for 5.2p4 coding style when account is not usable */
55154790Ssdussud int inactive, reset, expired;
55164790Ssdussud
55174790Ssdussud if (ectrls == NULL) {
55184790Ssdussud (void) sprintf(errstr, gettext("Invalid ectrls parameter"));
55194790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
55201179Svv149972 return (NS_LDAP_INVALID_PARAM);
55214790Ssdussud }
55221179Svv149972
55231179Svv149972 for (i = 0; ectrls[i] != NULL; i++) {
55241179Svv149972 if (strcmp(ectrls[i]->ldctl_oid, NS_LDAP_ACCOUNT_USABLE_CONTROL)
55254790Ssdussud == 0) {
55264790Ssdussud break;
55274790Ssdussud }
55281179Svv149972 }
55294790Ssdussud
55304790Ssdussud if (ectrls[i] == NULL) {
55314790Ssdussud /* Ldap control is not found */
55324790Ssdussud (void) sprintf(errstr, gettext("Account Usable Control "
55334790Ssdussud "not found"));
55344790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
55354790Ssdussud return (NS_LDAP_NOTFOUND);
55364790Ssdussud }
55374790Ssdussud
55384790Ssdussud /* Allocate a BER element from the control value and parse it. */
55391179Svv149972 if ((ber = ber_init(&ectrls[i]->ldctl_value)) == NULL)
55401179Svv149972 return (NS_LDAP_MEMORY);
55411179Svv149972
55421179Svv149972 if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) {
55431179Svv149972 /* Ldap decoding error */
55444790Ssdussud (void) sprintf(errstr, gettext("Error decoding 1st tag"));
55454790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
55461179Svv149972 ber_free(ber, 1);
55471179Svv149972 return (NS_LDAP_INTERNAL);
55481179Svv149972 }
55491179Svv149972
55501179Svv149972 switch (tag) {
55514790Ssdussud case DS52p4_USABLE:
55524790Ssdussud case NEW_USABLE:
55534790Ssdussud acctResp->choice = 0;
55544790Ssdussud if (ber_scanf(ber, "i", &seconds_before_expiry)
55554790Ssdussud == LBER_ERROR) {
55564790Ssdussud /* Ldap decoding error */
55574790Ssdussud (void) sprintf(errstr, gettext("Can not get "
55584790Ssdussud "seconds_before_expiry"));
55594790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
55604790Ssdussud rc = NS_LDAP_INTERNAL;
55614790Ssdussud break;
55624790Ssdussud }
55634790Ssdussud /* ber_scanf() succeeded */
55644790Ssdussud (acctResp->AcctUsableResp).seconds_before_expiry =
55654790Ssdussud seconds_before_expiry;
55664790Ssdussud break;
55674790Ssdussud
55684790Ssdussud case DS52p4_NOT_USABLE:
55694790Ssdussud acctResp->choice = 1;
55704790Ssdussud if (ber_scanf(ber, "{bbb", &inactive, &reset, &expired)
55714790Ssdussud == LBER_ERROR) {
55724790Ssdussud /* Ldap decoding error */
55734790Ssdussud (void) sprintf(errstr, gettext("Can not get "
55744790Ssdussud "inactive/reset/expired"));
55754790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
55764790Ssdussud rc = NS_LDAP_INTERNAL;
55774790Ssdussud break;
55784790Ssdussud }
55794790Ssdussud /* ber_scanf() succeeded */
55804790Ssdussud (acctResp->AcctUsableResp).more_info.inactive =
55814790Ssdussud ((inactive == 0) ? 0 : 1);
55824790Ssdussud (acctResp->AcctUsableResp).more_info.reset =
55834790Ssdussud ((reset == 0) ? 0 : 1);
55844790Ssdussud (acctResp->AcctUsableResp).more_info.expired =
55854790Ssdussud ((expired == 0) ? 0 : 1);
55864790Ssdussud (acctResp->AcctUsableResp).more_info.rem_grace = 0;
55874790Ssdussud (acctResp->AcctUsableResp).more_info.sec_b4_unlock = 0;
55884790Ssdussud
55894790Ssdussud if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) {
55904790Ssdussud /* this is a success case, break to exit */
55914790Ssdussud (void) sprintf(errstr, gettext("No optional data"));
55924790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
55931179Svv149972 break;
55944790Ssdussud }
55954790Ssdussud
55964790Ssdussud /*
55974790Ssdussud * Look at what optional more_info BER element is/are
55984790Ssdussud * left to be decoded.
55994790Ssdussud */
56004790Ssdussud rc = get_old_acct_opt_more_info(tag, ber, acctResp);
56014790Ssdussud break;
56024790Ssdussud
56034790Ssdussud case NEW_NOT_USABLE:
56044790Ssdussud acctResp->choice = 1;
56054790Ssdussud /*
56064790Ssdussud * Recent LDAP servers won't code more_info data for default
56074790Ssdussud * values (see above comments on ASN1 description for what
56084790Ssdussud * fields have default values & what fields are optional).
56094790Ssdussud */
56104790Ssdussud (acctResp->AcctUsableResp).more_info.inactive = 0;
56114790Ssdussud (acctResp->AcctUsableResp).more_info.reset = 0;
56124790Ssdussud (acctResp->AcctUsableResp).more_info.expired = 0;
56134790Ssdussud (acctResp->AcctUsableResp).more_info.rem_grace = 0;
56144790Ssdussud (acctResp->AcctUsableResp).more_info.sec_b4_unlock = 0;
56154790Ssdussud
56164790Ssdussud if (len == 0) {
56174790Ssdussud /*
56184790Ssdussud * Nothing else to decode; this is valid and we
56194790Ssdussud * use default values set above.
56204790Ssdussud */
56214790Ssdussud (void) sprintf(errstr, gettext("more_info is "
56224790Ssdussud "empty, using default values"));
56234790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
56241179Svv149972 break;
56254790Ssdussud }
56264790Ssdussud
56274790Ssdussud /*
56284790Ssdussud * Look at what more_info BER element is/are left to
56294790Ssdussud * be decoded.
56304790Ssdussud */
56314790Ssdussud rc = get_new_acct_more_info(ber, acctResp);
56324790Ssdussud break;
56334790Ssdussud
56344790Ssdussud default:
56354790Ssdussud (void) sprintf(errstr, gettext("unknwon coding style "
56364790Ssdussud "(tag: 0x%x)"), tag);
56374790Ssdussud syslog(LOG_DEBUG, "libsldap: %s", errstr);
56384790Ssdussud rc = NS_LDAP_INTERNAL;
56394790Ssdussud break;
56401179Svv149972 }
56411179Svv149972
56421179Svv149972 ber_free(ber, 1);
56434790Ssdussud return (rc);
56441179Svv149972 }
56451179Svv149972
56461179Svv149972 /*
56476842Sth160488 * internal function for __ns_ldap_getAcctMgmt()
56481179Svv149972 */
56496842Sth160488 static int
getAcctMgmt(const char * user,AcctUsableResponse_t * acctResp,ns_conn_user_t * conn_user)56506842Sth160488 getAcctMgmt(const char *user, AcctUsableResponse_t *acctResp,
56516842Sth160488 ns_conn_user_t *conn_user)
56521179Svv149972 {
56531179Svv149972 int scope, rc;
56541179Svv149972 char ldapfilter[1024];
56551179Svv149972 ns_ldap_cookie_t *cookie;
56561179Svv149972 ns_ldap_search_desc_t **sdlist = NULL;
56571179Svv149972 ns_ldap_search_desc_t *dptr;
56581179Svv149972 ns_ldap_error_t *error = NULL;
56591179Svv149972 char **dns = NULL;
56601179Svv149972 char service[] = "shadow";
56611179Svv149972
56621179Svv149972 if (user == NULL || acctResp == NULL)
56631179Svv149972 return (NS_LDAP_INVALID_PARAM);
56641179Svv149972
56651179Svv149972 /* Initialize State machine cookie */
56661179Svv149972 cookie = init_search_state_machine();
56671179Svv149972 if (cookie == NULL)
56681179Svv149972 return (NS_LDAP_MEMORY);
56696842Sth160488 cookie->conn_user = conn_user;
56701179Svv149972
56711179Svv149972 /* see if need to follow referrals */
56721179Svv149972 rc = __s_api_toFollowReferrals(0,
56734765Smj162486 &cookie->followRef, &error);
56741179Svv149972 if (rc != NS_LDAP_SUCCESS) {
56751179Svv149972 (void) __ns_ldap_freeError(&error);
56761179Svv149972 goto out;
56771179Svv149972 }
56781179Svv149972
56791179Svv149972 /* get the service descriptor - or create a default one */
56801179Svv149972 rc = __s_api_get_SSD_from_SSDtoUse_service(service,
56814765Smj162486 &sdlist, &error);
56821179Svv149972 if (rc != NS_LDAP_SUCCESS) {
56831179Svv149972 (void) __ns_ldap_freeError(&error);
56841179Svv149972 goto out;
56851179Svv149972 }
56861179Svv149972
56871179Svv149972 if (sdlist == NULL) {
56881179Svv149972 /* Create default service Desc */
56891179Svv149972 sdlist = (ns_ldap_search_desc_t **)calloc(2,
56904765Smj162486 sizeof (ns_ldap_search_desc_t *));
56911179Svv149972 if (sdlist == NULL) {
56921179Svv149972 rc = NS_LDAP_MEMORY;
56931179Svv149972 goto out;
56941179Svv149972 }
56951179Svv149972 dptr = (ns_ldap_search_desc_t *)
56964765Smj162486 calloc(1, sizeof (ns_ldap_search_desc_t));
56971179Svv149972 if (dptr == NULL) {
56981179Svv149972 free(sdlist);
56991179Svv149972 rc = NS_LDAP_MEMORY;
57001179Svv149972 goto out;
57011179Svv149972 }
57021179Svv149972 sdlist[0] = dptr;
57031179Svv149972
57041179Svv149972 /* default base */
57051179Svv149972 rc = __s_api_getDNs(&dns, service, &cookie->errorp);
57061179Svv149972 if (rc != NS_LDAP_SUCCESS) {
57071179Svv149972 if (dns) {
57081179Svv149972 __s_api_free2dArray(dns);
57091179Svv149972 dns = NULL;
57101179Svv149972 }
57111179Svv149972 (void) __ns_ldap_freeError(&(cookie->errorp));
57121179Svv149972 cookie->errorp = NULL;
57131179Svv149972 goto out;
57141179Svv149972 }
57151179Svv149972 dptr->basedn = strdup(dns[0]);
57161179Svv149972 if (dptr->basedn == NULL) {
57171179Svv149972 free(sdlist);
57181179Svv149972 free(dptr);
57191179Svv149972 if (dns) {
57201179Svv149972 __s_api_free2dArray(dns);
57211179Svv149972 dns = NULL;
57221179Svv149972 }
57231179Svv149972 rc = NS_LDAP_MEMORY;
57241179Svv149972 goto out;
57251179Svv149972 }
57261179Svv149972 __s_api_free2dArray(dns);
57271179Svv149972 dns = NULL;
57281179Svv149972
57291179Svv149972 /* default scope */
57301179Svv149972 scope = 0;
57311179Svv149972 rc = __s_api_getSearchScope(&scope, &cookie->errorp);
57321179Svv149972 dptr->scope = scope;
57331179Svv149972 }
57341179Svv149972
57351179Svv149972 cookie->sdlist = sdlist;
57361179Svv149972
57371179Svv149972 cookie->service = strdup(service);
57381179Svv149972 if (cookie->service == NULL) {
57391179Svv149972 rc = NS_LDAP_MEMORY;
57401179Svv149972 goto out;
57411179Svv149972 }
57421179Svv149972
57431179Svv149972 /* search for entries for this particular uid */
57441179Svv149972 (void) snprintf(ldapfilter, sizeof (ldapfilter), "(uid=%s)", user);
57451179Svv149972 cookie->i_filter = strdup(ldapfilter);
57461179Svv149972 if (cookie->i_filter == NULL) {
57471179Svv149972 rc = NS_LDAP_MEMORY;
57481179Svv149972 goto out;
57491179Svv149972 }
57501179Svv149972
57511179Svv149972 /* create the control request */
57521179Svv149972 if ((rc = setup_acctmgmt_params(cookie)) != NS_LDAP_SUCCESS)
57531179Svv149972 goto out;
57541179Svv149972
57551179Svv149972 /* Process search */
57561179Svv149972 rc = search_state_machine(cookie, GET_ACCT_MGMT_INFO, 0);
57571179Svv149972
57581179Svv149972 /* Copy results back to user */
57591179Svv149972 rc = cookie->err_rc;
57601179Svv149972 if (rc != NS_LDAP_SUCCESS)
57611179Svv149972 (void) __ns_ldap_freeError(&(cookie->errorp));
57621179Svv149972
57631179Svv149972 if (cookie->result == NULL)
57641179Svv149972 goto out;
57651179Svv149972
57661179Svv149972 if ((rc = parse_acct_cont_resp_msg(cookie->resultctrl, acctResp))
57674765Smj162486 != NS_LDAP_SUCCESS)
57681179Svv149972 goto out;
57691179Svv149972
57701179Svv149972 rc = NS_LDAP_SUCCESS;
57711179Svv149972
57721179Svv149972 out:
57731179Svv149972 delete_search_cookie(cookie);
57741179Svv149972
57751179Svv149972 return (rc);
57761179Svv149972 }
57776842Sth160488
57786842Sth160488 /*
57796842Sth160488 * __ns_ldap_getAcctMgmt() is called from pam account management stack
57806842Sth160488 * for retrieving accounting information of users with no user password -
57816842Sth160488 * eg. rlogin, rsh, etc. This function uses the account management control
57826842Sth160488 * request to do a search on the server for the user in question. The
57836842Sth160488 * response control returned from the server is got from the cookie.
57846842Sth160488 * Input params: username of whose account mgmt information is to be got
57856842Sth160488 * pointer to hold the parsed account management information
57866842Sth160488 * Return values: NS_LDAP_SUCCESS on success or appropriate error
57876842Sth160488 * code on failure
57886842Sth160488 */
57896842Sth160488 int
__ns_ldap_getAcctMgmt(const char * user,AcctUsableResponse_t * acctResp)57906842Sth160488 __ns_ldap_getAcctMgmt(const char *user, AcctUsableResponse_t *acctResp)
57916842Sth160488 {
57926842Sth160488 ns_conn_user_t *cu = NULL;
57936842Sth160488 int try_cnt = 0;
57946842Sth160488 int rc = NS_LDAP_SUCCESS;
57956842Sth160488 ns_ldap_error_t *error = NULL;
57966842Sth160488
57976842Sth160488 for (;;) {
57986842Sth160488 if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
57996842Sth160488 &try_cnt, &rc, &error) == 0)
58006842Sth160488 break;
58016842Sth160488 rc = getAcctMgmt(user, acctResp, cu);
58026842Sth160488 }
58036842Sth160488 return (rc);
58046842Sth160488 }
5805