From 819d4093ae9454809f15869967d12ba86fb0c8ff Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Fri, 24 Jan 2003 01:43:09 +0000 Subject: [PATCH] Honour PermitModify control when adding or deleting values. This code needs review although, with the control disabled, it should not affect existing code paths. --- servers/slapd/add.c | 2 +- servers/slapd/back-bdb/modify.c | 8 +-- servers/slapd/back-ldbm/modify.c | 8 +-- servers/slapd/mods.c | 91 ++++++++++++++++++++++++++++---- servers/slapd/proto-slap.h | 5 +- 5 files changed, 93 insertions(+), 21 deletions(-) diff --git a/servers/slapd/add.c b/servers/slapd/add.c index bbeedc1176..924d537f57 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -454,7 +454,7 @@ slap_mods2entry( char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' }; rc = modify_check_duplicates( mods->sml_desc, mr, - NULL, mods->sml_bvalues, + NULL, mods->sml_bvalues, 0, &text, textbuf, sizeof( textbuf ) ); if ( rc != LDAP_SUCCESS ) { diff --git a/servers/slapd/back-bdb/modify.c b/servers/slapd/back-bdb/modify.c index 3bf41f6928..92f376fa17 100644 --- a/servers/slapd/back-bdb/modify.c +++ b/servers/slapd/back-bdb/modify.c @@ -56,7 +56,7 @@ int bdb_modify_internal( #else Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: add\n", 0, 0, 0); #endif - err = modify_add_values( e, mod, text, textbuf, textlen ); + err = modify_add_values( e, mod, op->o_permitmodify, text, textbuf, textlen ); if( err != LDAP_SUCCESS ) { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ERR, @@ -75,7 +75,7 @@ int bdb_modify_internal( #else Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: delete\n", 0, 0, 0); #endif - err = modify_delete_values( e, mod, text, textbuf, textlen ); + err = modify_delete_values( e, mod, op->o_permitmodify, text, textbuf, textlen ); assert( err != LDAP_TYPE_OR_VALUE_EXISTS ); if( err != LDAP_SUCCESS ) { #ifdef NEW_LOGGING @@ -95,7 +95,7 @@ int bdb_modify_internal( #else Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: replace\n", 0, 0, 0); #endif - err = modify_replace_values( e, mod, text, textbuf, textlen ); + err = modify_replace_values( e, mod, op->o_permitmodify, text, textbuf, textlen ); if( err != LDAP_SUCCESS ) { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ERR, @@ -119,7 +119,7 @@ int bdb_modify_internal( */ mod->sm_op = LDAP_MOD_ADD; - err = modify_add_values( e, mod, text, textbuf, textlen ); + err = modify_add_values( e, mod, op->o_permitmodify, text, textbuf, textlen ); if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) { err = LDAP_SUCCESS; } diff --git a/servers/slapd/back-ldbm/modify.c b/servers/slapd/back-ldbm/modify.c index d5db4e28fc..7daf460d78 100644 --- a/servers/slapd/back-ldbm/modify.c +++ b/servers/slapd/back-ldbm/modify.c @@ -65,7 +65,7 @@ int ldbm_modify_internal( Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: add\n", 0, 0, 0); #endif - rc = modify_add_values( e, mod, text, textbuf, textlen ); + rc = modify_add_values( e, mod, op->o_permitmodify, text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING LDAP_LOG( BACK_LDBM, INFO, @@ -84,7 +84,7 @@ int ldbm_modify_internal( Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: delete\n", 0, 0, 0); #endif - rc = modify_delete_values( e, mod, text, textbuf, textlen ); + rc = modify_delete_values( e, mod, op->o_permitmodify, text, textbuf, textlen ); assert( rc != LDAP_TYPE_OR_VALUE_EXISTS ); if( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING @@ -104,7 +104,7 @@ int ldbm_modify_internal( Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: replace\n", 0, 0, 0); #endif - rc = modify_replace_values( e, mod, text, textbuf, textlen ); + rc = modify_replace_values( e, mod, op->o_permitmodify, text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING LDAP_LOG( BACK_LDBM, INFO, @@ -129,7 +129,7 @@ int ldbm_modify_internal( */ mod->sm_op = LDAP_MOD_ADD; - rc = modify_add_values( e, mod, text, textbuf, textlen ); + rc = modify_add_values( e, mod, op->o_permitmodify, text, textbuf, textlen ); if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { rc = LDAP_SUCCESS; } diff --git a/servers/slapd/mods.c b/servers/slapd/mods.c index 20721784ce..81b6930cbe 100644 --- a/servers/slapd/mods.c +++ b/servers/slapd/mods.c @@ -24,11 +24,12 @@ modify_check_duplicates( MatchingRule *mr, BerVarray vals, BerVarray mods, + int permissive, const char **text, char *textbuf, size_t textlen ) { int i, j, numvals = 0, nummods, - rc = LDAP_SUCCESS; + rc = LDAP_SUCCESS, matched; BerVarray nvals = NULL, nmods = NULL; /* @@ -130,7 +131,7 @@ modify_check_duplicates( } if ( numvals > 0 && numvals < nummods ) { - for ( j = 0; nvals[ j ].bv_val; j++ ) { + for ( matched = 0, j = 0; nvals[ j ].bv_val; j++ ) { int match; rc = (*mr->smr_match)( &match, @@ -145,8 +146,12 @@ modify_check_duplicates( ad->ad_cname.bv_val ); goto return_results; } - + if ( match == 0 ) { + if ( permissive ) { + matched++; + continue; + } *text = textbuf; snprintf( textbuf, textlen, "%s: value #%d provided more than once", @@ -156,9 +161,15 @@ modify_check_duplicates( goto return_results; } } + + if ( permissive && matched == j ) { + nmods[ i + 1 ].bv_val = NULL; + rc = LDAP_TYPE_OR_VALUE_EXISTS; + goto return_results; + } } - for ( j = 0; j < i; j++ ) { + for ( matched = 0, j = 0; j < i; j++ ) { int match; rc = (*mr->smr_match)( &match, @@ -175,6 +186,10 @@ modify_check_duplicates( } if ( match == 0 ) { + if ( permissive ) { + matched++; + continue; + } *text = textbuf; snprintf( textbuf, textlen, "%s: value #%d provided more than once", @@ -184,6 +199,12 @@ modify_check_duplicates( goto return_results; } } + + if ( permissive && matched == j ) { + nmods[ i + 1 ].bv_val = NULL; + rc = LDAP_TYPE_OR_VALUE_EXISTS; + goto return_results; + } } nmods[ i ].bv_val = NULL; @@ -205,7 +226,7 @@ modify_check_duplicates( goto return_results; } - for ( i = 0; nmods[ i ].bv_val; i++ ) { + for ( matched = 0, i = 0; nmods[ i ].bv_val; i++ ) { int match; rc = (*mr->smr_match)( &match, @@ -221,6 +242,10 @@ modify_check_duplicates( } if ( match == 0 ) { + if ( permissive ) { + matched++; + continue; + } *text = textbuf; snprintf( textbuf, textlen, "%s: value #%d provided more than once", @@ -230,6 +255,10 @@ modify_check_duplicates( } } + if ( permissive && matched == i ) { + rc = LDAP_TYPE_OR_VALUE_EXISTS; + goto return_results; + } } } @@ -248,11 +277,13 @@ int modify_add_values( Entry *e, Modification *mod, + int permissive, const char **text, char *textbuf, size_t textlen ) { int i, j; + int matched; Attribute *a; MatchingRule *mr = mod->sm_desc->ad_type->sat_equality; const char *op; @@ -271,6 +302,12 @@ modify_add_values( a = attr_find( e->e_attrs, mod->sm_desc ); + /* + * With permissive set, as long as the attribute being added + * has the same value(s?) as the existing attribute, then the + * modify will succeed. + */ + /* check if the values we're adding already exist */ if( mr == NULL || !mr->smr_match ) { if ( a != NULL ) { @@ -286,10 +323,13 @@ modify_add_values( for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) { /* test asserted values against existing values */ if( a ) { - for( j = 0; a->a_vals[j].bv_val != NULL; j++ ) { + for( matched = 0, j = 0; a->a_vals[j].bv_val != NULL; j++ ) { if ( bvmatch( &mod->sm_bvalues[i], &a->a_vals[j] ) ) { - + if ( permissive ) { + matched++; + continue; + } /* value exists already */ *text = textbuf; snprintf( textbuf, textlen, @@ -298,6 +338,10 @@ modify_add_values( return LDAP_TYPE_OR_VALUE_EXISTS; } } + if ( permissive && matched == j ) { + /* values already exist; do nothing */ + return LDAP_SUCCESS; + } } /* test asserted values against themselves */ @@ -357,7 +401,7 @@ modify_add_values( return rc; } - for ( i = 0; a->a_vals[ i ].bv_val; i++ ) { + for ( matched = 0, i = 0; a->a_vals[ i ].bv_val; i++ ) { int match; rc = value_match( &match, mod->sm_desc, mr, @@ -365,6 +409,10 @@ modify_add_values( &a->a_vals[ i ], &asserted, text ); if( rc == LDAP_SUCCESS && match == 0 ) { + if ( permissive ) { + matched++; + continue; + } free( asserted.bv_val ); *text = textbuf; snprintf( textbuf, textlen, @@ -373,13 +421,22 @@ modify_add_values( return LDAP_TYPE_OR_VALUE_EXISTS; } } + if ( permissive && matched == i ) { + /* values already exist; do nothing */ + return LDAP_SUCCESS; + } } } else { rc = modify_check_duplicates( mod->sm_desc, mr, a ? a->a_vals : NULL, mod->sm_bvalues, + permissive, text, textbuf, textlen ); - + + if ( permissive && rc == LDAP_TYPE_OR_VALUE_EXISTS ) { + return LDAP_SUCCESS; + } + if ( rc != LDAP_SUCCESS ) { return rc; } @@ -403,6 +460,7 @@ int modify_delete_values( Entry *e, Modification *mod, + int permissive, const char **text, char *textbuf, size_t textlen ) @@ -413,11 +471,18 @@ modify_delete_values( BerVarray nvals = NULL; char dummy = '\0'; + /* + * If permissive is set, then the non-existence of an + * attribute is not treated as an error. + */ + /* delete the entire attribute */ if ( mod->sm_bvalues == NULL ) { rc = attr_delete( &e->e_attrs, mod->sm_desc ); - if( rc != LDAP_SUCCESS ) { + if( permissive ) { + rc = LDAP_SUCCESS; + } else if( rc != LDAP_SUCCESS ) { *text = textbuf; snprintf( textbuf, textlen, "modify/delete: %s: no such attribute", @@ -439,6 +504,9 @@ modify_delete_values( /* delete specific values - find the attribute first */ if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) { + if( permissive ) { + return LDAP_SUCCESS; + } *text = textbuf; snprintf( textbuf, textlen, "modify/delete: %s: no such attribute", @@ -581,6 +649,7 @@ int modify_replace_values( Entry *e, Modification *mod, + int permissive, const char **text, char *textbuf, size_t textlen ) @@ -588,7 +657,7 @@ modify_replace_values( (void) attr_delete( &e->e_attrs, mod->sm_desc ); if ( mod->sm_bvalues ) { - return modify_add_values( e, mod, text, textbuf, textlen ); + return modify_add_values( e, mod, permissive, text, textbuf, textlen ); } return LDAP_SUCCESS; diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index d281fe4f32..cab27a8eb8 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -590,16 +590,19 @@ LDAP_SLAPD_F( int ) slap_mods_opattrs( */ LDAP_SLAPD_F( int ) modify_check_duplicates( AttributeDescription *ad, MatchingRule *mr, - BerVarray vals, BerVarray mods, + BerVarray vals, BerVarray mods, int permissive, const char **text, char *textbuf, size_t textlen ); LDAP_SLAPD_F( int ) modify_add_values( Entry *e, Modification *mod, + int permissive, const char **text, char *textbuf, size_t textlen ); LDAP_SLAPD_F( int ) modify_delete_values( Entry *e, Modification *mod, + int permissive, const char **text, char *textbuf, size_t textlen ); LDAP_SLAPD_F( int ) modify_replace_values( Entry *e, Modification *mod, + int permissive, const char **text, char *textbuf, size_t textlen ); LDAP_SLAPD_F( void ) slap_mod_free( Modification *mod, int freeit ); -- 2.39.5