FT: Handle AssocResp generation failures as fatal errors

Instead of sending out a partially completed frame, abort the
association process if something unexpected happens and remove the STA
entry.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2018-06-05 21:09:43 +03:00
parent c52626489a
commit 2cf36d6085
3 changed files with 22 additions and 9 deletions

View file

@ -453,6 +453,10 @@ skip_wpa_check:
#ifdef CONFIG_IEEE80211R_AP #ifdef CONFIG_IEEE80211R_AP
p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf), p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf),
sta->auth_alg, req_ies, req_ies_len); sta->auth_alg, req_ies, req_ies_len);
if (!p) {
wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
#endif /* CONFIG_IEEE80211R_AP */ #endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_FILS #ifdef CONFIG_FILS

View file

@ -2879,6 +2879,12 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p, p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
buf + buflen - p, buf + buflen - p,
sta->auth_alg, ies, ies_len); sta->auth_alg, ies, ies_len);
if (!p) {
wpa_printf(MSG_DEBUG,
"FT: Failed to write AssocResp IEs");
res = WLAN_STATUS_UNSPECIFIED_FAILURE;
goto done;
}
} }
#endif /* CONFIG_IEEE80211R_AP */ #endif /* CONFIG_IEEE80211R_AP */

View file

@ -2377,7 +2377,7 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
*/ */
res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name); res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name);
if (res < 0) if (res < 0)
return pos; return NULL;
rsnie = pos; rsnie = pos;
rsnie_len = res; rsnie_len = res;
pos += res; pos += res;
@ -2386,7 +2386,7 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
/* Mobility Domain Information */ /* Mobility Domain Information */
res = wpa_write_mdie(conf, pos, end - pos); res = wpa_write_mdie(conf, pos, end - pos);
if (res < 0) if (res < 0)
return pos; return NULL;
mdie = pos; mdie = pos;
mdie_len = res; mdie_len = res;
pos += res; pos += res;
@ -2397,7 +2397,7 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
if (!subelem) { if (!subelem) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"FT: Failed to add GTK subelement"); "FT: Failed to add GTK subelement");
return pos; return NULL;
} }
r0kh_id = sm->r0kh_id; r0kh_id = sm->r0kh_id;
r0kh_id_len = sm->r0kh_id_len; r0kh_id_len = sm->r0kh_id_len;
@ -2413,13 +2413,13 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"FT: Failed to add IGTK subelement"); "FT: Failed to add IGTK subelement");
os_free(subelem); os_free(subelem);
return pos; return NULL;
} }
nbuf = os_realloc(subelem, subelem_len + igtk_len); nbuf = os_realloc(subelem, subelem_len + igtk_len);
if (nbuf == NULL) { if (nbuf == NULL) {
os_free(subelem); os_free(subelem);
os_free(igtk); os_free(igtk);
return pos; return NULL;
} }
subelem = nbuf; subelem = nbuf;
os_memcpy(subelem + subelem_len, igtk, igtk_len); os_memcpy(subelem + subelem_len, igtk, igtk_len);
@ -2438,7 +2438,7 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
subelem, subelem_len); subelem, subelem_len);
os_free(subelem); os_free(subelem);
if (res < 0) if (res < 0)
return pos; return NULL;
ftie = pos; ftie = pos;
ftie_len = res; ftie_len = res;
pos += res; pos += res;
@ -2483,13 +2483,16 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
mdie, mdie_len, ftie, ftie_len, mdie, mdie_len, ftie, ftie_len,
rsnie, rsnie_len, rsnie, rsnie_len,
ric_start, ric_start ? pos - ric_start : 0, ric_start, ric_start ? pos - ric_start : 0,
fte_mic) < 0) fte_mic) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
return NULL;
}
os_free(sm->assoc_resp_ftie); os_free(sm->assoc_resp_ftie);
sm->assoc_resp_ftie = os_malloc(ftie_len); sm->assoc_resp_ftie = os_malloc(ftie_len);
if (sm->assoc_resp_ftie) if (!sm->assoc_resp_ftie)
os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len); return NULL;
os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len);
return pos; return pos;
} }