diff options
-rw-r--r-- | man/NetworkManager.conf.xml.in | 4 | ||||
-rw-r--r-- | src/devices/wifi/nm-device-wifi.c | 17 | ||||
-rw-r--r-- | src/supplicant-manager/nm-supplicant-config.c | 53 | ||||
-rw-r--r-- | src/supplicant-manager/nm-supplicant-config.h | 7 | ||||
-rw-r--r-- | src/supplicant-manager/nm-supplicant-interface.c | 105 | ||||
-rw-r--r-- | src/supplicant-manager/nm-supplicant-interface.h | 6 | ||||
-rw-r--r-- | src/supplicant-manager/nm-supplicant-types.h | 6 | ||||
-rw-r--r-- | src/supplicant-manager/tests/test-supplicant-config.c | 24 |
8 files changed, 190 insertions, 32 deletions
diff --git a/man/NetworkManager.conf.xml.in b/man/NetworkManager.conf.xml.in index 3fd1b12b19..b7e228aa3e 100644 --- a/man/NetworkManager.conf.xml.in +++ b/man/NetworkManager.conf.xml.in @@ -610,6 +610,10 @@ ipv6.ip6-privacy=1 <term><varname>vpn.timeout</varname></term> <listitem><para>If left unspecified, default value of 60 seconds is used.</para></listitem> </varlistentry> + <varlistentry> + <term><varname>wifi.mac-address-randomization</varname></term> + <listitem><para>If left unspecified, MAC address randomization is disabled.</para></listitem> + </varlistentry> </para> </refsect1> diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 3ba532dd6d..6327cba0df 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -49,6 +49,7 @@ #include "nm-enum-types.h" #include "nm-connection-provider.h" #include "nm-core-internal.h" +#include "nm-config.h" #include "nmdbus-device-wifi.h" @@ -2201,6 +2202,9 @@ build_supplicant_config (NMDeviceWifi *self, NMSupplicantConfig *config = NULL; NMSettingWireless *s_wireless; NMSettingWirelessSecurity *s_wireless_sec; + NMSupplicantFeature mac_randomization_support; + NMSettingMacRandomization mac_randomization_fallback; + gs_free char *svalue = NULL; g_return_val_if_fail (self != NULL, NULL); @@ -2217,9 +2221,20 @@ build_supplicant_config (NMDeviceWifi *self, _LOGW (LOGD_WIFI, "Supplicant may not support AP mode; connection may time out."); } + mac_randomization_support = nm_supplicant_interface_get_mac_randomization_support (priv->sup_iface); + svalue = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "wifi." NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, + NM_DEVICE (self)); + mac_randomization_fallback = _nm_utils_ascii_str_to_int64 (svalue, 10, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT, + NM_SETTING_MAC_RANDOMIZATION_ALWAYS, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT); + if (!nm_supplicant_config_add_setting_wireless (config, s_wireless, - fixed_freq)) { + fixed_freq, + mac_randomization_support, + mac_randomization_fallback)) { _LOGE (LOGD_WIFI, "Couldn't add 802-11-wireless setting to supplicant config."); goto error; } 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, |