From a39d46c63737ae26e531df0e47b687b4f62a4379 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Mon, 29 Jun 2026 16:54:27 +0000 Subject: [PATCH] location: validate SUPL host as FQDN or IP When parsing a SUPL address, if the host is not a valid IPv4 address, validate it as a FQDN (allowing only alphanumeric characters, dots, and hyphens). This prevents injecting AT command delimiters (like CR or semicolon) into the host string, which is later spliced into modem-specific AT commands (+XLCSSLP). Introduce a common helper mm_utils_is_valid_fqdn() to validate FQDNs, and add unit tests for it. https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1063 Signed-off-by: Aleksander Morgado --- src/mm-modem-helpers.c | 20 ++++++++++++++++++++ src/mm-modem-helpers.h | 1 + src/tests/test-modem-helpers.c | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index e243e6ea..bbb9606f 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -5554,6 +5554,11 @@ mm_parse_supl_address (const gchar *supl, /* Try to parse first item as IP */ if (inet_pton (AF_INET, split[0], &ip) <= 0) { /* Otherwise, assume it's a domain name */ + if (!mm_utils_is_valid_fqdn (split[0])) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, + "Invalid SUPL host: not a valid FQDN or IP: %s", split[0]); + goto out; + } if (out_fqdn) *out_fqdn = g_strdup (split[0]); if (out_ip) @@ -5957,3 +5962,18 @@ mm_utils_remove_control_characters (gchar *str) } *dst = '\0'; } + +gboolean +mm_utils_is_valid_fqdn (const gchar *fqdn) +{ + const gchar *c; + + if (!fqdn || !fqdn[0]) + return FALSE; + + for (c = fqdn; *c; c++) { + if (!g_ascii_isalnum (*c) && *c != '-' && *c != '.') + return FALSE; + } + return TRUE; +} diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index 46d3f695..bf102251 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h @@ -572,6 +572,7 @@ gboolean mm_parse_supl_address (const gchar *supl, GError **error); void mm_utils_remove_control_characters (gchar *str); +gboolean mm_utils_is_valid_fqdn (const gchar *fqdn); gboolean mm_validate_cbs_channels (GArray *channels, GError **error); diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c index ec820802..03785791 100644 --- a/src/tests/test-modem-helpers.c +++ b/src/tests/test-modem-helpers.c @@ -4891,6 +4891,23 @@ test_remove_control_characters (void *f, gpointer d) mm_utils_remove_control_characters (NULL); } +static void +test_is_valid_fqdn (void *f, gpointer d) +{ + g_assert (mm_utils_is_valid_fqdn ("google.com")); + g_assert (mm_utils_is_valid_fqdn ("a.b.c.d")); + g_assert (mm_utils_is_valid_fqdn ("valid-host.com")); + g_assert (mm_utils_is_valid_fqdn ("123.com")); + g_assert (mm_utils_is_valid_fqdn ("a")); + + g_assert (!mm_utils_is_valid_fqdn (NULL)); + g_assert (!mm_utils_is_valid_fqdn ("")); + g_assert (!mm_utils_is_valid_fqdn ("invalid host.com")); + g_assert (!mm_utils_is_valid_fqdn ("host;com")); + g_assert (!mm_utils_is_valid_fqdn ("host\rcom")); + g_assert (!mm_utils_is_valid_fqdn ("host/com")); +} + /*****************************************************************************/ typedef struct { @@ -5438,6 +5455,7 @@ int main (int argc, char **argv) g_test_suite_add (suite, TESTCASE (test_at_quote_string, NULL)); g_test_suite_add (suite, TESTCASE (test_remove_control_characters, NULL)); + g_test_suite_add (suite, TESTCASE (test_is_valid_fqdn, NULL)); g_test_suite_add (suite, TESTCASE (test_cpol_response, NULL));