]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE: More robust password identifier checks for AP mode
authorJouni Malinen <quic_jouni@quicinc.com>
Wed, 30 Oct 2024 10:30:35 +0000 (12:30 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 31 Oct 2024 09:13:24 +0000 (11:13 +0200)
Do not update the more persistent sae->tmp->pw_id value based on each
received SAE commit message before having successfully processed the
commit. In particular, this includes checking for a matcing password
identifier in cases where the AP has enabled one or more SAE passwords
with identifiers.

A per-received message sae->tmp->parsed_pw_id is used during parsing and
processing of each individual message and sae->tmp->pw_id is set only
after having successfully processed a commit message. This avoids
getting sae->tmp->pw_id being bound to an unknown value.

An earlier commit addressed some of the sequences that could have this
issue, but it missed some cases. This newer more robust version covers
what the earlier commit did, so that part can be removed with the new
design.

Fixes: 761041b18ab2 ("SAE: Free password identifier if SAE commit is rejected due to it")
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
src/ap/ieee802_11.c
src/common/sae.c
src/common/sae.h

index 98609c013e74e89b6974e993572a062834e6db49..8115b68cce08d7784358447cbaaf08e59df45345 100644 (file)
@@ -621,7 +621,8 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
 #endif /* CONFIG_IEEE80211BE */
 
        if (sta->sae->tmp) {
-               rx_id = sta->sae->tmp->pw_id;
+               rx_id = sta->sae->tmp->parsed_pw_id ?
+                       sta->sae->tmp->parsed_pw_id : sta->sae->tmp->pw_id;
                use_pt = sta->sae->h2e;
 #ifdef CONFIG_SAE_PK
                os_memcpy(sta->sae->tmp->own_addr, own_addr, ETH_ALEN);
@@ -713,7 +714,8 @@ static int auth_sae_send_commit(struct hostapd_data *hapd,
        u16 status;
 
        data = auth_build_sae_commit(hapd, sta, update, status_code);
-       if (!data && sta->sae->tmp && sta->sae->tmp->pw_id)
+       if (!data && sta->sae->tmp &&
+           (sta->sae->tmp->pw_id || sta->sae->tmp->parsed_pw_id))
                return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
        if (data == NULL)
                return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -1002,7 +1004,9 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
        switch (sta->sae->state) {
        case SAE_NOTHING:
                if (auth_transaction == 1) {
-                       if (sta->sae->tmp) {
+                       struct sae_temporary_data *tmp = sta->sae->tmp;
+
+                       if (tmp) {
                                sta->sae->h2e =
                                        (status_code ==
                                         WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
@@ -1012,8 +1016,21 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
                        }
                        ret = auth_sae_send_commit(hapd, sta,
                                                   !allow_reuse, status_code);
+                       if (ret == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER)
+                               wpa_msg(hapd->msg_ctx, MSG_INFO,
+                                       WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER
+                                       MACSTR, MAC2STR(sta->addr));
                        if (ret)
                                return ret;
+
+                       if (tmp && tmp->parsed_pw_id && !tmp->pw_id) {
+                               tmp->pw_id = tmp->parsed_pw_id;
+                               tmp->parsed_pw_id = NULL;
+                               wpa_printf(MSG_DEBUG,
+                                          "SAE: Known Password Identifier bound to this STA: '%s'",
+                                          tmp->pw_id);
+                       }
+
                        sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
 
                        if (sae_process_commit(sta->sae) < 0)
@@ -1637,14 +1654,6 @@ reply:
                                data ? wpabuf_head(data) : (u8 *) "",
                                data ? wpabuf_len(data) : 0, "auth-sae");
                sae_sme_send_external_auth_status(hapd, sta, resp);
-               if (sta->sae && sta->sae->tmp && sta->sae->tmp->pw_id &&
-                   resp == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER &&
-                   auth_transaction == 1) {
-                       wpa_printf(MSG_DEBUG,
-                                  "SAE: Clear stored password identifier since this SAE commit was not accepted");
-                       os_free(sta->sae->tmp->pw_id);
-                       sta->sae->tmp->pw_id = NULL;
-               }
        }
 
 remove_sta:
index c93d3a6d2ae05e037ffdf0710f9be7f6a5434e1a..6b06473e1e96e810cb188e8c48ade437d9845c71 100644 (file)
@@ -114,6 +114,7 @@ void sae_clear_temp_data(struct sae_data *sae)
        wpabuf_free(tmp->own_rejected_groups);
        wpabuf_free(tmp->peer_rejected_groups);
        os_free(tmp->pw_id);
+       os_free(tmp->parsed_pw_id);
        bin_clear_free(tmp, sizeof(*tmp));
        sae->tmp = NULL;
 }
@@ -2061,8 +2062,8 @@ static int sae_parse_password_identifier(struct sae_data *sae,
                                   sae->tmp->pw_id);
                        return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
                }
-               os_free(sae->tmp->pw_id);
-               sae->tmp->pw_id = NULL;
+               os_free(sae->tmp->parsed_pw_id);
+               sae->tmp->parsed_pw_id = NULL;
                return WLAN_STATUS_SUCCESS; /* No Password Identifier */
        }
 
@@ -2089,14 +2090,14 @@ static int sae_parse_password_identifier(struct sae_data *sae,
                return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
        }
 
-       os_free(sae->tmp->pw_id);
-       sae->tmp->pw_id = os_malloc(len + 1);
-       if (!sae->tmp->pw_id)
+       os_free(sae->tmp->parsed_pw_id);
+       sae->tmp->parsed_pw_id = os_malloc(len + 1);
+       if (!sae->tmp->parsed_pw_id)
                return WLAN_STATUS_UNSPECIFIED_FAILURE;
-       os_memcpy(sae->tmp->pw_id, epos, len);
-       sae->tmp->pw_id[len] = '\0';
+       os_memcpy(sae->tmp->parsed_pw_id, epos, len);
+       sae->tmp->parsed_pw_id[len] = '\0';
        wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier",
-                         sae->tmp->pw_id, len);
+                         sae->tmp->parsed_pw_id, len);
        *pos = epos + len;
        return WLAN_STATUS_SUCCESS;
 }
index 3a83c3be513fedba5a1a83cede64e3d00084b19e..8f74353bebf76ba3985005c3f20cb1a33dc81762 100644 (file)
@@ -59,6 +59,7 @@ struct sae_temporary_data {
        struct crypto_bignum *order_buf;
        struct wpabuf *anti_clogging_token;
        char *pw_id;
+       char *parsed_pw_id;
        int vlan_id;
        u8 bssid[ETH_ALEN];
        struct wpabuf *own_rejected_groups;