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 */ 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/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c index b6be7d0242..2a14829314 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,33 @@ 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 + **/ + /* ---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, "", "", + 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; 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 0eeb8459ce..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" @@ -628,7 +629,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; } } @@ -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); @@ -2213,13 +2217,24 @@ 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."); } + 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/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/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 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; diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c index 65d6e2df44..521a26134e 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,23 @@ 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) { + /* use randomization if supported. */ + priv->mac_randomization = (mac_randomization_support == NM_SUPPLICANT_FEATURE_YES) + ? NM_SETTING_MAC_RANDOMIZATION_ALWAYS + : 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 +842,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 38eaabcb43..8267fb98af 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -71,7 +71,8 @@ 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 */ + NMSupplicantFeature mac_randomization_support; gboolean fast_supported; guint32 max_scan_ssids; guint32 ready_count; @@ -461,7 +462,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 +470,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); @@ -480,8 +481,31 @@ 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) +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; NMSupplicantInterfacePrivate *priv; @@ -489,7 +513,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 +524,28 @@ 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 = AP_SUPPORT_YES; + priv->ap_support = NM_SUPPLICANT_FEATURE_YES; + + 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); @@ -714,7 +757,8 @@ 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 || + 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 +771,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); } } @@ -1113,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) { @@ -1139,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 @@ -1330,7 +1429,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..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 { - 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; - struct _NMSupplicantInterface { GObject parent; }; @@ -125,7 +119,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 +157,11 @@ 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); + +NMSupplicantFeature nm_supplicant_interface_get_mac_randomization_support (NMSupplicantInterface *self); #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; 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,