From daa40960844e7b9557a152869f06bb08f150cd2a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 15 Oct 2017 23:25:55 +0300 Subject: [PATCH] Allow last (Re)Association Request frame to be replayed for testing The new wpa_supplicant RESEND_ASSOC command can be used to request the last (Re)Association Request frame to be sent to the AP to test FT protocol behavior. This functionality is for testing purposes and included only in builds with CONFIG_TESTING_OPTIONS=y. Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 38 +++++++++++++++++++++++++++++++ wpa_supplicant/events.c | 10 ++++++++ wpa_supplicant/sme.c | 8 +++++++ wpa_supplicant/wpa_supplicant.c | 5 ++++ wpa_supplicant/wpa_supplicant_i.h | 2 ++ 5 files changed, 63 insertions(+) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index cd76fea36..c4d8dfe34 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -7771,6 +7771,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->p2p_go_csa_on_inv = 0; wpa_s->ignore_auth_resp = 0; wpa_s->ignore_assoc_disallow = 0; + wpa_s->testing_resend_assoc = 0; wpa_s->reject_btm_req_reason = 0; wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL); os_free(wpa_s->get_pref_freq_list_override); @@ -8952,6 +8953,40 @@ static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd) return 0; } + +static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s) +{ +#ifdef CONFIG_SME + struct wpa_driver_associate_params params; + int ret; + + os_memset(¶ms, 0, sizeof(params)); + params.bssid = wpa_s->bssid; + params.ssid = wpa_s->sme.ssid; + params.ssid_len = wpa_s->sme.ssid_len; + params.freq.freq = wpa_s->sme.freq; + if (wpa_s->last_assoc_req_wpa_ie) { + params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie); + params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie); + } + params.pairwise_suite = wpa_s->pairwise_cipher; + params.group_suite = wpa_s->group_cipher; + params.mgmt_group_suite = wpa_s->mgmt_group_cipher; + params.key_mgmt_suite = wpa_s->key_mgmt; + params.wpa_proto = wpa_s->wpa_proto; + params.mgmt_frame_protection = wpa_s->sme.mfp; + params.rrm_used = wpa_s->rrm.rrm_used; + if (wpa_s->sme.prev_bssid_set) + params.prev_bssid = wpa_s->sme.prev_bssid; + wpa_printf(MSG_INFO, "TESTING: Resend association request"); + ret = wpa_drv_associate(wpa_s, ¶ms); + wpa_s->testing_resend_assoc = 1; + return ret; +#else /* CONFIG_SME */ + return -1; +#endif /* CONFIG_SME */ +} + #endif /* CONFIG_TESTING_OPTIONS */ @@ -10329,6 +10364,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) { if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0) reply_len = -1; + } else if (os_strcmp(buf, "RESEND_ASSOC") == 0) { + if (wpas_ctrl_resend_assoc(wpa_s) < 0) + reply_len = -1; #endif /* CONFIG_TESTING_OPTIONS */ } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) { if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 6e4a9f6d3..94b3fd9e0 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -3844,6 +3844,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, "EVENT_ASSOC - ignore_auth_resp active!"); break; } + if (wpa_s->testing_resend_assoc) { + wpa_printf(MSG_INFO, + "EVENT_DEAUTH - testing_resend_assoc"); + break; + } #endif /* CONFIG_TESTING_OPTIONS */ wpa_supplicant_event_assoc(wpa_s, data); if (data && @@ -3868,6 +3873,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, "EVENT_DEAUTH - ignore_auth_resp active!"); break; } + if (wpa_s->testing_resend_assoc) { + wpa_printf(MSG_INFO, + "EVENT_DEAUTH - testing_resend_assoc"); + break; + } #endif /* CONFIG_TESTING_OPTIONS */ wpas_event_deauth(wpa_s, data ? &data->deauth_info : NULL); diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 8b35f16a5..da0e8eb41 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -1314,6 +1314,14 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s, NULL); + +#ifdef CONFIG_TESTING_OPTIONS + wpabuf_free(wpa_s->last_assoc_req_wpa_ie); + wpa_s->last_assoc_req_wpa_ie = NULL; + if (params.wpa_ie) + wpa_s->last_assoc_req_wpa_ie = + wpabuf_alloc_copy(params.wpa_ie, params.wpa_ie_len); +#endif /* CONFIG_TESTING_OPTIONS */ } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index f543b9dbd..7e4d086b0 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -465,6 +465,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) wpa_s->l2_test = NULL; os_free(wpa_s->get_pref_freq_list_override); wpa_s->get_pref_freq_list_override = NULL; + wpabuf_free(wpa_s->last_assoc_req_wpa_ie); + wpa_s->last_assoc_req_wpa_ie = NULL; #endif /* CONFIG_TESTING_OPTIONS */ if (wpa_s->conf != NULL) { @@ -1795,6 +1797,9 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, wmm_ac_clear_saved_tspecs(wpa_s); wpa_s->reassoc_same_bss = 0; wpa_s->reassoc_same_ess = 0; +#ifdef CONFIG_TESTING_OPTIONS + wpa_s->testing_resend_assoc = 0; +#endif /* CONFIG_TESTING_OPTIONS */ if (wpa_s->last_ssid == ssid) { wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS"); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 8ce7085bc..cfb9753f4 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1076,12 +1076,14 @@ struct wpa_supplicant { unsigned int p2p_go_csa_on_inv:1; unsigned int ignore_auth_resp:1; unsigned int ignore_assoc_disallow:1; + unsigned int testing_resend_assoc:1; struct wpabuf *sae_commit_override; enum wpa_alg last_tk_alg; u8 last_tk_addr[ETH_ALEN]; int last_tk_key_idx; u8 last_tk[WPA_TK_MAX_LEN]; size_t last_tk_len; + struct wpabuf *last_assoc_req_wpa_ie; #endif /* CONFIG_TESTING_OPTIONS */ struct wmm_ac_assoc_data *wmm_ac_assoc_info;