From 6a425692bebfe6451437796b669eed50e553ca9b Mon Sep 17 00:00:00 2001
From: Pierangelo Masarati <ando@openldap.org>
Date: Tue, 9 Mar 2004 07:06:20 +0000
Subject: [PATCH] another round at rwm; now add and compare are nearly
 complete; error handling is in place

---
 servers/slapd/overlays/rwm.c     | 179 +++++++++++++++++++++----
 servers/slapd/overlays/rwm.h     |  32 ++++-
 servers/slapd/overlays/rwmconf.c |  62 ++++++---
 servers/slapd/overlays/rwmmap.c  | 216 ++++++++++++++++++++++---------
 4 files changed, 383 insertions(+), 106 deletions(-)

diff --git a/servers/slapd/overlays/rwm.c b/servers/slapd/overlays/rwm.c
index 21430a77e2..24fcb2ca16 100644
--- a/servers/slapd/overlays/rwm.c
+++ b/servers/slapd/overlays/rwm.c
@@ -76,83 +76,205 @@ rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie )
 }
 
 static int
-rwm_bind( Operation *op, SlapReply *rs )
+rwm_add( Operation *op, SlapReply *rs )
 {
-	int	rc;
+	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
+	struct ldaprwmap	*rwmap = 
+			(struct ldaprwmap *)on->on_bi.bi_private;
+
+	int			rc,
+				i,
+				isupdate;
+	Attribute		**ap = NULL;
 
 #ifdef ENABLE_REWRITE
-	rc = rwm_op_dn_massage( op, rs, "bindDn" );
+	rc = rwm_op_dn_massage( op, rs, "addDn" );
 #else
 	rc = 1;
 	rc = rwm_op_dn_massage( op, rs, &rc );
 #endif
 	if ( rc != LDAP_SUCCESS ) {
-		return rc;
+		op->o_bd->bd_info = (BackendInfo *)on->on_info;
+		send_ldap_error( op, rs, rc, "addDn massage error" );
+		return -1;
 	}
 
+	/* Count number of attributes in entry */ 
+	isupdate = be_isupdate( op->o_bd, &op->o_ndn );
+	for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
+		struct berval	mapped;
+		Attribute	*a;
+
+		if ( !isupdate && (*ap)->a_desc->ad_type->sat_no_user_mod ) {
+			goto cleanup_attr;
+		}
+
+		rwm_map( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname,
+				&mapped, RWM_MAP );
+		if ( mapped.bv_val == NULL || mapped.bv_val[0] == '\0' ) {
+			goto cleanup_attr;
+		}
+
+		if ( (*ap)->a_desc->ad_type->sat_syntax
+				== slap_schema.si_syn_distinguishedName )
+		{
+			/*
+			 * FIXME: rewrite could fail; in this case
+			 * the operation should give up, right?
+			 */
+#ifdef ENABLE_REWRITE
+			rc = rwm_dnattr_rewrite( op, rs, "addDn",
+					(*ap)->a_vals );
+#else
+			rc = 1;
+			rc = rwm_op_dn_massage( op, rs, &rc,
+					(*ap)->a_vals );
+#endif
+			if ( rc ) {
+				goto cleanup_attr;
+			}
+		}
+
+		ap = &(*ap)->a_next;
+		continue;
+
+cleanup_attr:;
+		/* FIXME: leaking attribute/values? */
+		a = *ap;
+
+		*ap = (*ap)->a_next;
+		ber_bvarray_free( a->a_vals );
+		ber_bvarray_free( a->a_nvals );
+		ch_free( a );
+	}
+
+
+	/* TODO: map attribute types, values of DN-valued attributes ... */
 	return SLAP_CB_CONTINUE;
 }
 
 static int
-rwm_add( Operation *op, SlapReply *rs )
+rwm_bind( Operation *op, SlapReply *rs )
 {
-	int	rc;
+	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
+	int			rc;
 
 #ifdef ENABLE_REWRITE
-	rc = rwm_op_dn_massage( op, rs, "addDn" );
+	rc = rwm_op_dn_massage( op, rs, "bindDn" );
 #else
 	rc = 1;
 	rc = rwm_op_dn_massage( op, rs, &rc );
 #endif
 	if ( rc != LDAP_SUCCESS ) {
-		return rc;
+		op->o_bd->bd_info = (BackendInfo *)on->on_info;
+		send_ldap_error( op, rs, rc, "bindDn massage error" );
+		return -1;
 	}
 
-	/* TODO: rewrite attribute types, values of DN-valued attributes ... */
 	return SLAP_CB_CONTINUE;
 }
 
 static int
-rwm_delete( Operation *op, SlapReply *rs )
+rwm_compare( Operation *op, SlapReply *rs )
 {
-	int	rc;
+	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
+	struct ldaprwmap	*rwmap = 
+			(struct ldaprwmap *)on->on_bi.bi_private;
+
+	int			rc;
+	struct berval		mapped_at = { 0, NULL },
+				mapped_vals[2] = { { 0, NULL }, { 0, NULL } };
 
 #ifdef ENABLE_REWRITE
-	rc = rwm_op_dn_massage( op, rs, "deleteDn" );
+	rc = rwm_op_dn_massage( op, rs, "compareDn" );
 #else
 	rc = 1;
 	rc = rwm_op_dn_massage( op, rs, &rc );
 #endif
 	if ( rc != LDAP_SUCCESS ) {
-		return rc;
+		op->o_bd->bd_info = (BackendInfo *)on->on_info;
+		send_ldap_error( op, rs, rc, "compareDn massage error" );
+		return -1;
+	}
+
+	/* if the attribute is an objectClass, try to remap its value */
+	if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass
+			|| op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass )
+	{
+		rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value,
+				&mapped_vals[0], RWM_MAP );
+		if ( mapped_vals[0].bv_val == NULL
+				|| mapped_vals[0].bv_val[0] == '\0')
+		{
+			op->o_bd->bd_info = (BackendInfo *)on->on_info;
+			send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" );
+			return -1;
+
+		} else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
+			free( op->orc_ava->aa_value.bv_val );
+			op->orc_ava->aa_value = mapped_vals[0];
+		}
+		mapped_at = op->orc_ava->aa_desc->ad_cname;
+
+	} else {
+		rwm_map( &rwmap->rwm_at,
+				&op->orc_ava->aa_desc->ad_cname,
+				&mapped_at,
+				RWM_MAP );
+		if ( mapped_at.bv_val == NULL 
+				|| mapped_at.bv_val[0] == '\0')
+		{
+			op->o_bd->bd_info = (BackendInfo *)on->on_info;
+			send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" );
+			return -1;
+		}
+		if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
+		{
+			mapped_vals[0] = op->orc_ava->aa_value;
+			rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", mapped_vals );
+			if ( rc != LDAP_SUCCESS ) {
+				op->o_bd->bd_info = (BackendInfo *)on->on_info;
+				send_ldap_error( op, rs, rc, "compareAttrDN massage error" );
+				return -1;
+			}
+
+			if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
+				free( op->orc_ava->aa_value.bv_val );
+				op->orc_ava->aa_value = mapped_vals[0];
+			}
+		}
 	}
 
+	/* TODO: rewrite attribute types, values of DN-valued attributes ... */
 	return SLAP_CB_CONTINUE;
 }
 
 static int
-rwm_modrdn( Operation *op, SlapReply *rs )
+rwm_delete( Operation *op, SlapReply *rs )
 {
-	int	rc;
+	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
+	int			rc;
 
 #ifdef ENABLE_REWRITE
-	rc = rwm_op_dn_massage( op, rs, "renameDn" );
+	rc = rwm_op_dn_massage( op, rs, "deleteDn" );
 #else
 	rc = 1;
 	rc = rwm_op_dn_massage( op, rs, &rc );
 #endif
 	if ( rc != LDAP_SUCCESS ) {
+		op->o_bd->bd_info = (BackendInfo *)on->on_info;
+		send_ldap_error( op, rs, rc, "deleteDn massage error" );
 		return rc;
 	}
 
-	/* TODO: rewrite attribute types, values of DN-valued attributes ... */
 	return SLAP_CB_CONTINUE;
 }
 
 static int
 rwm_modify( Operation *op, SlapReply *rs )
 {
-	int	rc;
+	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
+	int			rc;
 
 #ifdef ENABLE_REWRITE
 	rc = rwm_op_dn_massage( op, rs, "modifyDn" );
@@ -161,6 +283,8 @@ rwm_modify( Operation *op, SlapReply *rs )
 	rc = rwm_op_dn_massage( op, rs, &rc );
 #endif
 	if ( rc != LDAP_SUCCESS ) {
+		op->o_bd->bd_info = (BackendInfo *)on->on_info;
+		send_ldap_error( op, rs, rc, "modifyDn massage error" );
 		return rc;
 	}
 
@@ -169,17 +293,20 @@ rwm_modify( Operation *op, SlapReply *rs )
 }
 
 static int
-rwm_compare( Operation *op, SlapReply *rs )
+rwm_modrdn( Operation *op, SlapReply *rs )
 {
-	int	rc;
+	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
+	int			rc;
 
 #ifdef ENABLE_REWRITE
-	rc = rwm_op_dn_massage( op, rs, "compareDn" );
+	rc = rwm_op_dn_massage( op, rs, "renameDn" );
 #else
 	rc = 1;
 	rc = rwm_op_dn_massage( op, rs, &rc );
 #endif
 	if ( rc != LDAP_SUCCESS ) {
+		op->o_bd->bd_info = (BackendInfo *)on->on_info;
+		send_ldap_error( op, rs, rc, "renameDn massage error" );
 		return rc;
 	}
 
@@ -190,7 +317,8 @@ rwm_compare( Operation *op, SlapReply *rs )
 static int
 rwm_search( Operation *op, SlapReply *rs )
 {
-	int	rc;
+	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
+	int			rc;
 
 #ifdef ENABLE_REWRITE
 	rc = rwm_op_dn_massage( op, rs, "searchDn" );
@@ -199,6 +327,8 @@ rwm_search( Operation *op, SlapReply *rs )
 	rc = rwm_op_dn_massage( op, rs, &rc );
 #endif
 	if ( rc != LDAP_SUCCESS ) {
+		op->o_bd->bd_info = (BackendInfo *)on->on_info;
+		send_ldap_error( op, rs, rc, "searchDn massage error" );
 		return rc;
 	}
 
@@ -209,7 +339,8 @@ rwm_search( Operation *op, SlapReply *rs )
 static int
 rwm_extended( Operation *op, SlapReply *rs )
 {
-	int	rc;
+	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
+	int			rc;
 
 #ifdef ENABLE_REWRITE
 	rc = rwm_op_dn_massage( op, rs, "extendedDn" );
@@ -218,6 +349,8 @@ rwm_extended( Operation *op, SlapReply *rs )
 	rc = rwm_op_dn_massage( op, rs, &rc );
 #endif
 	if ( rc != LDAP_SUCCESS ) {
+		op->o_bd->bd_info = (BackendInfo *)on->on_info;
+		send_ldap_error( op, rs, rc, "extendedDn massage error" );
 		return rc;
 	}
 
diff --git a/servers/slapd/overlays/rwm.h b/servers/slapd/overlays/rwm.h
index c50c1b8fbe..c3d2cc2745 100644
--- a/servers/slapd/overlays/rwm.h
+++ b/servers/slapd/overlays/rwm.h
@@ -39,8 +39,25 @@ struct ldapmap {
 };
 
 struct ldapmapping {
-	struct berval src;
-	struct berval dst;
+	int			m_flags;
+#define	RWMMAP_F_NONE		0x00
+#define	RWMMAP_F_IS_OC		0x01
+#define RWMMAP_F_FREE_SRC	0x10
+#define RWMMAP_F_FREE_DST	0x20
+	struct berval		m_src;
+	union {
+		AttributeDescription	*m_s_ad;
+		ObjectClass		*m_s_oc;
+	} m_src_ref;
+#define m_src_ad	m_src_ref.m_s_ad
+#define m_src_oc	m_src_ref.m_s_oc
+	struct berval		m_dst;
+	union {
+		AttributeDescription	*m_d_ad;
+		ObjectClass		*m_d_oc;
+	} m_dst_ref;
+#define m_dst_ad	m_dst_ref.m_d_ad
+#define m_dst_oc	m_dst_ref.m_d_oc
 };
 
 struct ldaprwmap {
@@ -85,8 +102,8 @@ int rwm_mapping_dup (void *, void *);
 void rwm_map_init ( struct ldapmap *lm, struct ldapmapping ** );
 void rwm_map ( struct ldapmap *map, struct berval *s, struct berval *m,
 	int remap );
-#define BACKLDAP_MAP	0
-#define BACKLDAP_REMAP	1
+#define RWM_MAP	0
+#define RWM_REMAP	1
 char *
 rwm_map_filter(
 		struct ldapmap *at_map,
@@ -126,7 +143,12 @@ extern int rwm_suffix_massage_config( struct rewrite_info *info,
 		struct berval *pvnc, struct berval *nvnc,
 		struct berval *prnc, struct berval *nrnc);
 #endif /* ENABLE_REWRITE */
-extern int rwm_dnattr_rewrite( dncookie *dc, BerVarray a_vals );
+extern int rwm_dnattr_rewrite(
+	Operation		*op,
+	SlapReply		*rs,
+	void			*cookie,
+	BerVarray		a_vals
+	);
 extern int rwm_dnattr_result_rewrite( dncookie *dc, BerVarray a_vals );
 
 LDAP_END_DECL
diff --git a/servers/slapd/overlays/rwmconf.c b/servers/slapd/overlays/rwmconf.c
index 103524281f..d664b4a952 100644
--- a/servers/slapd/overlays/rwmconf.c
+++ b/servers/slapd/overlays/rwmconf.c
@@ -93,6 +93,7 @@ rwm_map_config(
 		fprintf( stderr,
 			"%s: line %d: objectclass attribute cannot be mapped\n",
 			fname, lineno );
+		return 1;
 	}
 
 	mapping = (struct ldapmapping *)ch_calloc( 2,
@@ -103,17 +104,21 @@ rwm_map_config(
 			fname, lineno );
 		return 1;
 	}
-	ber_str2bv( src, 0, 1, &mapping->src );
-	ber_str2bv( dst, 0, 1, &mapping->dst );
-	mapping[1].src = mapping->dst;
-	mapping[1].dst = mapping->src;
+	ber_str2bv( src, 0, 1, &mapping[0].m_src );
+	ber_str2bv( dst, 0, 1, &mapping[0].m_dst );
+	mapping[1].m_src = mapping[0].m_dst;
+	mapping[1].m_dst = mapping[0].m_src;
+
+	mapping[0].m_flags = RWMMAP_F_NONE;
+	mapping[1].m_flags = RWMMAP_F_NONE;
 
 	/*
 	 * schema check
 	 */
 	if ( is_oc ) {
 		if ( src[0] != '\0' ) {
-			if ( oc_bvfind( &mapping->src ) == NULL ) {
+			mapping[0].m_src_oc = oc_bvfind( &mapping[0].m_src );
+			if ( mapping[0].m_src_oc == NULL ) {
 				fprintf( stderr,
 	"%s: line %d: warning, source objectClass '%s' "
 	"should be defined in schema\n",
@@ -122,22 +127,38 @@ rwm_map_config(
 				/*
 				 * FIXME: this should become an err
 				 */
+				mapping[0].m_src_oc = ch_malloc( sizeof( ObjectClass ) );
+				memset( mapping[0].m_src_oc, 0, sizeof( ObjectClass ) );
+				mapping[0].m_src_oc->soc_cname = mapping[0].m_src;
+				mapping[0].m_flags |= RWMMAP_F_FREE_SRC;
 			}
+			mapping[1].m_dst_oc = mapping[0].m_src_oc;
 		}
 
-		if ( oc_bvfind( &mapping->dst ) == NULL ) {
+		mapping[0].m_dst_oc = oc_bvfind( &mapping[0].m_dst );
+		if ( mapping[0].m_dst_oc == NULL ) {
 			fprintf( stderr,
 	"%s: line %d: warning, destination objectClass '%s' "
 	"is not defined in schema\n",
 				fname, lineno, dst );
+
+			mapping[0].m_dst_oc = ch_malloc( sizeof( ObjectClass ) );
+			memset( mapping[0].m_dst_oc, 0, sizeof( ObjectClass ) );
+			mapping[0].m_dst_oc->soc_cname = mapping[0].m_dst;
+			mapping[0].m_flags |= RWMMAP_F_FREE_DST;
 		}
+		mapping[1].m_src_oc = mapping[0].m_dst_oc;
+
+		mapping[0].m_flags |= RWMMAP_F_IS_OC;
+		mapping[1].m_flags |= RWMMAP_F_IS_OC;
+
 	} else {
 		int			rc;
 		const char		*text = NULL;
-		AttributeDescription	*ad = NULL;
 
 		if ( src[0] != '\0' ) {
-			rc = slap_bv2ad( &mapping->src, &ad, &text );
+			rc = slap_bv2ad( &mapping[0].m_src,
+					&mapping[0].m_src_ad, &text );
 			if ( rc != LDAP_SUCCESS ) {
 				fprintf( stderr,
 	"%s: line %d: warning, source attributeType '%s' "
@@ -146,19 +167,32 @@ rwm_map_config(
 
 				/*
 				 * FIXME: this should become an err
+				 *
+				 * FIXME: or, we should create a fake ad
+				 * and add it here.
 				 */
-			}
 
-			ad = NULL;
+				mapping[0].m_src_ad = ch_malloc( sizeof( AttributeDescription ) );
+				memset( mapping[0].m_src_ad, 0, sizeof( AttributeDescription ) );
+				mapping[0].m_src_ad->ad_cname = mapping[0].m_src;
+				mapping[1].m_flags |= RWMMAP_F_FREE_SRC;
+			}
+			mapping[1].m_dst_ad = mapping[0].m_src_ad;
 		}
 
-		rc = slap_bv2ad( &mapping->dst, &ad, &text );
+		rc = slap_bv2ad( &mapping[0].m_dst, &mapping[0].m_dst_ad, &text );
 		if ( rc != LDAP_SUCCESS ) {
 			fprintf( stderr,
 	"%s: line %d: warning, destination attributeType '%s' "
 	"is not defined in schema\n",
 				fname, lineno, dst );
+
+			mapping[0].m_dst_ad = ch_malloc( sizeof( AttributeDescription ) );
+			memset( mapping[0].m_dst_ad, 0, sizeof( AttributeDescription ) );
+			mapping[0].m_dst_ad->ad_cname = mapping[0].m_dst;
+			mapping[1].m_flags |= RWMMAP_F_FREE_SRC;
 		}
+		mapping[1].m_src_ad = mapping[0].m_dst_ad;
 	}
 
 	if ( (src[0] != '\0' && avl_find( map->map, (caddr_t)mapping, rwm_mapping_cmp ) != NULL)
@@ -172,7 +206,7 @@ rwm_map_config(
 	}
 
 	if ( src[0] != '\0' ) {
-		avl_insert( &map->map, (caddr_t)mapping,
+		avl_insert( &map->map, (caddr_t)&mapping[0],
 					rwm_mapping_cmp, rwm_mapping_dup );
 	}
 	avl_insert( &map->remap, (caddr_t)&mapping[1],
@@ -182,9 +216,7 @@ rwm_map_config(
 
 error_return:;
 	if ( mapping ) {
-		ch_free( mapping->src.bv_val );
-		ch_free( mapping->dst.bv_val );
-		ch_free( mapping );
+		mapping_free( mapping );
 	}
 
 	return 1;
diff --git a/servers/slapd/overlays/rwmmap.c b/servers/slapd/overlays/rwmmap.c
index 11cbbef65d..5ecb959f1d 100644
--- a/servers/slapd/overlays/rwmmap.c
+++ b/servers/slapd/overlays/rwmmap.c
@@ -37,26 +37,33 @@
 #include "../../../libraries/libldap/ldap-int.h"
 
 int
-rwm_mapping_cmp ( const void *c1, const void *c2 )
+rwm_mapping_cmp( const void *c1, const void *c2 )
 {
 	struct ldapmapping *map1 = (struct ldapmapping *)c1;
 	struct ldapmapping *map2 = (struct ldapmapping *)c2;
-	int rc = map1->src.bv_len - map2->src.bv_len;
-	if (rc) return rc;
-	return ( strcasecmp(map1->src.bv_val, map2->src.bv_val) );
+	int rc = map1->m_src.bv_len - map2->m_src.bv_len;
+	if ( rc ) {
+		return rc;
+	}
+	return strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val );
 }
 
 int
-rwm_mapping_dup ( void *c1, void *c2 )
+rwm_mapping_dup( void *c1, 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;
+
+	if ( rc ) {
+		return 0;
+	}
 
-	return( ( strcasecmp(map1->src.bv_val, map2->src.bv_val) == 0 ) ? -1 : 0 );
+	return ( ( strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val ) == 0 ) ? -1 : 0 );
 }
 
 void
-rwm_map_init ( struct ldapmap *lm, struct ldapmapping **m )
+rwm_map_init( struct ldapmap *lm, struct ldapmapping **m )
 {
 	struct ldapmapping *mapping;
 
@@ -70,10 +77,11 @@ rwm_map_init ( struct ldapmap *lm, struct ldapmapping **m )
 		return;
 	}
 
-	ber_str2bv( "objectclass", sizeof("objectclass")-1, 1, &mapping->src);
-	ber_dupbv( &mapping->dst, &mapping->src );
-	mapping[1].src = mapping->src;
-	mapping[1].dst = mapping->dst;
+	ber_str2bv( "objectClass", sizeof("objectClass") - 1, 1,
+			&mapping->m_src);
+	ber_dupbv( &mapping->m_dst, &mapping->m_src );
+	mapping[1].m_src = mapping->m_src;
+	mapping[1].m_dst = mapping->m_dst;
 
 	avl_insert( &lm->map, (caddr_t)mapping, 
 			rwm_mapping_cmp, rwm_mapping_dup );
@@ -83,29 +91,32 @@ rwm_map_init ( struct ldapmap *lm, struct ldapmapping **m )
 }
 
 void
-rwm_map ( struct ldapmap *map, struct berval *s, struct berval *bv,
-	int remap )
+rwm_map( struct ldapmap *map, struct berval *s, struct berval *bv, int remap )
 {
 	Avlnode *tree;
 	struct ldapmapping *mapping, fmapping;
 
-	if (remap == BACKLDAP_REMAP)
+	if (remap == RWM_REMAP) {
 		tree = map->remap;
-	else
+	} else {
 		tree = map->map;
+	}
 
 	bv->bv_len = 0;
 	bv->bv_val = NULL;
-	fmapping.src = *s;
-	mapping = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, rwm_mapping_cmp );
-	if (mapping != NULL) {
-		if ( mapping->dst.bv_val )
-			*bv = mapping->dst;
+	fmapping.m_src = *s;
+	mapping = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping,
+			rwm_mapping_cmp );
+	if ( mapping != NULL ) {
+		if ( mapping->m_dst.bv_val ) {
+			*bv = mapping->m_dst;
+		}
 		return;
 	}
 
-	if (!map->drop_missing)
+	if ( !map->drop_missing ) {
 		*bv = *s;
+	}
 
 	return;
 }
@@ -122,28 +133,30 @@ rwm_map_attrs(
 	char **na;
 	struct berval mapped;
 
-	if (an == NULL) {
+	if ( an == NULL ) {
 		*mapped_attrs = NULL;
 		return LDAP_SUCCESS;
 	}
 
-	for (i = 0; an[i].an_name.bv_val; i++) {
+	for ( i = 0; an[i].an_name.bv_val; i++ ) {
 		/*  */
 	}
 
-	na = (char **)ch_calloc( i + 1, sizeof(char *) );
+	na = (char **)ch_calloc( i + 1, sizeof( char * ) );
 	if (na == NULL) {
 		*mapped_attrs = NULL;
 		return LDAP_NO_MEMORY;
 	}
 
-	for (i = j = 0; an[i].an_name.bv_val; i++) {
-		rwm_map(at_map, &an[i].an_name, &mapped, remap);
-		if (mapped.bv_val != NULL && mapped.bv_val != '\0')
+	for ( i = j = 0; an[i].an_name.bv_val; i++ ) {
+		rwm_map( at_map, &an[i].an_name, &mapped, remap );
+		if ( mapped.bv_val != NULL && mapped.bv_val != '\0' ) {
 			na[j++] = mapped.bv_val;
+		}
 	}
-	if (j == 0 && i != 0)
+	if ( j == 0 && i != 0 ) {
 		na[j++] = LDAP_NO_ATTRS;
+	}
 	na[j] = NULL;
 
 	*mapped_attrs = na;
@@ -167,8 +180,11 @@ map_attr_value(
 		/*
 		 * 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 ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
+		rwm_map( &dc->rwmap->rwm_oc, &ad->ad_cname, mapped_attr,
+				remap );
+		if ( mapped_attr->bv_val == NULL
+				|| mapped_attr->bv_val[0] == '\0' )
+		{
 			*mapped_attr = ad->ad_cname;
 		}
 	}
@@ -199,7 +215,9 @@ map_attr_value(
 			return -1;
 		}
 
-	} else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
+	} else if ( ad == slap_schema.si_ad_objectClass
+			|| ad == slap_schema.si_ad_structuralObjectClass )
+	{
 		rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
 		if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
 			vtmp = *value;
@@ -227,12 +245,20 @@ rwm_filter_map_rewrite(
 {
 	int		i;
 	Filter		*p;
-	struct berval	atmp;
-	struct berval	vtmp;
+	struct berval	atmp,
+			vtmp,
+			tmp;
+	static struct berval
+			ber_bvfalse = BER_BVC( "(?=false)" ),
+			ber_bvtrue = BER_BVC( "(?=true)" ),
+			ber_bvundefined = BER_BVC( "(?=undefined)" ),
+			ber_bverror = BER_BVC( "(?=error)" ),
+			ber_bvunknown = BER_BVC( "(?=unknown)" ),
+			ber_bvnone = BER_BVC( "(?=none)" );
 	ber_len_t	len;
 
 	if ( f == NULL ) {
-		ber_str2bv( "No filter!", sizeof("No filter!")-1, 1, fstr );
+		ber_dupbv( fstr, &ber_bvnone );
 		return -1;
 	}
 
@@ -245,7 +271,7 @@ rwm_filter_map_rewrite(
 		}
 
 		fstr->bv_len = atmp.bv_len + vtmp.bv_len
-			+ ( sizeof("(=)") - 1 );
+			+ ( sizeof( "(=)" ) - 1 );
 		fstr->bv_val = malloc( fstr->bv_len + 1 );
 
 		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
@@ -262,7 +288,7 @@ rwm_filter_map_rewrite(
 		}
 
 		fstr->bv_len = atmp.bv_len + vtmp.bv_len
-			+ ( sizeof("(>=)") - 1 );
+			+ ( sizeof( "(>=)" ) - 1 );
 		fstr->bv_val = malloc( fstr->bv_len + 1 );
 
 		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
@@ -279,7 +305,7 @@ rwm_filter_map_rewrite(
 		}
 
 		fstr->bv_len = atmp.bv_len + vtmp.bv_len
-			+ ( sizeof("(<=)") - 1 );
+			+ ( sizeof( "(<=)" ) - 1 );
 		fstr->bv_val = malloc( fstr->bv_len + 1 );
 
 		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
@@ -296,7 +322,7 @@ rwm_filter_map_rewrite(
 		}
 
 		fstr->bv_len = atmp.bv_len + vtmp.bv_len
-			+ ( sizeof("(~=)") - 1 );
+			+ ( sizeof( "(~=)" ) - 1 );
 		fstr->bv_val = malloc( fstr->bv_len + 1 );
 
 		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
@@ -314,7 +340,7 @@ rwm_filter_map_rewrite(
 
 		/* cannot be a DN ... */
 
-		fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
+		fstr->bv_len = atmp.bv_len + ( sizeof( "(=*)" ) - 1 );
 		fstr->bv_val = malloc( fstr->bv_len + 128 );
 
 		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
@@ -374,7 +400,7 @@ rwm_filter_map_rewrite(
 			return -1;
 		}
 
-		fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
+		fstr->bv_len = atmp.bv_len + ( sizeof( "(=*)" ) - 1 );
 		fstr->bv_val = malloc( fstr->bv_len + 1 );
 
 		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
@@ -384,7 +410,7 @@ rwm_filter_map_rewrite(
 	case LDAP_FILTER_AND:
 	case LDAP_FILTER_OR:
 	case LDAP_FILTER_NOT:
-		fstr->bv_len = sizeof("(%)") - 1;
+		fstr->bv_len = sizeof( "(%)" ) - 1;
 		fstr->bv_val = malloc( fstr->bv_len + 128 );
 
 		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
@@ -427,9 +453,9 @@ rwm_filter_map_rewrite(
 			
 
 		fstr->bv_len = atmp.bv_len +
-			( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
-			( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
-			vtmp.bv_len + ( sizeof("(:=)") - 1 );
+			( f->f_mr_dnattrs ? sizeof( ":dn" ) - 1 : 0 ) +
+			( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len + 1 : 0 ) +
+			vtmp.bv_len + ( sizeof( "(:=)" ) - 1 );
 		fstr->bv_val = malloc( fstr->bv_len + 1 );
 
 		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
@@ -442,20 +468,29 @@ rwm_filter_map_rewrite(
 		} break;
 
 	case SLAPD_FILTER_COMPUTED:
-		ber_str2bv(
-			f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
-			f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
-			f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
-			"(?=error)",
-			f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
-			f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
-			f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
-			sizeof("(?=error)")-1,
-			1, fstr );
-		break;
+		switch ( f->f_result ) {
+		case LDAP_COMPARE_FALSE:
+			tmp = ber_bvfalse;
+			break;
 
+		case LDAP_COMPARE_TRUE:
+			tmp = ber_bvtrue;
+			break;
+			
+		case SLAPD_COMPARE_UNDEFINED:
+			tmp = ber_bvundefined;
+			break;
+			
+		default:
+			tmp = ber_bverror;
+			break;
+		}
+
+		ber_dupbv( fstr, &tmp );
+		break;
+		
 	default:
-		ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );
+		ber_dupbv( fstr, &ber_bvunknown );
 		break;
 	}
 
@@ -471,18 +506,39 @@ rwm_filter_map_rewrite(
  */
 int
 rwm_dnattr_rewrite(
-	dncookie		*dc,
+	Operation		*op,
+	SlapReply		*rs,
+	void			*cookie,
 	BerVarray		a_vals
-)
+	)
 {
-	struct berval	bv;
-	int		i, last;
+	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
+	struct ldaprwmap	*rwmap = 
+			(struct ldaprwmap *)on->on_bi.bi_private;
+
+	struct berval		bv;
+	int			i, last;
+
+	dncookie		dc;
+
+	/*
+	 * Rewrite the bind dn if needed
+	 */
+	dc.rwmap = rwmap;
+#ifdef ENABLE_REWRITE
+	dc.conn = op->o_conn;
+	dc.rs = rs;
+	dc.ctx = (char *)cookie;
+#else
+	dc.tofrom = ((int *)cookie)[0];
+	dc.normalized = 0;
+#endif
 
 	for ( last = 0; a_vals[last].bv_val != NULL; last++ );
 	last--;
 
 	for ( i = 0; a_vals[i].bv_val != NULL; i++ ) {
-		switch ( rwm_dn_massage( dc, &a_vals[i], &bv ) ) {
+		switch ( rwm_dn_massage( &dc, &a_vals[i], &bv ) ) {
 		case LDAP_UNWILLING_TO_PERFORM:
 			/*
 			 * FIXME: need to check if it may be considered 
@@ -557,9 +613,43 @@ void
 rwm_mapping_free( void *v_mapping )
 {
 	struct ldapmapping *mapping = v_mapping;
-	ch_free( mapping->src.bv_val );
-	ch_free( mapping->dst.bv_val );
+
+	if ( mapping[0].m_src.bv_val ) {
+		ch_free( mapping[0].m_src.bv_val );
+	}
+
+	if ( mapping[0].m_flags & RWMMAP_F_FREE_SRC ) {
+		if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
+			if ( mapping[0].m_src_oc ) {
+				ch_free( mapping[0].m_src_oc );
+			}
+
+		} else {
+			if ( mapping[0].m_src_ad ) {
+				ch_free( mapping[0].m_src_ad );
+			}
+		}
+	}
+
+	if ( mapping[0].m_dst.bv_val ) {
+		ch_free( mapping[0].m_dst.bv_val );
+	}
+
+	if ( mapping[0].m_flags & RWMMAP_F_FREE_DST ) {
+		if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
+			if ( mapping[0].m_dst_oc ) {
+				ch_free( mapping[0].m_dst_oc );
+			}
+
+		} else {
+			if ( mapping[0].m_dst_ad ) {
+				ch_free( mapping[0].m_dst_ad );
+			}
+		}
+	}
+
 	ch_free( mapping );
+
 }
 
 #endif /* SLAPD_OVER_RWM */
-- 
GitLab