From 6f0edd6c22097820d92a3fa57e1b84700414bfcc Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sun, 31 Jul 2005 04:56:27 +0000 Subject: [PATCH] Call slap_mods2entry() in do_add(), so that global overlays (including global SLAPI plugins) have access to op->ora_e. Note that slap_mods2entry() is still called in fe_op_add() in order to add any operational attributes. --- servers/slapd/add.c | 46 ++++++++++++++++++------------ servers/slapd/back-ldap/chain.c | 37 ++---------------------- servers/slapd/modify.c | 28 ++++++++++++++++++ servers/slapd/proto-slap.h | 9 +++++- servers/slapd/slapi/proto-slapi.h | 2 +- servers/slapd/slapi/slapi_ops.c | 24 ++++++++++------ servers/slapd/slapi/slapi_pblock.c | 14 ++++++--- servers/slapd/slapi/slapi_utils.c | 17 +++++++---- 8 files changed, 103 insertions(+), 74 deletions(-) diff --git a/servers/slapd/add.c b/servers/slapd/add.c index b877169f49..30af7693dd 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -166,6 +166,14 @@ do_add( Operation *op, SlapReply *rs ) /* temporary; remove if not invoking backend function */ op->ora_modlist = modlist; + /* call this so global overlays/SLAPI have access to ora_e */ + rs->sr_err = slap_mods2entry( op->ora_modlist, &op->ora_e, + 1, 0, &rs->sr_text, textbuf, textlen ); + if ( rs->sr_err != LDAP_SUCCESS ) { + send_ldap_result( op, rs ); + goto done; + } + op->o_bd = frontendDB; rc = frontendDB->be_add( op, rs ); if ( rc == 0 ) { @@ -302,6 +310,7 @@ fe_op_add( Operation *op, SlapReply *rs ) assert( (*modtail)->sml_desc != NULL ); } + rs->sr_err = slap_mods_opattrs( op, modlist, modtail, &rs->sr_text, textbuf, textlen, 1 ); @@ -309,13 +318,21 @@ fe_op_add( Operation *op, SlapReply *rs ) send_ldap_result( op, rs ); goto done; } - } - rs->sr_err = slap_mods2entry( modlist, &op->ora_e, - repl_user, 0, &rs->sr_text, textbuf, textlen ); - if ( rs->sr_err != LDAP_SUCCESS ) { - send_ldap_result( op, rs ); - goto done; + /* check for duplicate values */ + rs->sr_err = slap_mods_no_repl_user_mod_check( op, + modlist, &rs->sr_text, textbuf, textlen ); + if ( rs->sr_err != LDAP_SUCCESS ) { + send_ldap_result( op, rs ); + goto done; + } + + rs->sr_err = slap_mods2entry( *modtail, &op->ora_e, + 0, 0, &rs->sr_text, textbuf, textlen ); + if ( rs->sr_err != LDAP_SUCCESS ) { + send_ldap_result( op, rs ); + goto done; + } } #ifdef SLAPD_MULTIMASTER @@ -373,22 +390,22 @@ int slap_mods2entry( Modifications *mods, Entry **e, - int repl_user, + int initial, int dup, const char **text, char *textbuf, size_t textlen ) { Attribute **tail = &(*e)->e_attrs; - assert( *tail == NULL ); + + if ( initial ) { + assert( *tail == NULL ); + } *text = textbuf; for( ; mods != NULL; mods = mods->sml_next ) { Attribute *attr; - if ( !repl_user ) { - assert( mods->sml_op == LDAP_MOD_ADD ); - } assert( mods->sml_desc != NULL ); attr = attr_find( (*e)->e_attrs, mods->sml_desc ); @@ -398,13 +415,6 @@ slap_mods2entry( #ifdef SLURPD_FRIENDLY ber_len_t i,j; - if( !repl_user ) { - snprintf( textbuf, textlen, - "attribute '%s' provided more than once", - mods->sml_desc->ad_cname.bv_val ); - return LDAP_TYPE_OR_VALUE_EXISTS; - } - for( i=0; attr->a_vals[i].bv_val; i++ ) { /* count them */ } diff --git a/servers/slapd/back-ldap/chain.c b/servers/slapd/back-ldap/chain.c index 4b1bc2433b..2cba84c833 100644 --- a/servers/slapd/back-ldap/chain.c +++ b/servers/slapd/back-ldap/chain.c @@ -441,43 +441,10 @@ ldap_chain_response( Operation *op, SlapReply *rs ) } break; case LDAP_REQ_ADD: - { - int cleanup_attrs = 0; - - if ( op->ora_e->e_attrs == NULL ) { - char textbuf[ SLAP_TEXT_BUFLEN ]; - size_t textlen = sizeof( textbuf ); - -#if 0 - /* FIXME: op->o_bd is still set to the BackendDB - * structure of the database that tried to handle - * the operation and actually returned a referral - * ... */ - assert( SLAP_DBFLAGS( op->o_bd ) & SLAP_DBFLAG_GLOBAL_OVERLAY ); -#endif - - /* global overlay: create entry */ - /* NOTE: this is a hack to use the chain overlay - * as global. I expect to be able to remove this - * soon by using slap_mods2entry() earlier in - * do_add(), adding the operational attrs later - * if required. */ - rs->sr_err = slap_mods2entry( op->ora_modlist, - &op->ora_e, 0, 1, - &rs->sr_text, textbuf, textlen ); - if ( rs->sr_err != LDAP_SUCCESS ) { - send_ldap_result( op, rs ); - rc = 1; - break; - } - } + /* slap_mods2entry () should be called in do_add() */ + assert( op->ora_e->e_attrs != NULL ); rc = ldap_chain_op( op, rs, lback->bi_op_add, ref ); - if ( cleanup_attrs ) { - attrs_free( op->ora_e->e_attrs ); - op->ora_e->e_attrs = NULL; - } break; - } case LDAP_REQ_DELETE: rc = ldap_chain_op( op, rs, lback->bi_op_delete, ref ); break; diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c index e943b22db1..efa03812d9 100644 --- a/servers/slapd/modify.c +++ b/servers/slapd/modify.c @@ -525,6 +525,34 @@ slap_mods_no_user_mod_check( return LDAP_SUCCESS; } +int +slap_mods_no_repl_user_mod_check( + Operation *op, + Modifications *ml, + const char **text, + char *textbuf, + size_t textlen ) +{ + Modifications *mods; + Modifications *modp; + + for ( mods = ml; mods != NULL; mods = mods->sml_next ) { + assert( mods->sml_op == LDAP_MOD_ADD ); + + /* check doesn't already appear */ + for ( modp = ml; modp != NULL; modp = modp->sml_next ) { + if ( mods->sml_desc == modp->sml_desc ) { + snprintf( textbuf, textlen, + "attribute '%s' provided more than once", + mods->sml_desc->ad_cname.bv_val ); + return LDAP_TYPE_OR_VALUE_EXISTS; + } + } + } + + return LDAP_SUCCESS; +} + /* * Do basic attribute type checking and syntax validation. */ diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 29c6d8f15c..77eea618ac 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -157,7 +157,7 @@ LDAP_SLAPD_V( AttributeName * ) slap_anlist_all_attributes; * add.c */ LDAP_SLAPD_F (int) slap_mods2entry LDAP_P(( Modifications *mods, Entry **e, - int repl_user, int dup, const char **text, char *textbuf, size_t textlen )); + int initial, int dup, const char **text, char *textbuf, size_t textlen )); LDAP_SLAPD_F (int) slap_entry2mods LDAP_P(( Entry *e, Modifications **mods, const char **text, @@ -957,6 +957,13 @@ LDAP_SLAPD_F( int ) slap_mods_no_user_mod_check( const char **text, char *textbuf, size_t textlen ); +LDAP_SLAPD_F ( int ) slap_mods_no_repl_user_mod_check( + Operation *op, + Modifications *ml, + const char **text, + char *textbuf, + size_t textlen ); + LDAP_SLAPD_F( int ) slap_mods_check( Modifications *ml, const char **text, diff --git a/servers/slapd/slapi/proto-slapi.h b/servers/slapd/slapi/proto-slapi.h index 4a7d6b0dde..b39873745d 100644 --- a/servers/slapd/slapi/proto-slapi.h +++ b/servers/slapd/slapi/proto-slapi.h @@ -27,7 +27,7 @@ LDAP_BEGIN_DECL /* slapi_utils.c */ LDAP_SLAPI_F (LDAPMod **) slapi_int_modifications2ldapmods LDAP_P(( Modifications **, void *ctx )); -LDAP_SLAPI_F (Modifications *) slapi_int_ldapmods2modifications LDAP_P(( LDAPMod **, void *ctx )); +LDAP_SLAPI_F (Modifications *) slapi_int_ldapmods2modifications LDAP_P(( LDAPMod **, int dup, void *ctx )); LDAP_SLAPI_F (void) slapi_int_free_ldapmods LDAP_P(( LDAPMod ** )); LDAP_SLAPI_F (int) slapi_int_count_controls LDAP_P(( LDAPControl **ctrls )); LDAP_SLAPI_F (char **) slapi_get_supported_extended_ops LDAP_P((void)); diff --git a/servers/slapd/slapi/slapi_ops.c b/servers/slapd/slapi/slapi_ops.c index c224d7a667..d57f3fc651 100644 --- a/servers/slapd/slapi/slapi_ops.c +++ b/servers/slapd/slapi/slapi_ops.c @@ -296,7 +296,7 @@ slapi_int_set_operation_dn( Slapi_PBlock *pb ) if ( BER_BVISNULL( &op->o_ndn ) ) { /* set to root DN */ - be = select_backend( &op->o_req_ndn, 0, 0 ); + be = select_backend( &op->o_req_ndn, get_manageDSAit( op ), 1 ); if ( be != NULL ) { ber_dupbv( &op->o_dn, &be->be_rootdn ); ber_dupbv( &op->o_ndn, &be->be_rootndn ); @@ -344,10 +344,10 @@ slapi_int_connection_done_pb( Slapi_PBlock *pb ) } break; case LDAP_REQ_ADD: - slapi_int_mods_free( op->ora_modlist ); + slap_mods_free( op->ora_modlist ); break; case LDAP_REQ_MODIFY: - slapi_int_mods_free( op->orm_modlist ); + slap_mods_free( op->orm_modlist ); break; case LDAP_REQ_SEARCH: if ( op->ors_attrs != NULL ) { @@ -429,6 +429,10 @@ slapi_add_internal_pb( Slapi_PBlock *pb ) entry_orig = pb->pb_op->ora_e; pb->pb_op->ora_e = NULL; + /* + * The caller can specify a new entry, or a target DN and set + * of modifications, but not both. + */ if ( entry_orig != NULL ) { if ( pb->pb_op->ora_modlist != NULL || !BER_BVISNULL( &pb->pb_op->o_req_ndn )) { rs->sr_err = LDAP_PARAM_ERROR; @@ -443,10 +447,6 @@ slapi_add_internal_pb( Slapi_PBlock *pb ) goto cleanup; } - /* - * The caller can specify a new entry, or a target DN and set - * of modifications, but not both. - */ pb->pb_op->ora_e = (Entry *)slapi_ch_calloc( 1, sizeof(Entry) ); ber_dupbv( &pb->pb_op->ora_e->e_name, &pb->pb_op->o_req_dn ); ber_dupbv( &pb->pb_op->ora_e->e_nname, &pb->pb_op->o_req_ndn ); @@ -469,11 +469,17 @@ slapi_add_internal_pb( Slapi_PBlock *pb ) goto cleanup; } + /* Duplicate the values, because we may call slapi_entry_free() */ + rs->sr_err = slap_mods2entry( pb->pb_op->ora_modlist, &pb->pb_op->ora_e, + 1, 1, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) ); + if ( rs->sr_err != LDAP_SUCCESS ) { + goto cleanup; + } + if ( slapi_int_func_internal_pb( pb, op_add ) == 0 ) { if ( pb->pb_op->ora_e != NULL && pb->pb_op->o_private != NULL ) { BackendDB *bd = pb->pb_op->o_bd; - /* could we use SLAPI_BACKEND instead? */ pb->pb_op->o_bd = (BackendDB *)pb->pb_op->o_private; pb->pb_op->o_private = NULL; be_entry_release_w( pb->pb_op, pb->pb_op->ora_e ); @@ -492,7 +498,7 @@ cleanup: } if ( entry_orig != NULL ) { pb->pb_op->ora_e = entry_orig; - slapi_int_mods_free( pb->pb_op->ora_modlist ); + slap_mods_free( pb->pb_op->ora_modlist ); pb->pb_op->ora_modlist = NULL; } diff --git a/servers/slapd/slapi/slapi_pblock.c b/servers/slapd/slapi/slapi_pblock.c index cc1b653e76..791a3101d1 100644 --- a/servers/slapd/slapi/slapi_pblock.c +++ b/servers/slapd/slapi/slapi_pblock.c @@ -889,11 +889,10 @@ pblock_set( Slapi_PBlock *pb, int param, void *value ) break; case SLAPI_ADD_ENTRY: PBLOCK_ASSERT_OP( pb, 0 ); - if ( pb->pb_op->o_tag == LDAP_REQ_ADD ) { + if ( pb->pb_op->o_tag == LDAP_REQ_ADD ) pb->pb_op->ora_e = (Slapi_Entry *)value; - } else { + else rc = PBLOCK_ERROR; - } break; case SLAPI_MODIFY_MODS: { Modifications **mlp; @@ -916,7 +915,14 @@ pblock_set( Slapi_PBlock *pb, int param, void *value ) slapi_int_mods_free( *mlp ); *mlp = NULL; } - *mlp = slapi_int_ldapmods2modifications( (LDAPMod **)value, NULL ); + /* + * Note: for internal operations, the modifications need to be + * duplicated because slap_mods_check() will free values before + * prettying, and we have no idea how the values were + * allocated. For frontend operations, slap_mods_check() will + * have already been called. + */ + *mlp = slapi_int_ldapmods2modifications( (LDAPMod **)value, pb->pb_intop, NULL ); break; } case SLAPI_MODRDN_NEWRDN: diff --git a/servers/slapd/slapi/slapi_utils.c b/servers/slapd/slapi/slapi_utils.c index fea5e7d02e..e12d8ab900 100644 --- a/servers/slapd/slapi/slapi_utils.c +++ b/servers/slapd/slapi/slapi_utils.c @@ -2657,7 +2657,7 @@ int slapi_acl_check_mods(Slapi_PBlock *pb, Slapi_Entry *e, LDAPMod **mods, char if ( pb == NULL || pb->pb_op == NULL ) return LDAP_PARAM_ERROR; - ml = slapi_int_ldapmods2modifications( mods, NULL ); + ml = slapi_int_ldapmods2modifications( mods, 0, NULL ); if ( ml == NULL ) { return LDAP_OTHER; } @@ -2741,7 +2741,7 @@ LDAPMod **slapi_int_modifications2ldapmods( * LDAPMods array; the latter MUST be freed with * slapi_int_free_ldapmods() (see below). */ -Modifications *slapi_int_ldapmods2modifications ( LDAPMod **mods, void *memctx ) +Modifications *slapi_int_ldapmods2modifications ( LDAPMod **mods, int dup, void *memctx ) { Modifications *modlist = NULL, **modtail; LDAPMod **modp; @@ -2791,12 +2791,17 @@ Modifications *slapi_int_ldapmods2modifications ( LDAPMod **mods, void *memctx ) /* NB: This implicitly trusts a plugin to return valid modifications. */ if ( lmod->mod_op & LDAP_MOD_BVALUES ) { for ( i = 0; lmod->mod_bvalues[i] != NULL; i++ ) { - mod->sml_values[i].bv_val = lmod->mod_bvalues[i]->bv_val; - mod->sml_values[i].bv_len = lmod->mod_bvalues[i]->bv_len; + if ( dup ) { + ber_dupbv( &mod->sml_values[i], lmod->mod_bvalues[i] ); + } else { + mod->sml_values[i].bv_val = lmod->mod_bvalues[i]->bv_val; + mod->sml_values[i].bv_len = lmod->mod_bvalues[i]->bv_len; + } } } else { for ( i = 0; lmod->mod_values[i] != NULL; i++ ) { - mod->sml_values[i].bv_val = lmod->mod_values[i]; + mod->sml_values[i].bv_val = dup ? slapi_ch_strdup( lmod->mod_values[i] ) : + lmod->mod_values[i]; mod->sml_values[i].bv_len = strlen( lmod->mod_values[i] ); } } @@ -2837,7 +2842,7 @@ slapi_int_mods_free( Modifications *ml ) /* * This function only frees the parts of the mods array that * are not shared with the Modification list that was created - * by slapi_int_ldapmods2modifications(). + * by slapi_int_ldapmods2modifications() (if dup == 0). */ void slapi_int_free_ldapmods ( LDAPMod **mods ) -- 2.39.2