Don't has the current server cs, use a unique id provided by the process module.
//!< 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
};
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;
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.
};
* @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;
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;
{
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;
* 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");
/** 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;
/*
* 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);
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;
}
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) {
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) {
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);
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
#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) },
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;
}
} 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
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) },
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;
} 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;
}
request->request_state = REQUEST_PROCESS;
-
+
} else {
goto setup_send;
}
* 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;
}
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;
/*
},
/* authorization */
-
+
{
.name = "recv",
.name2 = "Authorization-Request",