xref: /titanic_50/usr/src/lib/libnisdb/ldap_ldap.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 *
evalMappingElement(__nis_mapping_element_t * e,__nis_rule_value_t * rvIn)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 *
lookupLDAP(__nis_search_triple_t * t,char * attrName,__nis_rule_value_t * rv,__nis_object_dn_t * def,int * np_ldap_stat)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
storeLDAP(__nis_mapping_item_t * item,int index,int numIndexes,__nis_value_t * val,__nis_object_dn_t * defDN,char ** dn,int numDN)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