Skip to content

Commit

Permalink
Added trigger to authenticator to re-start delayed EAP-TLS
Browse files Browse the repository at this point in the history
If authenticator has delayed supplicant EAP-TLS negotiation because
limit for simultaneous EAP-TLS negotiations has been reached,
authenticator can now continue delayed EAP-TLS negotiation. There
is time window (60 seconds after original request) when the
continue is made. This ensures that supplicant is still waiting
for EAP-TLS to start when authenticator triggers the negotiation.
  • Loading branch information
Mika Leppänen committed Apr 2, 2019
1 parent 30c538a commit e9759e8
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 12 deletions.
54 changes: 44 additions & 10 deletions source/6LoWPAN/ws/ws_pae_auth.c
Expand Up @@ -59,6 +59,10 @@
// Maximum number of simultaneous EAP-TLS negotiations
#define MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS 3

/* If EAP-TLS is delayed due to simultaneous negotiations limit, defines how
long to wait for previous negotiation to complete */
#define EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT 60 * 10 // 60 seconds

typedef struct {
ns_list_link_t link; /**< Link */
kmp_service_t *kmp_service; /**< KMP service */
Expand Down Expand Up @@ -100,6 +104,7 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_
static void ws_pae_auth_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e result);
static void ws_pae_auth_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr);
static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys);
static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry);
static kmp_type_e ws_pae_auth_next_protocol_get(supp_entry_t *supp_entry);
static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry);
static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp);
Expand Down Expand Up @@ -834,6 +839,20 @@ static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e
// Should not be possible
return;
}
kmp_service_t *service = kmp_api_service_get(kmp);
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
if (!pae_auth) {
// Should not be possible
return;
}

ws_pae_auth_next_kmp_trigger(pae_auth, supp_entry);
}

static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry)
{
// Disables KMP retry timer
supp_entry->retry_ticks = 0;

// Get next protocol based on what keys supplicant has
kmp_type_e next_type = ws_pae_auth_next_protocol_get(supp_entry);
Expand All @@ -846,19 +865,17 @@ static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e
// Increases waiting time for supplicant authentication
ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_FOR_AUTHENTICATION_TICKS);

kmp_service_t *service = kmp_api_service_get(kmp);
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
if (!pae_auth) {
return;
}

if (next_type == IEEE_802_1X_MKA) {
/* For EAP-TLS, limits the number of ongoing negotiations. If limit
is reached, supplicant must re-send initial EAPOL-Key to try again
using its trickle schedule */
is reached, authenticator does not initiate EAP-TLS right away.
If previous EAP-TLS negotiation completes before negotiation
trigger timeout, authenticator initiates EAP-TLS towards
supplicant. Otherwise supplicant must re-send initial EAPOL-Key
to try again using its trickle schedule */
uint16_t ongoing_eap_tls_cnt = ws_pae_lib_supp_list_kmp_count(&pae_auth->active_supp_list, IEEE_802_1X_MKA);
if (ongoing_eap_tls_cnt >= MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS) {
tr_info("EAP-TLS max ongoing reached, count %i, ignored: eui-64: %s", ongoing_eap_tls_cnt, trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
supp_entry->retry_ticks = EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT;
tr_info("EAP-TLS max ongoing reached, count %i, delayed: eui-64: %s", ongoing_eap_tls_cnt, trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
return;
}
}
Expand All @@ -877,7 +894,7 @@ static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e
return;
}
// Create TLS instance */
if (ws_pae_auth_kmp_create_and_start(service, TLS_PROT, supp_entry) == NULL) {
if (ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, TLS_PROT, supp_entry) == NULL) {
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
return;
}
Expand Down Expand Up @@ -970,8 +987,25 @@ static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp)
return;
}

pae_auth_t *pae_auth = NULL;
supp_entry_t *retry_supp = NULL;
// When EAP-TLS completes check if there are other supplicants that have requested it lately
if (kmp_api_type_get(kmp) == IEEE_802_1X_MKA) {
kmp_service_t *service = kmp_api_service_get(kmp);
pae_auth = ws_pae_auth_by_kmp_service_get(service);
if (pae_auth) {
retry_supp = ws_pae_lib_supp_list_entry_retry_timer_get(&pae_auth->active_supp_list);
}
}

// Delete KMP
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, kmp);

if (retry_supp) {
tr_info("PAE next KMP trigger, eui-64: %s", trace_array(kmp_address_eui_64_get(retry_supp->addr), 8));
ws_pae_auth_next_kmp_trigger(pae_auth, retry_supp);
}

}

#endif /* HAVE_PAE_AUTH */
Expand Down
25 changes: 25 additions & 0 deletions source/6LoWPAN/ws/ws_pae_lib.c
Expand Up @@ -228,6 +228,7 @@ void ws_pae_lib_supp_init(supp_entry_t *entry)
entry->addr = 0;
memset(&entry->sec_keys, 0, sizeof(sec_prot_keys_t));
entry->ticks = 0;
entry->retry_ticks = 0;
entry->active = true;
entry->access_revoked = false;
}
Expand All @@ -250,9 +251,17 @@ bool ws_pae_lib_supp_timer_update(supp_entry_t *entry, uint16_t ticks, ws_pae_li
entry->ticks -= ticks;
} else {
entry->ticks = 0;
entry->retry_ticks = 0;
}
}

// Updates retry timer
if (entry->retry_ticks > ticks) {
entry->retry_ticks -= ticks;
} else {
entry->retry_ticks = 0;
}

return keep_timer_running;
}

Expand Down Expand Up @@ -322,4 +331,20 @@ uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type)
return kmp_count;
}

supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list)
{
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;
}
}
}

return retry_supp;
}

#endif /* HAVE_WS */
15 changes: 13 additions & 2 deletions source/6LoWPAN/ws/ws_pae_lib.h
Expand Up @@ -36,8 +36,9 @@ typedef struct {
kmp_addr_t *addr; /**< EUI-64 (Relay IP address, Relay port) */
sec_prot_keys_t sec_keys; /**< Security keys */
uint32_t ticks; /**< Ticks */
bool active; /**< Is active */
bool access_revoked; /**< Nodes access is revoked */
uint16_t retry_ticks; /**< Retry ticks */
bool active : 1; /**< Is active */
bool access_revoked : 1; /**< Nodes access is revoked */
ns_list_link_t link; /**< Link */
} supp_entry_t;

Expand Down Expand Up @@ -290,4 +291,14 @@ void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t
*/
uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type);

/**
* ws_pae_lib_supp_list_entry_retry_timer_get checks if some supplicant has retry timer running
*
* \param supp_list list of supplicants
*
* \return supplicant with retry timer running or NULL if no supplicants with timer running
*
*/
supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list);

#endif /* WS_PAE_AUTH_H_ */

0 comments on commit e9759e8

Please sign in to comment.