]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#10013 Make freeing controls the job of whoever added it
authorOndřej Kuzník <ondra@mistotebe.net>
Mon, 12 Jun 2023 10:42:55 +0000 (11:42 +0100)
committerQuanah Gibson-Mount <quanah@openldap.org>
Tue, 21 Nov 2023 17:21:52 +0000 (17:21 +0000)
contrib/slapd-modules/dupent/dupent.c
contrib/slapd-modules/noopsrch/noopsrch.c
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/search.c
servers/slapd/back-mdb/search.c
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/search.c
servers/slapd/back-wt/search.c
servers/slapd/overlays/deref.c
servers/slapd/overlays/sssvlv.c
servers/slapd/result.c

index 76af313e94b02a49fa1dc965193e78f002d09689..7f5aeed3d4c0807aee25143faaf8f37ba196e8de 100644 (file)
@@ -52,6 +52,8 @@
 static int dupent_cid;
 static slap_overinst dupent;
 
+static const char dupent_response_oid[] = LDAP_CONTROL_DUPENT_RESPONSE;
+
 typedef struct dupent_t {
        AttributeName   *ds_an;
        ber_len_t               ds_nattrs;
@@ -273,7 +275,7 @@ dupent_response_done( Operation *op, SlapReply *rs )
                sizeof( LDAPControl ) + ctrlval.bv_len + 1,
                op->o_tmpmemctx );
        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_value.bv_len = 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 level )
 {
+       LDAPControl ctrl = {
+               .ldctl_oid = LDAP_CONTROL_DUPENT_ENTRY,
+               .ldctl_iscritical = 0
+       };
        int i, rc = LDAP_SUCCESS;
 
        for ( i = 0; i < valnum[level].ap->a_numvals; i++ ) {
-               LDAPControl     *ctrl;
-
                valnum[level].a.a_vals[0] = valnum[level].ap->a_vals[i];
                if ( valnum[level].ap->a_nvals != valnum[level].ap->a_vals ) {
                        valnum[level].a.a_nvals[0] = valnum[level].ap->a_nvals[i];
@@ -315,15 +319,7 @@ dupent_response_entry_1level(
                        continue;
                }
 
-               /* NOTE: add the control all times, under the assumption
-                * 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 );
+               slap_add_ctrl( op, rs, &ctrl );
 
                /* do the real send */
                rs->sr_entry = e;
@@ -434,11 +430,6 @@ dupent_response_entry( Operation *op, SlapReply *rs )
 
        *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;
        rc = dupent_response_entry_1level( op, rs, e, valnum, nattrs, 0 );
        dc->dc_skip = 0;
@@ -489,6 +480,22 @@ dupent_cleanup( Operation *op, SlapReply *rs )
                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;
 }
 
index 6e0c35b0100606c0167863ec899b1fd81164a77f..cb008d683b7ae0656b15665d23deb70ac20635d3 100644 (file)
@@ -28,6 +28,8 @@
  */
 #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 "ac/string.h"
 
@@ -128,7 +130,7 @@ noopsrch_response( Operation *op, SlapReply *rs )
                        sizeof( LDAPControl ) + ctrlval.bv_len + 1,
                        op->o_tmpmemctx );
                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_value.bv_len = 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;
        }
 
+       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;
 }
 
index 7665cb6ae7ff745a862f201b404d03fc6db16244..14357ac42c038cd618a2eb2239fa3f2104c6d8c6 100644 (file)
@@ -1978,7 +1978,6 @@ retry:;
                        rs->sr_flags |= REP_CTRLS_MUSTBEFREED;
 
                } else {
-                       assert( rs->sr_ctrls != NULL );
                        rs->sr_ctrls = NULL;
                }
 
index 90b5b65121c36ea48e3ee912ce571fa026dabe74..daf4bfe8847894391b92500ccb8d00978a49545f 100644 (file)
@@ -160,7 +160,7 @@ ldap_back_search(
        char            **attrs = NULL;
        int             freetext = 0, filter_undef = 0;
        int             do_retry = 1, dont_retry = 0;
-       LDAPControl     **ctrls = NULL;
+       LDAPControl     **ctrls = NULL, **res_ctrls = NULL;
        char            **references = NULL;
        int             remove_unknown_schema =
                                 LDAP_BACK_OMIT_UNKNOWN_SCHEMA (li);
@@ -374,15 +374,18 @@ retry:
                        rc = ldap_build_entry( op, e, &ent, &bdn,
                                                remove_unknown_schema);
                        if ( rc == LDAP_SUCCESS ) {
+
                                ldap_get_entry_controls( lc->lc_ld, res, &rs->sr_ctrls );
+                               res_ctrls = rs->sr_ctrls;
+
                                rs->sr_entry = &ent;
                                rs->sr_attrs = op->ors_attrs;
                                rs->sr_operational_attrs = NULL;
                                rs->sr_flags = 0;
                                rs->sr_err = LDAP_SUCCESS;
                                rc = rs->sr_err = send_search_entry( op, rs );
-                               if ( rs->sr_ctrls ) {
-                                       ldap_controls_free( rs->sr_ctrls );
+                               if ( res_ctrls ) {
+                                       ldap_controls_free( res_ctrls );
                                        rs->sr_ctrls = NULL;
                                }
                                rs->sr_entry = NULL;
@@ -426,6 +429,7 @@ retry:
                        if ( rc != LDAP_SUCCESS ) {
                                continue;
                        }
+                       res_ctrls = rs->sr_ctrls;
 
                        /* FIXME: there MUST be at least one */
                        if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) {
@@ -464,8 +468,8 @@ retry:
                                references = NULL;
                        }
 
-                       if ( rs->sr_ctrls ) {
-                               ldap_controls_free( rs->sr_ctrls );
+                       if ( res_ctrls ) {
+                               ldap_controls_free( res_ctrls );
                                rs->sr_ctrls = NULL;
                        }
 
@@ -481,6 +485,7 @@ retry:
                        if ( rc != LDAP_SUCCESS ) {
                                continue;
                        }
+                       res_ctrls = rs->sr_ctrls;
 
                        slap_send_ldap_intermediate( op, rs );
 
@@ -494,8 +499,8 @@ retry:
                                rs->sr_rspdata = NULL;
                        }
 
-                       if ( rs->sr_ctrls != NULL ) {
-                               ldap_controls_free( rs->sr_ctrls );
+                       if ( res_ctrls ) {
+                               ldap_controls_free( res_ctrls );
                                rs->sr_ctrls = NULL;
                        }
 
@@ -514,6 +519,7 @@ retry:
                                rs->sr_err = rc;
                        }
                        rs->sr_err = slap_map_api2result( rs );
+                       res_ctrls = rs->sr_ctrls;
 
                        /* RFC 4511: referrals can only appear
                         * if result code is LDAP_REFERRAL */
@@ -634,9 +640,10 @@ finish:;
 
        (void)ldap_back_controls_free( op, rs, &ctrls );
 
-       if ( rs->sr_ctrls ) {
-               ldap_controls_free( rs->sr_ctrls );
+       if ( res_ctrls ) {
+               ldap_controls_free( res_ctrls );
                rs->sr_ctrls = NULL;
+               res_ctrls = NULL;
        }
 
        if ( rs->sr_text ) {
@@ -935,7 +942,7 @@ ldap_back_entry_get(
        char            *filter = NULL;
        SlapReply       rs;
        int             do_retry = 1;
-       LDAPControl     **ctrls = NULL;
+       LDAPControl     **ctrls = NULL, **res_ctrls = NULL;
        Operation op2 = *op;
 
        int             remove_unknown_schema =
index 927a3204ef71560a1daa60cd12e6d019a94f3a6f..81b4e0188247e0486b2c767806e9d88ac502d5b3 100644 (file)
@@ -1492,7 +1492,10 @@ send_paged_response(
        ID              *lastid,
        int             tentries )
 {
-       LDAPControl     *ctrl;
+       LDAPControl     ctrl = {
+               .ldctl_oid = LDAP_CONTROL_PAGEDRESULTS,
+               .ldctl_iscritical = 0
+       };
        BerElementBuffer berbuf;
        BerElement      *ber = (BerElement *)&berbuf;
        PagedResultsCookie respcookie;
@@ -1522,15 +1525,11 @@ send_paged_response(
        /* return size of 0 -- no estimate */
        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;
        }
 
-       ctrl->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
-       ctrl->ldctl_iscritical = 0;
-
-       slap_add_ctrl( op, rs, ctrl );
+       slap_add_ctrl( op, rs, &ctrl );
        rs->sr_err = LDAP_SUCCESS;
        send_ldap_result( op, rs );
 
index edfabbb440728932f189c5ee49eb0155a79f83f5..07062a591089bb59e452ef663fed14970d7982d0 100644 (file)
@@ -1261,7 +1261,6 @@ retry:;
                ber_memvfree( (void **)refs );
        }
        if ( ctrls ) {
-               assert( rs->sr_ctrls != NULL );
                ldap_controls_free( ctrls );
        }
 
index cfd2f4b0c11dd918db104d3e54a76552c55382e9..397a4bc05882321c66261b2b24f28c2ca597a2b2 100644 (file)
@@ -2016,6 +2016,7 @@ meta_send_entry(
        Entry                   ent = { 0 };
        BerElement              ber = *ldap_get_message_ber( e );
        Attribute               *attr, **attrp;
+       LDAPControl **res_ctrls;
        struct berval           bdn,
                                dn = BER_BVNULL;
        const char              *text;
@@ -2396,12 +2397,13 @@ next_attr:;
        }
 
        ldap_get_entry_controls( mc->mc_conns[target].msc_ld,
-               e, &rs->sr_ctrls );
+               e, &res_ctrls );
        rs->sr_entry = &ent;
        rs->sr_attrs = op->ors_attrs;
        rs->sr_operational_attrs = NULL;
        rs->sr_flags = mi->mi_targets[ target ]->mt_rep_flags;
        rs->sr_err = LDAP_SUCCESS;
+       rs->sr_ctrls = res_ctrls;
        rc = send_search_entry( op, rs );
        switch ( rc ) {
        case LDAP_UNAVAILABLE:
@@ -2412,8 +2414,8 @@ next_attr:;
 done:;
        rs->sr_entry = NULL;
        rs->sr_attrs = NULL;
-       if ( rs->sr_ctrls != NULL ) {
-               ldap_controls_free( rs->sr_ctrls );
+       if ( res_ctrls != NULL ) {
+               ldap_controls_free( res_ctrls );
                rs->sr_ctrls = NULL;
        }
        if ( !BER_BVISNULL( &ent.e_name ) ) {
index 41d031a4f1d495a831289cdebb5f2bf92847cd27..924179f31dd19d7143a63af065cc8e669c345539 100644 (file)
@@ -273,7 +273,7 @@ send_paged_response(
        ID      *lastid,
        int     tentries )
 {
-       LDAPControl *ctrl;
+       LDAPControl ctrl;
        BerElementBuffer berbuf;
        BerElement  *ber = (BerElement *)&berbuf;
        PagedResultsCookie respcookie;
@@ -303,15 +303,14 @@ send_paged_response(
        /* return size of 0 -- no estimate */
        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;
        }
 
-       ctrl->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
-       ctrl->ldctl_iscritical = 0;
+       ctrl.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
+       ctrl.ldctl_iscritical = 0;
 
-       slap_add_ctrl( op, rs, ctrl );
+       slap_add_ctrl( op, rs, &ctrl );
        rs->sr_err = LDAP_SUCCESS;
        send_ldap_result( op, rs );
 
index 51f7625d2e3fd89de0e36b01dc6f82b2f1705b58..664536ff15138f57475529d3c04ab00cc06034d7 100644 (file)
@@ -141,6 +141,8 @@ static int                  deref_cid;
 static slap_overinst           deref;
 static int ov_count;
 
+static const char deref_oid[] = LDAP_CONTROL_X_DEREF;
+
 static int
 deref_parseCtrl (
        Operation *op,
@@ -275,6 +277,21 @@ deref_cleanup( Operation *op, SlapReply *rs )
                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;
 }
 
@@ -465,7 +482,7 @@ deref_response( Operation *op, SlapReply *rs )
                        sizeof( LDAPControl ) + ctrlval.bv_len + 1,
                        op->o_tmpmemctx );
                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_value.bv_len = ctrlval.bv_len;
                AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len );
index 92255dd7a64f6afae6fff69f2e11185d1f0d653b..1334b9dacbbdff2c160c6c46446985b5879387af 100644 (file)
@@ -704,6 +704,10 @@ static void send_result(
                slap_add_ctrls( op, rs, ctrls, i );
        send_ldap_result( op, rs );
 
+       for ( ; i--; ) {
+               op->o_tmpfree( ctrls[i], op->o_tmpmemctx );
+       }
+
        if ( so->so_tree == NULL ) {
                /* Search finished, so clean up */
                free_sort_op( op->o_conn, so );
@@ -813,10 +817,10 @@ static int sssvlv_op_search(
        PagedResultsState *ps;
        vlv_ctrl *vc;
        int sess_id;
+       LDAPControl *ctrl = NULL;
 
        if ( op->o_ctrlflag[sss_cid] <= SLAP_CONTROL_IGNORED ) {
                if ( op->o_ctrlflag[vlv_cid] > SLAP_CONTROL_IGNORED ) {
-                       LDAPControl *ctrl;
                        so2.so_vcontext = 0;
                        so2.so_vlv_target = 0;
                        so2.so_nentries = 0;
index a928e95c71eadabfa06860071e368402654547fe..c9f9c8a3655aa97509753bfdc999d32e719fdea4 100644 (file)
@@ -816,7 +816,7 @@ clean2:;
        if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
                rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */
                if ( rs->sr_ctrls ) {
-                       slap_free_ctrls( op, rs->sr_ctrls );
+                       op->o_tmpfree( rs->sr_ctrls, op->o_tmpmemctx );
                        rs->sr_ctrls = NULL;
                }
        }
@@ -1543,7 +1543,7 @@ error_return:;
        if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
                rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */
                if ( rs->sr_ctrls ) {
-                       slap_free_ctrls( op, rs->sr_ctrls );
+                       op->o_tmpfree( rs->sr_ctrls, op->o_tmpmemctx );
                        rs->sr_ctrls = NULL;
                }
        }
@@ -1701,7 +1701,7 @@ rel:
        if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
                rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */
                if ( rs->sr_ctrls ) {
-                       slap_free_ctrls( op, rs->sr_ctrls );
+                       op->o_tmpfree( rs->sr_ctrls, op->o_tmpmemctx );
                        rs->sr_ctrls = NULL;
                }
        }