summaryrefslogtreecommitdiff
path: root/src/supplicant-manager
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2015-10-07 16:03:16 -0500
committerThomas Haller <thaller@redhat.com>2015-11-18 15:37:42 +0100
commit190e0e31cd553566c80d371466f7171a0384bf50 (patch)
treecbe93aa402a7c7423aff9bcf330210ebeb39c0db /src/supplicant-manager
parent21e84f21af1799ac50fc9a7e38c5be603668d2a3 (diff)
downloadNetworkManager-190e0e31cd553566c80d371466f7171a0384bf50.tar.gz
wifi: implement MAC address randomization
If the supplicant supports it and the connection requests it, tell the supplicant to randomize the MAC address for the association. In addition, like both iOS, Android, and other OSs always randomize the MAC address when performing a WiFi scan.
Diffstat (limited to 'src/supplicant-manager')
-rw-r--r--src/supplicant-manager/nm-supplicant-config.c53
-rw-r--r--src/supplicant-manager/nm-supplicant-config.h7
-rw-r--r--src/supplicant-manager/nm-supplicant-interface.c105
-rw-r--r--src/supplicant-manager/nm-supplicant-interface.h6
-rw-r--r--src/supplicant-manager/nm-supplicant-types.h6
-rw-r--r--src/supplicant-manager/tests/test-supplicant-config.c24
6 files changed, 170 insertions, 31 deletions
diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c
index 65d6e2df44..28047b62e8 100644
--- a/src/supplicant-manager/nm-supplicant-config.c
+++ b/src/supplicant-manager/nm-supplicant-config.c
@@ -39,7 +39,7 @@ G_DEFINE_TYPE (NMSupplicantConfig, nm_supplicant_config, G_TYPE_OBJECT)
typedef struct {
char *value;
- guint32 len;
+ guint32 len;
OptType type;
} ConfigOption;
@@ -48,6 +48,7 @@ typedef struct
GHashTable *config;
GHashTable *blobs;
guint32 ap_scan;
+ NMSettingMacRandomization mac_randomization;
gboolean fast_required;
gboolean dispose_has_run;
} NMSupplicantConfigPrivate;
@@ -85,6 +86,7 @@ nm_supplicant_config_init (NMSupplicantConfig * self)
(GDestroyNotify) blob_free);
priv->ap_scan = 1;
+ priv->mac_randomization = NM_SETTING_MAC_RANDOMIZATION_DEFAULT;
priv->dispose_has_run = FALSE;
}
@@ -240,14 +242,30 @@ nm_supplicant_config_get_ap_scan (NMSupplicantConfig * self)
return NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->ap_scan;
}
-void
-nm_supplicant_config_set_ap_scan (NMSupplicantConfig * self,
- guint32 ap_scan)
+const char *
+nm_supplicant_config_get_mac_randomization (NMSupplicantConfig *self)
{
- g_return_if_fail (NM_IS_SUPPLICANT_CONFIG (self));
- g_return_if_fail (ap_scan <= 2);
+ g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), 0);
+
+ /**
+ * mac_addr - MAC address policy default
+ *
+ * 0 = use permanent MAC address
+ * 1 = use random MAC address for each ESS connection
+ * 2 = like 1, but maintain OUI (with local admin bit set)
+ *
+ * By default, permanent MAC address is used unless policy is changed by
+ * the per-network mac_addr parameter.
+ */
- NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->ap_scan = ap_scan;
+ switch (NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->mac_randomization) {
+ case NM_SETTING_MAC_RANDOMIZATION_ALWAYS:
+ return "1";
+ case NM_SETTING_MAC_RANDOMIZATION_NEVER:
+ case NM_SETTING_MAC_RANDOMIZATION_DEFAULT:
+ default:
+ return "0";
+ }
}
gboolean
@@ -336,7 +354,9 @@ wifi_freqs_to_string (gboolean bg_band)
gboolean
nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self,
NMSettingWireless * setting,
- guint32 fixed_freq)
+ guint32 fixed_freq,
+ NMSupplicantFeature mac_randomization_support,
+ NMSettingMacRandomization mac_randomization_fallback)
{
NMSupplicantConfigPrivate *priv;
gboolean is_adhoc, is_ap;
@@ -441,6 +461,21 @@ nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self,
}
}
+ priv->mac_randomization = nm_setting_wireless_get_mac_address_randomization (setting);
+ if (priv->mac_randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT) {
+ priv->mac_randomization = mac_randomization_fallback;
+ if (priv->mac_randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT) {
+ /* the value is unconfigured. For now, that means we don't use randomization.*/
+ priv->mac_randomization = NM_SETTING_MAC_RANDOMIZATION_NEVER;
+ }
+ }
+
+ if ( priv->mac_randomization != NM_SETTING_MAC_RANDOMIZATION_NEVER
+ && mac_randomization_support != NM_SUPPLICANT_FEATURE_YES) {
+ nm_log_warn (LOGD_SUPPLICANT, "MAC address randomization is not supported");
+ return FALSE;
+ }
+
return TRUE;
}
@@ -805,7 +840,7 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
/* Wired 802.1x must always use eapol_flags=0 */
if (!add_string_val (self, "0", "eapol_flags", FALSE, FALSE))
return FALSE;
- nm_supplicant_config_set_ap_scan (self, 0);
+ priv->ap_scan = 0;
}
ADD_STRING_LIST_VAL (setting, 802_1x, eap_method, eap_methods, "eap", ' ', TRUE, FALSE);
diff --git a/src/supplicant-manager/nm-supplicant-config.h b/src/supplicant-manager/nm-supplicant-config.h
index 0cd3243ebf..b87edb43b0 100644
--- a/src/supplicant-manager/nm-supplicant-config.h
+++ b/src/supplicant-manager/nm-supplicant-config.h
@@ -54,8 +54,7 @@ NMSupplicantConfig *nm_supplicant_config_new (void);
guint32 nm_supplicant_config_get_ap_scan (NMSupplicantConfig *self);
-void nm_supplicant_config_set_ap_scan (NMSupplicantConfig *self,
- guint32 ap_scan);
+const char *nm_supplicant_config_get_mac_randomization (NMSupplicantConfig *self);
gboolean nm_supplicant_config_fast_required (NMSupplicantConfig *self);
@@ -65,7 +64,9 @@ GHashTable *nm_supplicant_config_get_blobs (NMSupplicantConfig *self);
gboolean nm_supplicant_config_add_setting_wireless (NMSupplicantConfig *self,
NMSettingWireless *setting,
- guint32 fixed_freq);
+ guint32 fixed_freq,
+ NMSupplicantFeature mac_randomization_support,
+ NMSettingMacRandomization mac_randomization_fallback);
gboolean nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
NMSettingWirelessSecurity *setting,
diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c
index 64a06b62fa..8267fb98af 100644
--- a/src/supplicant-manager/nm-supplicant-interface.c
+++ b/src/supplicant-manager/nm-supplicant-interface.c
@@ -488,6 +488,23 @@ nm_supplicant_interface_get_mac_randomization_support (NMSupplicantInterface *se
}
static void
+set_preassoc_scan_mac_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
+{
+ gs_unref_variant GVariant *variant = NULL;
+ gs_free_error GError *error = NULL;
+
+ variant = _nm_dbus_proxy_call_finish (proxy, result,
+ G_VARIANT_TYPE ("()"),
+ &error);
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+ if (error)
+ nm_log_warn (LOGD_SUPPLICANT, "Failed to enable scan MAC address randomization");
+
+ iface_check_ready (NM_SUPPLICANT_INTERFACE (user_data));
+}
+
+static void
iface_introspect_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
{
NMSupplicantInterface *self;
@@ -512,8 +529,23 @@ iface_introspect_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data
if (strstr (data, "ProbeRequest"))
priv->ap_support = NM_SUPPLICANT_FEATURE_YES;
- if (strstr (data, "PreassocMacAddr"))
+ if (strstr (data, "PreassocMacAddr")) {
priv->mac_randomization_support = NM_SUPPLICANT_FEATURE_YES;
+
+ /* Turn on MAC randomization during scans by default */
+ priv->ready_count++;
+ g_dbus_proxy_call (priv->iface_proxy,
+ DBUS_INTERFACE_PROPERTIES ".Set",
+ g_variant_new ("(ssv)",
+ WPAS_DBUS_IFACE_INTERFACE,
+ "PreassocMacAddr",
+ g_variant_new_string ("1")),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ priv->init_cancellable,
+ (GAsyncReadyCallback) set_preassoc_scan_mac_cb,
+ self);
+ }
}
iface_check_ready (self);
@@ -1126,6 +1158,51 @@ add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
}
static void
+add_network (NMSupplicantInterface *self)
+{
+ NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+ g_dbus_proxy_call (priv->iface_proxy,
+ "AddNetwork",
+ g_variant_new ("(@a{sv})", nm_supplicant_config_to_variant (priv->cfg)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ priv->assoc_cancellable,
+ (GAsyncReadyCallback) add_network_cb,
+ self);
+}
+
+static void
+set_mac_randomization_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);
+ nm_log_warn (LOGD_SUPPLICANT, "Couldn't send MAC randomization mode to "
+ "the supplicant interface: %s.",
+ error->message);
+ emit_error_helper (self, error);
+ return;
+ }
+
+ nm_log_info (LOGD_SUPPLICANT, "Config: set MAC randomization to %s",
+ nm_supplicant_config_get_mac_randomization (priv->cfg));
+
+ add_network (self);
+}
+
+static void
set_ap_scan_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
{
NMSupplicantInterface *self;
@@ -1151,14 +1228,24 @@ set_ap_scan_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
nm_log_info (LOGD_SUPPLICANT, "Config: set interface ap_scan to %d",
nm_supplicant_config_get_ap_scan (priv->cfg));
- g_dbus_proxy_call (priv->iface_proxy,
- "AddNetwork",
- g_variant_new ("(@a{sv})", nm_supplicant_config_to_variant (priv->cfg)),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- priv->assoc_cancellable,
- (GAsyncReadyCallback) add_network_cb,
- self);
+ if (priv->mac_randomization_support == NM_SUPPLICANT_FEATURE_YES) {
+ const char *mac_randomization = nm_supplicant_config_get_mac_randomization (priv->cfg);
+
+ /* Enable/disable association MAC address randomization */
+ g_dbus_proxy_call (priv->iface_proxy,
+ DBUS_INTERFACE_PROPERTIES ".Set",
+ g_variant_new ("(ssv)",
+ WPAS_DBUS_IFACE_INTERFACE,
+ "MacAddr",
+ g_variant_new_string (mac_randomization)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ priv->assoc_cancellable,
+ (GAsyncReadyCallback) set_mac_randomization_cb,
+ self);
+ } else {
+ add_network (self);
+ }
}
gboolean
diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h
index 4cfdf5fdd8..77371789fe 100644
--- a/src/supplicant-manager/nm-supplicant-interface.h
+++ b/src/supplicant-manager/nm-supplicant-interface.h
@@ -67,12 +67,6 @@ enum {
#define NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR "connection-error"
#define NM_SUPPLICANT_INTERFACE_CREDENTIALS_REQUEST "credentials-request"
-typedef enum {
- NM_SUPPLICANT_FEATURE_UNKNOWN = 0, /* Can't detect whether supported or not */
- NM_SUPPLICANT_FEATURE_NO = 1, /* Feature definitely not supported */
- NM_SUPPLICANT_FEATURE_YES = 2, /* Feature definitely supported */
-} NMSupplicantFeature;
-
struct _NMSupplicantInterface {
GObject parent;
};
diff --git a/src/supplicant-manager/nm-supplicant-types.h b/src/supplicant-manager/nm-supplicant-types.h
index 1c16e49433..02682f566c 100644
--- a/src/supplicant-manager/nm-supplicant-types.h
+++ b/src/supplicant-manager/nm-supplicant-types.h
@@ -29,4 +29,10 @@ typedef struct _NMSupplicantManager NMSupplicantManager;
typedef struct _NMSupplicantInterface NMSupplicantInterface;
typedef struct _NMSupplicantConfig NMSupplicantConfig;
+typedef enum {
+ NM_SUPPLICANT_FEATURE_UNKNOWN = 0, /* Can't detect whether supported or not */
+ NM_SUPPLICANT_FEATURE_NO = 1, /* Feature definitely not supported */
+ NM_SUPPLICANT_FEATURE_YES = 2, /* Feature definitely supported */
+} NMSupplicantFeature;
+
#endif /* NM_SUPPLICANT_TYPES_H */
diff --git a/src/supplicant-manager/tests/test-supplicant-config.c b/src/supplicant-manager/tests/test-supplicant-config.c
index 11b027a3ed..01f5535a2b 100644
--- a/src/supplicant-manager/tests/test-supplicant-config.c
+++ b/src/supplicant-manager/tests/test-supplicant-config.c
@@ -158,7 +158,11 @@ test_wifi_open (void)
"*added 'bssid' value '11:22:33:44:55:66'*");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*added 'freq_list' value *");
- g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, 0));
+ g_assert (nm_supplicant_config_add_setting_wireless (config,
+ s_wifi,
+ 0,
+ NM_SUPPLICANT_FEATURE_UNKNOWN,
+ NM_SETTING_MAC_RANDOMIZATION_DEFAULT));
g_test_assert_expected_messages ();
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
@@ -256,7 +260,11 @@ test_wifi_wep_key (const char *detail,
"*added 'bssid' value '11:22:33:44:55:66'*");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*added 'freq_list' value *");
- g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, 0));
+ g_assert (nm_supplicant_config_add_setting_wireless (config,
+ s_wifi,
+ 0,
+ NM_SUPPLICANT_FEATURE_UNKNOWN,
+ NM_SETTING_MAC_RANDOMIZATION_DEFAULT));
g_test_assert_expected_messages ();
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
@@ -393,7 +401,11 @@ test_wifi_wpa_psk (const char *detail,
"*added 'bssid' value '11:22:33:44:55:66'*");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*added 'freq_list' value *");
- g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, 0));
+ g_assert (nm_supplicant_config_add_setting_wireless (config,
+ s_wifi,
+ 0,
+ NM_SUPPLICANT_FEATURE_UNKNOWN,
+ NM_SETTING_MAC_RANDOMIZATION_DEFAULT));
g_test_assert_expected_messages ();
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
@@ -532,7 +544,11 @@ test_wifi_eap (void)
"*added 'bssid' value '11:22:33:44:55:66'*");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*added 'freq_list' value *");
- g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, 0));
+ g_assert (nm_supplicant_config_add_setting_wireless (config,
+ s_wifi,
+ 0,
+ NM_SUPPLICANT_FEATURE_UNKNOWN,
+ NM_SETTING_MAC_RANDOMIZATION_DEFAULT));
g_test_assert_expected_messages ();
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,