aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2008-02-19 20:45:28 (GMT)
committerJouni Malinen <j@w1.fi>2008-02-19 20:45:28 (GMT)
commitcdf7337cfcc00e5b33f626914c7368a1c6c19af5 (patch)
tree1587e17df58b9f29ec433e3cb4073ae685a4c211
parent9bd80cf08831f20c0004adc21c72f13702a8aee4 (diff)
downloadhostap-history-cdf7337cfcc00e5b33f626914c7368a1c6c19af5.zip
hostap-history-cdf7337cfcc00e5b33f626914c7368a1c6c19af5.tar.gz
hostap-history-cdf7337cfcc00e5b33f626914c7368a1c6c19af5.tar.bz2
Use more robust mechanism for determining when group key update is complete
GNoStations variable was not always correct as far as number of STAs that could really complete group key update is concerned. Furthermore, the pending counter was decreased for new WPA STAs if they completed their initial group key handshake during a scheduled group rekey. The new mechanism counts the STAs that are marked with GUpdateStationKeys when iterating through the potential STAs. If a STA is not in PTKINITDONE state, group (re-)key handshake will not be started for it.
-rw-r--r--hostapd/wpa.c43
-rw-r--r--hostapd/wpa_auth_i.h2
2 files changed, 16 insertions, 29 deletions
diff --git a/hostapd/wpa.c b/hostapd/wpa.c
index 08104c2..63efce2 100644
--- a/hostapd/wpa.c
+++ b/hostapd/wpa.c
@@ -1,6 +1,6 @@
/*
* hostapd - IEEE 802.11i-2004 / WPA Authenticator
- * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -1171,14 +1171,6 @@ SM_STATE(WPA_PTK, DISCONNECT)
SM_STATE(WPA_PTK, DISCONNECTED)
{
SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk);
- if (sm->sta_counted) {
- sm->group->GNoStations--;
- sm->sta_counted = 0;
- } else {
- wpa_printf(MSG_DEBUG, "WPA: WPA_PTK::DISCONNECTED - did not "
- "decrease GNoStations (STA " MACSTR ")",
- MAC2STR(sm->addr));
- }
sm->DeauthenticationRequest = FALSE;
}
@@ -1186,14 +1178,6 @@ SM_STATE(WPA_PTK, DISCONNECTED)
SM_STATE(WPA_PTK, AUTHENTICATION)
{
SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk);
- if (!sm->sta_counted) {
- sm->group->GNoStations++;
- sm->sta_counted = 1;
- } else {
- wpa_printf(MSG_DEBUG, "WPA: WPA_PTK::DISCONNECTED - did not "
- "increase GNoStations (STA " MACSTR ")",
- MAC2STR(sm->addr));
- }
os_memset(&sm->PTK, 0, sizeof(sm->PTK));
sm->PTK_valid = FALSE;
wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto,
@@ -1729,8 +1713,9 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
{
SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group);
sm->EAPOLKeyReceived = FALSE;
+ if (sm->GUpdateStationKeys)
+ sm->group->GKeyDoneStations--;
sm->GUpdateStationKeys = FALSE;
- sm->group->GKeyDoneStations--;
sm->GTimeoutCtr = 0;
/* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
@@ -1743,7 +1728,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
SM_STATE(WPA_PTK_GROUP, KEYERROR)
{
SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group);
- sm->group->GKeyDoneStations--;
+ if (sm->GUpdateStationKeys)
+ sm->group->GKeyDoneStations--;
sm->GUpdateStationKeys = FALSE;
sm->Disconnect = TRUE;
}
@@ -1830,6 +1816,12 @@ static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth,
static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
{
+ if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
+ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ "Not in PTKINITDONE; skip Group Key update");
+ return 0;
+ }
+ sm->group->GKeyDoneStations++;
sm->GUpdateStationKeys = TRUE;
wpa_sm_step(sm);
return 0;
@@ -1854,10 +1846,14 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
group->GM_igtk = group->GN_igtk;
group->GN_igtk = tmp;
#endif /* CONFIG_IEEE80211W */
- group->GKeyDoneStations = group->GNoStations;
+ /* "GKeyDoneStations = GNoStations" is done in more robust way by
+ * counting the STAs that are marked with GUpdateStationKeys instead of
+ * including all STAs that could be in not-yet-completed state. */
wpa_gtk_update(wpa_auth, group);
wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, NULL);
+ wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
+ group->GKeyDoneStations);
}
@@ -2307,13 +2303,6 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state "
"machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id);
- if (sm->group && sm->group != group && sm->sta_counted) {
- sm->group->GNoStations--;
- sm->sta_counted = 0;
- wpa_printf(MSG_DEBUG, "WLA: Decreased GNoStations for the "
- "previously used group state machine");
- }
-
sm->group = group;
return 0;
}
diff --git a/hostapd/wpa_auth_i.h b/hostapd/wpa_auth_i.h
index 1a4751b..8178f01 100644
--- a/hostapd/wpa_auth_i.h
+++ b/hostapd/wpa_auth_i.h
@@ -79,7 +79,6 @@ struct wpa_state_machine {
unsigned int in_step_loop:1;
unsigned int pending_deinit:1;
unsigned int started:1;
- unsigned int sta_counted:1;
unsigned int mgmt_frame_prot:1;
#ifdef CONFIG_IEEE80211R
unsigned int ft_completed:1;
@@ -121,7 +120,6 @@ struct wpa_group {
int vlan_id;
Boolean GInit;
- int GNoStations;
int GKeyDoneStations;
Boolean GTKReKey;
int GTK_len;