]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
identification: Validate ASN.1 DN in from_data() constructor
authorTobias Brunner <tobias@strongswan.org>
Mon, 2 Nov 2020 14:09:13 +0000 (15:09 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 3 Dec 2020 07:23:54 +0000 (08:23 +0100)
The DN is otherwise not parsed until compared/printed.  This avoids
false detections as ASN.1 DN if e.g. an email address starts with "0",
which is 0x30 = ASN.1 sequence tag, and the next character denotes
the exact length of the rest of the string (see the unit tests for an
example).

src/libstrongswan/tests/suites/test_identification.c
src/libstrongswan/utils/identification.c

index 8560f9ea7c7b979be357d4187da8c28ee8f2ccb4..e47c0cb5f9a6b23453205591b365154520c63d5a 100644 (file)
@@ -62,6 +62,23 @@ START_TEST(test_from_data)
        ck_assert(chunk_equals(expected, encoding));
        a->destroy(a);
 
+       /* this is not actually ASN.1, even though it starts with 0x30 and the
+        * correct length (0x31=49) */
+       expected = chunk_from_str("01234567-aaaa-bbbb-cccc-ddddeeeeffff@strongswan.org");
+       a = identification_create_from_data(chunk_from_chars(
+                                                               0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
+                                                               0x2d,0x61,0x61,0x61,0x61,0x2d,0x62,0x62,
+                                                               0x62,0x62,0x2d,0x63,0x63,0x63,0x63,0x2d,
+                                                               0x64,0x64,0x64,0x64,0x65,0x65,0x65,0x65,
+                                                               0x66,0x66,0x66,0x66,0x40,0x73,0x74,0x72,
+                                                               0x6f,0x6e,0x67,0x73,0x77,0x61,0x6e,0x2e,
+                                                               0x6f,0x72,0x67));
+       ck_assert(ID_RFC822_ADDR == a->get_type(a));
+       encoding = a->get_encoding(a);
+       ck_assert(expected.ptr != encoding.ptr);
+       ck_assert(chunk_equals(expected, encoding));
+       a->destroy(a);
+
        /* everything else is handled by the string parser */
        expected = chunk_from_str("moon@strongswan.org");
        a = identification_create_from_data(expected);
index 3d803c04bb9261316520b693d1e577fb658bc0b2..eabf745844675a7cd5fd6399b2fc37fcda2f801a 100644 (file)
@@ -867,6 +867,31 @@ static bool compare_dn(chunk_t t_dn, chunk_t o_dn, int *wc)
        return finished;
 }
 
+/**
+ * Check if the data in the given chunk represents a valid DN.
+ */
+static bool is_valid_dn(chunk_t dn)
+{
+       enumerator_t *enumerator;
+       chunk_t oid, data;
+       u_char type;
+       bool finished = FALSE;
+
+       enumerator = create_rdn_enumerator(dn);
+       while (enumerator->enumerate(enumerator, &oid, &type, &data))
+       {
+               /* the enumerator returns FALSE on parse error, we are finished
+                * if we have reached the end of the DN only */
+               if ((data.ptr + data.len == dn.ptr + dn.len))
+               {
+                       finished = TRUE;
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       return finished;
+}
+
 METHOD(identification_t, equals_dn, bool,
        private_identification_t *this, identification_t *other)
 {
@@ -1713,7 +1738,7 @@ identification_t * identification_create_from_data(chunk_t data)
 {
        char buf[data.len + 1];
 
-       if (is_asn1(data))
+       if (is_asn1(data) && is_valid_dn(data))
        {
                return identification_create_from_encoding(ID_DER_ASN1_DN, data);
        }