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"
48 mapping_cmp ( const void *c1, const void *c2 )
50 struct ldapmapping *map1 = (struct ldapmapping *)c1;
51 struct ldapmapping *map2 = (struct ldapmapping *)c2;
52 int rc = map1->src.bv_len - map2->src.bv_len;
54 return ( strcasecmp(map1->src.bv_val, map2->src.bv_val) );
58 mapping_dup ( void *c1, void *c2 )
60 struct ldapmapping *map1 = (struct ldapmapping *)c1;
61 struct ldapmapping *map2 = (struct ldapmapping *)c2;
63 return( ( strcasecmp(map1->src.bv_val, map2->src.bv_val) == 0 ) ? -1 : 0 );
67 ldap_back_map_init ( struct ldapmap *lm, struct ldapmapping **m )
69 struct ldapmapping *mapping;
75 mapping = (struct ldapmapping *)ch_calloc( 2,
76 sizeof( struct ldapmapping ) );
77 if ( mapping == NULL ) {
81 ber_str2bv( "objectclass", sizeof("objectclass")-1, 1, &mapping->src);
82 ber_dupbv( &mapping->dst, &mapping->src );
83 mapping[1].src = mapping->src;
84 mapping[1].dst = mapping->dst;
86 avl_insert( &lm->map, (caddr_t)mapping,
87 mapping_cmp, mapping_dup );
88 avl_insert( &lm->remap, (caddr_t)&mapping[1],
89 mapping_cmp, mapping_dup );
94 ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv,
98 struct ldapmapping *mapping, fmapping;
100 if (remap == BACKLDAP_REMAP)
108 mapping = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, mapping_cmp );
109 if (mapping != NULL) {
110 if ( mapping->dst.bv_val )
115 if (!map->drop_missing)
122 ldap_back_map_filter(
123 struct ldapmap *at_map,
124 struct ldapmap *oc_map,
129 char *nf, *p, *q, *s, c;
130 int len, extra, plen, in_quote;
131 struct berval m, tmp;
139 nf = ch_malloc( len + 1 );
143 /* this loop assumes the filter ends with one
144 * of the delimiter chars -- probably ')'.
150 for (p = f->bv_val; (c = *p); p++) {
152 in_quote = !in_quote;
155 AC_MEMCPY(s, q, plen);
160 } else if (in_quote) {
161 /* ignore everything in quotes --
162 * what about attrs in DNs?
165 } else if (c != '(' && c != ')'
166 && c != '=' && c != '>' && c != '<'
167 && c != '|' && c != '&')
176 ldap_back_map(at_map, &tmp, &m, remap);
177 if (m.bv_val == NULL || m.bv_val[0] == '\0') {
179 * FIXME: are we sure we need to search
180 * oc_map if at_map fails?
182 ldap_back_map(oc_map, &tmp, &m, remap);
183 if (m.bv_val == NULL || m.bv_val[0] == '\0') {
197 tmpnf = ch_realloc(nf, len + 1);
205 AC_MEMCPY(s, m.bv_val, plen);
219 struct ldapmap *at_map,
227 struct berval mapped;
230 *mapped_attrs = NULL;
234 for (i = 0; an[i].an_name.bv_val; i++) {
238 na = (char **)ch_calloc( i + 1, sizeof(char *) );
240 *mapped_attrs = NULL;
241 return LDAP_NO_MEMORY;
244 for (i = j = 0; an[i].an_name.bv_val; i++) {
245 ldap_back_map(at_map, &an[i].an_name, &mapped, remap);
246 if (mapped.bv_val != NULL && mapped.bv_val != '\0')
247 na[j++] = mapped.bv_val;
249 if (j == 0 && i != 0)
250 na[j++] = LDAP_NO_ATTRS;
257 #ifdef ENABLE_REWRITE
261 struct rewrite_info *info,
263 struct ldapmap *at_map,
264 struct ldapmap *oc_map,
265 AttributeDescription *ad,
266 struct berval *mapped_attr,
267 struct berval *value,
268 struct berval *mapped_value,
274 ldap_back_map( at_map, &ad->ad_cname, mapped_attr, remap );
275 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
277 * FIXME: are we sure we need to search oc_map if at_map fails?
279 ldap_back_map( oc_map, &ad->ad_cname, mapped_attr, remap );
280 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
281 *mapped_attr = ad->ad_cname;
285 if ( value == NULL ) {
289 if ( strcmp( ad->ad_type->sat_syntax->ssyn_oid, SLAPD_DN_SYNTAX ) == 0 )
291 switch ( rewrite_session( info, "searchFilter",
292 value->bv_val, cookie, &vtmp.bv_val ) ) {
293 case REWRITE_REGEXEC_OK:
294 if ( vtmp.bv_val == NULL ) {
297 vtmp.bv_len = strlen( vtmp.bv_val );
301 LDAP_LOG( BACK_LDAP, DETAIL1,
302 "[rw] searchFilter: \"%s\" -> \"%s\"\n",
303 value->bv_val, vtmp.bv_val, 0 );
304 #else /* !NEW_LOGGING */
305 Debug( LDAP_DEBUG_ARGS, "rw> searchFilter: \"%s\" -> \"%s\"\n%s",
306 value->bv_val, vtmp.bv_val, "" );
307 #endif /* !NEW_LOGGING */
311 case REWRITE_REGEXEC_UNWILLING:
314 case REWRITE_REGEXEC_ERR:
318 } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
319 ldap_back_map( oc_map, value, &vtmp, remap );
320 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
328 filter_escape_value( &vtmp, mapped_value );
331 ber_memfree( vtmp.bv_val );
337 #define map_attr_value(at_map, oc_map, ad, mapped_attr, value, mapped_value, remap) \
338 map_attr_value_(info, cookie, (at_map), (oc_map), (ad), (mapped_attr), (value), (mapped_value), (remap))
339 #define ldap_back_filter_map_rewrite(at_map, oc_map, f, fstr, remap) \
340 ldap_back_filter_map_rewrite_(info, cookie, (at_map), (oc_map), (f), (fstr), (remap))
342 #else /* ! ENABLE_REWRITE */
346 struct ldapmap *at_map,
347 struct ldapmap *oc_map,
348 AttributeDescription *ad,
349 struct berval *mapped_attr,
350 struct berval *value,
351 struct berval *mapped_value,
356 ldap_back_map( at_map, &ad->ad_cname, mapped_attr, remap );
357 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
359 * FIXME: are we sure we need to search oc_map if at_map fails?
361 ldap_back_map( oc_map, &ad->ad_cname, mapped_attr, remap );
362 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
363 *mapped_attr = ad->ad_cname;
367 if ( value == NULL ) {
371 if ( strcmp( ad->ad_type->sat_syntax->ssyn_oid, SLAPD_DN_SYNTAX ) == 0 )
373 /* FIXME: use suffix massage capabilities */
376 } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
377 ldap_back_map( oc_map, value, &vtmp, remap );
378 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
386 filter_escape_value( &vtmp, mapped_value );
391 #define map_attr_value(at_map, oc_map, ad, mapped_attr, value, mapped_value, remap) \
392 map_attr_value_((at_map), (oc_map), (ad), (mapped_attr), (value), (mapped_value), (remap))
393 #define ldap_back_filter_map_rewrite(at_map, oc_map, f, fstr, remap) \
394 ldap_back_filter_map_rewrite_((at_map), (oc_map), (f), (fstr), (remap))
396 #endif /* ! ENABLE_REWRITE */
399 ldap_back_filter_map_rewrite_(
400 #ifdef ENABLE_REWRITE
401 struct rewrite_info *info,
403 #endif /* ENABLE_REWRITE */
404 struct ldapmap *at_map,
405 struct ldapmap *oc_map,
417 ber_str2bv( "No filter!", sizeof("No filter!")-1, 1, fstr );
421 switch ( f->f_choice ) {
422 case LDAP_FILTER_EQUALITY:
423 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
424 &f->f_av_value, &vtmp, remap ) )
429 fstr->bv_len = atmp.bv_len + vtmp.bv_len
430 + ( sizeof("(=)") - 1 );
431 fstr->bv_val = malloc( fstr->bv_len + 1 );
433 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
434 atmp.bv_val, vtmp.bv_val );
436 ber_memfree( vtmp.bv_val );
440 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
441 &f->f_av_value, &vtmp, remap ) )
446 fstr->bv_len = atmp.bv_len + vtmp.bv_len
447 + ( sizeof("(>=)") - 1 );
448 fstr->bv_val = malloc( fstr->bv_len + 1 );
450 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
451 atmp.bv_val, vtmp.bv_val );
453 ber_memfree( vtmp.bv_val );
457 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
458 &f->f_av_value, &vtmp, remap ) )
463 fstr->bv_len = atmp.bv_len + vtmp.bv_len
464 + ( sizeof("(<=)") - 1 );
465 fstr->bv_val = malloc( fstr->bv_len + 1 );
467 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
468 atmp.bv_val, vtmp.bv_val );
470 ber_memfree( vtmp.bv_val );
473 case LDAP_FILTER_APPROX:
474 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
475 &f->f_av_value, &vtmp, remap ) )
480 fstr->bv_len = atmp.bv_len + vtmp.bv_len
481 + ( sizeof("(~=)") - 1 );
482 fstr->bv_val = malloc( fstr->bv_len + 1 );
484 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
485 atmp.bv_val, vtmp.bv_val );
487 ber_memfree( vtmp.bv_val );
490 case LDAP_FILTER_SUBSTRINGS:
491 if ( map_attr_value( at_map, oc_map, f->f_sub_desc, &atmp,
492 NULL, NULL, remap ) )
497 /* cannot be a DN ... */
499 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
500 fstr->bv_val = malloc( fstr->bv_len + 128 );
502 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
505 if ( f->f_sub_initial.bv_val != NULL ) {
508 filter_escape_value( &f->f_sub_initial, &vtmp );
510 fstr->bv_len += vtmp.bv_len;
511 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
513 snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
514 /* "(attr=" */ "%s*)",
517 ber_memfree( vtmp.bv_val );
520 if ( f->f_sub_any != NULL ) {
521 for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
523 filter_escape_value( &f->f_sub_any[i], &vtmp );
525 fstr->bv_len += vtmp.bv_len + 1;
526 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
528 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
529 /* "(attr=[init]*[any*]" */ "%s*)",
531 ber_memfree( vtmp.bv_val );
535 if ( f->f_sub_final.bv_val != NULL ) {
538 filter_escape_value( &f->f_sub_final, &vtmp );
540 fstr->bv_len += vtmp.bv_len;
541 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
543 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
544 /* "(attr=[init*][any*]" */ "%s)",
547 ber_memfree( vtmp.bv_val );
552 case LDAP_FILTER_PRESENT:
553 if ( map_attr_value( at_map, oc_map, f->f_desc, &atmp,
554 NULL, NULL, remap ) )
559 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
560 fstr->bv_val = malloc( fstr->bv_len + 1 );
562 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
566 case LDAP_FILTER_AND:
568 case LDAP_FILTER_NOT:
569 fstr->bv_len = sizeof("(%)") - 1;
570 fstr->bv_val = malloc( fstr->bv_len + 128 );
572 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
573 f->f_choice == LDAP_FILTER_AND ? '&' :
574 f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
576 for ( p = f->f_list; p != NULL; p = p->f_next ) {
579 if ( ldap_back_filter_map_rewrite( at_map, oc_map, p, &vtmp, remap ) )
584 fstr->bv_len += vtmp.bv_len;
585 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
587 snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
588 /*"("*/ "%s)", vtmp.bv_val );
590 ch_free( vtmp.bv_val );
595 case LDAP_FILTER_EXT: {
596 if ( f->f_mr_desc ) {
597 if ( map_attr_value( at_map, oc_map, f->f_mr_desc, &atmp,
598 &f->f_mr_value, &vtmp, remap ) )
607 filter_escape_value( &f->f_mr_value, &vtmp );
611 fstr->bv_len = atmp.bv_len +
612 ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
613 ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
614 vtmp.bv_len + ( sizeof("(:=)") - 1 );
615 fstr->bv_val = malloc( fstr->bv_len + 1 );
617 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
619 f->f_mr_dnattrs ? ":dn" : "",
620 f->f_mr_rule_text.bv_len ? ":" : "",
621 f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
623 ber_memfree( vtmp.bv_val );
626 case SLAPD_FILTER_COMPUTED:
628 f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
629 f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
630 f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
632 f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
633 f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
634 f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
635 sizeof("(?=error)")-1,
640 ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );