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,
226 struct berval mapped;
231 for (i = 0; an[i].an_name.bv_val; i++) {
235 na = (char **)ch_calloc( i + 1, sizeof(char *) );
239 for (i = j = 0; an[i].an_name.bv_val; i++) {
240 ldap_back_map(at_map, &an[i].an_name, &mapped, remap);
241 if (mapped.bv_val != NULL && mapped.bv_val != '\0')
242 na[j++] = mapped.bv_val;
244 if (j == 0 && i != 0)
245 na[j++] = LDAP_NO_ATTRS;
251 #ifdef ENABLE_REWRITE
255 struct rewrite_info *info,
257 struct ldapmap *at_map,
258 struct ldapmap *oc_map,
259 AttributeDescription *ad,
260 struct berval *mapped_attr,
261 struct berval *value,
262 struct berval *mapped_value,
268 ldap_back_map( at_map, &ad->ad_cname, mapped_attr, remap );
269 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
271 * FIXME: are we sure we need to search oc_map if at_map fails?
273 ldap_back_map( oc_map, &ad->ad_cname, mapped_attr, remap );
274 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
275 *mapped_attr = ad->ad_cname;
279 if ( value == NULL ) {
283 if ( strcmp( ad->ad_type->sat_syntax->ssyn_oid, SLAPD_DN_SYNTAX ) == 0 )
285 switch ( rewrite_session( info, "searchFilter",
286 value->bv_val, cookie, &vtmp.bv_val ) ) {
287 case REWRITE_REGEXEC_OK:
288 if ( vtmp.bv_val == NULL ) {
291 vtmp.bv_len = strlen( vtmp.bv_val );
295 LDAP_LOG( BACK_LDAP, DETAIL1,
296 "[rw] searchFilter: \"%s\" -> \"%s\"\n",
297 value->bv_val, vtmp.bv_val, 0 );
298 #else /* !NEW_LOGGING */
299 Debug( LDAP_DEBUG_ARGS, "rw> searchFilter: \"%s\" -> \"%s\"\n%s",
300 value->bv_val, vtmp.bv_val, "" );
301 #endif /* !NEW_LOGGING */
305 case REWRITE_REGEXEC_UNWILLING:
308 case REWRITE_REGEXEC_ERR:
312 } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
313 ldap_back_map( oc_map, value, &vtmp, remap );
314 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
322 filter_escape_value( &vtmp, mapped_value );
325 ber_memfree( vtmp.bv_val );
331 #define map_attr_value(at_map, oc_map, ad, mapped_attr, value, mapped_value, remap) \
332 map_attr_value_(info, cookie, (at_map), (oc_map), (ad), (mapped_attr), (value), (mapped_value), (remap))
333 #define ldap_back_filter_map_rewrite(at_map, oc_map, f, fstr, remap) \
334 ldap_back_filter_map_rewrite_(info, cookie, (at_map), (oc_map), (f), (fstr), (remap))
336 #else /* ! ENABLE_REWRITE */
340 struct ldapmap *at_map,
341 struct ldapmap *oc_map,
342 AttributeDescription *ad,
343 struct berval *mapped_attr,
344 struct berval *value,
345 struct berval *mapped_value,
350 ldap_back_map( at_map, &ad->ad_cname, mapped_attr, remap );
351 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
353 * FIXME: are we sure we need to search oc_map if at_map fails?
355 ldap_back_map( oc_map, &ad->ad_cname, mapped_attr, remap );
356 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
357 *mapped_attr = ad->ad_cname;
361 if ( value == NULL ) {
365 if ( strcmp( ad->ad_type->sat_syntax->ssyn_oid, SLAPD_DN_SYNTAX ) == 0 )
367 /* FIXME: use suffix massage capabilities */
370 } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
371 ldap_back_map( oc_map, value, &vtmp, remap );
372 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
380 filter_escape_value( &vtmp, mapped_value );
385 #define map_attr_value(at_map, oc_map, ad, mapped_attr, value, mapped_value, remap) \
386 map_attr_value_((at_map), (oc_map), (ad), (mapped_attr), (value), (mapped_value), (remap))
387 #define ldap_back_filter_map_rewrite(at_map, oc_map, f, fstr, remap) \
388 ldap_back_filter_map_rewrite_((at_map), (oc_map), (f), (fstr), (remap))
390 #endif /* ! ENABLE_REWRITE */
393 ldap_back_filter_map_rewrite_(
394 #ifdef ENABLE_REWRITE
395 struct rewrite_info *info,
397 #endif /* ENABLE_REWRITE */
398 struct ldapmap *at_map,
399 struct ldapmap *oc_map,
411 ber_str2bv( "No filter!", sizeof("No filter!")-1, 1, fstr );
415 switch ( f->f_choice ) {
416 case LDAP_FILTER_EQUALITY:
417 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
418 &f->f_av_value, &vtmp, remap ) )
423 fstr->bv_len = atmp.bv_len + vtmp.bv_len
424 + ( sizeof("(=)") - 1 );
425 fstr->bv_val = malloc( fstr->bv_len + 1 );
427 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
428 atmp.bv_val, vtmp.bv_val );
430 ber_memfree( vtmp.bv_val );
434 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
435 &f->f_av_value, &vtmp, remap ) )
440 fstr->bv_len = atmp.bv_len + vtmp.bv_len
441 + ( sizeof("(>=)") - 1 );
442 fstr->bv_val = malloc( fstr->bv_len + 1 );
444 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
445 atmp.bv_val, vtmp.bv_val );
447 ber_memfree( vtmp.bv_val );
451 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
452 &f->f_av_value, &vtmp, remap ) )
457 fstr->bv_len = atmp.bv_len + vtmp.bv_len
458 + ( sizeof("(<=)") - 1 );
459 fstr->bv_val = malloc( fstr->bv_len + 1 );
461 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
462 atmp.bv_val, vtmp.bv_val );
464 ber_memfree( vtmp.bv_val );
467 case LDAP_FILTER_APPROX:
468 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
469 &f->f_av_value, &vtmp, remap ) )
474 fstr->bv_len = atmp.bv_len + vtmp.bv_len
475 + ( sizeof("(~=)") - 1 );
476 fstr->bv_val = malloc( fstr->bv_len + 1 );
478 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
479 atmp.bv_val, vtmp.bv_val );
481 ber_memfree( vtmp.bv_val );
484 case LDAP_FILTER_SUBSTRINGS:
485 if ( map_attr_value( at_map, oc_map, f->f_sub_desc, &atmp,
486 NULL, NULL, remap ) )
491 /* cannot be a DN ... */
493 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
494 fstr->bv_val = malloc( fstr->bv_len + 128 );
496 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
499 if ( f->f_sub_initial.bv_val != NULL ) {
502 filter_escape_value( &f->f_sub_initial, &vtmp );
504 fstr->bv_len += vtmp.bv_len;
505 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
507 snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
508 /* "(attr=" */ "%s*)",
511 ber_memfree( vtmp.bv_val );
514 if ( f->f_sub_any != NULL ) {
515 for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
517 filter_escape_value( &f->f_sub_any[i], &vtmp );
519 fstr->bv_len += vtmp.bv_len + 1;
520 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
522 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
523 /* "(attr=[init]*[any*]" */ "%s*)",
525 ber_memfree( vtmp.bv_val );
529 if ( f->f_sub_final.bv_val != NULL ) {
532 filter_escape_value( &f->f_sub_final, &vtmp );
534 fstr->bv_len += vtmp.bv_len;
535 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
537 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
538 /* "(attr=[init*][any*]" */ "%s)",
541 ber_memfree( vtmp.bv_val );
546 case LDAP_FILTER_PRESENT:
547 if ( map_attr_value( at_map, oc_map, f->f_desc, &atmp,
548 NULL, NULL, remap ) )
553 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
554 fstr->bv_val = malloc( fstr->bv_len + 1 );
556 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
560 case LDAP_FILTER_AND:
562 case LDAP_FILTER_NOT:
563 fstr->bv_len = sizeof("(%)") - 1;
564 fstr->bv_val = malloc( fstr->bv_len + 128 );
566 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
567 f->f_choice == LDAP_FILTER_AND ? '&' :
568 f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
570 for ( p = f->f_list; p != NULL; p = p->f_next ) {
573 if ( ldap_back_filter_map_rewrite( at_map, oc_map, p, &vtmp, remap ) )
578 fstr->bv_len += vtmp.bv_len;
579 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
581 snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
582 /*"("*/ "%s)", vtmp.bv_val );
584 ch_free( vtmp.bv_val );
589 case LDAP_FILTER_EXT: {
590 if ( f->f_mr_desc ) {
591 if ( map_attr_value( at_map, oc_map, f->f_mr_desc, &atmp,
592 &f->f_mr_value, &vtmp, remap ) )
601 filter_escape_value( &f->f_mr_value, &vtmp );
605 fstr->bv_len = atmp.bv_len +
606 ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
607 ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
608 vtmp.bv_len + ( sizeof("(:=)") - 1 );
609 fstr->bv_val = malloc( fstr->bv_len + 1 );
611 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
613 f->f_mr_dnattrs ? ":dn" : "",
614 f->f_mr_rule_text.bv_len ? ":" : "",
615 f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
617 ber_memfree( vtmp.bv_val );
620 case SLAPD_FILTER_COMPUTED:
622 f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
623 f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
624 f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
626 f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
627 f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
628 f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
629 sizeof("(?=error)")-1,
634 ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );