]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Process Transition Disable KDE in station mode
authorJouni Malinen <jouni@codeaurora.org>
Wed, 25 Mar 2020 22:10:16 +0000 (00:10 +0200)
committerJouni Malinen <j@w1.fi>
Wed, 25 Mar 2020 22:13:14 +0000 (00:13 +0200)
Check whether the Transition Disable KDE is received from an
authenticated AP and if so, whether it contains valid indication for
disabling a transition mode. If that is the case, update the local
network profile by removing the less secure options.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
src/common/wpa_common.c
src/common/wpa_common.h
src/common/wpa_ctrl.h
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
wpa_supplicant/wpas_glue.c

index aaeb130238f4cf11b81d10694495e33cf6978f4c..1284743023c6b86de47bc39404541432ab8c1301 100644 (file)
@@ -2784,6 +2784,16 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
                return 0;
        }
 
+       if (pos[1] >= RSN_SELECTOR_LEN + 1 &&
+           RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_TRANSITION_DISABLE) {
+               ie->transition_disable = pos + 2 + RSN_SELECTOR_LEN;
+               ie->transition_disable_len = pos[1] - RSN_SELECTOR_LEN;
+               wpa_hexdump(MSG_DEBUG,
+                           "WPA: Transition Disable KDE in EAPOL-Key",
+                           pos, pos[1] + 2);
+               return 0;
+       }
+
        return 0;
 }
 
index bcdf160b6d5bfde67396863ce1c9fab9bb35e988..da58159e4316be107d4b854e169660b799e10344 100644 (file)
@@ -516,6 +516,8 @@ struct wpa_eapol_ie_parse {
        size_t ftie_len;
        const u8 *ip_addr_req;
        const u8 *ip_addr_alloc;
+       const u8 *transition_disable;
+       size_t transition_disable_len;
        const u8 *oci;
        size_t oci_len;
        const u8 *osen;
index 12906708a22aba17687325c5ab9522b9a4b3839a..7471f0d15384de5a7a00c76b516b365a69961290 100644 (file)
@@ -380,6 +380,9 @@ extern "C" {
 #define WDS_STA_INTERFACE_ADDED "WDS-STA-INTERFACE-ADDED "
 #define WDS_STA_INTERFACE_REMOVED "WDS-STA-INTERFACE-REMOVED "
 
+/* Transition mode disabled indication - followed by bitmap */
+#define TRANSITION_DISABLE "TRANSITION-DISABLE "
+
 #ifndef BIT
 #define BIT(x) (1U << (x))
 #endif
index 14fe0846d6dfea1a60d2b8afca429f2d34da240a..1c896642212835f2869571abbdd08d272ba53583 100644 (file)
@@ -1771,6 +1771,8 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
                        sm->cur_pmksa = sa;
        }
 
+       if (ie.transition_disable)
+               wpa_sm_transition_disable(sm, ie.transition_disable[0]);
        sm->msg_3_of_4_ok = 1;
        return;
 
@@ -4809,6 +4811,9 @@ int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len)
        sm->fils_completed = 1;
        forced_memzero(&gd, sizeof(gd));
 
+       if (kde.transition_disable)
+               wpa_sm_transition_disable(sm, kde.transition_disable[0]);
+
        return 0;
 fail:
        forced_memzero(&gd, sizeof(gd));
index 02b5df883a6e0bb5c1bf8883442db29483f976ed..1f22f2f26a9e5d695fd29da258cd24817060bca2 100644 (file)
@@ -85,6 +85,7 @@ struct wpa_sm_ctx {
        void (*fils_hlp_rx)(void *ctx, const u8 *dst, const u8 *src,
                            const u8 *pkt, size_t pkt_len);
        int (*channel_info)(void *ctx, struct wpa_channel_info *ci);
+       void (*transition_disable)(void *ctx, u8 bitmap);
 };
 
 
index 5fd70a498b217dbe24a902c84e3f09e46d6f08db..5178c28cb4909ed167a8ef602eb106a45a250912 100644 (file)
@@ -426,6 +426,12 @@ static inline int wpa_sm_channel_info(struct wpa_sm *sm,
        return sm->ctx->channel_info(sm->ctx->ctx, ci);
 }
 
+static inline void wpa_sm_transition_disable(struct wpa_sm *sm, u8 bitmap)
+{
+       if (sm->ctx->transition_disable)
+               sm->ctx->transition_disable(sm->ctx->ctx, bitmap);
+}
+
 
 int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk,
                       int ver, const u8 *dest, u16 proto,
index a3049daf54f82ce0a772ec59bb63b34000b0d711..200a439cb3116e89212df6f765a1087a47b1dd57 100644 (file)
@@ -1238,6 +1238,73 @@ static int wpa_supplicant_channel_info(void *_wpa_s,
        return wpa_drv_channel_info(wpa_s, ci);
 }
 
+
+static void disable_wpa_wpa2(struct wpa_ssid *ssid)
+{
+       ssid->proto &= ~WPA_PROTO_WPA;
+       ssid->proto |= WPA_PROTO_RSN;
+       ssid->key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
+                           WPA_KEY_MGMT_PSK_SHA256);
+       ssid->group_cipher &= ~WPA_CIPHER_TKIP;
+       if (!(ssid->group_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
+                                   WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256)))
+               ssid->group_cipher |= WPA_CIPHER_CCMP;
+       ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+}
+
+
+static void wpa_supplicant_transition_disable(void *_wpa_s, u8 bitmap)
+{
+       struct wpa_supplicant *wpa_s = _wpa_s;
+       struct wpa_ssid *ssid;
+       int changed = 0;
+
+       wpa_msg(wpa_s, MSG_INFO, TRANSITION_DISABLE "%02x", bitmap);
+
+       ssid = wpa_s->current_ssid;
+       if (!ssid)
+               return;
+
+       if ((bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) &&
+           wpa_key_mgmt_sae(wpa_s->key_mgmt) &&
+           (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) &&
+           (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED ||
+            (ssid->group_cipher & WPA_CIPHER_TKIP))) {
+               wpa_printf(MSG_DEBUG,
+                          "WPA3-Personal transition mode disabled based on AP notification");
+               disable_wpa_wpa2(ssid);
+               changed = 1;
+       }
+
+       if ((bitmap & TRANSITION_DISABLE_WPA3_ENTERPRISE) &&
+           wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
+           (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X |
+                              WPA_KEY_MGMT_FT_IEEE8021X |
+                              WPA_KEY_MGMT_IEEE8021X_SHA256)) &&
+           (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED ||
+            (ssid->group_cipher & WPA_CIPHER_TKIP))) {
+               disable_wpa_wpa2(ssid);
+               changed = 1;
+       }
+
+       if ((bitmap & TRANSITION_DISABLE_ENHANCED_OPEN) &&
+           wpa_s->key_mgmt == WPA_KEY_MGMT_OWE &&
+           (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
+           !ssid->owe_only) {
+               ssid->owe_only = 1;
+               changed = 1;
+       }
+
+       if (!changed)
+               return;
+
+#ifndef CONFIG_NO_CONFIG_WRITE
+       if (wpa_s->conf->update_config &&
+           wpa_config_write(wpa_s->confname, wpa_s->conf))
+               wpa_printf(MSG_DEBUG, "Failed to update configuration");
+#endif /* CONFIG_NO_CONFIG_WRITE */
+}
+
 #endif /* CONFIG_NO_WPA */
 
 
@@ -1290,6 +1357,7 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
        ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk;
        ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx;
        ctx->channel_info = wpa_supplicant_channel_info;
+       ctx->transition_disable = wpa_supplicant_transition_disable;
 
        wpa_s->wpa = wpa_sm_init(ctx);
        if (wpa_s->wpa == NULL) {