diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 49f0ddf54..7ee3c8771 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -247,6 +247,7 @@ struct hostapd_data { #ifdef CONFIG_MESH int num_plinks; int max_plinks; + void (*mesh_sta_free_cb)(struct sta_info *sta); #endif /* CONFIG_MESH */ #ifdef CONFIG_SQLITE diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index ec0e493c3..c48222e40 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -227,6 +227,11 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) set_beacon++; #endif /* NEED_AP_MLME && CONFIG_IEEE80211N */ +#ifdef CONFIG_MESH + if (hapd->mesh_sta_free_cb) + hapd->mesh_sta_free_cb(sta); +#endif /* CONFIG_MESH */ + if (set_beacon) ieee802_11_set_beacons(hapd->iface); diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 8ba3ff23c..76e34e405 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -66,6 +66,7 @@ struct sta_info { u8 aek[32]; /* SHA256 digest length */ u8 mtk[16]; u8 mgtk[16]; + u8 sae_auth_retry; #endif /* CONFIG_MESH */ unsigned int nonerp_set:1; diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index 1ad4bf674..6439d645c 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -147,6 +147,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, bss->driver = wpa_s->driver; bss->drv_priv = wpa_s->drv_priv; bss->iface = ifmsh; + bss->mesh_sta_free_cb = mesh_mpm_free_sta; wpa_s->assoc_freq = ssid->frequency; wpa_s->current_ssid = ssid; diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index de6c3ebb9..e440d4ffb 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -908,3 +908,11 @@ void mesh_mpm_action_rx(struct wpa_supplicant *wpa_s, } mesh_mpm_fsm(wpa_s, sta, event); } + + +/* called by ap_free_sta */ +void mesh_mpm_free_sta(struct sta_info *sta) +{ + eloop_cancel_timeout(plink_timer, ELOOP_ALL_CTX, sta); + eloop_cancel_timeout(mesh_auth_timer, ELOOP_ALL_CTX, sta); +} diff --git a/wpa_supplicant/mesh_mpm.h b/wpa_supplicant/mesh_mpm.h index 056cedd5d..2f7f6a783 100644 --- a/wpa_supplicant/mesh_mpm.h +++ b/wpa_supplicant/mesh_mpm.h @@ -14,6 +14,7 @@ void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr, struct ieee802_11_elems *elems); void mesh_mpm_deinit(struct wpa_supplicant *wpa_s, struct hostapd_iface *ifmsh); void mesh_mpm_auth_peer(struct wpa_supplicant *wpa_s, const u8 *addr); +void mesh_mpm_free_sta(struct sta_info *sta); #ifdef CONFIG_MESH diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c index ecc639312..4ee3431dc 100644 --- a/wpa_supplicant/mesh_rsn.c +++ b/wpa_supplicant/mesh_rsn.c @@ -9,6 +9,7 @@ #include "utils/includes.h" #include "utils/common.h" +#include "utils/eloop.h" #include "crypto/sha256.h" #include "crypto/random.h" #include "crypto/aes.h" @@ -23,6 +24,29 @@ #include "mesh_mpm.h" #include "mesh_rsn.h" +#define MESH_AUTH_TIMEOUT 10 +#define MESH_AUTH_RETRY 3 + +void mesh_auth_timer(void *eloop_ctx, void *user_data) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + struct sta_info *sta = user_data; + + if (sta->sae->state != SAE_ACCEPTED) { + wpa_printf(MSG_DEBUG, "AUTH: Re-authenticate with " MACSTR + " (attempt %d) ", + MAC2STR(sta->addr), sta->sae_auth_retry); + if (sta->sae_auth_retry < MESH_AUTH_RETRY) { + mesh_rsn_auth_sae_sta(wpa_s, sta); + } else { + /* block the STA if exceeded the number of attempts */ + sta->plink_state = PLINK_BLOCKED; + sta->sae->state = SAE_NOTHING; + } + sta->sae_auth_retry++; + } +} + static void auth_logger(void *ctx, const u8 *addr, logger_level level, const char *txt) @@ -81,10 +105,17 @@ static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, static int auth_start_ampe(void *ctx, const u8 *addr) { struct mesh_rsn *mesh_rsn = ctx; + struct hostapd_data *hapd; + struct sta_info *sta; if (mesh_rsn->wpa_s->current_ssid->mode != WPAS_MODE_MESH) return -1; + hapd = mesh_rsn->wpa_s->ifmsh->bss[0]; + sta = ap_get_sta(hapd, addr); + if (sta) + eloop_cancel_timeout(mesh_auth_timer, mesh_rsn->wpa_s, sta); + mesh_mpm_auth_peer(mesh_rsn->wpa_s, addr); return 0; } @@ -296,6 +327,7 @@ int mesh_rsn_auth_sae_sta(struct wpa_supplicant *wpa_s, { struct wpa_ssid *ssid = wpa_s->current_ssid; struct wpabuf *buf; + unsigned int rnd; if (!sta->sae) { sta->sae = os_zalloc(sizeof(*sta->sae)); @@ -317,6 +349,9 @@ int mesh_rsn_auth_sae_sta(struct wpa_supplicant *wpa_s, mesh_rsn_send_auth(wpa_s, sta->addr, wpa_s->own_addr, 1, WLAN_STATUS_SUCCESS, buf); + rnd = rand() % MESH_AUTH_TIMEOUT; + eloop_register_timeout(MESH_AUTH_TIMEOUT + rnd, 0, mesh_auth_timer, + wpa_s, sta); wpabuf_free(buf); return 0; diff --git a/wpa_supplicant/mesh_rsn.h b/wpa_supplicant/mesh_rsn.h index 2dcf76dba..b1471b2de 100644 --- a/wpa_supplicant/mesh_rsn.h +++ b/wpa_supplicant/mesh_rsn.h @@ -31,5 +31,6 @@ int mesh_rsn_protect_frame(struct mesh_rsn *rsn, struct sta_info *sta, int mesh_rsn_process_ampe(struct wpa_supplicant *wpa_s, struct sta_info *sta, struct ieee802_11_elems *elems, const u8 *cat, const u8 *start, size_t elems_len); +void mesh_auth_timer(void *eloop_ctx, void *user_data); #endif /* MESH_RSN_H */