aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni@codeaurora.org>2020-03-25 22:10:16 (GMT)
committerJouni Malinen <j@w1.fi>2020-03-25 22:13:14 (GMT)
commit9d1857cf35c8b52c21df672bd277058af542edce (patch)
treeac13e6ffcba525d1be707b4851b79a3366a45a8a
parent82cc0b0cc2dce13064e9095cf32f454208477a87 (diff)
downloadhostap-9d1857cf35c8b52c21df672bd277058af542edce.zip
hostap-9d1857cf35c8b52c21df672bd277058af542edce.tar.gz
hostap-9d1857cf35c8b52c21df672bd277058af542edce.tar.bz2
Process Transition Disable KDE in station mode
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>
-rw-r--r--src/common/wpa_common.c10
-rw-r--r--src/common/wpa_common.h2
-rw-r--r--src/common/wpa_ctrl.h3
-rw-r--r--src/rsn_supp/wpa.c5
-rw-r--r--src/rsn_supp/wpa.h1
-rw-r--r--src/rsn_supp/wpa_i.h6
-rw-r--r--wpa_supplicant/wpas_glue.c68
7 files changed, 95 insertions, 0 deletions
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index aaeb130..1284743 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -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;
}
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index bcdf160..da58159 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -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;
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 1290670..7471f0d 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -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
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 14fe084..1c89664 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -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));
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 02b5df8..1f22f2f 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -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);
};
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 5fd70a4..5178c28 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -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,
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index a3049da..200a439 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -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) {