From 3f56a2b7460a57a2b68b48b936be134bf04aa36d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 26 Jan 2015 17:40:22 +0200 Subject: [PATCH] Ignore pmf=1 default if driver does not support PMF Connection with a PMF enabled AP will fail if we try to negotiate PMF while the local driver does not support this. Since pmf=1 does not require PMF for a successful connection, it can be ignored in such a case to avoid connectivity issues with invalid configuration. This makes it somewhat easier to allow upper layer programs to use pmf=1 default regardless of driver capabilities. Signed-off-by: Jouni Malinen --- wpa_supplicant/events.c | 3 +-- wpa_supplicant/sme.c | 7 ++---- wpa_supplicant/wpa_supplicant.c | 38 +++++++++++++++++++++++-------- wpa_supplicant/wpa_supplicant_i.h | 1 + 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 07d160783..ee034d5e5 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -476,8 +476,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, #ifdef CONFIG_IEEE80211W if (!(ie.capabilities & WPA_CAPABILITY_MFPC) && - (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? - wpa_s->conf->pmf : ssid->ieee80211w) == + wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) { wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - no mgmt " "frame protection"); diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index d34668a5a..c2b0990a6 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -384,8 +384,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W - wpa_s->sme.mfp = ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? - wpa_s->conf->pmf : ssid->ieee80211w; + wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid); if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) { const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); struct wpa_ie_data _ie; @@ -1547,9 +1546,7 @@ void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa, if (wpa_s->wpa_state != WPA_COMPLETED) return; ssid = wpa_s->current_ssid; - if (ssid == NULL || - (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? - wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION) + if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) return; if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) return; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 68c3cdc6a..434847d52 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -962,9 +962,7 @@ static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s, #ifdef CONFIG_IEEE80211W if (!(ie->capabilities & WPA_CAPABILITY_MFPC) && - (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? - wpa_s->conf->pmf : ssid->ieee80211w) == - MGMT_FRAME_PROTECTION_REQUIRED) { + wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) { wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP " "that does not support management frame protection - " "reject"); @@ -1203,8 +1201,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, #ifdef CONFIG_IEEE80211W sel = ie.mgmt_group_cipher; - if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? - wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION || + if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION || !(ie.capabilities & WPA_CAPABILITY_MFPC)) sel = 0; if (sel & WPA_CIPHER_AES_128_CMAC) { @@ -1230,8 +1227,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP, wpa_s->mgmt_group_cipher); wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP, - (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? - wpa_s->conf->pmf : ssid->ieee80211w)); + wpas_get_ssid_pmf(wpa_s, ssid)); #endif /* CONFIG_IEEE80211W */ if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) { @@ -2169,9 +2165,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) params.drop_unencrypted = use_crypt; #ifdef CONFIG_IEEE80211W - params.mgmt_frame_protection = - ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? - wpa_s->conf->pmf : ssid->ieee80211w; + params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid); if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) { const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); struct wpa_ie_data ie; @@ -4898,6 +4892,30 @@ int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) } +int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) +{ +#ifdef CONFIG_IEEE80211W + if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) { + if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL && + !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) { + /* + * Driver does not support BIP -- ignore pmf=1 default + * since the connection with PMF would fail and the + * configuration does not require PMF to be enabled. + */ + return NO_MGMT_FRAME_PROTECTION; + } + + return wpa_s->conf->pmf; + } + + return ssid->ieee80211w; +#else /* CONFIG_IEEE80211W */ + return NO_MGMT_FRAME_PROTECTION; +#endif /* CONFIG_IEEE80211W */ +} + + int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s) { if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P) diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index d1938fab7..7d22000a0 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1113,6 +1113,7 @@ static inline int network_is_persistent_group(struct wpa_ssid *ssid) } int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); +int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); int wpas_init_ext_pw(struct wpa_supplicant *wpa_s);