summary refs log tree commit diff
path: root/src/supplicant
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-04-23 18:00:21 +0200
committerMichael Biebl <biebl@debian.org>2018-04-23 18:00:21 +0200
commitf60117b41d5433be1b4a96d82cd11d0c3dce9b63 (patch)
tree2dd55c4ab0fdcbe9cddb26adb4a554b1a45c73c8 /src/supplicant
parent7e9ff09fcb2366b383b7ebbec80d2f6fff117290 (diff)
New upstream version 1.11.3 upstream/1.11.3
Diffstat (limited to 'src/supplicant')
-rw-r--r--src/supplicant/nm-supplicant-config.c71
-rw-r--r--src/supplicant/nm-supplicant-config.h3
-rw-r--r--src/supplicant/nm-supplicant-interface.c42
-rw-r--r--src/supplicant/nm-supplicant-interface.h8
-rw-r--r--src/supplicant/nm-supplicant-manager.c15
-rw-r--r--src/supplicant/nm-supplicant-settings-verify.c9
-rw-r--r--src/supplicant/nm-supplicant-types.h6
-rw-r--r--src/supplicant/tests/meson.build14
-rw-r--r--src/supplicant/tests/test-supplicant-config.c196
9 files changed, 265 insertions, 99 deletions
diff --git a/src/supplicant/nm-supplicant-config.c b/src/supplicant/nm-supplicant-config.c
index 16e7851a..14f5cac8 100644
--- a/src/supplicant/nm-supplicant-config.c
+++ b/src/supplicant/nm-supplicant-config.c
@@ -47,6 +47,8 @@ typedef struct {
 	guint32    ap_scan;
 	gboolean   fast_required;
 	gboolean   dispose_has_run;
+	gboolean   support_pmf;
+	gboolean   support_fils;
 } NMSupplicantConfigPrivate;
 
 struct _NMSupplicantConfig {
@@ -65,9 +67,18 @@ G_DEFINE_TYPE (NMSupplicantConfig, nm_supplicant_config, G_TYPE_OBJECT)
 /*****************************************************************************/
 
 NMSupplicantConfig *
-nm_supplicant_config_new (void)
+nm_supplicant_config_new (gboolean support_pmf, gboolean support_fils)
 {
-	return g_object_new (NM_TYPE_SUPPLICANT_CONFIG, NULL);
+	NMSupplicantConfigPrivate *priv;
+	NMSupplicantConfig *self;
+
+	self = g_object_new (NM_TYPE_SUPPLICANT_CONFIG, NULL);
+	priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
+
+	priv->support_pmf = support_pmf;
+	priv->support_fils = support_fils;
+
+	return self;
 }
 
 static void
@@ -369,7 +380,6 @@ nm_supplicant_config_add_setting_macsec (NMSupplicantConfig * self,
                                          NMSettingMacsec * setting,
                                          GError **error)
 {
-	NMSupplicantConfigPrivate *priv;
 	gs_unref_bytes GBytes *bytes = NULL;
 	const char *value;
 	char buf[32];
@@ -379,8 +389,6 @@ nm_supplicant_config_add_setting_macsec (NMSupplicantConfig * self,
 	g_return_val_if_fail (setting != NULL, FALSE);
 	g_return_val_if_fail (!error || !*error, FALSE);
 
-	priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
-
 	if (!nm_supplicant_config_add_option (self, "macsec_policy", "1", -1, NULL, error))
 		return FALSE;
 
@@ -736,8 +744,10 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
                                                     const char *con_uuid,
                                                     guint32 mtu,
                                                     NMSettingWirelessSecurityPmf pmf,
+                                                    NMSettingWirelessSecurityFils fils,
                                                     GError **error)
 {
+	NMSupplicantConfigPrivate *priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
 	const char *key_mgmt, *key_mgmt_conf, *auth_alg;
 	const char *psk;
 
@@ -746,18 +756,37 @@ 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);
 
+	/* Check if we actually support FILS */
+	if (!priv->support_fils) {
+		if (fils == NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED) {
+			g_set_error_literal (error, NM_SUPPLICANT_ERROR, NM_SUPPLICANT_ERROR_CONFIG,
+			                     "Supplicant does not support FILS");
+			return FALSE;
+		} else if (fils == NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL)
+			fils = NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE;
+	}
+
 	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"))
+	if (nm_streq (key_mgmt, "wpa-psk")) {
+		if (priv->support_pmf)
 			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";
+	} else if (nm_streq (key_mgmt, "wpa-eap")) {
+		switch (fils) {
+		case NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL:
+			key_mgmt_conf = priv->support_pmf
+				? "wpa-eap wpa-eap-sha256 fils-sha256 fils-sha384"
+				: "wpa-eap fils-sha256 fils-sha384";
+			break;
+		case NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED:
+			key_mgmt_conf = "fils-sha256 fils-sha384";
+			break;
+		default:
+			if (priv->support_pmf)
+				key_mgmt_conf = "wpa-eap wpa-eap-sha256";
+			break;
+		}
 	}
+
 	if (!add_string_val (self, key_mgmt_conf, "key_mgmt", TRUE, NULL, error))
 		return FALSE;
 
@@ -803,6 +832,20 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
 		}
 	}
 
+	/* Don't try to enable PMF on non-WPA networks */
+	if (!NM_IN_STRSET (key_mgmt, "wpa-eap", "wpa-psk"))
+		pmf = NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE;
+
+	/* Check if we actually support PMF */
+	if (!priv->support_pmf) {
+		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");
+			return FALSE;
+		} else if (pmf == NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL)
+			pmf = NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE;
+	}
+
 	/* Only WPA-specific things when using WPA */
 	if (   !strcmp (key_mgmt, "wpa-none")
 	    || !strcmp (key_mgmt, "wpa-psk")
diff --git a/src/supplicant/nm-supplicant-config.h b/src/supplicant/nm-supplicant-config.h
index d90d82b8..f6c845a3 100644
--- a/src/supplicant/nm-supplicant-config.h
+++ b/src/supplicant/nm-supplicant-config.h
@@ -40,7 +40,7 @@ typedef struct _NMSupplicantConfigClass NMSupplicantConfigClass;
 
 GType nm_supplicant_config_get_type (void);
 
-NMSupplicantConfig *nm_supplicant_config_new (void);
+NMSupplicantConfig *nm_supplicant_config_new (gboolean support_pmf, gboolean support_fils);
 
 guint32 nm_supplicant_config_get_ap_scan (NMSupplicantConfig *self);
 
@@ -65,6 +65,7 @@ gboolean nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig
                                                              const char *con_uuid,
                                                              guint32 mtu,
                                                              NMSettingWirelessSecurityPmf pmf,
+                                                             NMSettingWirelessSecurityFils fils,
                                                              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 44f887cb..3511b151 100644
--- a/src/supplicant/nm-supplicant-interface.c
+++ b/src/supplicant/nm-supplicant-interface.c
@@ -93,6 +93,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSupplicantInterface,
 	PROP_FAST_SUPPORT,
 	PROP_AP_SUPPORT,
 	PROP_PMF_SUPPORT,
+	PROP_FILS_SUPPORT,
 );
 
 typedef struct {
@@ -102,6 +103,7 @@ typedef struct {
 	NMSupplicantFeature fast_support;
 	NMSupplicantFeature ap_support;   /* Lightweight AP mode support */
 	NMSupplicantFeature pmf_support;
+	NMSupplicantFeature fils_support;
 	guint32        max_scan_ssids;
 	guint32        ready_count;
 
@@ -565,6 +567,12 @@ nm_supplicant_interface_get_pmf_support (NMSupplicantInterface *self)
 	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->pmf_support;
 }
 
+NMSupplicantFeature
+nm_supplicant_interface_get_fils_support (NMSupplicantInterface *self)
+{
+	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->fils_support;
+}
+
 void
 nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self,
                                         NMSupplicantFeature ap_support)
@@ -596,6 +604,15 @@ nm_supplicant_interface_set_pmf_support (NMSupplicantInterface *self,
 	priv->pmf_support = pmf_support;
 }
 
+void
+nm_supplicant_interface_set_fils_support (NMSupplicantInterface *self,
+                                          NMSupplicantFeature fils_support)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	priv->fils_support = fils_support;
+}
+
 /*****************************************************************************/
 
 static void
@@ -1057,9 +1074,8 @@ props_changed_cb (GDBusProxy *proxy,
 	}
 
 	if (g_variant_lookup (changed_properties, "CurrentBSS", "&o", &s)) {
-		if (strcmp (s, "/") == 0)
-			s = NULL;
-		if (g_strcmp0 (s, priv->current_bss) != 0) {
+		s = nm_utils_dbus_normalize_object_path (s);
+		if (!nm_streq0 (s, priv->current_bss)) {
 			g_free (priv->current_bss);
 			priv->current_bss = g_strdup (s);
 			_notify (self, PROP_CURRENT_BSS);
@@ -1198,7 +1214,6 @@ static void
 interface_get_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
 	NMSupplicantInterface *self;
-	NMSupplicantInterfacePrivate *priv;
 	gs_unref_variant GVariant *variant = NULL;
 	gs_free_error GError *error = NULL;
 	const char *path;
@@ -1210,7 +1225,6 @@ interface_get_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 		return;
 
 	self = NM_SUPPLICANT_INTERFACE (user_data);
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
 	if (variant) {
 		g_variant_get (variant, "(&o)", &path);
@@ -1900,6 +1914,10 @@ set_property (GObject *object,
 		/* construct-only */
 		priv->pmf_support = g_value_get_int (value);
 		break;
+	case PROP_FILS_SUPPORT:
+		/* construct-only */
+		priv->fils_support = g_value_get_int (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1920,7 +1938,8 @@ nm_supplicant_interface_new (const char *ifname,
                              NMSupplicantDriver driver,
                              NMSupplicantFeature fast_support,
                              NMSupplicantFeature ap_support,
-                             NMSupplicantFeature pmf_support)
+                             NMSupplicantFeature pmf_support,
+                             NMSupplicantFeature fils_support)
 {
 	g_return_val_if_fail (ifname != NULL, NULL);
 
@@ -1930,6 +1949,7 @@ nm_supplicant_interface_new (const char *ifname,
 	                     NM_SUPPLICANT_INTERFACE_FAST_SUPPORT, (int) fast_support,
 	                     NM_SUPPLICANT_INTERFACE_AP_SUPPORT, (int) ap_support,
 	                     NM_SUPPLICANT_INTERFACE_PMF_SUPPORT, (int) pmf_support,
+	                     NM_SUPPLICANT_INTERFACE_FILS_SUPPORT, (int) fils_support,
 	                     NULL);
 }
 
@@ -1964,7 +1984,7 @@ dispose (GObject *object)
 	nm_clear_g_cancellable (&priv->other_cancellable);
 
 	g_clear_object (&priv->wpas_proxy);
-	g_clear_pointer (&priv->bss_proxies, (GDestroyNotify) g_hash_table_destroy);
+	g_clear_pointer (&priv->bss_proxies, g_hash_table_destroy);
 
 	g_clear_pointer (&priv->net_path, g_free);
 	g_clear_pointer (&priv->dev, g_free);
@@ -2029,6 +2049,14 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass)
 	                      G_PARAM_WRITABLE |
 	                      G_PARAM_CONSTRUCT_ONLY |
 	                      G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_FILS_SUPPORT] =
+	    g_param_spec_int (NM_SUPPLICANT_INTERFACE_FILS_SUPPORT, "", "",
+	                      NM_SUPPLICANT_FEATURE_UNKNOWN,
+	                      NM_SUPPLICANT_FEATURE_YES,
+	                      NM_SUPPLICANT_FEATURE_UNKNOWN,
+	                      G_PARAM_WRITABLE |
+	                      G_PARAM_CONSTRUCT_ONLY |
+	                      G_PARAM_STATIC_STRINGS);
 
 	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 
diff --git a/src/supplicant/nm-supplicant-interface.h b/src/supplicant/nm-supplicant-interface.h
index 567cf96f..f32ad8dd 100644
--- a/src/supplicant/nm-supplicant-interface.h
+++ b/src/supplicant/nm-supplicant-interface.h
@@ -61,6 +61,7 @@ typedef enum {
 #define NM_SUPPLICANT_INTERFACE_FAST_SUPPORT     "fast-support"
 #define NM_SUPPLICANT_INTERFACE_AP_SUPPORT       "ap-support"
 #define NM_SUPPLICANT_INTERFACE_PMF_SUPPORT      "pmf-support"
+#define NM_SUPPLICANT_INTERFACE_FILS_SUPPORT     "fils-support"
 
 /* Signals */
 #define NM_SUPPLICANT_INTERFACE_STATE            "state"
@@ -79,7 +80,8 @@ NMSupplicantInterface * nm_supplicant_interface_new (const char *ifname,
                                                      NMSupplicantDriver driver,
                                                      NMSupplicantFeature fast_support,
                                                      NMSupplicantFeature ap_support,
-                                                     NMSupplicantFeature pmf_support);
+                                                     NMSupplicantFeature pmf_support,
+                                                     NMSupplicantFeature fils_support);
 
 void nm_supplicant_interface_set_supplicant_available (NMSupplicantInterface *self,
                                                        gboolean available);
@@ -123,6 +125,7 @@ gboolean nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self,
 
 NMSupplicantFeature nm_supplicant_interface_get_ap_support (NMSupplicantInterface *self);
 NMSupplicantFeature nm_supplicant_interface_get_pmf_support (NMSupplicantInterface *self);
+NMSupplicantFeature nm_supplicant_interface_get_fils_support (NMSupplicantInterface *self);
 
 void nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self,
                                              NMSupplicantFeature apmode);
@@ -133,6 +136,9 @@ void nm_supplicant_interface_set_fast_support (NMSupplicantInterface *self,
 void nm_supplicant_interface_set_pmf_support (NMSupplicantInterface *self,
                                               NMSupplicantFeature pmf_support);
 
+void nm_supplicant_interface_set_fils_support (NMSupplicantInterface *self,
+                                               NMSupplicantFeature fils_support);
+
 void nm_supplicant_interface_enroll_wps (NMSupplicantInterface *self,
                                          const char *const type,
                                          const char *bssid,
diff --git a/src/supplicant/nm-supplicant-manager.c b/src/supplicant/nm-supplicant-manager.c
index 0f2eb63a..5ab96f88 100644
--- a/src/supplicant/nm-supplicant-manager.c
+++ b/src/supplicant/nm-supplicant-manager.c
@@ -40,6 +40,7 @@ typedef struct {
 	NMSupplicantFeature fast_support;
 	NMSupplicantFeature ap_support;
 	NMSupplicantFeature pmf_support;
+	NMSupplicantFeature fils_support;
 	guint             die_count_reset_id;
 	guint             die_count;
 } NMSupplicantManagerPrivate;
@@ -161,7 +162,8 @@ nm_supplicant_manager_create_interface (NMSupplicantManager *self,
 	                                     driver,
 	                                     priv->fast_support,
 	                                     priv->ap_support,
-	                                     priv->pmf_support);
+	                                     priv->pmf_support,
+	                                     priv->fils_support);
 
 	priv->ifaces = g_slist_prepend (priv->ifaces, iface);
 	g_object_add_toggle_ref ((GObject *) iface, _sup_iface_last_ref, self);
@@ -196,6 +198,7 @@ update_capabilities (NMSupplicantManager *self)
 	 */
 	priv->ap_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
 	priv->pmf_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
+	priv->fils_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
 
 	value = g_dbus_proxy_get_cached_property (priv->proxy, "Capabilities");
 	if (value) {
@@ -203,21 +206,25 @@ update_capabilities (NMSupplicantManager *self)
 			array = g_variant_get_strv (value, NULL);
 			priv->ap_support = NM_SUPPLICANT_FEATURE_NO;
 			priv->pmf_support = NM_SUPPLICANT_FEATURE_NO;
+			priv->fils_support = NM_SUPPLICANT_FEATURE_NO;
 			if (array) {
 				if (g_strv_contains (array, "ap"))
 					priv->ap_support = NM_SUPPLICANT_FEATURE_YES;
 				if (g_strv_contains (array, "pmf"))
 					priv->pmf_support = NM_SUPPLICANT_FEATURE_YES;
+				if (g_strv_contains (array, "fils"))
+					priv->fils_support = NM_SUPPLICANT_FEATURE_YES;
 				g_free (array);
 			}
 		}
 		g_variant_unref (value);
 	}
 
-	/* Tell all interfaces about results of the AP/PMF check */
+	/* Tell all interfaces about results of the AP/PMF/FILS check */
 	for (ifaces = priv->ifaces; ifaces; ifaces = ifaces->next) {
 		nm_supplicant_interface_set_ap_support (ifaces->data, priv->ap_support);
 		nm_supplicant_interface_set_pmf_support (ifaces->data, priv->pmf_support);
+		nm_supplicant_interface_set_fils_support (ifaces->data, priv->fils_support);
 	}
 
 	_LOGD ("AP mode is %ssupported",
@@ -226,6 +233,9 @@ update_capabilities (NMSupplicantManager *self)
 	_LOGD ("PMF is %ssupported",
 	       (priv->pmf_support == NM_SUPPLICANT_FEATURE_YES) ? "" :
 	           (priv->pmf_support == NM_SUPPLICANT_FEATURE_NO) ? "not " : "possibly ");
+	_LOGD ("FILS is %ssupported",
+	       (priv->fils_support == NM_SUPPLICANT_FEATURE_YES) ? "" :
+	           (priv->fils_support == NM_SUPPLICANT_FEATURE_NO) ? "not " : "possibly ");
 
 	/* EAP-FAST */
 	priv->fast_support = NM_SUPPLICANT_FEATURE_NO;
@@ -349,6 +359,7 @@ name_owner_cb (GDBusProxy *proxy, GParamSpec *pspec, gpointer user_data)
 		priv->ap_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
 		priv->fast_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
 		priv->pmf_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
+		priv->fils_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
 
 		set_running (self, FALSE);
 	}
diff --git a/src/supplicant/nm-supplicant-settings-verify.c b/src/supplicant/nm-supplicant-settings-verify.c
index 14daf693..5198d75f 100644
--- a/src/supplicant/nm-supplicant-settings-verify.c
+++ b/src/supplicant/nm-supplicant-settings-verify.c
@@ -73,6 +73,7 @@ const char * group_allowed[] =    { "CCMP", "TKIP", "WEP104", "WEP40", NULL };
 const char * proto_allowed[] =    { "WPA", "RSN", NULL };
 const char * key_mgmt_allowed[] = { "WPA-PSK", "WPA-PSK-SHA256",
                                     "WPA-EAP", "WPA-EAP-SHA256",
+                                    "FILS-SHA256", "FILS-SHA384",
                                     "IEEE8021X", "WPA-NONE",
                                     "NONE", NULL };
 const char * auth_alg_allowed[] = { "OPEN", "SHARED", "LEAP", NULL };
@@ -221,10 +222,10 @@ validate_type_keyword (const struct Opt * opt,
                        const char * value,
                        const guint32 len)
 {
-	char **		allowed;
-	gchar **	candidates = NULL;
-	char **		candidate;
-	gboolean	found = FALSE;
+	char **allowed;
+	gchar **candidates = NULL;
+	char **candidate;
+	gboolean found = FALSE;
 
 	g_return_val_if_fail (opt != NULL, FALSE);
 	g_return_val_if_fail (value != NULL, FALSE);
diff --git a/src/supplicant/nm-supplicant-types.h b/src/supplicant/nm-supplicant-types.h
index f75827ec..747cf152 100644
--- a/src/supplicant/nm-supplicant-types.h
+++ b/src/supplicant/nm-supplicant-types.h
@@ -21,9 +21,9 @@
 #ifndef __NETWORKMANAGER_SUPPLICANT_TYPES_H__
 #define __NETWORKMANAGER_SUPPLICANT_TYPES_H__
 
-#define WPAS_DBUS_SERVICE	"fi.w1.wpa_supplicant1"
-#define WPAS_DBUS_PATH		"/fi/w1/wpa_supplicant1"
-#define WPAS_DBUS_INTERFACE	"fi.w1.wpa_supplicant1"
+#define WPAS_DBUS_SERVICE       "fi.w1.wpa_supplicant1"
+#define WPAS_DBUS_PATH          "/fi/w1/wpa_supplicant1"
+#define WPAS_DBUS_INTERFACE     "fi.w1.wpa_supplicant1"
 
 typedef struct _NMSupplicantManager NMSupplicantManager;
 typedef struct _NMSupplicantInterface NMSupplicantInterface;
diff --git a/src/supplicant/tests/meson.build b/src/supplicant/tests/meson.build
new file mode 100644
index 00000000..e6a86b20
--- /dev/null
+++ b/src/supplicant/tests/meson.build
@@ -0,0 +1,14 @@
+test_unit = 'test-supplicant-config'
+
+exe = executable(
+  test_unit,
+  test_unit + '.c',
+  dependencies: test_nm_dep,
+  c_args: '-DTEST_CERT_DIR="@0@"'.format(join_paths(meson.current_source_dir(), 'certs'))
+)
+
+test(
+  'supplicant/' + test_unit,
+  test_script,
+  args: test_args + [exe.full_path()]
+)
diff --git a/src/supplicant/tests/test-supplicant-config.c b/src/supplicant/tests/test-supplicant-config.c
index 4b4a4935..60ca5258 100644
--- a/src/supplicant/tests/test-supplicant-config.c
+++ b/src/supplicant/tests/test-supplicant-config.c
@@ -95,7 +95,11 @@ validate_opt (const char *detail,
 }
 
 static GVariant *
-build_supplicant_config (NMConnection *connection, guint mtu, guint fixed_freq)
+build_supplicant_config (NMConnection *connection,
+                         guint mtu,
+                         guint fixed_freq,
+                         gboolean support_pmf,
+                         gboolean support_fils)
 {
 	gs_unref_object NMSupplicantConfig *config = NULL;
 	gs_free_error GError *error = NULL;
@@ -104,7 +108,7 @@ build_supplicant_config (NMConnection *connection, guint mtu, guint fixed_freq)
 	NMSetting8021x *s_8021x;
 	gboolean success;
 
-	config = nm_supplicant_config_new ();
+	config = nm_supplicant_config_new (support_pmf, support_fils);
 
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
@@ -118,6 +122,7 @@ build_supplicant_config (NMConnection *connection, guint mtu, guint fixed_freq)
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
 	if (s_wsec) {
 		NMSettingWirelessSecurityPmf pmf = nm_setting_wireless_security_get_pmf (s_wsec);
+		NMSettingWirelessSecurityFils fils = nm_setting_wireless_security_get_fils (s_wsec);
 		s_8021x = nm_connection_get_setting_802_1x (connection);
 		success = nm_supplicant_config_add_setting_wireless_security (config,
 			                                                          s_wsec,
@@ -125,6 +130,7 @@ build_supplicant_config (NMConnection *connection, guint mtu, guint fixed_freq)
 			                                                          nm_connection_get_uuid (connection),
 			                                                          mtu,
 			                                                          pmf,
+			                                                          fils,
 			                                                          &error);
 	} else {
 		success = nm_supplicant_config_add_no_security (config, &error);
@@ -140,7 +146,6 @@ build_supplicant_config (NMConnection *connection, guint mtu, guint fixed_freq)
 	return nm_supplicant_config_to_variant (config);
 }
 
-#define EXPECT(msg) g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, msg)
 
 static NMConnection *
 new_basic_connection (const char *id,
@@ -199,12 +204,12 @@ test_wifi_open (void)
 	g_assert_no_error (error);
 	g_assert (success);
 
-	EXPECT ("*added 'ssid' value 'Test SSID'*");
-	EXPECT ("*added 'scan_ssid' value '1'*");
-	EXPECT ("*added 'bssid' value '11:22:33:44:55:66'*");
-	EXPECT ("*added 'freq_list' value *");
-	EXPECT ("*added 'key_mgmt' value 'NONE'");
-	config_dict = build_supplicant_config (connection, 1500, 0);
+	NMTST_EXPECT_NM_INFO ("Config: added 'ssid' value 'Test SSID'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'scan_ssid' value '1'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'bssid' value '11:22:33:44:55:66'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'freq_list' value *");
+	NMTST_EXPECT_NM_INFO ("Config: added 'key_mgmt' value 'NONE'");
+	config_dict = build_supplicant_config (connection, 1500, 0, TRUE, TRUE);
 	g_test_assert_expected_messages ();
 	g_assert (config_dict);
 
@@ -249,19 +254,19 @@ test_wifi_wep_key (const char *detail,
 	g_assert_no_error (error);
 	g_assert (success);
 
-	EXPECT ("*added 'ssid' value 'Test SSID'*");
-	EXPECT ("*added 'scan_ssid' value '1'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'ssid' value 'Test SSID'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'scan_ssid' value '1'*");
 	if (test_bssid)
-		EXPECT ("*added 'bssid' value '11:22:33:44:55:66'*");
+		NMTST_EXPECT_NM_INFO ("Config: added 'bssid' value '11:22:33:44:55:66'*");
 
-	EXPECT ("*added 'freq_list' value *");
-	EXPECT ("*added 'key_mgmt' value 'NONE'");
-	EXPECT ("*added 'wep_key0' value *");
-	EXPECT ("*added 'wep_tx_keyidx' value '0'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'freq_list' value *");
+	NMTST_EXPECT_NM_INFO ("Config: added 'key_mgmt' value 'NONE'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'wep_key0' value *");
+	NMTST_EXPECT_NM_INFO ("Config: added 'wep_tx_keyidx' value '0'");
 	if (!test_bssid)
-		EXPECT ("*added 'bgscan' value 'simple:30:-80:86400'*");
+		NMTST_EXPECT_NM_INFO ("Config: added 'bgscan' value 'simple:30:-80:86400'*");
 
-	config_dict = build_supplicant_config (connection, 1500, 0);
+	config_dict = build_supplicant_config (connection, 1500, 0, TRUE, TRUE);
 	g_test_assert_expected_messages ();
 	g_assert (config_dict);
 
@@ -308,7 +313,8 @@ test_wifi_wpa_psk (const char *detail,
                    OptType key_type,
                    const char *key_data,
                    const unsigned char *expected,
-                   size_t expected_size)
+                   size_t expected_size,
+                   NMSettingWirelessSecurityPmf pmf)
 {
 	gs_unref_object NMConnection *connection = NULL;
 	gs_unref_variant GVariant *config_dict = NULL;
@@ -328,7 +334,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, (int) NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL,
+	              NM_SETTING_WIRELESS_SECURITY_PMF, (int) pmf,
 	              NULL);
 	nm_setting_wireless_security_add_proto (s_wsec, "wpa");
 	nm_setting_wireless_security_add_proto (s_wsec, "rsn");
@@ -341,17 +347,26 @@ test_wifi_wpa_psk (const char *detail,
 	g_assert_no_error (error);
 	g_assert (success);
 
-	EXPECT ("*added 'ssid' value 'Test SSID'*");
-	EXPECT ("*added 'scan_ssid' value '1'*");
-	EXPECT ("*added 'bssid' value '11:22:33:44:55:66'*");
-	EXPECT ("*added 'freq_list' value *");
-	EXPECT ("*added 'key_mgmt' value 'WPA-PSK WPA-PSK-SHA256'");
-	EXPECT ("*added 'psk' value *");
-	EXPECT ("*added 'proto' value 'WPA RSN'");
-	EXPECT ("*added 'pairwise' value 'TKIP CCMP'");
-	EXPECT ("*added 'group' value 'TKIP CCMP'");
-	EXPECT ("*added 'ieee80211w' value '1'");
-	config_dict = build_supplicant_config (connection, 1500, 0);
+	NMTST_EXPECT_NM_INFO ("Config: added 'ssid' value 'Test SSID'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'scan_ssid' value '1'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'bssid' value '11:22:33:44:55:66'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'freq_list' value *");
+	NMTST_EXPECT_NM_INFO ("Config: added 'key_mgmt' value 'WPA-PSK WPA-PSK-SHA256'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'psk' value *");
+	NMTST_EXPECT_NM_INFO ("Config: added 'proto' value 'WPA RSN'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'pairwise' value 'TKIP CCMP'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'group' value 'TKIP CCMP'");
+	switch (pmf) {
+	case NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL:
+		NMTST_EXPECT_NM_INFO ("Config: added 'ieee80211w' value '1'");
+		break;
+	case NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED:
+		NMTST_EXPECT_NM_INFO ("Config: added 'ieee80211w' value '2'");
+		break;
+	default:
+		break;
+	}
+	config_dict = build_supplicant_config (connection, 1500, 0, TRUE, TRUE);
 
 	g_test_assert_expected_messages ();
 	g_assert (config_dict);
@@ -381,12 +396,16 @@ test_wifi_wpa_psk_types (void)
 	                                        0x6c, 0x2f, 0x11, 0x60, 0x5a, 0x16, 0x08, 0x93 };
 	const char *key2 = "r34lly l33t wp4 p4ssphr4s3 for t3st1ng";
 
-	test_wifi_wpa_psk ("wifi-wpa-psk-hex", TYPE_BYTES, key1, key1_expected, sizeof (key1_expected));
-	test_wifi_wpa_psk ("wifi-wep-psk-passphrase", TYPE_STRING, key2, (gconstpointer) key2, strlen (key2));
+	test_wifi_wpa_psk ("wifi-wpa-psk-hex", TYPE_BYTES, key1, key1_expected,
+	                   sizeof (key1_expected), NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL);
+	test_wifi_wpa_psk ("wifi-wep-psk-passphrase", TYPE_STRING, key2,
+	                   (gconstpointer) key2, strlen (key2), NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED);
+	test_wifi_wpa_psk ("pmf-disabled", TYPE_STRING, key2,
+	                   (gconstpointer) key2, strlen (key2), NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE);
 }
 
 static NMConnection *
-generate_wifi_eap_connection (const char *id, GBytes *ssid, const char *bssid_str)
+generate_wifi_eap_connection (const char *id, GBytes *ssid, const char *bssid_str, NMSettingWirelessSecurityFils fils)
 {
 	NMConnection *connection = NULL;
 	NMSettingWirelessSecurity *s_wsec;
@@ -401,6 +420,7 @@ generate_wifi_eap_connection (const char *id, GBytes *ssid, const char *bssid_st
 	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
 	g_object_set (s_wsec,
 	              NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap",
+	              NM_SETTING_WIRELESS_SECURITY_FILS, (int) fils,
 	              NULL);
 	nm_setting_wireless_security_add_proto (s_wsec, "wpa");
 	nm_setting_wireless_security_add_proto (s_wsec, "rsn");
@@ -434,22 +454,22 @@ test_wifi_eap_locked_bssid (void)
 	const char *bssid_str = "11:22:33:44:55:66";
 	guint32 mtu = 1100;
 
-	connection = generate_wifi_eap_connection ("Test Wifi EAP-TLS Locked", ssid, bssid_str);
-
-	EXPECT ("*added 'ssid' value 'Test SSID'*");
-	EXPECT ("*added 'scan_ssid' value '1'*");
-	EXPECT ("*added 'bssid' value '11:22:33:44:55:66'*");
-	EXPECT ("*added 'freq_list' value *");
-	EXPECT ("*added 'key_mgmt' value 'WPA-EAP'");
-	EXPECT ("*added 'proto' value 'WPA RSN'");
-	EXPECT ("*added 'pairwise' value 'TKIP CCMP'");
-	EXPECT ("*added 'group' value 'TKIP CCMP'");
-	EXPECT ("*Config: added 'eap' value 'TLS'");
-	EXPECT ("*Config: added 'fragment_size' value '1086'");
-	EXPECT ("* Config: added 'ca_cert' value '*/test-ca-cert.pem'");
-	EXPECT ("* Config: added 'private_key' value '*/test-cert.p12'");
-	EXPECT ("*Config: added 'proactive_key_caching' value '1'");
-	config_dict = build_supplicant_config (connection, mtu, 0);
+	connection = generate_wifi_eap_connection ("Test Wifi EAP-TLS Locked", ssid, bssid_str, NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL);
+
+	NMTST_EXPECT_NM_INFO ("Config: added 'ssid' value 'Test SSID'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'scan_ssid' value '1'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'bssid' value '11:22:33:44:55:66'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'freq_list' value *");
+	NMTST_EXPECT_NM_INFO ("Config: added 'key_mgmt' value 'WPA-EAP'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'proto' value 'WPA RSN'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'pairwise' value 'TKIP CCMP'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'group' value 'TKIP CCMP'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'eap' value 'TLS'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'fragment_size' value '1086'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'ca_cert' value '*/test-ca-cert.pem'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'private_key' value '*/test-cert.p12'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'proactive_key_caching' value '1'");
+	config_dict = build_supplicant_config (connection, mtu, 0, FALSE, FALSE);
 	g_test_assert_expected_messages ();
 	g_assert (config_dict);
 
@@ -475,28 +495,69 @@ test_wifi_eap_unlocked_bssid (void)
 	gs_unref_bytes GBytes *bgscan = g_bytes_new (bgscan_data, strlen (bgscan_data));
 	guint32 mtu = 1100;
 
-	connection = generate_wifi_eap_connection ("Test Wifi EAP-TLS Unlocked", ssid, NULL);
-
-	EXPECT ("*added 'ssid' value 'Test SSID'*");
-	EXPECT ("*added 'scan_ssid' value '1'*");
-	EXPECT ("*added 'freq_list' value *");
-	EXPECT ("*added 'key_mgmt' value 'WPA-EAP'");
-	EXPECT ("*added 'proto' value 'WPA RSN'");
-	EXPECT ("*added 'pairwise' value 'TKIP CCMP'");
-	EXPECT ("*added 'group' value 'TKIP CCMP'");
-	EXPECT ("*Config: added 'eap' value 'TLS'");
-	EXPECT ("*Config: added 'fragment_size' value '1086'");
-	EXPECT ("* Config: added 'ca_cert' value '*/test-ca-cert.pem'");
-	EXPECT ("* Config: added 'private_key' value '*/test-cert.p12'");
-	EXPECT ("*Config: added 'proactive_key_caching' value '1'");
-	EXPECT ("*Config: added 'bgscan' value 'simple:30:-65:300'");
-	config_dict = build_supplicant_config (connection, mtu, 0);
+	connection = generate_wifi_eap_connection ("Test Wifi EAP-TLS Unlocked", ssid, NULL, NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED);
+
+	NMTST_EXPECT_NM_INFO ("Config: added 'ssid' value 'Test SSID'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'scan_ssid' value '1'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'freq_list' value *");
+	NMTST_EXPECT_NM_INFO ("Config: added 'key_mgmt' value 'FILS-SHA256 FILS-SHA384'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'proto' value 'WPA RSN'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'pairwise' value 'TKIP CCMP'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'group' value 'TKIP CCMP'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'eap' value 'TLS'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'fragment_size' value '1086'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'ca_cert' value '*/test-ca-cert.pem'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'private_key' value '*/test-cert.p12'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'proactive_key_caching' value '1'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'bgscan' value 'simple:30:-65:300'");
+	config_dict = build_supplicant_config (connection, mtu, 0, FALSE, TRUE);
 	g_test_assert_expected_messages ();
 	g_assert (config_dict);
 
 	validate_opt ("wifi-eap", config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1));
 	validate_opt ("wifi-eap", config_dict, "ssid", TYPE_BYTES, ssid);
-	validate_opt ("wifi-eap", config_dict, "key_mgmt", TYPE_KEYWORD, "WPA-EAP");
+	validate_opt ("wifi-eap", config_dict, "key_mgmt", TYPE_KEYWORD, "FILS-SHA256 FILS-SHA384");
+	validate_opt ("wifi-eap", config_dict, "eap", TYPE_KEYWORD, "TLS");
+	validate_opt ("wifi-eap", config_dict, "proto", TYPE_KEYWORD, "WPA RSN");
+	validate_opt ("wifi-eap", config_dict, "pairwise", TYPE_KEYWORD, "TKIP CCMP");
+	validate_opt ("wifi-eap", config_dict, "group", TYPE_KEYWORD, "TKIP CCMP");
+	validate_opt ("wifi-eap", config_dict, "fragment_size", TYPE_INT, GINT_TO_POINTER(mtu-14));
+	validate_opt ("wifi-eap", config_dict, "bgscan", TYPE_BYTES, bgscan);
+}
+
+static void
+test_wifi_eap_fils_disabled (void)
+{
+	gs_unref_object NMConnection *connection = NULL;
+	gs_unref_variant GVariant *config_dict = NULL;
+	const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 };
+	gs_unref_bytes GBytes *ssid = g_bytes_new (ssid_data, sizeof (ssid_data));
+	const char *bgscan_data = "simple:30:-65:300";
+	gs_unref_bytes GBytes *bgscan = g_bytes_new (bgscan_data, strlen (bgscan_data));
+	guint32 mtu = 1100;
+
+	connection = generate_wifi_eap_connection ("Test Wifi FILS disabled", ssid, NULL, NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE);
+
+	NMTST_EXPECT_NM_INFO ("Config: added 'ssid' value 'Test SSID'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'scan_ssid' value '1'*");
+	NMTST_EXPECT_NM_INFO ("Config: added 'freq_list' value *");
+	NMTST_EXPECT_NM_INFO ("Config: added 'key_mgmt' value 'WPA-EAP WPA-EAP-SHA256'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'proto' value 'WPA RSN'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'pairwise' value 'TKIP CCMP'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'group' value 'TKIP CCMP'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'eap' value 'TLS'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'fragment_size' value '1086'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'ca_cert' value '*/test-ca-cert.pem'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'private_key' value '*/test-cert.p12'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'proactive_key_caching' value '1'");
+	NMTST_EXPECT_NM_INFO ("Config: added 'bgscan' value 'simple:30:-65:300'");
+	config_dict = build_supplicant_config (connection, mtu, 0, TRUE, TRUE);
+	g_test_assert_expected_messages ();
+	g_assert (config_dict);
+
+	validate_opt ("wifi-eap", config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1));
+	validate_opt ("wifi-eap", config_dict, "ssid", TYPE_BYTES, ssid);
+	validate_opt ("wifi-eap", config_dict, "key_mgmt", TYPE_KEYWORD, "WPA-EAP WPA-EAP-SHA256");
 	validate_opt ("wifi-eap", config_dict, "eap", TYPE_KEYWORD, "TLS");
 	validate_opt ("wifi-eap", config_dict, "proto", TYPE_KEYWORD, "WPA RSN");
 	validate_opt ("wifi-eap", config_dict, "pairwise", TYPE_KEYWORD, "TKIP CCMP");
@@ -516,6 +577,7 @@ int main (int argc, char **argv)
 	g_test_add_func ("/supplicant-config/wifi-wpa-psk-types", test_wifi_wpa_psk_types);
 	g_test_add_func ("/supplicant-config/wifi-eap/locked-bssid", test_wifi_eap_locked_bssid);
 	g_test_add_func ("/supplicant-config/wifi-eap/unlocked-bssid", test_wifi_eap_unlocked_bssid);
+	g_test_add_func ("/supplicant-config/wifi-eap/fils-disabled", test_wifi_eap_fils_disabled);
 
 	return g_test_run ();
 }