]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - wpa_supplicant/wpa_supplicant.c
FILS: Track completion with FILS shared key authentication offload
[thirdparty/hostap.git] / wpa_supplicant / wpa_supplicant.c
index 448a592710115ca0d331ec929431c081a6ea134d..498820a3d9b098b618b25f5018bf241ed5c6199c 100644 (file)
@@ -452,6 +452,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
 #ifdef CONFIG_TESTING_OPTIONS
        l2_packet_deinit(wpa_s->l2_test);
        wpa_s->l2_test = NULL;
+       os_free(wpa_s->get_pref_freq_list_override);
+       wpa_s->get_pref_freq_list_override = NULL;
 #endif /* CONFIG_TESTING_OPTIONS */
 
        if (wpa_s->conf != NULL) {
@@ -524,6 +526,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
 
        os_free(wpa_s->manual_scan_freqs);
        wpa_s->manual_scan_freqs = NULL;
+       os_free(wpa_s->select_network_scan_freqs);
+       wpa_s->select_network_scan_freqs = NULL;
 
        os_free(wpa_s->manual_sched_scan_freqs);
        wpa_s->manual_sched_scan_freqs = NULL;
@@ -617,6 +621,9 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
 
        wpas_flush_fils_hlp_req(wpa_s);
+
+       wpabuf_free(wpa_s->ric_ies);
+       wpa_s->ric_ies = NULL;
 }
 
 
@@ -990,7 +997,8 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
         * TODO: should notify EAPOL SM about changes in opensc_engine_path,
         * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
         */
-       if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
+       if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
+           wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
                /*
                 * Clear forced success to clear EAP state for next
                 * authentication.
@@ -1326,6 +1334,11 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
                wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
                wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
 #endif /* CONFIG_HS20 */
+#ifdef CONFIG_OWE
+       } else if (sel & WPA_KEY_MGMT_OWE) {
+               wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
+               wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
+#endif /* CONFIG_OWE */
        } else {
                wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
                        "authenticated key management type");
@@ -1868,11 +1881,6 @@ static int drv_supports_vht(struct wpa_supplicant *wpa_s,
        u8 channel;
        int i;
 
-#ifdef CONFIG_HT_OVERRIDES
-       if (ssid->disable_ht)
-               return 0;
-#endif /* CONFIG_HT_OVERRIDES */
-
        hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
        if (hw_mode == NUM_HOSTAPD_MODES)
                return 0;
@@ -2186,6 +2194,11 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
        struct ieee80211_vht_capabilities vhtcaps;
        struct ieee80211_vht_capabilities vhtcaps_mask;
 #endif /* CONFIG_VHT_OVERRIDES */
+#ifdef CONFIG_FILS
+       const u8 *realm, *username, *rrk;
+       size_t realm_len, username_len, rrk_len;
+       u16 next_seq_num;
+#endif /* CONFIG_FILS */
 
        if (deinit) {
                if (work->started) {
@@ -2273,7 +2286,28 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
                                algs |= WPA_AUTH_ALG_LEAP;
                }
        }
+
+#ifdef CONFIG_FILS
+       /* Clear FILS association */
+       wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
+
+       if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
+           ssid->eap.erp && wpa_key_mgmt_fils(ssid->key_mgmt) &&
+           eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
+                                 &username_len, &realm, &realm_len,
+                                 &next_seq_num, &rrk, &rrk_len) == 0) {
+               algs = WPA_AUTH_ALG_FILS;
+               params.fils_erp_username = username;
+               params.fils_erp_username_len = username_len;
+               params.fils_erp_realm = realm;
+               params.fils_erp_realm_len = realm_len;
+               params.fils_erp_next_seq_num = next_seq_num;
+               params.fils_erp_rrk = rrk;
+               params.fils_erp_rrk_len = rrk_len;
+       }
+#endif /* CONFIG_FILS */
 #endif /* IEEE8021X_EAPOL */
+
        wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
        if (ssid->auth_alg) {
                algs = ssid->auth_alg;
@@ -2285,12 +2319,19 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
                    wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
            wpa_key_mgmt_wpa(ssid->key_mgmt)) {
                int try_opportunistic;
+               const u8 *cache_id = NULL;
+
                try_opportunistic = (ssid->proactive_key_caching < 0 ?
                                     wpa_s->conf->okc :
                                     ssid->proactive_key_caching) &&
                        (ssid->proto & WPA_PROTO_RSN);
+#ifdef CONFIG_FILS
+               if (wpa_key_mgmt_fils(ssid->key_mgmt))
+                       cache_id = wpa_bss_get_fils_cache_id(bss);
+#endif /* CONFIG_FILS */
                if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
-                                           ssid, try_opportunistic) == 0)
+                                           ssid, try_opportunistic,
+                                           cache_id) == 0)
                        eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
                wpa_ie_len = sizeof(wpa_ie);
                if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
@@ -2555,6 +2596,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
        params.key_mgmt_suite = wpa_s->key_mgmt;
        params.wpa_proto = wpa_s->wpa_proto;
        params.auth_alg = algs;
+       wpa_s->auth_alg = params.auth_alg;
        params.mode = ssid->mode;
        params.bg_scan_period = ssid->bg_scan_period;
        for (i = 0; i < NUM_WEP_KEYS; i++) {
@@ -3573,6 +3615,7 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
 
        os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
        if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
+           wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
            eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
                return;
        wpa_drv_poll(wpa_s);
@@ -4367,6 +4410,20 @@ static void radio_work_free(struct wpa_radio_work *work)
 }
 
 
+static int radio_work_is_connect(struct wpa_radio_work *work)
+{
+       return os_strcmp(work->type, "sme-connect") == 0 ||
+               os_strcmp(work->type, "connect") == 0;
+}
+
+
+static int radio_work_is_scan(struct wpa_radio_work *work)
+{
+       return os_strcmp(work->type, "scan") == 0 ||
+               os_strcmp(work->type, "p2p-scan") == 0;
+}
+
+
 static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
 {
        struct wpa_radio_work *active_work = NULL;
@@ -4396,8 +4453,7 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
                return NULL;
        }
 
-       if (os_strcmp(active_work->type, "sme-connect") == 0 ||
-           os_strcmp(active_work->type, "connect") == 0) {
+       if (radio_work_is_connect(active_work)) {
                /*
                 * If the active work is either connect or sme-connect,
                 * do not parallelize them with other radio works.
@@ -4416,10 +4472,20 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
                 * If connect or sme-connect are enqueued, parallelize only
                 * those operations ahead of them in the queue.
                 */
-               if (os_strcmp(tmp->type, "connect") == 0 ||
-                   os_strcmp(tmp->type, "sme-connect") == 0)
+               if (radio_work_is_connect(tmp))
                        break;
 
+               /* Serialize parallel scan and p2p_scan operations on the same
+                * interface since the driver_nl80211 mechanism for tracking
+                * scan cookies does not yet have support for this. */
+               if (active_work->wpa_s == tmp->wpa_s &&
+                   radio_work_is_scan(active_work) &&
+                   radio_work_is_scan(tmp)) {
+                       wpa_dbg(active_work->wpa_s, MSG_DEBUG,
+                               "Do not start work '%s' when another work '%s' is already scheduled",
+                               tmp->type, active_work->type);
+                       continue;
+               }
                /*
                 * Check that the radio works are distinct and
                 * on different bands.
@@ -5951,6 +6017,7 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
        case WPA_CTRL_REQ_SIM:
                str_clear_free(eap->external_sim_resp);
                eap->external_sim_resp = os_strdup(value);
+               eap->pending_req_sim = 0;
                break;
        case WPA_CTRL_REQ_PSK_PASSPHRASE:
                if (wpa_config_set(ssid, "psk", value, 0) < 0)