Fixed race condition between disassociation event and group key handshake

This avoids getting stuck in state where wpa_supplicant has canceled scans,
but the driver is actually in disassociated state. The previously used code
that controlled scan timeout from WPA module is not really needed anymore
(and has not been needed for past four years since authentication timeout
was separated from scan request timeout), so this can simply be removed to
resolved the race condition. As an extra bonus, this simplifies the
interface to WPA module.
[Bug 261]
This commit is contained in:
Jouni Malinen 2008-06-09 16:26:47 +03:00
parent 2eeaa5c9d0
commit 3e2ad1b932
6 changed files with 6 additions and 46 deletions

View file

@ -450,7 +450,6 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr), MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr),
wpa_cipher_txt(sm->pairwise_cipher), wpa_cipher_txt(sm->pairwise_cipher),
wpa_cipher_txt(sm->group_cipher)); wpa_cipher_txt(sm->group_cipher));
wpa_sm_cancel_scan(sm);
wpa_sm_cancel_auth_timeout(sm); wpa_sm_cancel_auth_timeout(sm);
wpa_sm_set_state(sm, WPA_COMPLETED); wpa_sm_set_state(sm, WPA_COMPLETED);
@ -782,7 +781,6 @@ static void wpa_report_ie_mismatch(struct wpa_sm *sm,
} }
wpa_sm_disassociate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS); wpa_sm_disassociate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
wpa_sm_req_scan(sm, 0, 0);
} }
@ -1790,7 +1788,6 @@ static void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
os_memset(sm->pmk, 0, sizeof(sm->pmk)); os_memset(sm->pmk, 0, sizeof(sm->pmk));
wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
wpa_sm_req_scan(sm, 0, 0);
} }
} }

View file

@ -36,8 +36,6 @@ struct wpa_sm_ctx {
void (*set_state)(void *ctx, wpa_states state); void (*set_state)(void *ctx, wpa_states state);
wpa_states (*get_state)(void *ctx); wpa_states (*get_state)(void *ctx);
void (*req_scan)(void *ctx, int sec, int usec);
void (*cancel_scan)(void *ctx);
void (*deauthenticate)(void * ctx, int reason_code); void (*deauthenticate)(void * ctx, int reason_code);
void (*disassociate)(void *ctx, int reason_code); void (*disassociate)(void *ctx, int reason_code);
int (*set_key)(void *ctx, wpa_alg alg, int (*set_key)(void *ctx, wpa_alg alg,

View file

@ -120,18 +120,6 @@ static inline wpa_states wpa_sm_get_state(struct wpa_sm *sm)
return sm->ctx->get_state(sm->ctx->ctx); return sm->ctx->get_state(sm->ctx->ctx);
} }
static inline void wpa_sm_req_scan(struct wpa_sm *sm, int sec, int usec)
{
WPA_ASSERT(sm->ctx->req_scan);
sm->ctx->req_scan(sm->ctx->ctx, sec, usec);
}
static inline void wpa_sm_cancel_scan(struct wpa_sm *sm)
{
WPA_ASSERT(sm->ctx->cancel_scan);
sm->ctx->cancel_scan(sm->ctx->ctx);
}
static inline void wpa_sm_deauthenticate(struct wpa_sm *sm, int reason_code) static inline void wpa_sm_deauthenticate(struct wpa_sm *sm, int reason_code)
{ {
WPA_ASSERT(sm->ctx->deauthenticate); WPA_ASSERT(sm->ctx->deauthenticate);

View file

@ -14,6 +14,8 @@ ChangeLog for wpa_supplicant
* added option of using faster, but larger, routines in the internal * added option of using faster, but larger, routines in the internal
LibTomMath (for internal TLS implementation) to speed up DH and RSA LibTomMath (for internal TLS implementation) to speed up DH and RSA
calculations (CONFIG_INTERNAL_LIBTOMMATH_FAST=y) calculations (CONFIG_INTERNAL_LIBTOMMATH_FAST=y)
* fixed race condition between disassociation event and group key
handshake to avoid getting stuck in incorrect state [Bug 261]
2008-02-22 - v0.6.3 2008-02-22 - v0.6.3
* removed 'nai' and 'eappsk' network configuration variables that were * removed 'nai' and 'eappsk' network configuration variables that were

View file

@ -43,18 +43,6 @@ struct preauth_test_data {
}; };
static void _wpa_supplicant_req_scan(void *wpa_s, int sec, int usec)
{
wpa_supplicant_req_scan(wpa_s, sec, usec);
}
static void _wpa_supplicant_cancel_scan(void *wpa_s)
{
wpa_supplicant_cancel_scan(wpa_s);
}
static void _wpa_supplicant_disassociate(void *wpa_s, int reason_code) static void _wpa_supplicant_disassociate(void *wpa_s, int reason_code)
{ {
wpa_supplicant_disassociate(wpa_s, reason_code); wpa_supplicant_disassociate(wpa_s, reason_code);
@ -253,8 +241,6 @@ static void wpa_init_conf(struct wpa_supplicant *wpa_s, const char *ifname)
ctx->ctx = wpa_s; ctx->ctx = wpa_s;
ctx->set_state = _wpa_supplicant_set_state; ctx->set_state = _wpa_supplicant_set_state;
ctx->get_state = _wpa_supplicant_get_state; ctx->get_state = _wpa_supplicant_get_state;
ctx->req_scan = _wpa_supplicant_req_scan;
ctx->cancel_scan = _wpa_supplicant_cancel_scan;
ctx->deauthenticate = _wpa_supplicant_deauthenticate; ctx->deauthenticate = _wpa_supplicant_deauthenticate;
ctx->disassociate = _wpa_supplicant_disassociate; ctx->disassociate = _wpa_supplicant_disassociate;
ctx->set_key = wpa_supplicant_set_key; ctx->set_key = wpa_supplicant_set_key;

View file

@ -269,7 +269,6 @@ static void wpa_supplicant_notify_eapol_done(void *ctx)
wpa_s->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) { wpa_s->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE); wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE);
} else { } else {
wpa_supplicant_cancel_scan(wpa_s);
wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_cancel_auth_timeout(wpa_s);
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
} }
@ -353,18 +352,6 @@ static int _wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto,
} }
static void _wpa_supplicant_req_scan(void *wpa_s, int sec, int usec)
{
wpa_supplicant_req_scan(wpa_s, sec, usec);
}
static void _wpa_supplicant_cancel_scan(void *wpa_s)
{
wpa_supplicant_cancel_scan(wpa_s);
}
static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s) static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s)
{ {
wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_cancel_auth_timeout(wpa_s);
@ -397,12 +384,16 @@ static wpa_states _wpa_supplicant_get_state(void *wpa_s)
static void _wpa_supplicant_disassociate(void *wpa_s, int reason_code) static void _wpa_supplicant_disassociate(void *wpa_s, int reason_code)
{ {
wpa_supplicant_disassociate(wpa_s, reason_code); wpa_supplicant_disassociate(wpa_s, reason_code);
/* Schedule a scan to make sure we continue looking for networks */
wpa_supplicant_req_scan(wpa_s, 0, 0);
} }
static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code) static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code)
{ {
wpa_supplicant_deauthenticate(wpa_s, reason_code); wpa_supplicant_deauthenticate(wpa_s, reason_code);
/* Schedule a scan to make sure we continue looking for networks */
wpa_supplicant_req_scan(wpa_s, 0, 0);
} }
@ -574,8 +565,6 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
ctx->ctx = wpa_s; ctx->ctx = wpa_s;
ctx->set_state = _wpa_supplicant_set_state; ctx->set_state = _wpa_supplicant_set_state;
ctx->get_state = _wpa_supplicant_get_state; ctx->get_state = _wpa_supplicant_get_state;
ctx->req_scan = _wpa_supplicant_req_scan;
ctx->cancel_scan = _wpa_supplicant_cancel_scan;
ctx->deauthenticate = _wpa_supplicant_deauthenticate; ctx->deauthenticate = _wpa_supplicant_deauthenticate;
ctx->disassociate = _wpa_supplicant_disassociate; ctx->disassociate = _wpa_supplicant_disassociate;
ctx->set_key = wpa_supplicant_set_key; ctx->set_key = wpa_supplicant_set_key;