wifi: don't limit active scans for SSIDs to 5

As far as NMSupplicantInterface is concerned, don't clamp the
max-scan-ssids to 5. We should track the real value that wpa_supplicant
announces, and it's up to the caller to provide fewer SSIDs.

In particular, we want to limit the number of hidden SSIDs that we
accept from connection profiles, but we don't want to limit the number
of active scans via `nmcli device wifi rescan ssid $SSID [...]`.

(cherry picked from commit c9ae23af5e)
This commit is contained in:
Thomas Haller 2020-04-29 10:50:13 +02:00
parent 7500e90b53
commit e00475ac8f
2 changed files with 55 additions and 27 deletions

View file

@ -1533,7 +1533,9 @@ _scan_request_ssids_build_hidden (NMDeviceWifi *self,
gs_free NMSettingsConnection **connections = NULL;
gs_unref_ptrarray GPtrArray *ssids = NULL;
gs_unref_hashtable GHashTable *unique_ssids = NULL;
guint i, len;
guint connections_len;
guint n_hidden;
guint i;
NM_SET_OUT (out_has_hidden_profiles, FALSE);
@ -1558,7 +1560,7 @@ _scan_request_ssids_build_hidden (NMDeviceWifi *self,
}
connections = nm_settings_get_connections_clone (nm_device_get_settings ((NMDevice *) self),
&len,
&connections_len,
hidden_filter_func,
NULL,
NULL,
@ -1579,28 +1581,36 @@ _scan_request_ssids_build_hidden (NMDeviceWifi *self,
}
g_qsort_with_data (connections,
len,
connections_len,
sizeof (NMSettingsConnection *),
nm_settings_connection_cmp_timestamp_p_with_data,
NULL);
for (i = 0; connections[i]; i++) {
n_hidden = 0;
for (i = 0; i < connections_len; i++) {
NMSettingWireless *s_wifi;
GBytes *ssid;
if (ssids->len >= max_scan_ssids)
break;
if (n_hidden > 4) {
/* we allow at most 4 hidden profiles to be actively scanned. The
* reason is speed and to not disclose too many SSIDs. */
break;
}
s_wifi = nm_connection_get_setting_wireless (nm_settings_connection_get_connection (connections[i]));
ssid = nm_setting_wireless_get_ssid (s_wifi);
if (!g_hash_table_add (unique_ssids, ssid))
continue;
NM_SET_OUT (out_has_hidden_profiles, TRUE);
g_ptr_array_add (ssids, g_bytes_ref (ssid));
n_hidden++;
}
NM_SET_OUT (out_has_hidden_profiles, n_hidden > 0);
return g_steal_pointer (&ssids);
}

View file

@ -154,6 +154,9 @@ typedef struct _NMSupplicantInterfacePrivate {
bool is_ready_main:1;
bool is_ready_p2p_device:1;
bool prop_scan_active:1;
bool prop_scan_ssid:1;
} NMSupplicantInterfacePrivate;
struct _NMSupplicantInterfaceClass {
@ -1167,10 +1170,11 @@ static void
parse_capabilities (NMSupplicantInterface *self, GVariant *capabilities)
{
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
gboolean have_active = FALSE;
gboolean have_ssid = FALSE;
const gboolean old_prop_scan_active = priv->prop_scan_active;
const gboolean old_prop_scan_ssid = priv->prop_scan_ssid;
const guint32 old_max_scan_ssids = priv->max_scan_ssids;
gboolean have_ft = FALSE;
gint32 max_scan_ssids = -1;
gint32 max_scan_ssids;
const char **array;
nm_assert (capabilities && g_variant_is_of_type (capabilities, G_VARIANT_TYPE_VARDICT));
@ -1195,28 +1199,37 @@ parse_capabilities (NMSupplicantInterface *self, GVariant *capabilities)
}
if (g_variant_lookup (capabilities, "Scan", "^a&s", &array)) {
if (g_strv_contains (array, "active"))
have_active = TRUE;
if (g_strv_contains (array, "ssid"))
have_ssid = TRUE;
const char **a;
priv->prop_scan_active = FALSE;
priv->prop_scan_ssid = FALSE;
for (a = array; *a; a++) {
if (nm_streq (*a, "active"))
priv->prop_scan_active = TRUE;
else if (nm_streq (*a, "ssid"))
priv->prop_scan_ssid = TRUE;
}
g_free (array);
}
if (g_variant_lookup (capabilities, "MaxScanSSID", "i", &max_scan_ssids)) {
/* We need active scan and SSID probe capabilities to care about MaxScanSSIDs */
if ( max_scan_ssids > 0
&& have_active
&& have_ssid) {
/* wpa_supplicant's NM_WPAS_MAX_SCAN_SSIDS value is 16, but for speed
* and to ensure we don't disclose too many SSIDs from the hidden
* list, we'll limit to 5.
*/
max_scan_ssids = CLAMP (max_scan_ssids, 0, 5);
if (max_scan_ssids != priv->max_scan_ssids) {
priv->max_scan_ssids = max_scan_ssids;
_LOGD ("supports %d scan SSIDs", priv->max_scan_ssids);
}
}
const gint32 WPAS_MAX_SCAN_SSIDS = 16;
/* Even if supplicant claims that 20 SSIDs are supported, the Scan request
* still only accepts WPAS_MAX_SCAN_SSIDS SSIDs. Otherwise the D-Bus
* request will be rejected with "fi.w1.wpa_supplicant1.InvalidArgs"
* Body: ('Did not receive correct message arguments.', 'Too many ssids specified. Specify at most four')
* */
priv->max_scan_ssids = CLAMP (max_scan_ssids, 0, WPAS_MAX_SCAN_SSIDS);
}
if ( old_max_scan_ssids != priv->max_scan_ssids
|| old_prop_scan_active != priv->prop_scan_active
|| old_prop_scan_ssid != priv->prop_scan_ssid) {
_LOGD ("supports %u scan SSIDs (scan: %cactive %cssid)",
(guint32) priv->max_scan_ssids,
priv->prop_scan_active ? '+' : '-',
priv->prop_scan_ssid ? '+' : '-');
}
}
@ -2514,9 +2527,14 @@ nm_supplicant_interface_get_ifname (NMSupplicantInterface *self)
guint
nm_supplicant_interface_get_max_scan_ssids (NMSupplicantInterface *self)
{
NMSupplicantInterfacePrivate *priv;
g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), 0);
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->max_scan_ssids;
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
return priv->prop_scan_active && priv->prop_scan_ssid
? priv->max_scan_ssids
: 0u;
}
/*****************************************************************************/