Browse Source

Clear various flags on re-association to allow key_mgmt changes

If a STA reassociates and changes key_mgmt (e.g., from WPA-PSK to WPS),
hostapd needs to reset some of the existing STA and WPA state machine
variables to allow correct processing for the new association.
Jouni Malinen 16 years ago
parent
commit
a8d05fca5f
5 changed files with 19 additions and 2 deletions
  1. 2 1
      hostapd/hostapd.c
  2. 3 1
      hostapd/ieee802_11.c
  3. 1 0
      hostapd/ieee802_1x.c
  4. 12 0
      hostapd/wpa.c
  5. 1 0
      hostapd/wpa.h

+ 2 - 1
hostapd/hostapd.c

@@ -254,7 +254,8 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
 	/* Start IEEE 802.1X authentication process for new stations */
 	/* Start IEEE 802.1X authentication process for new stations */
 	ieee802_1x_new_station(hapd, sta);
 	ieee802_1x_new_station(hapd, sta);
 	if (reassoc) {
 	if (reassoc) {
-		if (sta->auth_alg != WLAN_AUTH_FT)
+		if (sta->auth_alg != WLAN_AUTH_FT &&
+		    !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
 			wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
 			wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
 	} else
 	} else
 		wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
 		wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);

+ 3 - 1
hostapd/ieee802_11.c

@@ -833,6 +833,7 @@ static void handle_assoc(struct hostapd_data *hapd,
 		wpa_ie_len = 0;
 		wpa_ie_len = 0;
 	}
 	}
 #ifdef CONFIG_WPS
 #ifdef CONFIG_WPS
+	sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
 	if (hapd->conf->wps_state && wpa_ie == NULL) {
 	if (hapd->conf->wps_state && wpa_ie == NULL) {
 		if (elems.wps_ie) {
 		if (elems.wps_ie) {
 			wpa_printf(MSG_DEBUG, "STA included WPS IE in "
 			wpa_printf(MSG_DEBUG, "STA included WPS IE in "
@@ -930,7 +931,8 @@ static void handle_assoc(struct hostapd_data *hapd,
 				goto fail;
 				goto fail;
 		}
 		}
 #endif /* CONFIG_IEEE80211R */
 #endif /* CONFIG_IEEE80211R */
-	}
+	} else
+		wpa_auth_sta_no_wpa(sta->wpa_sm);
 
 
 	if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
 	if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
 		sta->flags |= WLAN_STA_NONERP;
 		sta->flags |= WLAN_STA_NONERP;

+ 1 - 0
hostapd/ieee802_1x.c

@@ -848,6 +848,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
 	}
 	}
 
 
 #ifdef CONFIG_WPS
 #ifdef CONFIG_WPS
+	sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
 	if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS)) {
 	if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS)) {
 		/*
 		/*
 		 * Delay EAPOL frame transmission until a possible WPS
 		 * Delay EAPOL frame transmission until a possible WPS

+ 12 - 0
hostapd/wpa.c

@@ -516,6 +516,18 @@ void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
 }
 }
 
 
 
 
+void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
+{
+	/* WPA/RSN was not used - clear WPA state. This is needed if the STA
+	 * reassociates back to the same AP while the previous entry for the
+	 * STA has not yet been removed. */
+	if (sm == NULL)
+		return;
+
+	sm->wpa_key_mgmt = 0;
+}
+
+
 static void wpa_free_sta_sm(struct wpa_state_machine *sm)
 static void wpa_free_sta_sm(struct wpa_state_machine *sm)
 {
 {
 	os_free(sm->last_rx_eapol_key);
 	os_free(sm->last_rx_eapol_key);

+ 1 - 0
hostapd/wpa.h

@@ -229,6 +229,7 @@ struct wpa_state_machine *
 wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr);
 wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr);
 void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
 void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
 			     struct wpa_state_machine *sm);
 			     struct wpa_state_machine *sm);
+void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm);
 void wpa_auth_sta_deinit(struct wpa_state_machine *sm);
 void wpa_auth_sta_deinit(struct wpa_state_machine *sm);
 void wpa_receive(struct wpa_authenticator *wpa_auth,
 void wpa_receive(struct wpa_authenticator *wpa_auth,
 		 struct wpa_state_machine *sm,
 		 struct wpa_state_machine *sm,