]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
FILS: Add HLP support with driver-based AP SME
authorJeffin Mammen <jmammen@qti.qualcomm.com>
Thu, 6 Jul 2017 10:57:54 +0000 (13:57 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 6 Jul 2017 12:24:42 +0000 (15:24 +0300)
This allows HLP processing to postpone association processing in
hostapd_notify_assoc().

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/ap/drv_callbacks.c
src/ap/fils_hlp.c
src/ap/hostapd.h
src/ap/ieee802_11.c
src/ap/sta_info.h
src/ap/wpa_auth.c
src/ap/wpa_auth.h

index 9e30abf02528e84af90dfd70c257b8252cd7a0e0..7e948d25e563b193031c4956e90c4608c573cc87 100644 (file)
 #include "beacon.h"
 #include "mbo_ap.h"
 #include "dpp_hostapd.h"
+#include "fils_hlp.h"
+
+
+#ifdef CONFIG_FILS
+void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd,
+                                     struct sta_info *sta)
+{
+       u16 reply_res = WLAN_STATUS_SUCCESS;
+       struct ieee802_11_elems elems;
+       u8 buf[IEEE80211_MAX_MMPDU_SIZE], *p = buf;
+       int new_assoc;
+
+       wpa_printf(MSG_DEBUG, "%s FILS: Finish association with " MACSTR,
+                  __func__, MAC2STR(sta->addr));
+       eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
+       if (!sta->fils_pending_assoc_req)
+               return;
+
+       ieee802_11_parse_elems(sta->fils_pending_assoc_req,
+                              sta->fils_pending_assoc_req_len, &elems, 0);
+       if (!elems.fils_session) {
+               wpa_printf(MSG_DEBUG, "%s failed to find FILS Session element",
+                          __func__);
+               return;
+       }
+
+       p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
+                                          elems.fils_session,
+                                          sta->fils_hlp_resp);
+
+       reply_res = hostapd_sta_assoc(hapd, sta->addr,
+                                     sta->fils_pending_assoc_is_reassoc,
+                                     WLAN_STATUS_SUCCESS,
+                                     buf, p - buf);
+       ap_sta_set_authorized(hapd, sta, 1);
+       new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
+       sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
+       sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
+       hostapd_set_sta_flags(hapd, sta);
+       wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FILS);
+       ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
+       hostapd_new_assoc_sta(hapd, sta, !new_assoc);
+       os_free(sta->fils_pending_assoc_req);
+       sta->fils_pending_assoc_req = NULL;
+       sta->fils_pending_assoc_req_len = 0;
+       wpabuf_free(sta->fils_hlp_resp);
+       sta->fils_hlp_resp = NULL;
+       wpabuf_free(sta->hlp_dhcp_discover);
+       sta->hlp_dhcp_discover = NULL;
+       fils_hlp_deinit(hapd);
+
+       /*
+        * Remove the station in case transmission of a success response fails
+        * (the STA was added associated to the driver) or if the station was
+        * previously added unassociated.
+        */
+       if (reply_res != WLAN_STATUS_SUCCESS || sta->added_unassoc) {
+               hostapd_drv_sta_remove(hapd, sta->addr);
+               sta->added_unassoc = 0;
+       }
+}
+#endif /* CONFIG_FILS */
 
 
 int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
@@ -388,6 +450,8 @@ skip_wpa_check:
        if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
            sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
            sta->auth_alg == WLAN_AUTH_FILS_PK) {
+               int delay_assoc = 0;
+
                if (!wpa_fils_validate_fils_session(sta->wpa_sm, req_ies,
                                                    req_ies_len,
                                                    sta->fils_session)) {
@@ -404,14 +468,51 @@ skip_wpa_check:
                        return WLAN_STATUS_UNSPECIFIED_FAILURE;
                }
 
-               if (!elems.fils_session) {
+               if (fils_process_hlp(hapd, sta, req_ies, req_ies_len) > 0) {
                        wpa_printf(MSG_DEBUG,
-                                  "FILS: Session element not found");
-                       return WLAN_STATUS_UNSPECIFIED_FAILURE;
+                                  "FILS: Delaying Assoc Response (HLP)");
+                       delay_assoc = 1;
+               } else {
+                       wpa_printf(MSG_DEBUG,
+                                  "FILS: Going ahead with Assoc Response (no HLP)");
                }
 
+               if (sta) {
+                       wpa_printf(MSG_DEBUG, "FILS: HLP callback cleanup");
+                       eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
+                       os_free(sta->fils_pending_assoc_req);
+                       sta->fils_pending_assoc_req = NULL;
+                       sta->fils_pending_assoc_req_len = 0;
+                       wpabuf_free(sta->fils_hlp_resp);
+                       sta->fils_hlp_resp = NULL;
+                       sta->fils_drv_assoc_finish = 0;
+               }
+
+               if (sta && delay_assoc && status == WLAN_STATUS_SUCCESS) {
+                       u8 *req_tmp;
+
+                       req_tmp = os_malloc(req_ies_len);
+                       if (!req_tmp) {
+                               wpa_printf(MSG_DEBUG,
+                                          "FILS: buffer allocation failed for assoc req");
+                               goto fail;
+                       }
+                       os_memcpy(req_tmp, req_ies, req_ies_len);
+                       sta->fils_pending_assoc_req = req_tmp;
+                       sta->fils_pending_assoc_req_len = req_ies_len;
+                       sta->fils_pending_assoc_is_reassoc = reassoc;
+                       sta->fils_drv_assoc_finish = 1;
+                       wpa_printf(MSG_DEBUG,
+                                  "FILS: Waiting for HLP processing before sending (Re)Association Response frame to "
+                                  MACSTR, MAC2STR(sta->addr));
+                       eloop_register_timeout(
+                               0, hapd->conf->fils_hlp_wait_time * 1024,
+                               fils_hlp_timeout, hapd, sta);
+                       return 0;
+               }
                p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
-                                                  elems.fils_session);
+                                                  elems.fils_session,
+                                                  sta->fils_hlp_resp);
                wpa_hexdump(MSG_DEBUG, "FILS Assoc Resp BUF (IEs)",
                            buf, p - buf);
        }
index c5e7aec4a242117522825022fc4105c0aa9e59a1..2370a8bbdc62e50c001f41057c109c50bfa83dae 100644 (file)
@@ -314,7 +314,11 @@ static void fils_dhcp_handler(int sd, void *eloop_ctx, void *sock_ctx)
                left -= len;
        }
        wpabuf_free(resp);
-       fils_hlp_finish_assoc(hapd, sta);
+
+       if (sta->fils_drv_assoc_finish)
+               hostapd_notify_assoc_fils_finish(hapd, sta);
+       else
+               fils_hlp_finish_assoc(hapd, sta);
 }
 
 
index 2afeee2188335e0971f96c7bf4c46257ffc6c77b..8580d80734c70d890c0876ae27d36c72ad471739 100644 (file)
@@ -552,6 +552,8 @@ int hostapd_register_probereq_cb(struct hostapd_data *hapd,
 void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
 
 /* drv_callbacks.c (TODO: move to somewhere else?) */
+void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd,
+                                     struct sta_info *sta);
 int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
                        const u8 *ie, size_t ielen, int reassoc);
 void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
index ac89c908ea425950f5e3d01b60d86fb1c1fae8b4..64db441ac1d82b5111b5357c30c7e4f32792e0ab 100644 (file)
@@ -2850,7 +2850,10 @@ void fils_hlp_timeout(void *eloop_ctx, void *eloop_data)
        wpa_printf(MSG_DEBUG,
                   "FILS: HLP response timeout - continue with association response for "
                   MACSTR, MAC2STR(sta->addr));
-       fils_hlp_finish_assoc(hapd, sta);
+       if (sta->fils_drv_assoc_finish)
+               hostapd_notify_assoc_fils_finish(hapd, sta);
+       else
+               fils_hlp_finish_assoc(hapd, sta);
 }
 
 #endif /* CONFIG_FILS */
@@ -3204,6 +3207,7 @@ static void handle_assoc(struct hostapd_data *hapd,
                sta->fils_pending_assoc_req = tmp;
                sta->fils_pending_assoc_req_len = left;
                sta->fils_pending_assoc_is_reassoc = reassoc;
+               sta->fils_drv_assoc_finish = 0;
                wpa_printf(MSG_DEBUG,
                           "FILS: Waiting for HLP processing before sending (Re)Association Response frame to "
                           MACSTR, MAC2STR(sta->addr));
index 0a23050846c3ee6254ccd8f19f9bf6be33df5a12..271128b9e05511b9302ebfb1e75321d8e4d520df 100644 (file)
@@ -232,6 +232,7 @@ struct sta_info {
        unsigned int fils_pending_assoc_is_reassoc:1;
        unsigned int fils_dhcp_rapid_commit_proxy:1;
        unsigned int fils_erp_pmkid_set:1;
+       unsigned int fils_drv_assoc_finish:1;
        struct wpabuf *fils_hlp_resp;
        struct wpabuf *hlp_dhcp_discover;
        void (*fils_pending_cb)(struct hostapd_data *hapd, struct sta_info *sta,
index bb86a92c4ce9673c604ee1b305629e4065b8d50c..b1edce813be850335880171d8e52bed8e3c9d531 100644 (file)
@@ -2282,6 +2282,11 @@ int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies,
                return -1;
        }
 
+       if (!elems.fils_session) {
+               wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
+               return -1;
+       }
+
        if (!elems.fils_key_confirm) {
                wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
                return -1;
@@ -2565,7 +2570,7 @@ int fils_set_tk(struct wpa_state_machine *sm)
 
 
 u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
-                                   const u8 *fils_session)
+                                   const u8 *fils_session, struct wpabuf *hlp)
 {
        struct wpabuf *plain;
        u8 *pos = buf;
@@ -2577,7 +2582,7 @@ u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
        os_memcpy(pos, fils_session, FILS_SESSION_LEN);
        pos += FILS_SESSION_LEN;
 
-       plain = fils_prepare_plainbuf(sm, NULL);
+       plain = fils_prepare_plainbuf(sm, hlp);
        if (!plain) {
                wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
                return NULL;
index 3b69789a1ea1a9933b8dd88b415e4dddd31cda7d..df4fac5cf7c59c0fa799ce4ecfa0ce0c97342822 100644 (file)
@@ -409,7 +409,8 @@ int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
                       const struct wpabuf *hlp);
 int fils_set_tk(struct wpa_state_machine *sm);
 u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *eid,
-                                   const u8 *fils_session);
+                                   const u8 *fils_session,
+                                   struct wpabuf *fils_hlp_resp);
 const u8 *  wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
                                           const u8 *ies, size_t ies_len,
                                           const u8 *fils_session);