]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Use internal times for the state tree
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sat, 20 Mar 2021 18:20:39 +0000 (18:20 +0000)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 31 Mar 2021 15:07:23 +0000 (16:07 +0100)
Don't has the current server cs, use a unique id provided by the process module.

src/lib/server/state.c
src/lib/server/state.h
src/process/radius/base.c
src/process/tacacs/base.c

index 2f3b83b95cda04576592bf9a6d48156455eab027..50a6d9d7dad5981370822f8749de2b6835124401 100644 (file)
@@ -75,7 +75,7 @@ typedef struct {
                                                                //!< to locate authentication sessions originating
                                                                //!< from a particular backend authentication server.
 
-                       uint32_t        server_hash;            //!< Hash of the current virtual server, xor'd with
+                       uint32_t        context_id;             //!< Hash of the current virtual server, xor'd with
                                                                //!< r1, r2, r3, r4 after the original state value
                                                                //!< is sent, but before the state entry is inserted
                                                                //!< into the tree.  The receiving virtual server
@@ -100,7 +100,7 @@ typedef struct {
        };
 
        uint64_t                seq_start;                      //!< Number of first request in this sequence.
-       time_t                  cleanup;                        //!< When this entry should be cleaned up.
+       fr_time_t               cleanup;                        //!< When this entry should be cleaned up.
        fr_dlist_t              list;                           //!< Entry in the list of things to expire.
 
        int                     tries;
@@ -139,12 +139,14 @@ struct fr_state_tree_s {
        rbtree_t                *tree;                          //!< rbtree used to lookup state value.
        fr_dlist_head_t         to_expire;                      //!< Linked list of entries to free.
 
-       uint32_t                timeout;                        //!< How long to wait before cleaning up state entires.
+       fr_time_delta_t         timeout;                        //!< How long to wait before cleaning up state entires.
 
        bool                    thread_safe;                    //!< Whether we lock the tree whilst modifying it.
        pthread_mutex_t         mutex;                          //!< Synchronisation mutex.
 
        uint8_t                 server_id;                      //!< ID to use for load balancing.
+       uint32_t                context_id;                     //!< ID binding state values to a context such
+                                                               ///< as a virtual server.
 
        fr_dict_attr_t const    *da;                            //!< State attribute used.
 };
@@ -197,12 +199,15 @@ static int _state_tree_free(fr_state_tree_t *state)
  * @param[in] max_sessions     we track state for.
  * @param[in] timeout          How long to wait before cleaning up entries.
  * @param[in] server_id                ID byte to use in load-balancing operations.
+ * @param[in] context_id       Specifies a unique ctx id to prevent states being
+ *                             used in contexts for which they weren't intended.
  * @return
  *     - A new state tree.
  *     - NULL on failure.
  */
 fr_state_tree_t *fr_state_tree_init(TALLOC_CTX *ctx, fr_dict_attr_t const *da, bool thread_safe,
-                                   uint32_t max_sessions, uint32_t timeout, uint8_t server_id)
+                                   uint32_t max_sessions, fr_time_delta_t timeout,
+                                   uint8_t server_id, uint32_t context_id)
 {
        fr_state_tree_t *state;
 
@@ -243,6 +248,7 @@ fr_state_tree_t *fr_state_tree_init(TALLOC_CTX *ctx, fr_dict_attr_t const *da, b
 
        state->da = da;         /* Remember which attribute we use to load/store state */
        state->server_id = server_id;
+       state->context_id = context_id;
        state->thread_safe = thread_safe;
 
        return state;
@@ -312,7 +318,7 @@ static fr_state_entry_t *state_entry_create(fr_state_tree_t *state, request_t *r
 {
        size_t                  i;
        uint32_t                x;
-       time_t                  now = time(NULL);
+       fr_time_t               now = fr_time();
        fr_pair_t               *vp;
        fr_state_entry_t        *entry, *next;
 
@@ -506,7 +512,7 @@ static fr_state_entry_t *state_entry_create(fr_state_tree_t *state, request_t *r
         *      only succeed in the virtual server that created the state
         *      value.
         */
-       *((uint32_t *)(&entry->state_comp.server_hash)) ^= fr_hash_string(cf_section_name2(request->server_cs));
+       *((uint32_t *)(&entry->state_comp.context_id)) ^= state->context_id;
 
        if (!rbtree_insert(state->tree, entry)) {
                RERROR("Failed inserting state entry - Insertion into state tree failed");
@@ -527,7 +533,7 @@ static fr_state_entry_t *state_entry_create(fr_state_tree_t *state, request_t *r
 /** Find the entry, based on the State attribute
  *
  */
-static fr_state_entry_t *state_entry_find(fr_state_tree_t *state, request_t *request, fr_value_box_t const *vb)
+static fr_state_entry_t *state_entry_find(fr_state_tree_t *state, fr_value_box_t const *vb)
 {
        fr_state_entry_t *entry, my_entry;
 
@@ -556,7 +562,7 @@ static fr_state_entry_t *state_entry_find(fr_state_tree_t *state, request_t *req
        /*
         *      Make it unique for different virtual servers handling the same request
         */
-       my_entry.state_comp.server_hash ^= fr_hash_string(cf_section_name2(request->server_cs));
+       my_entry.state_comp.context_id ^= state->context_id;
 
        entry = rbtree_find_data(state->tree, &my_entry);
 
@@ -577,7 +583,7 @@ void fr_state_discard(fr_state_tree_t *state, request_t *request)
        if (!vp) return;
 
        PTHREAD_MUTEX_LOCK(&state->mutex);
-       entry = state_entry_find(state, request, &vp->data);
+       entry = state_entry_find(state, &vp->data);
        if (!entry) {
                PTHREAD_MUTEX_UNLOCK(&state->mutex);
                return;
@@ -634,7 +640,7 @@ void fr_state_to_request(fr_state_tree_t *state, request_t *request)
        }
 
        PTHREAD_MUTEX_LOCK(&state->mutex);
-       entry = state_entry_find(state, request, &vp->data);
+       entry = state_entry_find(state, &vp->data);
        if (entry) {
                (void)talloc_get_type_abort(entry, fr_state_entry_t);
                if (entry->thawed) {
@@ -698,7 +704,7 @@ int fr_request_to_state(fr_state_tree_t *state, request_t *request)
        vp = fr_pair_find_by_da(&request->request_pairs, state->da);
 
        PTHREAD_MUTEX_LOCK(&state->mutex);
-       if (vp) old = state_entry_find(state, request, &vp->data);
+       if (vp) old = state_entry_find(state, &vp->data);
 
        entry = state_entry_create(state, request, &request->reply_pairs, old);
        if (!entry) {
index 6a75500056d5a02203909bf83d415c8a98021bdf..3f37ea0cb087c5442275d937331c0f9898c5fcc5 100644 (file)
@@ -36,7 +36,8 @@ extern "C" {
 typedef struct fr_state_tree_s fr_state_tree_t;
 
 fr_state_tree_t *fr_state_tree_init(TALLOC_CTX *ctx, fr_dict_attr_t const *da, bool thread_safe,
-                                   uint32_t max_sessions, uint32_t timeout, uint8_t server_id);
+                                   uint32_t max_sessions, fr_time_delta_t timeout,
+                                   uint8_t server_id, uint32_t context_id);
 
 void   fr_state_discard(fr_state_tree_t *state, request_t *request);
 
index e0fafe7711896c00b48835f36b92a767493c6520..d4b6ea32c048effd9c393f1a3a398ee2feb523fb 100644 (file)
@@ -127,7 +127,7 @@ typedef struct {
        char const      *denied_msg;            //!< Additional text to append if the user is already logged
                                                //!< in (simultaneous use check failed).
 
-       uint32_t        session_timeout;        //!< Maximum time between the last response and next request.
+       fr_time_delta_t session_timeout;        //!< Maximum time between the last response and next request.
        uint32_t        max_session;            //!< Maximum ongoing session allowed.
 
        uint8_t         state_server_id;        //!< Sets a specific byte in the state to allow the
@@ -152,7 +152,7 @@ typedef struct {
 #include <freeradius-devel/server/process.h>
 
 static const CONF_PARSER session_config[] = {
-       { FR_CONF_OFFSET("timeout", FR_TYPE_UINT32, process_radius_auth_t, session_timeout), .dflt = "15" },
+       { FR_CONF_OFFSET("timeout", FR_TYPE_TIME_DELTA, process_radius_auth_t, session_timeout), .dflt = "15" },
        { FR_CONF_OFFSET("max", FR_TYPE_UINT32, process_radius_auth_t, max_session), .dflt = "4096" },
        { FR_CONF_OFFSET("state_server_id", FR_TYPE_UINT8, process_radius_auth_t, state_server_id) },
 
@@ -691,7 +691,8 @@ static int mod_instantiate(void *instance, UNUSED CONF_SECTION *process_app_cs)
        process_radius_t        *inst = instance;
 
        inst->auth.state_tree = fr_state_tree_init(inst, attr_state, main_config->spawn_workers, inst->auth.max_session,
-                                                  inst->auth.session_timeout, inst->auth.state_server_id);
+                                                  inst->auth.session_timeout, inst->auth.state_server_id,
+                                                  fr_hash_string(cf_section_name2(inst->server_cs)));
 
        return 0;
 }
index 04e583d27d0862db5650efcfdf0576700156337f..09ed6f5eb4c2e16e27a04aa0c73a5c1604fc3e4c 100644 (file)
@@ -56,7 +56,7 @@ typedef struct {
 } tacacs_unlang_t;
 
 typedef struct {
-       uint32_t        session_timeout;                //!< Maximum time between the last response and next request.
+       fr_time_delta_t session_timeout;                //!< Maximum time between the last response and next request.
        uint32_t        max_session;                    //!< Maximum ongoing session allowed.
 
        uint8_t         state_server_id;                //!< Sets a specific byte in the state to allow the
@@ -69,10 +69,12 @@ typedef struct {
        tacacs_unlang_t auth_cont;
        tacacs_unlang_t autz;
        tacacs_unlang_t acct;
+
+       CONF_SECTION    *server_cs;
 } process_tacacs_t;
 
 static const CONF_PARSER session_config[] = {
-       { FR_CONF_OFFSET("timeout", FR_TYPE_UINT32, process_tacacs_t, session_timeout), .dflt = "15" },
+       { FR_CONF_OFFSET("timeout", FR_TYPE_TIME_DELTA, process_tacacs_t, session_timeout), .dflt = "15" },
        { FR_CONF_OFFSET("max", FR_TYPE_UINT32, process_tacacs_t, max_session), .dflt = "4096" },
        { FR_CONF_OFFSET("state_server_id", FR_TYPE_UINT8, process_tacacs_t, state_server_id) },
 
@@ -190,11 +192,11 @@ static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mc
                ctx = &inst->auth_start;
                break;
 
-       case FR_PACKET_TYPE_VALUE_AUTHORIZATION_REQUEST: 
+       case FR_PACKET_TYPE_VALUE_AUTHORIZATION_REQUEST:
                ctx = &inst->autz;
                break;
 
-       case FR_PACKET_TYPE_VALUE_ACCOUNTING_REQUEST: 
+       case FR_PACKET_TYPE_VALUE_ACCOUNTING_REQUEST:
                ctx = &inst->acct;
                break;
 
@@ -351,7 +353,7 @@ static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mc
                } else if (ctx->attr_process == attr_tacacs_accounting_flags) {
                        vp = fr_pair_find_by_da(&request->request_pairs, attr_tacacs_accounting_flags);
                        if (!vp) goto setup_send;
-                       
+
                        dv = fr_dict_enum_by_value(vp->da, &vp->data);
                        if (!dv) goto setup_send;
 
@@ -367,7 +369,7 @@ static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mc
                        }
 
                        request->request_state = REQUEST_PROCESS;
-                       
+
                } else {
                        goto setup_send;
                }
@@ -499,7 +501,8 @@ static int mod_instantiate(void *instance, UNUSED CONF_SECTION *process_app_cs)
         *      connection.
         */
        inst->state_tree = fr_state_tree_init(inst, attr_tacacs_state, main_config->spawn_workers, inst->max_session,
-                                             inst->session_timeout, inst->state_server_id);
+                                             inst->session_timeout, inst->state_server_id,
+                                             fr_hash_string(cf_section_name2(inst->server_cs)));
 
        return 0;
 }
@@ -514,6 +517,7 @@ static int mod_bootstrap(void *instance, CONF_SECTION *process_app_cs)
 
        fr_assert(strcmp(cf_section_name1(server_cs), "server") == 0);
 
+       inst->server_cs = server_cs;
        if (virtual_server_section_attribute_define(server_cs, "authenticate", attr_auth_type) < 0) return -1;
 
        /*
@@ -599,7 +603,7 @@ static virtual_server_compile_t compile_list[] = {
        },
 
        /* authorization */
-       
+
        {
                .name = "recv",
                .name2 = "Authorization-Request",