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>
This commit is contained in:
parent
31ec556cef
commit
8b5ddda5fb
7 changed files with 127 additions and 9 deletions
|
|
@ -38,6 +38,68 @@
|
||||||
#include "beacon.h"
|
#include "beacon.h"
|
||||||
#include "mbo_ap.h"
|
#include "mbo_ap.h"
|
||||||
#include "dpp_hostapd.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,
|
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 ||
|
if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
|
||||||
sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
|
sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
|
||||||
sta->auth_alg == WLAN_AUTH_FILS_PK) {
|
sta->auth_alg == WLAN_AUTH_FILS_PK) {
|
||||||
|
int delay_assoc = 0;
|
||||||
|
|
||||||
if (!wpa_fils_validate_fils_session(sta->wpa_sm, req_ies,
|
if (!wpa_fils_validate_fils_session(sta->wpa_sm, req_ies,
|
||||||
req_ies_len,
|
req_ies_len,
|
||||||
sta->fils_session)) {
|
sta->fils_session)) {
|
||||||
|
|
@ -404,14 +468,51 @@ skip_wpa_check:
|
||||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
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,
|
wpa_printf(MSG_DEBUG,
|
||||||
"FILS: Session element not found");
|
"FILS: Delaying Assoc Response (HLP)");
|
||||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
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,
|
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)",
|
wpa_hexdump(MSG_DEBUG, "FILS Assoc Resp BUF (IEs)",
|
||||||
buf, p - buf);
|
buf, p - buf);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -314,7 +314,11 @@ static void fils_dhcp_handler(int sd, void *eloop_ctx, void *sock_ctx)
|
||||||
left -= len;
|
left -= len;
|
||||||
}
|
}
|
||||||
wpabuf_free(resp);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -552,6 +552,8 @@ int hostapd_register_probereq_cb(struct hostapd_data *hapd,
|
||||||
void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
|
void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
|
||||||
|
|
||||||
/* drv_callbacks.c (TODO: move to somewhere else?) */
|
/* 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,
|
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||||
const u8 *ie, size_t ielen, int reassoc);
|
const u8 *ie, size_t ielen, int reassoc);
|
||||||
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
|
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
|
||||||
|
|
|
||||||
|
|
@ -2850,7 +2850,10 @@ void fils_hlp_timeout(void *eloop_ctx, void *eloop_data)
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"FILS: HLP response timeout - continue with association response for "
|
"FILS: HLP response timeout - continue with association response for "
|
||||||
MACSTR, MAC2STR(sta->addr));
|
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 */
|
#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 = tmp;
|
||||||
sta->fils_pending_assoc_req_len = left;
|
sta->fils_pending_assoc_req_len = left;
|
||||||
sta->fils_pending_assoc_is_reassoc = reassoc;
|
sta->fils_pending_assoc_is_reassoc = reassoc;
|
||||||
|
sta->fils_drv_assoc_finish = 0;
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"FILS: Waiting for HLP processing before sending (Re)Association Response frame to "
|
"FILS: Waiting for HLP processing before sending (Re)Association Response frame to "
|
||||||
MACSTR, MAC2STR(sta->addr));
|
MACSTR, MAC2STR(sta->addr));
|
||||||
|
|
|
||||||
|
|
@ -232,6 +232,7 @@ struct sta_info {
|
||||||
unsigned int fils_pending_assoc_is_reassoc:1;
|
unsigned int fils_pending_assoc_is_reassoc:1;
|
||||||
unsigned int fils_dhcp_rapid_commit_proxy:1;
|
unsigned int fils_dhcp_rapid_commit_proxy:1;
|
||||||
unsigned int fils_erp_pmkid_set:1;
|
unsigned int fils_erp_pmkid_set:1;
|
||||||
|
unsigned int fils_drv_assoc_finish:1;
|
||||||
struct wpabuf *fils_hlp_resp;
|
struct wpabuf *fils_hlp_resp;
|
||||||
struct wpabuf *hlp_dhcp_discover;
|
struct wpabuf *hlp_dhcp_discover;
|
||||||
void (*fils_pending_cb)(struct hostapd_data *hapd, struct sta_info *sta,
|
void (*fils_pending_cb)(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
|
|
|
||||||
|
|
@ -2282,6 +2282,11 @@ int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!elems.fils_session) {
|
||||||
|
wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!elems.fils_key_confirm) {
|
if (!elems.fils_key_confirm) {
|
||||||
wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
|
wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
|
||||||
return -1;
|
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,
|
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;
|
struct wpabuf *plain;
|
||||||
u8 *pos = buf;
|
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);
|
os_memcpy(pos, fils_session, FILS_SESSION_LEN);
|
||||||
pos += FILS_SESSION_LEN;
|
pos += FILS_SESSION_LEN;
|
||||||
|
|
||||||
plain = fils_prepare_plainbuf(sm, NULL);
|
plain = fils_prepare_plainbuf(sm, hlp);
|
||||||
if (!plain) {
|
if (!plain) {
|
||||||
wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
|
wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
||||||
|
|
@ -409,7 +409,8 @@ int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
|
||||||
const struct wpabuf *hlp);
|
const struct wpabuf *hlp);
|
||||||
int fils_set_tk(struct wpa_state_machine *sm);
|
int fils_set_tk(struct wpa_state_machine *sm);
|
||||||
u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *eid,
|
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 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
|
||||||
const u8 *ies, size_t ies_len,
|
const u8 *ies, size_t ies_len,
|
||||||
const u8 *fils_session);
|
const u8 *fils_session);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue