From: Arran Cudbard-Bell Date: Thu, 25 Mar 2021 17:39:53 +0000 (+0000) Subject: Restore session state in the RADIUS process module X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=111dddc9f4d5b8ad03e7d5fdd3488e600a218460;p=thirdparty%2Ffreeradius-server.git Restore session state in the RADIUS process module --- diff --git a/src/lib/server/state.c b/src/lib/server/state.c index 50a6d9d7dad..afeaf241599 100644 --- a/src/lib/server/state.c +++ b/src/lib/server/state.c @@ -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; } diff --git a/src/lib/server/state.h b/src/lib/server/state.h index 3f37ea0cb08..64bbbddf5f4 100644 --- a/src/lib/server/state.h +++ b/src/lib/server/state.h @@ -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); diff --git a/src/process/radius/base.c b/src/process/radius/base.c index 5f72182a972..7b020c7ae44 100644 --- a/src/process/radius/base.c +++ b/src/process/radius/base.c @@ -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), },