From afa2ffb41344db90d41958ce5d2aeae1d741892c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 14 Dec 2014 23:52:02 +0200 Subject: [PATCH] SAE: Check Status Code in Authentication frames While other authentication algorithms mark Status Code as being Reserved in the case of the transaction number 1, SAE does not. Check that the Status Code indicates success before creating SAE state. In addition, fix the mesh anti-clogging token request parsing on big endian CPUs. Transaction number 2 (confirm) can also have non-zero Status Code to report an error. Those should be processed, but not replied to with yet another error message. This could happen in mesh case. Avoid a loop of error messages by dropping the non-success case without additional response. In addition, don't reply to unknown transaction numbers if the status code is non-zero. This avoids a loop of error messages if an invalid frame where to be injected (or unlikely corruption were to occur). Signed-off-by: Jouni Malinen --- src/ap/ieee802_11.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 8a51b33be..09c398ab1 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -620,13 +620,13 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta, static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, const struct ieee80211_mgmt *mgmt, size_t len, - u8 auth_transaction) + u16 auth_transaction, u16 status_code) { u16 resp = WLAN_STATUS_SUCCESS; struct wpabuf *data = NULL; if (!sta->sae) { - if (auth_transaction != 1) + if (auth_transaction != 1 || status_code != WLAN_STATUS_SUCCESS) return; sta->sae = os_zalloc(sizeof(*sta->sae)); if (sta->sae == NULL) @@ -639,11 +639,12 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, size_t token_len = 0; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, - "start SAE authentication (RX commit)"); + "start SAE authentication (RX commit, status=%u)", + status_code); if ((hapd->conf->mesh & MESH_ENABLED) && - mgmt->u.auth.status_code == - WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ && sta->sae->tmp) { + status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ && + sta->sae->tmp) { pos = mgmt->u.auth.variable; end = ((const u8 *) mgmt) + len; if (pos + sizeof(le16) > end) { @@ -687,6 +688,9 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, return; } + if (status_code != WLAN_STATUS_SUCCESS) + return; + resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable, ((const u8 *) mgmt) + len - mgmt->u.auth.variable, &token, @@ -718,7 +722,10 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, } else if (auth_transaction == 2) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, - "SAE authentication (RX confirm)"); + "SAE authentication (RX confirm, status=%u)", + status_code); + if (status_code != WLAN_STATUS_SUCCESS) + return; if (sta->sae->state >= SAE_CONFIRMED || !(hapd->conf->mesh & MESH_ENABLED)) { if (sae_check_confirm(sta->sae, mgmt->u.auth.variable, @@ -729,12 +736,13 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, } } resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction); - } else { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, - "unexpected SAE authentication transaction %u", - auth_transaction); + "unexpected SAE authentication transaction %u (status=%u)", + auth_transaction, status_code); + if (status_code != WLAN_STATUS_SUCCESS) + return; resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; } @@ -977,7 +985,8 @@ static void handle_auth(struct hostapd_data *hapd, #ifdef CONFIG_SAE case WLAN_AUTH_SAE: #ifdef CONFIG_MESH - if (hapd->conf->mesh & MESH_ENABLED) { + if (status_code == WLAN_STATUS_SUCCESS && + hapd->conf->mesh & MESH_ENABLED) { if (sta->wpa_sm == NULL) sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, @@ -990,7 +999,8 @@ static void handle_auth(struct hostapd_data *hapd, } } #endif /* CONFIG_MESH */ - handle_auth_sae(hapd, sta, mgmt, len, auth_transaction); + handle_auth_sae(hapd, sta, mgmt, len, auth_transaction, + status_code); return; #endif /* CONFIG_SAE */ }