SAE: Check Status Code in Authentication frames
authorJouni Malinen <j@w1.fi>
Sun, 14 Dec 2014 21:52:02 +0000 (23:52 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 14 Dec 2014 22:06:56 +0000 (00:06 +0200)
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 <j@w1.fi>
src/ap/ieee802_11.c

index 8a51b33..09c398a 100644 (file)
@@ -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 */
        }