1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #include <lber.h> 31*7c478bd9Sstevel@tonic-gate #include <ldap.h> 32*7c478bd9Sstevel@tonic-gate #include <string.h> 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include "ldap_util.h" 35*7c478bd9Sstevel@tonic-gate #include "ldap_op.h" 36*7c478bd9Sstevel@tonic-gate #include "ldap_attr.h" 37*7c478bd9Sstevel@tonic-gate #include "ldap_ldap.h" 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate static __nis_value_t * 41*7c478bd9Sstevel@tonic-gate evalMappingElement(__nis_mapping_element_t *e, __nis_rule_value_t *rvIn) { 42*7c478bd9Sstevel@tonic-gate __nis_rule_value_t *rv = rvIn; 43*7c478bd9Sstevel@tonic-gate int freeRv = 0; 44*7c478bd9Sstevel@tonic-gate __nis_value_t *val; 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate if (rv == 0) { 47*7c478bd9Sstevel@tonic-gate rv = initRuleValue(1, 0); 48*7c478bd9Sstevel@tonic-gate if (rv == 0) 49*7c478bd9Sstevel@tonic-gate return (0); 50*7c478bd9Sstevel@tonic-gate freeRv = 1; 51*7c478bd9Sstevel@tonic-gate } 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate val = getMappingElement(e, mit_any, rv, NULL); 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate if (freeRv) 56*7c478bd9Sstevel@tonic-gate freeRuleValue(rv, 1); 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate return (val); 59*7c478bd9Sstevel@tonic-gate } 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate __nis_value_t * 62*7c478bd9Sstevel@tonic-gate lookupLDAP(__nis_search_triple_t *t, char *attrName, __nis_rule_value_t *rv, 63*7c478bd9Sstevel@tonic-gate __nis_object_dn_t *def, int *np_ldap_stat) { 64*7c478bd9Sstevel@tonic-gate __nis_value_t *val, *eVal = 0; 65*7c478bd9Sstevel@tonic-gate char *base, *filter; 66*7c478bd9Sstevel@tonic-gate __nis_ldap_search_t *ls; 67*7c478bd9Sstevel@tonic-gate char *attrs[2]; 68*7c478bd9Sstevel@tonic-gate int scope, i, stat, nrv = 0, freeBase = 0; 69*7c478bd9Sstevel@tonic-gate char *myself = "lookupLDAP"; 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate if (t == 0 || slen(attrName) <= 0) 72*7c478bd9Sstevel@tonic-gate return (0); 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate if (t->element != 0) { 75*7c478bd9Sstevel@tonic-gate /* Evaluate t->element to get the t->attrs value */ 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate eVal = evalMappingElement(t->element, rv); 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate if (eVal == 0) 80*7c478bd9Sstevel@tonic-gate return (0); 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate if (eVal->type != vt_string || eVal->numVals <= 0) { 83*7c478bd9Sstevel@tonic-gate freeValue(eVal, 1); 84*7c478bd9Sstevel@tonic-gate { 85*7c478bd9Sstevel@tonic-gate char *ename = "<unknown>"; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate eVal = evalMappingElement(t->element, 0); 88*7c478bd9Sstevel@tonic-gate if (eVal != 0 && eVal->type == vt_string && 89*7c478bd9Sstevel@tonic-gate eVal->numVals == 1 && 90*7c478bd9Sstevel@tonic-gate eVal->val[0].length > 0 && 91*7c478bd9Sstevel@tonic-gate eVal->val[0].value != 0) 92*7c478bd9Sstevel@tonic-gate ename = eVal->val[0].value; 93*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 94*7c478bd9Sstevel@tonic-gate "%s: %s: unable to evaluate filter expression \"%s\"", 95*7c478bd9Sstevel@tonic-gate myself, attrName, ename); 96*7c478bd9Sstevel@tonic-gate freeValue(eVal, 1); 97*7c478bd9Sstevel@tonic-gate } 98*7c478bd9Sstevel@tonic-gate return (0); 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate filter = eVal->val[0].value; 102*7c478bd9Sstevel@tonic-gate } else { 103*7c478bd9Sstevel@tonic-gate filter = t->attrs; 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate if (slen(t->base) > 0) { 107*7c478bd9Sstevel@tonic-gate base = appendBase(t->base, (def != 0) ? def->read.base : 0, 108*7c478bd9Sstevel@tonic-gate &stat, 0); 109*7c478bd9Sstevel@tonic-gate if (stat != 0) { 110*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 111*7c478bd9Sstevel@tonic-gate "%s: %s: error appending \"%s\" to \"%s\"", 112*7c478bd9Sstevel@tonic-gate myself, attrName, NIL(def->read.base), 113*7c478bd9Sstevel@tonic-gate NIL(t->base)); 114*7c478bd9Sstevel@tonic-gate return (0); 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate freeBase = 1; 117*7c478bd9Sstevel@tonic-gate } else { 118*7c478bd9Sstevel@tonic-gate if (def == 0 || def->read.scope == LDAP_SCOPE_UNKNOWN || 119*7c478bd9Sstevel@tonic-gate slen(def->read.base) <= 0) { 120*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 121*7c478bd9Sstevel@tonic-gate "%s: %s: no supplied or default search base", 122*7c478bd9Sstevel@tonic-gate myself, attrName); 123*7c478bd9Sstevel@tonic-gate freeValue(eVal, 1); 124*7c478bd9Sstevel@tonic-gate return (0); 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate base = def->read.base; 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate if (slen(filter) > 0) 130*7c478bd9Sstevel@tonic-gate scope = t->scope; 131*7c478bd9Sstevel@tonic-gate else 132*7c478bd9Sstevel@tonic-gate scope = LDAP_SCOPE_BASE; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate attrs[0] = attrName; 135*7c478bd9Sstevel@tonic-gate attrs[1] = 0; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate ls = buildLdapSearch(base, scope, 0, 0, filter, attrs, 0, 0); 138*7c478bd9Sstevel@tonic-gate if (ls == 0) { 139*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 140*7c478bd9Sstevel@tonic-gate "%s: %s: error building LDAP search information for \"%s?%s?%s\"", 141*7c478bd9Sstevel@tonic-gate myself, attrName, NIL(base), getScope(scope), 142*7c478bd9Sstevel@tonic-gate NIL(filter)); 143*7c478bd9Sstevel@tonic-gate freeValue(eVal, 1); 144*7c478bd9Sstevel@tonic-gate if (freeBase) 145*7c478bd9Sstevel@tonic-gate sfree(base); 146*7c478bd9Sstevel@tonic-gate return (0); 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate rv = ldapSearch(ls, &nrv, 0, &stat); 150*7c478bd9Sstevel@tonic-gate freeLdapSearch(ls); 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate /* 153*7c478bd9Sstevel@tonic-gate * If ldapSearch returns LDAP_NO_SUCH_OBJECT, then entry that 154*7c478bd9Sstevel@tonic-gate * looked for is not there in LDAP, so return NP_LDAP_NO_VALUE 155*7c478bd9Sstevel@tonic-gate * in np_ldap_stat. 156*7c478bd9Sstevel@tonic-gate */ 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate if (np_ldap_stat != NULL && stat == LDAP_NO_SUCH_OBJECT) 159*7c478bd9Sstevel@tonic-gate *np_ldap_stat = NP_LDAP_NO_VALUE; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate if (rv == 0) { 162*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 163*7c478bd9Sstevel@tonic-gate (stat == LDAP_NO_SUCH_OBJECT)?LOG_DEBUG:LOG_ERR, 164*7c478bd9Sstevel@tonic-gate "%s: %s: LDAP error %d (%s) for \"%s?%s?%s\"", 165*7c478bd9Sstevel@tonic-gate myself, attrName, stat, ldap_err2string(stat), 166*7c478bd9Sstevel@tonic-gate NIL(base), getScope(scope), NIL(filter)); 167*7c478bd9Sstevel@tonic-gate if (freeBase) 168*7c478bd9Sstevel@tonic-gate sfree(base); 169*7c478bd9Sstevel@tonic-gate freeValue(eVal, 1); 170*7c478bd9Sstevel@tonic-gate return (0); 171*7c478bd9Sstevel@tonic-gate } 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate if (freeBase) 174*7c478bd9Sstevel@tonic-gate sfree(base); 175*7c478bd9Sstevel@tonic-gate freeValue(eVal, 1); 176*7c478bd9Sstevel@tonic-gate eVal = 0; 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate for (i = 0, val = 0; i < nrv; i++) { 179*7c478bd9Sstevel@tonic-gate int j; 180*7c478bd9Sstevel@tonic-gate for (j = 0; j < rv[i].numAttrs; j++) { 181*7c478bd9Sstevel@tonic-gate if (strcasecmp(attrName, rv[i].attrName[j]) == 0) { 182*7c478bd9Sstevel@tonic-gate eVal = concatenateValues(val, 183*7c478bd9Sstevel@tonic-gate &rv[i].attrVal[j]); 184*7c478bd9Sstevel@tonic-gate freeValue(val, 1); 185*7c478bd9Sstevel@tonic-gate if (eVal == 0) { 186*7c478bd9Sstevel@tonic-gate freeRuleValue(rv, nrv); 187*7c478bd9Sstevel@tonic-gate return (0); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate val = eVal; 190*7c478bd9Sstevel@tonic-gate break; 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate freeRuleValue(rv, nrv); 196*7c478bd9Sstevel@tonic-gate return (val); 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate /* 200*7c478bd9Sstevel@tonic-gate * Store 'val' at the LDAP location indicated by 'item'. As usual, 201*7c478bd9Sstevel@tonic-gate * val->numVals == -1 indicates deletion. 202*7c478bd9Sstevel@tonic-gate * 203*7c478bd9Sstevel@tonic-gate * The 'index' and 'numIndexes' parameters are used as follows: 204*7c478bd9Sstevel@tonic-gate * 205*7c478bd9Sstevel@tonic-gate * index < 0 || index >= numIndexes 206*7c478bd9Sstevel@tonic-gate * Illegal 207*7c478bd9Sstevel@tonic-gate * 208*7c478bd9Sstevel@tonic-gate * index >= val->numVals 209*7c478bd9Sstevel@tonic-gate * Store val->val[val->numVals-1] 210*7c478bd9Sstevel@tonic-gate * 211*7c478bd9Sstevel@tonic-gate * item->repeat == 0 || index < numIndexes 212*7c478bd9Sstevel@tonic-gate * Store val->val[index] 213*7c478bd9Sstevel@tonic-gate * 214*7c478bd9Sstevel@tonic-gate * Else (repeat != 0 && index == numIndexes-1) 215*7c478bd9Sstevel@tonic-gate * Store val->val[index...val->numVals-1] 216*7c478bd9Sstevel@tonic-gate * 217*7c478bd9Sstevel@tonic-gate * 'defDN' should be the default object DN specification, primarily 218*7c478bd9Sstevel@tonic-gate * used when the item search triple is invalid. Also, the defDN->write.base 219*7c478bd9Sstevel@tonic-gate * value is appended to the item search base if the latter is empty, or ends 220*7c478bd9Sstevel@tonic-gate * in a comma. 221*7c478bd9Sstevel@tonic-gate * 222*7c478bd9Sstevel@tonic-gate * If the item search triple is invalid, 'dn' must contain the DN(s) 223*7c478bd9Sstevel@tonic-gate * of the LDAP entry to be modified. If the search triple is valid, 224*7c478bd9Sstevel@tonic-gate * the DN(s) is(are) either: 225*7c478bd9Sstevel@tonic-gate * Derived via an LDAP search on the search triple 'attrs' or 226*7c478bd9Sstevel@tonic-gate * 'element' fields, or (if neither of those fields is set) 227*7c478bd9Sstevel@tonic-gate * assumed to be the search triple base. 228*7c478bd9Sstevel@tonic-gate * 229*7c478bd9Sstevel@tonic-gate * Returns LDAP_SUCCESS when successful, or an appropriate LDAP 230*7c478bd9Sstevel@tonic-gate * error status otherwise. 231*7c478bd9Sstevel@tonic-gate */ 232*7c478bd9Sstevel@tonic-gate int 233*7c478bd9Sstevel@tonic-gate storeLDAP(__nis_mapping_item_t *item, int index, int numIndexes, 234*7c478bd9Sstevel@tonic-gate __nis_value_t *val, __nis_object_dn_t *defDN, 235*7c478bd9Sstevel@tonic-gate char **dn, int numDN) { 236*7c478bd9Sstevel@tonic-gate __nis_ldap_search_t ls; 237*7c478bd9Sstevel@tonic-gate int stat, i, ix, six, nix; 238*7c478bd9Sstevel@tonic-gate int freeDN = 0; 239*7c478bd9Sstevel@tonic-gate char *locDN[1]; 240*7c478bd9Sstevel@tonic-gate __nis_rule_value_t *rv; 241*7c478bd9Sstevel@tonic-gate char *defBase = 0; 242*7c478bd9Sstevel@tonic-gate char *myself = "storeLDAP"; 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate if (item == 0 || item->type != mit_ldap || item->name == 0 || 245*7c478bd9Sstevel@tonic-gate index < 0 || index >= numIndexes || 246*7c478bd9Sstevel@tonic-gate val == 0 || val->numVals < -1 || val->numVals == 0) 247*7c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate if (defDN != 0 && slen(defDN->write.base) > 0) 250*7c478bd9Sstevel@tonic-gate defBase = defDN->write.base; 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate ls.numFilterComps = 0; 253*7c478bd9Sstevel@tonic-gate ls.filterComp = 0; 254*7c478bd9Sstevel@tonic-gate ls.numAttrs = 0; 255*7c478bd9Sstevel@tonic-gate ls.attrs = 0; 256*7c478bd9Sstevel@tonic-gate ls.isDN = 0; 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate if (item->searchSpec.triple.scope == LDAP_SCOPE_UNKNOWN) { 259*7c478bd9Sstevel@tonic-gate /* If 'defDN' is NULL, we don't know where to write */ 260*7c478bd9Sstevel@tonic-gate if (defDN == 0) 261*7c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 262*7c478bd9Sstevel@tonic-gate /* 263*7c478bd9Sstevel@tonic-gate * Check if we're supposed to write. Since we want the 264*7c478bd9Sstevel@tonic-gate * admin to be able to use the nisplusLDAPobjectDN attribute 265*7c478bd9Sstevel@tonic-gate * as an on/off switch, we don't flag failure as an error. 266*7c478bd9Sstevel@tonic-gate */ 267*7c478bd9Sstevel@tonic-gate if (defDN != 0 && defDN->write.scope == LDAP_SCOPE_UNKNOWN) { 268*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 269*7c478bd9Sstevel@tonic-gate "%s: write not enabled for \"%s\"", 270*7c478bd9Sstevel@tonic-gate myself, NIL(item->name)); 271*7c478bd9Sstevel@tonic-gate return (LDAP_SUCCESS); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate } else { 274*7c478bd9Sstevel@tonic-gate /* 275*7c478bd9Sstevel@tonic-gate * Attempt to get a DN from the search triple. 276*7c478bd9Sstevel@tonic-gate */ 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate if (slen(item->searchSpec.triple.base) > 0) 279*7c478bd9Sstevel@tonic-gate ls.base = item->searchSpec.triple.base; 280*7c478bd9Sstevel@tonic-gate else 281*7c478bd9Sstevel@tonic-gate ls.base = defBase; 282*7c478bd9Sstevel@tonic-gate ls.base = appendBase(ls.base, defBase, &stat, 0); 283*7c478bd9Sstevel@tonic-gate if (stat != 0) 284*7c478bd9Sstevel@tonic-gate return (0); 285*7c478bd9Sstevel@tonic-gate ls.scope = item->searchSpec.triple.scope; 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate /* 288*7c478bd9Sstevel@tonic-gate * If the search triple specifies a filter, we use the 289*7c478bd9Sstevel@tonic-gate * base, scope and filter to get an entry to supply the 290*7c478bd9Sstevel@tonic-gate * DN. Otherwise, the triple.base is assumed to be the DN. 291*7c478bd9Sstevel@tonic-gate */ 292*7c478bd9Sstevel@tonic-gate if (slen(item->searchSpec.triple.attrs) > 0 || 293*7c478bd9Sstevel@tonic-gate item->searchSpec.triple.element != 0) { 294*7c478bd9Sstevel@tonic-gate __nis_value_t *eVal = 0; 295*7c478bd9Sstevel@tonic-gate __nis_rule_value_t *rvDN; 296*7c478bd9Sstevel@tonic-gate int nv = 0; 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate if (item->searchSpec.triple.element != 0) { 299*7c478bd9Sstevel@tonic-gate eVal = evalMappingElement( 300*7c478bd9Sstevel@tonic-gate item->searchSpec.triple.element, 0); 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate if (eVal == 0) { 303*7c478bd9Sstevel@tonic-gate sfree(ls.base); 304*7c478bd9Sstevel@tonic-gate return (0); 305*7c478bd9Sstevel@tonic-gate } 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate if (eVal->type != vt_string || 308*7c478bd9Sstevel@tonic-gate eVal->numVals <= 0) { 309*7c478bd9Sstevel@tonic-gate sfree(ls.base); 310*7c478bd9Sstevel@tonic-gate freeValue(eVal, 1); 311*7c478bd9Sstevel@tonic-gate return (0); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate ls.filter = eVal->val[0].value; 315*7c478bd9Sstevel@tonic-gate } else { 316*7c478bd9Sstevel@tonic-gate ls.filter = item->searchSpec.triple.attrs; 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate rvDN = ldapSearch(&ls, &nv, 0, &stat); 320*7c478bd9Sstevel@tonic-gate sfree(ls.base); 321*7c478bd9Sstevel@tonic-gate freeValue(eVal, 1); 322*7c478bd9Sstevel@tonic-gate if (rvDN == 0 || nv <= 0) 323*7c478bd9Sstevel@tonic-gate return (stat); 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /* Look for DNs */ 326*7c478bd9Sstevel@tonic-gate dn = findDNs(myself, rvDN, nv, 0, &numDN); 327*7c478bd9Sstevel@tonic-gate freeRuleValue(rvDN, nv); 328*7c478bd9Sstevel@tonic-gate if (dn == 0 || numDN <= 0) { 329*7c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 330*7c478bd9Sstevel@tonic-gate return (LDAP_NO_MEMORY); 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate freeDN = 1; 333*7c478bd9Sstevel@tonic-gate } else if (slen(item->searchSpec.triple.base) > 0) { 334*7c478bd9Sstevel@tonic-gate locDN[0] = item->searchSpec.triple.base; 335*7c478bd9Sstevel@tonic-gate dn = locDN; 336*7c478bd9Sstevel@tonic-gate numDN = 1; 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate /* We must have at least one DN to continue */ 341*7c478bd9Sstevel@tonic-gate if (dn == 0 || numDN < 1) { 342*7c478bd9Sstevel@tonic-gate if (freeDN) 343*7c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 344*7c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate if (val->numVals > 0) { 348*7c478bd9Sstevel@tonic-gate /* Make a rule-value describing the modification */ 349*7c478bd9Sstevel@tonic-gate rv = am(myself, sizeof (*rv)); 350*7c478bd9Sstevel@tonic-gate if (rv == 0) 351*7c478bd9Sstevel@tonic-gate return (LDAP_NO_MEMORY); 352*7c478bd9Sstevel@tonic-gate rv->attrName = am(myself, sizeof (rv->attrName[0])); 353*7c478bd9Sstevel@tonic-gate rv->attrVal = am(myself, sizeof (rv->attrVal[0])); 354*7c478bd9Sstevel@tonic-gate if (rv->attrName == 0 || rv->attrVal == 0) { 355*7c478bd9Sstevel@tonic-gate if (freeDN) 356*7c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 357*7c478bd9Sstevel@tonic-gate freeRuleValue(rv, 1); 358*7c478bd9Sstevel@tonic-gate return (LDAP_NO_MEMORY); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate /* 362*7c478bd9Sstevel@tonic-gate * What's the start index in val->val[], and how many elements 363*7c478bd9Sstevel@tonic-gate * should we copy ? 364*7c478bd9Sstevel@tonic-gate */ 365*7c478bd9Sstevel@tonic-gate if (index < val->numVals) 366*7c478bd9Sstevel@tonic-gate six = index; 367*7c478bd9Sstevel@tonic-gate else 368*7c478bd9Sstevel@tonic-gate six = val->numVals - 1; 369*7c478bd9Sstevel@tonic-gate if (item->repeat && index == (numIndexes - 1)) 370*7c478bd9Sstevel@tonic-gate nix = 1 + (six - (val->numVals - 1)); 371*7c478bd9Sstevel@tonic-gate else 372*7c478bd9Sstevel@tonic-gate nix = 1; 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate rv->attrName[0] = sdup(myself, T, item->name); 375*7c478bd9Sstevel@tonic-gate rv->attrVal[0].val = am(myself, 376*7c478bd9Sstevel@tonic-gate nix * sizeof (rv->attrVal[0].val[0])); 377*7c478bd9Sstevel@tonic-gate if (rv->attrName[0] == 0 || rv->attrVal[0].val == 0) { 378*7c478bd9Sstevel@tonic-gate if (freeDN) 379*7c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 380*7c478bd9Sstevel@tonic-gate freeRuleValue(rv, 1); 381*7c478bd9Sstevel@tonic-gate return (LDAP_NO_MEMORY); 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate rv->numAttrs = 1; 384*7c478bd9Sstevel@tonic-gate for (ix = six; ix < nix; ix++) { 385*7c478bd9Sstevel@tonic-gate rv->attrVal[0].numVals++; 386*7c478bd9Sstevel@tonic-gate rv->attrVal[0].val[ix-six].value = 387*7c478bd9Sstevel@tonic-gate am(myself, val->val[ix].length); 388*7c478bd9Sstevel@tonic-gate if (rv->attrVal[0].val[ix-six].value == 0 && 389*7c478bd9Sstevel@tonic-gate val->val[ix].value != 0) { 390*7c478bd9Sstevel@tonic-gate if (freeDN) 391*7c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 392*7c478bd9Sstevel@tonic-gate freeRuleValue(rv, 1); 393*7c478bd9Sstevel@tonic-gate return (LDAP_NO_MEMORY); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate rv->attrVal[0].val[ix-six].length = 396*7c478bd9Sstevel@tonic-gate val->val[ix].length; 397*7c478bd9Sstevel@tonic-gate if (rv->attrVal[0].val[ix-six].length > 0) { 398*7c478bd9Sstevel@tonic-gate (void) memcpy(rv->attrVal[0].val[ix-six].value, 399*7c478bd9Sstevel@tonic-gate val->val[ix].value, 400*7c478bd9Sstevel@tonic-gate rv->attrVal[0].val[ix-six].length); 401*7c478bd9Sstevel@tonic-gate } 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate rv->attrVal[0].type = val->type; 404*7c478bd9Sstevel@tonic-gate } else { 405*7c478bd9Sstevel@tonic-gate /* 406*7c478bd9Sstevel@tonic-gate * We already rejected val->numvals < -1 and val->numVals == 0 407*7c478bd9Sstevel@tonic-gate * in the initial sanity check, so it must be -1. This means 408*7c478bd9Sstevel@tonic-gate * deletion, which we indicate to ldapModify() by supplying 409*7c478bd9Sstevel@tonic-gate * a NULL rule-value pointer. 410*7c478bd9Sstevel@tonic-gate */ 411*7c478bd9Sstevel@tonic-gate rv = 0; 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate /* For each DN */ 415*7c478bd9Sstevel@tonic-gate for (i = 0; i < numDN; i++) { 416*7c478bd9Sstevel@tonic-gate stat = ldapModify(dn[i], rv, item->searchSpec.triple.attrs, 0); 417*7c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) 418*7c478bd9Sstevel@tonic-gate break; 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate if (freeDN) 422*7c478bd9Sstevel@tonic-gate freeDNs(dn, numDN); 423*7c478bd9Sstevel@tonic-gate freeRuleValue(rv, 1); 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate return (stat); 426*7c478bd9Sstevel@tonic-gate } 427