1 /* map.c - ldap backend mapping routines */
3 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6 /* This is an altered version */
8 * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
10 * Permission is granted to anyone to use this software for any purpose
11 * on any computer system, and to alter it and redistribute it, subject
12 * to the following restrictions:
14 * 1. The author is not responsible for the consequences of use of this
15 * software, no matter how awful, even if they arise from flaws in it.
17 * 2. The origin of this software must not be misrepresented, either by
18 * explicit claim or by omission. Since few users ever read sources,
19 * credits should appear in the documentation.
21 * 3. Altered versions must be plainly marked as such, and must not be
22 * misrepresented as being the original software. Since few users
23 * ever read sources, credits should appear in the documentation.
25 * 4. This notice may not be removed or altered.
29 * Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
31 * This software is being modified by Pierangelo Masarati.
32 * The previously reported conditions apply to the modified code as well.
33 * Changes in the original code are highlighted where required.
34 * Credits for the original code go to the author, Howard Chu.
41 #include <ac/string.h>
42 #include <ac/socket.h>
45 #include "back-ldap.h"
47 #undef ldap_debug /* silence a warning in ldap-int.h */
48 #include "../../../libraries/libldap/ldap-int.h"
51 mapping_cmp ( const void *c1, const void *c2 )
53 struct ldapmapping *map1 = (struct ldapmapping *)c1;
54 struct ldapmapping *map2 = (struct ldapmapping *)c2;
55 int rc = map1->src.bv_len - map2->src.bv_len;
57 return ( strcasecmp(map1->src.bv_val, map2->src.bv_val) );
61 mapping_dup ( void *c1, void *c2 )
63 struct ldapmapping *map1 = (struct ldapmapping *)c1;
64 struct ldapmapping *map2 = (struct ldapmapping *)c2;
66 return( ( strcasecmp(map1->src.bv_val, map2->src.bv_val) == 0 ) ? -1 : 0 );
70 ldap_back_map_init ( struct ldapmap *lm, struct ldapmapping **m )
72 struct ldapmapping *mapping;
78 mapping = (struct ldapmapping *)ch_calloc( 2,
79 sizeof( struct ldapmapping ) );
80 if ( mapping == NULL ) {
84 ber_str2bv( "objectclass", sizeof("objectclass")-1, 1, &mapping->src);
85 ber_dupbv( &mapping->dst, &mapping->src );
86 mapping[1].src = mapping->src;
87 mapping[1].dst = mapping->dst;
89 avl_insert( &lm->map, (caddr_t)mapping,
90 mapping_cmp, mapping_dup );
91 avl_insert( &lm->remap, (caddr_t)&mapping[1],
92 mapping_cmp, mapping_dup );
97 ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv,
101 struct ldapmapping *mapping, fmapping;
103 if (remap == BACKLDAP_REMAP)
111 mapping = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, mapping_cmp );
112 if (mapping != NULL) {
113 if ( mapping->dst.bv_val )
118 if (!map->drop_missing)
126 struct ldapmap *at_map,
134 struct berval mapped;
137 *mapped_attrs = NULL;
141 for (i = 0; an[i].an_name.bv_val; i++) {
145 na = (char **)ch_calloc( i + 1, sizeof(char *) );
147 *mapped_attrs = NULL;
148 return LDAP_NO_MEMORY;
151 for (i = j = 0; an[i].an_name.bv_val; i++) {
152 ldap_back_map(at_map, &an[i].an_name, &mapped, remap);
153 if (mapped.bv_val != NULL && mapped.bv_val != '\0')
154 na[j++] = mapped.bv_val;
156 if (j == 0 && i != 0)
157 na[j++] = LDAP_NO_ATTRS;
167 AttributeDescription *ad,
168 struct berval *mapped_attr,
169 struct berval *value,
170 struct berval *mapped_value,
176 ldap_back_map( &dc->rwmap->rwm_at, &ad->ad_cname, mapped_attr, remap );
177 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
179 * FIXME: are we sure we need to search oc_map if at_map fails?
181 ldap_back_map( &dc->rwmap->rwm_oc, &ad->ad_cname, mapped_attr, remap );
182 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
183 *mapped_attr = ad->ad_cname;
187 if ( value == NULL ) {
191 if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
195 #ifdef ENABLE_REWRITE
196 fdc.ctx = "searchFilter";
199 switch ( ldap_back_dn_massage( &fdc, value, &vtmp ) ) {
201 if ( vtmp.bv_val != value->bv_val ) {
206 case LDAP_UNWILLING_TO_PERFORM:
213 } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
214 ldap_back_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
215 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
223 filter_escape_value( &vtmp, mapped_value );
226 ber_memfree( vtmp.bv_val );
233 ldap_back_filter_map_rewrite(
246 ber_str2bv( "No filter!", sizeof("No filter!")-1, 1, fstr );
250 switch ( f->f_choice ) {
251 case LDAP_FILTER_EQUALITY:
252 if ( map_attr_value( dc, f->f_av_desc, &atmp,
253 &f->f_av_value, &vtmp, remap ) )
258 fstr->bv_len = atmp.bv_len + vtmp.bv_len
259 + ( sizeof("(=)") - 1 );
260 fstr->bv_val = malloc( fstr->bv_len + 1 );
262 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
263 atmp.bv_val, vtmp.bv_val );
265 ber_memfree( vtmp.bv_val );
269 if ( map_attr_value( dc, f->f_av_desc, &atmp,
270 &f->f_av_value, &vtmp, remap ) )
275 fstr->bv_len = atmp.bv_len + vtmp.bv_len
276 + ( sizeof("(>=)") - 1 );
277 fstr->bv_val = malloc( fstr->bv_len + 1 );
279 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
280 atmp.bv_val, vtmp.bv_val );
282 ber_memfree( vtmp.bv_val );
286 if ( map_attr_value( dc, f->f_av_desc, &atmp,
287 &f->f_av_value, &vtmp, remap ) )
292 fstr->bv_len = atmp.bv_len + vtmp.bv_len
293 + ( sizeof("(<=)") - 1 );
294 fstr->bv_val = malloc( fstr->bv_len + 1 );
296 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
297 atmp.bv_val, vtmp.bv_val );
299 ber_memfree( vtmp.bv_val );
302 case LDAP_FILTER_APPROX:
303 if ( map_attr_value( dc, f->f_av_desc, &atmp,
304 &f->f_av_value, &vtmp, remap ) )
309 fstr->bv_len = atmp.bv_len + vtmp.bv_len
310 + ( sizeof("(~=)") - 1 );
311 fstr->bv_val = malloc( fstr->bv_len + 1 );
313 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
314 atmp.bv_val, vtmp.bv_val );
316 ber_memfree( vtmp.bv_val );
319 case LDAP_FILTER_SUBSTRINGS:
320 if ( map_attr_value( dc, f->f_sub_desc, &atmp,
321 NULL, NULL, remap ) )
326 /* cannot be a DN ... */
328 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
329 fstr->bv_val = malloc( fstr->bv_len + 128 );
331 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
334 if ( f->f_sub_initial.bv_val != NULL ) {
337 filter_escape_value( &f->f_sub_initial, &vtmp );
339 fstr->bv_len += vtmp.bv_len;
340 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
342 snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
343 /* "(attr=" */ "%s*)",
346 ber_memfree( vtmp.bv_val );
349 if ( f->f_sub_any != NULL ) {
350 for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
352 filter_escape_value( &f->f_sub_any[i], &vtmp );
354 fstr->bv_len += vtmp.bv_len + 1;
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*)",
360 ber_memfree( vtmp.bv_val );
364 if ( f->f_sub_final.bv_val != NULL ) {
367 filter_escape_value( &f->f_sub_final, &vtmp );
369 fstr->bv_len += vtmp.bv_len;
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)",
376 ber_memfree( vtmp.bv_val );
381 case LDAP_FILTER_PRESENT:
382 if ( map_attr_value( dc, f->f_desc, &atmp,
383 NULL, NULL, remap ) )
388 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
389 fstr->bv_val = malloc( fstr->bv_len + 1 );
391 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
395 case LDAP_FILTER_AND:
397 case LDAP_FILTER_NOT:
398 fstr->bv_len = sizeof("(%)") - 1;
399 fstr->bv_val = malloc( fstr->bv_len + 128 );
401 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
402 f->f_choice == LDAP_FILTER_AND ? '&' :
403 f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
405 for ( p = f->f_list; p != NULL; p = p->f_next ) {
408 if ( ldap_back_filter_map_rewrite( dc, p, &vtmp, remap ) )
413 fstr->bv_len += vtmp.bv_len;
414 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
416 snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
417 /*"("*/ "%s)", vtmp.bv_val );
419 ch_free( vtmp.bv_val );
424 case LDAP_FILTER_EXT: {
425 if ( f->f_mr_desc ) {
426 if ( map_attr_value( dc, f->f_mr_desc, &atmp,
427 &f->f_mr_value, &vtmp, remap ) )
436 filter_escape_value( &f->f_mr_value, &vtmp );
440 fstr->bv_len = atmp.bv_len +
441 ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
442 ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
443 vtmp.bv_len + ( sizeof("(:=)") - 1 );
444 fstr->bv_val = malloc( fstr->bv_len + 1 );
446 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
448 f->f_mr_dnattrs ? ":dn" : "",
449 f->f_mr_rule_text.bv_len ? ":" : "",
450 f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
452 ber_memfree( vtmp.bv_val );
455 case SLAPD_FILTER_COMPUTED:
457 f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
458 f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
459 f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
461 f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
462 f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
463 f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
464 sizeof("(?=error)")-1,
469 ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );
477 * I don't like this much, but we need two different
478 * functions because different heap managers may be
479 * in use in back-ldap/meta to reduce the amount of
480 * calls to malloc routines, and some of the free()
481 * routines may be macros with args
492 for ( last = 0; a_vals[last].bv_val != NULL; last++ );
495 for ( i = 0; a_vals[i].bv_val != NULL; i++ ) {
496 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
497 case LDAP_UNWILLING_TO_PERFORM:
499 * FIXME: need to check if it may be considered
500 * legal to trim values when adding/modifying;
501 * it should be when searching (e.g. ACLs).
503 ch_free( a_vals[i].bv_val );
505 a_vals[i] = a_vals[last];
507 a_vals[last].bv_len = 0;
508 a_vals[last].bv_val = NULL;
513 /* leave attr untouched if massage failed */
514 if ( bv.bv_val && bv.bv_val != a_vals[i].bv_val ) {
515 ch_free( a_vals[i].bv_val );
526 ldap_dnattr_result_rewrite(
534 for ( last = 0; a_vals[last].bv_val; last++ );
537 for ( i = 0; a_vals[i].bv_val; i++ ) {
538 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
539 case LDAP_UNWILLING_TO_PERFORM:
541 * FIXME: need to check if it may be considered
542 * legal to trim values when adding/modifying;
543 * it should be when searching (e.g. ACLs).
545 LBER_FREE( &a_vals[i].bv_val );
547 a_vals[i] = a_vals[last];
549 a_vals[last].bv_val = NULL;
550 a_vals[last].bv_len = 0;
555 /* leave attr untouched if massage failed */
556 if ( bv.bv_val && a_vals[i].bv_val != bv.bv_val ) {
557 LBER_FREE( a_vals[i].bv_val );