summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2017-04-28 09:59:34 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2017-04-28 09:59:34 +0200
commita7fdf09848070990710529946fff782fc60c1461 (patch)
tree244bc8ba5428a9b88e186a0493a1dbcd0977be2c
parent1f40bb13cf0789e31fb0206f954850a662b8f97c (diff)
parentacb70d84f9cc58cb09e02d68d01660f6d5087b34 (diff)
wifi: merge branch 'bg/wifi-pmf-bgo748367-pt2'
Per-connection configurable PMF (802.11w) support. https://bugzilla.gnome.org/show_bug.cgi?id=748367
-rw-r--r--clients/common/nm-meta-setting-desc.c8
-rw-r--r--clients/common/settings-docs.c.in1
-rw-r--r--libnm-core/nm-setting-wireless-security.c79
-rw-r--r--libnm-core/nm-setting-wireless-security.h22
-rw-r--r--libnm/libnm.ver6
-rw-r--r--man/NetworkManager.conf.xml5
-rw-r--r--src/devices/wifi/nm-device-wifi.c36
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c20
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c11
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c1
-rw-r--r--src/supplicant/nm-supplicant-config.c59
-rw-r--r--src/supplicant/nm-supplicant-config.h1
-rw-r--r--src/supplicant/nm-supplicant-interface.c54
-rw-r--r--src/supplicant/nm-supplicant-interface.h1
-rw-r--r--src/supplicant/nm-supplicant-settings-verify.c1
-rw-r--r--src/supplicant/tests/test-supplicant-config.c10
16 files changed, 234 insertions, 81 deletions
diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c
index 98a5c38cd9..6807735937 100644
--- a/clients/common/nm-meta-setting-desc.c
+++ b/clients/common/nm-meta-setting-desc.c
@@ -6926,6 +6926,14 @@ static const NMMetaPropertyInfo *const property_infos_WIRELESS_SECURITY[] = {
.values_static = wifi_sec_valid_groups,
),
),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_PMF,
+ .property_type = &_pt_gobject_enum,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA (
+ PROPERTY_TYP_DATA_SUBTYPE (gobject_enum,
+ .get_gtype = nm_setting_wireless_security_pmf_get_type,
+ ),
+ ),
+ ),
PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME,
.property_type = &_pt_gobject_string,
),
diff --git a/clients/common/settings-docs.c.in b/clients/common/settings-docs.c.in
index 0ebddc6185..5710ce73a5 100644
--- a/clients/common/settings-docs.c.in
+++ b/clients/common/settings-docs.c.in
@@ -29,6 +29,7 @@
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME N_("The login username for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\").")
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_NAME N_("The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PAIRWISE N_("A list of pairwise encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty. Each list element may be one of \"tkip\" or \"ccmp\".")
+#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PMF N_("Indicates whether Protected Management Frames (802.11w) must be enabled for the connection. One of NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE (1) (disable PMF), NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (2) (enable PMF if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (3) (enable PMF and fail if not supported). When set to NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) and no global default is set, PMF will be optionally enabled.")
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PROTO N_("List of strings specifying the allowed WPA protocol versions to use. Each element may be one \"wpa\" (allow WPA) or \"rsn\" (allow WPA2/RSN). If not specified, both WPA and RSN connections are allowed.")
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PSK N_("Pre-Shared-Key for WPA networks. If the key is 64-characters long, it must contain only hexadecimal characters and is interpreted as a hexadecimal WPA key. Otherwise, the key must be between 8 and 63 ASCII characters (as specified in the 802.11i standard) and is interpreted as a WPA passphrase, and is hashed to derive the actual WPA-PSK used when connecting to the Wi-Fi network.")
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS N_("Flags indicating how to handle the \"psk\" property.")
diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c
index 70bdf7541d..dd5e9b5a9f 100644
--- a/libnm-core/nm-setting-wireless-security.c
+++ b/libnm-core/nm-setting-wireless-security.c
@@ -65,6 +65,7 @@ typedef struct {
GSList *proto; /* GSList of strings */
GSList *pairwise; /* GSList of strings */
GSList *group; /* GSList of strings */
+ guint pmf;
/* LEAP */
char *leap_username;
@@ -93,6 +94,7 @@ enum {
PROP_PROTO,
PROP_PAIRWISE,
PROP_GROUP,
+ PROP_PMF,
PROP_LEAP_USERNAME,
PROP_WEP_KEY0,
PROP_WEP_KEY1,
@@ -573,6 +575,22 @@ nm_setting_wireless_security_clear_groups (NMSettingWirelessSecurity *setting)
g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_GROUP);
}
+/*
+ * nm_setting_wireless_security_get_pmf:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the #NMSettingWirelessSecurity:pmf property of the setting
+ *
+ * Since: 1.10
+ **/
+NMSettingWirelessSecurityPmf
+nm_setting_wireless_security_get_pmf (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0);
+
+ return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->pmf;
+}
+
/**
* nm_setting_wireless_security_get_psk:
* @setting: the #NMSettingWirelessSecurity
@@ -1013,6 +1031,30 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
}
}
+ if (priv->pmf > NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PMF);
+ return FALSE;
+ }
+
+ if ( NM_IN_SET (priv->pmf,
+ NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL,
+ NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED)
+ && !NM_IN_STRSET (priv->key_mgmt, "wpa-eap", "wpa-psk")) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' can only be used with '%s=%s or '%s=%s'"),
+ priv->pmf == NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL ? "optional" : "required",
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap",
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk");
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PMF);
+ return FALSE;
+ }
+
return TRUE;
}
@@ -1198,6 +1240,9 @@ set_property (GObject *object, guint prop_id,
g_slist_free_full (priv->group, g_free);
priv->group = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE);
break;
+ case PROP_PMF:
+ priv->pmf = g_value_get_uint (value);
+ break;
case PROP_LEAP_USERNAME:
g_free (priv->leap_username);
priv->leap_username = g_value_dup_string (value);
@@ -1270,6 +1315,9 @@ get_property (GObject *object, guint prop_id,
case PROP_GROUP:
g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->group, TRUE));
break;
+ case PROP_PMF:
+ g_value_set_uint (value, nm_setting_wireless_security_get_pmf (setting));
+ break;
case PROP_LEAP_USERNAME:
g_value_set_string (value, priv->leap_username);
break;
@@ -1468,6 +1516,37 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
G_PARAM_STATIC_STRINGS));
/**
+ * NMSettingWirelessSecurity:pmf:
+ *
+ * Indicates whether Protected Management Frames (802.11w) must be enabled
+ * for the connection. One of %NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT
+ * (use global default value), %NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE
+ * (disable PMF), %NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (enable PMF if
+ * the supplicant and the access point support it) or
+ * %NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (enable PMF and fail if not
+ * supported). When set to %NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT and no
+ * global default is set, PMF will be optionally enabled.
+ *
+ * Since: 1.10
+ **/
+ /* ---ifcfg-rh---
+ * property: pmf
+ * variable: PMF(+)
+ * values: default, disable, optional, required
+ * description: Enables or disables PMF (802.11w)
+ * example: PMF=required
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PMF,
+ g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_PMF, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
* NMSettingWirelessSecurity:leap-username:
*
* The login username for legacy LEAP connections (ie, key-mgmt =
diff --git a/libnm-core/nm-setting-wireless-security.h b/libnm-core/nm-setting-wireless-security.h
index ae252f1124..2c6dcaad62 100644
--- a/libnm-core/nm-setting-wireless-security.h
+++ b/libnm-core/nm-setting-wireless-security.h
@@ -71,12 +71,31 @@ typedef enum {
NM_WEP_KEY_TYPE_LAST = NM_WEP_KEY_TYPE_PASSPHRASE
} NMWepKeyType;
+/**
+ * NMSettingWirelessSecurityPmf:
+ * @NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT: use the default value
+ * @NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE: disable PMF
+ * @NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL: enable PMF if the supplicant and the AP support it
+ * @NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED: require PMF and fail if not available
+ *
+ * These flags indicate whether PMF must be enabled.
+ **/
+typedef enum {
+ NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT = 0,
+ NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE = 1,
+ NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL = 2,
+ NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED = 3,
+ _NM_SETTING_WIRELESS_SECURITY_PMF_NUM, /*< skip >*/
+ NM_SETTING_WIRELESS_SECURITY_PMF_LAST = _NM_SETTING_WIRELESS_SECURITY_PMF_NUM - 1, /*< skip >*/
+} NMSettingWirelessSecurityPmf;
+
#define NM_SETTING_WIRELESS_SECURITY_KEY_MGMT "key-mgmt"
#define NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX "wep-tx-keyidx"
#define NM_SETTING_WIRELESS_SECURITY_AUTH_ALG "auth-alg"
#define NM_SETTING_WIRELESS_SECURITY_PROTO "proto"
#define NM_SETTING_WIRELESS_SECURITY_PAIRWISE "pairwise"
#define NM_SETTING_WIRELESS_SECURITY_GROUP "group"
+#define NM_SETTING_WIRELESS_SECURITY_PMF "pmf"
#define NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME "leap-username"
#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY0 "wep-key0"
#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY1 "wep-key1"
@@ -132,6 +151,9 @@ void nm_setting_wireless_security_remove_group (NMSettingWireles
gboolean nm_setting_wireless_security_remove_group_by_value (NMSettingWirelessSecurity *setting, const char *group);
void nm_setting_wireless_security_clear_groups (NMSettingWirelessSecurity *setting);
+NM_AVAILABLE_IN_1_10
+NMSettingWirelessSecurityPmf nm_setting_wireless_security_get_pmf (NMSettingWirelessSecurity *setting);
+
const char *nm_setting_wireless_security_get_psk (NMSettingWirelessSecurity *setting);
NMSettingSecretFlags nm_setting_wireless_security_get_psk_flags (NMSettingWirelessSecurity *setting);
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index b767bf83a5..f9d826d831 100644
--- a/libnm/libnm.ver
+++ b/libnm/libnm.ver
@@ -1177,3 +1177,9 @@ global:
nm_utils_format_variant_attributes;
nm_utils_parse_variant_attributes;
} libnm_1_6_0;
+
+libnm_1_10_0 {
+global:
+ nm_setting_wireless_security_get_pmf;
+ nm_setting_wireless_security_pmf_get_type;
+} libnm_1_8_0;
diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml
index 658fd7c2d6..808f7375df 100644
--- a/man/NetworkManager.conf.xml
+++ b/man/NetworkManager.conf.xml
@@ -701,6 +701,11 @@ ipv6.ip6-privacy=0
<listitem><para>If left unspecified, the default value
"<literal>ignore</literal>" will be used.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>wifi-sec.pmf</varname></term>
+ <listitem><para>If left unspecified, the default value
+ "<literal>optional</literal>" will be used.</para></listitem>
+ </varlistentry>
</variablelist>
</para>
</refsect2>
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 7359be96ea..fd0cd0d9f3 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -2348,6 +2348,8 @@ build_supplicant_config (NMDeviceWifi *self,
NMSupplicantConfig *config = NULL;
NMSettingWireless *s_wireless;
NMSettingWirelessSecurity *s_wireless_sec;
+ NMSettingWirelessSecurityPmf pmf;
+ gs_free char *value = NULL;
g_return_val_if_fail (priv->sup_iface, NULL);
@@ -2378,12 +2380,46 @@ build_supplicant_config (NMDeviceWifi *self,
nm_device_get_ifindex (NM_DEVICE (self)));
g_assert (con_uuid);
+
+ /* Configure PMF (802.11w) */
+ pmf = nm_setting_wireless_security_get_pmf (s_wireless_sec);
+ if (pmf == NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT) {
+ value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
+ "wifi-sec.pmf",
+ NM_DEVICE (self));
+ pmf = _nm_utils_ascii_str_to_int64 (value, 10,
+ NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE,
+ NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED,
+ NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL);
+ }
+
+ /* Don't try to enable PMF on non-WPA networks */
+ if (!NM_IN_STRSET (nm_setting_wireless_security_get_key_mgmt (s_wireless_sec),
+ "wpa-eap",
+ "wpa-psk"))
+ pmf = NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE;
+
+ /* Check if we actually support PMF */
+ if (nm_supplicant_interface_get_pmf_support (priv->sup_iface) != NM_SUPPLICANT_FEATURE_YES) {
+ if (pmf == NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) {
+ g_set_error_literal (error, NM_SUPPLICANT_ERROR, NM_SUPPLICANT_ERROR_CONFIG,
+ "Supplicant does not support PMF");
+ goto error;
+ } else if (pmf == NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL) {
+ /* To be on the safe side, assume no support if we can't determine
+ * capabilities.
+ */
+ pmf = NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE;
+ }
+ }
+
s_8021x = nm_connection_get_setting_802_1x (connection);
if (!nm_supplicant_config_add_setting_wireless_security (config,
s_wireless_sec,
s_8021x,
con_uuid,
mtu,
+ pmf,
error)) {
g_prefix_error (error, "802-11-wireless-security: ");
goto error;
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
index f16aaa8420..c4221c8893 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
@@ -3294,7 +3294,9 @@ make_wpa_setting (shvarFile *ifcfg,
{
NMSettingWirelessSecurity *wsec;
char *value, *psk, *lower;
+ const char *cvalue;
gboolean wpa_psk = FALSE, wpa_eap = FALSE, ieee8021x = FALSE;
+ guint pmf = NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT;
wsec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
@@ -3373,6 +3375,24 @@ make_wpa_setting (shvarFile *ifcfg,
g_free (value);
+ cvalue = svGetValue (ifcfg, "PMF", &value);
+ if (cvalue) {
+ int i_pmf;
+
+ if (!nm_utils_enum_from_str (nm_setting_wireless_security_pmf_get_type (),
+ cvalue,
+ &i_pmf,
+ NULL)) {
+ g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+ "Invalid PMF value '%s'", cvalue);
+ g_free (value);
+ goto error;
+ }
+ pmf = i_pmf;
+ g_free (value);
+ }
+ g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_PMF, pmf, NULL);
+
value = svGetValueStr_cp (ifcfg, "SECURITYMODE");
if (NM_IN_STRSET (value, NULL, "open"))
g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, value, NULL);
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
index c6957e8816..3b2b1a5c73 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
@@ -707,6 +707,17 @@ write_wireless_security_setting (NMConnection *connection,
"WPA_PSK_FLAGS",
wpa ? nm_setting_wireless_security_get_psk_flags (s_wsec) : NM_SETTING_SECRET_FLAG_NONE);
+
+ if (nm_setting_wireless_security_get_pmf (s_wsec) == NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT)
+ svUnsetValue (ifcfg, "PMF");
+ else {
+ gs_free char * value = NULL;
+
+ value = nm_utils_enum_to_str (nm_setting_wireless_security_pmf_get_type(),
+ nm_setting_wireless_security_get_pmf (s_wsec));
+ svSetValueStr (ifcfg, "PMF", value);
+ }
+
return TRUE;
}
diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index 057d72d5f6..97b65eaaf7 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -5768,6 +5768,7 @@ test_write_wifi_wpa_psk (gconstpointer test_data)
g_object_set (s_wsec,
NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk",
NM_SETTING_WIRELESS_SECURITY_PSK, args.psk,
+ NM_SETTING_WIRELESS_SECURITY_PMF, (guint) NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED,
NULL);
if (GPOINTER_TO_INT (args.wep_group_p)) {
diff --git a/src/supplicant/nm-supplicant-config.c b/src/supplicant/nm-supplicant-config.c
index 4ff376a5cd..3f607420c6 100644
--- a/src/supplicant/nm-supplicant-config.c
+++ b/src/supplicant/nm-supplicant-config.c
@@ -684,9 +684,10 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
NMSetting8021x *setting_8021x,
const char *con_uuid,
guint32 mtu,
+ NMSettingWirelessSecurityPmf pmf,
GError **error)
{
- const char *key_mgmt, *auth_alg;
+ const char *key_mgmt, *key_mgmt_conf, *auth_alg;
const char *psk;
g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
@@ -694,8 +695,19 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
g_return_val_if_fail (con_uuid != NULL, FALSE);
g_return_val_if_fail (!error || !*error, FALSE);
- key_mgmt = nm_setting_wireless_security_get_key_mgmt (setting);
- if (!add_string_val (self, key_mgmt, "key_mgmt", TRUE, NULL, error))
+ key_mgmt = key_mgmt_conf = nm_setting_wireless_security_get_key_mgmt (setting);
+ if (pmf == NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL) {
+ if (nm_streq (key_mgmt_conf, "wpa-psk"))
+ key_mgmt_conf = "wpa-psk wpa-psk-sha256";
+ else if (nm_streq (key_mgmt_conf, "wpa-eap"))
+ key_mgmt_conf = "wpa-eap wpa-eap-sha256";
+ } else if (pmf == NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) {
+ if (nm_streq (key_mgmt_conf, "wpa-psk"))
+ key_mgmt_conf = "wpa-psk-sha256";
+ else if (nm_streq (key_mgmt_conf, "wpa-eap"))
+ key_mgmt_conf = "wpa-eap-sha256";
+ }
+ if (!add_string_val (self, key_mgmt_conf, "key_mgmt", TRUE, NULL, error))
return FALSE;
auth_alg = nm_setting_wireless_security_get_auth_alg (setting);
@@ -750,6 +762,19 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
return FALSE;
if (!ADD_STRING_LIST_VAL (self, setting, wireless_security, group, groups, "group", ' ', TRUE, NULL, error))
return FALSE;
+
+ if ( !nm_streq (key_mgmt, "wpa-none")
+ && NM_IN_SET (pmf,
+ NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL,
+ NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED)) {
+ if (!nm_supplicant_config_add_option (self,
+ "ieee80211w",
+ pmf == NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL ? "1" : "2",
+ -1,
+ NULL,
+ error))
+ return FALSE;
+ }
}
/* WEP keys if required */
@@ -1325,31 +1350,3 @@ nm_supplicant_config_add_no_security (NMSupplicantConfig *self, GError **error)
return nm_supplicant_config_add_option (self, "key_mgmt", "NONE", -1, NULL, error);
}
-gboolean
-nm_supplicant_config_enable_pmf_akm (NMSupplicantConfig *self, GError **error)
-{
- NMSupplicantConfigPrivate *priv;
- ConfigOption *option;
-
- g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
- g_return_val_if_fail (!error || !*error, FALSE);
-
- priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
-
- option = g_hash_table_lookup (priv->config, "key_mgmt");
- if (!option)
- return TRUE;
-
- if (nm_streq0 (option->value, "WPA-PSK")) {
- g_hash_table_remove (priv->config, "key_mgmt");
- if (!nm_supplicant_config_add_option (self, "key_mgmt", "WPA-PSK WPA-PSK-SHA256", -1, NULL, error))
- return FALSE;
- } else if (nm_streq0 (option->value, "WPA-EAP")) {
- g_hash_table_remove (priv->config, "key_mgmt");
- if (!nm_supplicant_config_add_option (self, "key_mgmt", "WPA-EAP WPA-EAP-SHA256", -1, NULL, error))
- return FALSE;
- }
-
- return TRUE;
-}
-
diff --git a/src/supplicant/nm-supplicant-config.h b/src/supplicant/nm-supplicant-config.h
index 705833ff5f..93fc57ce3a 100644
--- a/src/supplicant/nm-supplicant-config.h
+++ b/src/supplicant/nm-supplicant-config.h
@@ -60,6 +60,7 @@ gboolean nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig
NMSetting8021x *setting_8021x,
const char *con_uuid,
guint32 mtu,
+ NMSettingWirelessSecurityPmf pmf,
GError **error);
gboolean nm_supplicant_config_add_no_security (NMSupplicantConfig *self,
diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c
index dec208276e..c4633f2535 100644
--- a/src/supplicant/nm-supplicant-interface.c
+++ b/src/supplicant/nm-supplicant-interface.c
@@ -472,30 +472,6 @@ iface_check_ready (NMSupplicantInterface *self)
}
}
-static void
-set_pmf_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
- NMSupplicantInterface *self;
- NMSupplicantInterfacePrivate *priv;
- gs_unref_variant GVariant *reply = NULL;
- gs_free_error GError *error = NULL;
-
- reply = g_dbus_proxy_call_finish (proxy, result, &error);
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
- return;
-
- self = NM_SUPPLICANT_INTERFACE (user_data);
- priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
- if (!reply) {
- g_dbus_error_strip_remote_error (error);
- _LOGW ("couldn't enable PMF: %s", error->message);
- return;
- }
-
- _LOGD ("PMF enabled");
-}
-
gboolean
nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self,
const char *field,
@@ -567,6 +543,12 @@ nm_supplicant_interface_get_ap_support (NMSupplicantInterface *self)
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->ap_support;
}
+NMSupplicantFeature
+nm_supplicant_interface_get_pmf_support (NMSupplicantInterface *self)
+{
+ return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->pmf_support;
+}
+
void
nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self,
NMSupplicantFeature ap_support)
@@ -841,21 +823,6 @@ on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_
NULL,
NULL);
- if ( priv->pmf_support == NM_SUPPLICANT_FEATURE_YES
- && priv->driver == NM_SUPPLICANT_DRIVER_WIRELESS) {
- g_dbus_proxy_call (priv->iface_proxy,
- DBUS_INTERFACE_PROPERTIES ".Set",
- g_variant_new ("(ssv)",
- WPAS_DBUS_IFACE_INTERFACE,
- "Pmf",
- g_variant_new_uint32 (1)),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- priv->init_cancellable,
- (GAsyncReadyCallback) set_pmf_cb,
- self);
- }
-
/* Check whether NetworkReply and AP mode are supported */
priv->ready_count = 1;
g_dbus_proxy_call (priv->iface_proxy,
@@ -1424,7 +1391,6 @@ nm_supplicant_interface_assoc (NMSupplicantInterface *self,
{
NMSupplicantInterfacePrivate *priv;
AssocData *assoc_data;
- GError *error = NULL;
g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
g_return_if_fail (NM_IS_SUPPLICANT_CONFIG (cfg));
@@ -1441,14 +1407,6 @@ nm_supplicant_interface_assoc (NMSupplicantInterface *self,
assoc_data->callback = callback;
assoc_data->user_data = user_data;
- if ( priv->driver == NM_SUPPLICANT_DRIVER_WIRELESS
- && priv->pmf_support == NM_SUPPLICANT_FEATURE_YES) {
- if (!nm_supplicant_config_enable_pmf_akm (cfg, &error)) {
- _LOGW ("could not enable PMF AKMs in config: %s", error->message);
- g_error_free (error);
- }
- }
-
_LOGD ("assoc[%p]: starting association...", assoc_data);
/* Make sure the supplicant supports EAP-FAST before trying to send
diff --git a/src/supplicant/nm-supplicant-interface.h b/src/supplicant/nm-supplicant-interface.h
index a881ede236..a31d2b8a81 100644
--- a/src/supplicant/nm-supplicant-interface.h
+++ b/src/supplicant/nm-supplicant-interface.h
@@ -121,6 +121,7 @@ gboolean nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self,
GError **error);
NMSupplicantFeature nm_supplicant_interface_get_ap_support (NMSupplicantInterface *self);
+NMSupplicantFeature nm_supplicant_interface_get_pmf_support (NMSupplicantInterface *self);
void nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self,
NMSupplicantFeature apmode);
diff --git a/src/supplicant/nm-supplicant-settings-verify.c b/src/supplicant/nm-supplicant-settings-verify.c
index fd5b06eacf..14daf6938b 100644
--- a/src/supplicant/nm-supplicant-settings-verify.c
+++ b/src/supplicant/nm-supplicant-settings-verify.c
@@ -151,6 +151,7 @@ static const struct Opt opt_table[] = {
{ "mka_cak", TYPE_BYTES, 0, 65536, FALSE, NULL },
{ "mka_ckn", TYPE_BYTES, 0, 65536, FALSE, NULL },
{ "macsec_port", TYPE_INT, 1, 65534, FALSE, NULL },
+ { "ieee80211w", TYPE_INT, 0, 2, FALSE, NULL },
};
diff --git a/src/supplicant/tests/test-supplicant-config.c b/src/supplicant/tests/test-supplicant-config.c
index fd91e92177..68c4f83da3 100644
--- a/src/supplicant/tests/test-supplicant-config.c
+++ b/src/supplicant/tests/test-supplicant-config.c
@@ -278,6 +278,7 @@ test_wifi_wep_key (const char *detail,
NULL,
"376aced7-b28c-46be-9a62-fcdf072571da",
1500,
+ 0,
&error));
g_assert_no_error (error);
g_test_assert_expected_messages ();
@@ -374,6 +375,7 @@ test_wifi_wpa_psk (const char *detail,
g_object_set (s_wsec,
NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk",
NM_SETTING_WIRELESS_SECURITY_PSK, key_data,
+ NM_SETTING_WIRELESS_SECURITY_PMF, NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL,
NULL);
nm_setting_wireless_security_add_proto (s_wsec, "wpa");
@@ -411,7 +413,7 @@ test_wifi_wpa_psk (const char *detail,
g_test_assert_expected_messages ();
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO,
- "*added 'key_mgmt' value 'WPA-PSK'");
+ "*added 'key_mgmt' value 'WPA-PSK WPA-PSK-SHA256'");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO,
"*added 'psk' value *");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO,
@@ -420,11 +422,14 @@ test_wifi_wpa_psk (const char *detail,
"*added 'pairwise' value 'TKIP CCMP'");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO,
"*added 'group' value 'TKIP CCMP'");
+ g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO,
+ "*added 'ieee80211w' value '1'");
g_assert (nm_supplicant_config_add_setting_wireless_security (config,
s_wsec,
NULL,
"376aced7-b28c-46be-9a62-fcdf072571da",
1500,
+ NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL,
&error));
g_assert_no_error (error);
g_test_assert_expected_messages ();
@@ -435,7 +440,7 @@ test_wifi_wpa_psk (const char *detail,
validate_opt (detail, config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1);
validate_opt (detail, config_dict, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data));
validate_opt (detail, config_dict, "bssid", TYPE_KEYWORD, bssid_str, -1);
- validate_opt (detail, config_dict, "key_mgmt", TYPE_KEYWORD, "WPA-PSK", -1);
+ validate_opt (detail, config_dict, "key_mgmt", TYPE_KEYWORD, "WPA-PSK WPA-PSK-SHA256", -1);
validate_opt (detail, config_dict, "proto", TYPE_KEYWORD, "WPA RSN", -1);
validate_opt (detail, config_dict, "pairwise", TYPE_KEYWORD, "TKIP CCMP", -1);
validate_opt (detail, config_dict, "group", TYPE_KEYWORD, "TKIP CCMP", -1);
@@ -580,6 +585,7 @@ test_wifi_eap (void)
s_8021x,
"d5b488af-9cab-41ed-bad4-97709c58430f",
mtu,
+ NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE,
&error));
g_assert_no_error (error);
g_test_assert_expected_messages ();