]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
PASN: Add support for comeback flow in AP mode
authorIlan Peer <ilan.peer@intel.com>
Sun, 21 Mar 2021 11:55:08 +0000 (13:55 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 21 Mar 2021 16:01:27 +0000 (18:01 +0200)
Reuse the SAE anti-clogging token implementation to support similar
design with the PASN comeback cookie.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
hostapd/config_file.c
hostapd/hostapd.conf
src/ap/ap_config.c
src/ap/ap_config.h
src/ap/ieee802_11.c

index fd9bc0e9fced17eff0a816c490c1aff74de7284f..d73a737821b2f9fc205da392a3f245925a03084f 100644 (file)
@@ -4675,6 +4675,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                                   line, pos);
                        return 1;
                }
+       } else if (os_strcmp(buf, "pasn_comeback_after") == 0) {
+               bss->pasn_comeback_after = atoi(pos);
 #endif /* CONFIG_PASN */
        } else {
                wpa_printf(MSG_ERROR,
index d19db5a154f830c0740833c2244732f4afc02a52..7932cb862f48e9a55124463bdbae801fcf179320 100644 (file)
@@ -2051,6 +2051,13 @@ own_ip_addr=127.0.0.1
 # http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-10
 #pasn_groups=19 20 21
 
+# PASN comeback after time in TUs
+# In case the AP is temporarily unable to handle a PASN authentication exchange
+# due to a too large number of parallel operations, this value indicates to the
+# peer after how many TUs it can try the PASN exchange again.
+# (default: 10 TUs)
+#pasn_comeback_after=10
+
 ##### IEEE 802.11r configuration ##############################################
 
 # Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
index 452386b7e5de563faabbf10ffa05e4a8695d42b6..7b6249bbe5cff9d59d2425f6dcd6e3af603f6b7a 100644 (file)
@@ -165,6 +165,11 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
 #ifdef CONFIG_TESTING_OPTIONS
        bss->sae_commit_status = -1;
 #endif /* CONFIG_TESTING_OPTIONS */
+
+#ifdef CONFIG_PASN
+       /* comeback after 10 TUs */
+       bss->pasn_comeback_after = 10;
+#endif /* CONFIG_PASN */
 }
 
 
index 8aeb03107af21d98b43cc986801c337372d6c288..f86cf26ca322e06cee69d13daa52c10b6607ce76 100644 (file)
@@ -880,6 +880,12 @@ struct hostapd_bss_config {
 #endif /* CONFIG_TESTING_OPTIONS */
 
        int *pasn_groups;
+
+       /*
+        * The time in TUs after which the non-AP STA is requested to retry the
+        * PASN authentication in case there are too many parallel operations.
+        */
+       u16 pasn_comeback_after;
 #endif /* CONFIG_PASN */
 
        unsigned int unsol_bcast_probe_resp_interval;
index 72d102f44e2120fde6ba5fda39eb990a5249c532..877d03e3aa5ac50d41a227a8904a96e5b46cb7c7 100644 (file)
@@ -702,13 +702,15 @@ static int use_anti_clogging(struct hostapd_data *hapd)
 
        for (sta = hapd->sta_list; sta; sta = sta->next) {
 #ifdef CONFIG_SAE
-               if (!sta->sae)
-                       continue;
-               if (sta->sae->state != SAE_COMMITTED &&
-                   sta->sae->state != SAE_CONFIRMED)
-                       continue;
-               open++;
+               if (sta->sae &&
+                   (sta->sae->state == SAE_COMMITTED ||
+                    sta->sae->state == SAE_CONFIRMED))
+                       open++;
 #endif /* CONFIG_SAE */
+#ifdef CONFIG_PASN
+               if (sta->pasn && sta->pasn->ecdh)
+                       open++;
+#endif /* CONFIG_PASN */
                if (open >= hapd->conf->anti_clogging_threshold)
                        return 1;
        }
@@ -806,7 +808,8 @@ static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
        if (buf == NULL)
                return NULL;
 
-       wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
+       if (group)
+               wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
 
        if (h2e) {
                /* Encapsulate Anti-clogging Token field in a container IE */
@@ -2891,6 +2894,54 @@ pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta,
 }
 
 
+static void handle_auth_pasn_comeback(struct hostapd_data *hapd,
+                                     struct sta_info *sta, u16 group)
+{
+       struct wpabuf *buf, *comeback;
+       int ret;
+
+       wpa_printf(MSG_DEBUG,
+                  "PASN: Building comeback frame 2. Comeback after=%u",
+                  hapd->conf->pasn_comeback_after);
+
+       buf = wpabuf_alloc(1500);
+       if (!buf)
+               return;
+
+       wpa_pasn_build_auth_header(buf, hapd->own_addr, hapd->own_addr,
+                                  sta->addr, 2,
+                                  WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY);
+
+       /*
+        * Do not include the group as a part of the token since it is not going
+        * to be used.
+        */
+       comeback = auth_build_token_req(hapd, 0, sta->addr, 0);
+       if (!comeback) {
+               wpa_printf(MSG_DEBUG,
+                          "PASN: Failed sending auth with comeback");
+               wpabuf_free(buf);
+               return;
+       }
+
+       wpa_pasn_add_parameter_ie(buf, group,
+                                 WPA_PASN_WRAPPED_DATA_NO,
+                                 NULL, 0, comeback,
+                                 hapd->conf->pasn_comeback_after);
+       wpabuf_free(comeback);
+
+       wpa_printf(MSG_DEBUG,
+                  "PASN: comeback: STA=" MACSTR, MAC2STR(sta->addr));
+
+       ret = hostapd_drv_send_mlme(hapd, wpabuf_head(buf), wpabuf_len(buf), 0,
+                                   NULL, 0, 0);
+       if (ret)
+               wpa_printf(MSG_INFO, "PASN: Failed to send comeback frame 2");
+
+       wpabuf_free(buf);
+}
+
+
 static int handle_auth_pasn_resp(struct hostapd_data *hapd,
                                 struct sta_info *sta,
                                 struct rsn_pmksa_cache_entry *pmksa,
@@ -3133,6 +3184,25 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta,
                goto send_resp;
        }
 
+       if (pasn_params.comeback) {
+               wpa_printf(MSG_DEBUG, "PASN: Checking peer comeback token");
+
+               ret = check_comeback_token(hapd, sta->addr,
+                                          pasn_params.comeback,
+                                          pasn_params.comeback_len);
+
+               if (ret) {
+                       wpa_printf(MSG_DEBUG, "PASN: Invalid comeback token");
+                       status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                       goto send_resp;
+               }
+       } else if (use_anti_clogging(hapd)) {
+               wpa_printf(MSG_DEBUG, "PASN: Respond with comeback");
+               handle_auth_pasn_comeback(hapd, sta, pasn_params.group);
+               ap_free_sta(hapd, sta);
+               return;
+       }
+
        sta->pasn->ecdh = crypto_ecdh_init(pasn_params.group);
        if (!sta->pasn->ecdh) {
                wpa_printf(MSG_DEBUG, "PASN: Failed to init ECDH");