Commit 47571243 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Fixed slapd ldbm modified attrs on failure (ITS#179) (ITS#181)

parent 33c5d487
......@@ -6,6 +6,7 @@ Changes included in OpenLDAP 1.2 Release Engineering
Fixed slapd modify: delete of last attribute value bug (ITS#229)
Fixed slapd print in signal handler bug (ITS#230)
Fixed slapd index null vals bug (ITS#238)
Fixed slapd ldbm modified attrs on failure (ITS#179) (ITS#181)
Import password security fix from -devel (ITS#232)
Provided slapd workaround for "*" attribute type specifier (ITS#236)
Fixed slapd attribute type list/only specifier on cn=monitor/config
......
......@@ -30,6 +30,69 @@ attr_free( Attribute *a )
free( a );
}
void
attrs_free( Attribute *a )
{
Attribute *next;
for( ; a != NULL ; a = next ) {
next = a->a_next;
attr_free( a );
}
}
Attribute *attr_dup( Attribute *a )
{
Attribute *tmp;
if( a == NULL) return NULL;
tmp = ch_malloc( sizeof(Attribute) );
if( a->a_vals != NULL ) {
int i;
for( i=0; a->a_vals[i] != NULL; i++ ) {
/* EMPTY */ ;
}
tmp->a_vals = ch_malloc((i+1) * sizeof(struct berval*));
for( i=0; a->a_vals[i] != NULL; i++ ) {
tmp->a_vals[i] = ber_bvdup( a->a_vals[i] );
}
tmp->a_vals[i] = NULL;
} else {
tmp->a_vals = NULL;
}
tmp->a_type = ch_strdup( a->a_type );
tmp->a_syntax = a->a_syntax;
tmp->a_next = NULL;
return tmp;
}
Attribute *attrs_dup( Attribute *a )
{
Attribute *tmp, **next;
if( a == NULL ) return NULL;
tmp = NULL;
next = &tmp;
for( ; a != NULL ; a = a->a_next ) {
*next = attr_dup( a );
next = &((*next)->a_next);
}
*next = NULL;
return tmp;
}
/*
* attr_normalize - normalize an attribute name (make it all lowercase)
*/
......
......@@ -108,12 +108,13 @@ int ldbm_internal_modify(
int i, err;
LDAPMod *mod;
Attribute *a;
Attribute *save_attrs;
if ( ((be->be_lastmod == ON)
|| ((be->be_lastmod == UNDEFINED)&&(global_lastmod == ON)))
&& (be->be_update_ndn == NULL)) {
/* XXX: It may be wrong, it changes mod time even if
/* XXX: It may be wrong, it changes mod time even if
* mod fails! I also Think this is leaking memory...
*/
add_lastmods( op, &mods );
......@@ -125,6 +126,9 @@ int ldbm_internal_modify(
return -1;
}
save_attrs = e->e_attrs;
e->e_attrs = attrs_dup( e->e_attrs );
for ( mod = mods; mod != NULL; mod = mod->mod_next ) {
switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
case LDAP_MOD_ADD:
......@@ -136,21 +140,9 @@ int ldbm_internal_modify(
break;
case LDAP_MOD_REPLACE:
/* Need to remove all values from indexes before they
* are lost.
*/
if( e->e_attrs
&& ((a = attr_find( e->e_attrs, mod->mod_type ))
!= NULL) ) {
(void) index_change_values( be,
mod->mod_type,
a->a_vals,
e->e_id,
__INDEX_DEL_OP);
}
err = replace_values( e, mod, op->o_ndn );
break;
case LDAP_MOD_SOFTADD:
/* Avoid problems in index_add_mods()
* We need to add index if necessary.
......@@ -167,14 +159,28 @@ int ldbm_internal_modify(
}
if ( err != LDAP_SUCCESS ) {
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
/* unlock entry, delete from cache */
send_ldap_result( conn, op, err, NULL, NULL );
return -1;
}
}
/* check for abandon */
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
return -1;
}
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* check that the entry still obeys the schema */
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, NULL, NULL );
return -1;
......@@ -183,6 +189,8 @@ int ldbm_internal_modify(
/* check for abandon */
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
return -1;
}
......@@ -190,10 +198,33 @@ int ldbm_internal_modify(
/* modify indexes */
if ( index_add_mods( be, mods, e->e_id ) != 0 ) {
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
return -1;
}
if( save_attrs != NULL ) {
for ( mod = mods; mod != NULL; mod = mod->mod_next ) {
if( ( mod->mod_op & ~LDAP_MOD_BVALUES )
== LDAP_MOD_REPLACE )
{
/* Need to remove all values from indexes */
a = attr_find( save_attrs, mod->mod_type );
if( a != NULL ) {
(void) index_change_values( be,
mod->mod_type,
a->a_vals,
e->e_id,
__INDEX_DEL_OP);
}
}
}
attrs_free( save_attrs );
}
/* check for abandon */
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
if ( op->o_abandon ) {
......@@ -203,8 +234,7 @@ int ldbm_internal_modify(
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
return 0;
}/* int ldbm_internal_modify() */
}
int
......
......@@ -35,6 +35,7 @@ int str2access LDAP_P(( char *str ));
*/
void attr_free LDAP_P(( Attribute *a ));
Attribute *attr_dup LDAP_P(( Attribute *a ));
char * attr_normalize LDAP_P(( char *s ));
int attr_merge_fast LDAP_P(( Entry *e, char *type, struct berval **vals, int nvals,
int naddvals, int *maxvals, Attribute ***a ));
......@@ -44,6 +45,9 @@ int attr_delete LDAP_P(( Attribute **attrs, char *type ));
int attr_syntax LDAP_P(( char *type ));
void attr_syntax_config LDAP_P(( char *fname, int lineno, int argc, char **argv ));
void attrs_free LDAP_P(( Attribute *a ));
Attribute *attrs_dup LDAP_P(( Attribute *a ));
/*
* ava.c
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment