1 /* map.c - ldap backend mapping routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2003 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
17 * This work was initially developed by the Howard Chu for inclusion
18 * in OpenLDAP Software and subsequently enhanced by Pierangelo
21 /* This is an altered version */
23 * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
25 * Permission is granted to anyone to use this software for any purpose
26 * on any computer system, and to alter it and redistribute it, subject
27 * to the following restrictions:
29 * 1. The author is not responsible for the consequences of use of this
30 * software, no matter how awful, even if they arise from flaws in it.
32 * 2. The origin of this software must not be misrepresented, either by
33 * explicit claim or by omission. Since few users ever read sources,
34 * credits should appear in the documentation.
36 * 3. Altered versions must be plainly marked as such, and must not be
37 * misrepresented as being the original software. Since few users
38 * ever read sources, credits should appear in the documentation.
40 * 4. This notice may not be removed or altered.
44 * Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
46 * This software is being modified by Pierangelo Masarati.
47 * The previously reported conditions apply to the modified code as well.
48 * Changes in the original code are highlighted where required.
49 * Credits for the original code go to the author, Howard Chu.
56 #include <ac/string.h>
57 #include <ac/socket.h>
60 #include "back-ldap.h"
62 #undef ldap_debug /* silence a warning in ldap-int.h */
63 #include "../../../libraries/libldap/ldap-int.h"
66 mapping_cmp ( const void *c1, const void *c2 )
68 struct ldapmapping *map1 = (struct ldapmapping *)c1;
69 struct ldapmapping *map2 = (struct ldapmapping *)c2;
70 int rc = map1->src.bv_len - map2->src.bv_len;
72 return ( strcasecmp(map1->src.bv_val, map2->src.bv_val) );
76 mapping_dup ( void *c1, void *c2 )
78 struct ldapmapping *map1 = (struct ldapmapping *)c1;
79 struct ldapmapping *map2 = (struct ldapmapping *)c2;
81 return( ( strcasecmp(map1->src.bv_val, map2->src.bv_val) == 0 ) ? -1 : 0 );
85 ldap_back_map_init ( struct ldapmap *lm, struct ldapmapping **m )
87 struct ldapmapping *mapping;
93 mapping = (struct ldapmapping *)ch_calloc( 2,
94 sizeof( struct ldapmapping ) );
95 if ( mapping == NULL ) {
99 ber_str2bv( "objectclass", sizeof("objectclass")-1, 1, &mapping->src);
100 ber_dupbv( &mapping->dst, &mapping->src );
101 mapping[1].src = mapping->src;
102 mapping[1].dst = mapping->dst;
104 avl_insert( &lm->map, (caddr_t)mapping,
105 mapping_cmp, mapping_dup );
106 avl_insert( &lm->remap, (caddr_t)&mapping[1],
107 mapping_cmp, mapping_dup );
112 ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv,
116 struct ldapmapping *mapping, fmapping;
118 if (remap == BACKLDAP_REMAP)
126 mapping = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, mapping_cmp );
127 if (mapping != NULL) {
128 if ( mapping->dst.bv_val )
133 if (!map->drop_missing)
141 struct ldapmap *at_map,
149 struct berval mapped;
152 *mapped_attrs = NULL;
156 for (i = 0; an[i].an_name.bv_val; i++) {
160 na = (char **)ch_calloc( i + 1, sizeof(char *) );
162 *mapped_attrs = NULL;
163 return LDAP_NO_MEMORY;
166 for (i = j = 0; an[i].an_name.bv_val; i++) {
167 ldap_back_map(at_map, &an[i].an_name, &mapped, remap);
168 if (mapped.bv_val != NULL && mapped.bv_val != '\0')
169 na[j++] = mapped.bv_val;
171 if (j == 0 && i != 0)
172 na[j++] = LDAP_NO_ATTRS;
182 AttributeDescription *ad,
183 struct berval *mapped_attr,
184 struct berval *value,
185 struct berval *mapped_value,
191 ldap_back_map( &dc->rwmap->rwm_at, &ad->ad_cname, mapped_attr, remap );
192 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
194 * FIXME: are we sure we need to search oc_map if at_map fails?
196 ldap_back_map( &dc->rwmap->rwm_oc, &ad->ad_cname, mapped_attr, remap );
197 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
198 *mapped_attr = ad->ad_cname;
202 if ( value == NULL ) {
206 if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
210 #ifdef ENABLE_REWRITE
211 fdc.ctx = "searchFilter";
214 switch ( ldap_back_dn_massage( &fdc, value, &vtmp ) ) {
216 if ( vtmp.bv_val != value->bv_val ) {
221 case LDAP_UNWILLING_TO_PERFORM:
228 } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
229 ldap_back_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
230 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
238 filter_escape_value( &vtmp, mapped_value );
241 ber_memfree( vtmp.bv_val );
248 ldap_back_filter_map_rewrite(
261 ber_str2bv( "No filter!", sizeof("No filter!")-1, 1, fstr );
265 switch ( f->f_choice ) {
266 case LDAP_FILTER_EQUALITY:
267 if ( map_attr_value( dc, f->f_av_desc, &atmp,
268 &f->f_av_value, &vtmp, remap ) )
273 fstr->bv_len = atmp.bv_len + vtmp.bv_len
274 + ( sizeof("(=)") - 1 );
275 fstr->bv_val = malloc( fstr->bv_len + 1 );
277 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
278 atmp.bv_val, vtmp.bv_val );
280 ber_memfree( vtmp.bv_val );
284 if ( map_attr_value( dc, f->f_av_desc, &atmp,
285 &f->f_av_value, &vtmp, remap ) )
290 fstr->bv_len = atmp.bv_len + vtmp.bv_len
291 + ( sizeof("(>=)") - 1 );
292 fstr->bv_val = malloc( fstr->bv_len + 1 );
294 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
295 atmp.bv_val, vtmp.bv_val );
297 ber_memfree( vtmp.bv_val );
301 if ( map_attr_value( dc, f->f_av_desc, &atmp,
302 &f->f_av_value, &vtmp, remap ) )
307 fstr->bv_len = atmp.bv_len + vtmp.bv_len
308 + ( sizeof("(<=)") - 1 );
309 fstr->bv_val = malloc( fstr->bv_len + 1 );
311 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
312 atmp.bv_val, vtmp.bv_val );
314 ber_memfree( vtmp.bv_val );
317 case LDAP_FILTER_APPROX:
318 if ( map_attr_value( dc, f->f_av_desc, &atmp,
319 &f->f_av_value, &vtmp, remap ) )
324 fstr->bv_len = atmp.bv_len + vtmp.bv_len
325 + ( sizeof("(~=)") - 1 );
326 fstr->bv_val = malloc( fstr->bv_len + 1 );
328 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
329 atmp.bv_val, vtmp.bv_val );
331 ber_memfree( vtmp.bv_val );
334 case LDAP_FILTER_SUBSTRINGS:
335 if ( map_attr_value( dc, f->f_sub_desc, &atmp,
336 NULL, NULL, remap ) )
341 /* cannot be a DN ... */
343 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
344 fstr->bv_val = malloc( fstr->bv_len + 128 );
346 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
349 if ( f->f_sub_initial.bv_val != NULL ) {
352 filter_escape_value( &f->f_sub_initial, &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 - 2], vtmp.bv_len + 3,
358 /* "(attr=" */ "%s*)",
361 ber_memfree( vtmp.bv_val );
364 if ( f->f_sub_any != NULL ) {
365 for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
367 filter_escape_value( &f->f_sub_any[i], &vtmp );
369 fstr->bv_len += vtmp.bv_len + 1;
370 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
372 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
373 /* "(attr=[init]*[any*]" */ "%s*)",
375 ber_memfree( vtmp.bv_val );
379 if ( f->f_sub_final.bv_val != NULL ) {
382 filter_escape_value( &f->f_sub_final, &vtmp );
384 fstr->bv_len += vtmp.bv_len;
385 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
387 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
388 /* "(attr=[init*][any*]" */ "%s)",
391 ber_memfree( vtmp.bv_val );
396 case LDAP_FILTER_PRESENT:
397 if ( map_attr_value( dc, f->f_desc, &atmp,
398 NULL, NULL, remap ) )
403 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
404 fstr->bv_val = malloc( fstr->bv_len + 1 );
406 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
410 case LDAP_FILTER_AND:
412 case LDAP_FILTER_NOT:
413 fstr->bv_len = sizeof("(%)") - 1;
414 fstr->bv_val = malloc( fstr->bv_len + 128 );
416 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
417 f->f_choice == LDAP_FILTER_AND ? '&' :
418 f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
420 for ( p = f->f_list; p != NULL; p = p->f_next ) {
423 if ( ldap_back_filter_map_rewrite( dc, p, &vtmp, remap ) )
428 fstr->bv_len += vtmp.bv_len;
429 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
431 snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
432 /*"("*/ "%s)", vtmp.bv_val );
434 ch_free( vtmp.bv_val );
439 case LDAP_FILTER_EXT: {
440 if ( f->f_mr_desc ) {
441 if ( map_attr_value( dc, f->f_mr_desc, &atmp,
442 &f->f_mr_value, &vtmp, remap ) )
451 filter_escape_value( &f->f_mr_value, &vtmp );
455 fstr->bv_len = atmp.bv_len +
456 ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
457 ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
458 vtmp.bv_len + ( sizeof("(:=)") - 1 );
459 fstr->bv_val = malloc( fstr->bv_len + 1 );
461 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
463 f->f_mr_dnattrs ? ":dn" : "",
464 f->f_mr_rule_text.bv_len ? ":" : "",
465 f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
467 ber_memfree( vtmp.bv_val );
470 case SLAPD_FILTER_COMPUTED:
472 f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
473 f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
474 f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
476 f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
477 f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
478 f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
479 sizeof("(?=error)")-1,
484 ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );
492 * I don't like this much, but we need two different
493 * functions because different heap managers may be
494 * in use in back-ldap/meta to reduce the amount of
495 * calls to malloc routines, and some of the free()
496 * routines may be macros with args
507 for ( last = 0; a_vals[last].bv_val != NULL; last++ );
510 for ( i = 0; a_vals[i].bv_val != NULL; i++ ) {
511 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
512 case LDAP_UNWILLING_TO_PERFORM:
514 * FIXME: need to check if it may be considered
515 * legal to trim values when adding/modifying;
516 * it should be when searching (e.g. ACLs).
518 ch_free( a_vals[i].bv_val );
520 a_vals[i] = a_vals[last];
522 a_vals[last].bv_len = 0;
523 a_vals[last].bv_val = NULL;
528 /* leave attr untouched if massage failed */
529 if ( bv.bv_val && bv.bv_val != a_vals[i].bv_val ) {
530 ch_free( a_vals[i].bv_val );
541 ldap_dnattr_result_rewrite(
549 for ( last = 0; a_vals[last].bv_val; last++ );
552 for ( i = 0; a_vals[i].bv_val; i++ ) {
553 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
554 case LDAP_UNWILLING_TO_PERFORM:
556 * FIXME: need to check if it may be considered
557 * legal to trim values when adding/modifying;
558 * it should be when searching (e.g. ACLs).
560 LBER_FREE( &a_vals[i].bv_val );
562 a_vals[i] = a_vals[last];
564 a_vals[last].bv_val = NULL;
565 a_vals[last].bv_len = 0;
570 /* leave attr untouched if massage failed */
571 if ( bv.bv_val && a_vals[i].bv_val != bv.bv_val ) {
572 LBER_FREE( a_vals[i].bv_val );