diff --git a/include/rewrite.h b/include/rewrite.h
index fdf7c1f4dfb86aa3d18a070226178413ed4beb69..6e6bc86e062d866f055b8ea6ea12c9230e72ceff 100644
--- a/include/rewrite.h
+++ b/include/rewrite.h
@@ -74,6 +74,30 @@
 #define REWRITE_REGEXEC_STOP            0x0002
 #define REWRITE_REGEXEC_UNWILLING       0x0004
 
+/*
+ * Rewrite variable flags
+ *	REWRITE_VAR_INSERT		insert mode (default) when adding
+ *					a variable; if not set during value
+ *					update, the variable is not inserted
+ *					if not present
+ *	REWRITE_VAR_UPDATE		update mode (default) when updating
+ *					a variable; if not set during insert,
+ *					the value is not updated if the
+ *					variable already exists
+ *	REWRITE_VAR_COPY_NAME		copy the variable name; if not set,
+ *					the name is not copied; be sure the
+ *					referenced string is available for
+ *					the entire life scope of the variable.
+ *	REWRITE_VAR_COPY_VALUE		copy the variable value; if not set,
+ *					the value is not copied; be sure the
+ *					referenced string is available for
+ *					the entire life scope of the variable.
+ */
+#define REWRITE_VAR_INSERT		0x0001
+#define REWRITE_VAR_UPDATE		0x0002
+#define REWRITE_VAR_COPY_NAME		0x0004
+#define REWRITE_VAR_COPY_VALUE		0x0008
+
 /*
  * Rewrite info
  */
@@ -177,13 +201,18 @@ rewrite_session_init(
  * Defines and inits a variable with session scope
  */
 LDAP_REWRITE_F (int)
-rewrite_session_var_set(
+rewrite_session_var_set_f(
 		struct rewrite_info *info,
 		const void *cookie,
 		const char *name,
-		const char *value
+		const char *value,
+		int flags
 );
 
+#define rewrite_session_var_set(info, cookie, name, value) \
+	rewrite_session_var_set_f((info), (cookie), (name), (value), \
+			REWRITE_VAR_INSERT|REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE)
+
 /*
  * Deletes a session
  */
diff --git a/libraries/librewrite/rewrite-int.h b/libraries/librewrite/rewrite-int.h
index 3f14b0c16030f63b3f8c3fbe582089708f998212..c08b5f047a6cdf18c31b4e089e3d495c20ad6b84 100644
--- a/libraries/librewrite/rewrite-int.h
+++ b/libraries/librewrite/rewrite-int.h
@@ -248,6 +248,7 @@ struct rewrite_session {
  */
 struct rewrite_var {
 	char                           *lv_name;
+	int				lv_flags;
 	struct berval                   lv_value;
 };
 
@@ -459,11 +460,12 @@ rewrite_session_find(
  * Defines and inits a variable with session scope
  */
 LDAP_REWRITE_F (int)
-rewrite_session_var_set(
+rewrite_session_var_set_f(
                 struct rewrite_info *info,
                 const void *cookie,
                 const char *name,
-                const char *value
+                const char *value,
+		int flags
 );
 
 /*
@@ -508,27 +510,46 @@ rewrite_var_find(
                 const char *name
 );
 
+/*
+ * Replaces the value of a variable
+ */
+LDAP_REWRITE_F (int)
+rewrite_var_replace(
+		struct rewrite_var *var,
+		const char *value,
+		int flags
+);
+
 /*
  * Inserts a newly created var
  */
 LDAP_REWRITE_F (struct rewrite_var *)
-rewrite_var_insert(
+rewrite_var_insert_f(
                 Avlnode **tree,
                 const char *name,
-                const char *value
+                const char *value,
+		int flags
 );
 
+#define rewrite_var_insert(tree, name, value) \
+	rewrite_var_insert_f((tree), (name), (value), \
+			REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE)
+
 /*
  * Sets/inserts a var
  */
 LDAP_REWRITE_F (struct rewrite_var *)
-rewrite_var_set(
+rewrite_var_set_f(
                 Avlnode **tree,
                 const char *name,
                 const char *value,
-                int insert
+                int flags
 );
 
+#define rewrite_var_set(tree, name, value, insert) \
+	rewrite_var_set_f((tree), (name), (value), \
+			REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE|((insert)? REWRITE_VAR_INSERT : 0))
+
 /*
  * Deletes a var tree
  */
diff --git a/libraries/librewrite/session.c b/libraries/librewrite/session.c
index 3a09fb40d2be1a82371621a9556a665a2754cea0..34feb4959ed0213c04bbb3438c8e542d6cc1d210 100644
--- a/libraries/librewrite/session.c
+++ b/libraries/librewrite/session.c
@@ -185,11 +185,12 @@ rewrite_session_return(
  * Defines and inits a var with session scope
  */
 int
-rewrite_session_var_set(
+rewrite_session_var_set_f(
 		struct rewrite_info *info,
 		const void *cookie,
 		const char *name,
-		const char *value
+		const char *value,
+		int flags
 )
 {
 	struct rewrite_session *session;
@@ -212,11 +213,11 @@ rewrite_session_var_set(
 	var = rewrite_var_find( session->ls_vars, name );
 	if ( var != NULL ) {
 		assert( var->lv_value.bv_val != NULL );
-		free( var->lv_value.bv_val );
-		var->lv_value.bv_val = strdup( value );
-		var->lv_value.bv_len = strlen( value );
+
+		(void)rewrite_var_replace( var, value, flags );
+
 	} else {
-		var = rewrite_var_insert( &session->ls_vars, name, value );
+		var = rewrite_var_insert_f( &session->ls_vars, name, value, flags );
 		if ( var == NULL ) {
 #ifdef USE_REWRITE_LDAP_PVT_THREADS
 			ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex );
diff --git a/libraries/librewrite/var.c b/libraries/librewrite/var.c
index 9a4ca786f90f1a65b03b76a7bb977493595f56a5..80bba9f1824c699b78e8157b25593d7f8f6d3a3f 100644
--- a/libraries/librewrite/var.c
+++ b/libraries/librewrite/var.c
@@ -65,6 +65,39 @@ rewrite_var_dup(
 	return ( strcasecmp( v1->lv_name, v2->lv_name ) == 0 ? -1 : 0 );
 }
 
+/*
+ * Frees a var
+ */
+static void 
+rewrite_var_free(
+		void *v_var
+)
+{
+	struct rewrite_var *var = v_var;
+	assert( var != NULL );
+
+	assert( var->lv_name != NULL );
+	assert( var->lv_value.bv_val != NULL );
+
+	if ( var->lv_flags & REWRITE_VAR_COPY_NAME )
+		free( var->lv_name );
+	if ( var->lv_flags & REWRITE_VAR_COPY_VALUE )
+		free( var->lv_value.bv_val );
+	free( var );
+}
+
+/*
+ * Deletes a var tree
+ */
+int
+rewrite_var_delete(
+		Avlnode *tree
+)
+{
+	avl_free( tree, rewrite_var_free );
+	return REWRITE_SUCCESS;
+}
+
 /*
  * Finds a var
  */
@@ -83,51 +116,112 @@ rewrite_var_find(
 			( caddr_t )&var, rewrite_var_cmp );
 }
 
+int
+rewrite_var_replace(
+		struct rewrite_var *var,
+		const char *value,
+		int flags
+)
+{
+	ber_len_t	len = strlen( value );
+
+	if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) {
+		if ( flags & REWRITE_VAR_COPY_VALUE ) {
+			if ( len <= var->lv_value.bv_len ) {
+				AC_MEMCPY(var->lv_value.bv_val, value, len + 1);
+
+			} else {
+				free( var->lv_value.bv_val );
+				var->lv_value.bv_val = strdup( value );
+			}
+
+		} else {
+			free( var->lv_value.bv_val );
+			var->lv_value.bv_val = (char *)value;
+			var->lv_flags &= ~REWRITE_VAR_COPY_VALUE;
+		}
+
+	} else {
+		if ( flags & REWRITE_VAR_COPY_VALUE ) {
+			var->lv_value.bv_val = strdup( value );
+			var->lv_flags |= REWRITE_VAR_COPY_VALUE;
+
+		} else {
+			var->lv_value.bv_val = (char *)value;
+		}
+	}
+
+	var->lv_value.bv_len = len;
+
+	return 0;
+}
+
 /*
  * Inserts a newly created var
  */
 struct rewrite_var *
-rewrite_var_insert(
+rewrite_var_insert_f(
 		Avlnode **tree,
 		const char *name,
-		const char *value
+		const char *value,
+		int flags
 )
 {
 	struct rewrite_var *var;
-	int rc;
+	int rc = 0;
 
 	assert( tree != NULL );
 	assert( name != NULL );
 	assert( value != NULL );
 	
+	var = rewrite_var_find( *tree, name );
+	if ( var != NULL ) {
+		if ( flags & REWRITE_VAR_UPDATE ) {
+			(void)rewrite_var_replace( var, value, flags );
+			goto cleanup;
+		}
+		rc = -1;
+		goto cleanup;
+	}
+
 	var = calloc( sizeof( struct rewrite_var ), 1 );
 	if ( var == NULL ) {
 		return NULL;
 	}
+
 	memset( var, 0, sizeof( struct rewrite_var ) );
-	var->lv_name = strdup( name );
-	if ( var->lv_name == NULL ) {
-		rc = -1;
-		goto cleanup;
+
+	if ( flags & REWRITE_VAR_COPY_NAME ) {
+		var->lv_name = strdup( name );
+		if ( var->lv_name == NULL ) {
+			rc = -1;
+			goto cleanup;
+		}
+		var->lv_flags |= REWRITE_VAR_COPY_NAME;
+
+	} else {
+		var->lv_name = (char *)name;
 	}
-	var->lv_value.bv_val = strdup( value );
-	if ( var->lv_value.bv_val == NULL ) {
-		rc = -1;
-		goto cleanup;
+
+	if ( flags & REWRITE_VAR_COPY_VALUE ) {
+		var->lv_value.bv_val = strdup( value );
+		if ( var->lv_value.bv_val == NULL ) {
+			rc = -1;
+			goto cleanup;
+		}
+		var->lv_flags |= REWRITE_VAR_COPY_VALUE;
+		
+	} else {
+		var->lv_value.bv_val = (char *)value;
 	}
 	var->lv_value.bv_len = strlen( value );
 	rc = avl_insert( tree, ( caddr_t )var,
 			rewrite_var_cmp, rewrite_var_dup );
-	if ( rc != 0 ) { 
-		rc = -1;
-		goto cleanup;
-	}
 
 cleanup:;
-	if ( rc != 0 ) {
-		free( var->lv_name );
-		free( var->lv_value.bv_val );
-		free( var );
+	if ( rc != 0 && var ) {
+		avl_delete( tree, ( caddr_t )var, rewrite_var_cmp );
+		rewrite_var_free( var );
 		var = NULL;
 	}
 
@@ -138,11 +232,11 @@ cleanup:;
  * Sets/inserts a var
  */
 struct rewrite_var *
-rewrite_var_set(
+rewrite_var_set_f(
 		Avlnode **tree,
 		const char *name,
 		const char *value,
-		int insert
+		int flags
 )
 {
 	struct rewrite_var *var;
@@ -153,50 +247,19 @@ rewrite_var_set(
 	
 	var = rewrite_var_find( *tree, name );
 	if ( var == NULL ) {
-		if ( insert ) {
-			return rewrite_var_insert( tree, name, value );
+		if ( flags & REWRITE_VAR_INSERT ) {
+			return rewrite_var_insert_f( tree, name, value, flags );
+
 		} else {
 			return NULL;
 		}
+
 	} else {
 		assert( var->lv_value.bv_val != NULL );
 
-		free( var->lv_value.bv_val );
-		var->lv_value.bv_val = strdup( value );
-		var->lv_value.bv_len = strlen( value );
+		(void)rewrite_var_replace( var, value, flags );
 	}
 
 	return var;
 }
 
-/*
- * Frees a var
- */
-static void 
-rewrite_var_free(
-		void *v_var
-)
-{
-	struct rewrite_var *var = v_var;
-	assert( var != NULL );
-
-	assert( var->lv_name != NULL );
-	assert( var->lv_value.bv_val != NULL );
-
-	free( var->lv_name );
-	free( var->lv_value.bv_val );
-	free( var );
-}
-
-/*
- * Deletes a var tree
- */
-int
-rewrite_var_delete(
-		Avlnode *tree
-)
-{
-	avl_free( tree, rewrite_var_free );
-	return REWRITE_SUCCESS;
-}
-