From 325faa23799c617c238f110cb77d8a854614c76b Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 8 Oct 2015 13:40:45 +0200 Subject: [PATCH 1/8] ifcfg-rh: add svSetValueInt64() utility --- src/settings/plugins/ifcfg-rh/shvar.c | 9 +++++++++ src/settings/plugins/ifcfg-rh/shvar.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c index ffb0f8f7da..43068c6703 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.c +++ b/src/settings/plugins/ifcfg-rh/shvar.c @@ -445,6 +445,15 @@ svSetValueFull (shvarFile *s, const char *key, const char *value, gboolean verba g_free (keyValue); } +void +svSetValueInt64 (shvarFile *s, const char *key, gint64 value) +{ + gs_free char *v = NULL; + + v = g_strdup_printf ("%"G_GINT64_FORMAT, value); + svSetValueFull (s, key, v, TRUE); +} + /* Write the current contents iff modified. Returns FALSE on error * and TRUE on success. Do not write if no values have been modified. * The mode argument is only used if creating the file, not if diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h index d51e07685f..227a44db17 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.h +++ b/src/settings/plugins/ifcfg-rh/shvar.h @@ -75,6 +75,7 @@ gint64 svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, g */ void svSetValue (shvarFile *s, const char *key, const char *value, gboolean verbatim); void svSetValueFull (shvarFile *s, const char *key, const char *value, gboolean verbatim); +void svSetValueInt64 (shvarFile *s, const char *key, gint64 value); /* Write the current contents iff modified. Returns FALSE on error From 02228221340dc0824639c73d1a515ee85df3dbbc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 6 Oct 2015 17:42:15 -0400 Subject: [PATCH 2/8] libnm: add Wi-Fi MAC address randomization property --- libnm-core/nm-setting-wireless.c | 43 ++++++++++++++++++++++++++++++++ libnm-core/nm-setting-wireless.h | 4 +++ libnm-core/nm-setting.h | 16 ++++++++++++ libnm/libnm.ver | 2 ++ 4 files changed, 65 insertions(+) diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c index b6be7d0242..9931521825 100644 --- a/libnm-core/nm-setting-wireless.c +++ b/libnm-core/nm-setting-wireless.c @@ -59,6 +59,7 @@ typedef struct { GSList *seen_bssids; gboolean hidden; guint32 powersave; + NMSettingMacRandomization mac_address_randomization; } NMSettingWirelessPrivate; enum { @@ -77,6 +78,7 @@ enum { PROP_SEEN_BSSIDS, PROP_HIDDEN, PROP_POWERSAVE, + PROP_MAC_ADDRESS_RANDOMIZATION, LAST_PROP }; @@ -617,6 +619,23 @@ nm_setting_wireless_get_powersave (NMSettingWireless *setting) return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->powersave; } +/** + * nm_setting_wireless_get_mac_address_randomization: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:mac-address-randomization property of the + * setting + * + * Since: 1.2 + **/ +NMSettingMacRandomization +nm_setting_wireless_get_mac_address_randomization (NMSettingWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0); + + return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mac_address_randomization; +} + /** * nm_setting_wireless_add_seen_bssid: * @setting: the #NMSettingWireless @@ -935,6 +954,9 @@ set_property (GObject *object, guint prop_id, case PROP_POWERSAVE: priv->powersave = g_value_get_uint (value); break; + case PROP_MAC_ADDRESS_RANDOMIZATION: + priv->mac_address_randomization = g_value_get_uint (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -991,6 +1013,9 @@ get_property (GObject *object, guint prop_id, case PROP_POWERSAVE: g_value_set_uint (value, nm_setting_wireless_get_powersave (setting)); break; + case PROP_MAC_ADDRESS_RANDOMIZATION: + g_value_set_uint (value, nm_setting_wireless_get_mac_address_randomization (setting)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1362,6 +1387,24 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * NMSettingWireless:mac-address-randomization: + * + * One of %NM_SETTING_MAC_RANDOMIZATION_DEFAULT (never randomize unless + * the user has set a global default to randomize and the supplicant + * supports randomization), %NM_SETTING_MAC_RANDOMIZATION_NEVER (never + * randomize the MAC address), or %NM_SETTING_MAC_RANDOMIZATION_ALWAYS + * (always randomize the MAC address). + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_MAC_ADDRESS_RANDOMIZATION, + g_param_spec_uint (NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, "", "", + 0, G_MAXUINT32, NM_SETTING_MAC_RANDOMIZATION_DEFAULT, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + /* Compatibility for deprecated property */ /* ---ifcfg-rh--- * property: security diff --git a/libnm-core/nm-setting-wireless.h b/libnm-core/nm-setting-wireless.h index 9fdf6c1975..a4c0147f40 100644 --- a/libnm-core/nm-setting-wireless.h +++ b/libnm-core/nm-setting-wireless.h @@ -55,6 +55,7 @@ G_BEGIN_DECLS #define NM_SETTING_WIRELESS_SEEN_BSSIDS "seen-bssids" #define NM_SETTING_WIRELESS_HIDDEN "hidden" #define NM_SETTING_WIRELESS_POWERSAVE "powersave" +#define NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION "mac-address-randomization" /** * NM_SETTING_WIRELESS_MODE_ADHOC: @@ -121,6 +122,9 @@ gboolean nm_setting_wireless_get_hidden (NMSettingWireless NM_AVAILABLE_IN_1_2 guint32 nm_setting_wireless_get_powersave (NMSettingWireless *setting); +NM_AVAILABLE_IN_1_2 +NMSettingMacRandomization nm_setting_wireless_get_mac_address_randomization (NMSettingWireless *setting); + gboolean nm_setting_wireless_add_seen_bssid (NMSettingWireless *setting, const char *bssid); diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h index 5df73663cb..7b1d87d576 100644 --- a/libnm-core/nm-setting.h +++ b/libnm-core/nm-setting.h @@ -131,6 +131,22 @@ typedef enum { } NMSettingCompareFlags; +/** + * NMSettingMacRandomization: + * @NM_SETTING_MAC_RANDOMIZATION_DEFAULT: the default value, which unless + * overridden by user-controlled defaults configuration, is "never". + * @NM_SETTING_MAC_RANDOMIZATION_NEVER: the device's MAC address is always used. + * @NM_SETTING_MAC_RANDOMIZATION_ALWAYS: a random MAC address is used. + * + * Controls if and how the MAC address of a device is randomzied. + **/ +typedef enum { + NM_SETTING_MAC_RANDOMIZATION_DEFAULT = 0, + NM_SETTING_MAC_RANDOMIZATION_NEVER, + NM_SETTING_MAC_RANDOMIZATION_ALWAYS, +} NMSettingMacRandomization; + + /** * NMSetting: * diff --git a/libnm/libnm.ver b/libnm/libnm.ver index c99fc81917..eff17b3dae 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -891,11 +891,13 @@ global: nm_setting_ip_config_has_dns_options; nm_setting_ip_config_remove_dns_option; nm_setting_ip_config_remove_dns_option_by_value; + nm_setting_mac_randomization_get_type; nm_setting_vpn_get_timeout; nm_setting_wired_get_wake_on_lan; nm_setting_wired_get_wake_on_lan_password; nm_setting_wired_wake_on_lan_get_type; nm_setting_wireless_get_powersave; + nm_setting_wireless_get_mac_address_randomization; nm_utils_bond_mode_int_to_string; nm_utils_bond_mode_string_to_int; nm_utils_enum_from_str; From 63cbff08756cb63160f3092a20fb6a5f2bfce60c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 6 Oct 2015 20:02:40 -0500 Subject: [PATCH 3/8] trivial: wifi/supplicant: change ApSupport to NMSupplicantFeature --- src/devices/wifi/nm-device-wifi.c | 4 ++-- .../nm-supplicant-interface.c | 12 +++++------ .../nm-supplicant-interface.h | 14 ++++++------- .../nm-supplicant-manager.c | 20 +++++++++---------- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 0eeb8459ce..3ba532dd6d 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -628,7 +628,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) return FALSE; if (priv->sup_iface) { - if (nm_supplicant_interface_get_ap_support (priv->sup_iface) == AP_SUPPORT_NO) + if (nm_supplicant_interface_get_ap_support (priv->sup_iface) == NM_SUPPLICANT_FEATURE_NO) return FALSE; } } @@ -2213,7 +2213,7 @@ build_supplicant_config (NMDeviceWifi *self, /* Warn if AP mode may not be supported */ if ( g_strcmp0 (nm_setting_wireless_get_mode (s_wireless), NM_SETTING_WIRELESS_MODE_AP) == 0 - && nm_supplicant_interface_get_ap_support (priv->sup_iface) == AP_SUPPORT_UNKNOWN) { + && nm_supplicant_interface_get_ap_support (priv->sup_iface) == NM_SUPPLICANT_FEATURE_UNKNOWN) { _LOGW (LOGD_WIFI, "Supplicant may not support AP mode; connection may time out."); } diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index 38eaabcb43..406449e35e 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -71,7 +71,7 @@ typedef struct { char * dev; gboolean is_wireless; gboolean has_credreq; /* Whether querying 802.1x credentials is supported */ - ApSupport ap_support; /* Lightweight AP mode support */ + NMSupplicantFeature ap_support; /* Lightweight AP mode support */ gboolean fast_supported; guint32 max_scan_ssids; guint32 ready_count; @@ -461,7 +461,7 @@ iface_check_netreply_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_ iface_check_ready (self); } -ApSupport +NMSupplicantFeature nm_supplicant_interface_get_ap_support (NMSupplicantInterface *self) { return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->ap_support; @@ -469,7 +469,7 @@ nm_supplicant_interface_get_ap_support (NMSupplicantInterface *self) void nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self, - ApSupport ap_support) + NMSupplicantFeature ap_support) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); @@ -502,7 +502,7 @@ iface_check_ap_mode_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_d if (variant) { g_variant_get (variant, "(&s)", &data); if (strstr (data, "ProbeRequest")) - priv->ap_support = AP_SUPPORT_YES; + priv->ap_support = NM_SUPPLICANT_FEATURE_YES; } iface_check_ready (self); @@ -714,7 +714,7 @@ on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_ (GAsyncReadyCallback) iface_check_netreply_cb, self); - if (priv->ap_support == AP_SUPPORT_UNKNOWN) { + if (priv->ap_support == NM_SUPPLICANT_FEATURE_UNKNOWN) { /* If the global supplicant capabilities property is not present, we can * fall back to checking whether the ProbeRequest method is supported. If * neither of these works we have no way of determining if AP mode is @@ -1330,7 +1330,7 @@ NMSupplicantInterface * nm_supplicant_interface_new (const char *ifname, gboolean is_wireless, gboolean fast_supported, - ApSupport ap_support, + NMSupplicantFeature ap_support, gboolean start_now) { NMSupplicantInterface *self; diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h index 79c88dabaa..46de7c6fd2 100644 --- a/src/supplicant-manager/nm-supplicant-interface.h +++ b/src/supplicant-manager/nm-supplicant-interface.h @@ -68,10 +68,10 @@ enum { #define NM_SUPPLICANT_INTERFACE_CREDENTIALS_REQUEST "credentials-request" typedef enum { - AP_SUPPORT_UNKNOWN = 0, /* Can't detect whether supported or not */ - AP_SUPPORT_NO = 1, /* AP mode definitely not supported */ - AP_SUPPORT_YES = 2, /* AP mode definitely supported */ -} ApSupport; + 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; @@ -125,7 +125,7 @@ GType nm_supplicant_interface_get_type (void); NMSupplicantInterface * nm_supplicant_interface_new (const char *ifname, gboolean is_wireless, gboolean fast_supported, - ApSupport ap_support, + NMSupplicantFeature ap_support, gboolean start_now); void nm_supplicant_interface_set_supplicant_available (NMSupplicantInterface *self, @@ -163,9 +163,9 @@ gboolean nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self, const char *value, GError **error); -ApSupport nm_supplicant_interface_get_ap_support (NMSupplicantInterface *self); +NMSupplicantFeature nm_supplicant_interface_get_ap_support (NMSupplicantInterface *self); void nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self, - ApSupport apmode); + NMSupplicantFeature apmode); #endif /* NM_SUPPLICANT_INTERFACE_H */ diff --git a/src/supplicant-manager/nm-supplicant-manager.c b/src/supplicant-manager/nm-supplicant-manager.c index 8afddeec7f..5fd1758438 100644 --- a/src/supplicant-manager/nm-supplicant-manager.c +++ b/src/supplicant-manager/nm-supplicant-manager.c @@ -39,11 +39,11 @@ typedef struct { GCancellable * cancellable; gboolean running; - GHashTable * ifaces; - gboolean fast_supported; - ApSupport ap_support; - guint die_count_reset_id; - guint die_count; + GHashTable * ifaces; + gboolean fast_supported; + NMSupplicantFeature ap_support; + guint die_count_reset_id; + guint die_count; } NMSupplicantManagerPrivate; /********************************************************************/ @@ -146,15 +146,15 @@ update_capabilities (NMSupplicantManager *self) * * dbus: Add global capabilities property */ - priv->ap_support = AP_SUPPORT_UNKNOWN; + priv->ap_support = NM_SUPPLICANT_FEATURE_UNKNOWN; value = g_dbus_proxy_get_cached_property (priv->proxy, "Capabilities"); if (value) { if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING_ARRAY)) { array = g_variant_get_strv (value, NULL); - priv->ap_support = AP_SUPPORT_NO; + priv->ap_support = NM_SUPPLICANT_FEATURE_NO; if (_nm_utils_string_in_list ("ap", array)) - priv->ap_support = AP_SUPPORT_YES; + priv->ap_support = NM_SUPPLICANT_FEATURE_YES; g_free (array); } g_variant_unref (value); @@ -166,8 +166,8 @@ update_capabilities (NMSupplicantManager *self) nm_supplicant_interface_set_ap_support (iface, priv->ap_support); nm_log_dbg (LOGD_SUPPLICANT, "AP mode is %ssupported", - (priv->ap_support == AP_SUPPORT_YES) ? "" : - (priv->ap_support == AP_SUPPORT_NO) ? "not " : "possibly "); + (priv->ap_support == NM_SUPPLICANT_FEATURE_YES) ? "" : + (priv->ap_support == NM_SUPPLICANT_FEATURE_NO) ? "not " : "possibly "); /* EAP-FAST */ priv->fast_supported = FALSE; From 21e84f21af1799ac50fc9a7e38c5be603668d2a3 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 6 Oct 2015 21:31:04 -0500 Subject: [PATCH 4/8] supplicant: check for MAC address randomization support --- .../nm-supplicant-interface.c | 20 +++++++++++++++---- .../nm-supplicant-interface.h | 2 ++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index 406449e35e..64a06b62fa 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -72,6 +72,7 @@ typedef struct { gboolean is_wireless; gboolean has_credreq; /* Whether querying 802.1x credentials is supported */ NMSupplicantFeature ap_support; /* Lightweight AP mode support */ + NMSupplicantFeature mac_randomization_support; gboolean fast_supported; guint32 max_scan_ssids; guint32 ready_count; @@ -480,8 +481,14 @@ nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self, priv->ap_support = ap_support; } +NMSupplicantFeature +nm_supplicant_interface_get_mac_randomization_support (NMSupplicantInterface *self) +{ + return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->mac_randomization_support; +} + static void -iface_check_ap_mode_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) +iface_introspect_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) { NMSupplicantInterface *self; NMSupplicantInterfacePrivate *priv; @@ -489,7 +496,6 @@ iface_check_ap_mode_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_d gs_free_error GError *error = NULL; const char *data; - /* The ProbeRequest method only exists if AP mode has been enabled */ variant = _nm_dbus_proxy_call_finish (proxy, result, G_VARIANT_TYPE ("(s)"), &error); @@ -501,8 +507,13 @@ iface_check_ap_mode_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_d if (variant) { g_variant_get (variant, "(&s)", &data); + + /* The ProbeRequest method only exists if AP mode has been enabled */ if (strstr (data, "ProbeRequest")) priv->ap_support = NM_SUPPLICANT_FEATURE_YES; + + if (strstr (data, "PreassocMacAddr")) + priv->mac_randomization_support = NM_SUPPLICANT_FEATURE_YES; } iface_check_ready (self); @@ -714,7 +725,8 @@ on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_ (GAsyncReadyCallback) iface_check_netreply_cb, self); - if (priv->ap_support == NM_SUPPLICANT_FEATURE_UNKNOWN) { + if (priv->ap_support == NM_SUPPLICANT_FEATURE_UNKNOWN || + priv->mac_randomization_support == NM_SUPPLICANT_FEATURE_UNKNOWN) { /* If the global supplicant capabilities property is not present, we can * fall back to checking whether the ProbeRequest method is supported. If * neither of these works we have no way of determining if AP mode is @@ -727,7 +739,7 @@ on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_ G_DBUS_CALL_FLAGS_NONE, -1, priv->init_cancellable, - (GAsyncReadyCallback) iface_check_ap_mode_cb, + (GAsyncReadyCallback) iface_introspect_cb, self); } } diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h index 46de7c6fd2..4cfdf5fdd8 100644 --- a/src/supplicant-manager/nm-supplicant-interface.h +++ b/src/supplicant-manager/nm-supplicant-interface.h @@ -168,4 +168,6 @@ NMSupplicantFeature nm_supplicant_interface_get_ap_support (NMSupplicantInterfac void nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self, NMSupplicantFeature apmode); +NMSupplicantFeature nm_supplicant_interface_get_mac_randomization_support (NMSupplicantInterface *self); + #endif /* NM_SUPPLICANT_INTERFACE_H */ From 190e0e31cd553566c80d371466f7171a0384bf50 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 7 Oct 2015 16:03:16 -0500 Subject: [PATCH 5/8] 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. --- man/NetworkManager.conf.xml.in | 4 + src/devices/wifi/nm-device-wifi.c | 17 ++- src/supplicant-manager/nm-supplicant-config.c | 53 +++++++-- src/supplicant-manager/nm-supplicant-config.h | 7 +- .../nm-supplicant-interface.c | 105 ++++++++++++++++-- .../nm-supplicant-interface.h | 6 - src/supplicant-manager/nm-supplicant-types.h | 6 + .../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 vpn.timeout If left unspecified, default value of 60 seconds is used. + + wifi.mac-address-randomization + If left unspecified, MAC address randomization is disabled. + 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); - NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->ap_scan = ap_scan; + /** + * 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. + */ + + 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 @@ -487,6 +487,23 @@ nm_supplicant_interface_get_mac_randomization_support (NMSupplicantInterface *se return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->mac_randomization_support; } +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) { @@ -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); @@ -1125,6 +1157,51 @@ add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) call_select_network (self); } +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) { @@ -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, From 6a46dfca267f8bdb4ffc6539e168a39702bbb7c2 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 8 Oct 2015 13:32:36 +0200 Subject: [PATCH 6/8] ifcfg-rh: add support for NMSettingWireless:mac-address-randomization Old init-scripts that did not yet understand this key will have mac-address-randomization explicitly disabled. This is to ensure that old connections don't change behavior. Thus, the writer must always write the value explicitly. Downside is, if somebody creates a quick ifcfg-file, the feature is disabled by default. --- libnm-core/nm-setting-wireless.c | 9 ++ src/settings/plugins/ifcfg-rh/reader.c | 22 +++ .../tests/network-scripts/Makefile.am | 4 + .../ifcfg-test-wifi-mac-random-always | 7 + .../ifcfg-test-wifi-mac-random-default | 6 + .../ifcfg-test-wifi-mac-random-missing | 6 + .../ifcfg-test-wifi-mac-random-never | 6 + .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 146 ++++++++++++++++++ src/settings/plugins/ifcfg-rh/writer.c | 16 +- 9 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-always create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-default create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-missing create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-never diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c index 9931521825..2a14829314 100644 --- a/libnm-core/nm-setting-wireless.c +++ b/libnm-core/nm-setting-wireless.c @@ -1398,6 +1398,15 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class) * * Since: 1.2 **/ + /* ---ifcfg-rh--- + * property: mac-address-randomization + * variable: MAC_ADDRESS_RANDOMIZATION(+) + * values: 0 (default), (1) never, (2) always + * default: 1 + * description: Enables or disables Wi-Fi MAC address randomization. + * example: MAC_ADDRESS_RANDOMIZATION=2 + * ---end--- + */ g_object_class_install_property (object_class, PROP_MAC_ADDRESS_RANDOMIZATION, g_param_spec_uint (NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, "", "", diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index 6ca9b92b09..5dee64d146 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -3314,6 +3314,7 @@ make_wireless_setting (shvarFile *ifcfg, NMSettingWireless *s_wireless; char *value = NULL; gint64 chan = 0; + NMSettingMacRandomization mac_randomization = NM_SETTING_MAC_RANDOMIZATION_NEVER; s_wireless = NM_SETTING_WIRELESS (nm_setting_wireless_new ()); @@ -3496,6 +3497,27 @@ make_wireless_setting (shvarFile *ifcfg, svGetValueBoolean (ifcfg, "POWERSAVE", FALSE) ? 1 : 0, NULL); + value = svGetValueFull (ifcfg, "MAC_ADDRESS_RANDOMIZATION", FALSE); + if (value) { + if (strcmp (value, "default") == 0) + mac_randomization = NM_SETTING_MAC_RANDOMIZATION_DEFAULT; + else if (strcmp (value, "never") == 0) + mac_randomization = NM_SETTING_MAC_RANDOMIZATION_NEVER; + else if (strcmp (value, "always") == 0) + mac_randomization = NM_SETTING_MAC_RANDOMIZATION_ALWAYS; + else { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid MAC_ADDRESS_RANDOMIZATION value '%s'", value); + goto error; + } + } else + mac_randomization = NM_SETTING_MAC_RANDOMIZATION_NEVER; + + g_object_set (s_wireless, + NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, + mac_randomization, + NULL); + return NM_SETTING (s_wireless); error: diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am index 6d1d21b444..a1b414fd6c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am @@ -67,6 +67,10 @@ EXTRA_DIST = \ ifcfg-test-wifi-band-a \ ifcfg-test-wifi-band-a-channel-mismatch \ ifcfg-test-wifi-band-bg-channel-mismatch \ + ifcfg-test-wifi-mac-random-always \ + ifcfg-test-wifi-mac-random-never \ + ifcfg-test-wifi-mac-random-default \ + ifcfg-test-wifi-mac-random-missing \ test_ca_cert.pem \ test1_key_and_cert.pem \ ifcfg-test-ibft \ diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-always b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-always new file mode 100644 index 0000000000..9dcb5bf851 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-always @@ -0,0 +1,7 @@ +TYPE=Wireless +DEVICE=eth2 +BOOTPROTO=dhcp +ESSID=blahblah +ONBOOT=yes +MAC_ADDRESS_RANDOMIZATION=always + diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-default b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-default new file mode 100644 index 0000000000..3709c493c4 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-default @@ -0,0 +1,6 @@ +TYPE=Wireless +DEVICE=eth2 +BOOTPROTO=dhcp +ESSID=blahblah +ONBOOT=yes +MAC_ADDRESS_RANDOMIZATION=default diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-missing b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-missing new file mode 100644 index 0000000000..f896eb0f99 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-missing @@ -0,0 +1,6 @@ +TYPE=Wireless +DEVICE=eth2 +BOOTPROTO=dhcp +ESSID=blahblah +ONBOOT=yes + diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-never b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-never new file mode 100644 index 0000000000..aa12d74938 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-never @@ -0,0 +1,6 @@ +TYPE=Wireless +DEVICE=eth2 +BOOTPROTO=dhcp +ESSID=blahblah +ONBOOT=yes +MAC_ADDRESS_RANDOMIZATION=never 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 2b317e8ee2..b7a887d095 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -58,6 +58,12 @@ #include "nm-test-utils.h" +typedef struct { + const char *name; + const NMSettingMacRandomization value; + const char *write_expected; +} WifiMacRandomData; + #if 0 static void connection_diff (NMConnection *a, NMConnection *b) @@ -5465,6 +5471,117 @@ test_write_wifi_hidden (void) g_object_unref (reread); } +static void +test_read_wifi_mac_random (gconstpointer user_data) +{ + const WifiMacRandomData *test_data = user_data; + NMConnection *connection; + NMSettingWireless *s_wifi; + gboolean success; + GError *error = NULL; + char *path; + + path = g_strdup_printf (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-mac-random-%s", test_data->name); + connection = connection_from_file_test (path, NULL, TYPE_WIRELESS, NULL, &error); + g_free (path); + g_assert_no_error (error); + g_assert (connection); + + success = nm_connection_verify (connection, &error); + g_assert_no_error (error); + g_assert (success); + + s_wifi = nm_connection_get_setting_wireless (connection); + g_assert (s_wifi); + g_assert_cmpint (nm_setting_wireless_get_mac_address_randomization (s_wifi), ==, test_data->value); + + g_object_unref (connection); +} + +static void +test_write_wifi_mac_random (gconstpointer user_data) +{ + const WifiMacRandomData *test_data = user_data; + NMConnection *connection, *reread; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + char *uuid, *testfile = NULL, *val; + gboolean success; + GError *error = NULL; + shvarFile *f; + GBytes *ssid; + const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 }; + + connection = nm_simple_connection_new (); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + val = g_strdup_printf ("Test Write WiFi MAC %s", test_data->name); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, val, + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + g_free (val); + + /* Wifi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_bytes_new (ssid_data, sizeof (ssid_data)); + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_MODE, "infrastructure", + NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, test_data->value, + NULL); + g_bytes_unref (ssid); + + success = nm_connection_verify (connection, &error); + g_assert_no_error (error); + g_assert (success); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + g_assert_no_error (error); + g_assert (success); + + f = svOpenFile (testfile, &error); + g_assert_no_error (error); + g_assert (f); + + /* re-read the file to check that what key was written. */ + val = svGetValue (f, "MAC_ADDRESS_RANDOMIZATION", FALSE); + g_assert_cmpstr (val, ==, test_data->write_expected); + g_free (val); + svCloseFile (f); + + /* reread will be normalized, so we must normalize connection too. */ + nm_connection_normalize (connection, NULL, NULL, NULL); + + /* re-read the connection for comparison */ + reread = connection_from_file_test (testfile, NULL, TYPE_WIRELESS, NULL, &error); + unlink (testfile); + g_assert_no_error (error); + g_assert (reread); + + success = nm_connection_verify (reread, &error); + g_assert_no_error (error); + g_assert (success); + + g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT)); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + static void test_write_wired_wake_on_lan (void) { @@ -13061,6 +13178,35 @@ int main (int argc, char **argv) g_test_add_func (TPATH "wifi/read-band-a-channel-mismatch", test_read_wifi_band_a_channel_mismatch); g_test_add_func (TPATH "wifi/read-band-bg-channel-mismatch", test_read_wifi_band_bg_channel_mismatch); g_test_add_func (TPATH "wifi/read-hidden", test_read_wifi_hidden); + + { + static const WifiMacRandomData test_wifi_mac_random[] = { + { "always", NM_SETTING_MAC_RANDOMIZATION_ALWAYS, "always" }, + { "never", NM_SETTING_MAC_RANDOMIZATION_NEVER, "never" }, + { "default", NM_SETTING_MAC_RANDOMIZATION_DEFAULT, "default" }, + { "missing", NM_SETTING_MAC_RANDOMIZATION_NEVER, "never" }, + }; + int i; + + for (i = 0; i < G_N_ELEMENTS (test_wifi_mac_random); i++) { + char *tpath; + + tpath = g_strdup_printf (TPATH "wifi/read-mac-random-%s", test_wifi_mac_random[i].name); + g_test_add_data_func_full (tpath, + g_memdup (&test_wifi_mac_random[i], sizeof (test_wifi_mac_random[i])), + test_read_wifi_mac_random, + g_free); + g_free (tpath); + + tpath = g_strdup_printf (TPATH "wifi/write-mac-random-%s", test_wifi_mac_random[i].name); + g_test_add_data_func_full (tpath, + g_memdup (&test_wifi_mac_random[i], sizeof (test_wifi_mac_random[i])), + test_write_wifi_mac_random, + g_free); + g_free (tpath); + } + } + test_read_wired_qeth_static (); test_read_wired_ctc_static (); test_read_wifi_wep_no_keys (); diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c index aaf0ebe906..1ea932ee23 100644 --- a/src/settings/plugins/ifcfg-rh/writer.c +++ b/src/settings/plugins/ifcfg-rh/writer.c @@ -967,7 +967,7 @@ write_wireless_setting (NMConnection *connection, tmp = g_strdup_printf ("KEY_PASSPHRASE%d", i + 1); set_secret (ifcfg, tmp, NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE); g_free (tmp); - + tmp = g_strdup_printf ("KEY%d", i + 1); set_secret (ifcfg, tmp, NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE, FALSE); g_free (tmp); @@ -989,6 +989,20 @@ write_wireless_setting (NMConnection *connection, svSetValue (ifcfg, "SSID_HIDDEN", nm_setting_wireless_get_hidden (s_wireless) ? "yes" : NULL, TRUE); svSetValue (ifcfg, "POWERSAVE", nm_setting_wireless_get_powersave (s_wireless) ? "yes" : NULL, TRUE); + svSetValue (ifcfg, "MAC_ADDRESS_RANDOMIZATION", NULL, TRUE); + switch (nm_setting_wireless_get_mac_address_randomization (s_wireless)) { + case NM_SETTING_MAC_RANDOMIZATION_DEFAULT: + svSetValue (ifcfg, "MAC_ADDRESS_RANDOMIZATION", "default", TRUE); + break; + case NM_SETTING_MAC_RANDOMIZATION_ALWAYS: + svSetValue (ifcfg, "MAC_ADDRESS_RANDOMIZATION", "always", TRUE); + break; + default: + case NM_SETTING_MAC_RANDOMIZATION_NEVER: + svSetValue (ifcfg, "MAC_ADDRESS_RANDOMIZATION", "never", TRUE); + break; + } + svSetValue (ifcfg, "TYPE", TYPE_WIRELESS, FALSE); return TRUE; From 4f6c91d6962cc031f07e52bb31adde560ad70fac Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 8 Oct 2015 13:08:59 +0200 Subject: [PATCH 7/8] wifi: enable mac-address-randomization by default for new connections But ensure that old keyfiles that did not yet understand the new key continue to have it disabled. --- libnm-core/nm-keyfile-reader.c | 9 +++++++-- libnm-core/nm-keyfile-writer.c | 13 ++++++++++--- src/supplicant-manager/nm-supplicant-config.c | 6 ++++-- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/libnm-core/nm-keyfile-reader.c b/libnm-core/nm-keyfile-reader.c index 43e2618435..6a0584a539 100644 --- a/libnm-core/nm-keyfile-reader.c +++ b/libnm-core/nm-keyfile-reader.c @@ -1279,8 +1279,13 @@ set_default_for_missing_key (NMSetting *setting, const char *property) { /* Set a value different from the default value of the property's spec */ - if (NM_IS_SETTING_VLAN (setting) && !strcmp (property, NM_SETTING_VLAN_FLAGS)) - g_object_set (setting, property, (NMVlanFlags) 0, NULL); + if (NM_IS_SETTING_VLAN (setting)) { + if (!strcmp (property, NM_SETTING_VLAN_FLAGS)) + g_object_set (setting, property, (NMVlanFlags) 0, NULL); + } else if (NM_IS_SETTING_WIRELESS (setting)) { + if (!strcmp (property, NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION)) + g_object_set (setting, property, (NMSettingMacRandomization) NM_SETTING_MAC_RANDOMIZATION_NEVER, NULL); + } } static void diff --git a/libnm-core/nm-keyfile-writer.c b/libnm-core/nm-keyfile-writer.c index 2369922309..ba1736b996 100644 --- a/libnm-core/nm-keyfile-writer.c +++ b/libnm-core/nm-keyfile-writer.c @@ -608,9 +608,16 @@ static KeyWriter key_writers[] = { static gboolean can_omit_default_value (NMSetting *setting, const char *property) { - if ( (NM_IS_SETTING_VLAN (setting) && !strcmp (property, NM_SETTING_VLAN_FLAGS)) - || (NM_IS_SETTING_IP6_CONFIG (setting) && !strcmp (property, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE))) - return FALSE; + if (NM_IS_SETTING_VLAN (setting)) { + if (!strcmp (property, NM_SETTING_VLAN_FLAGS)) + return FALSE; + } else if (NM_IS_SETTING_IP6_CONFIG (setting)) { + if (!strcmp (property, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE)) + return FALSE; + } else if (NM_IS_SETTING_WIRELESS (setting)) { + if (!strcmp (property, NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION)) + return FALSE; + } return TRUE; } diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c index 28047b62e8..521a26134e 100644 --- a/src/supplicant-manager/nm-supplicant-config.c +++ b/src/supplicant-manager/nm-supplicant-config.c @@ -465,8 +465,10 @@ nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self, 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; + /* use randomization if supported. */ + priv->mac_randomization = (mac_randomization_support == NM_SUPPLICANT_FEATURE_YES) + ? NM_SETTING_MAC_RANDOMIZATION_ALWAYS + : NM_SETTING_MAC_RANDOMIZATION_NEVER; } } From 3ac82f2c7501e06db9a3d0b12fbbe78f7450e0cd Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 22 Oct 2015 09:33:10 -0500 Subject: [PATCH 8/8] nmcli: add support for WiFi MAC address randomization property --- clients/cli/settings.c | 98 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 79 insertions(+), 19 deletions(-) diff --git a/clients/cli/settings.c b/clients/cli/settings.c index b07c563475..4e63e24e67 100644 --- a/clients/cli/settings.c +++ b/clients/cli/settings.c @@ -190,21 +190,22 @@ NmcOutputField nmc_fields_setting_8021X[] = { /* Available fields for NM_SETTING_WIRELESS_SETTING_NAME */ NmcOutputField nmc_fields_setting_wireless[] = { - SETTING_FIELD ("name"), /* 0 */ - SETTING_FIELD (NM_SETTING_WIRELESS_SSID), /* 1 */ - SETTING_FIELD (NM_SETTING_WIRELESS_MODE), /* 2 */ - SETTING_FIELD (NM_SETTING_WIRELESS_BAND), /* 3 */ - SETTING_FIELD (NM_SETTING_WIRELESS_CHANNEL), /* 4 */ - SETTING_FIELD (NM_SETTING_WIRELESS_BSSID), /* 5 */ - SETTING_FIELD (NM_SETTING_WIRELESS_RATE), /* 6 */ - SETTING_FIELD (NM_SETTING_WIRELESS_TX_POWER), /* 7 */ - SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS), /* 8 */ - SETTING_FIELD (NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS), /* 9 */ - SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST), /* 10 */ - SETTING_FIELD (NM_SETTING_WIRELESS_MTU), /* 11 */ - SETTING_FIELD (NM_SETTING_WIRELESS_SEEN_BSSIDS), /* 12 */ - SETTING_FIELD (NM_SETTING_WIRELESS_HIDDEN), /* 13 */ - SETTING_FIELD (NM_SETTING_WIRELESS_POWERSAVE), /* 14 */ + SETTING_FIELD ("name"), /* 0 */ + SETTING_FIELD (NM_SETTING_WIRELESS_SSID), /* 1 */ + SETTING_FIELD (NM_SETTING_WIRELESS_MODE), /* 2 */ + SETTING_FIELD (NM_SETTING_WIRELESS_BAND), /* 3 */ + SETTING_FIELD (NM_SETTING_WIRELESS_CHANNEL), /* 4 */ + SETTING_FIELD (NM_SETTING_WIRELESS_BSSID), /* 5 */ + SETTING_FIELD (NM_SETTING_WIRELESS_RATE), /* 6 */ + SETTING_FIELD (NM_SETTING_WIRELESS_TX_POWER), /* 7 */ + SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS), /* 8 */ + SETTING_FIELD (NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS), /* 9 */ + SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST), /* 10 */ + SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION), /* 11 */ + SETTING_FIELD (NM_SETTING_WIRELESS_MTU), /* 12 */ + SETTING_FIELD (NM_SETTING_WIRELESS_SEEN_BSSIDS), /* 13 */ + SETTING_FIELD (NM_SETTING_WIRELESS_HIDDEN), /* 14 */ + SETTING_FIELD (NM_SETTING_WIRELESS_POWERSAVE), /* 15 */ {NULL, NULL, 0, NULL, FALSE, FALSE, 0} }; #define NMC_FIELDS_SETTING_WIRELESS_ALL "name"","\ @@ -218,6 +219,7 @@ NmcOutputField nmc_fields_setting_wireless[] = { NM_SETTING_WIRELESS_MAC_ADDRESS","\ NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS","\ NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST","\ + NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION","\ NM_SETTING_WIRELESS_MTU","\ NM_SETTING_WIRELESS_SEEN_BSSIDS","\ NM_SETTING_WIRELESS_HIDDEN"," \ @@ -1681,6 +1683,23 @@ nmc_property_wireless_get_powersave (NMSetting *setting, NmcPropertyGetType get_ return g_strdup_printf (_("yes (%u)"), powersave); } +static char * +nmc_property_wireless_get_mac_address_randomization (NMSetting *setting, NmcPropertyGetType get_type) +{ + NMSettingWireless *s_wifi = NM_SETTING_WIRELESS (setting); + NMSettingMacRandomization randomization = nm_setting_wireless_get_mac_address_randomization (s_wifi); + + if (randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT) + return g_strdup (_("default")); + else if (randomization == NM_SETTING_MAC_RANDOMIZATION_NEVER) + return g_strdup (_("never")); + else if (randomization == NM_SETTING_MAC_RANDOMIZATION_ALWAYS) + return g_strdup_printf (_("always")); + else + return g_strdup_printf (_("unknown")); +} + + /* --- NM_SETTING_WIRELESS_SECURITY_SETTING_NAME property get functions --- */ DEFINE_GETTER (nmc_property_wifi_sec_get_key_mgmt, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT) DEFINE_GETTER (nmc_property_wifi_sec_get_wep_tx_keyidx, NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX) @@ -4626,6 +4645,39 @@ nmc_property_wireless_set_powersave (NMSetting *setting, const char *prop, const return TRUE; } +static gboolean +nmc_property_wireless_set_mac_address_randomization (NMSetting *setting, + const char *prop, + const char *val, + GError **error) +{ + NMSettingMacRandomization randomization; + gs_free char *err_token = NULL; + gboolean ret; + long int t; + + if (nmc_string_to_int_base (val, 0, TRUE, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT, + NM_SETTING_MAC_RANDOMIZATION_ALWAYS, + &t)) + randomization = (NMSettingMacRandomization) t; + else { + ret = nm_utils_enum_from_str (nm_setting_mac_randomization_get_type (), + val, + (int *) &randomization, + &err_token); + + if (!ret) { + g_set_error (error, 1, 0, _("invalid option '%s', use 'default', 'never' or 'always'"), + err_token); + return FALSE; + } + } + + g_object_set (setting, prop, (guint) randomization, NULL); + return TRUE; +} + /* --- NM_SETTING_WIRELESS_SECURITY_SETTING_NAME property setter functions --- */ /* 'key-mgmt' */ static const char *wifi_sec_valid_key_mgmts[] = { "none", "ieee8021x", "wpa-none", "wpa-psk", "wpa-eap", NULL }; @@ -6688,6 +6740,13 @@ nmc_properties_init (void) NULL, NULL, NULL); + nmc_add_prop_funcs (GLUE (WIRELESS, MAC_ADDRESS_RANDOMIZATION), + nmc_property_wireless_get_mac_address_randomization, + nmc_property_wireless_set_mac_address_randomization, + NULL, + NULL, + NULL, + NULL); /* Add editable properties for NM_SETTING_WIRELESS_SECURITY_SETTING_NAME */ nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, KEY_MGMT), @@ -7269,10 +7328,11 @@ setting_wireless_details (NMSetting *setting, NmCli *nmc, const char *one_prop, set_val_str (arr, 8, nmc_property_wireless_get_mac_address (setting, NMC_PROPERTY_GET_PRETTY)); set_val_str (arr, 9, nmc_property_wireless_get_cloned_mac_address (setting, NMC_PROPERTY_GET_PRETTY)); set_val_str (arr, 10, nmc_property_wireless_get_mac_address_blacklist (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 11, nmc_property_wireless_get_mtu (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 12, nmc_property_wireless_get_seen_bssids (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 13, nmc_property_wireless_get_hidden (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 14, nmc_property_wireless_get_powersave (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 11, nmc_property_wireless_get_mac_address_randomization (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 12, nmc_property_wireless_get_mtu (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 13, nmc_property_wireless_get_seen_bssids (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 14, nmc_property_wireless_get_hidden (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 15, nmc_property_wireless_get_powersave (setting, NMC_PROPERTY_GET_PRETTY)); g_ptr_array_add (nmc->output_data, arr); print_data (nmc); /* Print all data */