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 <j@w1.fi>
This commit is contained in:
Jouni Malinen 2020-03-07 16:39:36 +02:00
parent 20cace9014
commit 9128b67269
3 changed files with 43 additions and 27 deletions

View File

@ -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) SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
{ {
u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, dummy_gtk[32]; 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; struct wpa_group *gsm = sm->group;
u8 *wpa_ie; u8 *wpa_ie;
int wpa_ie_len, secure, gtkidx, encr = 0; int secure, gtkidx, encr = 0;
u8 *wpa_ie_buf = NULL; u8 *wpa_ie_buf = NULL;
SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); 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; wpa_ie_len = sm->wpa_auth->wpa_ie_len;
if (sm->wpa == WPA_VERSION_WPA && if (sm->wpa == WPA_VERSION_WPA &&
(sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && (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-only STA, remove RSN IE and possible MDIE */
wpa_ie = wpa_ie + wpa_ie[1] + 2; wpa_ie = wpa_ie + wpa_ie[1] + 2;
if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN) if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
@ -3263,32 +3295,14 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
wpa_ie_len = wpa_ie[1] + 2; wpa_ie_len = wpa_ie[1] + 2;
} }
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS
if (sm->wpa_auth->conf.rsnxe_override_eapol_len) { if (sm->wpa_auth->conf.rsnxe_override_eapol_set) {
u8 *obuf = sm->wpa_auth->conf.rsnxe_override_eapol; wpa_ie_buf = replace_ie(
size_t olen = sm->wpa_auth->conf.rsnxe_override_eapol_len; "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX,
const u8 *rsnxe; sm->wpa_auth->conf.rsnxe_override_eapol,
sm->wpa_auth->conf.rsnxe_override_eapol_len);
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 (!wpa_ie_buf) if (!wpa_ie_buf)
return; goto done;
os_memcpy(wpa_ie_buf, wpa_ie, wpa_ie_len);
wpa_ie = wpa_ie_buf; 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 */ #endif /* CONFIG_TESTING_OPTIONS */
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,

View File

@ -225,6 +225,7 @@ struct wpa_auth_config {
size_t rsnxe_override_eapol_len; size_t rsnxe_override_eapol_len;
u8 gtk_rsc_override[WPA_KEY_RSC_LEN]; u8 gtk_rsc_override[WPA_KEY_RSC_LEN];
u8 igtk_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 gtk_rsc_override_set:1;
unsigned int igtk_rsc_override_set:1; unsigned int igtk_rsc_override_set:1;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */

View File

@ -123,6 +123,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
} }
if (conf->rsnxe_override_eapol && if (conf->rsnxe_override_eapol &&
wpabuf_len(conf->rsnxe_override_eapol) <= MAX_OWN_IE_OVERRIDE) { wpabuf_len(conf->rsnxe_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
wconf->rsnxe_override_eapol_set = 1;
wconf->rsnxe_override_eapol_len = wconf->rsnxe_override_eapol_len =
wpabuf_len(conf->rsnxe_override_eapol); wpabuf_len(conf->rsnxe_override_eapol);
os_memcpy(wconf->rsnxe_override_eapol, os_memcpy(wconf->rsnxe_override_eapol,