voice: validate outgoing and deflect call numbers
Validate the number parameter in Voice.CreateCall and Call.Deflect D-Bus methods to ensure they do not contain control characters or semicolons. This prevents AT command injection when the number is later spliced into ATD or +CTFR commands. Introduce a common helper mm_utils_is_valid_dial_number() to validate dial numbers, and add unit tests for it. https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1067 Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
This commit is contained in:
committed by
Aleksander Morgado
parent
3291e7dd1c
commit
6b3682ed65
@@ -440,6 +440,13 @@ handle_deflect_auth_ready (MMAuthProvider *authp,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Validate input number */
|
||||
if (!mm_utils_is_valid_dial_number (ctx->number, &error)) {
|
||||
mm_dbus_method_invocation_take_error (ctx->invocation, error);
|
||||
handle_deflect_context_free (ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
state = mm_gdbus_call_get_state (MM_GDBUS_CALL (ctx->self));
|
||||
|
||||
/* We can only deflect incoming call in ringing or waiting state */
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "mm-call-list.h"
|
||||
#include "mm-error-helpers.h"
|
||||
#include "mm-log-object.h"
|
||||
#include "mm-modem-helpers.h"
|
||||
|
||||
#define CALL_LIST_POLLING_CONTEXT_TAG "voice-call-list-polling-context-tag"
|
||||
#define IN_CALL_EVENT_CONTEXT_TAG "voice-in-call-event-context-tag"
|
||||
@@ -176,14 +177,9 @@ create_outgoing_call_from_properties (MMIfaceModemVoice *self,
|
||||
guint dtmf_tone_duration;
|
||||
|
||||
/* Don't create CALL from properties if either number is missing */
|
||||
number = mm_call_properties_get_number (properties) ;
|
||||
if (!number) {
|
||||
g_set_error (error,
|
||||
MM_CORE_ERROR,
|
||||
MM_CORE_ERROR_INVALID_ARGS,
|
||||
"Cannot create call: mandatory parameter 'number' is missing");
|
||||
number = mm_call_properties_get_number (properties);
|
||||
if (!mm_utils_is_valid_dial_number (number, error))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dtmf_tone_duration = mm_call_properties_get_dtmf_tone_duration (properties) ;
|
||||
|
||||
|
||||
@@ -5992,3 +5992,25 @@ mm_utils_is_numeric (const gchar *str)
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mm_utils_is_valid_dial_number (const gchar *str,
|
||||
GError **error)
|
||||
{
|
||||
const gchar *c;
|
||||
|
||||
if (!str || !str[0]) {
|
||||
g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
|
||||
"missing number");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (c = str; *c; c++) {
|
||||
if (((guint8)*c) < 0x20 || *c == ';') {
|
||||
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
|
||||
"invalid character '0x%02x' in number", (guint8)*c);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -574,6 +574,8 @@ gboolean mm_parse_supl_address (const gchar *supl,
|
||||
void mm_utils_remove_control_characters (gchar *str);
|
||||
gboolean mm_utils_is_valid_fqdn (const gchar *fqdn);
|
||||
gboolean mm_utils_is_numeric (const gchar *str);
|
||||
gboolean mm_utils_is_valid_dial_number (const gchar *str,
|
||||
GError **error);
|
||||
|
||||
gboolean mm_validate_cbs_channels (GArray *channels,
|
||||
GError **error);
|
||||
|
||||
@@ -4923,6 +4923,63 @@ test_is_numeric (void *f, gpointer d)
|
||||
g_assert (!mm_utils_is_numeric ("+123"));
|
||||
}
|
||||
|
||||
static void
|
||||
test_is_valid_dial_number (void *f, gpointer d)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gboolean r;
|
||||
|
||||
r = mm_utils_is_valid_dial_number ("123456", &error);
|
||||
g_assert (r);
|
||||
g_assert_no_error (error);
|
||||
|
||||
r = mm_utils_is_valid_dial_number ("+123456", &error);
|
||||
g_assert (r);
|
||||
g_assert_no_error (error);
|
||||
|
||||
r = mm_utils_is_valid_dial_number ("*123#", &error);
|
||||
g_assert (r);
|
||||
g_assert_no_error (error);
|
||||
|
||||
r = mm_utils_is_valid_dial_number ("123,456", &error);
|
||||
g_assert (r);
|
||||
g_assert_no_error (error);
|
||||
|
||||
r = mm_utils_is_valid_dial_number ("123W456", &error);
|
||||
g_assert (r);
|
||||
g_assert_no_error (error);
|
||||
|
||||
r = mm_utils_is_valid_dial_number (NULL, &error);
|
||||
g_assert (!r);
|
||||
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS);
|
||||
g_clear_error (&error);
|
||||
|
||||
r = mm_utils_is_valid_dial_number ("", &error);
|
||||
g_assert (!r);
|
||||
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS);
|
||||
g_clear_error (&error);
|
||||
|
||||
r = mm_utils_is_valid_dial_number ("123;456", &error);
|
||||
g_assert (!r);
|
||||
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS);
|
||||
g_clear_error (&error);
|
||||
|
||||
r = mm_utils_is_valid_dial_number ("123\r456", &error);
|
||||
g_assert (!r);
|
||||
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS);
|
||||
g_clear_error (&error);
|
||||
|
||||
r = mm_utils_is_valid_dial_number ("123\n456", &error);
|
||||
g_assert (!r);
|
||||
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS);
|
||||
g_clear_error (&error);
|
||||
|
||||
r = mm_utils_is_valid_dial_number ("123\x01" "456", &error);
|
||||
g_assert (!r);
|
||||
g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
@@ -5472,6 +5529,7 @@ int main (int argc, char **argv)
|
||||
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_is_numeric, NULL));
|
||||
g_test_suite_add (suite, TESTCASE (test_is_valid_dial_number, NULL));
|
||||
|
||||
g_test_suite_add (suite, TESTCASE (test_cpol_response, NULL));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user