Browse Source

mesh: Add timer for SAE authentication in RSN mesh

Add timer to do SAE re-authentication with number of tries defined
by MESH_AUTH_RETRY and timeout defined by MESH_AUTH_TIMEOUT.

Ignoring the sending of reply message on "SAE confirm before commit"
to avoid "ping-pong" issues with other mesh nodes. This is obvious when
number of mesh nodes in MBSS reaching 6.

Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@gmail.com>
Signed-off-by: Bob Copeland <me@bobcopeland.com>
Chun-Yeow Yeoh 10 years ago
parent
commit
c596f3f083

+ 1 - 0
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

+ 5 - 0
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);
 

+ 1 - 0
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;

+ 1 - 0
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;
 

+ 8 - 0
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);
+}

+ 1 - 0
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
 

+ 35 - 0
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;

+ 1 - 0
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 */