]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
FILS: Handle authentication/association in partial driver AP SME
authorJeffin Mammen <jmammen@qti.qualcomm.com>
Fri, 21 Apr 2017 15:42:00 +0000 (18:42 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 23 Apr 2017 22:07:39 +0000 (01:07 +0300)
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/ap/drv_callbacks.c
src/ap/wpa_auth.c
src/ap/wpa_auth.h

index 8f776cf7e1cfe6d312e32d5e641a6644c50650de..656b820eb960fa314c3e083bba6926dc3c24f5a7 100644 (file)
@@ -31,6 +31,7 @@
 #include "wps_hostapd.h"
 #include "ap_drv_ops.h"
 #include "ap_config.h"
+#include "ap_mlme.h"
 #include "hw_features.h"
 #include "dfs.h"
 #include "beacon.h"
@@ -381,6 +382,39 @@ skip_wpa_check:
                                        sta->auth_alg, req_ies, req_ies_len);
 #endif /* CONFIG_IEEE80211R_AP */
 
+#ifdef CONFIG_FILS
+       if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
+           sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
+           sta->auth_alg == WLAN_AUTH_FILS_PK) {
+               if (!wpa_fils_validate_fils_session(sta->wpa_sm, req_ies,
+                                                   req_ies_len,
+                                                   sta->fils_session)) {
+                       wpa_printf(MSG_DEBUG,
+                                  "FILS: Session validation failed");
+                       return WLAN_STATUS_UNSPECIFIED_FAILURE;
+               }
+
+               res = wpa_fils_validate_key_confirm(sta->wpa_sm, req_ies,
+                                                   req_ies_len);
+               if (res < 0) {
+                       wpa_printf(MSG_DEBUG,
+                                  "FILS: Key Confirm validation failed");
+                       return WLAN_STATUS_UNSPECIFIED_FAILURE;
+               }
+
+               if (!elems.fils_session) {
+                       wpa_printf(MSG_DEBUG,
+                                  "FILS: Session element not found");
+                       return WLAN_STATUS_UNSPECIFIED_FAILURE;
+               }
+
+               p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
+                                                  elems.fils_session);
+               wpa_hexdump(MSG_DEBUG, "FILS Assoc Resp BUF (IEs)",
+                           buf, p - buf);
+       }
+#endif /* CONFIG_FILS */
+
 #if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_FILS)
        hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
 
@@ -723,6 +757,32 @@ static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst,
 #endif /* CONFIG_IEEE80211R_AP */
 
 
+#ifdef CONFIG_FILS
+static void hostapd_notify_auth_fils_finish(struct hostapd_data *hapd,
+                                           struct sta_info *sta, u16 resp,
+                                           struct wpabuf *data, int pub)
+{
+       if (resp == WLAN_STATUS_SUCCESS) {
+               hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+                              HOSTAPD_LEVEL_DEBUG, "authentication OK (FILS)");
+               sta->flags |= WLAN_STA_AUTH;
+               wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
+               sta->auth_alg = WLAN_AUTH_FILS_SK;
+               mlme_authenticate_indication(hapd, sta);
+       } else {
+               hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+                              HOSTAPD_LEVEL_DEBUG,
+                              "authentication failed (FILS)");
+       }
+
+       hostapd_sta_auth(hapd, sta->addr, 2, resp,
+                        data ? wpabuf_head(data) : NULL,
+                        data ? wpabuf_len(data) : 0);
+       wpabuf_free(data);
+}
+#endif /* CONFIG_FILS */
+
+
 static void hostapd_notif_auth(struct hostapd_data *hapd,
                               struct auth_info *rx_auth)
 {
@@ -760,6 +820,18 @@ static void hostapd_notif_auth(struct hostapd_data *hapd,
                return;
        }
 #endif /* CONFIG_IEEE80211R_AP */
+
+#ifdef CONFIG_FILS
+       if (rx_auth->auth_type == WLAN_AUTH_FILS_SK) {
+               sta->auth_alg = WLAN_AUTH_FILS_SK;
+               handle_auth_fils(hapd, sta, rx_auth->ies, rx_auth->ies_len,
+                                rx_auth->auth_type, rx_auth->auth_transaction,
+                                rx_auth->status_code,
+                                hostapd_notify_auth_fils_finish);
+               return;
+       }
+#endif /* CONFIG_FILS */
+
 fail:
        hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1,
                         status, resp_ies, resp_ies_len);
index fcd4736c9b6f50350dc79c439a6916a5c359857b..172f20ffaf31133bcce66ba2ffdda77294af36f8 100644 (file)
@@ -2509,6 +2509,36 @@ int fils_set_tk(struct wpa_state_machine *sm)
        return 0;
 }
 
+
+u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
+                                   const u8 *fils_session)
+{
+       struct wpabuf *plain;
+       u8 *pos = buf;
+
+       /* FILS Session */
+       *pos++ = WLAN_EID_EXTENSION; /* Element ID */
+       *pos++ = 1 + FILS_SESSION_LEN; /* Length */
+       *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
+       os_memcpy(pos, fils_session, FILS_SESSION_LEN);
+       pos += FILS_SESSION_LEN;
+
+       plain = fils_prepare_plainbuf(sm, NULL);
+       if (!plain) {
+               wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
+               return NULL;
+       }
+
+       os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain));
+       pos += wpabuf_len(plain);
+
+       wpa_printf(MSG_DEBUG, "%s: plain buf_len: %u", __func__,
+                  (unsigned int) wpabuf_len(plain));
+       wpabuf_free(plain);
+       sm->fils_completed = 1;
+       return pos;
+}
+
 #endif /* CONFIG_FILS */
 
 
index 384fa6c081c4a727eeb430a1e227446279dfc359..2e3b78253f15c511924a79c949ed63d70297ba47 100644 (file)
@@ -374,6 +374,8 @@ int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
                       size_t current_len, size_t max_len,
                       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 *  wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
                                           const u8 *ies, size_t ies_len,
                                           const u8 *fils_session);