]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Restore session state in the RADIUS process module
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 25 Mar 2021 17:39:53 +0000 (17:39 +0000)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 31 Mar 2021 15:10:50 +0000 (16:10 +0100)
src/lib/server/state.c
src/lib/server/state.h
src/process/radius/base.c

index 50a6d9d7dad5981370822f8749de2b6835124401..afeaf24159971760a55c83ea4d25fdc7938d7118 100644 (file)
@@ -622,8 +622,16 @@ void fr_state_discard(fr_state_tree_t *state, request_t *request)
  *     are transferred between state entries as the conversation progresses.
  *
  * @note Called with the mutex free.
+ *
+ * @param[in] state    tree to lookup state in.
+ * @param[in] request  to restore state for.
+ * @return
+ *     - 0 on success (state restored)
+ *     - 1 if no state attribute existed.
+ *     - -1 if a state entry matching the value couldn't be found.
+ *     - -2 if a state entry has already been thawed by a another request.
  */
-void fr_state_to_request(fr_state_tree_t *state, request_t *request)
+int fr_state_to_request(fr_state_tree_t *state, request_t *request)
 {
        fr_state_entry_t        *entry;
        TALLOC_CTX              *old_ctx = NULL;
@@ -634,9 +642,9 @@ void fr_state_to_request(fr_state_tree_t *state, request_t *request)
         */
        vp = fr_pair_find_by_da(&request->request_pairs, state->da);
        if (!vp) {
-               RDEBUG3("No &request.State attribute, can't restore &session-state");
+               RDEBUG3("No &request.%s attribute, can't restore &session-state", state->da->name);
                if (request->seq_start == 0) request->seq_start = request->number;      /* Need check for fake requests */
-               return;
+               return 1;
        }
 
        PTHREAD_MUTEX_LOCK(&state->mutex);
@@ -646,7 +654,7 @@ void fr_state_to_request(fr_state_tree_t *state, request_t *request)
                if (entry->thawed) {
                        REDEBUG("State entry has already been thawed by a request %"PRIu64, entry->thawed->number);
                        PTHREAD_MUTEX_UNLOCK(&state->mutex);
-                       return;
+                       return -2;
                }
                if (request->session_state_ctx) old_ctx = request->session_state_ctx;   /* Store for later freeing */
 
@@ -658,8 +666,12 @@ void fr_state_to_request(fr_state_tree_t *state, request_t *request)
 
                entry->ctx = NULL;
                entry->thawed = request;
+               PTHREAD_MUTEX_UNLOCK(&state->mutex);
+       } else {
+               PTHREAD_MUTEX_UNLOCK(&state->mutex);
+               REDEBUG("No state entry matching &request.%pP found", vp);
+               return -1;
        }
-       PTHREAD_MUTEX_UNLOCK(&state->mutex);
 
        if (!fr_pair_list_empty(&request->session_state_pairs)) {
                RDEBUG2("Restored &session-state");
@@ -674,7 +686,7 @@ void fr_state_to_request(fr_state_tree_t *state, request_t *request)
        RDEBUG3("%s - restored", state->da->name);
 
        REQUEST_VERIFY(request);
-       return;
+       return 0;
 }
 
 
index 3f37ea0cb087c5442275d937331c0f9898c5fcc5..64bbbddf5f4aade5f5a0bbc3600bb37106a50316 100644 (file)
@@ -41,7 +41,7 @@ fr_state_tree_t *fr_state_tree_init(TALLOC_CTX *ctx, fr_dict_attr_t const *da, b
 
 void   fr_state_discard(fr_state_tree_t *state, request_t *request);
 
-void   fr_state_to_request(fr_state_tree_t *state, request_t *request);
+int    fr_state_to_request(fr_state_tree_t *state, request_t *request);
 int    fr_request_to_state(fr_state_tree_t *state, request_t *request);
 
 void   fr_state_store_in_parent(request_t *request, void const *unique_ptr, int unique_int);
index 5f72182a97206a20b29c47476a0f00c2d6a603be..7b020c7ae4498d3b228ba9e8426ed1e160cbd792 100644 (file)
@@ -311,13 +311,29 @@ static void CC_HINT(format (printf, 4, 5)) auth_message(process_radius_auth_t co
        talloc_free(msg);
 }
 
-
-#if 0
 RECV(access_request)
 {
-       RETURN_MODULE_FAIL;
+       process_radius_t const          *inst = talloc_get_type_abort_const(mctx->instance, process_radius_t);
+
+       /*
+        *      Requests with invalid state values
+        *      are extremely unlikely to result
+        *      in success, so reject them as quickly
+        *      as we possible.
+        */
+       if (fr_state_to_request(inst->auth.state_tree, request) < 0) {
+               fr_process_state_t const        *state;
+               CONF_SECTION                    *cs;
+
+               request->reply->code = FR_RADIUS_CODE_ACCESS_REJECT;
+               UPDATE_STATE_CS(reply);
+               return unlang_module_yield_to_section(p_result, request,
+                                                     cs, state->rcode, state->send,
+                                                     NULL, NULL);
+       }
+
+       return CALL_RECV(generic);
 }
-#endif
 
 RESUME(auth_type);
 
@@ -425,14 +441,16 @@ RESUME(auth_type)
        }
 
        /*
-        *      Set the reply code.
+        *      Most cases except handled...
         */
-       request->reply->code = auth_type_rcode[rcode];
-       if (!request->reply->code) {
+       if (auth_type_rcode[rcode]) request->reply->code = auth_type_rcode[rcode];
+
+       switch (request->reply->code) {
+       case 0:
                RDEBUG("No reply code was set.  Forcing to Access-Reject");
                request->reply->code = FR_RADIUS_CODE_ACCESS_REJECT;
+               FALL_THROUGH;
 
-       } else switch (request->reply->code) {
        /*
         *      Print complaints before running "send Access-Reject"
         */
@@ -759,7 +777,7 @@ static fr_process_state_t const process_state[] = {
                        [RLM_MODULE_NOTFOUND]   = FR_RADIUS_CODE_ACCESS_REJECT
                },
                .rcode = RLM_MODULE_NOOP,
-               .recv = recv_generic,
+               .recv = recv_access_request,
                .resume = resume_access_request,
                .section_offset = offsetof(process_radius_sections_t, access_request),
        },