From 4a73c1adbe73beccb80680d66abaed4fab19a521 Mon Sep 17 00:00:00 2001
From: Quanah Gibson-Mount <quanah@openldap.org>
Date: Fri, 13 Feb 2009 04:16:58 +0000
Subject: [PATCH] ITS#5940

---
 CHANGES                      |   1 +
 servers/slapd/backover.c     |   2 +
 servers/slapd/bconfig.c      |   4 +-
 servers/slapd/config.c       |   7 +-
 servers/slapd/config.h       |   2 +
 servers/slapd/overlays/rwm.c | 239 ++++++++++++++++++++++++++++++-----
 6 files changed, 216 insertions(+), 39 deletions(-)

diff --git a/CHANGES b/CHANGES
index 1f606c806a..5837f09d43 100644
--- a/CHANGES
+++ b/CHANGES
@@ -61,6 +61,7 @@ OpenLDAP 2.4.14 Engineering
 	Fixed slapo-ppolicy to not be global (ITS#5858)
 	Fixed slapo-rwm double free (ITS#5923)
 	Fixed slapo-rwm with back-config (ITS#5906)
+	Fixed slapo-rwm olcRwmRewrite modification (ITS#5940)
 	Added slapo-rwm newRDN rewriting (ITS#5834)
 	Added slapadd progress meter (ITS#5922)
 	Updated contrib/addpartial module (ITS#5764)
diff --git a/servers/slapd/backover.c b/servers/slapd/backover.c
index 8194e9869f..d69cf12c06 100644
--- a/servers/slapd/backover.c
+++ b/servers/slapd/backover.c
@@ -103,6 +103,8 @@ over_db_config(
 	ca.be = be;
 	snprintf( ca.log, sizeof( ca.log ), "%s: line %d",
 			ca.fname, ca.lineno );
+	ca.op = SLAP_CONFIG_ADD;
+	ca.valx = -1;
 
 	for (; on; on=on->on_next) {
 		rc = SLAP_CONF_UNKNOWN;
diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
index a2c90144c7..cd7f43ab89 100644
--- a/servers/slapd/bconfig.c
+++ b/servers/slapd/bconfig.c
@@ -4488,6 +4488,7 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
 		if ( !ct ) continue;	/* user data? */
 		for (i=0; a->a_vals[i].bv_val; i++) {
 			char *iptr = NULL;
+			ca->valx = -1;
 			ca->line = a->a_vals[i].bv_val;
 			if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED ) {
 				ptr = strchr( ca->line, '}' );
@@ -4499,8 +4500,6 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
 			if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED_SIB ) {
 				if ( iptr ) {
 					ca->valx = strtol( iptr+1, NULL, 0 );
-				} else {
-					ca->valx = -1;
 				}
 			} else {
 				ca->valx = i;
@@ -4789,6 +4788,7 @@ config_modify_add( ConfigTable *ct, ConfigArgs *ca, AttributeDescription *ad,
 {
 	int rc;
 
+	ca->valx = -1;
 	if (ad->ad_type->sat_flags & SLAP_AT_ORDERED &&
 		ca->line[0] == '{' )
 	{
diff --git a/servers/slapd/config.c b/servers/slapd/config.c
index 16e335e404..f03a11be8e 100644
--- a/servers/slapd/config.c
+++ b/servers/slapd/config.c
@@ -86,7 +86,6 @@ int slapi_plugins_used = 0;
 
 static int fp_getline(FILE *fp, ConfigArgs *c);
 static void fp_getline_init(ConfigArgs *c);
-static int fp_parse_line(ConfigArgs *c);
 
 static char	*strtok_quote(char *line, char *sep, char **quote_ptr);
 static char *strtok_quote_ldif(char **line);
@@ -716,7 +715,7 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf, ConfigTable *cft)
 
 		c->argc = 0;
 		ch_free( c->tline );
-		if ( fp_parse_line( c ) ) {
+		if ( config_fp_parse_line( c ) ) {
 			rc = 1;
 			goto done;
 		}
@@ -1955,8 +1954,8 @@ fp_getline( FILE *fp, ConfigArgs *c )
 	return(line[0] ? 1 : 0);
 }
 
-static int
-fp_parse_line(ConfigArgs *c)
+int
+config_fp_parse_line(ConfigArgs *c)
 {
 	char *token;
 	static char *const hide[] = {
diff --git a/servers/slapd/config.h b/servers/slapd/config.h
index ae2faf1033..4dc902dac9 100644
--- a/servers/slapd/config.h
+++ b/servers/slapd/config.h
@@ -171,6 +171,8 @@ typedef struct config_args_s {
 #define value_dn values.v_dn.vdn_dn
 #define value_ndn values.v_dn.vdn_ndn
 
+int config_fp_parse_line(ConfigArgs *c);
+
 int config_register_schema(ConfigTable *ct, ConfigOCs *co);
 int config_del_vals(ConfigTable *cf, ConfigArgs *c);
 int config_get_vals(ConfigTable *ct, ConfigArgs *c);
diff --git a/servers/slapd/overlays/rwm.c b/servers/slapd/overlays/rwm.c
index 66844b388e..b07b7e18a4 100644
--- a/servers/slapd/overlays/rwm.c
+++ b/servers/slapd/overlays/rwm.c
@@ -1947,6 +1947,60 @@ slap_rewrite_unparse( BerVarray in, BerVarray *out )
 	*out = bva;
 }
 
+static int
+rwm_bva_rewrite_add(
+	struct ldaprwmap	*rwmap,
+	int			idx,
+	const char		*argv[] )
+{
+	char		*line;
+	struct berval	bv;
+
+	line = ldap_charray2str( argv, "\" \"" );
+	if ( line != NULL ) {
+		int	len = strlen( argv[ 0 ] );
+
+		ber_str2bv( line, 0, 0, &bv );
+		AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
+			bv.bv_len - ( len + 1 ) );
+		bv.bv_val[ bv.bv_len - 1 ] = '"';
+
+		if ( idx == -1 ) {
+			ber_bvarray_add( &rwmap->rwm_bva_rewrite, &bv );
+
+		} else {
+			rwmap->rwm_bva_rewrite[ idx ] = bv;
+		}
+	}
+
+	return 0;
+}
+
+static int
+rwm_info_init( struct rewrite_info ** rwm_rw )
+{
+	char			*rargv[ 3 ];
+
+ 	*rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
+	if ( *rwm_rw == NULL ) {
+ 		return -1;
+ 	}
+
+	/* this rewriteContext by default must be null;
+	 * rules can be added if required */
+	rargv[ 0 ] = "rewriteContext";
+	rargv[ 1 ] = "searchFilter";
+	rargv[ 2 ] = NULL;
+	rewrite_parse( *rwm_rw, "<suffix massage>", 1, 2, rargv );
+
+	rargv[ 0 ] = "rewriteContext";
+	rargv[ 1 ] = "default";
+	rargv[ 2 ] = NULL;
+	rewrite_parse( *rwm_rw, "<suffix massage>", 2, 2, rargv );
+
+	return 0;
+}
+
 static int
 rwm_cf_gen( ConfigArgs *c )
 {
@@ -2014,8 +2068,48 @@ rwm_cf_gen( ConfigArgs *c )
 		switch ( c->type ) {
 		case RWM_CF_REWRITE:
 			if ( c->valx >= 0 ) {
-				/* single modification is not allowed */
-				rc = 1;
+				ConfigArgs ca = { 0 };
+				int i;
+
+				for ( i = 0; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
+					/* count'em */ ;
+
+				if ( i >= c->valx ) {
+					rc = 1;
+					break;
+				}
+
+				ber_memfree( rwmap->rwm_bva_rewrite[ c->valx ].bv_val );
+				for ( i = c->valx; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i + 1 ] ); i++ )
+				{
+					rwmap->rwm_bva_rewrite[ i ] = rwmap->rwm_bva_rewrite[ i + 1 ];
+				}
+				BER_BVZERO( &rwmap->rwm_bva_rewrite[ i ] );
+
+				rewrite_info_delete( &rwmap->rwm_rw );
+				assert( rwmap->rwm_rw == NULL );
+
+				rc = rwm_info_init( &rwmap->rwm_rw );
+
+				for ( i = 0; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
+				{
+					ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
+					ca.argc = 0;
+					config_fp_parse_line( &ca );
+					
+					if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
+						rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
+							ca.argc, ca.argv );
+
+					} else {
+						rc = rwm_rw_config( &db, c->fname, c->lineno,
+							ca.argc, ca.argv );
+					}
+
+					ch_free( ca.tline );
+
+					assert( rc == 0 );
+				}
 
 			} else if ( rwmap->rwm_rw != NULL ) {
 				rewrite_info_delete( &rwmap->rwm_rw );
@@ -2023,6 +2117,8 @@ rwm_cf_gen( ConfigArgs *c )
 
 				ber_bvarray_free( rwmap->rwm_bva_rewrite );
 				rwmap->rwm_bva_rewrite = NULL;
+
+				rc = rwm_info_init( &rwmap->rwm_rw );
 			}
 			break;
 
@@ -2067,6 +2163,108 @@ rwm_cf_gen( ConfigArgs *c )
 
 	switch ( c->type ) {
 	case RWM_CF_REWRITE:
+		if ( c->valx >= 0 ) {
+			struct rewrite_info *rwm_rw = rwmap->rwm_rw;
+			ConfigArgs ca = { 0 };
+			int i, last;
+
+			for ( last = 0; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ last ] ); last++ )
+				/* count'em */ ;
+
+			if ( c->valx > last ) {
+				c->valx = last;
+			}
+
+			rwmap->rwm_rw = NULL;
+			rc = rwm_info_init( &rwmap->rwm_rw );
+
+			for ( i = 0; i < c->valx; i++ ) {
+				ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
+				ca.argc = 0;
+				config_fp_parse_line( &ca );
+
+				argv0 = ca.argv[ 0 ];
+				ca.argv[ 0 ] += STRLENOF( "rwm-" );
+				
+				if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
+					rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
+						ca.argc, ca.argv );
+
+				} else {
+					rc = rwm_rw_config( &db, c->fname, c->lineno,
+						ca.argc, ca.argv );
+				}
+
+				ca.argv[ 0 ] = argv0;
+
+				ch_free( ca.tline );
+
+				assert( rc == 0 );
+			}
+
+			argv0 = c->argv[ idx0 ];
+			if ( strncasecmp( argv0, "rwm-", STRLENOF( "rwm-" ) ) != 0 ) {
+				return 1;
+			}
+			c->argv[ idx0 ] += STRLENOF( "rwm-" );
+			if ( strcasecmp( c->argv[ idx0 ], "suffixmassage" ) == 0 ) {
+				rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
+					c->argc - idx0, &c->argv[ idx0 ] );
+
+			} else {
+				rc = rwm_rw_config( &db, c->fname, c->lineno,
+					c->argc - idx0, &c->argv[ idx0 ] );
+			}
+			c->argv[ idx0 ] = argv0;
+			if ( rc != 0 ) {
+				rewrite_info_delete( &rwmap->rwm_rw );
+				assert( rwmap->rwm_rw == NULL );
+
+				rwmap->rwm_rw = rwm_rw;
+				return 1;
+			}
+
+			for ( i = c->valx; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
+			{
+				ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
+				ca.argc = 0;
+				config_fp_parse_line( &ca );
+				
+				argv0 = ca.argv[ 0 ];
+				ca.argv[ 0 ] += STRLENOF( "rwm-" );
+				
+				if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
+					rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
+						ca.argc, ca.argv );
+
+				} else {
+					rc = rwm_rw_config( &db, c->fname, c->lineno,
+						ca.argc, ca.argv );
+				}
+
+				ca.argv[ 0 ] = argv0;
+
+				ch_free( ca.tline );
+
+				assert( rc == 0 );
+			}
+
+			rwmap->rwm_bva_rewrite = ch_realloc( rwmap->rwm_bva_rewrite,
+				( last + 2 )*sizeof( struct berval ) );
+
+			for ( i = last - 1; i >= c->valx; i-- )
+			{
+				rwmap->rwm_bva_rewrite[ i + 1 ] = rwmap->rwm_bva_rewrite[ i ];
+			}
+
+			rwm_bva_rewrite_add( rwmap, c->valx, &c->argv[ idx0 ] );
+
+			rewrite_info_delete( &rwm_rw );
+			assert( rwm_rw == NULL );
+
+			break;
+		}
+
 		argv0 = c->argv[ idx0 ];
 		if ( strncasecmp( argv0, "rwm-", STRLENOF( "rwm-" ) ) != 0 ) {
 			return 1;
@@ -2085,19 +2283,7 @@ rwm_cf_gen( ConfigArgs *c )
 			return 1;
 
 		} else {
-			char		*line;
-			struct berval	bv;
-
-			line = ldap_charray2str( &c->argv[ idx0 ], "\" \"" );
-			if ( line != NULL ) {
-				int	len = strlen( c->argv[ idx0 ] );
-
-				ber_str2bv( line, 0, 0, &bv );
-				AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
-					bv.bv_len - ( len + 1 ) );
-				bv.bv_val[ bv.bv_len - 1 ] = '"';
-				ber_bvarray_add( &rwmap->rwm_bva_rewrite, &bv );
-			}
+			rwm_bva_rewrite_add( rwmap, -1, &c->argv[ idx0 ] );
 		}
 		break;
 
@@ -2113,6 +2299,10 @@ rwm_cf_gen( ConfigArgs *c )
 		break;
 
 	case RWM_CF_MAP:
+		if ( c->valx >= 0 ) {
+			return 1;
+		}
+
 		argv0 = c->argv[ 0 ];
 		c->argv[ 0 ] += STRLENOF( "rwm-" );
 		rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
@@ -2155,28 +2345,11 @@ rwm_db_init(
 {
 	slap_overinst		*on = (slap_overinst *) be->bd_info;
 	struct ldaprwmap	*rwmap;
-	char			*rargv[ 3 ];
 	int			rc = 0;
 
 	rwmap = (struct ldaprwmap *)ch_calloc( 1, sizeof( struct ldaprwmap ) );
 
- 	rwmap->rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
-	if ( rwmap->rwm_rw == NULL ) {
- 		rc = -1;
-		goto error_return;
- 	}
-
-	/* this rewriteContext by default must be null;
-	 * rules can be added if required */
-	rargv[ 0 ] = "rewriteContext";
-	rargv[ 1 ] = "searchFilter";
-	rargv[ 2 ] = NULL;
-	rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 1, 2, rargv );
-
-	rargv[ 0 ] = "rewriteContext";
-	rargv[ 1 ] = "default";
-	rargv[ 2 ] = NULL;
-	rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 2, 2, rargv );
+	rc = rwm_info_init( &rwmap->rwm_rw );
 
 error_return:;
 	on->on_bi.bi_private = (void *)rwmap;
-- 
GitLab