diff --git a/src/common/defs.h b/src/common/defs.h index 9a0300f8c..85e99329a 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -286,8 +286,9 @@ enum wpa_states { enum mfp_options { NO_MGMT_FRAME_PROTECTION = 0, MGMT_FRAME_PROTECTION_OPTIONAL = 1, - MGMT_FRAME_PROTECTION_REQUIRED = 2 + MGMT_FRAME_PROTECTION_REQUIRED = 2, }; +#define MGMT_FRAME_PROTECTION_DEFAULT 3 /** * enum hostapd_hw_mode - Hardware mode diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index a927f1cf6..e157845f7 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2042,6 +2042,9 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) ssid->ampdu_density = DEFAULT_AMPDU_DENSITY; #endif /* CONFIG_HT_OVERRIDES */ ssid->proactive_key_caching = -1; +#ifdef CONFIG_IEEE80211W + ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT; +#endif /* CONFIG_IEEE80211W */ } @@ -3035,6 +3038,7 @@ static const struct global_parse_data global_fields[] = { { INT(p2p_go_max_inactivity), 0 }, { INT_RANGE(auto_interworking, 0, 1), 0 }, { INT(okc), 0 }, + { INT(pmf), 0 }, }; #undef FUNC diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 3dbb4a080..c0aea0b33 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -782,6 +782,15 @@ struct wpa_config { * default behavior. */ int okc; + + /** + * pmf - Whether to enable/require PMF by default + * + * By default, PMF is disabled unless enabled by the per-network + * ieee80211w=1 or ieee80211w=2 parameter. pmf=1/2 can be used to change + * this default behavior. + */ + enum mfp_options pmf; }; diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index c25b4af6a..d66eac55a 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -680,7 +680,8 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT(disabled); INT(peerkey); #ifdef CONFIG_IEEE80211W - INT(ieee80211w); + write_int(f, "ieee80211w", ssid->ieee80211w, + MGMT_FRAME_PROTECTION_DEFAULT); #endif /* CONFIG_IEEE80211W */ STR(id_str); #ifdef CONFIG_P2P @@ -928,6 +929,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) config->auto_interworking); if (config->okc) fprintf(f, "okc=%d\n", config->okc); + if (config->pmf) + fprintf(f, "pmf=%d\n", config->pmf); } #endif /* CONFIG_NO_CONFIG_WRITE */ diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 99f37663b..a9a477aa1 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -361,6 +361,12 @@ struct wpa_ssid { * * This value is used to configure policy for management frame * protection (IEEE 802.11w). 0 = disabled, 1 = optional, 2 = required. + * This is disabled by default unless the default value has been changed + * with the global pmf=1/2 parameter. + * + * Internally, special value 3 is used to indicate that the parameter + * was not specified in the configuration (i.e., default behavior is + * followed). */ enum mfp_options ieee80211w; #endif /* CONFIG_IEEE80211W */ diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c index 48a1a9469..2750b6373 100644 --- a/wpa_supplicant/config_winreg.c +++ b/wpa_supplicant/config_winreg.c @@ -202,6 +202,7 @@ static int wpa_config_read_global_os_version(struct wpa_config *config, static int wpa_config_read_global(struct wpa_config *config, HKEY hk) { int errors = 0; + int val; wpa_config_read_reg_dword(hk, TEXT("ap_scan"), &config->ap_scan); wpa_config_read_reg_dword(hk, TEXT("fast_reauth"), @@ -272,6 +273,8 @@ static int wpa_config_read_global(struct wpa_config *config, HKEY hk) (int *) &config->disassoc_low_ack); wpa_config_read_reg_dword(hk, TEXT("okc"), &config->okc); + wpa_config_read_reg_dword(hk, TEXT("pmf"), &val); + config->pmf = val; return errors ? -1 : 0; } @@ -612,6 +615,7 @@ static int wpa_config_write_global(struct wpa_config *config, HKEY hk) config->disassoc_low_ack, 0); wpa_config_write_reg_dword(hk, TEXT("okc"), config->okc, 0); + wpa_config_write_reg_dword(hk, TEXT("pmf"), config->pmf, 0); return 0; } @@ -913,7 +917,8 @@ static int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id) INT(disabled); INT(peerkey); #ifdef CONFIG_IEEE80211W - INT(ieee80211w); + write_int(netw, "ieee80211w", ssid->ieee80211w, + MGMT_FRAME_PROTECTION_DEFAULT); #endif /* CONFIG_IEEE80211W */ STR(id_str); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 03c4d2fcd..13e5ab7e2 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -426,7 +426,9 @@ 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_REQUIRED) { + (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? + wpa_s->conf->pmf : ssid->ieee80211w) == + MGMT_FRAME_PROTECTION_REQUIRED) { wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - no mgmt " "frame protection"); break; diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index a5f60d322..a4d96ae6c 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -263,8 +263,9 @@ void sme_send_authentication(struct wpa_supplicant *wpa_s, #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W - wpa_s->sme.mfp = ssid->ieee80211w; - if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) { + wpa_s->sme.mfp = ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? + wpa_s->conf->pmf : ssid->ieee80211w; + 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; if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && @@ -1190,7 +1191,9 @@ 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 == 0) + if (ssid == NULL || + (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? + wpa_s->conf->pmf : ssid->ieee80211w) == 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 1a153f6fe..e77edb50d 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -930,7 +930,9 @@ 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_REQUIRED) { + (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? + wpa_s->conf->pmf : ssid->ieee80211w) == + MGMT_FRAME_PROTECTION_REQUIRED) { wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP " "that does not support management frame protection - " "reject"); @@ -1126,7 +1128,8 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, #ifdef CONFIG_IEEE80211W sel = ie.mgmt_group_cipher; - if (ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION || + if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? + wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION || !(ie.capabilities & WPA_CAPABILITY_MFPC)) sel = 0; if (sel & WPA_CIPHER_AES_128_CMAC) { @@ -1139,7 +1142,9 @@ 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); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP, + (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? + wpa_s->conf->pmf : ssid->ieee80211w)); #endif /* CONFIG_IEEE80211W */ if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) { @@ -1562,8 +1567,10 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, params.drop_unencrypted = use_crypt; #ifdef CONFIG_IEEE80211W - params.mgmt_frame_protection = ssid->ieee80211w; - if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION && bss) { + params.mgmt_frame_protection = + ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? + wpa_s->conf->pmf : ssid->ieee80211w; + 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; if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 && diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index e1000feb5..5f0dec66e 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -273,6 +273,14 @@ fast_reauth=1 # can be disabled with per-network proactive_key_caching=0 parameter. #okc=0 +# Protected Management Frames default +# This parameter can be used to set the default behavior for the ieee80211w +# parameter. By default, PMF is disabled unless enabled with the global pmf=1/2 +# parameter or with the per-network ieee80211w=1/2 parameter. With pmf=1/2, PMF +# is enabled/required by default, but can be disabled with the per-network +# ieee80211w parameter. +#pmf=0 + # Interworking (IEEE 802.11u) # Enable Interworking @@ -497,7 +505,7 @@ fast_reauth=1 # If not set, this defaults to: WPA-PSK WPA-EAP # # ieee80211w: whether management frame protection is enabled -# 0 = disabled (default) +# 0 = disabled (default unless changed with the global pmf parameter) # 1 = optional # 2 = required # The most common configuration options for this based on the PMF (protected