17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*54caa916SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India * Common Development and Distribution License (the "License"). 6*54caa916SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*54caa916SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <synch.h> 277c478bd9Sstevel@tonic-gate #include <strings.h> 287c478bd9Sstevel@tonic-gate #include <sys/time.h> 297c478bd9Sstevel@tonic-gate #include <ctype.h> 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include "ldap_op.h" 327c478bd9Sstevel@tonic-gate #include "ldap_util.h" 337c478bd9Sstevel@tonic-gate #include "ldap_structs.h" 347c478bd9Sstevel@tonic-gate #include "ldap_ruleval.h" 357c478bd9Sstevel@tonic-gate #include "ldap_attr.h" 367c478bd9Sstevel@tonic-gate #include "ldap_print.h" 377c478bd9Sstevel@tonic-gate #include "ldap_glob.h" 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate #include "nis_parse_ldap_conf.h" 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #ifndef LDAPS_PORT 427c478bd9Sstevel@tonic-gate #define LDAPS_PORT 636 437c478bd9Sstevel@tonic-gate #endif 447c478bd9Sstevel@tonic-gate 45a506a34cSth160488 static int setupConList(char *serverList, char *who, 46a506a34cSth160488 char *cred, auth_method_t method); 47a506a34cSth160488 48a506a34cSth160488 497c478bd9Sstevel@tonic-gate /* 507c478bd9Sstevel@tonic-gate * Build one of our internal LDAP search structures, containing copies of 517c478bd9Sstevel@tonic-gate * the supplied input. return NULL in case of error. 527c478bd9Sstevel@tonic-gate * 537c478bd9Sstevel@tonic-gate * If 'filter' is NULL, build an AND-filter using the filter components. 547c478bd9Sstevel@tonic-gate */ 557c478bd9Sstevel@tonic-gate __nis_ldap_search_t * 567c478bd9Sstevel@tonic-gate buildLdapSearch(char *base, int scope, int numFilterComps, char **filterComp, 577c478bd9Sstevel@tonic-gate char *filter, char **attrs, int attrsonly, int isDN) { 587c478bd9Sstevel@tonic-gate __nis_ldap_search_t *ls; 597c478bd9Sstevel@tonic-gate char **a; 607c478bd9Sstevel@tonic-gate int i, na, err = 0; 617c478bd9Sstevel@tonic-gate char *myself = "buildLdapSearch"; 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate ls = am(myself, sizeof (*ls)); 647c478bd9Sstevel@tonic-gate if (ls == 0) 657c478bd9Sstevel@tonic-gate return (0); 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate ls->base = sdup(myself, T, base); 687c478bd9Sstevel@tonic-gate if (ls->base == 0 && base != 0) 697c478bd9Sstevel@tonic-gate err++; 707c478bd9Sstevel@tonic-gate ls->scope = scope; 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate if (filterComp != 0 && numFilterComps > 0) { 737c478bd9Sstevel@tonic-gate ls->filterComp = am(myself, numFilterComps * 747c478bd9Sstevel@tonic-gate sizeof (ls->filterComp[0])); 757c478bd9Sstevel@tonic-gate if (ls->filterComp == 0) { 767c478bd9Sstevel@tonic-gate err++; 777c478bd9Sstevel@tonic-gate numFilterComps = 0; 787c478bd9Sstevel@tonic-gate } 797c478bd9Sstevel@tonic-gate for (i = 0; i < numFilterComps; i++) { 807c478bd9Sstevel@tonic-gate ls->filterComp[i] = sdup(myself, T, filterComp[i]); 817c478bd9Sstevel@tonic-gate if (ls->filterComp[i] == 0 && filterComp[i] != 0) 827c478bd9Sstevel@tonic-gate err++; 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate ls->numFilterComps = numFilterComps; 857c478bd9Sstevel@tonic-gate if (filter == 0) { 867c478bd9Sstevel@tonic-gate ls->filter = concatenateFilterComps(ls->numFilterComps, 877c478bd9Sstevel@tonic-gate ls->filterComp); 887c478bd9Sstevel@tonic-gate if (ls->filter == 0) 897c478bd9Sstevel@tonic-gate err++; 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate } else { 927c478bd9Sstevel@tonic-gate ls->filterComp = 0; 937c478bd9Sstevel@tonic-gate ls->numFilterComps = 0; 947c478bd9Sstevel@tonic-gate ls->filter = sdup(myself, T, filter); 957c478bd9Sstevel@tonic-gate if (ls->filter == 0 && filter != 0) 967c478bd9Sstevel@tonic-gate err++; 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate if (attrs != 0) { 1007c478bd9Sstevel@tonic-gate for (na = 0, a = attrs; *a != 0; a++, na++); 1017c478bd9Sstevel@tonic-gate ls->attrs = am(myself, (na + 1) * sizeof (ls->attrs[0])); 1027c478bd9Sstevel@tonic-gate if (ls->attrs != 0) { 1037c478bd9Sstevel@tonic-gate for (i = 0; i < na; i++) { 1047c478bd9Sstevel@tonic-gate ls->attrs[i] = sdup(myself, T, attrs[i]); 1057c478bd9Sstevel@tonic-gate if (ls->attrs[i] == 0 && attrs[i] != 0) 1067c478bd9Sstevel@tonic-gate err++; 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate ls->attrs[na] = 0; 1097c478bd9Sstevel@tonic-gate ls->numAttrs = na; 1107c478bd9Sstevel@tonic-gate } else { 1117c478bd9Sstevel@tonic-gate err++; 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate } else { 1147c478bd9Sstevel@tonic-gate ls->attrs = 0; 1157c478bd9Sstevel@tonic-gate ls->numAttrs = 0; 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate ls->attrsonly = attrsonly; 1197c478bd9Sstevel@tonic-gate ls->isDN = isDN; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate if (err > 0) { 1227c478bd9Sstevel@tonic-gate freeLdapSearch(ls); 1237c478bd9Sstevel@tonic-gate ls = 0; 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate return (ls); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate void 1307c478bd9Sstevel@tonic-gate freeLdapSearch(__nis_ldap_search_t *ls) { 1317c478bd9Sstevel@tonic-gate int i; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate if (ls == 0) 1347c478bd9Sstevel@tonic-gate return; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate sfree(ls->base); 1377c478bd9Sstevel@tonic-gate if (ls->filterComp != 0) { 1387c478bd9Sstevel@tonic-gate for (i = 0; i < ls->numFilterComps; i++) { 1397c478bd9Sstevel@tonic-gate sfree(ls->filterComp[i]); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate sfree(ls->filterComp); 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate sfree(ls->filter); 1447c478bd9Sstevel@tonic-gate if (ls->attrs != 0) { 1457c478bd9Sstevel@tonic-gate for (i = 0; i < ls->numAttrs; i++) { 1467c478bd9Sstevel@tonic-gate sfree(ls->attrs[i]); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate sfree(ls->attrs); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate free(ls); 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate /* 1557c478bd9Sstevel@tonic-gate * Given a table mapping, and a rule/value pointer, 1567c478bd9Sstevel@tonic-gate * return an LDAP search structure with values suitable for use 1577c478bd9Sstevel@tonic-gate * by ldap_search() or (if dn != 0) ldap_modify(). The rule/value 1587c478bd9Sstevel@tonic-gate * may be modified. 1597c478bd9Sstevel@tonic-gate * 1607c478bd9Sstevel@tonic-gate * If dn != 0 and *dn == 0, the function attemps to return a pointer 1617c478bd9Sstevel@tonic-gate * to the DN. This may necessitate an ldapSearch, if the rule set doesn't 1627c478bd9Sstevel@tonic-gate * produce a DN directly. 1637c478bd9Sstevel@tonic-gate * 1647c478bd9Sstevel@tonic-gate * if dn == 0, and the rule set produces a DN as well as other attribute/ 1657c478bd9Sstevel@tonic-gate * value pairs, the function returns an LDAP search structure with the 1667c478bd9Sstevel@tonic-gate * DN only. 1677c478bd9Sstevel@tonic-gate * 1687c478bd9Sstevel@tonic-gate * If 'fromLDAP' is set, the caller wants base/scope/filter from 1697c478bd9Sstevel@tonic-gate * t->objectDN->read; otherwise, from t->objectDN->write. 1707c478bd9Sstevel@tonic-gate * 1717c478bd9Sstevel@tonic-gate * If 'rv' is NULL, the caller wants an enumeration of the container. 1727c478bd9Sstevel@tonic-gate * 1737c478bd9Sstevel@tonic-gate * Note that this function only creates a search structure for 't' itself; 1747c478bd9Sstevel@tonic-gate * if there are alternative mappings for the table, those must be handled 1757c478bd9Sstevel@tonic-gate * by our caller. 1767c478bd9Sstevel@tonic-gate */ 1777c478bd9Sstevel@tonic-gate __nis_ldap_search_t * 1787c478bd9Sstevel@tonic-gate createLdapRequest(__nis_table_mapping_t *t, 1797c478bd9Sstevel@tonic-gate __nis_rule_value_t *rv, char **dn, int fromLDAP, 1807c478bd9Sstevel@tonic-gate int *res, __nis_object_dn_t *obj_dn) { 1817c478bd9Sstevel@tonic-gate int i, j; 1827c478bd9Sstevel@tonic-gate __nis_ldap_search_t *ls = 0; 1837c478bd9Sstevel@tonic-gate char **locDN; 1847c478bd9Sstevel@tonic-gate int numLocDN, stat = 0, count = 0; 1857c478bd9Sstevel@tonic-gate char *myself = "createLdapRequest"; 1867c478bd9Sstevel@tonic-gate __nis_object_dn_t *objectDN = NULL; 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate if (t == 0) 1897c478bd9Sstevel@tonic-gate return (0); 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate if (obj_dn == NULL) 1927c478bd9Sstevel@tonic-gate objectDN = t->objectDN; 1937c478bd9Sstevel@tonic-gate else 1947c478bd9Sstevel@tonic-gate objectDN = obj_dn; 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate if (rv == 0) { 1977c478bd9Sstevel@tonic-gate char *base; 1987c478bd9Sstevel@tonic-gate char *filter; 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate if (fromLDAP) { 2017c478bd9Sstevel@tonic-gate base = objectDN->read.base; 2027c478bd9Sstevel@tonic-gate filter = makeFilter(objectDN->read.attrs); 2037c478bd9Sstevel@tonic-gate } else { 2047c478bd9Sstevel@tonic-gate base = objectDN->write.base; 2057c478bd9Sstevel@tonic-gate filter = makeFilter(objectDN->write.attrs); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* Create request to enumerate container */ 2097c478bd9Sstevel@tonic-gate ls = buildLdapSearch(base, objectDN->read.scope, 0, 0, filter, 2107c478bd9Sstevel@tonic-gate 0, 0, 0); 2117c478bd9Sstevel@tonic-gate sfree(filter); 2127c478bd9Sstevel@tonic-gate return (ls); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate for (i = 0; i < t->numRulesToLDAP; i++) { 2167c478bd9Sstevel@tonic-gate rv = addLdapRuleValue(t, t->ruleToLDAP[i], 2177c478bd9Sstevel@tonic-gate mit_ldap, mit_nisplus, rv, !fromLDAP, &stat); 2187c478bd9Sstevel@tonic-gate if (rv == 0) 2197c478bd9Sstevel@tonic-gate return (0); 2207c478bd9Sstevel@tonic-gate if (stat == NP_LDAP_RULES_NO_VALUE) 2217c478bd9Sstevel@tonic-gate count++; 2227c478bd9Sstevel@tonic-gate stat = 0; 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* 2267c478bd9Sstevel@tonic-gate * If none of the rules produced a value despite 2277c478bd9Sstevel@tonic-gate * having enough NIS+ columns, return error. 2287c478bd9Sstevel@tonic-gate */ 2297c478bd9Sstevel@tonic-gate if (rv->numAttrs == 0 && count > 0) { 2307c478bd9Sstevel@tonic-gate *res = NP_LDAP_RULES_NO_VALUE; 2317c478bd9Sstevel@tonic-gate return (0); 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate /* 2357c478bd9Sstevel@tonic-gate * 'rv' now contains everything we know about the attributes and 2367c478bd9Sstevel@tonic-gate * values. Build an LDAP search structure from it. 2377c478bd9Sstevel@tonic-gate */ 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate /* Look for a single-valued DN */ 2407c478bd9Sstevel@tonic-gate locDN = findDNs(myself, rv, 1, 2417c478bd9Sstevel@tonic-gate fromLDAP ? objectDN->read.base : 2427c478bd9Sstevel@tonic-gate objectDN->write.base, 2437c478bd9Sstevel@tonic-gate &numLocDN); 2447c478bd9Sstevel@tonic-gate if (locDN != 0 && numLocDN == 1) { 2457c478bd9Sstevel@tonic-gate if (dn != 0 && *dn == 0) { 2467c478bd9Sstevel@tonic-gate *dn = locDN[0]; 2477c478bd9Sstevel@tonic-gate sfree(locDN); 2487c478bd9Sstevel@tonic-gate } else { 2497c478bd9Sstevel@tonic-gate char *filter; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate if (fromLDAP) 2527c478bd9Sstevel@tonic-gate filter = makeFilter(objectDN->read.attrs); 2537c478bd9Sstevel@tonic-gate else 2547c478bd9Sstevel@tonic-gate filter = makeFilter(objectDN->write.attrs); 2557c478bd9Sstevel@tonic-gate ls = buildLdapSearch(locDN[0], LDAP_SCOPE_BASE, 0, 0, 2567c478bd9Sstevel@tonic-gate filter, 0, 0, 1); 2577c478bd9Sstevel@tonic-gate sfree(filter); 2587c478bd9Sstevel@tonic-gate freeDNs(locDN, numLocDN); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate } else { 2617c478bd9Sstevel@tonic-gate freeDNs(locDN, numLocDN); 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate if (ls != 0) { 2657c478bd9Sstevel@tonic-gate ls->useCon = 1; 2667c478bd9Sstevel@tonic-gate return (ls); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate /* 2707c478bd9Sstevel@tonic-gate * No DN, or caller wanted a search structure with the non-DN 2717c478bd9Sstevel@tonic-gate * attributes. 2727c478bd9Sstevel@tonic-gate */ 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate /* Initialize search structure */ 2757c478bd9Sstevel@tonic-gate { 2767c478bd9Sstevel@tonic-gate char *filter = (fromLDAP) ? 2777c478bd9Sstevel@tonic-gate makeFilter(objectDN->read.attrs) : 2787c478bd9Sstevel@tonic-gate makeFilter(objectDN->write.attrs); 2797c478bd9Sstevel@tonic-gate char **ofc; 2807c478bd9Sstevel@tonic-gate int nofc = 0; 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate ofc = makeFilterComp(filter, &nofc); 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate if (filter != 0 && ofc == 0) { 2857c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 2867c478bd9Sstevel@tonic-gate "%s: Unable to break filter into components: \"%s\"", 2877c478bd9Sstevel@tonic-gate myself, NIL(filter)); 2887c478bd9Sstevel@tonic-gate sfree(filter); 2897c478bd9Sstevel@tonic-gate return (0); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate if (fromLDAP) 2937c478bd9Sstevel@tonic-gate ls = buildLdapSearch(objectDN->read.base, 2947c478bd9Sstevel@tonic-gate objectDN->read.scope, 2957c478bd9Sstevel@tonic-gate nofc, ofc, 0, 0, 0, 0); 2967c478bd9Sstevel@tonic-gate else 2977c478bd9Sstevel@tonic-gate ls = buildLdapSearch(objectDN->write.base, 2987c478bd9Sstevel@tonic-gate objectDN->write.scope, 2997c478bd9Sstevel@tonic-gate nofc, ofc, 0, 0, 0, 0); 3007c478bd9Sstevel@tonic-gate sfree(filter); 3017c478bd9Sstevel@tonic-gate freeFilterComp(ofc, nofc); 3027c478bd9Sstevel@tonic-gate if (ls == 0) 3037c478bd9Sstevel@tonic-gate return (0); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate /* Build and add the filter components */ 3077c478bd9Sstevel@tonic-gate for (i = 0; i < rv->numAttrs; i++) { 3087c478bd9Sstevel@tonic-gate /* Skip DN */ 3097c478bd9Sstevel@tonic-gate if (strcasecmp("dn", rv->attrName[i]) == 0) 3107c478bd9Sstevel@tonic-gate continue; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate /* Skip vt_ber values */ 3137c478bd9Sstevel@tonic-gate if (rv->attrVal[i].type == vt_ber) 3147c478bd9Sstevel@tonic-gate continue; 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate for (j = 0; j < rv->attrVal[i].numVals; j++) { 3177c478bd9Sstevel@tonic-gate __nis_buffer_t b = {0, 0}; 3187c478bd9Sstevel@tonic-gate char **tmpComp; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate bp2buf(myself, &b, "%s=%s", 3217c478bd9Sstevel@tonic-gate rv->attrName[i], rv->attrVal[i].val[j].value); 3227c478bd9Sstevel@tonic-gate tmpComp = addFilterComp(b.buf, ls->filterComp, 3237c478bd9Sstevel@tonic-gate &ls->numFilterComps); 3247c478bd9Sstevel@tonic-gate if (tmpComp == 0) { 3257c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 3267c478bd9Sstevel@tonic-gate "%s: Unable to add filter component \"%s\"", 3277c478bd9Sstevel@tonic-gate myself, NIL(b.buf)); 3287c478bd9Sstevel@tonic-gate sfree(b.buf); 3297c478bd9Sstevel@tonic-gate freeLdapSearch(ls); 3307c478bd9Sstevel@tonic-gate return (0); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate ls->filterComp = tmpComp; 3337c478bd9Sstevel@tonic-gate sfree(b.buf); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate if (ls->numFilterComps > 0) { 3387c478bd9Sstevel@tonic-gate sfree(ls->filter); 3397c478bd9Sstevel@tonic-gate ls->filter = concatenateFilterComps(ls->numFilterComps, 3407c478bd9Sstevel@tonic-gate ls->filterComp); 3417c478bd9Sstevel@tonic-gate if (ls->filter == 0) { 3427c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 3437c478bd9Sstevel@tonic-gate "%s: Unable to concatenate filter components", 3447c478bd9Sstevel@tonic-gate myself); 3457c478bd9Sstevel@tonic-gate freeLdapSearch(ls); 3467c478bd9Sstevel@tonic-gate return (0); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate if (dn != 0 && *dn == 0) { 3517c478bd9Sstevel@tonic-gate /* 3527c478bd9Sstevel@tonic-gate * The caller wants a DN, but we didn't get one from the 3537c478bd9Sstevel@tonic-gate * the rule set. We have an 'ls', so use it to ldapSearch() 3547c478bd9Sstevel@tonic-gate * for an entry from which we can extract the DN. 3557c478bd9Sstevel@tonic-gate */ 3567c478bd9Sstevel@tonic-gate __nis_rule_value_t *rvtmp; 3577c478bd9Sstevel@tonic-gate char **locDN; 3587c478bd9Sstevel@tonic-gate int nv = 0, numLocDN; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate rvtmp = ldapSearch(ls, &nv, 0, 0); 3617c478bd9Sstevel@tonic-gate locDN = findDNs(myself, rvtmp, nv, 0, &numLocDN); 3627c478bd9Sstevel@tonic-gate if (locDN != 0 && numLocDN == 1) { 3637c478bd9Sstevel@tonic-gate *dn = locDN[0]; 3647c478bd9Sstevel@tonic-gate sfree(locDN); 3657c478bd9Sstevel@tonic-gate } else { 3667c478bd9Sstevel@tonic-gate freeDNs(locDN, numLocDN); 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate freeRuleValue(rvtmp, nv); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate ls->useCon = 1; 3727c478bd9Sstevel@tonic-gate return (ls); 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate int ldapConnAttemptRetryTimeout = 60; /* seconds */ 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate typedef struct { 3787c478bd9Sstevel@tonic-gate LDAP *ld; 3797c478bd9Sstevel@tonic-gate mutex_t mutex; /* Mutex for update of structure */ 3807c478bd9Sstevel@tonic-gate pthread_t owner; /* Thread holding mutex */ 3817c478bd9Sstevel@tonic-gate mutex_t rcMutex; /* Mutex for refCount */ 3827c478bd9Sstevel@tonic-gate int refCount; /* Reference count */ 3837c478bd9Sstevel@tonic-gate int isBound; /* Is connection open and usable ? */ 3847c478bd9Sstevel@tonic-gate time_t retryTime; /* When should open be retried */ 3857c478bd9Sstevel@tonic-gate int status; /* Status of last operation */ 3867c478bd9Sstevel@tonic-gate int doDis; /* To be disconnected if refCount==0 */ 3877c478bd9Sstevel@tonic-gate int doDel; /* To be deleted if refCount zero */ 3887c478bd9Sstevel@tonic-gate int onList; /* True if on the 'ldapCon' list */ 3897c478bd9Sstevel@tonic-gate char *sp; /* server string */ 3907c478bd9Sstevel@tonic-gate char *who; 3917c478bd9Sstevel@tonic-gate char *cred; 3927c478bd9Sstevel@tonic-gate auth_method_t method; 3937c478bd9Sstevel@tonic-gate int port; 3947c478bd9Sstevel@tonic-gate struct timeval bindTimeout; 3957c478bd9Sstevel@tonic-gate struct timeval searchTimeout; 3967c478bd9Sstevel@tonic-gate struct timeval modifyTimeout; 3977c478bd9Sstevel@tonic-gate struct timeval addTimeout; 3987c478bd9Sstevel@tonic-gate struct timeval deleteTimeout; 3997c478bd9Sstevel@tonic-gate int simplePage; /* Can do simple-page */ 4007c478bd9Sstevel@tonic-gate int vlv; /* Can do VLV */ 4017c478bd9Sstevel@tonic-gate uint_t batchFrom; /* # entries read in one operation */ 4027c478bd9Sstevel@tonic-gate void *next; 4037c478bd9Sstevel@tonic-gate } __nis_ldap_conn_t; 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate /* 4067c478bd9Sstevel@tonic-gate * List of connections, 'ldapCon', protected by an RW lock. 4077c478bd9Sstevel@tonic-gate * 4087c478bd9Sstevel@tonic-gate * The following locking scheme is used: 4097c478bd9Sstevel@tonic-gate * 4107c478bd9Sstevel@tonic-gate * (1) Find a connection structure to use to talk to LDAP 4117c478bd9Sstevel@tonic-gate * Rlock list 4127c478bd9Sstevel@tonic-gate * Locate structure 4137c478bd9Sstevel@tonic-gate * Acquire 'mutex' 4147c478bd9Sstevel@tonic-gate * Acquire 'rcMutex' 4157c478bd9Sstevel@tonic-gate * update refCount 4167c478bd9Sstevel@tonic-gate * Release 'rcMutex' 4177c478bd9Sstevel@tonic-gate * release 'mutex' 4187c478bd9Sstevel@tonic-gate * Unlock list 4197c478bd9Sstevel@tonic-gate * Use structure 4207c478bd9Sstevel@tonic-gate * Release structure when done 4217c478bd9Sstevel@tonic-gate * (2) Insert/delete structure(s) on/from list 4227c478bd9Sstevel@tonic-gate * Wlock list 4237c478bd9Sstevel@tonic-gate * Insert/delete structure; if deleting, must 4247c478bd9Sstevel@tonic-gate * acquire 'mutex', and 'rcMutex' (in that order), 4257c478bd9Sstevel@tonic-gate * and 'refCount' must be zero. 4267c478bd9Sstevel@tonic-gate * Unlock list 4277c478bd9Sstevel@tonic-gate * (3) Modify structure 4287c478bd9Sstevel@tonic-gate * Find structure 4297c478bd9Sstevel@tonic-gate * Acquire 'mutex' 4307c478bd9Sstevel@tonic-gate * Modify (except refCount) 4317c478bd9Sstevel@tonic-gate * Release 'mutex' 4327c478bd9Sstevel@tonic-gate * Release structure 4337c478bd9Sstevel@tonic-gate */ 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate __nis_ldap_conn_t *ldapCon = 0; 4367c478bd9Sstevel@tonic-gate __nis_ldap_conn_t *ldapReferralCon = 0; 4377c478bd9Sstevel@tonic-gate static rwlock_t ldapConLock = DEFAULTRWLOCK; 4387c478bd9Sstevel@tonic-gate static rwlock_t referralConLock = DEFAULTRWLOCK; 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate void 4417c478bd9Sstevel@tonic-gate exclusiveLC(__nis_ldap_conn_t *lc) { 4427c478bd9Sstevel@tonic-gate pthread_t me = pthread_self(); 4437c478bd9Sstevel@tonic-gate int stat; 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate if (lc == 0) 4467c478bd9Sstevel@tonic-gate return; 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate stat = mutex_trylock(&lc->mutex); 4497c478bd9Sstevel@tonic-gate if (stat == EBUSY && lc->owner != me) 4507c478bd9Sstevel@tonic-gate mutex_lock(&lc->mutex); 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate lc->owner = me; 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate /* Return 1 if mutex held by this thread, 0 otherwise */ 4567c478bd9Sstevel@tonic-gate int 4577c478bd9Sstevel@tonic-gate assertExclusive(__nis_ldap_conn_t *lc) { 4587c478bd9Sstevel@tonic-gate pthread_t me; 4597c478bd9Sstevel@tonic-gate int stat; 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate if (lc == 0) 4627c478bd9Sstevel@tonic-gate return (0); 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate stat = mutex_trylock(&lc->mutex); 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if (stat == 0) { 4677c478bd9Sstevel@tonic-gate mutex_unlock(&lc->mutex); 4687c478bd9Sstevel@tonic-gate return (0); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate me = pthread_self(); 4727c478bd9Sstevel@tonic-gate if (stat != EBUSY || lc->owner != me) 4737c478bd9Sstevel@tonic-gate return (0); 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate return (1); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate void 4797c478bd9Sstevel@tonic-gate releaseLC(__nis_ldap_conn_t *lc) { 4807c478bd9Sstevel@tonic-gate pthread_t me = pthread_self(); 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate if (lc == 0 || lc->owner != me) 4837c478bd9Sstevel@tonic-gate return; 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate lc->owner = 0; 4867c478bd9Sstevel@tonic-gate (void) mutex_unlock(&lc->mutex); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate void 4907c478bd9Sstevel@tonic-gate incrementRC(__nis_ldap_conn_t *lc) { 4917c478bd9Sstevel@tonic-gate if (lc == 0) 4927c478bd9Sstevel@tonic-gate return; 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate (void) mutex_lock(&lc->rcMutex); 4957c478bd9Sstevel@tonic-gate lc->refCount++; 4967c478bd9Sstevel@tonic-gate (void) mutex_unlock(&lc->rcMutex); 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate void 5007c478bd9Sstevel@tonic-gate decrementRC(__nis_ldap_conn_t *lc) { 5017c478bd9Sstevel@tonic-gate if (lc == 0) 5027c478bd9Sstevel@tonic-gate return; 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate (void) mutex_lock(&lc->rcMutex); 5057c478bd9Sstevel@tonic-gate if (lc->refCount > 0) 5067c478bd9Sstevel@tonic-gate lc->refCount--; 5077c478bd9Sstevel@tonic-gate (void) mutex_unlock(&lc->rcMutex); 5087c478bd9Sstevel@tonic-gate } 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate /* Accept a server/port indication, and call ldap_init() */ 5117c478bd9Sstevel@tonic-gate static LDAP * 5127c478bd9Sstevel@tonic-gate ldapInit(char *srv, int port, bool_t use_ssl) { 5137c478bd9Sstevel@tonic-gate LDAP *ld; 5147c478bd9Sstevel@tonic-gate int ldapVersion = LDAP_VERSION3; 5157c478bd9Sstevel@tonic-gate int derefOption = LDAP_DEREF_ALWAYS; 5167c478bd9Sstevel@tonic-gate int timelimit = proxyInfo.search_time_limit; 5177c478bd9Sstevel@tonic-gate int sizelimit = proxyInfo.search_size_limit; 5187c478bd9Sstevel@tonic-gate char *myself = "ldapInit"; 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate if (srv == 0) 5217c478bd9Sstevel@tonic-gate return (0); 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate if (use_ssl) { 5247c478bd9Sstevel@tonic-gate ld = ldapssl_init(srv, port, 1); 5257c478bd9Sstevel@tonic-gate } else { 5267c478bd9Sstevel@tonic-gate ld = ldap_init(srv, port); 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate if (ld != 0) { 5307c478bd9Sstevel@tonic-gate (void) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, 5317c478bd9Sstevel@tonic-gate &ldapVersion); 5327c478bd9Sstevel@tonic-gate (void) ldap_set_option(ld, LDAP_OPT_DEREF, &derefOption); 5337c478bd9Sstevel@tonic-gate (void) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 5347c478bd9Sstevel@tonic-gate (void) ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &timelimit); 5357c478bd9Sstevel@tonic-gate (void) ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit); 5367c478bd9Sstevel@tonic-gate (void) ldap_set_option(ld, LDAP_OPT_REBIND_ARG, 0); 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate return (ld); 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate /* 5437c478bd9Sstevel@tonic-gate * Bind the specified LDAP structure per the supplied authentication. 5447c478bd9Sstevel@tonic-gate * Note: tested with none, simple, and digest_md5. May or may not 5457c478bd9Sstevel@tonic-gate * work with other authentication methods, mostly depending on whether 5467c478bd9Sstevel@tonic-gate * or not 'who' and 'cred' contain sufficient information. 5477c478bd9Sstevel@tonic-gate */ 5487c478bd9Sstevel@tonic-gate static int 5497c478bd9Sstevel@tonic-gate ldapBind(LDAP **ldP, char *who, char *cred, auth_method_t method, 5507c478bd9Sstevel@tonic-gate struct timeval timeout) { 5517c478bd9Sstevel@tonic-gate int ret; 5527c478bd9Sstevel@tonic-gate LDAP *ld; 5537c478bd9Sstevel@tonic-gate char *myself = "ldapBind"; 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate if (ldP == 0 || (ld = *ldP) == 0) 5567c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate if (method == none) { 5597c478bd9Sstevel@tonic-gate /* No ldap_bind() required (or even possible) */ 5607c478bd9Sstevel@tonic-gate ret = LDAP_SUCCESS; 5617c478bd9Sstevel@tonic-gate } else if (method == simple) { 5627c478bd9Sstevel@tonic-gate struct timeval tv; 5637c478bd9Sstevel@tonic-gate LDAPMessage *msg = 0; 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate tv = timeout; 5667c478bd9Sstevel@tonic-gate ret = ldap_bind(ld, who, cred, LDAP_AUTH_SIMPLE); 5677c478bd9Sstevel@tonic-gate if (ret != -1) { 5687c478bd9Sstevel@tonic-gate ret = ldap_result(ld, ret, 0, &tv, &msg); 5697c478bd9Sstevel@tonic-gate if (ret == 0) { 5707c478bd9Sstevel@tonic-gate ret = LDAP_TIMEOUT; 5717c478bd9Sstevel@tonic-gate } else if (ret == -1) { 5727c478bd9Sstevel@tonic-gate (void) ldap_get_option(ld, 5737c478bd9Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, 5747c478bd9Sstevel@tonic-gate &ret); 5757c478bd9Sstevel@tonic-gate } else { 5767c478bd9Sstevel@tonic-gate ret = ldap_result2error(ld, msg, 0); 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate if (msg != 0) 5797c478bd9Sstevel@tonic-gate (void) ldap_msgfree(msg); 5807c478bd9Sstevel@tonic-gate } else { 5817c478bd9Sstevel@tonic-gate (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, 5827c478bd9Sstevel@tonic-gate &ret); 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate } else if (method == cram_md5) { 5857c478bd9Sstevel@tonic-gate /* Note: there is only a synchronous call for cram-md5 */ 5867c478bd9Sstevel@tonic-gate struct berval ber_cred; 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate ber_cred.bv_len = strlen(cred); 5897c478bd9Sstevel@tonic-gate ber_cred.bv_val = cred; 5907c478bd9Sstevel@tonic-gate ret = ldap_sasl_cram_md5_bind_s(ld, who, &ber_cred, NULL, NULL); 5917c478bd9Sstevel@tonic-gate } else if (method == digest_md5) { 5927c478bd9Sstevel@tonic-gate /* Note: there is only a synchronous call for digest-md5 */ 5937c478bd9Sstevel@tonic-gate struct berval ber_cred; 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate ber_cred.bv_len = strlen(cred); 5967c478bd9Sstevel@tonic-gate ber_cred.bv_val = cred; 5977c478bd9Sstevel@tonic-gate ret = ldap_x_sasl_digest_md5_bind_s(ld, who, &ber_cred, NULL, 5987c478bd9Sstevel@tonic-gate NULL); 5997c478bd9Sstevel@tonic-gate } else { 6007c478bd9Sstevel@tonic-gate ret = LDAP_AUTH_METHOD_NOT_SUPPORTED; 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate if (ret != LDAP_SUCCESS) { 6047c478bd9Sstevel@tonic-gate (void) ldap_unbind_s(ld); 6057c478bd9Sstevel@tonic-gate *ldP = 0; 6067c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 6077c478bd9Sstevel@tonic-gate "%s: Unable to bind as: %s: %s", 6087c478bd9Sstevel@tonic-gate myself, who, ldap_err2string(ret)); 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate return (ret); 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate /* 6157c478bd9Sstevel@tonic-gate * Free 'lc' and all related memory. Caller must hold the exclusive lock. 6167c478bd9Sstevel@tonic-gate * Return LDAP_UNAVAILABLE upon success, in which case the caller mustn't 6177c478bd9Sstevel@tonic-gate * try to use the structure pointer in any way. 6187c478bd9Sstevel@tonic-gate */ 6197c478bd9Sstevel@tonic-gate static int 6207c478bd9Sstevel@tonic-gate freeCon(__nis_ldap_conn_t *lc) { 6217c478bd9Sstevel@tonic-gate char *myself = "freeCon"; 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate if (!assertExclusive(lc)) 6247c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate incrementRC(lc); 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate /* Must be unused, unbound, and not on the 'ldapCon' list */ 6297c478bd9Sstevel@tonic-gate if (lc->onList || lc->refCount != 1 || lc->isBound) { 6307c478bd9Sstevel@tonic-gate lc->doDel++; 6317c478bd9Sstevel@tonic-gate decrementRC(lc); 6327c478bd9Sstevel@tonic-gate return (LDAP_BUSY); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate sfree(lc->sp); 6367c478bd9Sstevel@tonic-gate sfree(lc->who); 6377c478bd9Sstevel@tonic-gate sfree(lc->cred); 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate /* Delete structure with both mutex:es held */ 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate free(lc); 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate return (LDAP_UNAVAILABLE); 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate /* 6477c478bd9Sstevel@tonic-gate * Disconnect the specified LDAP connection. Caller must have acquired 'mutex'. 6487c478bd9Sstevel@tonic-gate * 6497c478bd9Sstevel@tonic-gate * On return, if the status is LDAP_UNAVAILABLE, the caller must not touch 6507c478bd9Sstevel@tonic-gate * the structure in any way. 6517c478bd9Sstevel@tonic-gate */ 6527c478bd9Sstevel@tonic-gate static int 6537c478bd9Sstevel@tonic-gate disconnectCon(__nis_ldap_conn_t *lc) { 6547c478bd9Sstevel@tonic-gate int stat; 6557c478bd9Sstevel@tonic-gate char *myself = "disconnectCon"; 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate if (lc == 0) 6587c478bd9Sstevel@tonic-gate return (LDAP_SUCCESS); 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate if (!assertExclusive(lc)) 6617c478bd9Sstevel@tonic-gate return (LDAP_UNAVAILABLE); 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate if (lc->doDis) { 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate /* Increment refCount to protect against interference */ 6667c478bd9Sstevel@tonic-gate incrementRC(lc); 6677c478bd9Sstevel@tonic-gate /* refCount must be one (i.e., just us) */ 6687c478bd9Sstevel@tonic-gate if (lc->refCount != 1) { 6697c478bd9Sstevel@tonic-gate /* 6707c478bd9Sstevel@tonic-gate * In use; already marked for disconnect, 6717c478bd9Sstevel@tonic-gate * so do nothing. 6727c478bd9Sstevel@tonic-gate */ 6737c478bd9Sstevel@tonic-gate decrementRC(lc); 6747c478bd9Sstevel@tonic-gate return (LDAP_BUSY); 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate stat = ldap_unbind_s(lc->ld); 6787c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) { 6797c478bd9Sstevel@tonic-gate lc->ld = 0; 6807c478bd9Sstevel@tonic-gate lc->isBound = 0; 6817c478bd9Sstevel@tonic-gate lc->doDis = 0; 6827c478bd9Sstevel@tonic-gate /* Reset simple page and vlv indication */ 6837c478bd9Sstevel@tonic-gate lc->simplePage = 0; 6847c478bd9Sstevel@tonic-gate lc->vlv = 0; 6857c478bd9Sstevel@tonic-gate } else if (verbose) { 6867c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 6877c478bd9Sstevel@tonic-gate "%s: ldap_unbind_s() => %d (%s)", 6887c478bd9Sstevel@tonic-gate myself, stat, ldap_err2string(stat)); 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate decrementRC(lc); 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate if (lc->doDel) { 6957c478bd9Sstevel@tonic-gate if (LDAP_UNAVAILABLE == freeCon(lc)) 6967c478bd9Sstevel@tonic-gate stat = LDAP_UNAVAILABLE; 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate return (stat); 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate /* 7037c478bd9Sstevel@tonic-gate * controlSupported will determine for a given connection whether a set 7047c478bd9Sstevel@tonic-gate * of controls is supported or not. The input parameters: 7057c478bd9Sstevel@tonic-gate * lc The connection 7067c478bd9Sstevel@tonic-gate * ctrl A an array of OID strings, the terminal string should be NULL 7077c478bd9Sstevel@tonic-gate * The returned values if LDAP_SUCCESS is returned: 7087c478bd9Sstevel@tonic-gate * supported A caller supplied array which will be set to TRUE or 7097c478bd9Sstevel@tonic-gate * FALSE depending on whether the corresponding control 7107c478bd9Sstevel@tonic-gate * is reported as supported. 7117c478bd9Sstevel@tonic-gate * Returns LDAP_SUCCESS if the supportedControl attribute is read. 7127c478bd9Sstevel@tonic-gate */ 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate static int 7157c478bd9Sstevel@tonic-gate controlSupported(__nis_ldap_conn_t *lc, char **ctrl, bool_t *supported) { 7167c478bd9Sstevel@tonic-gate LDAPMessage *res, *e; 7177c478bd9Sstevel@tonic-gate char *attr[2], *a, **val; 7187c478bd9Sstevel@tonic-gate int stat, i; 7197c478bd9Sstevel@tonic-gate BerElement *ber = 0; 7207c478bd9Sstevel@tonic-gate char *myself = "controlSupported"; 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate attr[0] = "supportedControl"; 7237c478bd9Sstevel@tonic-gate attr[1] = 0; 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate stat = ldap_search_st(lc->ld, "", LDAP_SCOPE_BASE, "(objectclass=*)", 7267c478bd9Sstevel@tonic-gate attr, 0, &lc->searchTimeout, &res); 7277c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 7287c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 7297c478bd9Sstevel@tonic-gate "%s: Unable to retrieve supported control information for %s: %s", 7307c478bd9Sstevel@tonic-gate myself, NIL(lc->sp), ldap_err2string(stat)); 7317c478bd9Sstevel@tonic-gate return (stat); 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate e = ldap_first_entry(lc->ld, res); 7357c478bd9Sstevel@tonic-gate if (e != 0) { 7367c478bd9Sstevel@tonic-gate a = ldap_first_attribute(lc->ld, e, &ber); 7377c478bd9Sstevel@tonic-gate if (a != 0) { 7387c478bd9Sstevel@tonic-gate val = ldap_get_values(lc->ld, e, a); 7397c478bd9Sstevel@tonic-gate if (val == 0) { 7407c478bd9Sstevel@tonic-gate ldap_memfree(a); 7417c478bd9Sstevel@tonic-gate if (ber != 0) 7427c478bd9Sstevel@tonic-gate ber_free(ber, 0); 7437c478bd9Sstevel@tonic-gate } 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate } 7467c478bd9Sstevel@tonic-gate if (e == 0 || a == 0 || val == 0) { 7477c478bd9Sstevel@tonic-gate ldap_msgfree(res); 7487c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 7497c478bd9Sstevel@tonic-gate "%s: Unable to get root DSE for %s", 7507c478bd9Sstevel@tonic-gate myself, NIL(lc->sp)); 7517c478bd9Sstevel@tonic-gate return (LDAP_OPERATIONS_ERROR); 7527c478bd9Sstevel@tonic-gate } 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate while (*ctrl != NULL) { 7557c478bd9Sstevel@tonic-gate *supported = FALSE; 7567c478bd9Sstevel@tonic-gate for (i = 0; val[i] != 0; i++) { 7577c478bd9Sstevel@tonic-gate if (strstr(val[i], *ctrl) != 0) { 7587c478bd9Sstevel@tonic-gate *supported = TRUE; 7597c478bd9Sstevel@tonic-gate break; 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 7637c478bd9Sstevel@tonic-gate "%s: %s: %s: %s", 7647c478bd9Sstevel@tonic-gate myself, NIL(lc->sp), NIL(*ctrl), 7657c478bd9Sstevel@tonic-gate *supported ? "enabled" : "disabled"); 7667c478bd9Sstevel@tonic-gate ctrl++; 7677c478bd9Sstevel@tonic-gate supported++; 7687c478bd9Sstevel@tonic-gate } 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate ldap_value_free(val); 7717c478bd9Sstevel@tonic-gate ldap_memfree(a); 7727c478bd9Sstevel@tonic-gate if (ber != 0) 7737c478bd9Sstevel@tonic-gate ber_free(ber, 0); 7747c478bd9Sstevel@tonic-gate ldap_msgfree(res); 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate return (stat); 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate /* 7807c478bd9Sstevel@tonic-gate * Connect the LDAP connection 'lc'. Caller must have acquired the 'mutex', 7817c478bd9Sstevel@tonic-gate * and the refCount must be zero. 7827c478bd9Sstevel@tonic-gate * 7837c478bd9Sstevel@tonic-gate * On return, if the status is LDAP_UNAVAILABLE, the caller must not touch 7847c478bd9Sstevel@tonic-gate * the structure in any way. 7857c478bd9Sstevel@tonic-gate */ 7867c478bd9Sstevel@tonic-gate static int 7877c478bd9Sstevel@tonic-gate connectCon(__nis_ldap_conn_t *lc, int check_ctrl) { 7887c478bd9Sstevel@tonic-gate struct timeval tp; 7897c478bd9Sstevel@tonic-gate int stat; 7907c478bd9Sstevel@tonic-gate bool_t supported[2] = {FALSE, FALSE}; 7917c478bd9Sstevel@tonic-gate char *ctrl[3] = {LDAP_CONTROL_SIMPLE_PAGE, 7927c478bd9Sstevel@tonic-gate LDAP_CONTROL_VLVREQUEST, 7937c478bd9Sstevel@tonic-gate NULL}; 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate if (lc == 0) 7967c478bd9Sstevel@tonic-gate return (LDAP_SUCCESS); 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate if (!assertExclusive(lc)) 7997c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate incrementRC(lc); 8027c478bd9Sstevel@tonic-gate if (lc->refCount != 1) { 8037c478bd9Sstevel@tonic-gate /* 8047c478bd9Sstevel@tonic-gate * Don't want to step on structure when it's used by someone 8057c478bd9Sstevel@tonic-gate * else. 8067c478bd9Sstevel@tonic-gate */ 8077c478bd9Sstevel@tonic-gate decrementRC(lc); 8087c478bd9Sstevel@tonic-gate return (LDAP_BUSY); 8097c478bd9Sstevel@tonic-gate } 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate (void) gettimeofday(&tp, 0); 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate if (lc->ld != 0) { 8147c478bd9Sstevel@tonic-gate /* Try to disconnect */ 8157c478bd9Sstevel@tonic-gate lc->doDis++; 8167c478bd9Sstevel@tonic-gate decrementRC(lc); 8177c478bd9Sstevel@tonic-gate /* disconnctCon() will do the delete if required */ 8187c478bd9Sstevel@tonic-gate stat = disconnectCon(lc); 8197c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) 8207c478bd9Sstevel@tonic-gate return (stat); 8217c478bd9Sstevel@tonic-gate incrementRC(lc); 8227c478bd9Sstevel@tonic-gate if (lc->refCount != 1 || lc->ld != 0) { 8237c478bd9Sstevel@tonic-gate decrementRC(lc); 8247c478bd9Sstevel@tonic-gate return (lc->ld != 0) ? LDAP_SUCCESS : 8257c478bd9Sstevel@tonic-gate LDAP_BUSY; 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate } else if (tp.tv_sec < lc->retryTime) { 8287c478bd9Sstevel@tonic-gate /* Too early to retry connect */ 8297c478bd9Sstevel@tonic-gate decrementRC(lc); 8307c478bd9Sstevel@tonic-gate return (LDAP_SERVER_DOWN); 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate /* Set new retry time in case we fail below */ 8347c478bd9Sstevel@tonic-gate lc->retryTime = tp.tv_sec + ldapConnAttemptRetryTimeout; 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate lc->ld = ldapInit(lc->sp, lc->port, proxyInfo.tls_method != no_tls); 8377c478bd9Sstevel@tonic-gate if (lc->ld == 0) { 8387c478bd9Sstevel@tonic-gate decrementRC(lc); 8397c478bd9Sstevel@tonic-gate return (LDAP_LOCAL_ERROR); 8407c478bd9Sstevel@tonic-gate } 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate stat = lc->status = ldapBind(&lc->ld, lc->who, lc->cred, lc->method, 8437c478bd9Sstevel@tonic-gate lc->bindTimeout); 8447c478bd9Sstevel@tonic-gate if (lc->status == LDAP_SUCCESS) { 8457c478bd9Sstevel@tonic-gate lc->isBound = 1; 8467c478bd9Sstevel@tonic-gate lc->retryTime = 0; 8477c478bd9Sstevel@tonic-gate if (check_ctrl) { 8487c478bd9Sstevel@tonic-gate (void) controlSupported(lc, ctrl, supported); 8497c478bd9Sstevel@tonic-gate lc->simplePage = supported[0]; 8507c478bd9Sstevel@tonic-gate lc->vlv = supported[1]; 8517c478bd9Sstevel@tonic-gate lc->batchFrom = 50000; 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate decrementRC(lc); 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate return (stat); 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate /* 8617c478bd9Sstevel@tonic-gate * Find and return a connection believed to be OK. 8627c478bd9Sstevel@tonic-gate */ 8637c478bd9Sstevel@tonic-gate static __nis_ldap_conn_t * 8647c478bd9Sstevel@tonic-gate findCon(int *stat) { 8657c478bd9Sstevel@tonic-gate __nis_ldap_conn_t *lc; 8667c478bd9Sstevel@tonic-gate int ldapStat; 8677c478bd9Sstevel@tonic-gate char *myself = "findCon"; 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate if (stat == 0) 8707c478bd9Sstevel@tonic-gate stat = &ldapStat; 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ldapConLock); 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate if (ldapCon == 0) { 8757c478bd9Sstevel@tonic-gate /* Probably first call; try to set up the connection list */ 8767c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldapConLock); 8777c478bd9Sstevel@tonic-gate if ((*stat = setupConList(proxyInfo.default_servers, 8787c478bd9Sstevel@tonic-gate proxyInfo.proxy_dn, 8797c478bd9Sstevel@tonic-gate proxyInfo.proxy_passwd, 8807c478bd9Sstevel@tonic-gate proxyInfo.auth_method)) != 8817c478bd9Sstevel@tonic-gate LDAP_SUCCESS) 8827c478bd9Sstevel@tonic-gate return (0); 8837c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ldapConLock); 8847c478bd9Sstevel@tonic-gate } 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate for (lc = ldapCon; lc != 0; lc = lc->next) { 8877c478bd9Sstevel@tonic-gate exclusiveLC(lc); 8887c478bd9Sstevel@tonic-gate if (!lc->isBound) { 8897c478bd9Sstevel@tonic-gate *stat = connectCon(lc, 1); 8907c478bd9Sstevel@tonic-gate if (*stat != LDAP_SUCCESS) { 8917c478bd9Sstevel@tonic-gate if (*stat != LDAP_UNAVAILABLE) { 8927c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 8937c478bd9Sstevel@tonic-gate "%s: Cannot open connection to LDAP server (%s): %s", 8947c478bd9Sstevel@tonic-gate myself, NIL(lc->sp), 8957c478bd9Sstevel@tonic-gate ldap_err2string(*stat)); 8967c478bd9Sstevel@tonic-gate releaseLC(lc); 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate continue; 8997c478bd9Sstevel@tonic-gate } 9007c478bd9Sstevel@tonic-gate } else if (lc->doDis || lc->doDel) { 9017c478bd9Sstevel@tonic-gate *stat = disconnectCon(lc); 9027c478bd9Sstevel@tonic-gate if (*stat != LDAP_UNAVAILABLE) 9037c478bd9Sstevel@tonic-gate releaseLC(lc); 9047c478bd9Sstevel@tonic-gate continue; 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate incrementRC(lc); 9077c478bd9Sstevel@tonic-gate releaseLC(lc); 9087c478bd9Sstevel@tonic-gate break; 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldapConLock); 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate return (lc); 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate /* Release connection; decrements ref count for the connection */ 9177c478bd9Sstevel@tonic-gate static void 9187c478bd9Sstevel@tonic-gate releaseCon(__nis_ldap_conn_t *lc, int status) { 9197c478bd9Sstevel@tonic-gate int stat; 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate if (lc == 0) 9227c478bd9Sstevel@tonic-gate return; 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate exclusiveLC(lc); 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate lc->status = status; 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate decrementRC(lc); 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate if (lc->doDis) 9317c478bd9Sstevel@tonic-gate stat = disconnectCon(lc); 9327c478bd9Sstevel@tonic-gate else 9337c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate if (stat != LDAP_UNAVAILABLE) 9367c478bd9Sstevel@tonic-gate releaseLC(lc); 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate static __nis_ldap_conn_t * 9407c478bd9Sstevel@tonic-gate createCon(char *sp, char *who, char *cred, auth_method_t method, int port) { 9417c478bd9Sstevel@tonic-gate __nis_ldap_conn_t *lc; 9427c478bd9Sstevel@tonic-gate char *myself = "createCon"; 9437c478bd9Sstevel@tonic-gate char *r; 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate if (sp == 0) 9467c478bd9Sstevel@tonic-gate return (0); 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate lc = am(myself, sizeof (*lc)); 9497c478bd9Sstevel@tonic-gate if (lc == 0) 9507c478bd9Sstevel@tonic-gate return (0); 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate (void) mutex_init(&lc->mutex, 0, 0); 9537c478bd9Sstevel@tonic-gate (void) mutex_init(&lc->rcMutex, 0, 0); 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate /* If we need to delete 'lc', freeCon() wants the mutex held */ 9567c478bd9Sstevel@tonic-gate exclusiveLC(lc); 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate lc->sp = sdup(myself, T, sp); 9597c478bd9Sstevel@tonic-gate if (lc->sp == 0) { 9607c478bd9Sstevel@tonic-gate (void) freeCon(lc); 9617c478bd9Sstevel@tonic-gate return (0); 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate if ((r = strchr(lc->sp, ']')) != 0) { 9657c478bd9Sstevel@tonic-gate /* 9667c478bd9Sstevel@tonic-gate * IPv6 address. Does libldap want this with the 9677c478bd9Sstevel@tonic-gate * '[' and ']' left in place ? Assume so for now. 9687c478bd9Sstevel@tonic-gate */ 9697c478bd9Sstevel@tonic-gate r = strchr(r, ':'); 9707c478bd9Sstevel@tonic-gate } else { 9717c478bd9Sstevel@tonic-gate r = strchr(lc->sp, ':'); 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate if (r != NULL) { 9757c478bd9Sstevel@tonic-gate *r++ = '\0'; 9767c478bd9Sstevel@tonic-gate port = atoi(r); 9777c478bd9Sstevel@tonic-gate } else if (port == 0) 9787c478bd9Sstevel@tonic-gate port = proxyInfo.tls_method == ssl_tls ? LDAPS_PORT : LDAP_PORT; 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate if (who != 0) { 9817c478bd9Sstevel@tonic-gate lc->who = sdup(myself, T, who); 9827c478bd9Sstevel@tonic-gate if (lc->who == 0) { 9837c478bd9Sstevel@tonic-gate (void) freeCon(lc); 9847c478bd9Sstevel@tonic-gate return (0); 9857c478bd9Sstevel@tonic-gate } 9867c478bd9Sstevel@tonic-gate } 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate if (cred != 0) { 9897c478bd9Sstevel@tonic-gate lc->cred = sdup(myself, T, cred); 9907c478bd9Sstevel@tonic-gate if (lc->cred == 0) { 9917c478bd9Sstevel@tonic-gate (void) freeCon(lc); 9927c478bd9Sstevel@tonic-gate return (0); 9937c478bd9Sstevel@tonic-gate } 9947c478bd9Sstevel@tonic-gate } 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate lc->method = method; 9977c478bd9Sstevel@tonic-gate lc->port = port; 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate lc->bindTimeout = proxyInfo.bind_timeout; 10007c478bd9Sstevel@tonic-gate lc->searchTimeout = proxyInfo.search_timeout; 10017c478bd9Sstevel@tonic-gate lc->modifyTimeout = proxyInfo.modify_timeout; 10027c478bd9Sstevel@tonic-gate lc->addTimeout = proxyInfo.add_timeout; 10037c478bd9Sstevel@tonic-gate lc->deleteTimeout = proxyInfo.delete_timeout; 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate /* All other fields OK at zero */ 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate releaseLC(lc); 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate return (lc); 10107c478bd9Sstevel@tonic-gate } 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate static int 10137c478bd9Sstevel@tonic-gate setupConList(char *serverList, char *who, char *cred, auth_method_t method) { 10147c478bd9Sstevel@tonic-gate char *sls, *sl, *s, *e; 10157c478bd9Sstevel@tonic-gate __nis_ldap_conn_t *lc, *tmp; 10167c478bd9Sstevel@tonic-gate char *myself = "setupConList"; 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate if (serverList == 0) 10197c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ldapConLock); 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate if (ldapCon != 0) { 10247c478bd9Sstevel@tonic-gate /* Assume we've already been called and done the set-up */ 10257c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldapConLock); 10267c478bd9Sstevel@tonic-gate return (LDAP_SUCCESS); 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate /* Work on a copy of 'serverList' */ 10307c478bd9Sstevel@tonic-gate sl = sls = sdup(myself, T, serverList); 10317c478bd9Sstevel@tonic-gate if (sl == 0) { 10327c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldapConLock); 10337c478bd9Sstevel@tonic-gate return (LDAP_NO_MEMORY); 10347c478bd9Sstevel@tonic-gate } 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate /* Remove leading white space */ 10377c478bd9Sstevel@tonic-gate for (0; *sl == ' ' || *sl == '\t'; sl++); 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate /* Create connection for each server on the list */ 10407c478bd9Sstevel@tonic-gate for (s = sl; *s != '\0'; s = e+1) { 10417c478bd9Sstevel@tonic-gate int l; 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate /* Find end of server/port token */ 10447c478bd9Sstevel@tonic-gate for (e = s; *e != ' ' && *e != '\t' && *e != '\0'; e++); 10457c478bd9Sstevel@tonic-gate if (*e != '\0') 10467c478bd9Sstevel@tonic-gate *e = '\0'; 10477c478bd9Sstevel@tonic-gate else 10487c478bd9Sstevel@tonic-gate e--; 10497c478bd9Sstevel@tonic-gate l = slen(s); 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate if (l > 0) { 10527c478bd9Sstevel@tonic-gate lc = createCon(s, who, cred, method, 0); 10537c478bd9Sstevel@tonic-gate if (lc == 0) { 10547c478bd9Sstevel@tonic-gate free(sls); 10557c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldapConLock); 10567c478bd9Sstevel@tonic-gate return (LDAP_NO_MEMORY); 10577c478bd9Sstevel@tonic-gate } 10587c478bd9Sstevel@tonic-gate lc->onList = 1; 10597c478bd9Sstevel@tonic-gate if (ldapCon == 0) { 10607c478bd9Sstevel@tonic-gate ldapCon = lc; 10617c478bd9Sstevel@tonic-gate } else { 10627c478bd9Sstevel@tonic-gate /* Insert at end of list */ 10637c478bd9Sstevel@tonic-gate for (tmp = ldapCon; tmp->next != 0; 10647c478bd9Sstevel@tonic-gate tmp = tmp->next); 10657c478bd9Sstevel@tonic-gate tmp->next = lc; 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate } 10687c478bd9Sstevel@tonic-gate } 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate free(sls); 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldapConLock); 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate return (LDAP_SUCCESS); 10757c478bd9Sstevel@tonic-gate } 10767c478bd9Sstevel@tonic-gate 10777c478bd9Sstevel@tonic-gate static bool_t 10787c478bd9Sstevel@tonic-gate is_same_connection(__nis_ldap_conn_t *lc, LDAPURLDesc *ludpp) 10797c478bd9Sstevel@tonic-gate { 10807c478bd9Sstevel@tonic-gate return (strcasecmp(ludpp->lud_host, lc->sp) == 0 && 10817c478bd9Sstevel@tonic-gate ludpp->lud_port == lc->port); 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate 10847c478bd9Sstevel@tonic-gate static __nis_ldap_conn_t * 10857c478bd9Sstevel@tonic-gate find_connection_from_list(__nis_ldap_conn_t *list, 10867c478bd9Sstevel@tonic-gate LDAPURLDesc *ludpp, int *stat) 10877c478bd9Sstevel@tonic-gate { 10887c478bd9Sstevel@tonic-gate int ldapStat; 10897c478bd9Sstevel@tonic-gate __nis_ldap_conn_t *lc = NULL; 10907c478bd9Sstevel@tonic-gate if (stat == 0) 10917c478bd9Sstevel@tonic-gate stat = &ldapStat; 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate *stat = LDAP_SUCCESS; 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate for (lc = list; lc != 0; lc = lc->next) { 10967c478bd9Sstevel@tonic-gate exclusiveLC(lc); 10977c478bd9Sstevel@tonic-gate if (is_same_connection(lc, ludpp)) { 10987c478bd9Sstevel@tonic-gate if (!lc->isBound) { 10997c478bd9Sstevel@tonic-gate *stat = connectCon(lc, 1); 11007c478bd9Sstevel@tonic-gate if (*stat != LDAP_SUCCESS) { 11017c478bd9Sstevel@tonic-gate releaseLC(lc); 11027c478bd9Sstevel@tonic-gate continue; 11037c478bd9Sstevel@tonic-gate } 11047c478bd9Sstevel@tonic-gate } else if (lc->doDis || lc->doDel) { 11057c478bd9Sstevel@tonic-gate (void) disconnectCon(lc); 11067c478bd9Sstevel@tonic-gate releaseLC(lc); 11077c478bd9Sstevel@tonic-gate continue; 11087c478bd9Sstevel@tonic-gate } 11097c478bd9Sstevel@tonic-gate incrementRC(lc); 11107c478bd9Sstevel@tonic-gate releaseLC(lc); 11117c478bd9Sstevel@tonic-gate break; 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate releaseLC(lc); 11147c478bd9Sstevel@tonic-gate } 11157c478bd9Sstevel@tonic-gate return (lc); 11167c478bd9Sstevel@tonic-gate } 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate static __nis_ldap_conn_t * 11197c478bd9Sstevel@tonic-gate findReferralCon(char **referralsp, int *stat) 11207c478bd9Sstevel@tonic-gate { 11217c478bd9Sstevel@tonic-gate __nis_ldap_conn_t *lc = NULL; 11227c478bd9Sstevel@tonic-gate __nis_ldap_conn_t *tmp; 11237c478bd9Sstevel@tonic-gate int ldapStat; 11247c478bd9Sstevel@tonic-gate int i; 11257c478bd9Sstevel@tonic-gate LDAPURLDesc *ludpp = NULL; 11267c478bd9Sstevel@tonic-gate char *myself = "findReferralCon"; 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate if (stat == 0) 11297c478bd9Sstevel@tonic-gate stat = &ldapStat; 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate *stat = LDAP_SUCCESS; 11327c478bd9Sstevel@tonic-gate 11337c478bd9Sstevel@tonic-gate /* 11347c478bd9Sstevel@tonic-gate * We have the referral lock - to prevent multiple 11357c478bd9Sstevel@tonic-gate * threads from creating a referred connection simultaneously 11367c478bd9Sstevel@tonic-gate * 11377c478bd9Sstevel@tonic-gate * Note that this code assumes that the ldapCon list is a 11387c478bd9Sstevel@tonic-gate * static list - that it has previously been created 11397c478bd9Sstevel@tonic-gate * (otherwise we wouldn't have gotten a referral) and that 11407c478bd9Sstevel@tonic-gate * it will neither grow or shrink - elements may have new 11417c478bd9Sstevel@tonic-gate * connections or unbound. If this assumption is no longer valid, 11427c478bd9Sstevel@tonic-gate * the locking needs to be reworked. 11437c478bd9Sstevel@tonic-gate */ 11447c478bd9Sstevel@tonic-gate (void) rw_rdlock(&referralConLock); 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate for (i = 0; referralsp[i] != NULL; i++) { 11477c478bd9Sstevel@tonic-gate if (ldap_url_parse(referralsp[i], &ludpp) != LDAP_SUCCESS) 11487c478bd9Sstevel@tonic-gate continue; 11497c478bd9Sstevel@tonic-gate /* Ignore referrals if not at the appropriate tls level */ 11507c478bd9Sstevel@tonic-gate #ifdef LDAP_URL_OPT_SECURE 11517c478bd9Sstevel@tonic-gate if (ludpp->lud_options & LDAP_URL_OPT_SECURE) { 11527c478bd9Sstevel@tonic-gate if (proxyInfo.tls_method != ssl_tls) { 11537c478bd9Sstevel@tonic-gate ldap_free_urldesc(ludpp); 11547c478bd9Sstevel@tonic-gate continue; 11557c478bd9Sstevel@tonic-gate } 11567c478bd9Sstevel@tonic-gate } else { 11577c478bd9Sstevel@tonic-gate if (proxyInfo.tls_method != no_tls) { 11587c478bd9Sstevel@tonic-gate ldap_free_urldesc(ludpp); 11597c478bd9Sstevel@tonic-gate continue; 11607c478bd9Sstevel@tonic-gate } 11617c478bd9Sstevel@tonic-gate } 11627c478bd9Sstevel@tonic-gate #endif 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate /* Determine if we already have a connection to the server */ 11657c478bd9Sstevel@tonic-gate lc = find_connection_from_list(ldapReferralCon, ludpp, stat); 11667c478bd9Sstevel@tonic-gate if (lc == NULL) 11677c478bd9Sstevel@tonic-gate lc = find_connection_from_list(ldapCon, ludpp, stat); 11687c478bd9Sstevel@tonic-gate ldap_free_urldesc(ludpp); 11697c478bd9Sstevel@tonic-gate if (lc != NULL) { 11707c478bd9Sstevel@tonic-gate (void) rw_unlock(&referralConLock); 11717c478bd9Sstevel@tonic-gate return (lc); 11727c478bd9Sstevel@tonic-gate } 11737c478bd9Sstevel@tonic-gate } 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate for (i = 0; referralsp[i] != NULL; i++) { 11767c478bd9Sstevel@tonic-gate if (ldap_url_parse(referralsp[i], &ludpp) != LDAP_SUCCESS) 11777c478bd9Sstevel@tonic-gate continue; 11787c478bd9Sstevel@tonic-gate /* Ignore referrals if not at the appropriate tls level */ 11797c478bd9Sstevel@tonic-gate #ifdef LDAP_URL_OPT_SECURE 11807c478bd9Sstevel@tonic-gate if (ludpp->lud_options & LDAP_URL_OPT_SECURE) { 11817c478bd9Sstevel@tonic-gate if (proxyInfo.tls_method != ssl_tls) { 11827c478bd9Sstevel@tonic-gate ldap_free_urldesc(ludpp); 11837c478bd9Sstevel@tonic-gate continue; 11847c478bd9Sstevel@tonic-gate } 11857c478bd9Sstevel@tonic-gate } else { 11867c478bd9Sstevel@tonic-gate if (proxyInfo.tls_method != no_tls) { 11877c478bd9Sstevel@tonic-gate ldap_free_urldesc(ludpp); 11887c478bd9Sstevel@tonic-gate continue; 11897c478bd9Sstevel@tonic-gate } 11907c478bd9Sstevel@tonic-gate } 11917c478bd9Sstevel@tonic-gate #endif 11927c478bd9Sstevel@tonic-gate lc = createCon(ludpp->lud_host, proxyInfo.proxy_dn, 11937c478bd9Sstevel@tonic-gate proxyInfo.proxy_passwd, 11947c478bd9Sstevel@tonic-gate proxyInfo.auth_method, 11957c478bd9Sstevel@tonic-gate ludpp->lud_port); 11967c478bd9Sstevel@tonic-gate if (lc == 0) { 11977c478bd9Sstevel@tonic-gate ldap_free_urldesc(ludpp); 11987c478bd9Sstevel@tonic-gate (void) rw_unlock(&referralConLock); 11997c478bd9Sstevel@tonic-gate *stat = LDAP_NO_MEMORY; 12007c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 12017c478bd9Sstevel@tonic-gate "%s: Could not connect to host: %s", 12027c478bd9Sstevel@tonic-gate myself, NIL(ludpp->lud_host)); 12037c478bd9Sstevel@tonic-gate return (NULL); 12047c478bd9Sstevel@tonic-gate } 12057c478bd9Sstevel@tonic-gate 12067c478bd9Sstevel@tonic-gate lc->onList = 1; 12077c478bd9Sstevel@tonic-gate if (ldapReferralCon == 0) { 12087c478bd9Sstevel@tonic-gate ldapReferralCon = lc; 12097c478bd9Sstevel@tonic-gate } else { 12107c478bd9Sstevel@tonic-gate /* Insert at end of list */ 12117c478bd9Sstevel@tonic-gate for (tmp = ldapReferralCon; tmp->next != 0; 12127c478bd9Sstevel@tonic-gate tmp = tmp->next) {} 12137c478bd9Sstevel@tonic-gate tmp->next = lc; 12147c478bd9Sstevel@tonic-gate } 12157c478bd9Sstevel@tonic-gate lc = find_connection_from_list(ldapReferralCon, ludpp, stat); 12167c478bd9Sstevel@tonic-gate ldap_free_urldesc(ludpp); 12177c478bd9Sstevel@tonic-gate if (lc != NULL) 12187c478bd9Sstevel@tonic-gate break; 12197c478bd9Sstevel@tonic-gate } 12207c478bd9Sstevel@tonic-gate (void) rw_unlock(&referralConLock); 12217c478bd9Sstevel@tonic-gate if (lc == NULL) { 12227c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 12237c478bd9Sstevel@tonic-gate "%s: Could not find a connection to %s, ...", 12247c478bd9Sstevel@tonic-gate myself, NIL(referralsp[0])); 12257c478bd9Sstevel@tonic-gate } 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate return (lc); 12287c478bd9Sstevel@tonic-gate } 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate /* 12317c478bd9Sstevel@tonic-gate * Find and return a connection believed to be OK and ensure children 12327c478bd9Sstevel@tonic-gate * will never use parent's connection. 12337c478bd9Sstevel@tonic-gate */ 12347c478bd9Sstevel@tonic-gate static __nis_ldap_conn_t * 12357c478bd9Sstevel@tonic-gate findYPCon(__nis_ldap_search_t *ls, int *stat) { 12367c478bd9Sstevel@tonic-gate __nis_ldap_conn_t *lc, *newlc; 12377c478bd9Sstevel@tonic-gate int ldapStat, newstat; 12387c478bd9Sstevel@tonic-gate char *myself = "findYPCon"; 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate if (stat == 0) 12417c478bd9Sstevel@tonic-gate stat = &ldapStat; 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ldapConLock); 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate if (ldapCon == 0) { 12467c478bd9Sstevel@tonic-gate /* Probably first call; try to set up the connection list */ 12477c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldapConLock); 12487c478bd9Sstevel@tonic-gate if ((*stat = setupConList(proxyInfo.default_servers, 12497c478bd9Sstevel@tonic-gate proxyInfo.proxy_dn, 12507c478bd9Sstevel@tonic-gate proxyInfo.proxy_passwd, 12517c478bd9Sstevel@tonic-gate proxyInfo.auth_method)) != 12527c478bd9Sstevel@tonic-gate LDAP_SUCCESS) 12537c478bd9Sstevel@tonic-gate return (0); 12547c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ldapConLock); 12557c478bd9Sstevel@tonic-gate } 12567c478bd9Sstevel@tonic-gate 12577c478bd9Sstevel@tonic-gate for (lc = ldapCon; lc != 0; lc = lc->next) { 12587c478bd9Sstevel@tonic-gate exclusiveLC(lc); 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate if (lc->isBound && (lc->doDis || lc->doDel)) { 12617c478bd9Sstevel@tonic-gate *stat = disconnectCon(lc); 12627c478bd9Sstevel@tonic-gate if (*stat != LDAP_UNAVAILABLE) 12637c478bd9Sstevel@tonic-gate releaseLC(lc); 12647c478bd9Sstevel@tonic-gate continue; 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate /* 12687c478bd9Sstevel@tonic-gate * Use a new connection for all cases except when 12697c478bd9Sstevel@tonic-gate * requested by the main thread in the parent ypserv 12707c478bd9Sstevel@tonic-gate * process. 12717c478bd9Sstevel@tonic-gate */ 12727c478bd9Sstevel@tonic-gate if (ls->useCon == 0) { 12737c478bd9Sstevel@tonic-gate newlc = createCon(lc->sp, lc->who, lc->cred, 12747c478bd9Sstevel@tonic-gate lc->method, lc->port); 12757c478bd9Sstevel@tonic-gate if (!newlc) { 12767c478bd9Sstevel@tonic-gate releaseLC(lc); 12777c478bd9Sstevel@tonic-gate continue; 12787c478bd9Sstevel@tonic-gate } 12797c478bd9Sstevel@tonic-gate if (lc->ld != 0) { 12807c478bd9Sstevel@tonic-gate newlc->simplePage = lc->simplePage; 12817c478bd9Sstevel@tonic-gate newlc->vlv = lc->vlv; 12827c478bd9Sstevel@tonic-gate newlc->batchFrom = lc->batchFrom; 12837c478bd9Sstevel@tonic-gate } 12847c478bd9Sstevel@tonic-gate releaseLC(lc); 12857c478bd9Sstevel@tonic-gate exclusiveLC(newlc); 12867c478bd9Sstevel@tonic-gate newstat = connectCon(newlc, 0); 12877c478bd9Sstevel@tonic-gate if (newstat != LDAP_SUCCESS) { 12887c478bd9Sstevel@tonic-gate if (newstat != LDAP_UNAVAILABLE) { 12897c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 12907c478bd9Sstevel@tonic-gate "%s: Cannot open connection to LDAP server (%s): %s", 12917c478bd9Sstevel@tonic-gate myself, NIL(newlc->sp), 12927c478bd9Sstevel@tonic-gate ldap_err2string(*stat)); 12937c478bd9Sstevel@tonic-gate } 12947c478bd9Sstevel@tonic-gate (void) freeCon(newlc); 12957c478bd9Sstevel@tonic-gate newlc = 0; 12967c478bd9Sstevel@tonic-gate continue; 12977c478bd9Sstevel@tonic-gate } 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate /* 13007c478bd9Sstevel@tonic-gate * No need to put newlc on the ldapCon list as this 13017c478bd9Sstevel@tonic-gate * connection will be freed after use. 13027c478bd9Sstevel@tonic-gate */ 13037c478bd9Sstevel@tonic-gate newlc->onList = 0; 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate lc = newlc; 13067c478bd9Sstevel@tonic-gate } else if (!lc->isBound) { 13077c478bd9Sstevel@tonic-gate *stat = connectCon(lc, 1); 13087c478bd9Sstevel@tonic-gate if (*stat != LDAP_SUCCESS) { 13097c478bd9Sstevel@tonic-gate if (*stat != LDAP_UNAVAILABLE) { 13107c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 13117c478bd9Sstevel@tonic-gate "%s: Cannot open connection to LDAP server (%s): %s", 13127c478bd9Sstevel@tonic-gate myself, NIL(lc->sp), 13137c478bd9Sstevel@tonic-gate ldap_err2string(*stat)); 13147c478bd9Sstevel@tonic-gate releaseLC(lc); 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate continue; 13177c478bd9Sstevel@tonic-gate } 13187c478bd9Sstevel@tonic-gate } 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate incrementRC(lc); 13217c478bd9Sstevel@tonic-gate releaseLC(lc); 13227c478bd9Sstevel@tonic-gate break; 13237c478bd9Sstevel@tonic-gate } 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldapConLock); 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate return (lc); 13287c478bd9Sstevel@tonic-gate } 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate #define SORTKEYLIST "cn uid" 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate /* 13337c478bd9Sstevel@tonic-gate * Perform an LDAP search operation per 'ls', adding the result(s) to 13347c478bd9Sstevel@tonic-gate * a copy of the 'rvIn' structure; the copy becomes the return value. 13357c478bd9Sstevel@tonic-gate * The caller must deallocate both 'rvIn' and the result, if any. 13367c478bd9Sstevel@tonic-gate * 13377c478bd9Sstevel@tonic-gate * On entry, '*numValues' contains a hint regarding the expected 13387c478bd9Sstevel@tonic-gate * number of entries. Zero is the same as one, and negative values 13397c478bd9Sstevel@tonic-gate * imply no information. This is used to decide whether or not to 13407c478bd9Sstevel@tonic-gate * try an indexed search. 13417c478bd9Sstevel@tonic-gate * 13427c478bd9Sstevel@tonic-gate * On successful (non-NULL) return, '*numValues' contains the number 13437c478bd9Sstevel@tonic-gate * of __nis_rule_value_t elements in the returned array, and '*stat' 13447c478bd9Sstevel@tonic-gate * the LDAP operations status. 13457c478bd9Sstevel@tonic-gate */ 13467c478bd9Sstevel@tonic-gate __nis_rule_value_t * 13477c478bd9Sstevel@tonic-gate ldapSearch(__nis_ldap_search_t *ls, int *numValues, __nis_rule_value_t *rvIn, 13487c478bd9Sstevel@tonic-gate int *ldapStat) { 13497c478bd9Sstevel@tonic-gate __nis_rule_value_t *rv = 0; 13507c478bd9Sstevel@tonic-gate int stat, numEntries, numVals, tnv, done, lprEc; 13517c478bd9Sstevel@tonic-gate LDAPMessage *msg = 0, *m; 13527c478bd9Sstevel@tonic-gate __nis_ldap_conn_t *lc; 13537c478bd9Sstevel@tonic-gate struct timeval tv, start, now; 13547c478bd9Sstevel@tonic-gate LDAPsortkey **sortKeyList = 0; 13557c478bd9Sstevel@tonic-gate LDAPControl *ctrls[3], *sortCtrl = 0, *vlvCtrl = 0; 13567c478bd9Sstevel@tonic-gate LDAPControl **retCtrls = 0; 13577c478bd9Sstevel@tonic-gate LDAPVirtualList vList; 13587c478bd9Sstevel@tonic-gate struct berval *spCookie = 0; 13597c478bd9Sstevel@tonic-gate int doVLV = 0; 13607c478bd9Sstevel@tonic-gate int doSP = 0; 13617c478bd9Sstevel@tonic-gate long index; 13627c478bd9Sstevel@tonic-gate char *myself = "ldapSearch"; 13637c478bd9Sstevel@tonic-gate bool_t follow_referral = 13647c478bd9Sstevel@tonic-gate proxyInfo.follow_referral == follow; 13657c478bd9Sstevel@tonic-gate int doIndex = 1; 13667c478bd9Sstevel@tonic-gate char **referralsp = NULL; 13677c478bd9Sstevel@tonic-gate 1368*54caa916SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India ctrls[0] = ctrls[1] = ctrls[2] = 0; 1369*54caa916SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India 13707c478bd9Sstevel@tonic-gate if (ldapStat == 0) 13717c478bd9Sstevel@tonic-gate ldapStat = &stat; 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate if (ls == 0) { 13747c478bd9Sstevel@tonic-gate *ldapStat = LDAP_PARAM_ERROR; 13757c478bd9Sstevel@tonic-gate return (0); 13767c478bd9Sstevel@tonic-gate } 13777c478bd9Sstevel@tonic-gate 13787c478bd9Sstevel@tonic-gate if (yp2ldap) { 13797c478bd9Sstevel@tonic-gate /* make sure the parent's connection is not used by child */ 13807c478bd9Sstevel@tonic-gate if ((lc = findYPCon(ls, ldapStat)) == 0) { 13817c478bd9Sstevel@tonic-gate *ldapStat = LDAP_SERVER_DOWN; 13827c478bd9Sstevel@tonic-gate return (0); 13837c478bd9Sstevel@tonic-gate } 13847c478bd9Sstevel@tonic-gate } else { 13857c478bd9Sstevel@tonic-gate if ((lc = findCon(ldapStat)) == 0) { 13867c478bd9Sstevel@tonic-gate *ldapStat = LDAP_SERVER_DOWN; 13877c478bd9Sstevel@tonic-gate return (0); 13887c478bd9Sstevel@tonic-gate } 13897c478bd9Sstevel@tonic-gate } 13907c478bd9Sstevel@tonic-gate 13917c478bd9Sstevel@tonic-gate if (numValues != 0 && (*numValues == 0 || *numValues == 1)) 13927c478bd9Sstevel@tonic-gate doIndex = 0; 13937c478bd9Sstevel@tonic-gate 13947c478bd9Sstevel@tonic-gate retry_new_conn: 13957c478bd9Sstevel@tonic-gate /* Prefer VLV over simple page, and SP over nothing */ 13967c478bd9Sstevel@tonic-gate if (doIndex && lc->vlv) { 13977c478bd9Sstevel@tonic-gate stat = ldap_create_sort_keylist(&sortKeyList, SORTKEYLIST); 13987c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 13997c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 14007c478bd9Sstevel@tonic-gate "%s: Error creating sort keylist: %s", 14017c478bd9Sstevel@tonic-gate myself, ldap_err2string(stat)); 14027c478bd9Sstevel@tonic-gate freeRuleValue(rv, numVals); 14037c478bd9Sstevel@tonic-gate *ldapStat = stat; 14047c478bd9Sstevel@tonic-gate rv = 0; 14057c478bd9Sstevel@tonic-gate goto retry_noVLV; 14067c478bd9Sstevel@tonic-gate } 14077c478bd9Sstevel@tonic-gate stat = ldap_create_sort_control(lc->ld, sortKeyList, 1, 14087c478bd9Sstevel@tonic-gate &sortCtrl); 14097c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) { 14107c478bd9Sstevel@tonic-gate vList.ldvlist_before_count = 0; 14117c478bd9Sstevel@tonic-gate vList.ldvlist_after_count = lc->batchFrom - 1; 14127c478bd9Sstevel@tonic-gate vList.ldvlist_attrvalue = 0; 14137c478bd9Sstevel@tonic-gate vList.ldvlist_extradata = 0; 14147c478bd9Sstevel@tonic-gate index = 1; 14157c478bd9Sstevel@tonic-gate doVLV = 1; 14167c478bd9Sstevel@tonic-gate } else { 14177c478bd9Sstevel@tonic-gate ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, &stat); 14187c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 14197c478bd9Sstevel@tonic-gate "%s: Error creating VLV sort control: %s", 14207c478bd9Sstevel@tonic-gate myself, ldap_err2string(stat)); 14217c478bd9Sstevel@tonic-gate freeRuleValue(rv, numVals); 14227c478bd9Sstevel@tonic-gate *ldapStat = stat; 14237c478bd9Sstevel@tonic-gate rv = 0; 14247c478bd9Sstevel@tonic-gate } 14257c478bd9Sstevel@tonic-gate } 14267c478bd9Sstevel@tonic-gate 14277c478bd9Sstevel@tonic-gate retry_noVLV: 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate if (doIndex && !doVLV && lc->simplePage) { 14307c478bd9Sstevel@tonic-gate spCookie = am(myself, sizeof (*spCookie)); 14317c478bd9Sstevel@tonic-gate if (spCookie != 0 && 14327c478bd9Sstevel@tonic-gate (spCookie->bv_val = sdup(myself, T, "")) != 0) { 14337c478bd9Sstevel@tonic-gate spCookie->bv_len = 0; 14347c478bd9Sstevel@tonic-gate doSP = 1; 14357c478bd9Sstevel@tonic-gate } else { 14367c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 14377c478bd9Sstevel@tonic-gate "%s: No memory for simple page cookie; using un-paged LDAP search", 14387c478bd9Sstevel@tonic-gate myself); 14397c478bd9Sstevel@tonic-gate freeRuleValue(rv, numVals); 14407c478bd9Sstevel@tonic-gate *ldapStat = stat; 14417c478bd9Sstevel@tonic-gate rv = 0; 14427c478bd9Sstevel@tonic-gate goto cleanup; 14437c478bd9Sstevel@tonic-gate } 14447c478bd9Sstevel@tonic-gate } 14457c478bd9Sstevel@tonic-gate 14467c478bd9Sstevel@tonic-gate if (!doVLV && !doSP) 14477c478bd9Sstevel@tonic-gate ctrls[0] = ctrls[1] = 0; 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate numVals = 0; 14507c478bd9Sstevel@tonic-gate done = 0; 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate if (ls->timeout.tv_sec || ls->timeout.tv_usec) { 14537c478bd9Sstevel@tonic-gate tv = ls->timeout; 14547c478bd9Sstevel@tonic-gate } else { 14557c478bd9Sstevel@tonic-gate tv = lc->searchTimeout; 14567c478bd9Sstevel@tonic-gate } 14577c478bd9Sstevel@tonic-gate (void) gettimeofday(&start, 0); 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate do { 14607c478bd9Sstevel@tonic-gate /* don't do vlv or simple page for base level searches */ 14617c478bd9Sstevel@tonic-gate if (doVLV && ls->base != LDAP_SCOPE_BASE) { 14627c478bd9Sstevel@tonic-gate vList.ldvlist_index = index; 14637c478bd9Sstevel@tonic-gate vList.ldvlist_size = 0; 14647c478bd9Sstevel@tonic-gate if (vlvCtrl != 0) 14657c478bd9Sstevel@tonic-gate ldap_control_free(vlvCtrl); 14667c478bd9Sstevel@tonic-gate stat = ldap_create_virtuallist_control(lc->ld, 14677c478bd9Sstevel@tonic-gate &vList, &vlvCtrl); 14687c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 14697c478bd9Sstevel@tonic-gate ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, 14707c478bd9Sstevel@tonic-gate &stat); 14717c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 14727c478bd9Sstevel@tonic-gate "%s: Error creating VLV at index %ld: %s", 14737c478bd9Sstevel@tonic-gate myself, index, ldap_err2string(stat)); 14747c478bd9Sstevel@tonic-gate *ldapStat = stat; 14757c478bd9Sstevel@tonic-gate freeRuleValue(rv, numVals); 14767c478bd9Sstevel@tonic-gate rv = 0; 14777c478bd9Sstevel@tonic-gate goto cleanup; 14787c478bd9Sstevel@tonic-gate } 14797c478bd9Sstevel@tonic-gate ctrls[0] = sortCtrl; 14807c478bd9Sstevel@tonic-gate ctrls[1] = vlvCtrl; 14817c478bd9Sstevel@tonic-gate ctrls[2] = 0; 14827c478bd9Sstevel@tonic-gate stat = ldap_search_ext_s(lc->ld, ls->base, 14837c478bd9Sstevel@tonic-gate ls->scope, ls->filter, ls->attrs, 14847c478bd9Sstevel@tonic-gate ls->attrsonly, ctrls, 0, &tv, 14857c478bd9Sstevel@tonic-gate proxyInfo.search_size_limit, &msg); 14867c478bd9Sstevel@tonic-gate /* don't do vlv or simple page for base level searches */ 14877c478bd9Sstevel@tonic-gate } else if (doSP && ls->base != LDAP_SCOPE_BASE) { 14887c478bd9Sstevel@tonic-gate if (ctrls[0] != 0) 14897c478bd9Sstevel@tonic-gate ldap_control_free(ctrls[0]); 14907c478bd9Sstevel@tonic-gate stat = ldap_create_page_control(lc->ld, 14917c478bd9Sstevel@tonic-gate lc->batchFrom, spCookie, 0, &ctrls[0]); 14927c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 14937c478bd9Sstevel@tonic-gate ber_bvfree(spCookie); 14947c478bd9Sstevel@tonic-gate spCookie = 0; 14957c478bd9Sstevel@tonic-gate ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, 14967c478bd9Sstevel@tonic-gate &stat); 14977c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 14987c478bd9Sstevel@tonic-gate "%s: Simple page error: %s", 14997c478bd9Sstevel@tonic-gate myself, ldap_err2string(stat)); 15007c478bd9Sstevel@tonic-gate freeRuleValue(rv, numVals); 15017c478bd9Sstevel@tonic-gate *ldapStat = stat; 15027c478bd9Sstevel@tonic-gate rv = 0; 15037c478bd9Sstevel@tonic-gate goto cleanup; 15047c478bd9Sstevel@tonic-gate } 15057c478bd9Sstevel@tonic-gate ctrls[1] = 0; 15067c478bd9Sstevel@tonic-gate stat = ldap_search_ext_s(lc->ld, ls->base, 15077c478bd9Sstevel@tonic-gate ls->scope, ls->filter, ls->attrs, 15087c478bd9Sstevel@tonic-gate ls->attrsonly, ctrls, 0, &tv, 15097c478bd9Sstevel@tonic-gate proxyInfo.search_size_limit, &msg); 15107c478bd9Sstevel@tonic-gate } else { 15117c478bd9Sstevel@tonic-gate stat = ldap_search_st(lc->ld, ls->base, ls->scope, 15127c478bd9Sstevel@tonic-gate ls->filter, ls->attrs, ls->attrsonly, 15137c478bd9Sstevel@tonic-gate &tv, &msg); 15147c478bd9Sstevel@tonic-gate } 15157c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) 15167c478bd9Sstevel@tonic-gate ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, &stat); 15177c478bd9Sstevel@tonic-gate 15187c478bd9Sstevel@tonic-gate if (stat == LDAP_SERVER_DOWN) { 15197c478bd9Sstevel@tonic-gate lc->doDis++; 15207c478bd9Sstevel@tonic-gate releaseCon(lc, stat); 15217c478bd9Sstevel@tonic-gate lc = (yp2ldap)?findYPCon(ls, ldapStat): 15227c478bd9Sstevel@tonic-gate findCon(ldapStat); 15237c478bd9Sstevel@tonic-gate if (lc == 0) { 15247c478bd9Sstevel@tonic-gate *ldapStat = LDAP_SERVER_DOWN; 15257c478bd9Sstevel@tonic-gate rv = 0; 15267c478bd9Sstevel@tonic-gate goto cleanup; 15277c478bd9Sstevel@tonic-gate } 15287c478bd9Sstevel@tonic-gate goto retry_new_conn; 15297c478bd9Sstevel@tonic-gate } 15307c478bd9Sstevel@tonic-gate 15317c478bd9Sstevel@tonic-gate if (stat == LDAP_REFERRAL && follow_referral) { 15327c478bd9Sstevel@tonic-gate (void) ldap_parse_result(lc->ld, msg, NULL, NULL, NULL, 15337c478bd9Sstevel@tonic-gate &referralsp, NULL, 0); 15347c478bd9Sstevel@tonic-gate if (referralsp != NULL) { 15357c478bd9Sstevel@tonic-gate /* We support at most one level of referrals */ 15367c478bd9Sstevel@tonic-gate follow_referral = FALSE; 15377c478bd9Sstevel@tonic-gate releaseCon(lc, stat); 15387c478bd9Sstevel@tonic-gate lc = findReferralCon(referralsp, &stat); 15397c478bd9Sstevel@tonic-gate ldap_value_free(referralsp); 15407c478bd9Sstevel@tonic-gate if (lc == NULL) { 15417c478bd9Sstevel@tonic-gate freeRuleValue(rv, numVals); 15427c478bd9Sstevel@tonic-gate rv = 0; 15437c478bd9Sstevel@tonic-gate *ldapStat = stat; 15447c478bd9Sstevel@tonic-gate goto cleanup; 15457c478bd9Sstevel@tonic-gate } 15467c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 15477c478bd9Sstevel@tonic-gate goto retry_new_conn; 15487c478bd9Sstevel@tonic-gate } 15497c478bd9Sstevel@tonic-gate } 15507c478bd9Sstevel@tonic-gate *ldapStat = stat; 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate if (*ldapStat == LDAP_NO_SUCH_OBJECT) { 15537c478bd9Sstevel@tonic-gate freeRuleValue(rv, numVals); 15547c478bd9Sstevel@tonic-gate rv = 0; 15557c478bd9Sstevel@tonic-gate goto cleanup; 15567c478bd9Sstevel@tonic-gate } else if (doVLV && *ldapStat == LDAP_INSUFFICIENT_ACCESS) { 15577c478bd9Sstevel@tonic-gate /* 15587c478bd9Sstevel@tonic-gate * The LDAP server (at least Netscape 4.x) can return 15597c478bd9Sstevel@tonic-gate * LDAP_INSUFFICIENT_ACCESS when VLV is supported, 15607c478bd9Sstevel@tonic-gate * but not for the bind DN specified. So, just in 15617c478bd9Sstevel@tonic-gate * case, we clean up, and try again without VLV. 15627c478bd9Sstevel@tonic-gate */ 15637c478bd9Sstevel@tonic-gate doVLV = 0; 15647c478bd9Sstevel@tonic-gate if (msg != 0) { 15657c478bd9Sstevel@tonic-gate (void) ldap_msgfree(msg); 15667c478bd9Sstevel@tonic-gate msg = 0; 15677c478bd9Sstevel@tonic-gate } 15687c478bd9Sstevel@tonic-gate if (ctrls[0] != 0) { 15697c478bd9Sstevel@tonic-gate ldap_control_free(ctrls[0]); 15707c478bd9Sstevel@tonic-gate ctrls[0] = 0; 15717c478bd9Sstevel@tonic-gate } 15727c478bd9Sstevel@tonic-gate if (ctrls[1] != 0) { 15737c478bd9Sstevel@tonic-gate ldap_control_free(ctrls[1]); 15747c478bd9Sstevel@tonic-gate ctrls[1] = 0; 15757c478bd9Sstevel@tonic-gate } 15767c478bd9Sstevel@tonic-gate logmsg(MSG_VLV_INSUFF_ACC, LOG_WARNING, 15777c478bd9Sstevel@tonic-gate "%s: VLV insufficient access from server %s; retrying without VLV", 15787c478bd9Sstevel@tonic-gate myself, NIL(lc->sp)); 15797c478bd9Sstevel@tonic-gate goto retry_noVLV; 15807c478bd9Sstevel@tonic-gate } else if (*ldapStat != LDAP_SUCCESS) { 15817c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 15827c478bd9Sstevel@tonic-gate "ldap_search(0x%x,\n\t\"%s\",\n\t %d,", 15837c478bd9Sstevel@tonic-gate lc->ld, NIL(ls->base), ls->scope); 15847c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 15857c478bd9Sstevel@tonic-gate "\t\"%s\",\n\t0x%x,\n\t%d) => %d (%s)", 15867c478bd9Sstevel@tonic-gate NIL(ls->filter), ls->attrs, ls->attrsonly, 15877c478bd9Sstevel@tonic-gate *ldapStat, ldap_err2string(stat)); 15887c478bd9Sstevel@tonic-gate freeRuleValue(rv, numVals); 15897c478bd9Sstevel@tonic-gate rv = 0; 15907c478bd9Sstevel@tonic-gate goto cleanup; 15917c478bd9Sstevel@tonic-gate } 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate numEntries = ldap_count_entries(lc->ld, msg); 15947c478bd9Sstevel@tonic-gate if (numEntries == 0 && *ldapStat == LDAP_SUCCESS) { 15957c478bd9Sstevel@tonic-gate /* 15967c478bd9Sstevel@tonic-gate * This is a bit weird, but the server (or, at least, 15977c478bd9Sstevel@tonic-gate * ldap_search_ext()) can sometimes return 15987c478bd9Sstevel@tonic-gate * LDAP_SUCCESS and no entries when it didn't 15997c478bd9Sstevel@tonic-gate * find what we were looking for. Seems it ought to 16007c478bd9Sstevel@tonic-gate * return LDAP_NO_SUCH_OBJECT or some such. 16017c478bd9Sstevel@tonic-gate */ 16027c478bd9Sstevel@tonic-gate freeRuleValue(rv, numVals); 16037c478bd9Sstevel@tonic-gate rv = 0; 16047c478bd9Sstevel@tonic-gate *ldapStat = LDAP_NO_SUCH_OBJECT; 16057c478bd9Sstevel@tonic-gate goto cleanup; 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate 16087c478bd9Sstevel@tonic-gate tnv = numVals + numEntries; 16097c478bd9Sstevel@tonic-gate if ((rv = growRuleValue(numVals, tnv, rv, rvIn)) == 0) { 16107c478bd9Sstevel@tonic-gate *ldapStat = LDAP_NO_MEMORY; 16117c478bd9Sstevel@tonic-gate goto cleanup; 16127c478bd9Sstevel@tonic-gate } 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate for (m = ldap_first_entry(lc->ld, msg); m != 0; 16157c478bd9Sstevel@tonic-gate m = ldap_next_entry(lc->ld, m), numVals++) { 16167c478bd9Sstevel@tonic-gate char *nm; 16177c478bd9Sstevel@tonic-gate BerElement *ber = 0; 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate if (numVals > tnv) { 16207c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 16217c478bd9Sstevel@tonic-gate "%s: Inconsistent LDAP entry count > %d", 16227c478bd9Sstevel@tonic-gate myself, numEntries); 16237c478bd9Sstevel@tonic-gate break; 16247c478bd9Sstevel@tonic-gate } 16257c478bd9Sstevel@tonic-gate 16267c478bd9Sstevel@tonic-gate nm = ldap_get_dn(lc->ld, m); 16277c478bd9Sstevel@tonic-gate if (nm == 0 || addSAttr2RuleValue("dn", nm, 16287c478bd9Sstevel@tonic-gate &rv[numVals])) { 16297c478bd9Sstevel@tonic-gate sfree(nm); 16307c478bd9Sstevel@tonic-gate *ldapStat = LDAP_NO_MEMORY; 16317c478bd9Sstevel@tonic-gate freeRuleValue(rv, tnv); 16327c478bd9Sstevel@tonic-gate rv = 0; 16337c478bd9Sstevel@tonic-gate goto cleanup; 16347c478bd9Sstevel@tonic-gate } 16357c478bd9Sstevel@tonic-gate sfree(nm); 16367c478bd9Sstevel@tonic-gate 16377c478bd9Sstevel@tonic-gate for (nm = ldap_first_attribute(lc->ld, m, &ber); 16387c478bd9Sstevel@tonic-gate nm != 0; 16397c478bd9Sstevel@tonic-gate nm = ldap_next_attribute(lc->ld, m, ber)) { 16407c478bd9Sstevel@tonic-gate struct berval **val; 16417c478bd9Sstevel@tonic-gate int i, nv; 16427c478bd9Sstevel@tonic-gate 16437c478bd9Sstevel@tonic-gate val = ldap_get_values_len(lc->ld, m, nm); 16447c478bd9Sstevel@tonic-gate nv = (val == 0) ? 0 : 16457c478bd9Sstevel@tonic-gate ldap_count_values_len(val); 16467c478bd9Sstevel@tonic-gate for (i = 0; i < nv; i++) { 16477c478bd9Sstevel@tonic-gate /* 16487c478bd9Sstevel@tonic-gate * Since we don't know if the value is 16497c478bd9Sstevel@tonic-gate * BER-encoded or not, we mark it as a 16507c478bd9Sstevel@tonic-gate * string. All is well as long as we 16517c478bd9Sstevel@tonic-gate * don't insist on 'vt_ber' when 16527c478bd9Sstevel@tonic-gate * interpreting. 16537c478bd9Sstevel@tonic-gate */ 16547c478bd9Sstevel@tonic-gate if (addAttr2RuleValue(vt_string, nm, 16557c478bd9Sstevel@tonic-gate val[i]->bv_val, 16567c478bd9Sstevel@tonic-gate val[i]->bv_len, 16577c478bd9Sstevel@tonic-gate &rv[numVals])) { 16587c478bd9Sstevel@tonic-gate if (ber != 0) 16597c478bd9Sstevel@tonic-gate ber_free(ber, 0); 16607c478bd9Sstevel@tonic-gate ldap_value_free_len(val); 16617c478bd9Sstevel@tonic-gate *ldapStat = LDAP_NO_MEMORY; 16627c478bd9Sstevel@tonic-gate freeRuleValue(rv, tnv); 16637c478bd9Sstevel@tonic-gate rv = 0; 16647c478bd9Sstevel@tonic-gate goto cleanup; 16657c478bd9Sstevel@tonic-gate } 16667c478bd9Sstevel@tonic-gate } 16677c478bd9Sstevel@tonic-gate /* 16687c478bd9Sstevel@tonic-gate * XXX the ldap_first_attribute(3LDAP) man 16697c478bd9Sstevel@tonic-gate * page says that the ldap_first_attribute/ 16707c478bd9Sstevel@tonic-gate * ldap_next_attribute should be treated as 16717c478bd9Sstevel@tonic-gate * static, but the libldap.so.4 code mallocs 16727c478bd9Sstevel@tonic-gate * (and it's not TSD). So, in order to avoid 16737c478bd9Sstevel@tonic-gate * a leak, we free the return value. 16747c478bd9Sstevel@tonic-gate */ 16757c478bd9Sstevel@tonic-gate ldap_memfree(nm); 16767c478bd9Sstevel@tonic-gate if (val != 0) 16777c478bd9Sstevel@tonic-gate ldap_value_free_len(val); 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate /* 16807c478bd9Sstevel@tonic-gate * XXX ldap_next_attribute(3LDAP) says that the 'ber' 16817c478bd9Sstevel@tonic-gate * pointer is freed when it returns NULL, but that's 16827c478bd9Sstevel@tonic-gate * not implemented in the libldap.so.4 code, so we 16837c478bd9Sstevel@tonic-gate * free it here in order to avoid a memory leak. 16847c478bd9Sstevel@tonic-gate */ 16857c478bd9Sstevel@tonic-gate if (ber != 0) 16867c478bd9Sstevel@tonic-gate ber_free(ber, 0); 16877c478bd9Sstevel@tonic-gate } 16887c478bd9Sstevel@tonic-gate 16897c478bd9Sstevel@tonic-gate if (numVals != tnv) { 16907c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 16917c478bd9Sstevel@tonic-gate "%s: Inconsistent LDAP entry count, found = %d, expected %d", 16927c478bd9Sstevel@tonic-gate myself, numVals, tnv); 16937c478bd9Sstevel@tonic-gate } 16947c478bd9Sstevel@tonic-gate 16957c478bd9Sstevel@tonic-gate if (doVLV) { 16967c478bd9Sstevel@tonic-gate stat = ldap_parse_result(lc->ld, msg, &lprEc, 0, 0, 0, 16977c478bd9Sstevel@tonic-gate &retCtrls, 0); 16987c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 16997c478bd9Sstevel@tonic-gate ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, 17007c478bd9Sstevel@tonic-gate &stat); 17017c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 17027c478bd9Sstevel@tonic-gate "%s: VLV parse result error: %s", 17037c478bd9Sstevel@tonic-gate myself, ldap_err2string(stat)); 17047c478bd9Sstevel@tonic-gate *ldapStat = stat; 17057c478bd9Sstevel@tonic-gate freeRuleValue(rv, tnv); 17067c478bd9Sstevel@tonic-gate rv = 0; 17077c478bd9Sstevel@tonic-gate goto cleanup; 17087c478bd9Sstevel@tonic-gate } 17097c478bd9Sstevel@tonic-gate if (retCtrls != 0) { 17107c478bd9Sstevel@tonic-gate unsigned long targetPosP = 0; 17117c478bd9Sstevel@tonic-gate unsigned long listSize = 0; 17127c478bd9Sstevel@tonic-gate 17137c478bd9Sstevel@tonic-gate stat = ldap_parse_virtuallist_control(lc->ld, 17147c478bd9Sstevel@tonic-gate retCtrls, &targetPosP, &listSize, 17157c478bd9Sstevel@tonic-gate &lprEc); 17167c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) { 17177c478bd9Sstevel@tonic-gate index = targetPosP + lc->batchFrom; 17187c478bd9Sstevel@tonic-gate if (index >= listSize) 17197c478bd9Sstevel@tonic-gate done = 1; 17207c478bd9Sstevel@tonic-gate } 17217c478bd9Sstevel@tonic-gate ldap_controls_free(retCtrls); 17227c478bd9Sstevel@tonic-gate retCtrls = 0; 17237c478bd9Sstevel@tonic-gate } else { 17247c478bd9Sstevel@tonic-gate done = 1; 17257c478bd9Sstevel@tonic-gate } 17267c478bd9Sstevel@tonic-gate } else if (doSP) { 17277c478bd9Sstevel@tonic-gate stat = ldap_parse_result(lc->ld, msg, &lprEc, 0, 0, 0, 17287c478bd9Sstevel@tonic-gate &retCtrls, 0); 17297c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 17307c478bd9Sstevel@tonic-gate ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, 17317c478bd9Sstevel@tonic-gate &stat); 17327c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 17337c478bd9Sstevel@tonic-gate "%s: Simple page parse result error: %s", 17347c478bd9Sstevel@tonic-gate myself, ldap_err2string(stat)); 17357c478bd9Sstevel@tonic-gate *ldapStat = stat; 17367c478bd9Sstevel@tonic-gate freeRuleValue(rv, tnv); 17377c478bd9Sstevel@tonic-gate rv = 0; 17387c478bd9Sstevel@tonic-gate goto cleanup; 17397c478bd9Sstevel@tonic-gate } 17407c478bd9Sstevel@tonic-gate if (retCtrls != 0) { 17417c478bd9Sstevel@tonic-gate unsigned int count; 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate if (spCookie != 0) { 17447c478bd9Sstevel@tonic-gate ber_bvfree(spCookie); 17457c478bd9Sstevel@tonic-gate spCookie = 0; 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate stat = ldap_parse_page_control(lc->ld, 17487c478bd9Sstevel@tonic-gate retCtrls, &count, &spCookie); 17497c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) { 17507c478bd9Sstevel@tonic-gate if (spCookie == 0 || 17517c478bd9Sstevel@tonic-gate spCookie->bv_val == 0 || 17527c478bd9Sstevel@tonic-gate spCookie->bv_len == 0) 17537c478bd9Sstevel@tonic-gate done = 1; 17547c478bd9Sstevel@tonic-gate } 17557c478bd9Sstevel@tonic-gate ldap_controls_free(retCtrls); 17567c478bd9Sstevel@tonic-gate retCtrls = 0; 17577c478bd9Sstevel@tonic-gate } else { 17587c478bd9Sstevel@tonic-gate done = 1; 17597c478bd9Sstevel@tonic-gate } 17607c478bd9Sstevel@tonic-gate } else { 17617c478bd9Sstevel@tonic-gate done = 1; 17627c478bd9Sstevel@tonic-gate } 17637c478bd9Sstevel@tonic-gate 17647c478bd9Sstevel@tonic-gate (void) ldap_msgfree(msg); 17657c478bd9Sstevel@tonic-gate msg = 0; 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate /* 17687c478bd9Sstevel@tonic-gate * If we're using VLV or SP, the timeout should apply 17697c478bd9Sstevel@tonic-gate * to all calls as an aggregate, so we need to reduce 17707c478bd9Sstevel@tonic-gate * 'tv' with the time spent on this chunk of data. 17717c478bd9Sstevel@tonic-gate */ 17727c478bd9Sstevel@tonic-gate if (!done) { 17737c478bd9Sstevel@tonic-gate struct timeval tmp; 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate (void) gettimeofday(&now, 0); 17767c478bd9Sstevel@tonic-gate tmp = now; 17777c478bd9Sstevel@tonic-gate now.tv_sec -= start.tv_sec; 17787c478bd9Sstevel@tonic-gate now.tv_usec -= start.tv_usec; 17797c478bd9Sstevel@tonic-gate if (now.tv_usec < 0) { 17807c478bd9Sstevel@tonic-gate now.tv_usec += 1000000; 17817c478bd9Sstevel@tonic-gate now.tv_sec -= 1; 17827c478bd9Sstevel@tonic-gate } 17837c478bd9Sstevel@tonic-gate tv.tv_sec -= now.tv_sec; 17847c478bd9Sstevel@tonic-gate tv.tv_usec -= now.tv_usec; 17857c478bd9Sstevel@tonic-gate if (tv.tv_usec < 0) { 17867c478bd9Sstevel@tonic-gate tv.tv_usec += 1000000; 17877c478bd9Sstevel@tonic-gate tv.tv_sec -= 1; 17887c478bd9Sstevel@tonic-gate } 17897c478bd9Sstevel@tonic-gate if (tv.tv_sec < 0) { 17907c478bd9Sstevel@tonic-gate *ldapStat = LDAP_TIMEOUT; 17917c478bd9Sstevel@tonic-gate freeRuleValue(rv, tnv); 17927c478bd9Sstevel@tonic-gate rv = 0; 17937c478bd9Sstevel@tonic-gate goto cleanup; 17947c478bd9Sstevel@tonic-gate } 17957c478bd9Sstevel@tonic-gate start = tmp; 17967c478bd9Sstevel@tonic-gate } 17977c478bd9Sstevel@tonic-gate 17987c478bd9Sstevel@tonic-gate } while (!done); 17997c478bd9Sstevel@tonic-gate 18007c478bd9Sstevel@tonic-gate if (numValues != 0) 18017c478bd9Sstevel@tonic-gate *numValues = numVals; 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate cleanup: 18047c478bd9Sstevel@tonic-gate if (NULL != lc) { 18057c478bd9Sstevel@tonic-gate if (yp2ldap && ls->useCon == 0) { 18067c478bd9Sstevel@tonic-gate /* Disconnect and free the connection */ 18077c478bd9Sstevel@tonic-gate lc->doDis++; 18087c478bd9Sstevel@tonic-gate lc->doDel++; 18097c478bd9Sstevel@tonic-gate releaseCon(lc, stat); 18107c478bd9Sstevel@tonic-gate releaseLC(lc); 18117c478bd9Sstevel@tonic-gate 18127c478bd9Sstevel@tonic-gate } else { 18137c478bd9Sstevel@tonic-gate releaseCon(lc, stat); 18147c478bd9Sstevel@tonic-gate } 18157c478bd9Sstevel@tonic-gate } 18167c478bd9Sstevel@tonic-gate if (msg != 0) 18177c478bd9Sstevel@tonic-gate (void) ldap_msgfree(msg); 18187c478bd9Sstevel@tonic-gate if (ctrls[0] != 0) 18197c478bd9Sstevel@tonic-gate ldap_control_free(ctrls[0]); 18207c478bd9Sstevel@tonic-gate if (ctrls[1] != 0) 18217c478bd9Sstevel@tonic-gate ldap_control_free(ctrls[1]); 18227c478bd9Sstevel@tonic-gate if (spCookie != 0) 18237c478bd9Sstevel@tonic-gate ber_bvfree(spCookie); 18247c478bd9Sstevel@tonic-gate if (sortKeyList != 0) 18257c478bd9Sstevel@tonic-gate ldap_free_sort_keylist(sortKeyList); 18267c478bd9Sstevel@tonic-gate 18277c478bd9Sstevel@tonic-gate return (rv); 18287c478bd9Sstevel@tonic-gate } 18297c478bd9Sstevel@tonic-gate 18307c478bd9Sstevel@tonic-gate static void 18317c478bd9Sstevel@tonic-gate freeLdapModEntry(LDAPMod *m) { 18327c478bd9Sstevel@tonic-gate 18337c478bd9Sstevel@tonic-gate if (m == 0) 18347c478bd9Sstevel@tonic-gate return; 18357c478bd9Sstevel@tonic-gate 18367c478bd9Sstevel@tonic-gate sfree(m->mod_type); 18377c478bd9Sstevel@tonic-gate if ((m->mod_op & LDAP_MOD_BVALUES) == 0) { 18387c478bd9Sstevel@tonic-gate char **v = m->mod_values; 18397c478bd9Sstevel@tonic-gate 18407c478bd9Sstevel@tonic-gate if (v != 0) { 18417c478bd9Sstevel@tonic-gate while (*v != 0) { 18427c478bd9Sstevel@tonic-gate sfree(*v); 18437c478bd9Sstevel@tonic-gate v++; 18447c478bd9Sstevel@tonic-gate } 18457c478bd9Sstevel@tonic-gate free(m->mod_values); 18467c478bd9Sstevel@tonic-gate } 18477c478bd9Sstevel@tonic-gate } else { 18487c478bd9Sstevel@tonic-gate struct berval **b = m->mod_bvalues; 18497c478bd9Sstevel@tonic-gate 18507c478bd9Sstevel@tonic-gate if (b != 0) { 18517c478bd9Sstevel@tonic-gate while (*b != 0) { 18527c478bd9Sstevel@tonic-gate sfree((*b)->bv_val); 18537c478bd9Sstevel@tonic-gate free(*b); 18547c478bd9Sstevel@tonic-gate b++; 18557c478bd9Sstevel@tonic-gate } 18567c478bd9Sstevel@tonic-gate free(m->mod_bvalues); 18577c478bd9Sstevel@tonic-gate } 18587c478bd9Sstevel@tonic-gate } 18597c478bd9Sstevel@tonic-gate 18607c478bd9Sstevel@tonic-gate free(m); 18617c478bd9Sstevel@tonic-gate } 18627c478bd9Sstevel@tonic-gate 18637c478bd9Sstevel@tonic-gate static void 18647c478bd9Sstevel@tonic-gate freeLdapMod(LDAPMod **mods) { 18657c478bd9Sstevel@tonic-gate LDAPMod *m, **org = mods; 18667c478bd9Sstevel@tonic-gate 18677c478bd9Sstevel@tonic-gate if (mods == 0) 18687c478bd9Sstevel@tonic-gate return; 18697c478bd9Sstevel@tonic-gate 18707c478bd9Sstevel@tonic-gate while ((m = *mods) != 0) { 18717c478bd9Sstevel@tonic-gate freeLdapModEntry(m); 18727c478bd9Sstevel@tonic-gate mods++; 18737c478bd9Sstevel@tonic-gate } 18747c478bd9Sstevel@tonic-gate 18757c478bd9Sstevel@tonic-gate free(org); 18767c478bd9Sstevel@tonic-gate } 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate /* 18797c478bd9Sstevel@tonic-gate * Convert a rule-value structure to the corresponding LDAPMod. 18807c478bd9Sstevel@tonic-gate * If 'add' is set, attributes/values are added; object classes 18817c478bd9Sstevel@tonic-gate * are also added. If 'add' is cleared, attributes/values are modified, 18827c478bd9Sstevel@tonic-gate * and 'oc' controls whether or not object classes are added. 18837c478bd9Sstevel@tonic-gate */ 18847c478bd9Sstevel@tonic-gate LDAPMod ** 18857c478bd9Sstevel@tonic-gate search2LdapMod(__nis_rule_value_t *rv, int add, int oc) { 18867c478bd9Sstevel@tonic-gate LDAPMod **mods; 18877c478bd9Sstevel@tonic-gate int i, j, nm; 18887c478bd9Sstevel@tonic-gate char *myself = "search2LdapMod"; 18897c478bd9Sstevel@tonic-gate 18907c478bd9Sstevel@tonic-gate if (rv == 0 || rv->numAttrs <= 0) 18917c478bd9Sstevel@tonic-gate return (0); 18927c478bd9Sstevel@tonic-gate 18937c478bd9Sstevel@tonic-gate mods = am(myself, (rv->numAttrs + 1) * sizeof (mods[0])); 18947c478bd9Sstevel@tonic-gate if (mods == 0) 18957c478bd9Sstevel@tonic-gate return (0); 18967c478bd9Sstevel@tonic-gate 18977c478bd9Sstevel@tonic-gate for (i = 0, nm = 0; i < rv->numAttrs; i++) { 18987c478bd9Sstevel@tonic-gate int isOc; 18997c478bd9Sstevel@tonic-gate /* 19007c478bd9Sstevel@tonic-gate * If we're creating an LDAPMod array for an add operation, 19017c478bd9Sstevel@tonic-gate * just skip attributes that should be deleted. 19027c478bd9Sstevel@tonic-gate */ 19037c478bd9Sstevel@tonic-gate if (add && rv->attrVal[i].numVals < 0) 19047c478bd9Sstevel@tonic-gate continue; 19057c478bd9Sstevel@tonic-gate 19067c478bd9Sstevel@tonic-gate /* 19077c478bd9Sstevel@tonic-gate * Skip DN; it's specified separately to ldap_modify() 19087c478bd9Sstevel@tonic-gate * and ldap_add(), and mustn't appear among the 19097c478bd9Sstevel@tonic-gate * attributes to be modified/added. 19107c478bd9Sstevel@tonic-gate */ 19117c478bd9Sstevel@tonic-gate if (strcasecmp("dn", rv->attrName[i]) == 0) 19127c478bd9Sstevel@tonic-gate continue; 19137c478bd9Sstevel@tonic-gate 19147c478bd9Sstevel@tonic-gate /* 19157c478bd9Sstevel@tonic-gate * If modifying, and 'oc' is off, skip object class 19167c478bd9Sstevel@tonic-gate * attributes. 19177c478bd9Sstevel@tonic-gate */ 19187c478bd9Sstevel@tonic-gate isOc = (strcasecmp("objectclass", rv->attrName[i]) == 0); 19197c478bd9Sstevel@tonic-gate if (!add && !oc && isOc) 19207c478bd9Sstevel@tonic-gate continue; 19217c478bd9Sstevel@tonic-gate 19227c478bd9Sstevel@tonic-gate mods[nm] = am(myself, sizeof (*mods[nm])); 19237c478bd9Sstevel@tonic-gate if (mods[nm] == 0) { 19247c478bd9Sstevel@tonic-gate freeLdapMod(mods); 19257c478bd9Sstevel@tonic-gate return (0); 19267c478bd9Sstevel@tonic-gate } 19277c478bd9Sstevel@tonic-gate 19287c478bd9Sstevel@tonic-gate /* 'mod_type' is the attribute name */ 19297c478bd9Sstevel@tonic-gate mods[nm]->mod_type = sdup(myself, T, rv->attrName[i]); 19307c478bd9Sstevel@tonic-gate if (mods[nm]->mod_type == 0) { 19317c478bd9Sstevel@tonic-gate freeLdapMod(mods); 19327c478bd9Sstevel@tonic-gate return (0); 19337c478bd9Sstevel@tonic-gate } 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate /* 19367c478bd9Sstevel@tonic-gate * numVals < 0 means attribute and all values should 19377c478bd9Sstevel@tonic-gate * be deleted. 19387c478bd9Sstevel@tonic-gate */ 19397c478bd9Sstevel@tonic-gate if (rv->attrVal[i].numVals < 0) { 19407c478bd9Sstevel@tonic-gate mods[nm]->mod_op = LDAP_MOD_DELETE; 19417c478bd9Sstevel@tonic-gate mods[nm]->mod_values = 0; 19427c478bd9Sstevel@tonic-gate nm++; 19437c478bd9Sstevel@tonic-gate continue; 19447c478bd9Sstevel@tonic-gate } 19457c478bd9Sstevel@tonic-gate 19467c478bd9Sstevel@tonic-gate /* objectClass attributes always added */ 19477c478bd9Sstevel@tonic-gate mods[nm]->mod_op = (add) ? 0 : ((isOc) ? 0 : LDAP_MOD_REPLACE); 19487c478bd9Sstevel@tonic-gate 19497c478bd9Sstevel@tonic-gate if (rv->attrVal[i].type == vt_string) { 19507c478bd9Sstevel@tonic-gate /* 19517c478bd9Sstevel@tonic-gate * mods[]->mod_values is a NULL-terminated array 19527c478bd9Sstevel@tonic-gate * of (char *)'s. 19537c478bd9Sstevel@tonic-gate */ 19547c478bd9Sstevel@tonic-gate mods[nm]->mod_values = am(myself, 19557c478bd9Sstevel@tonic-gate (rv->attrVal[i].numVals + 1) * 19567c478bd9Sstevel@tonic-gate sizeof (mods[nm]->mod_values[0])); 19577c478bd9Sstevel@tonic-gate if (mods[nm]->mod_values == 0) { 19587c478bd9Sstevel@tonic-gate freeLdapMod(mods); 19597c478bd9Sstevel@tonic-gate return (0); 19607c478bd9Sstevel@tonic-gate } 19617c478bd9Sstevel@tonic-gate for (j = 0; j < rv->attrVal[i].numVals; j++) { 19627c478bd9Sstevel@tonic-gate /* 19637c478bd9Sstevel@tonic-gate * Just in case the string isn't NUL 19647c478bd9Sstevel@tonic-gate * terminated, add one byte to the 19657c478bd9Sstevel@tonic-gate * allocated length; am() will initialize 19667c478bd9Sstevel@tonic-gate * the buffer to zero. 19677c478bd9Sstevel@tonic-gate */ 19687c478bd9Sstevel@tonic-gate mods[nm]->mod_values[j] = am(myself, 19697c478bd9Sstevel@tonic-gate rv->attrVal[i].val[j].length + 1); 19707c478bd9Sstevel@tonic-gate if (mods[nm]->mod_values[j] == 0) { 19717c478bd9Sstevel@tonic-gate freeLdapMod(mods); 19727c478bd9Sstevel@tonic-gate return (0); 19737c478bd9Sstevel@tonic-gate } 19747c478bd9Sstevel@tonic-gate memcpy(mods[nm]->mod_values[j], 19757c478bd9Sstevel@tonic-gate rv->attrVal[i].val[j].value, 19767c478bd9Sstevel@tonic-gate rv->attrVal[i].val[j].length); 19777c478bd9Sstevel@tonic-gate } 19787c478bd9Sstevel@tonic-gate } else { 19797c478bd9Sstevel@tonic-gate mods[nm]->mod_op |= LDAP_MOD_BVALUES; 19807c478bd9Sstevel@tonic-gate mods[nm]->mod_bvalues = am(myself, 19817c478bd9Sstevel@tonic-gate (rv->attrVal[i].numVals+1) * 19827c478bd9Sstevel@tonic-gate sizeof (mods[nm]->mod_bvalues[0])); 19837c478bd9Sstevel@tonic-gate if (mods[nm]->mod_bvalues == 0) { 19847c478bd9Sstevel@tonic-gate freeLdapMod(mods); 19857c478bd9Sstevel@tonic-gate return (0); 19867c478bd9Sstevel@tonic-gate } 19877c478bd9Sstevel@tonic-gate for (j = 0; j < rv->attrVal[i].numVals; j++) { 19887c478bd9Sstevel@tonic-gate mods[nm]->mod_bvalues[j] = am(myself, 19897c478bd9Sstevel@tonic-gate sizeof (*mods[nm]->mod_bvalues[j])); 19907c478bd9Sstevel@tonic-gate if (mods[nm]->mod_bvalues[j] == 0) { 19917c478bd9Sstevel@tonic-gate freeLdapMod(mods); 19927c478bd9Sstevel@tonic-gate return (0); 19937c478bd9Sstevel@tonic-gate } 19947c478bd9Sstevel@tonic-gate mods[nm]->mod_bvalues[j]->bv_val = am(myself, 19957c478bd9Sstevel@tonic-gate rv->attrVal[i].val[j].length); 19967c478bd9Sstevel@tonic-gate if (mods[nm]->mod_bvalues[j]->bv_val == 0) { 19977c478bd9Sstevel@tonic-gate freeLdapMod(mods); 19987c478bd9Sstevel@tonic-gate return (0); 19997c478bd9Sstevel@tonic-gate } 20007c478bd9Sstevel@tonic-gate mods[nm]->mod_bvalues[j]->bv_len = 20017c478bd9Sstevel@tonic-gate rv->attrVal[i].val[j].length; 20027c478bd9Sstevel@tonic-gate memcpy(mods[nm]->mod_bvalues[j]->bv_val, 20037c478bd9Sstevel@tonic-gate rv->attrVal[i].val[j].value, 20047c478bd9Sstevel@tonic-gate mods[nm]->mod_bvalues[j]->bv_len); 20057c478bd9Sstevel@tonic-gate } 20067c478bd9Sstevel@tonic-gate } 20077c478bd9Sstevel@tonic-gate nm++; 20087c478bd9Sstevel@tonic-gate } 20097c478bd9Sstevel@tonic-gate 20107c478bd9Sstevel@tonic-gate return (mods); 20117c478bd9Sstevel@tonic-gate } 20127c478bd9Sstevel@tonic-gate 20137c478bd9Sstevel@tonic-gate /* 20147c478bd9Sstevel@tonic-gate * Remove 'value' from 'val'. If value==0, remove the entire 20157c478bd9Sstevel@tonic-gate * __nis_single_value_t array from 'val'. 20167c478bd9Sstevel@tonic-gate */ 20177c478bd9Sstevel@tonic-gate static void 20187c478bd9Sstevel@tonic-gate removeSingleValue(__nis_value_t *val, void *value, int length) { 20197c478bd9Sstevel@tonic-gate int i; 20207c478bd9Sstevel@tonic-gate 20217c478bd9Sstevel@tonic-gate if (val == 0) 20227c478bd9Sstevel@tonic-gate return; 20237c478bd9Sstevel@tonic-gate 20247c478bd9Sstevel@tonic-gate if (value == 0) { 20257c478bd9Sstevel@tonic-gate for (i = 0; i < val->numVals; i++) { 20267c478bd9Sstevel@tonic-gate sfree(val->val[i].value); 20277c478bd9Sstevel@tonic-gate } 20287c478bd9Sstevel@tonic-gate sfree(val->val); 20297c478bd9Sstevel@tonic-gate val->val = 0; 20307c478bd9Sstevel@tonic-gate val->numVals = 0; 20317c478bd9Sstevel@tonic-gate return; 20327c478bd9Sstevel@tonic-gate } 20337c478bd9Sstevel@tonic-gate 20347c478bd9Sstevel@tonic-gate for (i = 0; i < val->numVals; i++) { 20357c478bd9Sstevel@tonic-gate if (val->val[i].value == 0 || (val->val[i].length != length)) 20367c478bd9Sstevel@tonic-gate continue; 20377c478bd9Sstevel@tonic-gate if (memcmp(val->val[i].value, value, length) != 0) 20387c478bd9Sstevel@tonic-gate continue; 20397c478bd9Sstevel@tonic-gate sfree(val->val[i].value); 20407c478bd9Sstevel@tonic-gate if (i != (val->numVals - 1)) { 20417c478bd9Sstevel@tonic-gate (void) memmove(&val->val[i], &val->val[i+1], 20427c478bd9Sstevel@tonic-gate (val->numVals - 1 - i) * sizeof (val->val[0])); 20437c478bd9Sstevel@tonic-gate } 20447c478bd9Sstevel@tonic-gate val->numVals -= 1; 20457c478bd9Sstevel@tonic-gate break; 20467c478bd9Sstevel@tonic-gate } 20477c478bd9Sstevel@tonic-gate } 20487c478bd9Sstevel@tonic-gate 20497c478bd9Sstevel@tonic-gate /* 20507c478bd9Sstevel@tonic-gate * Helper function for LdapModify 20517c478bd9Sstevel@tonic-gate * When a modify operation fails with an object class violation, 20527c478bd9Sstevel@tonic-gate * the most probable reason is that the attributes we're modifying are new, 20537c478bd9Sstevel@tonic-gate * and the needed object class are not present. So, try the modify again, 20547c478bd9Sstevel@tonic-gate * but add the object classes this time. 20557c478bd9Sstevel@tonic-gate */ 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate static int 20587c478bd9Sstevel@tonic-gate ldapModifyObjectClass(__nis_ldap_conn_t **lc, char *dn, 20597c478bd9Sstevel@tonic-gate __nis_rule_value_t *rvIn, char *objClassAttrs) 20607c478bd9Sstevel@tonic-gate { 20617c478bd9Sstevel@tonic-gate LDAPMod **mods = 0; 20627c478bd9Sstevel@tonic-gate int msgid; 20637c478bd9Sstevel@tonic-gate int lderr; 20647c478bd9Sstevel@tonic-gate struct timeval tv; 20657c478bd9Sstevel@tonic-gate int stat; 20667c478bd9Sstevel@tonic-gate LDAPMessage *msg = 0; 20677c478bd9Sstevel@tonic-gate char **referralsp = NULL; 20687c478bd9Sstevel@tonic-gate __nis_rule_value_t *rv, *rvldap; 20697c478bd9Sstevel@tonic-gate __nis_ldap_search_t *ls; 20707c478bd9Sstevel@tonic-gate int i, ocrv, ocrvldap, nv; 20717c478bd9Sstevel@tonic-gate char *oc[2] = { "objectClass", 0}; 20727c478bd9Sstevel@tonic-gate char *myself = "ldapModifyObjectClass"; 20737c478bd9Sstevel@tonic-gate 20747c478bd9Sstevel@tonic-gate rv = initRuleValue(1, rvIn); 20757c478bd9Sstevel@tonic-gate if (rv == 0) 20767c478bd9Sstevel@tonic-gate return (LDAP_NO_MEMORY); 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate delAttrFromRuleValue(rv, "objectClass"); 20797c478bd9Sstevel@tonic-gate rv = addObjectClasses(rv, objClassAttrs); 20807c478bd9Sstevel@tonic-gate if (rv == 0) { 20817c478bd9Sstevel@tonic-gate stat = LDAP_OPERATIONS_ERROR; 20827c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 20837c478bd9Sstevel@tonic-gate "%s: addObjectClasses failed for %s", 20847c478bd9Sstevel@tonic-gate myself, NIL(dn)); 20857c478bd9Sstevel@tonic-gate goto cleanup; 20867c478bd9Sstevel@tonic-gate } 20877c478bd9Sstevel@tonic-gate 20887c478bd9Sstevel@tonic-gate /* 20897c478bd9Sstevel@tonic-gate * Before adding the object classes whole-sale, try retrieving 20907c478bd9Sstevel@tonic-gate * the entry specified by the 'dn'. If it exists, we filter out 20917c478bd9Sstevel@tonic-gate * those object classes that already are present in LDAP from our 20927c478bd9Sstevel@tonic-gate * update. 20937c478bd9Sstevel@tonic-gate */ 20947c478bd9Sstevel@tonic-gate ls = buildLdapSearch(dn, LDAP_SCOPE_BASE, 0, 0, "objectClass=*", 20957c478bd9Sstevel@tonic-gate oc, 0, 1); 20967c478bd9Sstevel@tonic-gate if (ls == 0) { 20977c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 20987c478bd9Sstevel@tonic-gate "%s: Unable to build DN search for \"%s\"", 20997c478bd9Sstevel@tonic-gate myself, NIL(dn)); 21007c478bd9Sstevel@tonic-gate /* Fall through to try just adding the object classes */ 21017c478bd9Sstevel@tonic-gate goto addObjectClasses; 21027c478bd9Sstevel@tonic-gate } 21037c478bd9Sstevel@tonic-gate 21047c478bd9Sstevel@tonic-gate nv = 0; 21057c478bd9Sstevel@tonic-gate rvldap = ldapSearch(ls, &nv, 0, &lderr); 21067c478bd9Sstevel@tonic-gate freeLdapSearch(ls); 21077c478bd9Sstevel@tonic-gate if (rvldap == 0) { 21087c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 21097c478bd9Sstevel@tonic-gate "%s: No data for DN search (\"%s\"); LDAP status %d", 21107c478bd9Sstevel@tonic-gate myself, NIL(dn), lderr); 21117c478bd9Sstevel@tonic-gate /* Fall through to try just adding the object classes */ 21127c478bd9Sstevel@tonic-gate goto addObjectClasses; 21137c478bd9Sstevel@tonic-gate } 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate /* 21167c478bd9Sstevel@tonic-gate * Find the indices of the 'objectClass' attribute 21177c478bd9Sstevel@tonic-gate * in 'rvldap' and 'rv'. 21187c478bd9Sstevel@tonic-gate */ 21197c478bd9Sstevel@tonic-gate for (i = 0, ocrvldap = -1; i < rvldap->numAttrs; i++) { 21207c478bd9Sstevel@tonic-gate if (rvldap->attrName[i] != 0 && 21217c478bd9Sstevel@tonic-gate strcasecmp("objectClass", rvldap->attrName[i]) == 0) { 21227c478bd9Sstevel@tonic-gate ocrvldap = i; 21237c478bd9Sstevel@tonic-gate break; 21247c478bd9Sstevel@tonic-gate } 21257c478bd9Sstevel@tonic-gate } 21267c478bd9Sstevel@tonic-gate for (i = 0, ocrv = -1; i < rv->numAttrs; i++) { 21277c478bd9Sstevel@tonic-gate if (rv->attrName[i] != 0 && 21287c478bd9Sstevel@tonic-gate strcasecmp("objectClass", rv->attrName[i]) == 0) { 21297c478bd9Sstevel@tonic-gate ocrv = i; 21307c478bd9Sstevel@tonic-gate break; 21317c478bd9Sstevel@tonic-gate } 21327c478bd9Sstevel@tonic-gate } 21337c478bd9Sstevel@tonic-gate 21347c478bd9Sstevel@tonic-gate /* 21357c478bd9Sstevel@tonic-gate * Remove those object classes that already exist 21367c478bd9Sstevel@tonic-gate * in LDAP (i.e., in 'rvldap') from 'rv'. 21377c478bd9Sstevel@tonic-gate */ 21387c478bd9Sstevel@tonic-gate if (ocrv >= 0 && ocrvldap >= 0) { 21397c478bd9Sstevel@tonic-gate for (i = 0; i < rvldap->attrVal[ocrvldap].numVals; i++) { 21407c478bd9Sstevel@tonic-gate removeSingleValue(&rv->attrVal[ocrv], 21417c478bd9Sstevel@tonic-gate rvldap->attrVal[ocrvldap].val[i].value, 21427c478bd9Sstevel@tonic-gate rvldap->attrVal[ocrvldap].val[i].length); 21437c478bd9Sstevel@tonic-gate } 21447c478bd9Sstevel@tonic-gate /* 21457c478bd9Sstevel@tonic-gate * If no 'objectClass' values left in 'rv', delete 21467c478bd9Sstevel@tonic-gate * 'objectClass' from 'rv'. 21477c478bd9Sstevel@tonic-gate */ 21487c478bd9Sstevel@tonic-gate if (rv->attrVal[ocrv].numVals == 0) 21497c478bd9Sstevel@tonic-gate delAttrFromRuleValue(rv, "objectClass"); 21507c478bd9Sstevel@tonic-gate } 21517c478bd9Sstevel@tonic-gate 21527c478bd9Sstevel@tonic-gate /* 21537c478bd9Sstevel@tonic-gate * 'rv' now contains the update we want to make, with just the 21547c478bd9Sstevel@tonic-gate * object class(es) that need to be added. Fall through to the 21557c478bd9Sstevel@tonic-gate * actual LDAP modify operation. 21567c478bd9Sstevel@tonic-gate */ 21577c478bd9Sstevel@tonic-gate freeRuleValue(rvldap, 1); 21587c478bd9Sstevel@tonic-gate 21597c478bd9Sstevel@tonic-gate addObjectClasses: 21607c478bd9Sstevel@tonic-gate 21617c478bd9Sstevel@tonic-gate mods = search2LdapMod(rv, 0, 1); 21627c478bd9Sstevel@tonic-gate if (mods == 0) { 21637c478bd9Sstevel@tonic-gate stat = LDAP_OPERATIONS_ERROR; 21647c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 21657c478bd9Sstevel@tonic-gate "%s: Unable to create LDAP modify changes with object classes for %s", 21667c478bd9Sstevel@tonic-gate myself, NIL(dn)); 21677c478bd9Sstevel@tonic-gate goto cleanup; 21687c478bd9Sstevel@tonic-gate } 21697c478bd9Sstevel@tonic-gate msgid = ldap_modify((*lc)->ld, dn, mods); 21707c478bd9Sstevel@tonic-gate if (msgid != -1) { 21717c478bd9Sstevel@tonic-gate tv = (*lc)->modifyTimeout; 21727c478bd9Sstevel@tonic-gate stat = ldap_result((*lc)->ld, msgid, 0, &tv, &msg); 21737c478bd9Sstevel@tonic-gate if (stat == 0) { 21747c478bd9Sstevel@tonic-gate stat = LDAP_TIMEOUT; 21757c478bd9Sstevel@tonic-gate } else if (stat == -1) { 21767c478bd9Sstevel@tonic-gate (void) ldap_get_option((*lc)->ld, 21777c478bd9Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, &stat); 21787c478bd9Sstevel@tonic-gate } else { 21797c478bd9Sstevel@tonic-gate stat = ldap_parse_result((*lc)->ld, msg, &lderr, NULL, 21807c478bd9Sstevel@tonic-gate NULL, &referralsp, NULL, 0); 21817c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) 21827c478bd9Sstevel@tonic-gate stat = lderr; 21837c478bd9Sstevel@tonic-gate stat = ldap_result2error((*lc)->ld, msg, 0); 21847c478bd9Sstevel@tonic-gate } 21857c478bd9Sstevel@tonic-gate } else { 21867c478bd9Sstevel@tonic-gate (void) ldap_get_option((*lc)->ld, LDAP_OPT_ERROR_NUMBER, 21877c478bd9Sstevel@tonic-gate &stat); 21887c478bd9Sstevel@tonic-gate } 21897c478bd9Sstevel@tonic-gate if (proxyInfo.follow_referral == follow && 21907c478bd9Sstevel@tonic-gate stat == LDAP_REFERRAL && referralsp != NULL) { 21917c478bd9Sstevel@tonic-gate releaseCon(*lc, stat); 21927c478bd9Sstevel@tonic-gate if (msg != NULL) 21937c478bd9Sstevel@tonic-gate (void) ldap_msgfree(msg); 21947c478bd9Sstevel@tonic-gate msg = NULL; 21957c478bd9Sstevel@tonic-gate *lc = findReferralCon(referralsp, &stat); 21967c478bd9Sstevel@tonic-gate ldap_value_free(referralsp); 21977c478bd9Sstevel@tonic-gate referralsp = NULL; 21987c478bd9Sstevel@tonic-gate if (*lc == NULL) 21997c478bd9Sstevel@tonic-gate goto cleanup; 22007c478bd9Sstevel@tonic-gate msgid = ldap_modify((*lc)->ld, dn, mods); 22017c478bd9Sstevel@tonic-gate if (msgid == -1) { 22027c478bd9Sstevel@tonic-gate (void) ldap_get_option((*lc)->ld, 22037c478bd9Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, &stat); 22047c478bd9Sstevel@tonic-gate goto cleanup; 22057c478bd9Sstevel@tonic-gate } 22067c478bd9Sstevel@tonic-gate stat = ldap_result((*lc)->ld, msgid, 0, &tv, &msg); 22077c478bd9Sstevel@tonic-gate if (stat == 0) { 22087c478bd9Sstevel@tonic-gate stat = LDAP_TIMEOUT; 22097c478bd9Sstevel@tonic-gate } else if (stat == -1) { 22107c478bd9Sstevel@tonic-gate (void) ldap_get_option((*lc)->ld, 22117c478bd9Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, &stat); 22127c478bd9Sstevel@tonic-gate } else { 22137c478bd9Sstevel@tonic-gate stat = ldap_parse_result((*lc)->ld, msg, &lderr, 22147c478bd9Sstevel@tonic-gate NULL, NULL, NULL, NULL, 0); 22157c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) 22167c478bd9Sstevel@tonic-gate stat = lderr; 22177c478bd9Sstevel@tonic-gate } 22187c478bd9Sstevel@tonic-gate } 22197c478bd9Sstevel@tonic-gate cleanup: 22207c478bd9Sstevel@tonic-gate if (mods != 0) 22217c478bd9Sstevel@tonic-gate freeLdapMod(mods); 22227c478bd9Sstevel@tonic-gate freeRuleValue(rv, 1); 22237c478bd9Sstevel@tonic-gate return (stat); 22247c478bd9Sstevel@tonic-gate } 22257c478bd9Sstevel@tonic-gate 22267c478bd9Sstevel@tonic-gate /* 22277c478bd9Sstevel@tonic-gate * Modify the specified 'dn' per the attribute names/values in 'rv'. 22287c478bd9Sstevel@tonic-gate * If 'rv' is NULL, we attempt to delete the entire entry. 22297c478bd9Sstevel@tonic-gate * 22307c478bd9Sstevel@tonic-gate * The 'objClassAttrs' parameter is needed if the entry must be added 22317c478bd9Sstevel@tonic-gate * (i.e., created), or a modify fails with an object class violation. 22327c478bd9Sstevel@tonic-gate * 22337c478bd9Sstevel@tonic-gate * If 'addFirst' is set, we try an add before a modify; modify before 22347c478bd9Sstevel@tonic-gate * add otherwise (ignored if we're deleting). 22357c478bd9Sstevel@tonic-gate */ 22367c478bd9Sstevel@tonic-gate int 22377c478bd9Sstevel@tonic-gate ldapModify(char *dn, __nis_rule_value_t *rv, char *objClassAttrs, 22387c478bd9Sstevel@tonic-gate int addFirst) { 22397c478bd9Sstevel@tonic-gate int stat, add = 0; 22407c478bd9Sstevel@tonic-gate LDAPMod **mods = 0; 22417c478bd9Sstevel@tonic-gate __nis_ldap_conn_t *lc; 22427c478bd9Sstevel@tonic-gate struct timeval tv; 22437c478bd9Sstevel@tonic-gate LDAPMessage *msg = 0; 22447c478bd9Sstevel@tonic-gate char *myself = "ldapModify"; 22457c478bd9Sstevel@tonic-gate int msgid; 22467c478bd9Sstevel@tonic-gate int lderr; 22477c478bd9Sstevel@tonic-gate char **referralsp = NULL; 22487c478bd9Sstevel@tonic-gate bool_t delete = FALSE; 22497c478bd9Sstevel@tonic-gate 22507c478bd9Sstevel@tonic-gate if (dn == 0) 22517c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 22527c478bd9Sstevel@tonic-gate 22537c478bd9Sstevel@tonic-gate if ((lc = findCon(&stat)) == 0) 22547c478bd9Sstevel@tonic-gate return (stat); 22557c478bd9Sstevel@tonic-gate 22567c478bd9Sstevel@tonic-gate if (rv == 0) { 22577c478bd9Sstevel@tonic-gate delete = TRUE; 22587c478bd9Sstevel@tonic-gate /* Simple case: if rv == 0, try to delete the entire entry */ 22597c478bd9Sstevel@tonic-gate msgid = ldap_delete(lc->ld, dn); 22607c478bd9Sstevel@tonic-gate if (msgid == -1) { 22617c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, 22627c478bd9Sstevel@tonic-gate &stat); 22637c478bd9Sstevel@tonic-gate goto cleanup; 22647c478bd9Sstevel@tonic-gate } 22657c478bd9Sstevel@tonic-gate tv = lc->deleteTimeout; 22667c478bd9Sstevel@tonic-gate stat = ldap_result(lc->ld, msgid, 0, &tv, &msg); 22677c478bd9Sstevel@tonic-gate 22687c478bd9Sstevel@tonic-gate if (stat == 0) { 22697c478bd9Sstevel@tonic-gate stat = LDAP_TIMEOUT; 22707c478bd9Sstevel@tonic-gate } else if (stat == -1) { 22717c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, 22727c478bd9Sstevel@tonic-gate &stat); 22737c478bd9Sstevel@tonic-gate } else { 22747c478bd9Sstevel@tonic-gate stat = ldap_parse_result(lc->ld, msg, &lderr, NULL, 22757c478bd9Sstevel@tonic-gate NULL, &referralsp, NULL, 0); 22767c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) 22777c478bd9Sstevel@tonic-gate stat = lderr; 22787c478bd9Sstevel@tonic-gate } 22797c478bd9Sstevel@tonic-gate if (proxyInfo.follow_referral == follow && 22807c478bd9Sstevel@tonic-gate stat == LDAP_REFERRAL && referralsp != NULL) { 22817c478bd9Sstevel@tonic-gate releaseCon(lc, stat); 22827c478bd9Sstevel@tonic-gate if (msg != NULL) 22837c478bd9Sstevel@tonic-gate (void) ldap_msgfree(msg); 22847c478bd9Sstevel@tonic-gate msg = NULL; 22857c478bd9Sstevel@tonic-gate lc = findReferralCon(referralsp, &stat); 22867c478bd9Sstevel@tonic-gate ldap_value_free(referralsp); 22877c478bd9Sstevel@tonic-gate if (lc == NULL) 22887c478bd9Sstevel@tonic-gate goto cleanup; 22897c478bd9Sstevel@tonic-gate msgid = ldap_delete(lc->ld, dn); 22907c478bd9Sstevel@tonic-gate if (msgid == -1) { 22917c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, 22927c478bd9Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, &stat); 22937c478bd9Sstevel@tonic-gate goto cleanup; 22947c478bd9Sstevel@tonic-gate } 22957c478bd9Sstevel@tonic-gate stat = ldap_result(lc->ld, msgid, 0, &tv, &msg); 22967c478bd9Sstevel@tonic-gate if (stat == 0) { 22977c478bd9Sstevel@tonic-gate stat = LDAP_TIMEOUT; 22987c478bd9Sstevel@tonic-gate } else if (stat == -1) { 22997c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, 23007c478bd9Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, &stat); 23017c478bd9Sstevel@tonic-gate } else { 23027c478bd9Sstevel@tonic-gate stat = ldap_parse_result(lc->ld, msg, &lderr, 23037c478bd9Sstevel@tonic-gate NULL, NULL, NULL, NULL, 0); 23047c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) 23057c478bd9Sstevel@tonic-gate stat = lderr; 23067c478bd9Sstevel@tonic-gate } 23077c478bd9Sstevel@tonic-gate } 23087c478bd9Sstevel@tonic-gate /* No such object means someone else has done our job */ 23097c478bd9Sstevel@tonic-gate if (stat == LDAP_NO_SUCH_OBJECT) 23107c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 23117c478bd9Sstevel@tonic-gate } else { 23127c478bd9Sstevel@tonic-gate if (addFirst) { 23137c478bd9Sstevel@tonic-gate stat = ldapAdd(dn, rv, objClassAttrs, lc); 23147c478bd9Sstevel@tonic-gate lc = NULL; 23157c478bd9Sstevel@tonic-gate if (stat != LDAP_ALREADY_EXISTS) 23167c478bd9Sstevel@tonic-gate goto cleanup; 23177c478bd9Sstevel@tonic-gate if ((lc = findCon(&stat)) == 0) 23187c478bd9Sstevel@tonic-gate return (stat); 23197c478bd9Sstevel@tonic-gate } 23207c478bd9Sstevel@tonic-gate 23217c478bd9Sstevel@tonic-gate /* 23227c478bd9Sstevel@tonic-gate * First try the modify without specifying object classes 23237c478bd9Sstevel@tonic-gate * (i.e., assume they're already present). 23247c478bd9Sstevel@tonic-gate */ 23257c478bd9Sstevel@tonic-gate mods = search2LdapMod(rv, 0, 0); 23267c478bd9Sstevel@tonic-gate if (mods == 0) { 23277c478bd9Sstevel@tonic-gate stat = LDAP_PARAM_ERROR; 23287c478bd9Sstevel@tonic-gate goto cleanup; 23297c478bd9Sstevel@tonic-gate } 23307c478bd9Sstevel@tonic-gate 23317c478bd9Sstevel@tonic-gate msgid = ldap_modify(lc->ld, dn, mods); 23327c478bd9Sstevel@tonic-gate if (msgid == -1) { 23337c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, 23347c478bd9Sstevel@tonic-gate &stat); 23357c478bd9Sstevel@tonic-gate goto cleanup; 23367c478bd9Sstevel@tonic-gate } 23377c478bd9Sstevel@tonic-gate tv = lc->modifyTimeout; 23387c478bd9Sstevel@tonic-gate stat = ldap_result(lc->ld, msgid, 0, &tv, &msg); 23397c478bd9Sstevel@tonic-gate if (stat == 0) { 23407c478bd9Sstevel@tonic-gate stat = LDAP_TIMEOUT; 23417c478bd9Sstevel@tonic-gate } else if (stat == -1) { 23427c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, 23437c478bd9Sstevel@tonic-gate &stat); 23447c478bd9Sstevel@tonic-gate } else { 23457c478bd9Sstevel@tonic-gate stat = ldap_parse_result(lc->ld, msg, &lderr, NULL, 23467c478bd9Sstevel@tonic-gate NULL, &referralsp, NULL, 0); 23477c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) 23487c478bd9Sstevel@tonic-gate stat = lderr; 23497c478bd9Sstevel@tonic-gate } 23507c478bd9Sstevel@tonic-gate if (proxyInfo.follow_referral == follow && 23517c478bd9Sstevel@tonic-gate stat == LDAP_REFERRAL && referralsp != NULL) { 23527c478bd9Sstevel@tonic-gate releaseCon(lc, stat); 23537c478bd9Sstevel@tonic-gate if (msg != NULL) 23547c478bd9Sstevel@tonic-gate (void) ldap_msgfree(msg); 23557c478bd9Sstevel@tonic-gate msg = NULL; 23567c478bd9Sstevel@tonic-gate lc = findReferralCon(referralsp, &stat); 23577c478bd9Sstevel@tonic-gate ldap_value_free(referralsp); 23587c478bd9Sstevel@tonic-gate referralsp = NULL; 23597c478bd9Sstevel@tonic-gate if (lc == NULL) 23607c478bd9Sstevel@tonic-gate goto cleanup; 23617c478bd9Sstevel@tonic-gate msgid = ldap_modify(lc->ld, dn, mods); 23627c478bd9Sstevel@tonic-gate if (msgid == -1) { 23637c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, 23647c478bd9Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, &stat); 23657c478bd9Sstevel@tonic-gate goto cleanup; 23667c478bd9Sstevel@tonic-gate } 23677c478bd9Sstevel@tonic-gate stat = ldap_result(lc->ld, msgid, 0, &tv, &msg); 23687c478bd9Sstevel@tonic-gate if (stat == 0) { 23697c478bd9Sstevel@tonic-gate stat = LDAP_TIMEOUT; 23707c478bd9Sstevel@tonic-gate } else if (stat == -1) { 23717c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, 23727c478bd9Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, &stat); 23737c478bd9Sstevel@tonic-gate } else { 23747c478bd9Sstevel@tonic-gate stat = ldap_parse_result(lc->ld, msg, &lderr, 23757c478bd9Sstevel@tonic-gate NULL, NULL, NULL, NULL, 0); 23767c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) 23777c478bd9Sstevel@tonic-gate stat = lderr; 23787c478bd9Sstevel@tonic-gate } 23797c478bd9Sstevel@tonic-gate } 23807c478bd9Sstevel@tonic-gate 23817c478bd9Sstevel@tonic-gate /* 23827c478bd9Sstevel@tonic-gate * If the modify failed with an object class violation, 23837c478bd9Sstevel@tonic-gate * the most probable reason is that at least on of the 23847c478bd9Sstevel@tonic-gate * attributes we're modifying didn't exist before, and 23857c478bd9Sstevel@tonic-gate * neither did its object class. So, try the modify again, 23867c478bd9Sstevel@tonic-gate * but add the object classes this time. 23877c478bd9Sstevel@tonic-gate */ 23887c478bd9Sstevel@tonic-gate if (stat == LDAP_OBJECT_CLASS_VIOLATION && 23897c478bd9Sstevel@tonic-gate objClassAttrs != 0) { 23907c478bd9Sstevel@tonic-gate freeLdapMod(mods); 23917c478bd9Sstevel@tonic-gate mods = 0; 23927c478bd9Sstevel@tonic-gate stat = ldapModifyObjectClass(&lc, dn, rv, 23937c478bd9Sstevel@tonic-gate objClassAttrs); 23947c478bd9Sstevel@tonic-gate } 23957c478bd9Sstevel@tonic-gate 23967c478bd9Sstevel@tonic-gate if (stat == LDAP_NO_SUCH_ATTRIBUTE) { 23977c478bd9Sstevel@tonic-gate /* 23987c478bd9Sstevel@tonic-gate * If there was at least one attribute delete, then 23997c478bd9Sstevel@tonic-gate * the cause of this error could be that said attribute 24007c478bd9Sstevel@tonic-gate * didn't exist in LDAP. So, do things the slow way, 24017c478bd9Sstevel@tonic-gate * and try to delete one attribute at a time. 24027c478bd9Sstevel@tonic-gate */ 24037c478bd9Sstevel@tonic-gate int d, numDelete, st; 24047c478bd9Sstevel@tonic-gate __nis_rule_value_t *rvt; 24057c478bd9Sstevel@tonic-gate 24067c478bd9Sstevel@tonic-gate for (d = 0, numDelete = 0; d < rv->numAttrs; d++) { 24077c478bd9Sstevel@tonic-gate if (rv->attrVal[d].numVals < 0) 24087c478bd9Sstevel@tonic-gate numDelete++; 24097c478bd9Sstevel@tonic-gate } 24107c478bd9Sstevel@tonic-gate 24117c478bd9Sstevel@tonic-gate /* If there's just one, we've already tried */ 24127c478bd9Sstevel@tonic-gate if (numDelete <= 1) 24137c478bd9Sstevel@tonic-gate goto cleanup; 24147c478bd9Sstevel@tonic-gate 24157c478bd9Sstevel@tonic-gate /* Make a copy of the rule value */ 24167c478bd9Sstevel@tonic-gate rvt = initRuleValue(1, rv); 24177c478bd9Sstevel@tonic-gate if (rvt == 0) 24187c478bd9Sstevel@tonic-gate goto cleanup; 24197c478bd9Sstevel@tonic-gate 24207c478bd9Sstevel@tonic-gate /* 24217c478bd9Sstevel@tonic-gate * Remove all delete attributes from the tmp 24227c478bd9Sstevel@tonic-gate * rule value. 24237c478bd9Sstevel@tonic-gate */ 24247c478bd9Sstevel@tonic-gate for (d = 0; d < rv->numAttrs; d++) { 24257c478bd9Sstevel@tonic-gate if (rv->attrVal[d].numVals < 0) { 24267c478bd9Sstevel@tonic-gate delAttrFromRuleValue(rvt, 24277c478bd9Sstevel@tonic-gate rv->attrName[d]); 24287c478bd9Sstevel@tonic-gate } 24297c478bd9Sstevel@tonic-gate } 24307c478bd9Sstevel@tonic-gate 24317c478bd9Sstevel@tonic-gate /* 24327c478bd9Sstevel@tonic-gate * Now put the attributes back in one by one, and 24337c478bd9Sstevel@tonic-gate * invoke ourselves. 24347c478bd9Sstevel@tonic-gate */ 24357c478bd9Sstevel@tonic-gate for (d = 0; d < rv->numAttrs; d++) { 24367c478bd9Sstevel@tonic-gate if (rv->attrVal[d].numVals >= 0) 24377c478bd9Sstevel@tonic-gate continue; 24387c478bd9Sstevel@tonic-gate st = addAttr2RuleValue(rv->attrVal[d].type, 24397c478bd9Sstevel@tonic-gate rv->attrName[d], 0, 0, rvt); 24407c478bd9Sstevel@tonic-gate if (st != 0) { 24417c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, 24427c478bd9Sstevel@tonic-gate "%s: Error deleting \"%s\" for \"%s\"", 24437c478bd9Sstevel@tonic-gate NIL(rv->attrName[d]), NIL(dn)); 24447c478bd9Sstevel@tonic-gate stat = LDAP_NO_MEMORY; 24457c478bd9Sstevel@tonic-gate freeRuleValue(rvt, 1); 24467c478bd9Sstevel@tonic-gate goto cleanup; 24477c478bd9Sstevel@tonic-gate } 24487c478bd9Sstevel@tonic-gate stat = ldapModify(dn, rvt, objClassAttrs, 0); 24497c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS && 24507c478bd9Sstevel@tonic-gate stat != LDAP_NO_SUCH_ATTRIBUTE) { 24517c478bd9Sstevel@tonic-gate freeRuleValue(rvt, 1); 24527c478bd9Sstevel@tonic-gate goto cleanup; 24537c478bd9Sstevel@tonic-gate } 24547c478bd9Sstevel@tonic-gate delAttrFromRuleValue(rvt, rv->attrName[d]); 24557c478bd9Sstevel@tonic-gate } 24567c478bd9Sstevel@tonic-gate 24577c478bd9Sstevel@tonic-gate /* 24587c478bd9Sstevel@tonic-gate * If we got here, then all attributes that should 24597c478bd9Sstevel@tonic-gate * be deleted either have been, or didn't exist. For 24607c478bd9Sstevel@tonic-gate * our purposes, the latter is as good as the former. 24617c478bd9Sstevel@tonic-gate */ 24627c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 24637c478bd9Sstevel@tonic-gate freeRuleValue(rvt, 1); 24647c478bd9Sstevel@tonic-gate } 24657c478bd9Sstevel@tonic-gate 24667c478bd9Sstevel@tonic-gate if (stat == LDAP_NO_SUCH_OBJECT && !addFirst) { 24677c478bd9Sstevel@tonic-gate /* 24687c478bd9Sstevel@tonic-gate * Entry doesn't exist, so try an ldap_add(). If the 24697c478bd9Sstevel@tonic-gate * ldap_add() also fails, that could be because someone 24707c478bd9Sstevel@tonic-gate * else added it between our modify and add operations. 24717c478bd9Sstevel@tonic-gate * If so, we consider that foreign add to be 24727c478bd9Sstevel@tonic-gate * authoritative (meaning we don't retry our modify). 24737c478bd9Sstevel@tonic-gate * 24747c478bd9Sstevel@tonic-gate * Also, if all modify operations specified by 'mods' 24757c478bd9Sstevel@tonic-gate * are deletes, LDAP_NO_SUCH_OBJECT is a kind of 24767c478bd9Sstevel@tonic-gate * success; we certainly don't want to create the 24777c478bd9Sstevel@tonic-gate * entry. 24787c478bd9Sstevel@tonic-gate */ 24797c478bd9Sstevel@tonic-gate int allDelete; 24807c478bd9Sstevel@tonic-gate LDAPMod **m; 24817c478bd9Sstevel@tonic-gate 24827c478bd9Sstevel@tonic-gate for (m = mods, allDelete = 1; *m != 0 && allDelete; 24837c478bd9Sstevel@tonic-gate m++) { 24847c478bd9Sstevel@tonic-gate if (((*m)->mod_op & LDAP_MOD_DELETE) == 0) 24857c478bd9Sstevel@tonic-gate allDelete = 0; 24867c478bd9Sstevel@tonic-gate } 24877c478bd9Sstevel@tonic-gate 24887c478bd9Sstevel@tonic-gate add = 1; 24897c478bd9Sstevel@tonic-gate 24907c478bd9Sstevel@tonic-gate if (allDelete) { 24917c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 24927c478bd9Sstevel@tonic-gate } else if (objClassAttrs == 0) { 24937c478bd9Sstevel@tonic-gate /* Now we need it, so this is fatal */ 24947c478bd9Sstevel@tonic-gate stat = LDAP_PARAM_ERROR; 24957c478bd9Sstevel@tonic-gate } else { 24967c478bd9Sstevel@tonic-gate stat = ldapAdd(dn, rv, objClassAttrs, lc); 24977c478bd9Sstevel@tonic-gate lc = NULL; 24987c478bd9Sstevel@tonic-gate } 24997c478bd9Sstevel@tonic-gate } 25007c478bd9Sstevel@tonic-gate } 25017c478bd9Sstevel@tonic-gate 25027c478bd9Sstevel@tonic-gate cleanup: 25037c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 25047c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 25057c478bd9Sstevel@tonic-gate "%s(0x%x (%s), \"%s\") => %d (%s)\n", 25067c478bd9Sstevel@tonic-gate !delete ? (add ? "ldap_add" : "ldap_modify") : 25077c478bd9Sstevel@tonic-gate "ldap_delete", 25087c478bd9Sstevel@tonic-gate lc != NULL ? lc->ld : 0, 25097c478bd9Sstevel@tonic-gate lc != NULL ? NIL(lc->sp) : "nil", 25107c478bd9Sstevel@tonic-gate dn, stat, ldap_err2string(stat)); 25117c478bd9Sstevel@tonic-gate } 25127c478bd9Sstevel@tonic-gate 25137c478bd9Sstevel@tonic-gate releaseCon(lc, stat); 25147c478bd9Sstevel@tonic-gate freeLdapMod(mods); 25157c478bd9Sstevel@tonic-gate if (msg != 0) 25167c478bd9Sstevel@tonic-gate (void) ldap_msgfree(msg); 25177c478bd9Sstevel@tonic-gate 25187c478bd9Sstevel@tonic-gate return (stat); 25197c478bd9Sstevel@tonic-gate } 25207c478bd9Sstevel@tonic-gate 25217c478bd9Sstevel@tonic-gate /* 25227c478bd9Sstevel@tonic-gate * Create the entry specified by 'dn' to have the values per 'rv'. 25237c478bd9Sstevel@tonic-gate * The 'objClassAttrs' are the extra object classes we need when 25247c478bd9Sstevel@tonic-gate * creating an entry. 25257c478bd9Sstevel@tonic-gate * 25267c478bd9Sstevel@tonic-gate * If 'lc' is non-NULL, we use that connection; otherwise, we find 25277c478bd9Sstevel@tonic-gate * our own. CAUTION: This connection will be released on return. Regardless 25287c478bd9Sstevel@tonic-gate * of return value, this connection should not subsequently used by the 25297c478bd9Sstevel@tonic-gate * caller. 25307c478bd9Sstevel@tonic-gate * 25317c478bd9Sstevel@tonic-gate * Returns an LDAP status. 25327c478bd9Sstevel@tonic-gate */ 25337c478bd9Sstevel@tonic-gate int 25347c478bd9Sstevel@tonic-gate ldapAdd(char *dn, __nis_rule_value_t *rv, char *objClassAttrs, void *lcv) { 25357c478bd9Sstevel@tonic-gate int stat; 25367c478bd9Sstevel@tonic-gate LDAPMod **mods = 0; 25377c478bd9Sstevel@tonic-gate struct timeval tv; 25387c478bd9Sstevel@tonic-gate LDAPMessage *msg = 0; 25397c478bd9Sstevel@tonic-gate __nis_ldap_conn_t *lc = lcv; 25407c478bd9Sstevel@tonic-gate int msgid; 25417c478bd9Sstevel@tonic-gate int lderr; 25427c478bd9Sstevel@tonic-gate char **referralsp = NULL; 25437c478bd9Sstevel@tonic-gate 25447c478bd9Sstevel@tonic-gate if (dn == 0 || rv == 0 || objClassAttrs == 0) { 25457c478bd9Sstevel@tonic-gate releaseCon(lc, LDAP_SUCCESS); 25467c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 25477c478bd9Sstevel@tonic-gate } 25487c478bd9Sstevel@tonic-gate 25497c478bd9Sstevel@tonic-gate if (lc == 0) { 25507c478bd9Sstevel@tonic-gate if ((lc = findCon(&stat)) == 0) 25517c478bd9Sstevel@tonic-gate return (stat); 25527c478bd9Sstevel@tonic-gate } 25537c478bd9Sstevel@tonic-gate 25547c478bd9Sstevel@tonic-gate rv = addObjectClasses(rv, objClassAttrs); 25557c478bd9Sstevel@tonic-gate if (rv == 0) { 25567c478bd9Sstevel@tonic-gate stat = LDAP_OPERATIONS_ERROR; 25577c478bd9Sstevel@tonic-gate goto cleanup; 25587c478bd9Sstevel@tonic-gate } 25597c478bd9Sstevel@tonic-gate 25607c478bd9Sstevel@tonic-gate mods = search2LdapMod(rv, 1, 0); 25617c478bd9Sstevel@tonic-gate if (mods == 0) { 25627c478bd9Sstevel@tonic-gate stat = LDAP_OPERATIONS_ERROR; 25637c478bd9Sstevel@tonic-gate goto cleanup; 25647c478bd9Sstevel@tonic-gate } 25657c478bd9Sstevel@tonic-gate 25667c478bd9Sstevel@tonic-gate msgid = ldap_add(lc->ld, dn, mods); 25677c478bd9Sstevel@tonic-gate if (msgid == -1) { 25687c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, &stat); 25697c478bd9Sstevel@tonic-gate goto cleanup; 25707c478bd9Sstevel@tonic-gate } 25717c478bd9Sstevel@tonic-gate tv = lc->addTimeout; 25727c478bd9Sstevel@tonic-gate stat = ldap_result(lc->ld, msgid, 0, &tv, &msg); 25737c478bd9Sstevel@tonic-gate if (stat == 0) { 25747c478bd9Sstevel@tonic-gate stat = LDAP_TIMEOUT; 25757c478bd9Sstevel@tonic-gate } else if (stat == -1) { 25767c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, &stat); 25777c478bd9Sstevel@tonic-gate } else { 25787c478bd9Sstevel@tonic-gate stat = ldap_parse_result(lc->ld, msg, &lderr, NULL, NULL, 25797c478bd9Sstevel@tonic-gate &referralsp, NULL, 0); 25807c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) 25817c478bd9Sstevel@tonic-gate stat = lderr; 25827c478bd9Sstevel@tonic-gate } 25837c478bd9Sstevel@tonic-gate if (proxyInfo.follow_referral == follow && stat == LDAP_REFERRAL && 25847c478bd9Sstevel@tonic-gate referralsp != NULL) { 25857c478bd9Sstevel@tonic-gate releaseCon(lc, stat); 25867c478bd9Sstevel@tonic-gate if (msg != NULL) 25877c478bd9Sstevel@tonic-gate (void) ldap_msgfree(msg); 25887c478bd9Sstevel@tonic-gate msg = NULL; 25897c478bd9Sstevel@tonic-gate lc = findReferralCon(referralsp, &stat); 25907c478bd9Sstevel@tonic-gate ldap_value_free(referralsp); 25917c478bd9Sstevel@tonic-gate if (lc == NULL) 25927c478bd9Sstevel@tonic-gate goto cleanup; 25937c478bd9Sstevel@tonic-gate msgid = ldap_add(lc->ld, dn, mods); 25947c478bd9Sstevel@tonic-gate if (msgid == -1) { 25957c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, 25967c478bd9Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, &stat); 25977c478bd9Sstevel@tonic-gate goto cleanup; 25987c478bd9Sstevel@tonic-gate } 25997c478bd9Sstevel@tonic-gate stat = ldap_result(lc->ld, msgid, 0, &tv, &msg); 26007c478bd9Sstevel@tonic-gate if (stat == 0) { 26017c478bd9Sstevel@tonic-gate stat = LDAP_TIMEOUT; 26027c478bd9Sstevel@tonic-gate } else if (stat == -1) { 26037c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, 26047c478bd9Sstevel@tonic-gate &stat); 26057c478bd9Sstevel@tonic-gate } else { 26067c478bd9Sstevel@tonic-gate stat = ldap_parse_result(lc->ld, msg, &lderr, NULL, 26077c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 0); 26087c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) 26097c478bd9Sstevel@tonic-gate stat = lderr; 26107c478bd9Sstevel@tonic-gate } 26117c478bd9Sstevel@tonic-gate } 26127c478bd9Sstevel@tonic-gate 26137c478bd9Sstevel@tonic-gate cleanup: 26147c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 26157c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 26167c478bd9Sstevel@tonic-gate "ldap_add(0x%x (%s), \"%s\") => %d (%s)\n", 26177c478bd9Sstevel@tonic-gate lc != NULL ? lc->ld : 0, 26187c478bd9Sstevel@tonic-gate lc != NULL ? NIL(lc->sp) : "nil", 26197c478bd9Sstevel@tonic-gate dn, stat, ldap_err2string(stat)); 26207c478bd9Sstevel@tonic-gate } 26217c478bd9Sstevel@tonic-gate 26227c478bd9Sstevel@tonic-gate releaseCon(lc, stat); 26237c478bd9Sstevel@tonic-gate freeLdapMod(mods); 26247c478bd9Sstevel@tonic-gate if (msg != 0) 26257c478bd9Sstevel@tonic-gate (void) ldap_msgfree(msg); 26267c478bd9Sstevel@tonic-gate 26277c478bd9Sstevel@tonic-gate return (stat); 26287c478bd9Sstevel@tonic-gate } 26297c478bd9Sstevel@tonic-gate 26307c478bd9Sstevel@tonic-gate /* 26317c478bd9Sstevel@tonic-gate * Change the entry at 'oldDn' to have the new DN (not RDN) 'dn'. 26327c478bd9Sstevel@tonic-gate * Returns an LDAP error status. 26337c478bd9Sstevel@tonic-gate */ 26347c478bd9Sstevel@tonic-gate int 26357c478bd9Sstevel@tonic-gate ldapChangeDN(char *oldDn, char *dn) { 26367c478bd9Sstevel@tonic-gate int stat; 26377c478bd9Sstevel@tonic-gate __nis_ldap_conn_t *lc; 26387c478bd9Sstevel@tonic-gate int i, j, lo, ln; 26397c478bd9Sstevel@tonic-gate char *rdn; 26407c478bd9Sstevel@tonic-gate int msgid; 26417c478bd9Sstevel@tonic-gate int lderr; 26427c478bd9Sstevel@tonic-gate struct timeval tv; 26437c478bd9Sstevel@tonic-gate LDAPMessage *msg = 0; 26447c478bd9Sstevel@tonic-gate char **referralsp = NULL; 26457c478bd9Sstevel@tonic-gate char *myself = "ldapChangeDN"; 26467c478bd9Sstevel@tonic-gate 26477c478bd9Sstevel@tonic-gate if ((lo = slen(oldDn)) <= 0 || (ln = slen(dn)) <= 0) 26487c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 26497c478bd9Sstevel@tonic-gate 26507c478bd9Sstevel@tonic-gate if (strcasecmp(oldDn, dn) == 0) 26517c478bd9Sstevel@tonic-gate return (LDAP_SUCCESS); 26527c478bd9Sstevel@tonic-gate 26537c478bd9Sstevel@tonic-gate if ((lc = findCon(&stat)) == 0) 26547c478bd9Sstevel@tonic-gate return (stat); 26557c478bd9Sstevel@tonic-gate 26567c478bd9Sstevel@tonic-gate rdn = sdup(myself, T, dn); 26577c478bd9Sstevel@tonic-gate if (rdn == 0) { 26587c478bd9Sstevel@tonic-gate releaseCon(lc, LDAP_SUCCESS); 26597c478bd9Sstevel@tonic-gate return (LDAP_NO_MEMORY); 26607c478bd9Sstevel@tonic-gate } 26617c478bd9Sstevel@tonic-gate 26627c478bd9Sstevel@tonic-gate /* Compare old and new DN from the end */ 26637c478bd9Sstevel@tonic-gate for (i = lo-1, j = ln-1; i >= 0 && j >= 0; i--, j--) { 26647c478bd9Sstevel@tonic-gate if (tolower(oldDn[i]) != tolower(rdn[j])) { 26657c478bd9Sstevel@tonic-gate /* 26667c478bd9Sstevel@tonic-gate * Terminate 'rdn' after this character in order 26677c478bd9Sstevel@tonic-gate * to snip off the portion of the new DN that is 26687c478bd9Sstevel@tonic-gate * the same as the old DN. What remains in 'rdn' 26697c478bd9Sstevel@tonic-gate * is the relative DN. 26707c478bd9Sstevel@tonic-gate */ 26717c478bd9Sstevel@tonic-gate rdn[j+1] = '\0'; 26727c478bd9Sstevel@tonic-gate break; 26737c478bd9Sstevel@tonic-gate } 26747c478bd9Sstevel@tonic-gate } 26757c478bd9Sstevel@tonic-gate 26767c478bd9Sstevel@tonic-gate stat = ldap_rename(lc->ld, oldDn, rdn, NULL, 1, NULL, NULL, &msgid); 26777c478bd9Sstevel@tonic-gate 26787c478bd9Sstevel@tonic-gate if (msgid != -1) { 26797c478bd9Sstevel@tonic-gate tv = lc->modifyTimeout; 26807c478bd9Sstevel@tonic-gate stat = ldap_result(lc->ld, msgid, 0, &tv, &msg); 26817c478bd9Sstevel@tonic-gate if (stat == 0) { 26827c478bd9Sstevel@tonic-gate stat = LDAP_TIMEOUT; 26837c478bd9Sstevel@tonic-gate } else if (stat == -1) { 26847c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, 26857c478bd9Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, &stat); 26867c478bd9Sstevel@tonic-gate } else { 26877c478bd9Sstevel@tonic-gate stat = ldap_parse_result(lc->ld, msg, &lderr, NULL, 26887c478bd9Sstevel@tonic-gate NULL, &referralsp, NULL, 0); 26897c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) 26907c478bd9Sstevel@tonic-gate stat = lderr; 26917c478bd9Sstevel@tonic-gate stat = ldap_result2error(lc->ld, msg, 0); 26927c478bd9Sstevel@tonic-gate } 26937c478bd9Sstevel@tonic-gate } else { 26947c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, 26957c478bd9Sstevel@tonic-gate &stat); 26967c478bd9Sstevel@tonic-gate } 26977c478bd9Sstevel@tonic-gate if (proxyInfo.follow_referral == follow && 26987c478bd9Sstevel@tonic-gate stat == LDAP_REFERRAL && referralsp != NULL) { 26997c478bd9Sstevel@tonic-gate releaseCon(lc, stat); 27007c478bd9Sstevel@tonic-gate if (msg != NULL) 27017c478bd9Sstevel@tonic-gate (void) ldap_msgfree(msg); 27027c478bd9Sstevel@tonic-gate msg = NULL; 27037c478bd9Sstevel@tonic-gate lc = findReferralCon(referralsp, &stat); 27047c478bd9Sstevel@tonic-gate ldap_value_free(referralsp); 27057c478bd9Sstevel@tonic-gate referralsp = NULL; 27067c478bd9Sstevel@tonic-gate if (lc == NULL) 27077c478bd9Sstevel@tonic-gate goto cleanup; 27087c478bd9Sstevel@tonic-gate msgid = ldap_rename(lc->ld, oldDn, rdn, NULL, 1, NULL, NULL, 27097c478bd9Sstevel@tonic-gate &msgid); 27107c478bd9Sstevel@tonic-gate if (msgid == -1) { 27117c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, 27127c478bd9Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, &stat); 27137c478bd9Sstevel@tonic-gate goto cleanup; 27147c478bd9Sstevel@tonic-gate } 27157c478bd9Sstevel@tonic-gate stat = ldap_result(lc->ld, msgid, 0, &tv, &msg); 27167c478bd9Sstevel@tonic-gate if (stat == 0) { 27177c478bd9Sstevel@tonic-gate stat = LDAP_TIMEOUT; 27187c478bd9Sstevel@tonic-gate } else if (stat == -1) { 27197c478bd9Sstevel@tonic-gate (void) ldap_get_option(lc->ld, 27207c478bd9Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, &stat); 27217c478bd9Sstevel@tonic-gate } else { 27227c478bd9Sstevel@tonic-gate stat = ldap_parse_result(lc->ld, msg, &lderr, 27237c478bd9Sstevel@tonic-gate NULL, NULL, NULL, NULL, 0); 27247c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) 27257c478bd9Sstevel@tonic-gate stat = lderr; 27267c478bd9Sstevel@tonic-gate } 27277c478bd9Sstevel@tonic-gate } 27287c478bd9Sstevel@tonic-gate 27297c478bd9Sstevel@tonic-gate cleanup: 27307c478bd9Sstevel@tonic-gate if (msg != NULL) 27317c478bd9Sstevel@tonic-gate (void) ldap_msgfree(msg); 27327c478bd9Sstevel@tonic-gate 27337c478bd9Sstevel@tonic-gate #if 1 27347c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: ldap_modrdn_s(0x%x, %s, %s, 1) => %s\n", 27357c478bd9Sstevel@tonic-gate myself, lc == NULL ? 0: lc->ld, NIL(oldDn), NIL(rdn), 27367c478bd9Sstevel@tonic-gate ldap_err2string(stat)); 27377c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 27387c478bd9Sstevel@tonic-gate "%s: ldap_modrdn_s(0x%x, %s, %s, 1) => %s", 27397c478bd9Sstevel@tonic-gate myself, lc == NULL ? 0: lc->ld, NIL(oldDn), NIL(rdn), 27407c478bd9Sstevel@tonic-gate ldap_err2string(stat)); 27417c478bd9Sstevel@tonic-gate #endif 27427c478bd9Sstevel@tonic-gate 27437c478bd9Sstevel@tonic-gate if (stat == LDAP_NO_SUCH_OBJECT) { 27447c478bd9Sstevel@tonic-gate /* 27457c478bd9Sstevel@tonic-gate * Fine from our point of view, since all we want to do 27467c478bd9Sstevel@tonic-gate * is to make sure that an update to the new DN doesn't 27477c478bd9Sstevel@tonic-gate * leave the old entry around. 27487c478bd9Sstevel@tonic-gate */ 27497c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 27507c478bd9Sstevel@tonic-gate } 27517c478bd9Sstevel@tonic-gate 27527c478bd9Sstevel@tonic-gate releaseCon(lc, stat); 27537c478bd9Sstevel@tonic-gate sfree(rdn); 27547c478bd9Sstevel@tonic-gate 27557c478bd9Sstevel@tonic-gate return (stat); 27567c478bd9Sstevel@tonic-gate } 2757