ITS#10013 Make freeing controls the job of whoever added it

This commit is contained in:
Ondřej Kuzník 2023-06-12 11:42:55 +01:00 committed by Quanah Gibson-Mount
parent c1f00a8af6
commit 860b61f41d
11 changed files with 101 additions and 51 deletions

View file

@ -52,6 +52,8 @@
static int dupent_cid; static int dupent_cid;
static slap_overinst dupent; static slap_overinst dupent;
static const char dupent_response_oid[] = LDAP_CONTROL_DUPENT_RESPONSE;
typedef struct dupent_t { typedef struct dupent_t {
AttributeName *ds_an; AttributeName *ds_an;
ber_len_t ds_nattrs; ber_len_t ds_nattrs;
@ -273,7 +275,7 @@ dupent_response_done( Operation *op, SlapReply *rs )
sizeof( LDAPControl ) + ctrlval.bv_len + 1, sizeof( LDAPControl ) + ctrlval.bv_len + 1,
op->o_tmpmemctx ); op->o_tmpmemctx );
ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ]; ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ];
ctrl->ldctl_oid = LDAP_CONTROL_DUPENT_RESPONSE; ctrl->ldctl_oid = dupent_response_oid;
ctrl->ldctl_iscritical = 0; ctrl->ldctl_iscritical = 0;
ctrl->ldctl_value.bv_len = ctrlval.bv_len; ctrl->ldctl_value.bv_len = ctrlval.bv_len;
AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len ); AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len );
@ -295,11 +297,13 @@ dupent_response_entry_1level(
int nattrs, int nattrs,
int level ) int level )
{ {
LDAPControl ctrl = {
.ldctl_oid = LDAP_CONTROL_DUPENT_ENTRY,
.ldctl_iscritical = 0
};
int i, rc = LDAP_SUCCESS; int i, rc = LDAP_SUCCESS;
for ( i = 0; i < valnum[level].ap->a_numvals; i++ ) { for ( i = 0; i < valnum[level].ap->a_numvals; i++ ) {
LDAPControl *ctrl;
valnum[level].a.a_vals[0] = valnum[level].ap->a_vals[i]; valnum[level].a.a_vals[0] = valnum[level].ap->a_vals[i];
if ( valnum[level].ap->a_nvals != valnum[level].ap->a_vals ) { if ( valnum[level].ap->a_nvals != valnum[level].ap->a_vals ) {
valnum[level].a.a_nvals[0] = valnum[level].ap->a_nvals[i]; valnum[level].a.a_nvals[0] = valnum[level].ap->a_nvals[i];
@ -315,15 +319,7 @@ dupent_response_entry_1level(
continue; continue;
} }
/* NOTE: add the control all times, under the assumption slap_add_ctrl( op, rs, &ctrl );
* send_search_entry() honors the REP_CTRLS_MUSTBEFREED
* set by slap_add_ctrls(); this is not true (ITS#6629)
*/
ctrl = op->o_tmpcalloc( 1, sizeof( LDAPControl ), op->o_tmpmemctx );
ctrl->ldctl_oid = LDAP_CONTROL_DUPENT_ENTRY;
ctrl->ldctl_iscritical = 0;
slap_add_ctrl( op, rs, ctrl );
/* do the real send */ /* do the real send */
rs->sr_entry = e; rs->sr_entry = e;
@ -434,11 +430,6 @@ dupent_response_entry( Operation *op, SlapReply *rs )
*app = &valnum[0].a; *app = &valnum[0].a;
/* NOTE: since send_search_entry() does not honor the
* REP_CTRLS_MUSTBEFREED flag set by slap_add_ctrls(),
* the control could be added here once for all (ITS#6629)
*/
dc->dc_skip = 1; dc->dc_skip = 1;
rc = dupent_response_entry_1level( op, rs, e, valnum, nattrs, 0 ); rc = dupent_response_entry_1level( op, rs, e, valnum, nattrs, 0 );
dc->dc_skip = 0; dc->dc_skip = 0;
@ -489,6 +480,22 @@ dupent_cleanup( Operation *op, SlapReply *rs )
op->o_ctrldupent = NULL; op->o_ctrldupent = NULL;
} }
if ( rs->sr_ctrls ) {
int n;
for ( n = 0; rs->sr_ctrls[n]; n++ ) {
/* We only add one control */
if ( rs->sr_ctrls[n]->ldctl_oid == dupent_response_oid ) {
op->o_tmpfree( rs->sr_ctrls[n], op->o_tmpmemctx );
break;
}
}
for ( ; rs->sr_ctrls[n]; n++ ) {
rs->sr_ctrls[n] = rs->sr_ctrls[n+1];
}
}
return SLAP_CB_CONTINUE; return SLAP_CB_CONTINUE;
} }

View file

@ -28,6 +28,8 @@
*/ */
#define LDAP_CONTROL_X_NOOPSRCH "1.3.6.1.4.1.4203.666.5.18" #define LDAP_CONTROL_X_NOOPSRCH "1.3.6.1.4.1.4203.666.5.18"
static const char noopsrch_oid[] = LDAP_CONTROL_X_NOOPSRCH;
#include "slap.h" #include "slap.h"
#include "ac/string.h" #include "ac/string.h"
@ -128,7 +130,7 @@ noopsrch_response( Operation *op, SlapReply *rs )
sizeof( LDAPControl ) + ctrlval.bv_len + 1, sizeof( LDAPControl ) + ctrlval.bv_len + 1,
op->o_tmpmemctx ); op->o_tmpmemctx );
ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ]; ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ];
ctrl->ldctl_oid = LDAP_CONTROL_X_NOOPSRCH; ctrl->ldctl_oid = noopsrch_oid;
ctrl->ldctl_iscritical = 0; ctrl->ldctl_iscritical = 0;
ctrl->ldctl_value.bv_len = ctrlval.bv_len; ctrl->ldctl_value.bv_len = ctrlval.bv_len;
AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len ); AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len );
@ -155,6 +157,21 @@ noopsrch_cleanup( Operation *op, SlapReply *rs )
op->o_callback = NULL; op->o_callback = NULL;
} }
if ( rs->sr_ctrls ) {
int n;
for ( n = 0; rs->sr_ctrls[n]; n++ ) {
if ( rs->sr_ctrls[n]->ldctl_oid == noopsrch_oid ) {
op->o_tmpfree( rs->sr_ctrls[n], op->o_tmpmemctx );
break;
}
}
for ( ; rs->sr_ctrls[n]; n++ ) {
rs->sr_ctrls[n] = rs->sr_ctrls[n+1];
}
}
return SLAP_CB_CONTINUE; return SLAP_CB_CONTINUE;
} }

View file

@ -1978,7 +1978,6 @@ retry:;
rs->sr_flags |= REP_CTRLS_MUSTBEFREED; rs->sr_flags |= REP_CTRLS_MUSTBEFREED;
} else { } else {
assert( rs->sr_ctrls != NULL );
rs->sr_ctrls = NULL; rs->sr_ctrls = NULL;
} }

View file

@ -160,7 +160,7 @@ ldap_back_search(
char **attrs = NULL; char **attrs = NULL;
int freetext = 0, filter_undef = 0; int freetext = 0, filter_undef = 0;
int do_retry = 1, dont_retry = 0; int do_retry = 1, dont_retry = 0;
LDAPControl **ctrls = NULL; LDAPControl **ctrls = NULL, **res_ctrls = NULL;
char **references = NULL; char **references = NULL;
int remove_unknown_schema = int remove_unknown_schema =
LDAP_BACK_OMIT_UNKNOWN_SCHEMA (li); LDAP_BACK_OMIT_UNKNOWN_SCHEMA (li);
@ -374,15 +374,18 @@ retry:
rc = ldap_build_entry( op, e, &ent, &bdn, rc = ldap_build_entry( op, e, &ent, &bdn,
remove_unknown_schema); remove_unknown_schema);
if ( rc == LDAP_SUCCESS ) { if ( rc == LDAP_SUCCESS ) {
ldap_get_entry_controls( lc->lc_ld, res, &rs->sr_ctrls ); ldap_get_entry_controls( lc->lc_ld, res, &rs->sr_ctrls );
res_ctrls = rs->sr_ctrls;
rs->sr_entry = &ent; rs->sr_entry = &ent;
rs->sr_attrs = op->ors_attrs; rs->sr_attrs = op->ors_attrs;
rs->sr_operational_attrs = NULL; rs->sr_operational_attrs = NULL;
rs->sr_flags = 0; rs->sr_flags = 0;
rs->sr_err = LDAP_SUCCESS; rs->sr_err = LDAP_SUCCESS;
rc = rs->sr_err = send_search_entry( op, rs ); rc = rs->sr_err = send_search_entry( op, rs );
if ( rs->sr_ctrls ) { if ( res_ctrls ) {
ldap_controls_free( rs->sr_ctrls ); ldap_controls_free( res_ctrls );
rs->sr_ctrls = NULL; rs->sr_ctrls = NULL;
} }
rs->sr_entry = NULL; rs->sr_entry = NULL;
@ -426,6 +429,7 @@ retry:
if ( rc != LDAP_SUCCESS ) { if ( rc != LDAP_SUCCESS ) {
continue; continue;
} }
res_ctrls = rs->sr_ctrls;
/* FIXME: there MUST be at least one */ /* FIXME: there MUST be at least one */
if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) { if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) {
@ -464,8 +468,8 @@ retry:
references = NULL; references = NULL;
} }
if ( rs->sr_ctrls ) { if ( res_ctrls ) {
ldap_controls_free( rs->sr_ctrls ); ldap_controls_free( res_ctrls );
rs->sr_ctrls = NULL; rs->sr_ctrls = NULL;
} }
@ -481,6 +485,7 @@ retry:
if ( rc != LDAP_SUCCESS ) { if ( rc != LDAP_SUCCESS ) {
continue; continue;
} }
res_ctrls = rs->sr_ctrls;
slap_send_ldap_intermediate( op, rs ); slap_send_ldap_intermediate( op, rs );
@ -494,8 +499,8 @@ retry:
rs->sr_rspdata = NULL; rs->sr_rspdata = NULL;
} }
if ( rs->sr_ctrls != NULL ) { if ( res_ctrls ) {
ldap_controls_free( rs->sr_ctrls ); ldap_controls_free( res_ctrls );
rs->sr_ctrls = NULL; rs->sr_ctrls = NULL;
} }
@ -514,6 +519,7 @@ retry:
rs->sr_err = rc; rs->sr_err = rc;
} }
rs->sr_err = slap_map_api2result( rs ); rs->sr_err = slap_map_api2result( rs );
res_ctrls = rs->sr_ctrls;
/* RFC 4511: referrals can only appear /* RFC 4511: referrals can only appear
* if result code is LDAP_REFERRAL */ * if result code is LDAP_REFERRAL */
@ -634,9 +640,10 @@ finish:;
(void)ldap_back_controls_free( op, rs, &ctrls ); (void)ldap_back_controls_free( op, rs, &ctrls );
if ( rs->sr_ctrls ) { if ( res_ctrls ) {
ldap_controls_free( rs->sr_ctrls ); ldap_controls_free( res_ctrls );
rs->sr_ctrls = NULL; rs->sr_ctrls = NULL;
res_ctrls = NULL;
} }
if ( rs->sr_text ) { if ( rs->sr_text ) {
@ -935,7 +942,7 @@ ldap_back_entry_get(
char *filter = NULL; char *filter = NULL;
SlapReply rs; SlapReply rs;
int do_retry = 1; int do_retry = 1;
LDAPControl **ctrls = NULL; LDAPControl **ctrls = NULL, **res_ctrls = NULL;
Operation op2 = *op; Operation op2 = *op;
int remove_unknown_schema = int remove_unknown_schema =

View file

@ -1492,7 +1492,10 @@ send_paged_response(
ID *lastid, ID *lastid,
int tentries ) int tentries )
{ {
LDAPControl *ctrl; LDAPControl ctrl = {
.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS,
.ldctl_iscritical = 0
};
BerElementBuffer berbuf; BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf; BerElement *ber = (BerElement *)&berbuf;
PagedResultsCookie respcookie; PagedResultsCookie respcookie;
@ -1522,15 +1525,11 @@ send_paged_response(
/* return size of 0 -- no estimate */ /* return size of 0 -- no estimate */
ber_printf( ber, "{iO}", 0, &cookie ); ber_printf( ber, "{iO}", 0, &cookie );
ctrl = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx ); if ( ber_flatten2( ber, &ctrl.ldctl_value, 0 ) == -1 ) {
if ( ber_flatten2( ber, &ctrl->ldctl_value, 0 ) == -1 ) {
goto done; goto done;
} }
ctrl->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; slap_add_ctrl( op, rs, &ctrl );
ctrl->ldctl_iscritical = 0;
slap_add_ctrl( op, rs, ctrl );
rs->sr_err = LDAP_SUCCESS; rs->sr_err = LDAP_SUCCESS;
send_ldap_result( op, rs ); send_ldap_result( op, rs );

View file

@ -1261,7 +1261,6 @@ retry:;
ber_memvfree( (void **)refs ); ber_memvfree( (void **)refs );
} }
if ( ctrls ) { if ( ctrls ) {
assert( rs->sr_ctrls != NULL );
ldap_controls_free( ctrls ); ldap_controls_free( ctrls );
} }

View file

@ -2016,6 +2016,7 @@ meta_send_entry(
Entry ent = { 0 }; Entry ent = { 0 };
BerElement ber = *ldap_get_message_ber( e ); BerElement ber = *ldap_get_message_ber( e );
Attribute *attr, **attrp; Attribute *attr, **attrp;
LDAPControl **res_ctrls;
struct berval bdn, struct berval bdn,
dn = BER_BVNULL; dn = BER_BVNULL;
const char *text; const char *text;
@ -2396,12 +2397,13 @@ next_attr:;
} }
ldap_get_entry_controls( mc->mc_conns[target].msc_ld, ldap_get_entry_controls( mc->mc_conns[target].msc_ld,
e, &rs->sr_ctrls ); e, &res_ctrls );
rs->sr_entry = &ent; rs->sr_entry = &ent;
rs->sr_attrs = op->ors_attrs; rs->sr_attrs = op->ors_attrs;
rs->sr_operational_attrs = NULL; rs->sr_operational_attrs = NULL;
rs->sr_flags = mi->mi_targets[ target ]->mt_rep_flags; rs->sr_flags = mi->mi_targets[ target ]->mt_rep_flags;
rs->sr_err = LDAP_SUCCESS; rs->sr_err = LDAP_SUCCESS;
rs->sr_ctrls = res_ctrls;
rc = send_search_entry( op, rs ); rc = send_search_entry( op, rs );
switch ( rc ) { switch ( rc ) {
case LDAP_UNAVAILABLE: case LDAP_UNAVAILABLE:
@ -2412,8 +2414,8 @@ next_attr:;
done:; done:;
rs->sr_entry = NULL; rs->sr_entry = NULL;
rs->sr_attrs = NULL; rs->sr_attrs = NULL;
if ( rs->sr_ctrls != NULL ) { if ( res_ctrls != NULL ) {
ldap_controls_free( rs->sr_ctrls ); ldap_controls_free( res_ctrls );
rs->sr_ctrls = NULL; rs->sr_ctrls = NULL;
} }
if ( !BER_BVISNULL( &ent.e_name ) ) { if ( !BER_BVISNULL( &ent.e_name ) ) {

View file

@ -273,7 +273,7 @@ send_paged_response(
ID *lastid, ID *lastid,
int tentries ) int tentries )
{ {
LDAPControl *ctrl; LDAPControl ctrl;
BerElementBuffer berbuf; BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf; BerElement *ber = (BerElement *)&berbuf;
PagedResultsCookie respcookie; PagedResultsCookie respcookie;
@ -303,15 +303,14 @@ send_paged_response(
/* return size of 0 -- no estimate */ /* return size of 0 -- no estimate */
ber_printf( ber, "{iO}", 0, &cookie ); ber_printf( ber, "{iO}", 0, &cookie );
ctrl = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx ); if ( ber_flatten2( ber, &ctrl.ldctl_value, 0 ) == -1 ) {
if ( ber_flatten2( ber, &ctrl->ldctl_value, 0 ) == -1 ) {
goto done; goto done;
} }
ctrl->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; ctrl.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
ctrl->ldctl_iscritical = 0; ctrl.ldctl_iscritical = 0;
slap_add_ctrl( op, rs, ctrl ); slap_add_ctrl( op, rs, &ctrl );
rs->sr_err = LDAP_SUCCESS; rs->sr_err = LDAP_SUCCESS;
send_ldap_result( op, rs ); send_ldap_result( op, rs );

View file

@ -141,6 +141,8 @@ static int deref_cid;
static slap_overinst deref; static slap_overinst deref;
static int ov_count; static int ov_count;
static const char deref_oid[] = LDAP_CONTROL_X_DEREF;
static int static int
deref_parseCtrl ( deref_parseCtrl (
Operation *op, Operation *op,
@ -275,6 +277,21 @@ deref_cleanup( Operation *op, SlapReply *rs )
op->o_ctrlderef = NULL; op->o_ctrlderef = NULL;
} }
if ( rs->sr_ctrls ) {
int n;
for ( n = 0; rs->sr_ctrls[n]; n++ ) {
if ( rs->sr_ctrls[n]->ldctl_oid == deref_oid ) {
op->o_tmpfree( rs->sr_ctrls[n], op->o_tmpmemctx );
break;
}
}
for ( ; rs->sr_ctrls[n]; n++ ) {
rs->sr_ctrls[n] = rs->sr_ctrls[n+1];
}
}
return SLAP_CB_CONTINUE; return SLAP_CB_CONTINUE;
} }
@ -465,7 +482,7 @@ deref_response( Operation *op, SlapReply *rs )
sizeof( LDAPControl ) + ctrlval.bv_len + 1, sizeof( LDAPControl ) + ctrlval.bv_len + 1,
op->o_tmpmemctx ); op->o_tmpmemctx );
ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ]; ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ];
ctrl->ldctl_oid = LDAP_CONTROL_X_DEREF; ctrl->ldctl_oid = deref_oid;
ctrl->ldctl_iscritical = 0; ctrl->ldctl_iscritical = 0;
ctrl->ldctl_value.bv_len = ctrlval.bv_len; ctrl->ldctl_value.bv_len = ctrlval.bv_len;
AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len ); AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len );

View file

@ -704,6 +704,10 @@ static void send_result(
slap_add_ctrls( op, rs, ctrls, i ); slap_add_ctrls( op, rs, ctrls, i );
send_ldap_result( op, rs ); send_ldap_result( op, rs );
for ( ; i--; ) {
op->o_tmpfree( ctrls[i], op->o_tmpmemctx );
}
if ( so->so_tree == NULL ) { if ( so->so_tree == NULL ) {
/* Search finished, so clean up */ /* Search finished, so clean up */
free_sort_op( op->o_conn, so ); free_sort_op( op->o_conn, so );
@ -813,10 +817,10 @@ static int sssvlv_op_search(
PagedResultsState *ps; PagedResultsState *ps;
vlv_ctrl *vc; vlv_ctrl *vc;
int sess_id; int sess_id;
LDAPControl *ctrl = NULL;
if ( op->o_ctrlflag[sss_cid] <= SLAP_CONTROL_IGNORED ) { if ( op->o_ctrlflag[sss_cid] <= SLAP_CONTROL_IGNORED ) {
if ( op->o_ctrlflag[vlv_cid] > SLAP_CONTROL_IGNORED ) { if ( op->o_ctrlflag[vlv_cid] > SLAP_CONTROL_IGNORED ) {
LDAPControl *ctrl;
so2.so_vcontext = 0; so2.so_vcontext = 0;
so2.so_vlv_target = 0; so2.so_vlv_target = 0;
so2.so_nentries = 0; so2.so_nentries = 0;

View file

@ -816,7 +816,7 @@ clean2:;
if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */ rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */
if ( rs->sr_ctrls ) { if ( rs->sr_ctrls ) {
slap_free_ctrls( op, rs->sr_ctrls ); op->o_tmpfree( rs->sr_ctrls, op->o_tmpmemctx );
rs->sr_ctrls = NULL; rs->sr_ctrls = NULL;
} }
} }
@ -1543,7 +1543,7 @@ error_return:;
if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */ rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */
if ( rs->sr_ctrls ) { if ( rs->sr_ctrls ) {
slap_free_ctrls( op, rs->sr_ctrls ); op->o_tmpfree( rs->sr_ctrls, op->o_tmpmemctx );
rs->sr_ctrls = NULL; rs->sr_ctrls = NULL;
} }
} }
@ -1701,7 +1701,7 @@ rel:
if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */ rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */
if ( rs->sr_ctrls ) { if ( rs->sr_ctrls ) {
slap_free_ctrls( op, rs->sr_ctrls ); op->o_tmpfree( rs->sr_ctrls, op->o_tmpmemctx );
rs->sr_ctrls = NULL; rs->sr_ctrls = NULL;
} }
} }