diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2018-01-08 13:37:24 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2018-09-22 10:52:15 +0200 |
commit | fdacaa50c8261b0a62deeff05fed2365bc2389f0 (patch) | |
tree | cc776ed2dd8ab78d935788d96b3a3f64f99adf27 | |
parent | 301331c30ac3f970b49b1aba5fd17c7769bc63ae (diff) | |
download | ModemManager-fdacaa50c8261b0a62deeff05fed2365bc2389f0.tar.gz |
helpers: allow 19-digit reported ICCIDs
The mm_3gpp_parse_iccid() method does validation of the ICCID string
and was originally implemented to handle +CRSM reported values. The
implementation was looking for 20-digit strings, even for 19-digit
ICCIDs (those finished with a trailing 'F').
We now extend the logic to also validate ICCID strings reported as
19-digit values directly, and when that happens we won't allow
swapping of the digits (a +CRSM specific requirement) or trailing 'F'
characters (as that is only required when reporting 19-digit ICCIDs
with 20-digit strings).
This change allows us to e.g. use the u-blox specific AT+CCID command
and validate the returned ICCID with the same helper method, which
currently fails:
(ttyACM2): --> 'AT+CCID<CR>'
(ttyACM2): <-- '<CR><LF>+CCID: 8934077700015848638<CR><LF><CR><LF>OK<CR><LF>'
couldn't load SIM identifier: 'Invalid ICCID response size (was 19, expected 20)'
(cherry picked from commit 02821232878d2a12bf248b7f2594c48076593810)
-rw-r--r-- | src/mm-modem-helpers.c | 25 | ||||
-rw-r--r-- | src/tests/test-modem-helpers.c | 15 |
2 files changed, 32 insertions, 8 deletions
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index c25867120..7e91f4749 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -3514,10 +3514,10 @@ mm_3gpp_parse_iccid (const char *raw_iccid, GError **error) goto error; } - /* BCD encoded ICCIDs are 20 digits long */ - if (len != 20) { + /* ICCIDs are 19 or 20 digits long */ + if (len < 19 || len > 20) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Invalid ICCID response size (was %zd, expected 20)", + "Invalid ICCID response size (was %zd, expected 19 or 20)", len); goto error; } @@ -3526,9 +3526,16 @@ mm_3gpp_parse_iccid (const char *raw_iccid, GError **error) * should be '89' for telecommunication purposes according to ISO/IEC 7812. */ if (buf[0] == '8' && buf[1] == '9') { - swap = FALSE; + swap = FALSE; } else if (buf[0] == '9' && buf[1] == '8') { - swap = TRUE; + /* swapped digits are only expected in raw +CRSM responses, which must all + * be 20-bytes long */ + if (len != 20) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Invalid ICCID response size while swap needed (expected 20)"); + goto error; + } + swap = TRUE; } else { /* FIXME: Instead of erroring out, revisit this solution if we find any SIM * that doesn't use '89' as the major industry identifier of the ICCID. @@ -3539,9 +3546,10 @@ mm_3gpp_parse_iccid (const char *raw_iccid, GError **error) } /* Ensure if there's an 'F' that it's second-to-last if swap = TRUE, - * otherwise last if swap = FALSE */ + * otherwise last if swap = FALSE. Also fail if an F is found within a + * 19-digit reported ICCID. */ if (f_pos >= 0) { - if ((swap && (f_pos != len - 2)) || (!swap && (f_pos != len - 1))) { + if ((len != 20) || (swap && (f_pos != len - 2)) || (!swap && (f_pos != len - 1))) { g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Invalid ICCID length (unexpected F position)"); goto error; @@ -3554,7 +3562,8 @@ mm_3gpp_parse_iccid (const char *raw_iccid, GError **error) * * 21436587 -> 12345678 */ - swapped = g_malloc0 (25); + g_assert (len == 20); + swapped = g_malloc0 (21); for (i = 0; i < 10; i++) { swapped[i * 2] = buf[(i * 2) + 1]; swapped[(i * 2) + 1] = buf[i * 2]; diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c index 4a044c681..839240512 100644 --- a/src/tests/test-modem-helpers.c +++ b/src/tests/test-modem-helpers.c @@ -2091,6 +2091,20 @@ test_iccid_parse_unquoted_unswapped_19_digit (void *f, gpointer d) } static void +test_iccid_parse_unquoted_unswapped_19_digit_no_f (void *f, gpointer d) +{ + const char *raw_iccid = "8944200053671052499"; + const char *expected = "8944200053671052499"; + char *parsed; + GError *error = NULL; + + parsed = mm_3gpp_parse_iccid (raw_iccid, &error); + g_assert_no_error (error); + g_assert_cmpstr (parsed, ==, expected); + g_free (parsed); +} + +static void test_iccid_parse_quoted_unswapped_20_digit (void *f, gpointer d) { const char *raw_iccid = "\"89324102234690160476\""; @@ -3924,6 +3938,7 @@ int main (int argc, char **argv) g_test_suite_add (suite, TESTCASE (test_iccid_parse_quoted_swap_19_digit, NULL)); g_test_suite_add (suite, TESTCASE (test_iccid_parse_unquoted_swap_20_digit, NULL)); g_test_suite_add (suite, TESTCASE (test_iccid_parse_unquoted_unswapped_19_digit, NULL)); + g_test_suite_add (suite, TESTCASE (test_iccid_parse_unquoted_unswapped_19_digit_no_f, NULL)); g_test_suite_add (suite, TESTCASE (test_iccid_parse_quoted_unswapped_20_digit, NULL)); g_test_suite_add (suite, TESTCASE (test_iccid_parse_short, NULL)); g_test_suite_add (suite, TESTCASE (test_iccid_parse_invalid_chars, NULL)); |