identification: Validate ASN.1 DN in from_data() constructor
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).
This commit is contained in:
@@ -62,6 +62,23 @@ START_TEST(test_from_data)
|
|||||||
ck_assert(chunk_equals(expected, encoding));
|
ck_assert(chunk_equals(expected, encoding));
|
||||||
a->destroy(a);
|
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("[email protected]");
|
||||||
|
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 */
|
/* everything else is handled by the string parser */
|
||||||
expected = chunk_from_str("[email protected]");
|
expected = chunk_from_str("[email protected]");
|
||||||
a = identification_create_from_data(expected);
|
a = identification_create_from_data(expected);
|
||||||
|
|||||||
@@ -867,6 +867,31 @@ static bool compare_dn(chunk_t t_dn, chunk_t o_dn, int *wc)
|
|||||||
return finished;
|
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,
|
METHOD(identification_t, equals_dn, bool,
|
||||||
private_identification_t *this, identification_t *other)
|
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];
|
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);
|
return identification_create_from_encoding(ID_DER_ASN1_DN, data);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user