ITS#7080 Do not reuse back-ldif's stack for controls

This commit is contained in:
Ondřej Kuzník 2024-10-24 16:01:15 +01:00 committed by Quanah Gibson-Mount
parent e58266229f
commit 70d8e22db7

View file

@ -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 = &sc;
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;