sim: validate PIN and PUK codes

Validate PIN and PUK codes in the SIM D-Bus interface handlers to
ensure they are numeric. This prevents injecting AT command
delimiters (like CR) into these fields, which are later spliced
into AT commands (+CPWD, +CLCK, +CPIN).

Introduce a common helper mm_utils_is_numeric() to check if a string
contains only digits, and add unit tests for it.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1065

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
This commit is contained in:
Aleksander Morgado
2026-07-10 13:43:48 +02:00
committed by Aleksander Morgado
parent dd54145d71
commit 50202ad76a
4 changed files with 60 additions and 0 deletions
+28
View File
@@ -261,6 +261,13 @@ handle_change_pin_auth_ready (MMAuthProvider *authp,
return;
}
if (!mm_utils_is_numeric (ctx->old_pin) || !mm_utils_is_numeric (ctx->new_pin)) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
"PIN must be numeric");
handle_change_pin_context_free (ctx);
return;
}
/* If changing PIN is not implemented, report an error */
if (!MM_BASE_SIM_GET_CLASS (ctx->self)->change_pin ||
!MM_BASE_SIM_GET_CLASS (ctx->self)->change_pin_finish) {
@@ -445,6 +452,13 @@ handle_enable_pin_auth_ready (MMAuthProvider *authp,
return;
}
if (!mm_utils_is_numeric (ctx->pin)) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
"PIN must be numeric");
handle_enable_pin_context_free (ctx);
return;
}
/* If changing PIN is not implemented, report an error */
if (!MM_BASE_SIM_GET_CLASS (ctx->self)->enable_pin ||
!MM_BASE_SIM_GET_CLASS (ctx->self)->enable_pin_finish) {
@@ -869,6 +883,13 @@ handle_send_pin_auth_ready (MMAuthProvider *authp,
return;
}
if (!mm_utils_is_numeric (ctx->pin)) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
"PIN must be numeric");
handle_send_pin_context_free (ctx);
return;
}
if (!mm_gdbus_sim_get_active (MM_GDBUS_SIM (ctx->self))) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Cannot send PIN: SIM not currently active");
@@ -974,6 +995,13 @@ handle_send_puk_auth_ready (MMAuthProvider *authp,
return;
}
if (!mm_utils_is_numeric (ctx->puk) || !mm_utils_is_numeric (ctx->new_pin)) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
"PIN/PUK must be numeric");
handle_send_puk_context_free (ctx);
return;
}
if (!mm_gdbus_sim_get_active (MM_GDBUS_SIM (ctx->self))) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Cannot send PUK: SIM not currently active");
+15
View File
@@ -5977,3 +5977,18 @@ mm_utils_is_valid_fqdn (const gchar *fqdn)
}
return TRUE;
}
gboolean
mm_utils_is_numeric (const gchar *str)
{
const gchar *c;
if (!str || !str[0])
return FALSE;
for (c = str; *c; c++) {
if (!g_ascii_isdigit (*c))
return FALSE;
}
return TRUE;
}
+1
View File
@@ -573,6 +573,7 @@ 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_validate_cbs_channels (GArray *channels,
GError **error);
+16
View File
@@ -4908,6 +4908,21 @@ test_is_valid_fqdn (void *f, gpointer d)
g_assert (!mm_utils_is_valid_fqdn ("host/com"));
}
static void
test_is_numeric (void *f, gpointer d)
{
g_assert (mm_utils_is_numeric ("123456"));
g_assert (mm_utils_is_numeric ("0"));
g_assert (mm_utils_is_numeric ("0123456789"));
g_assert (!mm_utils_is_numeric (NULL));
g_assert (!mm_utils_is_numeric (""));
g_assert (!mm_utils_is_numeric ("123a45"));
g_assert (!mm_utils_is_numeric ("123 45"));
g_assert (!mm_utils_is_numeric ("123\r45"));
g_assert (!mm_utils_is_numeric ("+123"));
}
/*****************************************************************************/
typedef struct {
@@ -5456,6 +5471,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_is_numeric, NULL));
g_test_suite_add (suite, TESTCASE (test_cpol_response, NULL));