1 /* map.c - ldap backend mapping routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2004 The OpenLDAP Foundation.
6 * Portions Copyright 1999-2003 Howard Chu.
7 * Portions Copyright 2000-2003 Pierangelo Masarati.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
19 * This work was initially developed by the Howard Chu for inclusion
20 * in OpenLDAP Software and subsequently enhanced by Pierangelo
28 #include <ac/string.h>
29 #include <ac/socket.h>
32 #include "back-ldap.h"
34 #undef ldap_debug /* silence a warning in ldap-int.h */
35 #include "../../../libraries/libldap/ldap-int.h"
38 mapping_cmp ( const void *c1, const void *c2 )
40 struct ldapmapping *map1 = (struct ldapmapping *)c1;
41 struct ldapmapping *map2 = (struct ldapmapping *)c2;
42 int rc = map1->src.bv_len - map2->src.bv_len;
44 return ( strcasecmp(map1->src.bv_val, map2->src.bv_val) );
48 mapping_dup ( void *c1, void *c2 )
50 struct ldapmapping *map1 = (struct ldapmapping *)c1;
51 struct ldapmapping *map2 = (struct ldapmapping *)c2;
53 return( ( strcasecmp(map1->src.bv_val, map2->src.bv_val) == 0 ) ? -1 : 0 );
57 ldap_back_map_init ( struct ldapmap *lm, struct ldapmapping **m )
59 struct ldapmapping *mapping;
65 mapping = (struct ldapmapping *)ch_calloc( 2,
66 sizeof( struct ldapmapping ) );
67 if ( mapping == NULL ) {
71 ber_str2bv( "objectclass", sizeof("objectclass")-1, 1, &mapping->src);
72 ber_dupbv( &mapping->dst, &mapping->src );
73 mapping[1].src = mapping->src;
74 mapping[1].dst = mapping->dst;
76 avl_insert( &lm->map, (caddr_t)mapping,
77 mapping_cmp, mapping_dup );
78 avl_insert( &lm->remap, (caddr_t)&mapping[1],
79 mapping_cmp, mapping_dup );
84 ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv,
88 struct ldapmapping *mapping, fmapping;
90 if (remap == BACKLDAP_REMAP)
98 mapping = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, mapping_cmp );
99 if (mapping != NULL) {
100 if ( mapping->dst.bv_val )
105 if (!map->drop_missing)
113 struct ldapmap *at_map,
121 struct berval mapped;
124 *mapped_attrs = NULL;
128 for (i = 0; an[i].an_name.bv_val; i++) {
132 na = (char **)ch_calloc( i + 1, sizeof(char *) );
134 *mapped_attrs = NULL;
135 return LDAP_NO_MEMORY;
138 for (i = j = 0; an[i].an_name.bv_val; i++) {
139 ldap_back_map(at_map, &an[i].an_name, &mapped, remap);
140 if (mapped.bv_val != NULL && mapped.bv_val != '\0')
141 na[j++] = mapped.bv_val;
143 if (j == 0 && i != 0)
144 na[j++] = LDAP_NO_ATTRS;
154 AttributeDescription *ad,
155 struct berval *mapped_attr,
156 struct berval *value,
157 struct berval *mapped_value,
163 ldap_back_map( &dc->rwmap->rwm_at, &ad->ad_cname, mapped_attr, remap );
164 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
166 * FIXME: are we sure we need to search oc_map if at_map fails?
168 ldap_back_map( &dc->rwmap->rwm_oc, &ad->ad_cname, mapped_attr, remap );
169 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
170 *mapped_attr = ad->ad_cname;
174 if ( value == NULL ) {
178 if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
182 #ifdef ENABLE_REWRITE
183 fdc.ctx = "searchFilter";
186 switch ( ldap_back_dn_massage( &fdc, value, &vtmp ) ) {
188 if ( vtmp.bv_val != value->bv_val ) {
193 case LDAP_UNWILLING_TO_PERFORM:
200 } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
201 ldap_back_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
202 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
210 filter_escape_value( &vtmp, mapped_value );
213 ber_memfree( vtmp.bv_val );
220 ldap_back_filter_map_rewrite(
233 ber_str2bv( "No filter!", sizeof("No filter!")-1, 1, fstr );
237 switch ( f->f_choice ) {
238 case LDAP_FILTER_EQUALITY:
239 if ( map_attr_value( dc, f->f_av_desc, &atmp,
240 &f->f_av_value, &vtmp, remap ) )
245 fstr->bv_len = atmp.bv_len + vtmp.bv_len
246 + ( sizeof("(=)") - 1 );
247 fstr->bv_val = malloc( fstr->bv_len + 1 );
249 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
250 atmp.bv_val, vtmp.bv_val );
252 ber_memfree( vtmp.bv_val );
256 if ( map_attr_value( dc, f->f_av_desc, &atmp,
257 &f->f_av_value, &vtmp, remap ) )
262 fstr->bv_len = atmp.bv_len + vtmp.bv_len
263 + ( sizeof("(>=)") - 1 );
264 fstr->bv_val = malloc( fstr->bv_len + 1 );
266 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
267 atmp.bv_val, vtmp.bv_val );
269 ber_memfree( vtmp.bv_val );
273 if ( map_attr_value( dc, f->f_av_desc, &atmp,
274 &f->f_av_value, &vtmp, remap ) )
279 fstr->bv_len = atmp.bv_len + vtmp.bv_len
280 + ( sizeof("(<=)") - 1 );
281 fstr->bv_val = malloc( fstr->bv_len + 1 );
283 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
284 atmp.bv_val, vtmp.bv_val );
286 ber_memfree( vtmp.bv_val );
289 case LDAP_FILTER_APPROX:
290 if ( map_attr_value( dc, f->f_av_desc, &atmp,
291 &f->f_av_value, &vtmp, remap ) )
296 fstr->bv_len = atmp.bv_len + vtmp.bv_len
297 + ( sizeof("(~=)") - 1 );
298 fstr->bv_val = malloc( fstr->bv_len + 1 );
300 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
301 atmp.bv_val, vtmp.bv_val );
303 ber_memfree( vtmp.bv_val );
306 case LDAP_FILTER_SUBSTRINGS:
307 if ( map_attr_value( dc, f->f_sub_desc, &atmp,
308 NULL, NULL, remap ) )
313 /* cannot be a DN ... */
315 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
316 fstr->bv_val = malloc( fstr->bv_len + 128 );
318 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
321 if ( f->f_sub_initial.bv_val != NULL ) {
324 filter_escape_value( &f->f_sub_initial, &vtmp );
326 fstr->bv_len += vtmp.bv_len;
327 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
329 snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
330 /* "(attr=" */ "%s*)",
333 ber_memfree( vtmp.bv_val );
336 if ( f->f_sub_any != NULL ) {
337 for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
339 filter_escape_value( &f->f_sub_any[i], &vtmp );
341 fstr->bv_len += vtmp.bv_len + 1;
342 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
344 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
345 /* "(attr=[init]*[any*]" */ "%s*)",
347 ber_memfree( vtmp.bv_val );
351 if ( f->f_sub_final.bv_val != NULL ) {
354 filter_escape_value( &f->f_sub_final, &vtmp );
356 fstr->bv_len += vtmp.bv_len;
357 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
359 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
360 /* "(attr=[init*][any*]" */ "%s)",
363 ber_memfree( vtmp.bv_val );
368 case LDAP_FILTER_PRESENT:
369 if ( map_attr_value( dc, f->f_desc, &atmp,
370 NULL, NULL, remap ) )
375 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
376 fstr->bv_val = malloc( fstr->bv_len + 1 );
378 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
382 case LDAP_FILTER_AND:
384 case LDAP_FILTER_NOT:
385 fstr->bv_len = sizeof("(%)") - 1;
386 fstr->bv_val = malloc( fstr->bv_len + 128 );
388 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
389 f->f_choice == LDAP_FILTER_AND ? '&' :
390 f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
392 for ( p = f->f_list; p != NULL; p = p->f_next ) {
395 if ( ldap_back_filter_map_rewrite( dc, p, &vtmp, remap ) )
400 fstr->bv_len += vtmp.bv_len;
401 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
403 snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
404 /*"("*/ "%s)", vtmp.bv_val );
406 ch_free( vtmp.bv_val );
411 case LDAP_FILTER_EXT: {
412 if ( f->f_mr_desc ) {
413 if ( map_attr_value( dc, f->f_mr_desc, &atmp,
414 &f->f_mr_value, &vtmp, remap ) )
423 filter_escape_value( &f->f_mr_value, &vtmp );
427 fstr->bv_len = atmp.bv_len +
428 ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
429 ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
430 vtmp.bv_len + ( sizeof("(:=)") - 1 );
431 fstr->bv_val = malloc( fstr->bv_len + 1 );
433 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
435 f->f_mr_dnattrs ? ":dn" : "",
436 f->f_mr_rule_text.bv_len ? ":" : "",
437 f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
439 ber_memfree( vtmp.bv_val );
442 case SLAPD_FILTER_COMPUTED:
444 f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
445 f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
446 f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
448 f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
449 f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
450 f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
451 sizeof("(?=error)")-1,
456 ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );
464 * I don't like this much, but we need two different
465 * functions because different heap managers may be
466 * in use in back-ldap/meta to reduce the amount of
467 * calls to malloc routines, and some of the free()
468 * routines may be macros with args
479 for ( last = 0; a_vals[last].bv_val != NULL; last++ );
482 for ( i = 0; a_vals[i].bv_val != NULL; i++ ) {
483 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
484 case LDAP_UNWILLING_TO_PERFORM:
486 * FIXME: need to check if it may be considered
487 * legal to trim values when adding/modifying;
488 * it should be when searching (e.g. ACLs).
490 ch_free( a_vals[i].bv_val );
492 a_vals[i] = a_vals[last];
494 a_vals[last].bv_len = 0;
495 a_vals[last].bv_val = NULL;
500 /* leave attr untouched if massage failed */
501 if ( bv.bv_val && bv.bv_val != a_vals[i].bv_val ) {
502 ch_free( a_vals[i].bv_val );
513 ldap_dnattr_result_rewrite(
521 for ( last = 0; a_vals[last].bv_val; last++ );
524 for ( i = 0; a_vals[i].bv_val; i++ ) {
525 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
526 case LDAP_UNWILLING_TO_PERFORM:
528 * FIXME: need to check if it may be considered
529 * legal to trim values when adding/modifying;
530 * it should be when searching (e.g. ACLs).
532 LBER_FREE( &a_vals[i].bv_val );
534 a_vals[i] = a_vals[last];
536 a_vals[last].bv_val = NULL;
537 a_vals[last].bv_len = 0;
542 /* leave attr untouched if massage failed */
543 if ( bv.bv_val && a_vals[i].bv_val != bv.bv_val ) {
544 LBER_FREE( a_vals[i].bv_val );