hostapd: Fix a regression in TKIP countermeasures processing

Commit 296a34f0c1 changed hostapd to
remove the internal STA entry at the beginning of TKIP countermeasures.
However, this did not take into account the case where this is triggered
by an EAPOL-Key error report from a station. In such a case, WPA
authenticator state machine may continue processing after having
processed the error report. This could result in use of freed memory.
Fix this by stopping WPA processing if the STA entry got removed.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2012-11-18 13:06:03 +02:00
parent 6366a17ce3
commit c772d054c2
5 changed files with 25 additions and 16 deletions

View file

@ -66,9 +66,10 @@ void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
}
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
{
struct os_time now;
int ret = 0;
if (addr && local) {
struct sta_info *sta = ap_get_sta(hapd, addr);
@ -84,7 +85,7 @@ void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
"MLME-MICHAELMICFAILURE.indication "
"for not associated STA (" MACSTR
") ignored", MAC2STR(addr));
return;
return ret;
}
}
@ -93,8 +94,12 @@ void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
hapd->michael_mic_failures = 1;
} else {
hapd->michael_mic_failures++;
if (hapd->michael_mic_failures > 1)
if (hapd->michael_mic_failures > 1) {
ieee80211_tkip_countermeasures_start(hapd);
ret = 1;
}
}
hapd->michael_mic_failure = now.sec;
return ret;
}

View file

@ -1,6 +1,6 @@
/*
* hostapd / TKIP countermeasures
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -9,7 +9,7 @@
#ifndef TKIP_COUNTERMEASURES_H
#define TKIP_COUNTERMEASURES_H
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local);
int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local);
void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd);
#endif /* TKIP_COUNTERMEASURES_H */

View file

@ -54,11 +54,12 @@ static const int dot11RSNAConfigPMKReauthThreshold = 70;
static const int dot11RSNAConfigSATimeout = 60;
static inline void wpa_auth_mic_failure_report(
static inline int wpa_auth_mic_failure_report(
struct wpa_authenticator *wpa_auth, const u8 *addr)
{
if (wpa_auth->cb.mic_failure_report)
wpa_auth->cb.mic_failure_report(wpa_auth->cb.ctx, addr);
return wpa_auth->cb.mic_failure_report(wpa_auth->cb.ctx, addr);
return 0;
}
@ -700,7 +701,7 @@ static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
#endif /* CONFIG_IEEE80211R */
static void wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm, int group)
{
/* Supplicant reported a Michael MIC error */
@ -718,7 +719,8 @@ static void wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
"ignore Michael MIC failure report since "
"pairwise cipher is not TKIP");
} else {
wpa_auth_mic_failure_report(wpa_auth, sm->addr);
if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0)
return 1; /* STA entry was removed */
sm->dot11RSNAStatsTKIPRemoteMICFailures++;
wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;
}
@ -728,6 +730,7 @@ static void wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
* Authenticator may do it, let's change the keys now anyway.
*/
wpa_request_new_ptk(sm);
return 0;
}
@ -1081,9 +1084,10 @@ continue_processing:
#endif /* CONFIG_PEERKEY */
return;
} else if (key_info & WPA_KEY_INFO_ERROR) {
wpa_receive_error_report(
if (wpa_receive_error_report(
wpa_auth, sm,
!(key_info & WPA_KEY_INFO_KEY_TYPE));
!(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0)
return; /* STA entry was removed */
} else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
"received EAPOL-Key Request for new "

View file

@ -177,7 +177,7 @@ struct wpa_auth_callbacks {
void (*logger)(void *ctx, const u8 *addr, logger_level level,
const char *txt);
void (*disconnect)(void *ctx, const u8 *addr, u16 reason);
void (*mic_failure_report)(void *ctx, const u8 *addr);
int (*mic_failure_report)(void *ctx, const u8 *addr);
void (*set_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var,
int value);
int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var);

View file

@ -112,10 +112,10 @@ static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr,
}
static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
static int hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
{
struct hostapd_data *hapd = ctx;
michael_mic_failure(hapd, addr, 0);
return michael_mic_failure(hapd, addr, 0);
}