1 /* map.c - ldap backend mapping routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2005 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_mapping ( struct ldapmap *map, struct berval *s, struct ldapmapping **m,
88 struct ldapmapping fmapping;
92 if ( remap == BACKLDAP_REMAP ) {
99 *m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, mapping_cmp );
101 return map->drop_missing;
108 ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv,
111 struct ldapmapping *mapping;
114 ( void )ldap_back_mapping( map, s, &mapping, remap );
115 if ( mapping != NULL ) {
116 if ( !BER_BVISNULL( &mapping->dst ) ) {
122 if ( !map->drop_missing ) {
129 struct ldapmap *at_map,
137 struct berval mapped;
140 *mapped_attrs = NULL;
144 for (i = 0; an[i].an_name.bv_val; i++) {
148 na = (char **)ch_calloc( i + 1, sizeof(char *) );
150 *mapped_attrs = NULL;
151 return LDAP_NO_MEMORY;
154 for (i = j = 0; an[i].an_name.bv_val; i++) {
155 ldap_back_map(at_map, &an[i].an_name, &mapped, remap);
156 if (mapped.bv_val != NULL && mapped.bv_val != '\0')
157 na[j++] = mapped.bv_val;
159 if (j == 0 && i != 0)
160 na[j++] = LDAP_NO_ATTRS;
170 AttributeDescription *ad,
171 struct berval *mapped_attr,
172 struct berval *value,
173 struct berval *mapped_value,
179 ldap_back_map( &dc->rwmap->rwm_at, &ad->ad_cname, mapped_attr, remap );
180 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
182 * FIXME: are we sure we need to search oc_map if at_map fails?
184 ldap_back_map( &dc->rwmap->rwm_oc, &ad->ad_cname, mapped_attr, remap );
185 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
186 *mapped_attr = ad->ad_cname;
190 if ( value == NULL ) {
194 if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
198 #ifdef ENABLE_REWRITE
199 fdc.ctx = "searchFilterAttrDN";
202 switch ( ldap_back_dn_massage( &fdc, value, &vtmp ) ) {
204 if ( vtmp.bv_val != value->bv_val ) {
209 case LDAP_UNWILLING_TO_PERFORM:
214 } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
215 ldap_back_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
216 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
224 filter_escape_value( &vtmp, mapped_value );
227 ber_memfree( vtmp.bv_val );
234 ldap_int_back_filter_map_rewrite(
247 ber_str2bv( "(?=error)", sizeof("(?=error)")-1, 1, fstr );
251 switch ( f->f_choice ) {
252 case LDAP_FILTER_EQUALITY:
253 rc = map_attr_value( dc, f->f_av_desc, &atmp,
254 &f->f_av_value, &vtmp, remap );
259 fstr->bv_len = atmp.bv_len + vtmp.bv_len
260 + ( sizeof("(=)") - 1 );
261 fstr->bv_val = malloc( fstr->bv_len + 1 );
263 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
264 atmp.bv_val, vtmp.bv_val );
266 ber_memfree( vtmp.bv_val );
270 rc = map_attr_value( dc, f->f_av_desc, &atmp,
271 &f->f_av_value, &vtmp, remap );
276 fstr->bv_len = atmp.bv_len + vtmp.bv_len
277 + ( sizeof("(>=)") - 1 );
278 fstr->bv_val = malloc( fstr->bv_len + 1 );
280 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
281 atmp.bv_val, vtmp.bv_val );
283 ber_memfree( vtmp.bv_val );
287 rc = map_attr_value( dc, f->f_av_desc, &atmp,
288 &f->f_av_value, &vtmp, remap );
293 fstr->bv_len = atmp.bv_len + vtmp.bv_len
294 + ( sizeof("(<=)") - 1 );
295 fstr->bv_val = malloc( fstr->bv_len + 1 );
297 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
298 atmp.bv_val, vtmp.bv_val );
300 ber_memfree( vtmp.bv_val );
303 case LDAP_FILTER_APPROX:
304 rc = map_attr_value( dc, f->f_av_desc, &atmp,
305 &f->f_av_value, &vtmp, remap );
310 fstr->bv_len = atmp.bv_len + vtmp.bv_len
311 + ( sizeof("(~=)") - 1 );
312 fstr->bv_val = malloc( fstr->bv_len + 1 );
314 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
315 atmp.bv_val, vtmp.bv_val );
317 ber_memfree( vtmp.bv_val );
320 case LDAP_FILTER_SUBSTRINGS:
321 rc = map_attr_value( dc, f->f_sub_desc, &atmp,
327 /* cannot be a DN ... */
329 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
330 fstr->bv_val = malloc( fstr->bv_len + 128 );
332 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
335 if ( f->f_sub_initial.bv_val != NULL ) {
338 filter_escape_value( &f->f_sub_initial, &vtmp );
340 fstr->bv_len += vtmp.bv_len;
341 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
343 snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
344 /* "(attr=" */ "%s*)",
347 ber_memfree( vtmp.bv_val );
350 if ( f->f_sub_any != NULL ) {
351 for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
353 filter_escape_value( &f->f_sub_any[i], &vtmp );
355 fstr->bv_len += vtmp.bv_len + 1;
356 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
358 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
359 /* "(attr=[init]*[any*]" */ "%s*)",
361 ber_memfree( vtmp.bv_val );
365 if ( f->f_sub_final.bv_val != NULL ) {
368 filter_escape_value( &f->f_sub_final, &vtmp );
370 fstr->bv_len += vtmp.bv_len;
371 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
373 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
374 /* "(attr=[init*][any*]" */ "%s)",
377 ber_memfree( vtmp.bv_val );
382 case LDAP_FILTER_PRESENT:
383 rc = map_attr_value( dc, f->f_desc, &atmp,
389 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
390 fstr->bv_val = malloc( fstr->bv_len + 1 );
392 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
396 case LDAP_FILTER_AND:
398 case LDAP_FILTER_NOT:
399 fstr->bv_len = sizeof("(%)") - 1;
400 fstr->bv_val = malloc( fstr->bv_len + 128 );
402 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
403 f->f_choice == LDAP_FILTER_AND ? '&' :
404 f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
406 for ( p = f->f_list; p != NULL; p = p->f_next ) {
409 rc = ldap_int_back_filter_map_rewrite( dc, p, &vtmp, remap );
410 if ( rc != LDAP_SUCCESS ) {
414 fstr->bv_len += vtmp.bv_len;
415 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
417 snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
418 /*"("*/ "%s)", vtmp.bv_val );
420 ch_free( vtmp.bv_val );
425 case LDAP_FILTER_EXT: {
426 if ( f->f_mr_desc ) {
427 rc = map_attr_value( dc, f->f_mr_desc, &atmp,
428 &f->f_mr_value, &vtmp, remap );
437 filter_escape_value( &f->f_mr_value, &vtmp );
441 fstr->bv_len = atmp.bv_len +
442 ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
443 ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
444 vtmp.bv_len + ( sizeof("(:=)") - 1 );
445 fstr->bv_val = malloc( fstr->bv_len + 1 );
447 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
449 f->f_mr_dnattrs ? ":dn" : "",
450 f->f_mr_rule_text.bv_len ? ":" : "",
451 f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
453 ber_memfree( vtmp.bv_val );
456 case SLAPD_FILTER_COMPUTED:
458 f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
459 f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
460 f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
462 f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
463 f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
464 f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
465 sizeof("(?=error)")-1,
467 return LDAP_COMPARE_FALSE;
470 ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );
471 return LDAP_COMPARE_FALSE;
478 ldap_back_filter_map_rewrite(
488 rc = ldap_int_back_filter_map_rewrite( dc, f, fstr, remap );
490 #ifdef ENABLE_REWRITE
491 if ( rc != LDAP_SUCCESS ) {
498 fdc.ctx = "searchFilter";
500 switch ( rewrite_session( fdc.rwmap->rwm_rw, fdc.ctx,
501 ( ftmp.bv_len ? ftmp.bv_val : "" ),
502 fdc.conn, &fstr->bv_val )) {
503 case REWRITE_REGEXEC_OK:
504 if ( fstr->bv_val != NULL ) {
505 fstr->bv_len = strlen( fstr->bv_val );
512 LDAP_LOG( BACK_LDAP, DETAIL1,
513 "[rw] %s: \"%s\" -> \"%s\"\n",
514 dc->ctx, ftmp.bv_val, fstr->bv_val );
515 #else /* !NEW_LOGGING */
516 Debug( LDAP_DEBUG_ARGS,
517 "[rw] %s: \"%s\" -> \"%s\"\n",
518 dc->ctx, ftmp.bv_val, fstr->bv_val );
519 #endif /* !NEW_LOGGING */
523 case REWRITE_REGEXEC_UNWILLING:
525 fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
526 fdc.rs->sr_text = "Operation not allowed";
528 rc = LDAP_UNWILLING_TO_PERFORM;
531 case REWRITE_REGEXEC_ERR:
533 fdc.rs->sr_err = LDAP_OTHER;
534 fdc.rs->sr_text = "Rewrite error";
540 #endif /* ENABLE_REWRITE */
545 * I don't like this much, but we need two different
546 * functions because different heap managers may be
547 * in use in back-ldap/meta to reduce the amount of
548 * calls to malloc routines, and some of the free()
549 * routines may be macros with args
560 assert( a_vals != NULL );
562 for ( last = 0; a_vals[last].bv_val != NULL; last++ );
565 for ( i = 0; a_vals[i].bv_val != NULL; i++ ) {
566 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
567 case LDAP_UNWILLING_TO_PERFORM:
569 * FIXME: need to check if it may be considered
570 * legal to trim values when adding/modifying;
571 * it should be when searching (e.g. ACLs).
573 ch_free( a_vals[i].bv_val );
575 a_vals[i] = a_vals[last];
577 a_vals[last].bv_len = 0;
578 a_vals[last].bv_val = NULL;
583 /* leave attr untouched if massage failed */
584 if ( bv.bv_val && bv.bv_val != a_vals[i].bv_val ) {
585 ch_free( a_vals[i].bv_val );
596 ldap_dnattr_result_rewrite(
604 assert( a_vals != NULL );
606 for ( last = 0; a_vals[last].bv_val; last++ );
609 for ( i = 0; a_vals[i].bv_val; i++ ) {
610 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
611 case LDAP_UNWILLING_TO_PERFORM:
613 * FIXME: need to check if it may be considered
614 * legal to trim values when adding/modifying;
615 * it should be when searching (e.g. ACLs).
617 LBER_FREE( a_vals[i].bv_val );
619 a_vals[i] = a_vals[last];
621 a_vals[last].bv_val = NULL;
622 a_vals[last].bv_len = 0;
627 /* leave attr untouched if massage failed */
628 if ( bv.bv_val && a_vals[i].bv_val != bv.bv_val ) {
629 LBER_FREE( a_vals[i].bv_val );