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-Url: http://git.ipfire.org/?a=commitdiff_plain;h=70d8e22db7f422bec797bd3f1539a28891b44e5d;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 be323511e2..96160c3de0 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 @@ -4818,7 +4838,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; @@ -4835,6 +4855,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; @@ -4854,6 +4876,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 ); @@ -5646,6 +5671,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) { @@ -5663,6 +5689,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; @@ -5670,6 +5699,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; @@ -5680,9 +5711,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; } @@ -5690,7 +5724,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; @@ -5698,14 +5736,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 @@ -5721,7 +5765,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, @@ -5803,7 +5849,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; @@ -5816,12 +5862,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; @@ -6387,7 +6439,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; @@ -6399,11 +6451,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++]; @@ -6441,8 +6498,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 ); @@ -6695,6 +6756,8 @@ config_back_modrdn( Operation *op, SlapReply *rs ) #endif /* SLAP_CONFIG_RENAME */ } + 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 ); @@ -6705,7 +6768,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; @@ -6743,13 +6807,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; @@ -6760,7 +6827,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; @@ -6858,7 +6925,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; @@ -6875,6 +6942,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; @@ -6882,7 +6952,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;