diff options
author | Andrew Zaborowski <andrew.zaborowski@intel.com> | 2020-10-23 20:13:01 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-11-12 15:35:56 +0100 |
commit | 96424ca35cbc4735f3b6470dea599e6fff2aca27 (patch) | |
tree | c42bee2a7d993763630454908de125ada2182943 | |
parent | c83472a269038bb6ce44b780f5152f9910111dd4 (diff) | |
download | NetworkManager-96424ca35cbc4735f3b6470dea599e6fff2aca27.tar.gz |
iwd: Validate UTF-8 SSID early in check_connection_compatible/complete_connection
IWD only supports UTF-8 SSIDs internally, any BSS who's SSID doesn't
validate as UTF-8 is ignored. There's also no way to ask IWD to connect
to such network/start AP/Adhoc etc. because SSIDs are passed as D-Bus
strings. So validate that connection SSIDs are UTF-8 early in
check_connection_compatible/complete_connection and refactor
check_connection slightly to avoid duplication.
Since NMWifiAPs are created by us, we already know those have valid
SSIDs so once we've also checked new NMConnections in
check_connection_compatible there should be no possibility that an SSID
anywhere else in the code is not UTF8. We should be able to treat the
GBytes values as UTF8 without redundant validation or the complex
locale-dependent conversions in _nm_utils_ssid_to_utf8.
-rw-r--r-- | src/devices/wifi/nm-device-iwd.c | 76 |
1 files changed, 46 insertions, 30 deletions
diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c index 50dd892427..4fe8ea57bb 100644 --- a/src/devices/wifi/nm-device-iwd.c +++ b/src/devices/wifi/nm-device-iwd.c @@ -656,6 +656,9 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * const char * mode; NMIwdNetworkSecurity security; gboolean mapped; + GBytes * ssid; + const guint8 * ssid_bytes; + gsize ssid_len; if (!NM_DEVICE_CLASS(nm_device_iwd_parent_class) ->check_connection_compatible(device, connection, error)) @@ -663,6 +666,23 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * s_wireless = nm_connection_get_setting_wireless(connection); + /* complete_connection would be called (if at all) before this function + * so an SSID should always be set. IWD doesn't support non-UTF8 SSIDs + * (ignores BSSes with such SSIDs and has no way to represent them on + * DBus) so we can cut it short for connections with a non-UTF8 SSID. + */ + ssid = nm_setting_wireless_get_ssid(s_wireless); + if (!ssid) + return FALSE; + + ssid_bytes = g_bytes_get_data(ssid, &ssid_len); + if (!g_utf8_validate((const char *) ssid_bytes, ssid_len, NULL)) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, + "non-UTF-8 connection SSID not supported by IWD backend"); + return FALSE; + } + perm_hw_addr = nm_device_get_permanent_hw_address(device); mac = nm_setting_wireless_get_mac_address(s_wireless); if (perm_hw_addr) { @@ -862,20 +882,18 @@ complete_connection(NMDevice * device, NMSettingWireless * s_wifi; gs_free char * ssid_utf8 = NULL; NMWifiAP * ap; - GBytes * ssid; - GBytes * setting_ssid = NULL; - gboolean hidden = FALSE; + GBytes * ssid = NULL; + gboolean hidden = FALSE; const char * mode; s_wifi = nm_connection_get_setting_wireless(connection); mode = s_wifi ? nm_setting_wireless_get_mode(s_wifi) : NULL; - if (nm_streq0(mode, NM_SETTING_WIRELESS_MODE_AP)) { - if (!nm_setting_verify(NM_SETTING(s_wifi), connection, error)) - return FALSE; - ap = NULL; - } else if (!specific_object) { + if (nm_streq0(mode, NM_SETTING_WIRELESS_MODE_AP) || !specific_object) { + const guint8 *ssid_bytes; + gsize ssid_len; + /* If not given a specific object, we need at minimum an SSID */ if (!s_wifi) { g_set_error_literal(error, @@ -885,16 +903,24 @@ complete_connection(NMDevice * device, return FALSE; } - setting_ssid = nm_setting_wireless_get_ssid(s_wifi); - if (!setting_ssid || g_bytes_get_size(setting_ssid) == 0) { - g_set_error_literal( - error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "A 'wireless' setting with a valid SSID is required if no AP path was given."); + ssid = nm_setting_wireless_get_ssid(s_wifi); + ssid_bytes = g_bytes_get_data(ssid, &ssid_len); + + if (!ssid || ssid_len == 0 || !g_utf8_validate((const char *) ssid_bytes, ssid_len, NULL)) { + g_set_error_literal(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "A 'wireless' setting with a valid UTF-8 SSID is required if no AP " + "path was given."); return FALSE; } + } + if (nm_streq0(mode, NM_SETTING_WIRELESS_MODE_AP)) { + if (!nm_setting_verify(NM_SETTING(s_wifi), connection, error)) + return FALSE; + ap = NULL; + } else if (!specific_object) { /* Find a compatible AP in the scan list */ ap = nm_wifi_aps_find_first_compatible(&priv->aps_lst_head, connection); if (!ap) { @@ -923,24 +949,14 @@ complete_connection(NMDevice * device, specific_object); return FALSE; } - } - - /* Add a wifi setting if one doesn't exist yet */ - if (!s_wifi) { - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - } - ssid = nm_setting_wireless_get_ssid(s_wifi); - if (!ssid && ap) ssid = nm_wifi_ap_get_ssid(ap); - if (!ssid) { - g_set_error_literal(error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "A 'wireless' setting with a valid SSID is required."); - return FALSE; + /* Add a wifi setting if one doesn't exist yet */ + if (!s_wifi) { + s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); + nm_connection_add_setting(connection, NM_SETTING(s_wifi)); + } } if (ap) { |