From: Ondřej Kuzník Date: Thu, 24 Oct 2024 15:01:15 +0000 (+0100) Subject: ITS#7080 Do not reuse back-ldif's stack for controls X-Git-Tag: OPENLDAP_REL_ENG_2_6_10~48 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c667f2ea5c048468f19d5de41a13fd9cc1e84e20;p=thirdparty%2Fopenldap.git ITS#7080 Do not reuse back-ldif's stack for controls --- diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index 1876106d6b..8ae98e12e6 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -1112,6 +1112,26 @@ config_substr_if_check( ConfigArgs *c ) return LDAP_SUCCESS; } +static int +config_copy_controls( Operation *op, SlapReply *rs ) +{ + /* Accumulate response controls so we can return them to client */ + if ( rs->sr_ctrls ) { + LDAPControl **prepared = op->o_callback->sc_private, + **received = rs->sr_ctrls; + slap_mask_t oldflags = rs->sr_flags; + + rs->sr_ctrls = prepared; + rs->sr_flags |= REP_CTRLS_MUSTBEFREED; + slap_add_ctrls( op, rs, received, 0 ); + op->o_callback->sc_private = rs->sr_ctrls; + + rs->sr_ctrls = received; + rs->sr_flags = oldflags; + } + return 0; +} + #define GOT_CONFIG 1 #define GOT_FRONTEND 2 static int @@ -4821,7 +4841,7 @@ config_rename_one( Operation *op, SlapReply *rs, Entry *e, if ( use_ldif ) { CfBackInfo *cfb = (CfBackInfo *)op->o_bd->be_private; BackendDB *be = op->o_bd; - slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp; + slap_callback sc = { NULL, config_copy_controls, NULL, rs->sr_ctrls }, *scp; struct berval dn, ndn, xdn, xndn; op->o_bd = &cfb->cb_db; @@ -4838,6 +4858,8 @@ config_rename_one( Operation *op, SlapReply *rs, Entry *e, scp = op->o_callback; op->o_callback = ≻ + rs->sr_ctrls = NULL; + op->orr_newrdn = *newrdn; op->orr_nnewrdn = *nnewrdn; op->orr_newSup = NULL; @@ -4857,6 +4879,9 @@ config_rename_one( Operation *op, SlapReply *rs, Entry *e, op->o_ndn = ndn; op->o_req_dn = xdn; op->o_req_ndn = xndn; + + rs->sr_ctrls = sc.sc_private; + rs->sr_flags |= REP_CTRLS_MUSTBEFREED; } free( odn.bv_val ); free( ondn.bv_val ); @@ -5648,6 +5673,7 @@ config_rename_add( Operation *op, SlapReply *rs, CfEntryInfo *ce, CfEntryInfo *ce2, *ce3, *cetmp = NULL, *cerem = NULL; ConfigType etype = ce->ce_type; int count = 0, rc = 0; + char preread = op->o_preread, postread = op->o_postread; /* Reverse ce list */ for (ce2 = ce->ce_sibs;ce2;ce2 = ce3) { @@ -5665,6 +5691,9 @@ config_rename_add( Operation *op, SlapReply *rs, CfEntryInfo *ce, } } + /* Suppress control generation for internal ops */ + op->o_postread = SLAP_CONTROL_NONE; + /* Move original to a temp name until increments are done */ if ( rebase ) { ce->ce_entry->e_private = NULL; @@ -5672,6 +5701,8 @@ config_rename_add( Operation *op, SlapReply *rs, CfEntryInfo *ce, base+BIGTMP, 0, use_ldif ); ce->ce_entry->e_private = ce; } + op->o_preread = SLAP_CONTROL_NONE; + /* start incrementing */ for (ce2=cetmp; ce2; ce2=ce3) { ce3 = ce2->ce_sibs; @@ -5682,9 +5713,12 @@ config_rename_add( Operation *op, SlapReply *rs, CfEntryInfo *ce, count+base, 0, use_ldif ); count--; } + + op->o_postread = postread; if ( rebase ) rc = config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry, base, 0, use_ldif ); + op->o_preread = preread; return rc; } @@ -5692,7 +5726,11 @@ static int config_rename_del( Operation *op, SlapReply *rs, CfEntryInfo *ce, CfEntryInfo *ce2, int old, int use_ldif ) { - int count = 0; + int rc, count = 0; + char preread = op->o_preread, postread = op->o_postread; + + /* Suppress control generation for internal ops */ + op->o_postread = SLAP_CONTROL_NONE; /* Renumber original to a temp value */ ce->ce_entry->e_private = NULL; @@ -5700,14 +5738,20 @@ config_rename_del( Operation *op, SlapReply *rs, CfEntryInfo *ce, old+BIGTMP, 0, use_ldif ); ce->ce_entry->e_private = ce; + op->o_preread = SLAP_CONTROL_NONE; + /* start decrementing */ for (; ce2 != ce; ce2=ce2->ce_sibs) { config_renumber_one( op, rs, ce2->ce_parent, ce2->ce_entry, count+old, 0, use_ldif ); count++; } - return config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry, + + op->o_postread = postread; + rc = config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry, count+old, 0, use_ldif ); + op->o_preread = preread; + return rc; } /* Parse an LDAP entry into config directives, then store in underlying @@ -5723,7 +5767,9 @@ config_back_add( Operation *op, SlapReply *rs ) LDAPControl **postread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; + char postread = op->o_postread; + op->o_postread = SLAP_CONTROL_NONE; ctrls[num_ctrls] = NULL; if ( !access_allowed( op, op->ora_e, slap_schema.si_ad_entry, @@ -5805,7 +5851,7 @@ config_back_add( Operation *op, SlapReply *rs ) if ( cfb->cb_use_ldif ) { BackendDB *be = op->o_bd; - slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp; + slap_callback sc = { NULL, config_copy_controls, NULL, rs->sr_ctrls }, *scp; struct berval dn, ndn; op->o_bd = &cfb->cb_db; @@ -5818,12 +5864,18 @@ config_back_add( Operation *op, SlapReply *rs ) scp = op->o_callback; op->o_callback = ≻ + op->o_postread = postread; + rs->sr_ctrls = NULL; + op->o_bd->be_add( op, rs ); op->o_bd = be; op->o_callback = scp; op->o_dn = dn; op->o_ndn = ndn; - } else if ( op->o_postread ) { + + rs->sr_ctrls = sc.sc_private; + rs->sr_flags |= REP_CTRLS_MUSTBEFREED; + } else if ( postread ) { if ( postread_ctrl == NULL ) { postread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; @@ -6389,7 +6441,7 @@ config_back_modify( Operation *op, SlapReply *rs ) rs->sr_text = ca.cr_msg; } else if ( cfb->cb_use_ldif ) { BackendDB *be = op->o_bd; - slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp; + slap_callback sc = { NULL, config_copy_controls, NULL, rs->sr_ctrls }, *scp; struct berval dn, ndn; op->o_bd = &cfb->cb_db; @@ -6401,11 +6453,16 @@ config_back_modify( Operation *op, SlapReply *rs ) scp = op->o_callback; op->o_callback = ≻ + rs->sr_ctrls = NULL; + op->o_bd->be_modify( op, rs ); op->o_bd = be; op->o_callback = scp; op->o_dn = dn; op->o_ndn = ndn; + + rs->sr_ctrls = sc.sc_private; + rs->sr_flags |= REP_CTRLS_MUSTBEFREED; } else if ( op->o_postread ) { if ( postread_ctrl == NULL ) { postread_ctrl = &ctrls[num_ctrls++]; @@ -6443,8 +6500,10 @@ config_back_modrdn( Operation *op, SlapReply *rs ) LDAPControl **postread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; + char preread = op->o_preread, postread = op->o_postread; ctrls[num_ctrls] = NULL; + op->o_preread = op->o_postread = SLAP_CONTROL_NONE; cfb = (CfBackInfo *)op->o_bd->be_private; @@ -6563,7 +6622,7 @@ config_back_modrdn( Operation *op, SlapReply *rs ) } /* If we have a backend, it will handle the control */ - if ( !cfb->cb_use_ldif && op->o_preread ) { + if ( !cfb->cb_use_ldif && preread > SLAP_CONTROL_IGNORED ) { if ( preread_ctrl == NULL ) { preread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; @@ -6606,6 +6665,8 @@ config_back_modrdn( Operation *op, SlapReply *rs ) Attribute *a; rs->sr_err = config_rename_attr( rs, ce->ce_entry, &rdn, &a ); if ( rs->sr_err == LDAP_SUCCESS ) { + op->o_preread = preread; + op->o_postread = postread; rs->sr_err = config_rename_one( op, rs, ce->ce_entry, ce->ce_parent, a, &op->orr_newrdn, &op->orr_nnewrdn, cfb->cb_use_ldif ); @@ -6653,7 +6714,9 @@ config_back_modrdn( Operation *op, SlapReply *rs ) backend_db_move( ce->ce_be, ixnew ); else if ( ce->ce_type == Cft_Overlay ) overlay_move( ce->ce_be, (slap_overinst *)ce->ce_bi, ixnew ); - + + op->o_preread = preread; + op->o_postread = postread; if ( ixold < ixnew ) { rs->sr_err = config_rename_del( op, rs, ce, ceold, ixold, cfb->cb_use_ldif ); @@ -6664,7 +6727,8 @@ config_back_modrdn( Operation *op, SlapReply *rs ) op->oq_modrdn = modr; } - if ( rs->sr_err == LDAP_SUCCESS && !cfb->cb_use_ldif && op->o_postread ) { + if ( rs->sr_err == LDAP_SUCCESS && !cfb->cb_use_ldif && + postread > SLAP_CONTROL_IGNORED ) { if ( postread_ctrl == NULL ) { postread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; @@ -6701,13 +6765,16 @@ config_back_delete( Operation *op, SlapReply *rs ) LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; + char preread = op->o_preread; + ctrls[num_ctrls] = NULL; + op->o_preread = SLAP_CONTROL_NONE; cfb = (CfBackInfo *)op->o_bd->be_private; /* If we have a backend, it will handle the control */ ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last, op ); - if ( ce && !cfb->cb_use_ldif && op->o_preread ) { + if ( ce && !cfb->cb_use_ldif && preread ) { if ( preread_ctrl == NULL ) { preread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; @@ -6718,7 +6785,7 @@ config_back_delete( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_ANY, "config_back_delete: " "pre-read failed \"%s\"\n", ce->ce_entry->e_name.bv_val ); - if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { + if ( preread & SLAP_CONTROL_CRITICAL ) { /* FIXME: is it correct to abort * operation if control fails? */ goto out; @@ -6816,7 +6883,7 @@ config_back_delete( Operation *op, SlapReply *rs ) /* remove from underlying database */ if ( cfb->cb_use_ldif ) { BackendDB *be = op->o_bd; - slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp; + slap_callback sc = { NULL, config_copy_controls, NULL, rs->sr_ctrls }, *scp; struct berval dn, ndn, req_dn, req_ndn; op->o_bd = &cfb->cb_db; @@ -6833,6 +6900,9 @@ config_back_delete( Operation *op, SlapReply *rs ) scp = op->o_callback; op->o_callback = ≻ + op->o_preread = preread; + rs->sr_ctrls = NULL; + op->o_bd->be_delete( op, rs ); op->o_bd = be; op->o_callback = scp; @@ -6840,7 +6910,11 @@ config_back_delete( Operation *op, SlapReply *rs ) op->o_ndn = ndn; op->o_req_dn = req_dn; op->o_req_ndn = req_ndn; + + rs->sr_ctrls = sc.sc_private; + rs->sr_flags |= REP_CTRLS_MUSTBEFREED; } + op->o_preread = SLAP_CONTROL_NONE; /* renumber siblings */ iptr = ber_bvchr( &op->o_req_ndn, '{' ) + 1;