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 = "searchFilterAttrDN";
186 switch ( ldap_back_dn_massage( &fdc, value, &vtmp ) ) {
188 if ( vtmp.bv_val != value->bv_val ) {
193 case LDAP_UNWILLING_TO_PERFORM:
198 } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
199 ldap_back_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
200 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
208 filter_escape_value( &vtmp, mapped_value );
211 ber_memfree( vtmp.bv_val );
218 ldap_int_back_filter_map_rewrite(
231 ber_str2bv( "(?=error)", sizeof("(?=error)")-1, 1, fstr );
235 switch ( f->f_choice ) {
236 case LDAP_FILTER_EQUALITY:
237 rc = map_attr_value( dc, f->f_av_desc, &atmp,
238 &f->f_av_value, &vtmp, remap );
243 fstr->bv_len = atmp.bv_len + vtmp.bv_len
244 + ( sizeof("(=)") - 1 );
245 fstr->bv_val = malloc( fstr->bv_len + 1 );
247 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
248 atmp.bv_val, vtmp.bv_val );
250 ber_memfree( vtmp.bv_val );
254 rc = map_attr_value( dc, f->f_av_desc, &atmp,
255 &f->f_av_value, &vtmp, remap );
260 fstr->bv_len = atmp.bv_len + vtmp.bv_len
261 + ( sizeof("(>=)") - 1 );
262 fstr->bv_val = malloc( fstr->bv_len + 1 );
264 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
265 atmp.bv_val, vtmp.bv_val );
267 ber_memfree( vtmp.bv_val );
271 rc = map_attr_value( dc, f->f_av_desc, &atmp,
272 &f->f_av_value, &vtmp, remap );
277 fstr->bv_len = atmp.bv_len + vtmp.bv_len
278 + ( sizeof("(<=)") - 1 );
279 fstr->bv_val = malloc( fstr->bv_len + 1 );
281 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
282 atmp.bv_val, vtmp.bv_val );
284 ber_memfree( vtmp.bv_val );
287 case LDAP_FILTER_APPROX:
288 rc = map_attr_value( dc, f->f_av_desc, &atmp,
289 &f->f_av_value, &vtmp, remap );
294 fstr->bv_len = atmp.bv_len + vtmp.bv_len
295 + ( sizeof("(~=)") - 1 );
296 fstr->bv_val = malloc( fstr->bv_len + 1 );
298 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
299 atmp.bv_val, vtmp.bv_val );
301 ber_memfree( vtmp.bv_val );
304 case LDAP_FILTER_SUBSTRINGS:
305 rc = map_attr_value( dc, f->f_sub_desc, &atmp,
311 /* cannot be a DN ... */
313 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
314 fstr->bv_val = malloc( fstr->bv_len + 128 );
316 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
319 if ( f->f_sub_initial.bv_val != NULL ) {
322 filter_escape_value( &f->f_sub_initial, &vtmp );
324 fstr->bv_len += vtmp.bv_len;
325 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
327 snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
328 /* "(attr=" */ "%s*)",
331 ber_memfree( vtmp.bv_val );
334 if ( f->f_sub_any != NULL ) {
335 for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
337 filter_escape_value( &f->f_sub_any[i], &vtmp );
339 fstr->bv_len += vtmp.bv_len + 1;
340 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
342 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
343 /* "(attr=[init]*[any*]" */ "%s*)",
345 ber_memfree( vtmp.bv_val );
349 if ( f->f_sub_final.bv_val != NULL ) {
352 filter_escape_value( &f->f_sub_final, &vtmp );
354 fstr->bv_len += vtmp.bv_len;
355 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
357 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
358 /* "(attr=[init*][any*]" */ "%s)",
361 ber_memfree( vtmp.bv_val );
366 case LDAP_FILTER_PRESENT:
367 rc = map_attr_value( dc, f->f_desc, &atmp,
373 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
374 fstr->bv_val = malloc( fstr->bv_len + 1 );
376 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
380 case LDAP_FILTER_AND:
382 case LDAP_FILTER_NOT:
383 fstr->bv_len = sizeof("(%)") - 1;
384 fstr->bv_val = malloc( fstr->bv_len + 128 );
386 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
387 f->f_choice == LDAP_FILTER_AND ? '&' :
388 f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
390 for ( p = f->f_list; p != NULL; p = p->f_next ) {
393 rc = ldap_int_back_filter_map_rewrite( dc, p, &vtmp, remap );
394 if ( rc != LDAP_SUCCESS ) {
398 fstr->bv_len += vtmp.bv_len;
399 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
401 snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
402 /*"("*/ "%s)", vtmp.bv_val );
404 ch_free( vtmp.bv_val );
409 case LDAP_FILTER_EXT: {
410 if ( f->f_mr_desc ) {
411 rc = map_attr_value( dc, f->f_mr_desc, &atmp,
412 &f->f_mr_value, &vtmp, remap );
421 filter_escape_value( &f->f_mr_value, &vtmp );
425 fstr->bv_len = atmp.bv_len +
426 ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
427 ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
428 vtmp.bv_len + ( sizeof("(:=)") - 1 );
429 fstr->bv_val = malloc( fstr->bv_len + 1 );
431 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
433 f->f_mr_dnattrs ? ":dn" : "",
434 f->f_mr_rule_text.bv_len ? ":" : "",
435 f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
437 ber_memfree( vtmp.bv_val );
440 case SLAPD_FILTER_COMPUTED:
442 f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
443 f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
444 f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
446 f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
447 f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
448 f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
449 sizeof("(?=error)")-1,
451 return LDAP_COMPARE_FALSE;
454 ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );
455 return LDAP_COMPARE_FALSE;
462 ldap_back_filter_map_rewrite(
472 rc = ldap_int_back_filter_map_rewrite( dc, f, fstr, remap );
474 #ifdef ENABLE_REWRITE
475 if ( rc != LDAP_SUCCESS ) {
482 fdc.ctx = "searchFilter";
484 switch ( rewrite_session( fdc.rwmap->rwm_rw, fdc.ctx,
485 ( ftmp.bv_len ? ftmp.bv_val : "" ),
486 fdc.conn, &fstr->bv_val )) {
487 case REWRITE_REGEXEC_OK:
488 if ( fstr->bv_val != NULL ) {
489 fstr->bv_len = strlen( fstr->bv_val );
496 LDAP_LOG( BACK_LDAP, DETAIL1,
497 "[rw] %s: \"%s\" -> \"%s\"\n",
498 dc->ctx, ftmp.bv_val, fstr->bv_val );
499 #else /* !NEW_LOGGING */
500 Debug( LDAP_DEBUG_ARGS,
501 "[rw] %s: \"%s\" -> \"%s\"\n",
502 dc->ctx, ftmp.bv_val, fstr->bv_val );
503 #endif /* !NEW_LOGGING */
507 case REWRITE_REGEXEC_UNWILLING:
509 fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
510 fdc.rs->sr_text = "Operation not allowed";
512 rc = LDAP_UNWILLING_TO_PERFORM;
515 case REWRITE_REGEXEC_ERR:
517 fdc.rs->sr_err = LDAP_OTHER;
518 fdc.rs->sr_text = "Rewrite error";
524 #endif /* ENABLE_REWRITE */
529 * I don't like this much, but we need two different
530 * functions because different heap managers may be
531 * in use in back-ldap/meta to reduce the amount of
532 * calls to malloc routines, and some of the free()
533 * routines may be macros with args
544 for ( last = 0; a_vals[last].bv_val != NULL; last++ );
547 for ( i = 0; a_vals[i].bv_val != NULL; i++ ) {
548 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
549 case LDAP_UNWILLING_TO_PERFORM:
551 * FIXME: need to check if it may be considered
552 * legal to trim values when adding/modifying;
553 * it should be when searching (e.g. ACLs).
555 ch_free( a_vals[i].bv_val );
557 a_vals[i] = a_vals[last];
559 a_vals[last].bv_len = 0;
560 a_vals[last].bv_val = NULL;
565 /* leave attr untouched if massage failed */
566 if ( bv.bv_val && bv.bv_val != a_vals[i].bv_val ) {
567 ch_free( a_vals[i].bv_val );
578 ldap_dnattr_result_rewrite(
586 for ( last = 0; a_vals[last].bv_val; last++ );
589 for ( i = 0; a_vals[i].bv_val; i++ ) {
590 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
591 case LDAP_UNWILLING_TO_PERFORM:
593 * FIXME: need to check if it may be considered
594 * legal to trim values when adding/modifying;
595 * it should be when searching (e.g. ACLs).
597 LBER_FREE( &a_vals[i].bv_val );
599 a_vals[i] = a_vals[last];
601 a_vals[last].bv_val = NULL;
602 a_vals[last].bv_len = 0;
607 /* leave attr untouched if massage failed */
608 if ( bv.bv_val && a_vals[i].bv_val != bv.bv_val ) {
609 LBER_FREE( a_vals[i].bv_val );