From 8958bcd60f7ab7bc9fe42ff4f6debf36495816da Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Thu, 6 Dec 2007 12:29:04 +0000 Subject: [PATCH] save old values when deleting (ITS#5258; not optimal) --- servers/slapd/overlays/memberof.c | 215 +++++++++++++++++------------- 1 file changed, 122 insertions(+), 93 deletions(-) diff --git a/servers/slapd/overlays/memberof.c b/servers/slapd/overlays/memberof.c index b64628fe12..0b0245d5b5 100644 --- a/servers/slapd/overlays/memberof.c +++ b/servers/slapd/overlays/memberof.c @@ -748,102 +748,133 @@ memberof_op_modify( Operation *op, SlapReply *rs ) save_dn = op->o_dn; save_ndn = op->o_ndn; - if ( MEMBEROF_DANGLING_CHECK( mo ) - && !get_relax( op ) - && memberof_isGroupOrMember( op, &iswhat ) == LDAP_SUCCESS - && ( iswhat & MEMBEROF_IS_GROUP ) ) + if ( memberof_isGroupOrMember( op, &iswhat ) == LDAP_SUCCESS + && ( iswhat & MEMBEROF_IS_GROUP ) ) { - op->o_dn = op->o_bd->be_rootdn; - op->o_dn = op->o_bd->be_rootndn; - op->o_bd->bd_info = (BackendInfo *)on->on_info; - - assert( op->orm_modlist != NULL ); - - for ( mlp = &op->orm_modlist; *mlp; ) { - Modifications *ml = *mlp; - int i; - - if ( !is_ad_subtype( ml->sml_desc, mo->mo_ad_member ) ) { - mlp = &ml->sml_next; - continue; + Modifications *ml; + int save_member = 0; + + for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) { + if ( ml->sml_desc == mo->mo_ad_member ) { + switch ( ml->sml_op ) { + case LDAP_MOD_DELETE: + case LDAP_MOD_REPLACE: + save_member = 1; + break; + } } - - switch ( ml->sml_op ) { - case LDAP_MOD_DELETE: - /* we don't care about cancellations: if the value - * exists, fine; if it doesn't, we let the underlying - * database fail as appropriate; */ - mlp = &ml->sml_next; - break; - - case LDAP_MOD_REPLACE: - case LDAP_MOD_ADD: - /* NOTE: right now, the attributeType we use - * for member must have a normalized value */ - assert( ml->sml_nvalues != NULL ); - - for ( i = 0; !BER_BVISNULL( &ml->sml_nvalues[ i ] ); i++ ) { - int rc; - Entry *e; - - if ( be_entry_get_rw( op, &ml->sml_nvalues[ i ], - NULL, NULL, 0, &e ) == LDAP_SUCCESS ) - { - be_entry_release_r( op, e ); - continue; - } - - if ( MEMBEROF_DANGLING_ERROR( mo ) ) { - rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION; - rs->sr_text = "adding non-existing object " - "as group member"; - send_ldap_result( op, rs ); - goto done; - } - - if ( MEMBEROF_DANGLING_DROP( mo ) ) { - int j; - - Debug( LDAP_DEBUG_ANY, "%s: memberof_op_modify(\"%s\"): " - "member=\"%s\" does not exist (stripping...)\n", - op->o_log_prefix, op->o_req_dn.bv_val, - ml->sml_nvalues[ i ].bv_val ); - - for ( j = i + 1; !BER_BVISNULL( &ml->sml_nvalues[ j ] ); j++ ); - ber_memfree( ml->sml_values[ i ].bv_val ); - BER_BVZERO( &ml->sml_values[ i ] ); - ber_memfree( ml->sml_nvalues[ i ].bv_val ); - BER_BVZERO( &ml->sml_nvalues[ i ] ); - ml->sml_numvals--; - if ( j - i == 1 ) { - break; - } - - AC_MEMCPY( &ml->sml_values[ i ], &ml->sml_values[ i + 1 ], - sizeof( struct berval ) * ( j - i ) ); - AC_MEMCPY( &ml->sml_nvalues[ i ], &ml->sml_nvalues[ i + 1 ], - sizeof( struct berval ) * ( j - i ) ); - i--; - } + } + + if ( save_member ) { + BerVarray vals = NULL; + + op->o_dn = op->o_bd->be_rootdn; + op->o_dn = op->o_bd->be_rootndn; + op->o_bd->bd_info = (BackendInfo *)on->on_info; + rc = backend_attribute( op, NULL, &op->o_req_ndn, + mo->mo_ad_member, &vals, ACL_READ ); + op->o_bd->bd_info = (BackendInfo *)on; + if ( rc == LDAP_SUCCESS && vals != NULL ) { + memberof_saved_member_set( op, &saved_member_vals, vals ); + ber_bvarray_free_x( vals, op->o_tmpmemctx ); + } + } + + if ( MEMBEROF_DANGLING_CHECK( mo ) + && !get_relax( op ) ) + { + op->o_dn = op->o_bd->be_rootdn; + op->o_dn = op->o_bd->be_rootndn; + op->o_bd->bd_info = (BackendInfo *)on->on_info; + + assert( op->orm_modlist != NULL ); + + for ( mlp = &op->orm_modlist; *mlp; ) { + Modifications *ml = *mlp; + int i; + + if ( !is_ad_subtype( ml->sml_desc, mo->mo_ad_member ) ) { + mlp = &ml->sml_next; + continue; } - - if ( BER_BVISNULL( &ml->sml_nvalues[ 0 ] ) ) { - *mlp = ml->sml_next; - slap_mod_free( &ml->sml_mod, 0 ); - free( ml ); - - } else { + + switch ( ml->sml_op ) { + case LDAP_MOD_DELETE: + /* we don't care about cancellations: if the value + * exists, fine; if it doesn't, we let the underlying + * database fail as appropriate; */ mlp = &ml->sml_next; + break; + + case LDAP_MOD_REPLACE: + case LDAP_MOD_ADD: + /* NOTE: right now, the attributeType we use + * for member must have a normalized value */ + assert( ml->sml_nvalues != NULL ); + + for ( i = 0; !BER_BVISNULL( &ml->sml_nvalues[ i ] ); i++ ) { + int rc; + Entry *e; + + if ( be_entry_get_rw( op, &ml->sml_nvalues[ i ], + NULL, NULL, 0, &e ) == LDAP_SUCCESS ) + { + be_entry_release_r( op, e ); + continue; + } + + if ( MEMBEROF_DANGLING_ERROR( mo ) ) { + rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION; + rs->sr_text = "adding non-existing object " + "as group member"; + send_ldap_result( op, rs ); + goto done; + } + + if ( MEMBEROF_DANGLING_DROP( mo ) ) { + int j; + + Debug( LDAP_DEBUG_ANY, "%s: memberof_op_modify(\"%s\"): " + "member=\"%s\" does not exist (stripping...)\n", + op->o_log_prefix, op->o_req_dn.bv_val, + ml->sml_nvalues[ i ].bv_val ); + + for ( j = i + 1; !BER_BVISNULL( &ml->sml_nvalues[ j ] ); j++ ); + ber_memfree( ml->sml_values[ i ].bv_val ); + BER_BVZERO( &ml->sml_values[ i ] ); + ber_memfree( ml->sml_nvalues[ i ].bv_val ); + BER_BVZERO( &ml->sml_nvalues[ i ] ); + ml->sml_numvals--; + if ( j - i == 1 ) { + break; + } + + AC_MEMCPY( &ml->sml_values[ i ], &ml->sml_values[ i + 1 ], + sizeof( struct berval ) * ( j - i ) ); + AC_MEMCPY( &ml->sml_nvalues[ i ], &ml->sml_nvalues[ i + 1 ], + sizeof( struct berval ) * ( j - i ) ); + i--; + } + } + + if ( BER_BVISNULL( &ml->sml_nvalues[ 0 ] ) ) { + *mlp = ml->sml_next; + slap_mod_free( &ml->sml_mod, 0 ); + free( ml ); + + } else { + mlp = &ml->sml_next; + } + + break; + + default: + assert( 0 ); } - - break; - - default: - assert( 0 ); } } } - + if ( mmlp != NULL ) { Modifications *ml = *mmlp; int i; @@ -1280,12 +1311,10 @@ memberof_res_modify( Operation *op, SlapReply *rs ) /* fall thru */ case LDAP_MOD_REPLACE: + vals = memberof_saved_member_get( op, &saved_member_vals ); + /* delete all ... */ - op->o_bd->bd_info = (BackendInfo *)on->on_info; - rc = backend_attribute( op, NULL, &op->o_req_ndn, - mo->mo_ad_member, &vals, ACL_READ ); - op->o_bd->bd_info = (BackendInfo *)on; - if ( rc == LDAP_SUCCESS ) { + if ( vals != NULL ) { for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) { (void)memberof_value_modify( op, rs, &vals[ i ], mo->mo_ad_memberof, -- 2.39.5