diff options
author | Thomas Haller <thaller@redhat.com> | 2016-06-20 12:28:04 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2016-06-30 08:29:56 +0200 |
commit | 767abfa69040c62ae1dc0989a77df8c5e0e489c1 (patch) | |
tree | 91209e506004192b863fe7afd0ed5b2845166e4a | |
parent | b7d76b2277113316879d9d2a9348dac5d2358f0c (diff) | |
download | NetworkManager-767abfa69040c62ae1dc0989a77df8c5e0e489c1.tar.gz |
wifi: implement MAC address randomization in NetworkManager instead of supplicant
'wireless.mac-address-randomization' broke 'wireless.cloned-mac-address',
because we would always set 'PreassocMacAddr=1'. The reason is that
supplicant would set 'wpa_s->mac_addr_changed' during scanning, and
later during association it would either set a random MAC address or
reset the permanent MAC address [1].
Anyway, 'wireless.mac-address-randomization' conflicts with
'wireless.cloned-mac-address'. Instead of letting supplicant set the
MAC address, manage the MAC addresses entirely from NetworkManager.
Supplicant should not touch it.
[1] https://w1.fi/cgit/hostap/tree/wpa_supplicant/wpa_supplicant.c?id=f885b8e97cf39b56fe7ca6577890f2d20df7ae08#n1663
-rw-r--r-- | man/NetworkManager.conf.xml | 4 | ||||
-rw-r--r-- | src/devices/nm-device.c | 67 | ||||
-rw-r--r-- | src/devices/wifi/nm-device-wifi.c | 63 | ||||
-rw-r--r-- | src/supplicant-manager/nm-supplicant-config.c | 47 | ||||
-rw-r--r-- | src/supplicant-manager/nm-supplicant-config.h | 4 | ||||
-rw-r--r-- | src/supplicant-manager/nm-supplicant-interface.c | 19 | ||||
-rw-r--r-- | src/supplicant-manager/nm-supplicant-interface.h | 2 | ||||
-rw-r--r-- | src/supplicant-manager/tests/test-supplicant-config.c | 8 |
8 files changed, 105 insertions, 109 deletions
diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml index e6050b8326..a766bf90f9 100644 --- a/man/NetworkManager.conf.xml +++ b/man/NetworkManager.conf.xml @@ -602,7 +602,9 @@ ipv6.ip6-privacy=0 </varlistentry> <varlistentry> <term><varname>wifi.mac-address-randomization</varname></term> - <listitem><para>If left unspecified, MAC address randomization is disabled.</para></listitem> + <listitem><para>If left unspecified, MAC address randomization is disabled. + This setting is deprecated for <literal>wifi.cloned-mac-address</literal>. + </para></listitem> </varlistentry> <varlistentry> <term><varname>wifi.powersave</varname></term> diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index ddf7933185..c448f04818 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -11009,6 +11009,7 @@ _set_state_full (NMDevice *self, if (nm_device_get_act_request (self)) nm_device_cleanup (self, reason, CLEANUP_TYPE_DECONFIGURE); nm_device_take_down (self, TRUE); + nm_device_hw_addr_reset (self); set_nm_ipv6ll (self, FALSE); restore_ip6_properties (self); } @@ -11409,9 +11410,13 @@ nm_device_update_hw_address (NMDevice *self) _LOGD (LOGD_HW | LOGD_DEVICE, "hw-addr: hardware address now %s", priv->hw_addr); _notify (self, PROP_HW_ADDRESS); - if (!priv->hw_addr_initial) { - /* when we get a hw_addr the first time, always update our inital - * hw-address as well. */ + if ( !priv->hw_addr_initial + || ( priv->hw_addr_type == HW_ADDR_TYPE_UNSET + && priv->state < NM_DEVICE_STATE_PREPARE + && !nm_device_is_activating (self))) { + /* when we get a hw_addr the first time or while the device + * is not activated (with no explict hw address set), always + * update our inital hw-address as well. */ nm_device_update_initial_hw_address (self); } } @@ -11433,10 +11438,14 @@ nm_device_update_initial_hw_address (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - priv->hw_addr_type = HW_ADDR_TYPE_UNSET; - if ( priv->hw_addr && !nm_streq0 (priv->hw_addr_initial, priv->hw_addr)) { + if ( priv->hw_addr_initial + && priv->hw_addr_type != HW_ADDR_TYPE_UNSET) { + /* once we have the initial hw address set, we only allow + * update if the currenty type is "unset". */ + return; + } g_free (priv->hw_addr_initial); priv->hw_addr_initial = g_strdup (priv->hw_addr); _LOGD (LOGD_DEVICE, "hw-addr: update initial MAC address %s", @@ -11515,11 +11524,26 @@ _get_cloned_mac_address_setting (NMDevice *self, NMConnection *connection, gbool a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, is_wifi ? "wifi.cloned-mac-address" : "ethernet.cloned-mac-address", self); - if ( !a - || ( !NM_CLONED_MAC_IS_SPECIAL (a) - && !nm_utils_hwaddr_valid (a, ETH_ALEN))) - addr = NM_CLONED_MAC_PERMANENT; - else + /* default is permanent. */ + addr = NM_CLONED_MAC_PERMANENT; + + if (!a) { + if (is_wifi) { + NMSettingMacRandomization v; + + /* for backward compatibility, read the deprecated wifi.mac-address-randomization setting. */ + a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "wifi." NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, + self); + v = _nm_utils_ascii_str_to_int64 (a, 10, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT, + NM_SETTING_MAC_RANDOMIZATION_ALWAYS, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT); + if (v == NM_SETTING_MAC_RANDOMIZATION_ALWAYS) + addr = NM_CLONED_MAC_RANDOM; + } + } else if ( NM_CLONED_MAC_IS_SPECIAL (a) + || nm_utils_hwaddr_valid (a, ETH_ALEN)) addr = *out_addr = g_steal_pointer (&a); } @@ -11547,6 +11571,7 @@ _hw_addr_set (NMDevice *self, const char *cur_addr; guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX]; guint hw_addr_len; + gboolean was_up; nm_assert (NM_IS_DEVICE (self)); nm_assert (addr); @@ -11571,8 +11596,11 @@ _hw_addr_set (NMDevice *self, _LOGT (LOGD_DEVICE, "set-hw-addr: setting MAC address to '%s'...", addr); - /* Can't change MAC address while device is up */ - nm_device_take_down (self, FALSE); + was_up = nm_device_is_up (self); + if (was_up) { + /* Can't change MAC address while device is up */ + nm_device_take_down (self, FALSE); + } success = nm_platform_link_set_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), addr_bytes, hw_addr_len); if (success) { @@ -11592,8 +11620,10 @@ _hw_addr_set (NMDevice *self, detail, addr); } - if (!nm_device_bring_up (self, TRUE, NULL)) - return FALSE; + if (was_up) { + if (!nm_device_bring_up (self, TRUE, NULL)) + return FALSE; + } return success; } @@ -11610,7 +11640,8 @@ nm_device_hw_addr_set (NMDevice *self, const char *addr) if (!addr) g_return_val_if_reached (FALSE); - /* this is called by NMDeviceVlan to take the MAC address from the parent. + /* this is called by NMDeviceVlan to take the MAC address from the parent + * and by NMDeviceWifi to set a random MAC address during scanning. * In this case, it's like setting it to PERMANENT. */ priv->hw_addr_type = HW_ADDR_TYPE_PERMANENT; @@ -11634,8 +11665,10 @@ nm_device_hw_addr_set_cloned (NMDevice *self, NMConnection *connection, gboolean addr = _get_cloned_mac_address_setting (self, connection, is_wifi, &hw_addr_tmp); - if (nm_streq (addr, NM_CLONED_MAC_PRESERVE)) - return TRUE; + if (nm_streq (addr, NM_CLONED_MAC_PRESERVE)) { + /* "preserve" means to reset the initial MAC address. */ + return nm_device_hw_addr_reset (self); + } if (nm_streq (addr, NM_CLONED_MAC_PERMANENT)) { addr = nm_device_get_permanent_hw_address (self, TRUE); diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 1437767127..39ca8c46be 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -62,6 +62,8 @@ _LOG_DECLARE_SELF(NMDeviceWifi); #define SCAN_INTERVAL_STEP 20 #define SCAN_INTERVAL_MAX 120 +#define SCAN_RAND_MAC_ADDRESS_EXPIRE_MIN 5 + #define WIRELESS_SECRETS_TRIES "wireless-secrets-tries" G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) @@ -119,6 +121,9 @@ struct _NMDeviceWifiPrivate { guint reacquire_iface_id; NMDeviceWifiCapabilities capabilities; + + gint32 hw_addr_scan_expire; + char *hw_addr_scan; }; static gboolean check_scanning_allowed (NMDeviceWifi *self); @@ -169,6 +174,8 @@ static void ap_add_remove (NMDeviceWifi *self, static void remove_supplicant_interface_error_handler (NMDeviceWifi *self); +static void _hw_addr_set_scanning (NMDeviceWifi *self); + /*****************************************************************/ static void @@ -482,7 +489,8 @@ deactivate (NMDevice *device) /* Clear any critical protocol notification in the Wi-Fi stack */ nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, ifindex, FALSE); - nm_device_hw_addr_reset (device); + g_clear_pointer (&priv->hw_addr_scan, g_free); + _hw_addr_set_scanning (self); /* Ensure we're in infrastructure mode after deactivation; some devices * (usually older ones) don't scan well in adhoc mode. @@ -1013,6 +1021,38 @@ impl_device_wifi_get_all_access_points (NMDeviceWifi *self, } static void +_hw_addr_set_scanning (NMDeviceWifi *self) +{ + NMDevice *device = (NMDevice *) self; + NMDeviceWifiPrivate *priv; + guint32 now; + + g_return_if_fail (NM_IS_DEVICE_WIFI (self)); + + if ( nm_device_is_activating (device) + || nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) + return; + + priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + now = nm_utils_get_monotonic_timestamp_s (); + if ( !priv->hw_addr_scan + || now >= priv->hw_addr_scan_expire) { + /* the random MAC address for scanning expires after a while. + * + * We don't bother with to update the MAC address exactly when + * it expires, instead on the next scan request, we will generate + * a new one.*/ + priv->hw_addr_scan_expire = now + (SCAN_RAND_MAC_ADDRESS_EXPIRE_MIN * 60); + + g_free (priv->hw_addr_scan); + priv->hw_addr_scan = nm_utils_hw_addr_gen_random_eth (); + } + + nm_device_hw_addr_set (device, priv->hw_addr_scan); +} + +static void request_scan_cb (NMDevice *device, GDBusMethodInvocation *context, NMAuthSubject *subject, @@ -1321,6 +1361,8 @@ request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options) _LOGD (LOGD_WIFI_SCAN, "no SSIDs to probe scan"); } + _hw_addr_set_scanning (self); + if (nm_supplicant_interface_request_scan (priv->sup_iface, ssids)) { /* success */ backoff = TRUE; @@ -2195,9 +2237,6 @@ 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 (priv->sup_iface, NULL); @@ -2212,20 +2251,9 @@ 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, - mac_randomization_support, - mac_randomization_fallback, error)) { g_prefix_error (error, "802-11-wireless: "); goto error; @@ -2314,6 +2342,9 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) return NM_ACT_STAGE_RETURN_FAILURE; } + /* forget the temporary MAC address used during scanning */ + g_clear_pointer (&priv->hw_addr_scan, g_free); + /* Set spoof MAC to the interface */ if (!nm_device_hw_addr_set_cloned (device, connection, TRUE)) return NM_ACT_STAGE_RETURN_FAILURE; @@ -2956,6 +2987,8 @@ finalize (GObject *object) g_hash_table_unref (priv->aps); + g_free (priv->hw_addr_scan); + G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object); } diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c index 5ce8bb3196..6283edd6ca 100644 --- a/src/supplicant-manager/nm-supplicant-config.c +++ b/src/supplicant-manager/nm-supplicant-config.c @@ -47,7 +47,6 @@ typedef struct GHashTable *config; GHashTable *blobs; guint32 ap_scan; - NMSettingMacRandomization mac_randomization; gboolean fast_required; gboolean dispose_has_run; } NMSupplicantConfigPrivate; @@ -85,7 +84,6 @@ 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; } @@ -272,32 +270,6 @@ nm_supplicant_config_get_ap_scan (NMSupplicantConfig * self) return NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->ap_scan; } -const char * -nm_supplicant_config_get_mac_randomization (NMSupplicantConfig *self) -{ - 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. - */ - - 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 nm_supplicant_config_fast_required (NMSupplicantConfig *self) { @@ -385,8 +357,6 @@ gboolean nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self, NMSettingWireless * setting, guint32 fixed_freq, - NMSupplicantFeature mac_randomization_support, - NMSettingMacRandomization mac_randomization_fallback, GError **error) { NMSupplicantConfigPrivate *priv; @@ -477,23 +447,6 @@ 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) { - /* Don't use randomization, unless explicitly enabled. - * Randomization can work badly with captive portals. */ - priv->mac_randomization = NM_SETTING_MAC_RANDOMIZATION_NEVER; - } - } - - if ( priv->mac_randomization != NM_SETTING_MAC_RANDOMIZATION_NEVER - && mac_randomization_support != NM_SUPPLICANT_FEATURE_YES) { - g_set_error (error, NM_SUPPLICANT_ERROR, NM_SUPPLICANT_ERROR_CONFIG, - "cannot enable mac-randomization due to missing supplicant support"); - return FALSE; - } - return TRUE; } diff --git a/src/supplicant-manager/nm-supplicant-config.h b/src/supplicant-manager/nm-supplicant-config.h index 921bc16cbc..32589930c7 100644 --- a/src/supplicant-manager/nm-supplicant-config.h +++ b/src/supplicant-manager/nm-supplicant-config.h @@ -54,8 +54,6 @@ NMSupplicantConfig *nm_supplicant_config_new (void); guint32 nm_supplicant_config_get_ap_scan (NMSupplicantConfig *self); -const char *nm_supplicant_config_get_mac_randomization (NMSupplicantConfig *self); - gboolean nm_supplicant_config_fast_required (NMSupplicantConfig *self); GVariant *nm_supplicant_config_to_variant (NMSupplicantConfig *self); @@ -65,8 +63,6 @@ GHashTable *nm_supplicant_config_get_blobs (NMSupplicantConfig *self); gboolean nm_supplicant_config_add_setting_wireless (NMSupplicantConfig *self, NMSettingWireless *setting, guint32 fixed_freq, - NMSupplicantFeature mac_randomization_support, - NMSettingMacRandomization mac_randomization_fallback, GError **error); gboolean nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self, diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index 59e0ef3905..626472d072 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -503,12 +503,6 @@ 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 set_preassoc_scan_mac_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) { @@ -563,7 +557,7 @@ iface_introspect_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data g_variant_new ("(ssv)", WPAS_DBUS_IFACE_INTERFACE, "PreassocMacAddr", - g_variant_new_string ("1")), + g_variant_new_string ("0")), G_DBUS_CALL_FLAGS_NONE, -1, priv->init_cancellable, @@ -1223,9 +1217,7 @@ set_mac_randomization_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user return; } - _LOGI ("config: set MAC randomization to %s", - nm_supplicant_config_get_mac_randomization (priv->cfg)); - + _LOGT ("config: set MAC randomization to 0"); add_network (self); } @@ -1256,23 +1248,20 @@ set_ap_scan_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) nm_supplicant_config_get_ap_scan (priv->cfg)); 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_variant_new_string ("0")), G_DBUS_CALL_FLAGS_NONE, -1, priv->assoc_cancellable, (GAsyncReadyCallback) set_mac_randomization_cb, self); - } else { + } else add_network (self); - } } gboolean diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h index dbe77b1c1b..d514c53bc9 100644 --- a/src/supplicant-manager/nm-supplicant-interface.h +++ b/src/supplicant-manager/nm-supplicant-interface.h @@ -165,6 +165,4 @@ 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 */ diff --git a/src/supplicant-manager/tests/test-supplicant-config.c b/src/supplicant-manager/tests/test-supplicant-config.c index 0e53080273..e8f8444863 100644 --- a/src/supplicant-manager/tests/test-supplicant-config.c +++ b/src/supplicant-manager/tests/test-supplicant-config.c @@ -160,8 +160,6 @@ test_wifi_open (void) g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, 0, - NM_SUPPLICANT_FEATURE_UNKNOWN, - NM_SETTING_MAC_RANDOMIZATION_DEFAULT, &error)); g_assert_no_error (error); g_test_assert_expected_messages (); @@ -265,8 +263,6 @@ test_wifi_wep_key (const char *detail, g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, 0, - NM_SUPPLICANT_FEATURE_UNKNOWN, - NM_SETTING_MAC_RANDOMIZATION_DEFAULT, &error)); g_assert_no_error (error); g_test_assert_expected_messages (); @@ -410,8 +406,6 @@ test_wifi_wpa_psk (const char *detail, g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, 0, - NM_SUPPLICANT_FEATURE_UNKNOWN, - NM_SETTING_MAC_RANDOMIZATION_DEFAULT, &error)); g_assert_no_error (error); g_test_assert_expected_messages (); @@ -557,8 +551,6 @@ test_wifi_eap (void) g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, 0, - NM_SUPPLICANT_FEATURE_UNKNOWN, - NM_SETTING_MAC_RANDOMIZATION_DEFAULT, &error)); g_assert_no_error (error); g_test_assert_expected_messages (); |