aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJeffin Mammen <jmammen@qti.qualcomm.com>2017-07-06 10:57:54 (GMT)
committerJouni Malinen <j@w1.fi>2017-07-06 12:24:42 (GMT)
commit8b5ddda5fba0dc9838f05d856cb5f831dbd7a1ea (patch)
tree39d252ebd95a5470ec9fe1d75766a72c412371a4 /src
parent31ec556cefb7b7ebf227fbb7c5f5750006cbe03a (diff)
downloadhostap-8b5ddda5fba0dc9838f05d856cb5f831dbd7a1ea.zip
hostap-8b5ddda5fba0dc9838f05d856cb5f831dbd7a1ea.tar.gz
hostap-8b5ddda5fba0dc9838f05d856cb5f831dbd7a1ea.tar.bz2
FILS: Add HLP support with driver-based AP SME
This allows HLP processing to postpone association processing in hostapd_notify_assoc(). Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Diffstat (limited to 'src')
-rw-r--r--src/ap/drv_callbacks.c109
-rw-r--r--src/ap/fils_hlp.c6
-rw-r--r--src/ap/hostapd.h2
-rw-r--r--src/ap/ieee802_11.c6
-rw-r--r--src/ap/sta_info.h1
-rw-r--r--src/ap/wpa_auth.c9
-rw-r--r--src/ap/wpa_auth.h3
7 files changed, 127 insertions, 9 deletions
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 9e30abf..7e948d2 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -38,6 +38,68 @@
#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);
}
diff --git a/src/ap/fils_hlp.c b/src/ap/fils_hlp.c
index c5e7aec..2370a8b 100644
--- a/src/ap/fils_hlp.c
+++ b/src/ap/fils_hlp.c
@@ -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);
}
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 2afeee2..8580d80 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -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);
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index ac89c90..64db441 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -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));
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 0a23050..271128b 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -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,
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index bb86a92..b1edce8 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -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;
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 3b69789..df4fac5 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -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);