From: Kurt Zeilenga Date: Thu, 29 Jul 1999 23:13:47 +0000 (+0000) Subject: Fixed slapd ldbm modified attrs on failure (ITS#179) (ITS#181) X-Git-Tag: OPENLDAP_REL_ENG_1_2_5~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=475712431908440fea71253efa10de4ff97bc0eb;p=thirdparty%2Fopenldap.git Fixed slapd ldbm modified attrs on failure (ITS#179) (ITS#181) --- diff --git a/CHANGES b/CHANGES index 626f45be37..a48d2865bb 100644 --- a/CHANGES +++ b/CHANGES @@ -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 diff --git a/servers/slapd/attr.c b/servers/slapd/attr.c index 6467a13f05..1e99fc30f9 100644 --- a/servers/slapd/attr.c +++ b/servers/slapd/attr.c @@ -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) */ diff --git a/servers/slapd/back-ldbm/modify.c b/servers/slapd/back-ldbm/modify.c index e0f2e2330e..af91677b7b 100644 --- a/servers/slapd/back-ldbm/modify.c +++ b/servers/slapd/back-ldbm/modify.c @@ -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 diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 41d4ecd7e8..f0f671b1b4 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -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 */