WPS: Parse Request Type from WPS IE in (Re)AssocReq and derive mgmt keys
[wpasupplicant] / hostapd / ieee802_1x.c
index f8e421a..5d3cbfb 100644 (file)
@@ -670,7 +670,8 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
        u16 datalen;
        struct rsn_pmksa_cache_entry *pmksa;
 
-       if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
+       if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
+           !hapd->conf->wps_state)
                return;
 
        wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR,
@@ -718,7 +719,8 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
                return;
        }
 
-       if (!hapd->conf->ieee802_1x ||
+       if ((!hapd->conf->ieee802_1x &&
+            !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) ||
            wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm)))
                return;
 
@@ -728,6 +730,18 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
                                                 sta);
                if (!sta->eapol_sm)
                        return;
+
+#ifdef CONFIG_WPS
+               if (!hapd->conf->ieee802_1x &&
+                   ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) ==
+                    WLAN_STA_MAYBE_WPS)) {
+                       /*
+                        * Delay EAPOL frame transmission until a possible WPS
+                        * STA initiates the handshake with EAPOL-Start.
+                        */
+                       sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
+               }
+#endif /* CONFIG_WPS */
        }
 
        /* since we support version 1, we can ignore version field and proceed
@@ -766,6 +780,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
                               "from STA");
                sta->acct_terminate_cause =
                        RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
+               accounting_sta_stop(hapd, sta);
                sta->eapol_sm->eapolLogoff = TRUE;
                sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++;
                break;
@@ -800,6 +815,18 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
        int reassoc = 1;
        int force_1x = 0;
 
+#ifdef CONFIG_WPS
+       if (hapd->conf->wps_state &&
+           (sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
+               /*
+                * Need to enable IEEE 802.1X/EAPOL state machines for possible
+                * WPS handshake even if IEEE 802.1X/EAPOL is not used for
+                * authentication in this BSS.
+                */
+               force_1x = 1;
+       }
+#endif /* CONFIG_WPS */
+
        if ((!force_1x && !hapd->conf->ieee802_1x) ||
            wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm)))
                return;
@@ -820,6 +847,16 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
                reassoc = 0;
        }
 
+#ifdef CONFIG_WPS
+       if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS)) {
+               /*
+                * Delay EAPOL frame transmission until a possible WPS
+                * initiates the handshake with EAPOL-Start.
+                */
+               sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
+       }
+#endif /* CONFIG_WPS */
+
        sta->eapol_sm->eap_if->portEnabled = TRUE;
 
        pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
@@ -1605,8 +1642,14 @@ int ieee802_1x_init(struct hostapd_data *hapd)
        conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len;
        conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key;
        conf.eap_fast_a_id = hapd->conf->eap_fast_a_id;
+       conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len;
+       conf.eap_fast_a_id_info = hapd->conf->eap_fast_a_id_info;
+       conf.eap_fast_prov = hapd->conf->eap_fast_prov;
+       conf.pac_key_lifetime = hapd->conf->pac_key_lifetime;
+       conf.pac_key_refresh_time = hapd->conf->pac_key_refresh_time;
        conf.eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind;
        conf.tnc = hapd->conf->tnc;
+       conf.wps = hapd->wps;
 
        os_memset(&cb, 0, sizeof(cb));
        cb.eapol_send = ieee802_1x_eapol_send;