4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
34 #include "ldap_util.h"
36 #include "ldap_attr.h"
37 #include "ldap_ldap.h"
40 static __nis_value_t
*
41 evalMappingElement(__nis_mapping_element_t
*e
, __nis_rule_value_t
*rvIn
) {
42 __nis_rule_value_t
*rv
= rvIn
;
47 rv
= initRuleValue(1, 0);
53 val
= getMappingElement(e
, mit_any
, rv
, NULL
);
62 lookupLDAP(__nis_search_triple_t
*t
, char *attrName
, __nis_rule_value_t
*rv
,
63 __nis_object_dn_t
*def
, int *np_ldap_stat
) {
64 __nis_value_t
*val
, *eVal
= 0;
66 __nis_ldap_search_t
*ls
;
68 int scope
, i
, stat
, nrv
= 0, freeBase
= 0;
69 char *myself
= "lookupLDAP";
71 if (t
== 0 || slen(attrName
) <= 0)
74 if (t
->element
!= 0) {
75 /* Evaluate t->element to get the t->attrs value */
77 eVal
= evalMappingElement(t
->element
, rv
);
82 if (eVal
->type
!= vt_string
|| eVal
->numVals
<= 0) {
85 char *ename
= "<unknown>";
87 eVal
= evalMappingElement(t
->element
, 0);
88 if (eVal
!= 0 && eVal
->type
== vt_string
&&
90 eVal
->val
[0].length
> 0 &&
91 eVal
->val
[0].value
!= 0)
92 ename
= eVal
->val
[0].value
;
93 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
94 "%s: %s: unable to evaluate filter expression \"%s\"",
95 myself
, attrName
, ename
);
101 filter
= eVal
->val
[0].value
;
106 if (slen(t
->base
) > 0) {
107 base
= appendBase(t
->base
, (def
!= 0) ? def
->read
.base
: 0,
110 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
111 "%s: %s: error appending \"%s\" to \"%s\"",
112 myself
, attrName
, NIL(def
->read
.base
),
118 if (def
== 0 || def
->read
.scope
== LDAP_SCOPE_UNKNOWN
||
119 slen(def
->read
.base
) <= 0) {
120 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
121 "%s: %s: no supplied or default search base",
126 base
= def
->read
.base
;
129 if (slen(filter
) > 0)
132 scope
= LDAP_SCOPE_BASE
;
137 ls
= buildLdapSearch(base
, scope
, 0, 0, filter
, attrs
, 0, 0);
139 logmsg(MSG_NOTIMECHECK
, LOG_ERR
,
140 "%s: %s: error building LDAP search information for \"%s?%s?%s\"",
141 myself
, attrName
, NIL(base
), getScope(scope
),
149 rv
= ldapSearch(ls
, &nrv
, 0, &stat
);
153 * If ldapSearch returns LDAP_NO_SUCH_OBJECT, then entry that
154 * looked for is not there in LDAP, so return NP_LDAP_NO_VALUE
158 if (np_ldap_stat
!= NULL
&& stat
== LDAP_NO_SUCH_OBJECT
)
159 *np_ldap_stat
= NP_LDAP_NO_VALUE
;
162 logmsg(MSG_NOTIMECHECK
,
163 (stat
== LDAP_NO_SUCH_OBJECT
)?LOG_DEBUG
:LOG_ERR
,
164 "%s: %s: LDAP error %d (%s) for \"%s?%s?%s\"",
165 myself
, attrName
, stat
, ldap_err2string(stat
),
166 NIL(base
), getScope(scope
), NIL(filter
));
178 for (i
= 0, val
= 0; i
< nrv
; i
++) {
180 for (j
= 0; j
< rv
[i
].numAttrs
; j
++) {
181 if (strcasecmp(attrName
, rv
[i
].attrName
[j
]) == 0) {
182 eVal
= concatenateValues(val
,
186 freeRuleValue(rv
, nrv
);
195 freeRuleValue(rv
, nrv
);
200 * Store 'val' at the LDAP location indicated by 'item'. As usual,
201 * val->numVals == -1 indicates deletion.
203 * The 'index' and 'numIndexes' parameters are used as follows:
205 * index < 0 || index >= numIndexes
208 * index >= val->numVals
209 * Store val->val[val->numVals-1]
211 * item->repeat == 0 || index < numIndexes
212 * Store val->val[index]
214 * Else (repeat != 0 && index == numIndexes-1)
215 * Store val->val[index...val->numVals-1]
217 * 'defDN' should be the default object DN specification, primarily
218 * used when the item search triple is invalid. Also, the defDN->write.base
219 * value is appended to the item search base if the latter is empty, or ends
222 * If the item search triple is invalid, 'dn' must contain the DN(s)
223 * of the LDAP entry to be modified. If the search triple is valid,
224 * the DN(s) is(are) either:
225 * Derived via an LDAP search on the search triple 'attrs' or
226 * 'element' fields, or (if neither of those fields is set)
227 * assumed to be the search triple base.
229 * Returns LDAP_SUCCESS when successful, or an appropriate LDAP
230 * error status otherwise.
233 storeLDAP(__nis_mapping_item_t
*item
, int index
, int numIndexes
,
234 __nis_value_t
*val
, __nis_object_dn_t
*defDN
,
235 char **dn
, int numDN
) {
236 __nis_ldap_search_t ls
;
237 int stat
, i
, ix
, six
, nix
;
240 __nis_rule_value_t
*rv
;
242 char *myself
= "storeLDAP";
244 if (item
== 0 || item
->type
!= mit_ldap
|| item
->name
== 0 ||
245 index
< 0 || index
>= numIndexes
||
246 val
== 0 || val
->numVals
< -1 || val
->numVals
== 0)
247 return (LDAP_PARAM_ERROR
);
249 if (defDN
!= 0 && slen(defDN
->write
.base
) > 0)
250 defBase
= defDN
->write
.base
;
252 ls
.numFilterComps
= 0;
258 if (item
->searchSpec
.triple
.scope
== LDAP_SCOPE_UNKNOWN
) {
259 /* If 'defDN' is NULL, we don't know where to write */
261 return (LDAP_PARAM_ERROR
);
263 * Check if we're supposed to write. Since we want the
264 * admin to be able to use the nisplusLDAPobjectDN attribute
265 * as an on/off switch, we don't flag failure as an error.
267 if (defDN
!= 0 && defDN
->write
.scope
== LDAP_SCOPE_UNKNOWN
) {
268 logmsg(MSG_NOTIMECHECK
, LOG_INFO
,
269 "%s: write not enabled for \"%s\"",
270 myself
, NIL(item
->name
));
271 return (LDAP_SUCCESS
);
275 * Attempt to get a DN from the search triple.
278 if (slen(item
->searchSpec
.triple
.base
) > 0)
279 ls
.base
= item
->searchSpec
.triple
.base
;
282 ls
.base
= appendBase(ls
.base
, defBase
, &stat
, 0);
285 ls
.scope
= item
->searchSpec
.triple
.scope
;
288 * If the search triple specifies a filter, we use the
289 * base, scope and filter to get an entry to supply the
290 * DN. Otherwise, the triple.base is assumed to be the DN.
292 if (slen(item
->searchSpec
.triple
.attrs
) > 0 ||
293 item
->searchSpec
.triple
.element
!= 0) {
294 __nis_value_t
*eVal
= 0;
295 __nis_rule_value_t
*rvDN
;
298 if (item
->searchSpec
.triple
.element
!= 0) {
299 eVal
= evalMappingElement(
300 item
->searchSpec
.triple
.element
, 0);
307 if (eVal
->type
!= vt_string
||
308 eVal
->numVals
<= 0) {
314 ls
.filter
= eVal
->val
[0].value
;
316 ls
.filter
= item
->searchSpec
.triple
.attrs
;
319 rvDN
= ldapSearch(&ls
, &nv
, 0, &stat
);
322 if (rvDN
== 0 || nv
<= 0)
326 dn
= findDNs(myself
, rvDN
, nv
, 0, &numDN
);
327 freeRuleValue(rvDN
, nv
);
328 if (dn
== 0 || numDN
<= 0) {
330 return (LDAP_NO_MEMORY
);
333 } else if (slen(item
->searchSpec
.triple
.base
) > 0) {
334 locDN
[0] = item
->searchSpec
.triple
.base
;
340 /* We must have at least one DN to continue */
341 if (dn
== 0 || numDN
< 1) {
344 return (LDAP_PARAM_ERROR
);
347 if (val
->numVals
> 0) {
348 /* Make a rule-value describing the modification */
349 rv
= am(myself
, sizeof (*rv
));
351 return (LDAP_NO_MEMORY
);
352 rv
->attrName
= am(myself
, sizeof (rv
->attrName
[0]));
353 rv
->attrVal
= am(myself
, sizeof (rv
->attrVal
[0]));
354 if (rv
->attrName
== 0 || rv
->attrVal
== 0) {
357 freeRuleValue(rv
, 1);
358 return (LDAP_NO_MEMORY
);
362 * What's the start index in val->val[], and how many elements
365 if (index
< val
->numVals
)
368 six
= val
->numVals
- 1;
369 if (item
->repeat
&& index
== (numIndexes
- 1))
370 nix
= 1 + (six
- (val
->numVals
- 1));
374 rv
->attrName
[0] = sdup(myself
, T
, item
->name
);
375 rv
->attrVal
[0].val
= am(myself
,
376 nix
* sizeof (rv
->attrVal
[0].val
[0]));
377 if (rv
->attrName
[0] == 0 || rv
->attrVal
[0].val
== 0) {
380 freeRuleValue(rv
, 1);
381 return (LDAP_NO_MEMORY
);
384 for (ix
= six
; ix
< nix
; ix
++) {
385 rv
->attrVal
[0].numVals
++;
386 rv
->attrVal
[0].val
[ix
-six
].value
=
387 am(myself
, val
->val
[ix
].length
);
388 if (rv
->attrVal
[0].val
[ix
-six
].value
== 0 &&
389 val
->val
[ix
].value
!= 0) {
392 freeRuleValue(rv
, 1);
393 return (LDAP_NO_MEMORY
);
395 rv
->attrVal
[0].val
[ix
-six
].length
=
397 if (rv
->attrVal
[0].val
[ix
-six
].length
> 0) {
398 (void) memcpy(rv
->attrVal
[0].val
[ix
-six
].value
,
400 rv
->attrVal
[0].val
[ix
-six
].length
);
403 rv
->attrVal
[0].type
= val
->type
;
406 * We already rejected val->numvals < -1 and val->numVals == 0
407 * in the initial sanity check, so it must be -1. This means
408 * deletion, which we indicate to ldapModify() by supplying
409 * a NULL rule-value pointer.
415 for (i
= 0; i
< numDN
; i
++) {
416 stat
= ldapModify(dn
[i
], rv
, item
->searchSpec
.triple
.attrs
, 0);
417 if (stat
!= LDAP_SUCCESS
)
423 freeRuleValue(rv
, 1);