Skip to content
Snippets Groups Projects
rwmmap.c 26 KiB
Newer Older
  • Learn to ignore specific revisions
  • /* rwmmap.c - rewrite/mapping routines */
    /* $OpenLDAP$ */
    /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
     *
    
    Kurt Zeilenga's avatar
    Kurt Zeilenga committed
     * Copyright 1999-2005 The OpenLDAP Foundation.
    
     * Portions Copyright 1999-2003 Howard Chu.
     * Portions Copyright 2000-2003 Pierangelo Masarati.
    
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted only as authorized by the OpenLDAP
     * Public License.
     *
     * A copy of this license is available in the file LICENSE in the
     * top-level directory of the distribution or, alternatively, at
     * <http://www.OpenLDAP.org/license.html>.
     */
    /* ACKNOWLEDGEMENTS:
     * This work was initially developed by the Howard Chu for inclusion
     * in OpenLDAP Software and subsequently enhanced by Pierangelo
     * Masarati.
     */
    
    #include "portable.h"
    
    
    #include <stdio.h>
    
    #include <ac/string.h>
    #include <ac/socket.h>
    
    #include "slap.h"
    #include "rwm.h"
    
    #undef ldap_debug	/* silence a warning in ldap-int.h */
    #include "../../../libraries/libldap/ldap-int.h"
    
    int
    
    rwm_mapping_cmp( const void *c1, const void *c2 )
    
    {
    	struct ldapmapping *map1 = (struct ldapmapping *)c1;
    	struct ldapmapping *map2 = (struct ldapmapping *)c2;
    
    	int rc = map1->m_src.bv_len - map2->m_src.bv_len;
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    	
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    
    
    	return strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val );
    
    {
    	struct ldapmapping *map1 = (struct ldapmapping *)c1;
    	struct ldapmapping *map2 = (struct ldapmapping *)c2;
    
    	int rc = map1->m_src.bv_len - map2->m_src.bv_len;
    
    	if ( rc ) {
    		return 0;
    	}
    
    	return ( ( strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val ) == 0 ) ? -1 : 0 );
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    int
    
    rwm_map_init( struct ldapmap *lm, struct ldapmapping **m )
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    	struct ldapmapping	*mapping;
    	const char		*text;
    	int			rc;
    
    
    	*m = NULL;
    	
    	mapping = (struct ldapmapping *)ch_calloc( 2, 
    			sizeof( struct ldapmapping ) );
    	if ( mapping == NULL ) {
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		return LDAP_NO_MEMORY;
    
    	/* FIXME: I don't think this is needed any more... */
    
    	rc = slap_str2ad( "objectClass", &mapping[0].m_src_ad, &text );
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    	if ( rc != LDAP_SUCCESS ) {
    		return rc;
    	}
    
    
    	mapping[0].m_dst_ad = mapping[0].m_src_ad;
    	ber_dupbv( &mapping[0].m_src, &mapping[0].m_src_ad->ad_cname );
    	ber_dupbv( &mapping[0].m_dst, &mapping[0].m_src );
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    
    
    	mapping[1].m_src = mapping[0].m_src;
    	mapping[1].m_dst = mapping[0].m_dst;
    	mapping[1].m_src_ad = mapping[0].m_src_ad;
    	mapping[1].m_dst_ad = mapping[1].m_src_ad;
    
    	avl_insert( &lm->map, (caddr_t)&mapping[0], 
    
    	avl_insert( &lm->remap, (caddr_t)&mapping[1], 
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    
    	return rc;
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    int
    rwm_mapping( struct ldapmap *map, struct berval *s, struct ldapmapping **m, int remap )
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    	struct ldapmapping fmapping;
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    
    	if ( remap == RWM_REMAP ) {
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    	*m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping,
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    
    	if ( *m == NULL ) {
    		return map->drop_missing;
    	}
    
    	return 0;
    }
    
    void
    rwm_map( struct ldapmap *map, struct berval *s, struct berval *bv, int remap )
    {
    	struct ldapmapping *mapping;
    
    	BER_BVZERO( bv );
    
    	( void )rwm_mapping( map, s, &mapping, remap );
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		if ( !BER_BVISNULL( &mapping->m_dst ) ) {
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    }
    
    /*
     * Map attribute names in place
     */
    int
    rwm_map_attrnames(
    		struct ldapmap *at_map,
    		struct ldapmap *oc_map,
    		AttributeName *an,
    		AttributeName **anp,
    		int remap
    )
    {
    	int		i, j;
    
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    	if ( an == NULL ) {
    		return LDAP_SUCCESS;
    	}
    
    	for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ )
    		/* just count */ ;
    	*anp = ch_malloc( ( i + 1 )* sizeof( AttributeName ) );
    
    	if ( *anp == NULL ) {
    		return LDAP_NO_MEMORY;
    	}
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    
    	for ( i = 0, j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
    		struct ldapmapping	*m;
    		int			at_drop_missing = 0,
    					oc_drop_missing = 0;
    
    		if ( an[i].an_desc ) {
    			if ( !at_map ) {
    				/* FIXME: better leave as is? */
    				continue;
    			}
    				
    			at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
    			if ( at_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
    				continue;
    			}
    
    			if ( !m ) {
    				(*anp)[j] = an[i];
    				j++;
    				continue;
    			}
    
    			(*anp)[j] = an[i];
    			if ( remap == RWM_MAP ) {
    				(*anp)[j].an_name = m->m_dst;
    				(*anp)[j].an_desc = m->m_dst_ad;
    			} else {
    				(*anp)[j].an_name = m->m_src;
    				(*anp)[j].an_desc = m->m_src_ad;
    
    			}
    
    			j++;
    			continue;
    
    		} else if ( an[i].an_oc ) {
    			if ( !oc_map ) {
    				/* FIXME: better leave as is? */
    				continue;
    			}
    
    			oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );
    
    			if ( oc_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
    				continue;
    			}
    
    			if ( !m ) {
    				(*anp)[j] = an[i];
    				j++;
    				continue;
    			}
    
    			(*anp)[j] = an[i];
    			if ( remap == RWM_MAP ) {
    				(*anp)[j].an_name = m->m_dst;
    				(*anp)[j].an_oc = m->m_dst_oc;
    			} else {
    				(*anp)[j].an_name = m->m_src;
    				(*anp)[j].an_oc = m->m_src_oc;
    			}
    
    		} else {
    			at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
    		
    			if ( at_drop_missing || !m ) {
    
    				oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );
    
    				/* if both at_map and oc_map required to drop missing,
    				 * then do it */
    				if ( oc_drop_missing && at_drop_missing ) {
    					continue;
    				}
    
    				/* if no oc_map mapping was found and at_map required
    				 * to drop missing, then do it; otherwise, at_map wins
    				 * and an is considered an attr and is left unchanged */
    				if ( !m ) {
    					if ( at_drop_missing ) {
    						continue;
    					}
    					(*anp)[j] = an[i];
    					j++;
    					continue;
    				}
    	
    				if ( BER_BVISNULL( &m->m_dst ) ) {
    					continue;
    				}
    
    				(*anp)[j] = an[i];
    				if ( remap == RWM_MAP ) {
    					(*anp)[j].an_name = m->m_dst;
    					(*anp)[j].an_oc = m->m_dst_oc;
    				} else {
    					(*anp)[j].an_name = m->m_src;
    					(*anp)[j].an_oc = m->m_src_oc;
    				}
    				j++;
    				continue;
    			}
    
    			if ( !BER_BVISNULL( &m->m_dst ) ) {
    				(*anp)[j] = an[i];
    				if ( remap == RWM_MAP ) {
    					(*anp)[j].an_name = m->m_dst;
    					(*anp)[j].an_desc = m->m_dst_ad;
    				} else {
    					(*anp)[j].an_name = m->m_src;
    					(*anp)[j].an_desc = m->m_src_ad;
    				}
    				j++;
    				continue;
    			}
    		}
    	}
    
    	if ( j == 0 && i != 0 ) {
    		memset( &(*anp)[0], 0, sizeof( AttributeName ) );
    		BER_BVSTR( &(*anp)[0].an_name, LDAP_NO_ATTRS );
    	}
    	memset( &(*anp)[j], 0, sizeof( AttributeName ) );
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    	return LDAP_SUCCESS;
    
    }
    
    int
    rwm_map_attrs(
    		struct ldapmap *at_map,
    		AttributeName *an,
    		int remap,
    		char ***mapped_attrs
    )
    {
    	int i, j;
    	char **na;
    
    
    		*mapped_attrs = NULL;
    		return LDAP_SUCCESS;
    	}
    
    
    	for ( i = 0; !BER_BVISNULL( &an[ i ].an_name ); i++ ) {
    
    	na = (char **)ch_calloc( i + 1, sizeof( char * ) );
    
    	if ( na == NULL ) {
    
    		*mapped_attrs = NULL;
    		return LDAP_NO_MEMORY;
    	}
    
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    	for ( i = j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
    
    		struct ldapmapping	*mapping;
    
    		if ( rwm_mapping( at_map, &an[i].an_name, &mapping, remap ) ) {
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    			continue;
    		}
    
    
    		if ( !mapping ) {
    			na[ j++ ] = an[ i ].an_name.bv_val;
    			
    		} else if ( !BER_BVISNULL( &mapping->m_dst ) ) {
    			na[ j++ ] = mapping->m_dst.bv_val;
    
    		na[ j++ ] = LDAP_NO_ATTRS;
    
    map_attr_value(
    		dncookie		*dc,
    
    		AttributeDescription 	**adp,
    
    		struct berval		*mapped_attr,
    		struct berval		*value,
    		struct berval		*mapped_value,
    		int			remap )
    {
    
    	AttributeDescription	*ad = *adp;
    	struct ldapmapping	*mapping = NULL;
    
    	rwm_mapping( &dc->rwmap->rwm_at, &ad->ad_cname, &mapping, remap );
    	if ( mapping == NULL ) {
    		if ( dc->rwmap->rwm_at.drop_missing ) {
    			return -1;
    
    		*mapped_attr = ad->ad_cname;
    
    	} else {
    		*mapped_attr = mapping->m_dst;
    
    	if ( value != NULL ) {
    		assert( mapped_value != NULL );
    
    
    		if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
    				|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
    
    		{
    			dncookie 	fdc = *dc;
    			int		rc;
    
    			fdc.ctx = "searchFilterAttrDN";
    
    #endif /* ENABLE_REWRITE */
    
    			vtmp = *value;
    			rc = rwm_dn_massage_normalize( &fdc, value, &vtmp );
    			switch ( rc ) {
    			case LDAP_SUCCESS:
    				if ( vtmp.bv_val != value->bv_val ) {
    					freeval = 1;
    				}
    				break;
    
    			case LDAP_UNWILLING_TO_PERFORM:
    			case LDAP_OTHER:
    			default:
    				return -1;
    			}
    
    		} else if ( ad == slap_schema.si_ad_objectClass
    				|| ad == slap_schema.si_ad_structuralObjectClass )
    		{
    			rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
    			if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) {
    				vtmp = *value;
    			}
    		
    		} else {
    
    		filter_escape_value( &vtmp, mapped_value );
    
    		if ( freeval ) {
    			ch_free( vtmp.bv_val );
    		}
    
    	if ( mapping != NULL ) {
    		assert( mapping->m_dst_ad != NULL );
    		*adp = mapping->m_dst_ad;
    	}
    
    
    		dncookie		*dc,
    		Filter			*f,
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		struct berval		*fstr )
    
    			/* better than nothing... */
    			ber_bvfalse = BER_BVC( "(!(objectClass=*))" ),
    			ber_bvtf_false = BER_BVC( "(|)" ),
    			/* better than nothing... */
    			ber_bvtrue = BER_BVC( "(objectClass=*)" ),
    			ber_bvtf_true = BER_BVC( "(&)" ),
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    #if 0
    			/* no longer needed; preserved for completeness */
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    #endif
    
    			ber_bverror = BER_BVC( "(?=error)" ),
    			ber_bvunknown = BER_BVC( "(?=unknown)" ),
    			ber_bvnone = BER_BVC( "(?=none)" );
    
    	ber_len_t	len;
    
    	if ( f == NULL ) {
    
    		return -1;
    	}
    
    	switch ( f->f_choice ) {
    	case LDAP_FILTER_EQUALITY:
    
    		if ( map_attr_value( dc, &f->f_av_desc, &atmp,
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    					&f->f_av_value, &vtmp, RWM_MAP ) )
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(=)" );
    
    		fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
    
    
    		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
    			atmp.bv_val, vtmp.bv_val );
    
    
    		if ( map_attr_value( dc, &f->f_av_desc, &atmp,
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    					&f->f_av_value, &vtmp, RWM_MAP ) )
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(>=)" );
    
    		fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
    
    
    		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
    			atmp.bv_val, vtmp.bv_val );
    
    
    		if ( map_attr_value( dc, &f->f_av_desc, &atmp,
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    					&f->f_av_value, &vtmp, RWM_MAP ) )
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(<=)" );
    
    		fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
    
    
    		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
    			atmp.bv_val, vtmp.bv_val );
    
    
    		break;
    
    	case LDAP_FILTER_APPROX:
    
    		if ( map_attr_value( dc, &f->f_av_desc, &atmp,
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    					&f->f_av_value, &vtmp, RWM_MAP ) )
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(~=)" );
    
    		fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
    
    
    		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
    			atmp.bv_val, vtmp.bv_val );
    
    
    		break;
    
    	case LDAP_FILTER_SUBSTRINGS:
    
    		if ( map_attr_value( dc, &f->f_sub_desc, &atmp,
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    					NULL, NULL, RWM_MAP ) )
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
    
    		fstr->bv_val = ch_malloc( fstr->bv_len + 128 );
    
    
    		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
    			atmp.bv_val );
    
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		if ( !BER_BVISNULL( &f->f_sub_initial ) ) {
    
    			len = fstr->bv_len;
    
    			filter_escape_value( &f->f_sub_initial, &vtmp );
    
    			fstr->bv_len += vtmp.bv_len;
    			fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
    
    			snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
    				/* "(attr=" */ "%s*)",
    				vtmp.bv_val );
    
    
    		}
    
    		if ( f->f_sub_any != NULL ) {
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    			for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) {
    
    				len = fstr->bv_len;
    				filter_escape_value( &f->f_sub_any[i], &vtmp );
    
    				fstr->bv_len += vtmp.bv_len + 1;
    				fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
    
    				snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
    					/* "(attr=[init]*[any*]" */ "%s*)",
    					vtmp.bv_val );
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		if ( !BER_BVISNULL( &f->f_sub_final ) ) {
    
    			len = fstr->bv_len;
    
    			filter_escape_value( &f->f_sub_final, &vtmp );
    
    			fstr->bv_len += vtmp.bv_len;
    			fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
    
    			snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
    				/* "(attr=[init*][any*]" */ "%s)",
    				vtmp.bv_val );
    
    
    		if ( map_attr_value( dc, &f->f_desc, &atmp,
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    					NULL, NULL, RWM_MAP ) )
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
    
    		fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
    
    
    		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
    			atmp.bv_val );
    		break;
    
    	case LDAP_FILTER_AND:
    	case LDAP_FILTER_OR:
    	case LDAP_FILTER_NOT:
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		fstr->bv_len = STRLENOF( "(%)" );
    
    		fstr->bv_val = ch_malloc( fstr->bv_len + 128 );
    
    
    		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
    			f->f_choice == LDAP_FILTER_AND ? '&' :
    			f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
    
    		for ( p = f->f_list; p != NULL; p = p->f_next ) {
    			len = fstr->bv_len;
    
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    			if ( rwm_int_filter_map_rewrite( dc, p, &vtmp ) )
    
    			{
    				return -1;
    			}
    			
    			fstr->bv_len += vtmp.bv_len;
    			fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
    
    			snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 
    				/*"("*/ "%s)", vtmp.bv_val );
    
    			ch_free( vtmp.bv_val );
    		}
    
    		break;
    
    	case LDAP_FILTER_EXT: {
    		if ( f->f_mr_desc ) {
    
    			if ( map_attr_value( dc, &f->f_mr_desc, &atmp,
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    						&f->f_mr_value, &vtmp, RWM_MAP ) )
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    			BER_BVSTR( &atmp, "" );
    
    			filter_escape_value( &f->f_mr_value, &vtmp );
    		}
    			
    
    		fstr->bv_len = atmp.bv_len +
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    			( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) +
    
    			( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len + 1 : 0 ) +
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    			vtmp.bv_len + STRLENOF( "(:=)" );
    
    		fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
    
    
    		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
    			atmp.bv_val,
    			f->f_mr_dnattrs ? ":dn" : "",
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    			!BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
    			!BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
    
    
    	case SLAPD_FILTER_COMPUTED:
    
    			if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
    				tmp = ber_bvtf_false;
    
    			/* fallthru */
    
    		case SLAPD_COMPARE_UNDEFINED:
    			tmp = ber_bvfalse;
    
    			if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
    				tmp = ber_bvtf_true;
    			} else {
    				tmp = ber_bvtrue;
    			}
    
    int
    rwm_filter_map_rewrite(
    		dncookie		*dc,
    		Filter			*f,
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		struct berval		*fstr )
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    	rc = rwm_int_filter_map_rewrite( dc, f, fstr );
    
    	if ( rc != 0 ) {
    		return LDAP_OTHER;
    
    	}
    
    	fdc = *dc;
    	ftmp = *fstr;
    
    	fdc.ctx = "searchFilter";
    
    	switch ( rewrite_session( fdc.rwmap->rwm_rw, fdc.ctx, 
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    				( !BER_BVISEMPTY( &ftmp ) ? ftmp.bv_val : "" ), 
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		if ( !BER_BVISNULL( fstr ) ) {
    
    		} else {
    			*fstr = ftmp;
    		}
    
    		Debug( LDAP_DEBUG_ARGS,
    			"[rw] %s: \"%s\" -> \"%s\"\n",
    
    			fdc.ctx, ftmp.bv_val, fstr->bv_val );		
    
    		rc = LDAP_SUCCESS;
    		break;
     		
     	case REWRITE_REGEXEC_UNWILLING:
    		if ( fdc.rs ) {
    			fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
    			fdc.rs->sr_text = "Operation not allowed";
    		}
    		rc = LDAP_UNWILLING_TO_PERFORM;
    		break;
    	       	
    	case REWRITE_REGEXEC_ERR:
    		if ( fdc.rs ) {
    			fdc.rs->sr_err = LDAP_OTHER;
    			fdc.rs->sr_text = "Rewrite error";
    		}
    		rc = LDAP_OTHER;
    		break;
    	}
    
    #endif /* ENABLE_REWRITE */
    	return rc;
    }
    
    
    /*
     * I don't like this much, but we need two different
     * functions because different heap managers may be
     * in use in back-ldap/meta to reduce the amount of
     * calls to malloc routines, and some of the free()
     * routines may be macros with args
     */
    int
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    	BerVarray		a_vals,
    	BerVarray		*pa_nvals )
    
    	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    	struct ldaprwmap	*rwmap = 
    			(struct ldaprwmap *)on->on_bi.bi_private;
    
    	int			i, last;
    
    	dncookie		dc;
    
    	struct berval		dn = BER_BVNULL,
    				ndn = BER_BVNULL;
    
    	 */
    	dc.rwmap = rwmap;
    #ifdef ENABLE_REWRITE
    	dc.conn = op->o_conn;
    	dc.rs = rs;
    	dc.ctx = (char *)cookie;
    
    #else /* ! ENABLE_REWRITE */
    
    #endif /* ! ENABLE_REWRITE */
    
    	for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
    		;
    	last--;
    	
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    	if ( pa_nvals != NULL ) {
    		if ( *pa_nvals == NULL ) {
    
    			*pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
    			memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    	for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
    
    		struct berval	olddn = BER_BVNULL,
    				oldval;
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		int		rc;
    
    		LDAPURLDesc	*ludp;
    
    		oldval = a_vals[i];
    		rc = ldap_url_parse( oldval.bv_val, &ludp );
    		if ( rc != LDAP_URL_SUCCESS ) {
    			/* leave attr untouched if massage failed */
    			if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
    				ber_dupbv( &(*pa_nvals)[i], &oldval );
    			}
    			continue;
    		}
    
    
    		/* FIXME: URLs like "ldap:///dc=suffix" if passed
    		 * thru ldap_url_parse() and ldap_url_desc2str() 
    		 * get rewritten as "ldap:///dc=suffix??base";
    		 * we don't want this to occur... */
    		if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
    			ludp->lud_scope = LDAP_SCOPE_DEFAULT;
    		}
    
    
    		dn = olddn;
    		if ( pa_nvals ) {
    			ndn = olddn;
    			rc = rwm_dn_massage_pretty_normalize( &dc, &olddn,
    					&dn, &ndn );
    		} else {
    			rc = rwm_dn_massage_pretty( &dc, &olddn, &dn );
    		}
    
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		switch ( rc ) {
    
    		case LDAP_UNWILLING_TO_PERFORM:
    			/*
    			 * FIXME: need to check if it may be considered 
    			 * legal to trim values when adding/modifying;
    			 * it should be when searching (e.g. ACLs).
    			 */
    			ch_free( a_vals[i].bv_val );
    			if (last > i ) {
    				a_vals[i] = a_vals[last];
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    				if ( pa_nvals ) {
    					(*pa_nvals)[i] = (*pa_nvals)[last];
    				}
    			}
    			BER_BVZERO( &a_vals[last] );
    			if ( pa_nvals ) {
    				BER_BVZERO( &(*pa_nvals)[last] );
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    		
    		case LDAP_SUCCESS:
    
    			if ( !BER_BVISNULL( &dn ) && dn.bv_val != olddn.bv_val ) {
    				char	*newurl;
    
    				ludp->lud_dn = dn.bv_val;
    				newurl = ldap_url_desc2str( ludp );
    
    				ludp->lud_dn = olddn.bv_val;
    				ch_free( dn.bv_val );
    
    				if ( newurl == NULL ) {
    					/* FIXME: leave attr untouched
    
    					break;
    				}
    
    				ber_str2bv( newurl, 0, 1, &a_vals[i] );
    				LDAP_FREE( newurl );
    
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    				if ( pa_nvals ) {
    
    					ludp->lud_dn = ndn.bv_val;
    					newurl = ldap_url_desc2str( ludp );
    
    					ludp->lud_dn = olddn.bv_val;
    					ch_free( ndn.bv_val );
    
    					if ( newurl == NULL ) {
    						/* FIXME: leave attr untouched
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    					if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
    						ch_free( (*pa_nvals)[i].bv_val );
    					}
    
    					ber_str2bv( newurl, 0, 1, &(*pa_nvals)[i] );
    					LDAP_FREE( newurl );
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    				}
    
    
    				ch_free( oldval.bv_val );
    				ludp->lud_dn = olddn.bv_val;
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    			}
    			break;
    
    
    		default:
    			/* leave attr untouched if massage failed */
    
    Pierangelo Masarati's avatar
    Pierangelo Masarati committed
    			if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
    
    				ber_dupbv( &(*pa_nvals)[i], &a_vals[i] );
    			}
    			break;
    		}
    		ldap_free_urldesc( ludp );
    	}
    	
    	return 0;
    }
    
    /*
     * I don't like this much, but we need two different
     * functions because different heap managers may be
     * in use in back-ldap/meta to reduce the amount of
     * calls to malloc routines, and some of the free()
     * routines may be macros with args
     */
    int
    rwm_dnattr_rewrite(
    	Operation		*op,
    	SlapReply		*rs,
    	void			*cookie,
    	BerVarray		a_vals,
    	BerVarray		*pa_nvals )
    {
    	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    	struct ldaprwmap	*rwmap = 
    			(struct ldaprwmap *)on->on_bi.bi_private;
    
    	int			i, last;
    
    	dncookie		dc;
    
    	struct berval		dn = BER_BVNULL,
    				ndn = BER_BVNULL;
    
    	BerVarray		in;
    
    	if ( a_vals ) {
    		in = a_vals;
    
    	} else {
    		if ( pa_nvals == NULL || *pa_nvals == NULL ) {
    			return LDAP_OTHER;
    		}
    		in = *pa_nvals;
    	}
    
    	/*
    	 * Rewrite the dn if needed
    	 */
    	dc.rwmap = rwmap;
    #ifdef ENABLE_REWRITE
    	dc.conn = op->o_conn;
    	dc.rs = rs;
    	dc.ctx = (char *)cookie;
    
    #else /* ! ENABLE_REWRITE */
    
    	dc.tofrom = ((int *)cookie)[0];
    	dc.normalized = 0;
    
    #endif /* ! ENABLE_REWRITE */
    
    
    	for ( last = 0; !BER_BVISNULL( &in[last] ); last++ );
    
    	if ( pa_nvals != NULL ) {
    		if ( *pa_nvals == NULL ) {
    
    			*pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
    			memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );