Skip to content

Commit

Permalink
Added waiting queue to EAPOL authentications to Border Router
Browse files Browse the repository at this point in the history
If there is congestion (e.g. simultaneus authentications limit
has been reached) when initial-EAPOL key message arrives,
authenticator moves supplicant to waiting supplicants queue.
When previous authentications complete, authenticator checks
if the security negotation toward a supplicant on the queue
can be started (first supplicant on the queue).
  • Loading branch information
Mika Leppänen committed Feb 23, 2021
1 parent b9c0b7d commit 16e3402
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 106 deletions.
2 changes: 1 addition & 1 deletion source/6LoWPAN/ws/ws_bootstrap.c
Expand Up @@ -2335,7 +2335,7 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode)
ret_val = -4;
goto init_fail;
}
if (ws_pae_controller_configure(cur, &cur->ws_info->cfg->sec_timer, &cur->ws_info->cfg->sec_prot) < 0) {
if (ws_pae_controller_configure(cur, &cur->ws_info->cfg->sec_timer, &cur->ws_info->cfg->sec_prot, &cur->ws_info->cfg->timing) < 0) {
ret_val = -4;
goto init_fail;
}
Expand Down
5 changes: 3 additions & 2 deletions source/6LoWPAN/ws/ws_cfg_settings.c
Expand Up @@ -878,6 +878,7 @@ int8_t ws_cfg_timing_set(protocol_interface_info_entry_t *cur, ws_timing_cfg_t *
cur->ws_info->trickle_params_pan_discovery.Imax = new_cfg->disc_trickle_imax * 10;
cur->ws_info->trickle_params_pan_discovery.k = new_cfg->disc_trickle_k;
cur->ws_info->trickle_params_pan_discovery.TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE;
ws_pae_controller_configure(cur, NULL, NULL, new_cfg);
}

if (cfg == new_cfg) {
Expand Down Expand Up @@ -1207,7 +1208,7 @@ int8_t ws_cfg_sec_timer_set(protocol_interface_info_entry_t *cur, ws_sec_timer_c
}

if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
ws_pae_controller_configure(cur, new_cfg, NULL);
ws_pae_controller_configure(cur, new_cfg, NULL, NULL);
}

if (cfg == new_cfg) {
Expand Down Expand Up @@ -1276,7 +1277,7 @@ int8_t ws_cfg_sec_prot_set(protocol_interface_info_entry_t *cur, ws_sec_prot_cfg
}

if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) {
ws_pae_controller_configure(cur, NULL, new_cfg);
ws_pae_controller_configure(cur, NULL, new_cfg, NULL);
}

if (cfg == new_cfg) {
Expand Down
167 changes: 113 additions & 54 deletions source/6LoWPAN/ws/ws_pae_auth.c

Large diffs are not rendered by default.

12 changes: 8 additions & 4 deletions source/6LoWPAN/ws/ws_pae_controller.c
Expand Up @@ -702,7 +702,7 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr)
return 0;
}

int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg)
int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg, struct ws_timing_cfg_s *timing_cfg)
{
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
if (controller == NULL) {
Expand All @@ -729,6 +729,10 @@ int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_pt

controller->sec_cfg.radius_cfg = pae_controller_config.radius_cfg;

if (timing_cfg) {
controller->sec_cfg.timing_cfg.temp_eapol_min_timeout = timing_cfg->temp_eapol_min_timeout;
}

return 0;
}

Expand Down Expand Up @@ -1246,7 +1250,7 @@ int8_t ws_pae_controller_radius_address_set(int8_t interface_id, const uint8_t *
return 0;
}

if (ws_pae_controller_configure(controller->interface_ptr, NULL, NULL) < 0) {
if (ws_pae_controller_configure(controller->interface_ptr, NULL, NULL, NULL) < 0) {
return -1;
}

Expand Down Expand Up @@ -1296,7 +1300,7 @@ int8_t ws_pae_controller_radius_shared_secret_set(int8_t interface_id, const uin

pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
if (controller) {
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL);
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL, NULL);
}

return 0;
Expand Down Expand Up @@ -1349,7 +1353,7 @@ int8_t ws_pae_controller_radius_timing_set(int8_t interface_id, bbr_radius_timin

pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
if (controller) {
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL);
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL, NULL);
}

return 0;
Expand Down
4 changes: 3 additions & 1 deletion source/6LoWPAN/ws/ws_pae_controller.h
Expand Up @@ -31,6 +31,7 @@ struct nvm_tlv_entry;
struct ws_sec_timer_cfg_s;
struct ws_sec_prot_cfg_s;
struct bbr_radius_timing;
struct ws_timing_cfg_s;

/**
* ws_pae_controller_set_target sets EAPOL target for PAE supplicant
Expand Down Expand Up @@ -98,12 +99,13 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr);
* \param interface_ptr interface
* \param sec_timer_cfg timer configuration or NULL if not set
* \param sec_prot_cfg protocol configuration or NULL if not set
* \param timing_cfg timing configuration or NULL if not set
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg);
int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg, struct ws_timing_cfg_s *timing_cfg);

/**
* ws_pae_controller_init initializes PAE supplicant
Expand Down
65 changes: 34 additions & 31 deletions source/6LoWPAN/ws/ws_pae_lib.c
Expand Up @@ -193,18 +193,23 @@ supp_entry_t *ws_pae_lib_supp_list_add(supp_list_t *supp_list, const kmp_addr_t
entry->addr.type = KMP_ADDR_EUI_64_AND_IP;
kmp_address_copy(&entry->addr, addr);

ns_list_add_to_end(supp_list, entry);
ns_list_add_to_start(supp_list, entry);

return entry;
}

int8_t ws_pae_lib_supp_list_remove(supp_list_t *supp_list, supp_entry_t *supp)
int8_t ws_pae_lib_supp_list_remove(void *instance, supp_list_t *supp_list, supp_entry_t *supp, ws_pae_lib_supp_deleted supp_deleted)
{
ns_list_remove(supp_list, supp);

ws_pae_lib_supp_delete(supp);

ns_dyn_mem_free(supp);

if (supp_deleted != NULL) {
supp_deleted(instance);
}

return 0;
}

Expand All @@ -222,11 +227,11 @@ supp_entry_t *ws_pae_lib_supp_list_entry_eui_64_get(const supp_list_t *supp_list
void ws_pae_lib_supp_list_delete(supp_list_t *supp_list)
{
ns_list_foreach_safe(supp_entry_t, entry, supp_list) {
ws_pae_lib_supp_list_remove(supp_list, entry);
ws_pae_lib_supp_list_remove(NULL, supp_list, entry, NULL);
}
}

bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout)
bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout, ws_pae_lib_supp_deleted supp_deleted)
{
bool timer_running = false;

Expand All @@ -235,7 +240,7 @@ bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_
if (running) {
timer_running = true;
} else {
ws_pae_lib_supp_list_to_inactive(instance, active_supp_list, entry);
ws_pae_lib_supp_list_to_inactive(instance, active_supp_list, entry, supp_deleted);
}
}

Expand All @@ -260,7 +265,7 @@ void ws_pae_lib_supp_init(supp_entry_t *entry)
memset(&entry->addr, 0, sizeof(kmp_addr_t));
memset(&entry->sec_keys, 0, sizeof(sec_prot_keys_t));
entry->ticks = 0;
entry->retry_ticks = 0;
entry->waiting_ticks = 0;
entry->store_ticks = ws_pae_key_storage_storing_interval_get() * 1000;
entry->active = true;
entry->access_revoked = false;
Expand All @@ -283,18 +288,18 @@ bool ws_pae_lib_supp_timer_update(void *instance, supp_entry_t *entry, uint16_t
entry->ticks -= ticks;
} else {
entry->ticks = 0;
entry->retry_ticks = 0;
}
}

// Updates retry timer
if (entry->retry_ticks > ticks) {
entry->retry_ticks -= ticks;
if (entry->waiting_ticks > ticks) {
keep_timer_running = true;
entry->waiting_ticks -= ticks;
} else {
if (entry->retry_ticks > 0) {
tr_info("EAP-TLS max ongoing delay timeout eui-64: %s", trace_array(entry->addr.eui_64, 8));
if (entry->waiting_ticks > 0) {
tr_info("Waiting supplicant timeout eui-64: %s", trace_array(entry->addr.eui_64, 8));
}
entry->retry_ticks = 0;
entry->waiting_ticks = 0;
}

if (!instance) {
Expand Down Expand Up @@ -350,7 +355,7 @@ void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t *
entry->addr.type = KMP_ADDR_EUI_64_AND_IP;
}

void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry)
void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry, ws_pae_lib_supp_deleted supp_deleted)
{
if (!entry->active) {
return;
Expand All @@ -360,18 +365,21 @@ void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_l

if (entry->access_revoked) {
tr_info("Access revoked; deleted, eui-64: %s", trace_array(entry->addr.eui_64, 8));
ws_pae_lib_supp_list_remove(active_supp_list, entry);
ws_pae_lib_supp_list_remove(instance, active_supp_list, entry, supp_deleted);
return;
}

// Store to key storage
ws_pae_key_storage_supp_write(instance, entry);

// Remove supplicant entry
ws_pae_lib_supp_list_remove(active_supp_list, entry);
ws_pae_lib_supp_list_remove(instance, active_supp_list, entry, supp_deleted);
if (supp_deleted) {
supp_deleted(instance);
}
}

void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge)
void ws_pae_lib_supp_list_purge(void *instance, supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge, ws_pae_lib_supp_deleted supp_deleted)
{
uint16_t active_supp = ns_list_count(active_supp_list);

Expand All @@ -385,7 +393,7 @@ void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_numb
ns_list_foreach_safe(supp_entry_t, entry, active_supp_list) {
if (remove_count > 0 && ws_pae_lib_kmp_list_empty(&entry->kmp_list)) {
tr_info("Active supplicant removed, eui-64: %s", trace_array(kmp_address_eui_64_get(&entry->addr), 8));
ws_pae_lib_supp_list_remove(active_supp_list, entry);
ws_pae_lib_supp_list_remove(instance, active_supp_list, entry, supp_deleted);
remove_count--;
} else {
break;
Expand All @@ -409,33 +417,28 @@ uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type)
return kmp_count;
}

kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const void *pdu, uint16_t size)
bool ws_pae_lib_supp_list_entry_is_in_list(supp_list_t *supp_list, supp_entry_t *searched_entry)
{
ns_list_foreach(supp_entry_t, entry, supp_list) {
ns_list_foreach(kmp_entry_t, kmp_entry, &entry->kmp_list) {
if (kmp_api_receive_check(kmp_entry->kmp, pdu, size)) {
return kmp_entry->kmp;
}
if (entry == searched_entry) {
return true;
}
}

return NULL;
return false;
}

supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list)
kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const void *pdu, uint16_t size)
{
supp_entry_t *retry_supp = NULL;

ns_list_foreach(supp_entry_t, entry, supp_list) {
// Finds entry with shortest timeout i.e. oldest one
if (entry->retry_ticks > 0) {
if (!retry_supp || retry_supp->retry_ticks > entry->retry_ticks) {
retry_supp = entry;
ns_list_foreach(kmp_entry_t, kmp_entry, &entry->kmp_list) {
if (kmp_api_receive_check(kmp_entry->kmp, pdu, size)) {
return kmp_entry->kmp;
}
}
}

return retry_supp;
return NULL;
}

int8_t ws_pae_lib_shared_comp_list_init(shared_comp_list_t *comp_list)
Expand Down
41 changes: 28 additions & 13 deletions source/6LoWPAN/ws/ws_pae_lib.h
Expand Up @@ -36,7 +36,7 @@ typedef struct supp_entry_s {
kmp_addr_t addr; /**< EUI-64 (Relay IP address, Relay port) */
sec_prot_keys_t sec_keys; /**< Security keys */
uint32_t ticks; /**< Ticks */
uint16_t retry_ticks; /**< Retry ticks */
uint16_t waiting_ticks; /**< Waiting ticks */
uint16_t store_ticks; /**< NVM store ticks */
bool active : 1; /**< Is active */
bool access_revoked : 1; /**< Nodes access is revoked */
Expand Down Expand Up @@ -211,16 +211,26 @@ void ws_pae_lib_supp_list_init(supp_list_t *supp_list);
*/
supp_entry_t *ws_pae_lib_supp_list_add(supp_list_t *supp_list, const kmp_addr_t *addr);

/**
* ws_pae_lib_supp_deleted supplicant delete callback
*
* \param instance Instance
*
*/
typedef void ws_pae_lib_supp_deleted(void *instance);

/**
* ws_pae_lib_supp_list_add removes entry from supplicant list
*
* \param instance Instance
* \param supp_list supplicant list
* \param entry entry
* \param supp_deleted callback to call on supplicant delete
*
* \return < 0 failure
* \return >= 0 success
*/
int8_t ws_pae_lib_supp_list_remove(supp_list_t *supp_list, supp_entry_t *entry);
int8_t ws_pae_lib_supp_list_remove(void *instance, supp_list_t *supp_list, supp_entry_t *supp, ws_pae_lib_supp_deleted supp_deleted);

/**
* ws_pae_lib_supp_list_entry_eui_64_get gets entry from supplicant list based on EUI-64
Expand Down Expand Up @@ -249,11 +259,12 @@ void ws_pae_lib_supp_list_delete(supp_list_t *supp_list);
* \param inactive_supp_list list of inactive supplicants
* \param ticks timer ticks
* \param timeout callback to call on timeout
* \param supp_deleted callback to call on supplicant delete
*
* \return true timer needs still to be running
* \return false timer can be stopped
*/
bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout);
bool ws_pae_lib_supp_list_timer_update(void *instance, supp_list_t *active_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout, ws_pae_lib_supp_deleted supp_deleted);

/**
* ws_pae_lib_supp_list_slow_timer_update updates slow timer on supplicant list
Expand Down Expand Up @@ -336,20 +347,23 @@ void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t *
* \param instance Instance
* \param active_supp_list list of active supplicants
* \param entry supplicant entry
* \param supp_deleted callback to call on supplicant delete
*
*/
void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry);
void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_list, supp_entry_t *entry, ws_pae_lib_supp_deleted supp_deleted);

/**
* ws_pae_lib_supp_list_purge purge inactive supplicants list
*
* \param instance Instance
* \param active_supp_list list of active supplicants
* \param max_number maximum number of supplicant entries, can be set to 0 in combination with max_purge
* to free list entries even when maximum number supplicant entries has not been reached
* \param max_purge maximum number of supplicants to purge in one call, 0 means not limited
* \param supp_deleted callback to call on supplicant delete
*
*/
void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge);
void ws_pae_lib_supp_list_purge(void *instance, supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge, ws_pae_lib_supp_deleted supp_deleted);

/**
* ws_pae_lib_supp_list_kmp_count counts the number of KMPs of a certain type in a list of supplicants
Expand All @@ -363,26 +377,27 @@ void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, uint16_t max_numb
uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type);

/**
* ws_pae_lib_supp_list_kmp_receive_check check if received message is for this KMP in a list of supplicants
* ws_pae_lib_supp_list_entry_is_in_list checks if the entry is in the list
*
* \param supp_list list of supplicants
* \param pdu pdu
* \param size pdu size
* \param searched_entry entry that is searched
*
* \return KMP api for the received message
* \return TRUE entry is in list, FALSE otherwise
*
*/
kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const void *pdu, uint16_t size);
bool ws_pae_lib_supp_list_entry_is_in_list(supp_list_t *supp_list, supp_entry_t *searched_entry);

/**
* ws_pae_lib_supp_list_entry_retry_timer_get checks if some supplicant has retry timer running
* ws_pae_lib_supp_list_kmp_receive_check check if received message is for this KMP in a list of supplicants
*
* \param supp_list list of supplicants
* \param pdu pdu
* \param size pdu size
*
* \return supplicant with retry timer running or NULL if no supplicants with timer running
* \return KMP api for the received message
*
*/
supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list);
kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const void *pdu, uint16_t size);

/**
* ws_pae_lib_shared_comp_list_init init shared component list
Expand Down

0 comments on commit 16e3402

Please sign in to comment.