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;
/* 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,