From b116bb3814484ed25551b0cb87f353a2b77132ed Mon Sep 17 00:00:00 2001
From: Pierangelo Masarati <ando@openldap.org>
Date: Thu, 20 Jan 2005 22:44:54 +0000
Subject: [PATCH] fix ITS#3499 (may need further testing)

---
 servers/slapd/back-meta/add.c   |  17 +++--
 servers/slapd/overlays/rwm.c    |  74 +++++++++++-------
 servers/slapd/overlays/rwmmap.c | 129 ++++++++++++++++++--------------
 3 files changed, 126 insertions(+), 94 deletions(-)

diff --git a/servers/slapd/back-meta/add.c b/servers/slapd/back-meta/add.c
index 571b57b75f..15f13ee892 100644
--- a/servers/slapd/back-meta/add.c
+++ b/servers/slapd/back-meta/add.c
@@ -83,9 +83,10 @@ meta_back_add( Operation *op, SlapReply *rs )
 	/* Create array of LDAPMods for ldap_add() */
 	attrs = ch_malloc( sizeof( LDAPMod * )*i );
 
+	dc.ctx = "addAttrDN";
 	isupdate = be_shadow_update( op );
 	for ( i = 0, a = op->ora_e->e_attrs; a; a = a->a_next ) {
-		int	j, is_oc = 0;
+		int			j, is_oc = 0;
 
 		if ( !isupdate && a->a_desc->ad_type->sat_no_user_mod  ) {
 			continue;
@@ -154,12 +155,14 @@ meta_back_add( Operation *op, SlapReply *rs )
 				}
 			}
 
-			for ( j = 0; a->a_vals[ j ].bv_val; j++ );
-			attrs[ i ]->mod_vals.modv_bvals = ch_malloc((j+1)*sizeof(struct berval *));
-			for ( j = 0; a->a_vals[ j ].bv_val; j++ ) {
-				attrs[ i ]->mod_vals.modv_bvals[ j ] = &a->a_vals[ j ];
+			for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ )
+				;
+			
+			attrs[ i ]->mod_bvalues = ch_malloc( ( j + 1 ) * sizeof( struct berval * ) );
+			for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) {
+				attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ];
 			}
-			attrs[ i ]->mod_vals.modv_bvals[ j ] = NULL;
+			attrs[ i ]->mod_bvalues[ j ] = NULL;
 		}
 		i++;
 	}
@@ -168,7 +171,7 @@ meta_back_add( Operation *op, SlapReply *rs )
 	rs->sr_err = ldap_add_ext_s( lc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
 			      attrs, NULL, NULL );
 	for ( --i; i >= 0; --i ) {
-		free( attrs[ i ]->mod_vals.modv_bvals );
+		free( attrs[ i ]->mod_bvalues );
 		free( attrs[ i ] );
 	}
 	free( attrs );
diff --git a/servers/slapd/overlays/rwm.c b/servers/slapd/overlays/rwm.c
index c16ad4e1d7..d9ca042554 100644
--- a/servers/slapd/overlays/rwm.c
+++ b/servers/slapd/overlays/rwm.c
@@ -121,7 +121,6 @@ rwm_op_add( Operation *op, SlapReply *rs )
 	/* Count number of attributes in entry */ 
 	isupdate = be_shadow_update( op );
 	for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
-		struct berval	mapped;
 		Attribute	*a;
 
 		if ( (*ap)->a_desc == slap_schema.si_ad_objectClass ||
@@ -170,9 +169,6 @@ rwm_op_add( Operation *op, SlapReply *rs )
 				if ( rwmap->rwm_at.drop_missing ) {
 					goto cleanup_attr;
 				}
-
-			} else {
-				(*ap)->a_desc = mapping->m_dst_ad;
 			}
 
 			if ( (*ap)->a_desc->ad_type->sat_syntax
@@ -209,6 +205,11 @@ rwm_op_add( Operation *op, SlapReply *rs )
 					goto cleanup_attr;
 				}
 			}
+		
+			if ( mapping != NULL ) {
+				assert( mapping->m_dst_ad );
+				(*ap)->a_desc = mapping->m_dst_ad;
+			}
 		}
 
 next_attr:;
@@ -322,6 +323,7 @@ rwm_op_compare( Operation *op, SlapReply *rs )
 			}
 
 		} else {
+			assert( mapping->m_dst_ad );
 			ad = mapping->m_dst_ad;
 		}
 
@@ -401,8 +403,9 @@ rwm_op_modify( Operation *op, SlapReply *rs )
 
 	isupdate = be_shadow_update( op );
 	for ( mlp = &op->oq_modify.rs_modlist; *mlp; ) {
-		int		is_oc = 0;
-		Modifications	*ml;
+		int			is_oc = 0;
+		Modifications		*ml;
+		struct ldapmapping	*mapping = NULL;
 
 		if ( (*mlp)->sml_desc == slap_schema.si_ad_objectClass 
 				|| (*mlp)->sml_desc == slap_schema.si_ad_structuralObjectClass )
@@ -413,20 +416,15 @@ rwm_op_modify( Operation *op, SlapReply *rs )
 			goto next_mod;
 
 		} else {
-			struct ldapmapping	*m;
 			int			drop_missing;
 
-			drop_missing = rwm_mapping( &rwmap->rwm_at, &(*mlp)->sml_desc->ad_cname, &m, RWM_MAP );
-			if ( drop_missing || ( m != NULL && BER_BVISNULL( &m->m_dst ) ) )
+			drop_missing = rwm_mapping( &rwmap->rwm_at,
+					&(*mlp)->sml_desc->ad_cname,
+					&mapping, RWM_MAP );
+			if ( drop_missing || ( mapping != NULL && BER_BVISNULL( &mapping->m_dst ) ) )
 			{
 				goto cleanup_mod;
 			}
-
-			if ( m ) {
-				/* use new attribute description */
-				assert( m->m_dst_ad );
-				(*mlp)->sml_desc = m->m_dst_ad;
-			}
 		}
 
 		if ( (*mlp)->sml_values != NULL ) {
@@ -502,6 +500,12 @@ rwm_op_modify( Operation *op, SlapReply *rs )
 		}
 
 next_mod:;
+		if ( mapping != NULL ) {
+			/* use new attribute description */
+			assert( mapping->m_dst_ad );
+			(*mlp)->sml_desc = mapping->m_dst_ad;
+		}
+
 		mlp = &(*mlp)->sml_next;
 		continue;
 
@@ -818,7 +822,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first )
 	 * about duplicate values?) */
 	isupdate = be_shadow_update( op );
 	for ( ap = a_first; *ap; ) {
-		struct ldapmapping	*m;
+		struct ldapmapping	*mapping;
 		int			drop_missing;
 		int			last;
 		Attribute		*a;
@@ -827,10 +831,28 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first )
 		{
 			/* go on */ ;
 			
-		} else if ( op->ors_attrs != NULL && 
-				!SLAP_USERATTRS( rs->sr_attr_flags ) && 
-				!ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
-		{
+		} else {
+			drop_missing = rwm_mapping( &rwmap->rwm_at,
+					&(*ap)->a_desc->ad_cname, &mapping, RWM_REMAP );
+			if ( drop_missing || ( mapping != NULL && BER_BVISEMPTY( &mapping->m_dst ) ) )
+			{
+				goto cleanup_attr;
+			}
+
+			if ( mapping != NULL ) {
+				(*ap)->a_desc = mapping->m_dst_ad;
+			}
+
+			if ( op->ors_attrs != NULL && 
+					!SLAP_USERATTRS( rs->sr_attr_flags ) &&
+					!ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
+			{
+				goto cleanup_attr;
+			}
+		}
+
+		if ( (*ap)->a_desc == slap_schema.si_ad_entryDN ) {
+			/* will be generated by frontend */
 			goto cleanup_attr;
 		}
 
@@ -840,12 +862,6 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first )
 			goto next_attr;
 		}
 
-		drop_missing = rwm_mapping( &rwmap->rwm_at,
-				&(*ap)->a_desc->ad_cname, &m, RWM_REMAP );
-		if ( drop_missing || ( m != NULL && BER_BVISEMPTY( &m->m_dst ) ) ) {
-			goto cleanup_attr;
-		}
-
 		for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
 			/* just count */ ;
 
@@ -918,10 +934,10 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first )
 			}
 		}
 
-		if ( m != NULL ) {
+		if ( mapping != NULL ) {
 			/* rewrite the attribute description */
-			assert( m->m_dst_ad );
-			(*ap)->a_desc = m->m_dst_ad;
+			assert( mapping->m_dst_ad );
+			(*ap)->a_desc = mapping->m_dst_ad;
 		}
 
 next_attr:;
diff --git a/servers/slapd/overlays/rwmmap.c b/servers/slapd/overlays/rwmmap.c
index 9662661622..e551f3568a 100644
--- a/servers/slapd/overlays/rwmmap.c
+++ b/servers/slapd/overlays/rwmmap.c
@@ -321,40 +321,46 @@ rwm_map_attrs(
 		return LDAP_SUCCESS;
 	}
 
-	for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
+	for ( i = 0; !BER_BVISNULL( &an[ i ].an_name ); i++ ) {
 		/*  */
 	}
 
 	na = (char **)ch_calloc( i + 1, sizeof( char * ) );
-	if (na == NULL) {
+	if ( na == NULL ) {
 		*mapped_attrs = NULL;
 		return LDAP_NO_MEMORY;
 	}
 
 	for ( i = j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
-		struct ldapmapping	*m;
+		struct ldapmapping	*mapping;
 		
-		if ( rwm_mapping( at_map, &an[i].an_name, &m, remap ) ) {
+		if ( rwm_mapping( at_map, &an[i].an_name, &mapping, remap ) ) {
 			continue;
 		}
 
-		if ( !m || ( m && !BER_BVISNULL( &m->m_dst ) ) ) {
-			na[j++] = m->m_dst.bv_val;
+		if ( !mapping ) {
+			na[ j++ ] = an[ i ].an_name.bv_val;
+			
+		} else if ( !BER_BVISNULL( &mapping->m_dst ) ) {
+			na[ j++ ] = mapping->m_dst.bv_val;
 		}
 	}
+
 	if ( j == 0 && i != 0 ) {
-		na[j++] = LDAP_NO_ATTRS;
+		na[ j++ ] = LDAP_NO_ATTRS;
 	}
-	na[j] = NULL;
+
+	na[ j ] = NULL;
 
 	*mapped_attrs = na;
+
 	return LDAP_SUCCESS;
 }
 
 static int
 map_attr_value(
 		dncookie		*dc,
-		AttributeDescription 	*ad,
+		AttributeDescription 	**adp,
 		struct berval		*mapped_attr,
 		struct berval		*value,
 		struct berval		*mapped_value,
@@ -362,65 +368,72 @@ map_attr_value(
 {
 	struct berval		vtmp = BER_BVNULL;
 	int			freeval = 0;
+	AttributeDescription	*ad = *adp;
+	struct ldapmapping	*mapping = NULL;
 
-	rwm_map( &dc->rwmap->rwm_at, &ad->ad_cname, mapped_attr, remap );
-	if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) {
-		/*
-		 * FIXME: are we sure we need to search oc_map if at_map fails?
-		 */
-		rwm_map( &dc->rwmap->rwm_oc, &ad->ad_cname, mapped_attr, remap );
-		if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) )
-		{
-			*mapped_attr = ad->ad_cname;
+	rwm_mapping( &dc->rwmap->rwm_at, &ad->ad_cname, &mapping, remap );
+	if ( mapping == NULL ) {
+		if ( dc->rwmap->rwm_at.drop_missing ) {
+			return -1;
 		}
-	}
 
-	if ( value == NULL ) {
-		return 0;
+		*mapped_attr = ad->ad_cname;
+
+	} else {
+		*mapped_attr = mapping->m_dst;
 	}
 
-	if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
-	{
-		dncookie 	fdc = *dc;
-		int		rc;
+	if ( value != NULL ) {
+		assert( mapped_value != NULL );
+
+		if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
+		{
+			dncookie 	fdc = *dc;
+			int		rc;
 
 #ifdef ENABLE_REWRITE
-		fdc.ctx = "searchFilterAttrDN";
+			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;
+			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;
-		}
+			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 ) ) {
+		} 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 {
 			vtmp = *value;
 		}
-		
-	} else {
-		vtmp = *value;
-	}
 
-	filter_escape_value( &vtmp, mapped_value );
+		filter_escape_value( &vtmp, mapped_value );
 
-	if ( freeval ) {
-		ch_free( vtmp.bv_val );
+		if ( freeval ) {
+			ch_free( vtmp.bv_val );
+		}
 	}
 	
+	if ( mapping != NULL ) {
+		assert( mapping->m_dst_ad != NULL );
+		*adp = mapping->m_dst_ad;
+	}
+
 	return 0;
 }
 
@@ -451,7 +464,7 @@ rwm_int_filter_map_rewrite(
 
 	switch ( f->f_choice ) {
 	case LDAP_FILTER_EQUALITY:
-		if ( map_attr_value( dc, f->f_av_desc, &atmp,
+		if ( map_attr_value( dc, &f->f_av_desc, &atmp,
 					&f->f_av_value, &vtmp, RWM_MAP ) )
 		{
 			return -1;
@@ -467,7 +480,7 @@ rwm_int_filter_map_rewrite(
 		break;
 
 	case LDAP_FILTER_GE:
-		if ( map_attr_value( dc, f->f_av_desc, &atmp,
+		if ( map_attr_value( dc, &f->f_av_desc, &atmp,
 					&f->f_av_value, &vtmp, RWM_MAP ) )
 		{
 			return -1;
@@ -483,7 +496,7 @@ rwm_int_filter_map_rewrite(
 		break;
 
 	case LDAP_FILTER_LE:
-		if ( map_attr_value( dc, f->f_av_desc, &atmp,
+		if ( map_attr_value( dc, &f->f_av_desc, &atmp,
 					&f->f_av_value, &vtmp, RWM_MAP ) )
 		{
 			return -1;
@@ -499,7 +512,7 @@ rwm_int_filter_map_rewrite(
 		break;
 
 	case LDAP_FILTER_APPROX:
-		if ( map_attr_value( dc, f->f_av_desc, &atmp,
+		if ( map_attr_value( dc, &f->f_av_desc, &atmp,
 					&f->f_av_value, &vtmp, RWM_MAP ) )
 		{
 			return -1;
@@ -515,7 +528,7 @@ rwm_int_filter_map_rewrite(
 		break;
 
 	case LDAP_FILTER_SUBSTRINGS:
-		if ( map_attr_value( dc, f->f_sub_desc, &atmp,
+		if ( map_attr_value( dc, &f->f_sub_desc, &atmp,
 					NULL, NULL, RWM_MAP ) )
 		{
 			return -1;
@@ -577,7 +590,7 @@ rwm_int_filter_map_rewrite(
 		break;
 
 	case LDAP_FILTER_PRESENT:
-		if ( map_attr_value( dc, f->f_desc, &atmp,
+		if ( map_attr_value( dc, &f->f_desc, &atmp,
 					NULL, NULL, RWM_MAP ) )
 		{
 			return -1;
@@ -621,7 +634,7 @@ rwm_int_filter_map_rewrite(
 
 	case LDAP_FILTER_EXT: {
 		if ( f->f_mr_desc ) {
-			if ( map_attr_value( dc, f->f_mr_desc, &atmp,
+			if ( map_attr_value( dc, &f->f_mr_desc, &atmp,
 						&f->f_mr_value, &vtmp, RWM_MAP ) )
 			{
 				return -1;
-- 
GitLab