1 /* rwmmap.c - rewrite/mapping routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1999-2011 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
30 #include <ac/string.h>
31 #include <ac/socket.h>
36 #undef ldap_debug /* silence a warning in ldap-int.h */
37 #include "../../../libraries/libldap/ldap-int.h"
40 rwm_mapping_cmp( const void *c1, const void *c2 )
42 struct ldapmapping *map1 = (struct ldapmapping *)c1;
43 struct ldapmapping *map2 = (struct ldapmapping *)c2;
44 int rc = map1->m_src.bv_len - map2->m_src.bv_len;
50 return strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val );
54 rwm_mapping_dup( void *c1, void *c2 )
56 struct ldapmapping *map1 = (struct ldapmapping *)c1;
57 struct ldapmapping *map2 = (struct ldapmapping *)c2;
58 int rc = map1->m_src.bv_len - map2->m_src.bv_len;
64 return ( ( strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val ) == 0 ) ? -1 : 0 );
68 rwm_map_init( struct ldapmap *lm, struct ldapmapping **m )
70 struct ldapmapping *mapping;
78 mapping = (struct ldapmapping *)ch_calloc( 2,
79 sizeof( struct ldapmapping ) );
80 if ( mapping == NULL ) {
81 return LDAP_NO_MEMORY;
84 /* NOTE: this is needed to make sure that
86 * does not filter out all attributes including objectClass */
87 rc = slap_str2ad( "objectClass", &mapping[0].m_src_ad, &text );
88 if ( rc != LDAP_SUCCESS ) {
93 mapping[0].m_dst_ad = mapping[0].m_src_ad;
94 ber_dupbv( &mapping[0].m_src, &mapping[0].m_src_ad->ad_cname );
95 ber_dupbv( &mapping[0].m_dst, &mapping[0].m_src );
97 mapping[1].m_src = mapping[0].m_src;
98 mapping[1].m_dst = mapping[0].m_dst;
99 mapping[1].m_src_ad = mapping[0].m_src_ad;
100 mapping[1].m_dst_ad = mapping[1].m_src_ad;
102 avl_insert( &lm->map, (caddr_t)&mapping[0],
103 rwm_mapping_cmp, rwm_mapping_dup );
104 avl_insert( &lm->remap, (caddr_t)&mapping[1],
105 rwm_mapping_cmp, rwm_mapping_dup );
113 rwm_mapping( struct ldapmap *map, struct berval *s, struct ldapmapping **m, int remap )
116 struct ldapmapping fmapping;
124 /* let special attrnames slip through (ITS#5760) */
125 if ( bvmatch( s, slap_bv_no_attrs )
126 || bvmatch( s, slap_bv_all_user_attrs )
127 || bvmatch( s, slap_bv_all_operational_attrs ) )
133 if ( remap == RWM_REMAP ) {
141 *m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping,
145 return map->drop_missing;
152 rwm_map( struct ldapmap *map, struct berval *s, struct berval *bv, int remap )
154 struct ldapmapping *mapping;
156 /* map->map may be NULL when mapping is configured,
157 * but map->remap can't */
158 if ( map->remap == NULL ) {
164 ( void )rwm_mapping( map, s, &mapping, remap );
165 if ( mapping != NULL ) {
166 if ( !BER_BVISNULL( &mapping->m_dst ) ) {
167 *bv = mapping->m_dst;
172 if ( !map->drop_missing ) {
178 * Map attribute names in place
183 struct ldapmap *at_map,
184 struct ldapmap *oc_map,
191 assert( anp != NULL );
199 for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ )
201 *anp = op->o_tmpalloc( ( i + 1 )* sizeof( AttributeName ),
203 if ( *anp == NULL ) {
204 return LDAP_NO_MEMORY;
207 for ( i = 0, j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
208 struct ldapmapping *m;
209 int at_drop_missing = 0,
212 if ( an[i].an_desc ) {
214 /* FIXME: better leave as is? */
218 at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
219 if ( at_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
230 if ( remap == RWM_MAP ) {
231 (*anp)[j].an_name = m->m_dst;
232 (*anp)[j].an_desc = m->m_dst_ad;
234 (*anp)[j].an_name = m->m_src;
235 (*anp)[j].an_desc = m->m_src_ad;
242 } else if ( an[i].an_oc ) {
244 /* FIXME: better leave as is? */
248 oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );
250 if ( oc_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
261 if ( remap == RWM_MAP ) {
262 (*anp)[j].an_name = m->m_dst;
263 (*anp)[j].an_oc = m->m_dst_oc;
265 (*anp)[j].an_name = m->m_src;
266 (*anp)[j].an_oc = m->m_src_oc;
270 at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
272 if ( at_drop_missing || !m ) {
273 oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );
275 /* if both at_map and oc_map required to drop missing,
277 if ( oc_drop_missing && at_drop_missing ) {
281 /* if no oc_map mapping was found and at_map required
282 * to drop missing, then do it; otherwise, at_map wins
283 * and an is considered an attr and is left unchanged */
285 if ( at_drop_missing ) {
293 if ( BER_BVISNULL( &m->m_dst ) ) {
298 if ( remap == RWM_MAP ) {
299 (*anp)[j].an_name = m->m_dst;
300 (*anp)[j].an_oc = m->m_dst_oc;
302 (*anp)[j].an_name = m->m_src;
303 (*anp)[j].an_oc = m->m_src_oc;
309 if ( !BER_BVISNULL( &m->m_dst ) ) {
311 if ( remap == RWM_MAP ) {
312 (*anp)[j].an_name = m->m_dst;
313 (*anp)[j].an_desc = m->m_dst_ad;
315 (*anp)[j].an_name = m->m_src;
316 (*anp)[j].an_desc = m->m_src_ad;
324 if ( j == 0 && i != 0 ) {
325 memset( &(*anp)[0], 0, sizeof( AttributeName ) );
326 (*anp)[0].an_name = *slap_bv_no_attrs;
329 memset( &(*anp)[j], 0, sizeof( AttributeName ) );
337 struct ldapmap *at_map,
340 char ***mapped_attrs )
346 *mapped_attrs = NULL;
350 for ( i = 0; !BER_BVISNULL( &an[ i ].an_name ); i++ )
353 na = (char **)ch_calloc( i + 1, sizeof( char * ) );
355 *mapped_attrs = NULL;
356 return LDAP_NO_MEMORY;
359 for ( i = j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
360 struct ldapmapping *mapping;
362 if ( rwm_mapping( at_map, &an[i].an_name, &mapping, remap ) ) {
367 na[ j++ ] = an[ i ].an_name.bv_val;
369 } else if ( !BER_BVISNULL( &mapping->m_dst ) ) {
370 na[ j++ ] = mapping->m_dst.bv_val;
374 if ( j == 0 && i != 0 ) {
375 na[ j++ ] = LDAP_NO_ATTRS;
389 AttributeDescription **adp,
390 struct berval *mapped_attr,
391 struct berval *value,
392 struct berval *mapped_value,
396 struct berval vtmp = BER_BVNULL;
398 AttributeDescription *ad = *adp;
399 struct ldapmapping *mapping = NULL;
401 rwm_mapping( &dc->rwmap->rwm_at, &ad->ad_cname, &mapping, remap );
402 if ( mapping == NULL ) {
403 if ( dc->rwmap->rwm_at.drop_missing ) {
407 *mapped_attr = ad->ad_cname;
410 *mapped_attr = mapping->m_dst;
413 if ( value != NULL ) {
414 assert( mapped_value != NULL );
416 if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
417 || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
422 fdc.ctx = "searchFilterAttrDN";
425 rc = rwm_dn_massage_normalize( &fdc, value, &vtmp );
428 if ( vtmp.bv_val != value->bv_val ) {
433 case LDAP_UNWILLING_TO_PERFORM:
439 } else if ( ad->ad_type->sat_equality &&
440 ( ad->ad_type->sat_equality->smr_usage & SLAP_MR_MUTATION_NORMALIZER ) )
442 if ( ad->ad_type->sat_equality->smr_normalize(
443 (SLAP_MR_DENORMALIZE|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX),
444 NULL, NULL, value, &vtmp, memctx ) )
450 } else if ( ad == slap_schema.si_ad_objectClass
451 || ad == slap_schema.si_ad_structuralObjectClass )
453 rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
454 if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) {
462 filter_escape_value_x( &vtmp, mapped_value, memctx );
466 ch_free( vtmp.bv_val );
470 ber_memfree_x( vtmp.bv_val, memctx );
475 if ( mapping != NULL ) {
476 assert( mapping->m_dst_ad != NULL );
477 *adp = mapping->m_dst_ad;
484 rwm_int_filter_map_rewrite(
488 struct berval *fstr )
492 AttributeDescription *ad;
497 /* better than nothing... */
498 ber_bvfalse = BER_BVC( "(!(objectClass=*))" ),
499 ber_bvtf_false = BER_BVC( "(|)" ),
500 /* better than nothing... */
501 ber_bvtrue = BER_BVC( "(objectClass=*)" ),
502 ber_bvtf_true = BER_BVC( "(&)" ),
504 /* no longer needed; preserved for completeness */
505 ber_bvundefined = BER_BVC( "(?=undefined)" ),
507 ber_bverror = BER_BVC( "(?=error)" ),
508 ber_bvunknown = BER_BVC( "(?=unknown)" ),
509 ber_bvnone = BER_BVC( "(?=none)" );
512 assert( fstr != NULL );
516 ber_dupbv_x( fstr, &ber_bvnone, op->o_tmpmemctx );
521 /* ITS#6814: give the caller a chance to use undefined filters */
522 if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
527 switch ( f->f_choice & SLAPD_FILTER_MASK ) {
528 case LDAP_FILTER_EQUALITY:
530 if ( map_attr_value( dc, &ad, &atmp,
531 &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
536 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(=)" );
537 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
539 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
540 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
542 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
547 if ( map_attr_value( dc, &ad, &atmp,
548 &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
553 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(>=)" );
554 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
556 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
557 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
559 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
564 if ( map_attr_value( dc, &ad, &atmp,
565 &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
570 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(<=)" );
571 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
573 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
574 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
576 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
579 case LDAP_FILTER_APPROX:
581 if ( map_attr_value( dc, &ad, &atmp,
582 &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
587 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(~=)" );
588 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
590 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
591 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
593 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
596 case LDAP_FILTER_SUBSTRINGS:
598 if ( map_attr_value( dc, &ad, &atmp,
599 NULL, NULL, RWM_MAP, op->o_tmpmemctx ) )
604 /* cannot be a DN ... */
606 fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
607 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
609 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
612 if ( !BER_BVISNULL( &f->f_sub_initial ) ) {
615 filter_escape_value_x( &f->f_sub_initial, &vtmp, op->o_tmpmemctx );
617 fstr->bv_len += vtmp.bv_len;
618 fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
621 snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
622 /* "(attr=" */ "%s*)",
623 vtmp.bv_len ? vtmp.bv_val : "" );
625 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
628 if ( f->f_sub_any != NULL ) {
629 for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) {
631 filter_escape_value_x( &f->f_sub_any[i], &vtmp,
634 fstr->bv_len += vtmp.bv_len + 1;
635 fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
638 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
639 /* "(attr=[init]*[any*]" */ "%s*)",
640 vtmp.bv_len ? vtmp.bv_val : "" );
641 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
645 if ( !BER_BVISNULL( &f->f_sub_final ) ) {
648 filter_escape_value_x( &f->f_sub_final, &vtmp, op->o_tmpmemctx );
650 fstr->bv_len += vtmp.bv_len;
651 fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
654 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
655 /* "(attr=[init*][any*]" */ "%s)",
656 vtmp.bv_len ? vtmp.bv_val : "" );
658 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
663 case LDAP_FILTER_PRESENT:
665 if ( map_attr_value( dc, &ad, &atmp,
666 NULL, NULL, RWM_MAP, op->o_tmpmemctx ) )
671 fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
672 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
674 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
678 case LDAP_FILTER_AND:
680 case LDAP_FILTER_NOT:
681 fstr->bv_len = STRLENOF( "(%)" );
682 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
684 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
685 f->f_choice == LDAP_FILTER_AND ? '&' :
686 f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
688 for ( p = f->f_list; p != NULL; p = p->f_next ) {
693 rc = rwm_int_filter_map_rewrite( op, dc, p, &vtmp );
694 if ( rc != LDAP_SUCCESS ) {
698 fstr->bv_len += vtmp.bv_len;
699 fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
702 snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
703 /*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" );
705 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
710 case LDAP_FILTER_EXT: {
711 if ( f->f_mr_desc ) {
713 if ( map_attr_value( dc, &ad, &atmp,
714 &f->f_mr_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
720 BER_BVSTR( &atmp, "" );
721 filter_escape_value_x( &f->f_mr_value, &vtmp, op->o_tmpmemctx );
725 fstr->bv_len = atmp.bv_len +
726 ( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) +
727 ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len + 1 : 0 ) +
728 vtmp.bv_len + STRLENOF( "(:=)" );
729 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
731 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
733 f->f_mr_dnattrs ? ":dn" : "",
734 !BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
735 !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
736 vtmp.bv_len ? vtmp.bv_val : "" );
737 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
743 filter_free_x( op, f, 0 );
744 f->f_choice = SLAPD_FILTER_COMPUTED;
745 f->f_result = SLAPD_COMPARE_UNDEFINED;
748 case SLAPD_FILTER_COMPUTED:
749 switch ( f->f_result ) {
750 case LDAP_COMPARE_FALSE:
751 /* FIXME: treat UNDEFINED as FALSE */
752 case SLAPD_COMPARE_UNDEFINED:
753 if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
754 tmp = &ber_bvtf_false;
760 case LDAP_COMPARE_TRUE:
761 if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
762 tmp = &ber_bvtf_true;
773 ber_dupbv_x( fstr, tmp, op->o_tmpmemctx );
777 ber_dupbv_x( fstr, &ber_bvunknown, op->o_tmpmemctx );
785 rwm_filter_map_rewrite(
789 struct berval *fstr )
795 rc = rwm_int_filter_map_rewrite( op, dc, f, fstr );
804 fdc.ctx = "searchFilter";
806 switch ( rewrite_session( fdc.rwmap->rwm_rw, fdc.ctx,
807 ( !BER_BVISEMPTY( &ftmp ) ? ftmp.bv_val : "" ),
808 fdc.conn, &fstr->bv_val ) )
810 case REWRITE_REGEXEC_OK:
811 if ( !BER_BVISNULL( fstr ) ) {
812 fstr->bv_len = strlen( fstr->bv_val );
818 Debug( LDAP_DEBUG_ARGS,
819 "[rw] %s: \"%s\" -> \"%s\"\n",
820 fdc.ctx, ftmp.bv_val, fstr->bv_val );
821 if ( fstr->bv_val != ftmp.bv_val ) {
822 ber_bvreplace_x( &ftmp, fstr, op->o_tmpmemctx );
823 ch_free( fstr->bv_val );
829 case REWRITE_REGEXEC_UNWILLING:
831 fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
832 fdc.rs->sr_text = "Operation not allowed";
834 op->o_tmpfree( ftmp.bv_val, op->o_tmpmemctx );
835 rc = LDAP_UNWILLING_TO_PERFORM;
838 case REWRITE_REGEXEC_ERR:
840 fdc.rs->sr_err = LDAP_OTHER;
841 fdc.rs->sr_text = "Rewrite error";
843 op->o_tmpfree( ftmp.bv_val, op->o_tmpmemctx );
852 * I don't like this much, but we need two different
853 * functions because different heap managers may be
854 * in use in back-ldap/meta to reduce the amount of
855 * calls to malloc routines, and some of the free()
856 * routines may be macros with args
859 rwm_referral_rewrite(
864 BerVarray *pa_nvals )
866 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
867 struct ldaprwmap *rwmap =
868 (struct ldaprwmap *)on->on_bi.bi_private;
873 struct berval dn = BER_BVNULL,
876 assert( a_vals != NULL );
879 * Rewrite the dn if needed
882 dc.conn = op->o_conn;
884 dc.ctx = (char *)cookie;
886 for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
890 if ( pa_nvals != NULL ) {
891 if ( *pa_nvals == NULL ) {
892 *pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
893 memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
897 for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
898 struct berval olddn = BER_BVNULL,
904 rc = ldap_url_parse( oldval.bv_val, &ludp );
905 if ( rc != LDAP_URL_SUCCESS ) {
906 /* leave attr untouched if massage failed */
907 if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
908 ber_dupbv( &(*pa_nvals)[i], &oldval );
913 /* FIXME: URLs like "ldap:///dc=suffix" if passed
914 * thru ldap_url_parse() and ldap_url_desc2str()
915 * get rewritten as "ldap:///dc=suffix??base";
916 * we don't want this to occur... */
917 if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
918 ludp->lud_scope = LDAP_SCOPE_DEFAULT;
921 ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
926 rc = rwm_dn_massage_pretty_normalize( &dc, &olddn,
929 rc = rwm_dn_massage_pretty( &dc, &olddn, &dn );
933 case LDAP_UNWILLING_TO_PERFORM:
935 * FIXME: need to check if it may be considered
936 * legal to trim values when adding/modifying;
937 * it should be when searching (e.g. ACLs).
939 ch_free( a_vals[i].bv_val );
941 a_vals[i] = a_vals[last];
943 (*pa_nvals)[i] = (*pa_nvals)[last];
946 BER_BVZERO( &a_vals[last] );
948 BER_BVZERO( &(*pa_nvals)[last] );
954 if ( !BER_BVISNULL( &dn ) && dn.bv_val != olddn.bv_val ) {
957 ludp->lud_dn = dn.bv_val;
958 newurl = ldap_url_desc2str( ludp );
959 ludp->lud_dn = olddn.bv_val;
960 ch_free( dn.bv_val );
961 if ( newurl == NULL ) {
962 /* FIXME: leave attr untouched
963 * even if ldap_url_desc2str failed...
968 ber_str2bv( newurl, 0, 1, &a_vals[i] );
969 ber_memfree( newurl );
972 ludp->lud_dn = ndn.bv_val;
973 newurl = ldap_url_desc2str( ludp );
974 ludp->lud_dn = olddn.bv_val;
975 ch_free( ndn.bv_val );
976 if ( newurl == NULL ) {
977 /* FIXME: leave attr untouched
978 * even if ldap_url_desc2str failed...
980 ch_free( a_vals[i].bv_val );
985 if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
986 ch_free( (*pa_nvals)[i].bv_val );
988 ber_str2bv( newurl, 0, 1, &(*pa_nvals)[i] );
989 ber_memfree( newurl );
992 ch_free( oldval.bv_val );
993 ludp->lud_dn = olddn.bv_val;
998 /* leave attr untouched if massage failed */
999 if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
1000 ber_dupbv( &(*pa_nvals)[i], &a_vals[i] );
1004 ldap_free_urldesc( ludp );
1011 * I don't like this much, but we need two different
1012 * functions because different heap managers may be
1013 * in use in back-ldap/meta to reduce the amount of
1014 * calls to malloc routines, and some of the free()
1015 * routines may be macros with args
1023 BerVarray *pa_nvals )
1025 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1026 struct ldaprwmap *rwmap =
1027 (struct ldaprwmap *)on->on_bi.bi_private;
1032 struct berval dn = BER_BVNULL,
1040 if ( pa_nvals == NULL || *pa_nvals == NULL ) {
1047 * Rewrite the dn if needed
1050 dc.conn = op->o_conn;
1052 dc.ctx = (char *)cookie;
1054 for ( last = 0; !BER_BVISNULL( &in[last] ); last++ );
1056 if ( pa_nvals != NULL ) {
1057 if ( *pa_nvals == NULL ) {
1058 *pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
1059 memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
1063 for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
1069 ndn = (*pa_nvals)[i];
1070 rc = rwm_dn_massage_pretty_normalize( &dc, &in[i], &dn, &ndn );
1072 rc = rwm_dn_massage_pretty( &dc, &in[i], &dn );
1076 rc = rwm_dn_massage_normalize( &dc, &in[i], &ndn );
1080 case LDAP_UNWILLING_TO_PERFORM:
1082 * FIXME: need to check if it may be considered
1083 * legal to trim values when adding/modifying;
1084 * it should be when searching (e.g. ACLs).
1086 ch_free( in[i].bv_val );
1089 if ( a_vals && pa_nvals ) {
1090 (*pa_nvals)[i] = (*pa_nvals)[last];
1093 BER_BVZERO( &in[last] );
1094 if ( a_vals && pa_nvals ) {
1095 BER_BVZERO( &(*pa_nvals)[last] );
1102 if ( !BER_BVISNULL( &dn ) && dn.bv_val != a_vals[i].bv_val ) {
1103 ch_free( a_vals[i].bv_val );
1107 if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
1108 ch_free( (*pa_nvals)[i].bv_val );
1110 (*pa_nvals)[i] = ndn;
1115 if ( !BER_BVISNULL( &ndn ) && ndn.bv_val != (*pa_nvals)[i].bv_val ) {
1116 ch_free( (*pa_nvals)[i].bv_val );
1117 (*pa_nvals)[i] = ndn;
1123 /* leave attr untouched if massage failed */
1124 if ( a_vals && pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
1125 dnNormalize( 0, NULL, NULL, &a_vals[i], &(*pa_nvals)[i], NULL );
1135 rwm_referral_result_rewrite(
1141 for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ );
1144 for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
1150 rc = ldap_url_parse( a_vals[i].bv_val, &ludp );
1151 if ( rc != LDAP_URL_SUCCESS ) {
1152 /* leave attr untouched if massage failed */
1156 /* FIXME: URLs like "ldap:///dc=suffix" if passed
1157 * thru ldap_url_parse() and ldap_url_desc2str()
1158 * get rewritten as "ldap:///dc=suffix??base";
1159 * we don't want this to occur... */
1160 if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
1161 ludp->lud_scope = LDAP_SCOPE_DEFAULT;
1164 ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
1167 rc = rwm_dn_massage_pretty( dc, &olddn, &dn );
1169 case LDAP_UNWILLING_TO_PERFORM:
1171 * FIXME: need to check if it may be considered
1172 * legal to trim values when adding/modifying;
1173 * it should be when searching (e.g. ACLs).
1175 ch_free( a_vals[i].bv_val );
1177 a_vals[i] = a_vals[last];
1179 BER_BVZERO( &a_vals[last] );
1185 /* leave attr untouched if massage failed */
1186 if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val ) {
1189 ludp->lud_dn = dn.bv_val;
1190 newurl = ldap_url_desc2str( ludp );
1191 if ( newurl == NULL ) {
1192 /* FIXME: leave attr untouched
1193 * even if ldap_url_desc2str failed...
1198 ch_free( a_vals[i].bv_val );
1199 ber_str2bv( newurl, 0, 1, &a_vals[i] );
1200 ber_memfree( newurl );
1201 ludp->lud_dn = olddn.bv_val;
1206 ldap_free_urldesc( ludp );
1213 rwm_dnattr_result_rewrite(
1220 for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ );
1223 for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
1224 struct berval pdn, ndn = BER_BVNULL;
1228 rc = rwm_dn_massage_pretty_normalize( dc, &a_vals[i], &pdn, &ndn );
1230 case LDAP_UNWILLING_TO_PERFORM:
1232 * FIXME: need to check if it may be considered
1233 * legal to trim values when adding/modifying;
1234 * it should be when searching (e.g. ACLs).
1236 assert( a_vals[i].bv_val != a_nvals[i].bv_val );
1237 ch_free( a_vals[i].bv_val );
1238 ch_free( a_nvals[i].bv_val );
1240 a_vals[i] = a_vals[last];
1241 a_nvals[i] = a_nvals[last];
1243 BER_BVZERO( &a_vals[last] );
1244 BER_BVZERO( &a_nvals[last] );
1249 /* leave attr untouched if massage failed */
1250 if ( !BER_BVISNULL( &pdn ) && a_vals[i].bv_val != pdn.bv_val ) {
1251 ch_free( a_vals[i].bv_val );
1254 if ( !BER_BVISNULL( &ndn ) && a_nvals[i].bv_val != ndn.bv_val ) {
1255 ch_free( a_nvals[i].bv_val );
1266 rwm_mapping_dst_free( void *v_mapping )
1268 struct ldapmapping *mapping = v_mapping;
1270 if ( BER_BVISEMPTY( &mapping[0].m_dst ) ) {
1271 rwm_mapping_free( &mapping[ -1 ] );
1276 rwm_mapping_free( void *v_mapping )
1278 struct ldapmapping *mapping = v_mapping;
1280 if ( !BER_BVISNULL( &mapping[0].m_src ) ) {
1281 ch_free( mapping[0].m_src.bv_val );
1284 if ( mapping[0].m_flags & RWMMAP_F_FREE_SRC ) {
1285 if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
1286 if ( mapping[0].m_src_oc ) {
1287 ch_free( mapping[0].m_src_oc );
1291 if ( mapping[0].m_src_ad ) {
1292 ch_free( mapping[0].m_src_ad );
1297 if ( !BER_BVISNULL( &mapping[0].m_dst ) ) {
1298 ch_free( mapping[0].m_dst.bv_val );
1301 if ( mapping[0].m_flags & RWMMAP_F_FREE_DST ) {
1302 if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
1303 if ( mapping[0].m_dst_oc ) {
1304 ch_free( mapping[0].m_dst_oc );
1308 if ( mapping[0].m_dst_ad ) {
1309 ch_free( mapping[0].m_dst_ad );
1318 #endif /* SLAPD_OVER_RWM */