]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE: Process received commit message through a queue
authorJouni Malinen <jouni@codeaurora.org>
Fri, 1 Mar 2019 17:54:51 +0000 (19:54 +0200)
committerJouni Malinen <j@w1.fi>
Wed, 6 Mar 2019 11:06:50 +0000 (13:06 +0200)
This allows better control of processing new SAE sessions so that other
operations can be given higher priority during bursts of SAE requests,
e.g., during a potential DoS attack. The receive commit messages are
queued (up to maximum of 15 entries) and processed from eloop callback.
If the queue has multiple pending entries, more wait time is used to go
through the each new entry to reduce heavy CPU load from SAE processing.

Enable anti-clogging token use also based on the pending commit message
queue and not only based on the already started sessions.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
src/ap/hostapd.c
src/ap/hostapd.h
src/ap/ieee802_11.c
src/ap/ieee802_11.h

index 60943cd02db4e8a12c81b0ef50bebf4fb13c77e2..849d20bec54191fa949d4d6d21caf1eba5a988ee 100644 (file)
@@ -417,6 +417,20 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
 
        hostapd_clean_rrm(hapd);
        fils_hlp_deinit(hapd);
+
+#ifdef CONFIG_SAE
+       {
+               struct hostapd_sae_commit_queue *q;
+
+               while ((q = dl_list_first(&hapd->sae_commit_queue,
+                                         struct hostapd_sae_commit_queue,
+                                         list))) {
+                       dl_list_del(&q->list);
+                       os_free(q);
+               }
+       }
+       eloop_cancel_timeout(auth_sae_process_commit, hapd, NULL);
+#endif /* CONFIG_SAE */
 }
 
 
@@ -2150,6 +2164,9 @@ hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
        dl_list_init(&hapd->l2_queue);
        dl_list_init(&hapd->l2_oui_queue);
 #endif /* CONFIG_IEEE80211R_AP */
+#ifdef CONFIG_SAE
+       dl_list_init(&hapd->sae_commit_queue);
+#endif /* CONFIG_SAE */
 
        return hapd;
 }
index d304c1171810cf81fba9b94f4272ba82efac71ad..733f3f22a59e42be560fa3ac9b25cd951d1c5124 100644 (file)
@@ -129,6 +129,13 @@ struct hostapd_neighbor_entry {
        int stationary;
 };
 
+struct hostapd_sae_commit_queue {
+       struct dl_list list;
+       int rssi;
+       size_t len;
+       u8 msg[];
+};
+
 /**
  * struct hostapd_data - hostapd per-BSS data structure
  */
@@ -308,6 +315,7 @@ struct hostapd_data {
        u8 sae_token_key[8];
        struct os_reltime last_sae_token_key_update;
        int dot11RSNASAERetransPeriod; /* msec */
+       struct dl_list sae_commit_queue; /* struct hostapd_sae_commit_queue */
 #endif /* CONFIG_SAE */
 
 #ifdef CONFIG_TESTING_OPTIONS
index 63dcb111adf621e0e4d3ee3b8b5feb34275e4286..0da1d42fc0f770bd1ea7f76b65bb2a93c5eeaf6c 100644 (file)
@@ -62,6 +62,9 @@ prepare_auth_resp_fils(struct hostapd_data *hapd,
                       const u8 *msk, size_t msk_len,
                       int *is_pub);
 #endif /* CONFIG_FILS */
+static void handle_auth(struct hostapd_data *hapd,
+                       const struct ieee80211_mgmt *mgmt, size_t len,
+                       int rssi, int from_queue);
 
 
 u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid)
@@ -518,6 +521,13 @@ static int use_sae_anti_clogging(struct hostapd_data *hapd)
                        return 1;
        }
 
+       /* In addition to already existing open SAE sessions, check whether
+        * there are enough pending commit messages in the processing queue to
+        * potentially result in too many open sessions. */
+       if (open + dl_list_len(&hapd->sae_commit_queue) >=
+           hapd->conf->sae_anti_clogging_threshold)
+               return 1;
+
        return 0;
 }
 
@@ -1176,6 +1186,62 @@ int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta)
        return 0;
 }
 
+
+void auth_sae_process_commit(void *eloop_ctx, void *user_ctx)
+{
+       struct hostapd_data *hapd = eloop_ctx;
+       struct hostapd_sae_commit_queue *q;
+       unsigned int queue_len;
+
+       q = dl_list_first(&hapd->sae_commit_queue,
+                         struct hostapd_sae_commit_queue, list);
+       if (!q)
+               return;
+       wpa_printf(MSG_DEBUG,
+                  "SAE: Process next available commit message from queue");
+       dl_list_del(&q->list);
+       handle_auth(hapd, (const struct ieee80211_mgmt *) q->msg, q->len,
+                   q->rssi, 1);
+       os_free(q);
+
+       if (eloop_is_timeout_registered(auth_sae_process_commit, hapd, NULL))
+               return;
+       queue_len = dl_list_len(&hapd->sae_commit_queue);
+       eloop_register_timeout(0, queue_len * 50000, auth_sae_process_commit,
+                              hapd, NULL);
+}
+
+
+static void auth_sae_queue_commit(struct hostapd_data *hapd,
+                                 const struct ieee80211_mgmt *mgmt, size_t len,
+                                 int rssi)
+{
+       struct hostapd_sae_commit_queue *q;
+       unsigned int queue_len;
+
+       queue_len = dl_list_len(&hapd->sae_commit_queue);
+       if (queue_len >= 15) {
+               wpa_printf(MSG_DEBUG,
+                          "SAE: No more room in commit message queue - drop the new frame from "
+                          MACSTR, MAC2STR(mgmt->sa));
+               return;
+       }
+
+       wpa_printf(MSG_DEBUG, "SAE: Queue Authentication commit message from "
+                  MACSTR " for processing", MAC2STR(mgmt->sa));
+       q = os_zalloc(sizeof(*q) + len);
+       if (!q)
+               return;
+       q->rssi = rssi;
+       q->len = len;
+       os_memcpy(q->msg, mgmt, len);
+       dl_list_add_tail(&hapd->sae_commit_queue, &q->list);
+       if (eloop_is_timeout_registered(auth_sae_process_commit, hapd, NULL))
+               return;
+       eloop_register_timeout(0, queue_len * 50000, auth_sae_process_commit,
+                              hapd, NULL);
+}
+
 #endif /* CONFIG_SAE */
 
 
@@ -1807,7 +1873,7 @@ ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
 
 static void handle_auth(struct hostapd_data *hapd,
                        const struct ieee80211_mgmt *mgmt, size_t len,
-                       int rssi)
+                       int rssi, int from_queue)
 {
        u16 auth_alg, auth_transaction, status_code;
        u16 resp = WLAN_STATUS_SUCCESS;
@@ -1854,11 +1920,12 @@ static void handle_auth(struct hostapd_data *hapd,
 
        wpa_printf(MSG_DEBUG, "authentication: STA=" MACSTR " auth_alg=%d "
                   "auth_transaction=%d status_code=%d wep=%d%s "
-                  "seq_ctrl=0x%x%s",
+                  "seq_ctrl=0x%x%s%s",
                   MAC2STR(mgmt->sa), auth_alg, auth_transaction,
                   status_code, !!(fc & WLAN_FC_ISWEP),
                   challenge ? " challenge" : "",
-                  seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
+                  seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "",
+                  from_queue ? " (from queue)" : "");
 
 #ifdef CONFIG_NO_RC4
        if (auth_alg == WLAN_AUTH_SHARED_KEY) {
@@ -1986,6 +2053,16 @@ static void handle_auth(struct hostapd_data *hapd,
        if (res == HOSTAPD_ACL_PENDING)
                return;
 
+#ifdef CONFIG_SAE
+       if (auth_alg == WLAN_AUTH_SAE && auth_transaction == 1 && !from_queue) {
+               /* Handle SAE Authentication commit message through a queue to
+                * provide more control for postponing the needed heavy
+                * processing under a possible DoS attack scenario. */
+               auth_sae_queue_commit(hapd, mgmt, len, rssi);
+               return;
+       }
+#endif /* CONFIG_SAE */
+
        sta = ap_get_sta(hapd, mgmt->sa);
        if (sta) {
                sta->flags &= ~WLAN_STA_PENDING_FILS_ERP;
@@ -4245,7 +4322,7 @@ int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
        switch (stype) {
        case WLAN_FC_STYPE_AUTH:
                wpa_printf(MSG_DEBUG, "mgmt::auth");
-               handle_auth(hapd, mgmt, len, ssi_signal);
+               handle_auth(hapd, mgmt, len, ssi_signal, 0);
                ret = 1;
                break;
        case WLAN_FC_STYPE_ASSOC_REQ:
index 50822267394ff8606a552c4dc5001184591ff7ad..db7badcfffaf6533d5ee82e4203540318e33d2e5 100644 (file)
@@ -175,4 +175,6 @@ int ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
 int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
                      int ap_seg1_idx, int *bandwidth, int *seg1_idx);
 
+void auth_sae_process_commit(void *eloop_ctx, void *user_ctx);
+
 #endif /* IEEE802_11_H */