mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-08 16:10:36 +01:00
wifi: fix connection to hidden SSID networks (rh #1069844)
When the PendingActivation removal changes landed, it required all connections to be in a device's AvailableConnections property. Of course since hidden networks don't broadcast the SSID, there's no way to match them up with connections and put them into the AvailableConnections property, so this was just plain broken.
This commit is contained in:
commit
da0ccf892b
9 changed files with 208 additions and 11 deletions
|
|
@ -1050,9 +1050,10 @@ check_connection_compatible (NMDevice *device,
|
|||
|
||||
|
||||
static gboolean
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
const char *specific_object)
|
||||
_internal_check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
const char *specific_object,
|
||||
gboolean ignore_ap_list)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
|
||||
NMSettingWireless *s_wifi;
|
||||
|
|
@ -1077,7 +1078,7 @@ check_connection_available (NMDevice *device,
|
|||
return TRUE;
|
||||
|
||||
/* Hidden SSIDs obviously don't always appear in the scan list either */
|
||||
if (nm_setting_wireless_get_hidden (s_wifi))
|
||||
if (nm_setting_wireless_get_hidden (s_wifi) || ignore_ap_list)
|
||||
return TRUE;
|
||||
|
||||
/* check if its visible */
|
||||
|
|
@ -1089,6 +1090,24 @@ check_connection_available (NMDevice *device,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
const char *specific_object)
|
||||
{
|
||||
return _internal_check_connection_available (device, connection, specific_object, FALSE);
|
||||
}
|
||||
|
||||
/* FIXME: remove this function when we require the 'hidden' property to be
|
||||
* set before a hidden connection can be activated.
|
||||
*/
|
||||
static gboolean
|
||||
check_connection_available_wifi_hidden (NMDevice *device,
|
||||
NMConnection *connection)
|
||||
{
|
||||
return _internal_check_connection_available (device, connection, NULL, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* List of manufacturer default SSIDs that are often unchanged by users.
|
||||
*
|
||||
|
|
@ -1142,6 +1161,7 @@ complete_connection (NMDevice *device,
|
|||
NMAccessPoint *ap = NULL;
|
||||
const GByteArray *ssid = NULL;
|
||||
GSList *iter;
|
||||
gboolean hidden = FALSE;
|
||||
|
||||
s_wifi = nm_connection_get_setting_wireless (connection);
|
||||
s_wsec = nm_connection_get_setting_wireless_security (connection);
|
||||
|
|
@ -1191,6 +1211,8 @@ complete_connection (NMDevice *device,
|
|||
g_slist_free (settings);
|
||||
if (!valid)
|
||||
return FALSE;
|
||||
|
||||
hidden = TRUE;
|
||||
}
|
||||
} else {
|
||||
ap = get_ap_by_path (self, specific_object);
|
||||
|
|
@ -1268,6 +1290,9 @@ complete_connection (NMDevice *device,
|
|||
g_free (str_ssid);
|
||||
g_free (format);
|
||||
|
||||
if (hidden)
|
||||
g_object_set (s_wifi, NM_SETTING_WIRELESS_HIDDEN, TRUE, NULL);
|
||||
|
||||
setting_mac = nm_setting_wireless_get_mac_address (s_wifi);
|
||||
if (setting_mac) {
|
||||
/* Make sure the setting MAC (if any) matches the device's permanent MAC */
|
||||
|
|
@ -3623,6 +3648,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
|
|||
parent_class->is_available = is_available;
|
||||
parent_class->check_connection_compatible = check_connection_compatible;
|
||||
parent_class->check_connection_available = check_connection_available;
|
||||
parent_class->check_connection_available_wifi_hidden = check_connection_available_wifi_hidden;
|
||||
parent_class->complete_connection = complete_connection;
|
||||
parent_class->set_enabled = set_enabled;
|
||||
|
||||
|
|
|
|||
|
|
@ -1643,7 +1643,7 @@ can_auto_connect (NMDevice *device,
|
|||
if (!nm_setting_connection_get_autoconnect (s_con))
|
||||
return FALSE;
|
||||
|
||||
return nm_device_connection_is_available (device, connection);
|
||||
return nm_device_connection_is_available (device, connection, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -7046,10 +7046,26 @@ nm_device_get_autoconnect (NMDevice *device)
|
|||
return NM_DEVICE_GET_PRIVATE (device)->autoconnect;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_connection_is_available():
|
||||
* @device: the #NMDevice
|
||||
* @connection: the #NMConnection to check for availability
|
||||
* @allow_device_override: set to %TRUE to let the device do specific checks
|
||||
*
|
||||
* Check if @connection is available to be activated on @device. Normally this
|
||||
* only checks if the connection is in @device's AvailableConnections property.
|
||||
* If @allow_device_override is %TRUE then the device is asked to do specific
|
||||
* checks that may bypass the AvailableConnections property.
|
||||
*
|
||||
* Returns: %TRUE if @connection can be activated on @device
|
||||
*/
|
||||
gboolean
|
||||
nm_device_connection_is_available (NMDevice *device, NMConnection *connection)
|
||||
nm_device_connection_is_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
gboolean allow_device_override)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
|
||||
gboolean available = FALSE;
|
||||
|
||||
if (priv->default_unmanaged && (priv->state == NM_DEVICE_STATE_UNMANAGED)) {
|
||||
/* default-unmanaged devices in UNMANAGED state have no available connections
|
||||
|
|
@ -7060,7 +7076,18 @@ nm_device_connection_is_available (NMDevice *device, NMConnection *connection)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
return !!g_hash_table_lookup (priv->available_connections, connection);
|
||||
available = !!g_hash_table_lookup (priv->available_connections, connection);
|
||||
if (!available && allow_device_override) {
|
||||
/* FIXME: hack for hidden WiFi becuase clients didn't consistently
|
||||
* set the 'hidden' property to indicate hidden SSID networks. If
|
||||
* activating but the network isn't available let the device recheck
|
||||
* availability.
|
||||
*/
|
||||
if (NM_DEVICE_GET_CLASS (device)->check_connection_available_wifi_hidden)
|
||||
available = NM_DEVICE_GET_CLASS (device)->check_connection_available_wifi_hidden (device, connection);
|
||||
}
|
||||
|
||||
return available;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -153,6 +153,14 @@ typedef struct {
|
|||
NMConnection *connection,
|
||||
const char *specific_object);
|
||||
|
||||
/* Same as check_connection_available() but called if the connection
|
||||
* is not present in the activating-connections array during activation,
|
||||
* to give the device a chance to allow/deny the activation. This is a
|
||||
* hack only meant for hidden WiFi networks.
|
||||
*/
|
||||
gboolean (* check_connection_available_wifi_hidden) (NMDevice *self,
|
||||
NMConnection *connection);
|
||||
|
||||
gboolean (* complete_connection) (NMDevice *self,
|
||||
NMConnection *connection,
|
||||
const char *specific_object,
|
||||
|
|
@ -331,7 +339,9 @@ const char *nm_device_get_physical_port_id (NMDevice *device);
|
|||
|
||||
guint32 nm_device_get_mtu (NMDevice *device);
|
||||
|
||||
gboolean nm_device_connection_is_available (NMDevice *device, NMConnection *connection);
|
||||
gboolean nm_device_connection_is_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
gboolean allow_device_override);
|
||||
|
||||
gboolean nm_device_notify_component_added (NMDevice *device, GObject *component);
|
||||
|
||||
|
|
|
|||
|
|
@ -2501,7 +2501,7 @@ ensure_master_active_connection (NMManager *self,
|
|||
if (!is_compatible_with_slave (candidate, connection))
|
||||
continue;
|
||||
|
||||
if (nm_device_connection_is_available (master_device, candidate)) {
|
||||
if (nm_device_connection_is_available (master_device, candidate, TRUE)) {
|
||||
master_ac = nm_manager_activate_connection (self,
|
||||
candidate,
|
||||
NULL,
|
||||
|
|
@ -2542,7 +2542,7 @@ ensure_master_active_connection (NMManager *self,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!nm_device_connection_is_available (candidate, master_connection))
|
||||
if (!nm_device_connection_is_available (candidate, master_connection, TRUE))
|
||||
continue;
|
||||
|
||||
found_device = TRUE;
|
||||
|
|
@ -2658,7 +2658,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
|
|||
}
|
||||
|
||||
/* Final connection must be available on device */
|
||||
if (!nm_device_connection_is_available (device, connection)) {
|
||||
if (!nm_device_connection_is_available (device, connection, TRUE)) {
|
||||
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
|
||||
"Connection '%s' is not available on the device %s at this time.",
|
||||
nm_connection_get_id (connection), nm_device_get_iface (device));
|
||||
|
|
|
|||
|
|
@ -3650,6 +3650,11 @@ make_wireless_setting (shvarFile *ifcfg,
|
|||
g_free (value);
|
||||
}
|
||||
|
||||
g_object_set (s_wireless,
|
||||
NM_SETTING_WIRELESS_HIDDEN,
|
||||
svTrueValue (ifcfg, "SSID_HIDDEN", FALSE),
|
||||
NULL);
|
||||
|
||||
return NM_SETTING (s_wireless);
|
||||
|
||||
error:
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ EXTRA_DIST = \
|
|||
keys-test-wifi-wpa-eap-tls \
|
||||
ifcfg-test-wifi-wpa-eap-ttls-tls \
|
||||
keys-test-wifi-wpa-eap-ttls-tls \
|
||||
ifcfg-test-wifi-hidden \
|
||||
test_ca_cert.pem \
|
||||
test1_key_and_cert.pem \
|
||||
ifcfg-test-ibft-dhcp \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
|
||||
TYPE=Wireless
|
||||
DEVICE=eth2
|
||||
HWADDR=00:16:41:11:22:33
|
||||
BOOTPROTO=dhcp
|
||||
ONBOOT=yes
|
||||
ESSID=blahblah
|
||||
MODE=Managed
|
||||
SSID_HIDDEN=yes
|
||||
|
||||
|
|
@ -5760,6 +5760,120 @@ test_read_wifi_wep_eap_ttls_chap (void)
|
|||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_wifi_hidden (void)
|
||||
{
|
||||
NMConnection *connection;
|
||||
NMSettingConnection *s_con;
|
||||
NMSettingWireless *s_wifi;
|
||||
gboolean success;
|
||||
GError *error = NULL;
|
||||
|
||||
connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-hidden",
|
||||
NULL, TYPE_WIRELESS, NULL, NULL, NULL, NULL, NULL, &error, NULL);
|
||||
g_assert_no_error (error);
|
||||
g_assert (connection);
|
||||
|
||||
success = nm_connection_verify (connection, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (success);
|
||||
|
||||
s_con = nm_connection_get_setting_connection (connection);
|
||||
g_assert (s_con);
|
||||
g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRELESS_SETTING_NAME);
|
||||
|
||||
s_wifi = nm_connection_get_setting_wireless (connection);
|
||||
g_assert (s_wifi);
|
||||
g_assert (nm_setting_wireless_get_hidden (s_wifi) == TRUE);
|
||||
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write_wifi_hidden (void)
|
||||
{
|
||||
NMConnection *connection, *reread;
|
||||
NMSettingConnection *s_con;
|
||||
NMSettingWireless *s_wifi;
|
||||
char *uuid, *testfile = NULL, *val;
|
||||
gboolean success;
|
||||
GError *error = NULL;
|
||||
shvarFile *f;
|
||||
GByteArray *ssid;
|
||||
const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 };
|
||||
|
||||
connection = nm_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 ();
|
||||
g_object_set (s_con,
|
||||
NM_SETTING_CONNECTION_ID, "Test Write WiFi Hidden",
|
||||
NM_SETTING_CONNECTION_UUID, uuid,
|
||||
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
|
||||
NULL);
|
||||
g_free (uuid);
|
||||
|
||||
/* Wifi setting */
|
||||
s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
|
||||
nm_connection_add_setting (connection, NM_SETTING (s_wifi));
|
||||
|
||||
ssid = g_byte_array_sized_new (sizeof (ssid_data));
|
||||
g_byte_array_append (ssid, ssid_data, sizeof (ssid_data));
|
||||
|
||||
g_object_set (s_wifi,
|
||||
NM_SETTING_WIRELESS_SSID, ssid,
|
||||
NM_SETTING_WIRELESS_MODE, "infrastructure",
|
||||
NM_SETTING_WIRELESS_HIDDEN, TRUE,
|
||||
NULL);
|
||||
|
||||
g_byte_array_free (ssid, TRUE);
|
||||
|
||||
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);
|
||||
f = svNewFile (testfile);
|
||||
g_assert (f);
|
||||
|
||||
g_assert_no_error (error);
|
||||
g_assert (success);
|
||||
|
||||
/* re-read the file to check that what key was written. */
|
||||
val = svGetValue (f, "SSID_HIDDEN", FALSE);
|
||||
g_assert (val);
|
||||
g_assert_cmpstr (val, ==, "yes");
|
||||
g_free (val);
|
||||
svCloseFile (f);
|
||||
|
||||
/* reread will be normalized, so we must normalize connection too. */
|
||||
nm_utils_normalize_connection (connection, TRUE);
|
||||
|
||||
/* re-read the connection for comparison */
|
||||
reread = connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL,
|
||||
NULL, NULL, NULL, NULL, &error, NULL);
|
||||
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);
|
||||
}
|
||||
|
||||
#define TEST_IFCFG_WIRED_QETH_STATIC TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-qeth-static"
|
||||
|
||||
static void
|
||||
|
|
@ -13781,6 +13895,7 @@ int main (int argc, char **argv)
|
|||
test_read_wifi_wpa_eap_tls ();
|
||||
test_read_wifi_wpa_eap_ttls_tls ();
|
||||
test_read_wifi_wep_eap_ttls_chap ();
|
||||
g_test_add_func (TPATH "wifi/read-hidden", test_read_wifi_hidden);
|
||||
test_read_wired_qeth_static ();
|
||||
test_read_wired_ctc_static ();
|
||||
test_read_wifi_wep_no_keys ();
|
||||
|
|
@ -13857,6 +13972,7 @@ int main (int argc, char **argv)
|
|||
test_write_wifi_dynamic_wep_leap ();
|
||||
test_write_wifi_wpa_then_open ();
|
||||
test_write_wifi_wpa_then_wep_with_perms ();
|
||||
g_test_add_func (TPATH "wifi/write-hidden", test_write_wifi_hidden);
|
||||
test_write_wired_qeth_dhcp ();
|
||||
test_write_wired_ctc_dhcp ();
|
||||
test_write_permissions ();
|
||||
|
|
|
|||
|
|
@ -984,6 +984,8 @@ write_wireless_setting (NMConnection *connection,
|
|||
g_free (keys_path);
|
||||
}
|
||||
|
||||
svSetValue (ifcfg, "SSID_HIDDEN", nm_setting_wireless_get_hidden (s_wireless) ? "yes" : NULL, TRUE);
|
||||
|
||||
svSetValue (ifcfg, "TYPE", TYPE_WIRELESS, FALSE);
|
||||
|
||||
return TRUE;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue