From 9128b67269c4072d7a9c01570811d9c3e9bbf00d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 16:39:36 +0200 Subject: [PATCH] Extend hostapd rsnxe_override_eapol to allow IE removal Previous implementation was determining whether the override value was set based on its length being larger than zero. Replace this with an explicit indication of whether the parameter is set to allow zero length replacement, i.e., remove of RSNXE from EAPOL-Key msg 3/4. In addition, move IE replacement into a more generic helper function to allow this to be used with other IEs as well. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 68 +++++++++++++++++++++++++----------------- src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_glue.c | 1 + 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 07cc514d9..f914875fe 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3221,13 +3221,45 @@ static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos) } +#ifdef CONFIG_TESTING_OPTIONS +static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid, + const u8 *ie, size_t ie_len) +{ + const u8 *elem; + u8 *buf; + + wpa_printf(MSG_DEBUG, "TESTING: %s EAPOL override", name); + wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie before override", + old_buf, *len); + buf = os_malloc(*len + ie_len); + if (!buf) + return NULL; + os_memcpy(buf, old_buf, *len); + elem = get_ie(buf, *len, eid); + if (elem) { + u8 elem_len = 2 + elem[1]; + + os_memmove((void *) elem, elem + elem_len, + *len - (elem - buf) - elem_len); + *len -= elem_len; + } + os_memcpy(buf + *len, ie, ie_len); + *len += ie_len; + wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie after EAPOL override", + buf, *len); + + return buf; +} +#endif /* CONFIG_TESTING_OPTIONS */ + + SM_STATE(WPA_PTK, PTKINITNEGOTIATING) { u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, dummy_gtk[32]; - size_t gtk_len, kde_len; + size_t gtk_len, kde_len, wpa_ie_len; struct wpa_group *gsm = sm->group; u8 *wpa_ie; - int wpa_ie_len, secure, gtkidx, encr = 0; + int secure, gtkidx, encr = 0; u8 *wpa_ie_buf = NULL; SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); @@ -3255,7 +3287,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_ie_len = sm->wpa_auth->wpa_ie_len; if (sm->wpa == WPA_VERSION_WPA && (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && - wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) { + wpa_ie_len > wpa_ie[1] + 2U && wpa_ie[0] == WLAN_EID_RSN) { /* WPA-only STA, remove RSN IE and possible MDIE */ wpa_ie = wpa_ie + wpa_ie[1] + 2; if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN) @@ -3263,32 +3295,14 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_ie_len = wpa_ie[1] + 2; } #ifdef CONFIG_TESTING_OPTIONS - if (sm->wpa_auth->conf.rsnxe_override_eapol_len) { - u8 *obuf = sm->wpa_auth->conf.rsnxe_override_eapol; - size_t olen = sm->wpa_auth->conf.rsnxe_override_eapol_len; - const u8 *rsnxe; - - wpa_hexdump(MSG_DEBUG, - "TESTING: wpa_ie before RSNXE EAPOL override", - wpa_ie, wpa_ie_len); - wpa_ie_buf = os_malloc(wpa_ie_len + olen); + if (sm->wpa_auth->conf.rsnxe_override_eapol_set) { + wpa_ie_buf = replace_ie( + "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX, + sm->wpa_auth->conf.rsnxe_override_eapol, + sm->wpa_auth->conf.rsnxe_override_eapol_len); if (!wpa_ie_buf) - return; - os_memcpy(wpa_ie_buf, wpa_ie, wpa_ie_len); + goto done; wpa_ie = wpa_ie_buf; - rsnxe = get_ie(wpa_ie, wpa_ie_len, WLAN_EID_RSNX); - if (rsnxe) { - u8 rsnxe_len = 2 + rsnxe[1]; - - os_memmove((void *) rsnxe, rsnxe + rsnxe_len, - wpa_ie_len - (rsnxe - wpa_ie) - rsnxe_len); - wpa_ie_len -= rsnxe_len; - } - os_memcpy(wpa_ie + wpa_ie_len, obuf, olen); - wpa_ie_len += olen; - wpa_hexdump(MSG_DEBUG, - "TESTING: wpa_ie after RSNXE EAPOL override", - wpa_ie, wpa_ie_len); } #endif /* CONFIG_TESTING_OPTIONS */ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 1f7ba4899..93d7f74f2 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -225,6 +225,7 @@ struct wpa_auth_config { size_t rsnxe_override_eapol_len; u8 gtk_rsc_override[WPA_KEY_RSC_LEN]; u8 igtk_rsc_override[WPA_KEY_RSC_LEN]; + unsigned int rsnxe_override_eapol_set:1; unsigned int gtk_rsc_override_set:1; unsigned int igtk_rsc_override_set:1; #endif /* CONFIG_TESTING_OPTIONS */ diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 82e82a7d2..4a303b039 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -123,6 +123,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, } if (conf->rsnxe_override_eapol && wpabuf_len(conf->rsnxe_override_eapol) <= MAX_OWN_IE_OVERRIDE) { + wconf->rsnxe_override_eapol_set = 1; wconf->rsnxe_override_eapol_len = wpabuf_len(conf->rsnxe_override_eapol); os_memcpy(wconf->rsnxe_override_eapol,