858 lines
26 KiB
C
858 lines
26 KiB
C
/*
|
|
* Copyright (C) 2013 Tobias Brunner
|
|
* Copyright (C) 2009 Martin Willi
|
|
* Hochschule fuer Technik Rapperswil
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*/
|
|
|
|
#include "test_suite.h"
|
|
|
|
#include <utils/identification.h>
|
|
|
|
/*******************************************************************************
|
|
* create (_from_encoding, _from_data, _from_string, _from_sockaddr)
|
|
*/
|
|
|
|
START_TEST(test_from_encoding)
|
|
{
|
|
identification_t *a;
|
|
chunk_t expected, encoding;
|
|
|
|
/* only ID_ANY is handled differently, for all other types the following
|
|
* applies. should we perhaps test that this is in fact the case? */
|
|
expected = chunk_from_str("[email protected]");
|
|
a = identification_create_from_encoding(ID_RFC822_ADDR, expected);
|
|
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);
|
|
|
|
a = identification_create_from_encoding(ID_ANY, expected);
|
|
ck_assert(ID_ANY == a->get_type(a));
|
|
encoding = a->get_encoding(a);
|
|
ck_assert(encoding.ptr == NULL);
|
|
ck_assert(encoding.len == 0);
|
|
a->destroy(a);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_from_data)
|
|
{
|
|
identification_t *a;
|
|
chunk_t expected, encoding;
|
|
|
|
/* this uses the DN parser (C=CH) */
|
|
expected = chunk_from_chars(0x30, 0x0d, 0x31, 0x0b, 0x30, 0x09, 0x06,
|
|
0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48);
|
|
a = identification_create_from_data(expected);
|
|
ck_assert(ID_DER_ASN1_DN == 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("[email protected]");
|
|
a = identification_create_from_data(expected);
|
|
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);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_from_sockaddr)
|
|
{
|
|
identification_t *a;
|
|
chunk_t expected, encoding;
|
|
struct sockaddr_in in = {
|
|
.sin_family = AF_INET,
|
|
};
|
|
struct sockaddr_in6 in6 = {
|
|
.sin6_family = AF_INET6,
|
|
};
|
|
|
|
expected = chunk_from_chars(0xc0, 0xa8, 0x01, 0x01);
|
|
memcpy(&in.sin_addr, expected.ptr, sizeof(in.sin_addr));
|
|
a = identification_create_from_sockaddr((sockaddr_t*)&in);
|
|
ck_assert(ID_IPV4_ADDR == a->get_type(a));
|
|
encoding = a->get_encoding(a);
|
|
ck_assert(chunk_equals(expected, encoding));
|
|
a->destroy(a);
|
|
|
|
expected = chunk_from_chars(0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
|
|
memcpy(&in6.sin6_addr, expected.ptr, sizeof(in6.sin6_addr));
|
|
a = identification_create_from_sockaddr((sockaddr_t*)&in6);
|
|
ck_assert(ID_IPV6_ADDR == a->get_type(a));
|
|
encoding = a->get_encoding(a);
|
|
ck_assert(chunk_equals(expected, encoding));
|
|
a->destroy(a);
|
|
|
|
in6.sin6_family = AF_UNSPEC;
|
|
a = identification_create_from_sockaddr((sockaddr_t*)&in6);
|
|
ck_assert(ID_ANY == a->get_type(a));
|
|
a->destroy(a);
|
|
}
|
|
END_TEST
|
|
|
|
static struct {
|
|
char *id;
|
|
id_type_t type;
|
|
struct {
|
|
enum {
|
|
ENC_CHUNK,
|
|
ENC_STRING,
|
|
ENC_SIMPLE,
|
|
} type;
|
|
union {
|
|
chunk_t c;
|
|
char *s;
|
|
} data;
|
|
} result;
|
|
} string_data[] = {
|
|
{NULL, ID_ANY, { .type = ENC_CHUNK }},
|
|
{"", ID_ANY, { .type = ENC_CHUNK }},
|
|
{"%any", ID_ANY, { .type = ENC_CHUNK }},
|
|
{"%any6", ID_ANY, { .type = ENC_CHUNK }},
|
|
{"0.0.0.0", ID_ANY, { .type = ENC_CHUNK }},
|
|
{"0::0", ID_ANY, { .type = ENC_CHUNK }},
|
|
{"::", ID_ANY, { .type = ENC_CHUNK }},
|
|
{"*", ID_ANY, { .type = ENC_CHUNK }},
|
|
{"any", ID_FQDN, { .type = ENC_SIMPLE }},
|
|
{"any6", ID_FQDN, { .type = ENC_SIMPLE }},
|
|
{"0", ID_FQDN, { .type = ENC_SIMPLE }},
|
|
{"**", ID_FQDN, { .type = ENC_SIMPLE }},
|
|
{"192.168.1.1", ID_IPV4_ADDR, { .type = ENC_CHUNK,
|
|
.data.c = chunk_from_chars(0xc0, 0xa8, 0x01, 0x01) }},
|
|
{"192.168.",ID_FQDN, { .type = ENC_SIMPLE }},
|
|
{".", ID_FQDN, { .type = ENC_SIMPLE }},
|
|
{"fec0::1", ID_IPV6_ADDR, { .type = ENC_CHUNK,
|
|
.data.c = chunk_from_chars(0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01) }},
|
|
{"fec0::", ID_IPV6_ADDR, { .type = ENC_CHUNK,
|
|
.data.c = chunk_from_chars(0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) }},
|
|
{"fec0:", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
|
{":", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
|
{"[email protected]", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
|
|
{"alice@strongswan", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
|
|
{"alice@", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
|
|
{"alice", ID_FQDN, { .type = ENC_SIMPLE }},
|
|
{"@", ID_FQDN, { .type = ENC_CHUNK }},
|
|
{" @", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
|
|
{"@strongswan.org", ID_FQDN, { .type = ENC_STRING,
|
|
.data.s = "strongswan.org" }},
|
|
{"@#deadbeef", ID_KEY_ID, { .type = ENC_CHUNK,
|
|
.data.c = chunk_from_chars(0xde, 0xad, 0xbe, 0xef) }},
|
|
{"@#deadbee", ID_KEY_ID, { .type = ENC_CHUNK,
|
|
.data.c = chunk_from_chars(0x0d, 0xea, 0xdb, 0xee) }},
|
|
{"foo=bar", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
|
{"foo=", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
|
{"=bar", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
|
{"C=", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
|
|
.data.c = chunk_from_chars(0x30, 0x0b, 0x31, 0x09, 0x30, 0x07, 0x06,
|
|
0x03, 0x55, 0x04, 0x06, 0x13, 0x00)}},
|
|
{"C=CH", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
|
|
.data.c = chunk_from_chars(0x30, 0x0d, 0x31, 0x0b, 0x30, 0x09, 0x06,
|
|
0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48)}},
|
|
{"C=CH,", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
|
|
.data.c = chunk_from_chars(0x30, 0x0d, 0x31, 0x0b, 0x30, 0x09, 0x06,
|
|
0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48)}},
|
|
{"C=CH, ", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
|
|
.data.c = chunk_from_chars(0x30, 0x0d, 0x31, 0x0b, 0x30, 0x09, 0x06,
|
|
0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48)}},
|
|
{"C=CH, O", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
|
};
|
|
|
|
START_TEST(test_from_string)
|
|
{
|
|
identification_t *a;
|
|
chunk_t encoding, expected = chunk_empty;
|
|
char *id;
|
|
|
|
id = string_data[_i].id;
|
|
a = identification_create_from_string(id);
|
|
fail_unless(a->get_type(a) == string_data[_i].type,
|
|
"type of id '%s' is %N, %N expected", id,
|
|
id_type_names, a->get_type(a),
|
|
id_type_names, string_data[_i].type);
|
|
|
|
encoding = a->get_encoding(a);
|
|
switch (string_data[_i].result.type)
|
|
{
|
|
case ENC_SIMPLE:
|
|
expected = chunk_from_str(string_data[_i].id);
|
|
break;
|
|
case ENC_STRING:
|
|
expected = chunk_from_str(string_data[_i].result.data.s);
|
|
break;
|
|
case ENC_CHUNK:
|
|
expected = string_data[_i].result.data.c;
|
|
break;
|
|
default:
|
|
fail("unexpected result type");
|
|
}
|
|
|
|
ck_assert(!id || (char*)encoding.ptr != id);
|
|
if (expected.ptr)
|
|
{
|
|
fail_unless(chunk_equals(encoding, expected),
|
|
"parsing '%s' failed\nencoding %B\nexpected %B\n",
|
|
id, &encoding, &expected);
|
|
}
|
|
else
|
|
{
|
|
ck_assert(encoding.ptr == NULL);
|
|
ck_assert(encoding.len == 0);
|
|
}
|
|
a->destroy(a);
|
|
}
|
|
END_TEST
|
|
|
|
/*******************************************************************************
|
|
* printf_hook
|
|
*/
|
|
|
|
static void string_equals(char *a_str, char *b_str)
|
|
{
|
|
identification_t *b;
|
|
char buf[128];
|
|
|
|
b = b_str ? identification_create_from_string(b_str) : NULL;
|
|
snprintf(buf, sizeof(buf), "%Y", b);
|
|
DESTROY_IF(b);
|
|
ck_assert_str_eq(a_str, buf);
|
|
}
|
|
|
|
static void string_equals_id(char *a_str, identification_t *b)
|
|
{
|
|
char buf[128];
|
|
|
|
snprintf(buf, sizeof(buf), "%Y", b);
|
|
DESTROY_IF(b);
|
|
ck_assert_str_eq(a_str, buf);
|
|
}
|
|
|
|
START_TEST(test_printf_hook)
|
|
{
|
|
string_equals("(null)", NULL);
|
|
string_equals("%any", "");
|
|
string_equals("%any", "%any");
|
|
string_equals("%any", "*");
|
|
|
|
string_equals("192.168.1.1", "192.168.1.1");
|
|
string_equals_id("(invalid ID_IPV4_ADDR)",
|
|
identification_create_from_encoding(ID_IPV4_ADDR, chunk_empty));
|
|
string_equals("fec0::1", "fec0::1");
|
|
string_equals("fec0::1", "fec0:0:0::1");
|
|
string_equals_id("(invalid ID_IPV6_ADDR)",
|
|
identification_create_from_encoding(ID_IPV6_ADDR, chunk_empty));
|
|
|
|
string_equals_id("(unknown ID type: 255)",
|
|
identification_create_from_encoding(255, chunk_empty));
|
|
|
|
string_equals("[email protected]", "[email protected]");
|
|
string_equals("[email protected]", "[email protected]");
|
|
/* non-printable characters */
|
|
string_equals_id("[email protected]", identification_create_from_encoding(ID_RFC822_ADDR,
|
|
chunk_from_chars(0xfa, 0xfb, 0xfc, 0xfd, 0x40, 0x73, 0x74, 0x72,
|
|
0x6f, 0x6e, 0x67, 0x73, 0x77, 0x61, 0x6e, 0x2e,
|
|
0x6f, 0x72, 0x67)));
|
|
|
|
/* not a DN => ID_KEY_ID => no normalization */
|
|
string_equals("C=CH, AsdF=asdf", "C=CH, AsdF=asdf");
|
|
string_equals_id("[email protected]", identification_create_from_encoding(ID_KEY_ID,
|
|
chunk_from_str("[email protected]")));
|
|
/* non-printable characters */
|
|
string_equals_id("de:ad:be:ef", identification_create_from_encoding(ID_KEY_ID,
|
|
chunk_from_chars(0xde, 0xad, 0xbe, 0xef)));
|
|
/* printable characters */
|
|
string_equals_id("ABCDEFGHIJKLMNOPQRS",
|
|
identification_create_from_encoding(ID_KEY_ID,
|
|
chunk_from_chars(0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
|
0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
|
|
0x51, 0x52, 0x53)));
|
|
/* ABCDEFGHIJKLMNOPQRST is printable but has the length of a SHA1 hash */
|
|
string_equals_id("41:42:43:44:45:46:47:48:49:4a:4b:4c:4d:4e:4f:50:51:52:53:54",
|
|
identification_create_from_encoding(ID_KEY_ID,
|
|
chunk_from_chars(0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
|
0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
|
|
0x51, 0x52, 0x53, 0x54)));
|
|
|
|
string_equals_id("", identification_create_from_encoding(ID_DER_ASN1_DN, chunk_empty));
|
|
string_equals("C=", "C=");
|
|
string_equals("C=", "C=,");
|
|
string_equals("C=", "C=, ");
|
|
string_equals("C=", "C= , ");
|
|
string_equals("C=, O=strongSwan", "C=, O=strongSwan");
|
|
string_equals("C=CH, O=", "C=CH, O=");
|
|
string_equals("C=CH, O=strongSwan, CN=strongswan.org",
|
|
"C=CH, O=strongSwan, CN=strongswan.org");
|
|
string_equals("CN=strongswan.org, O=strongSwan, C=CH",
|
|
"cn=strongswan.org, o=strongSwan, c=CH");
|
|
string_equals("C=CH, O=strongSwan, CN=strongswan.org",
|
|
"C=CH,O=strongSwan,CN=strongswan.org");
|
|
string_equals("C=CH, O=strongSwan, CN=strongswan.org",
|
|
"/C=CH/O=strongSwan/CN=strongswan.org");
|
|
string_equals("CN=strongswan.org, O=strongSwan, C=CH",
|
|
"CN=strongswan.org,O=strongSwan,C=CH");
|
|
|
|
string_equals("C=CH, [email protected], CN=moon",
|
|
"C=CH, [email protected], CN=moon");
|
|
string_equals("C=CH, [email protected], CN=moon",
|
|
"C=CH, [email protected], CN=moon");
|
|
|
|
/* C=CH, pseudonym=ANO (pseudonym is currently not recognized) */
|
|
string_equals_id("C=CH, 55:04:41=ANO", identification_create_from_encoding(ID_DER_ASN1_DN,
|
|
chunk_from_chars(0x30, 0x19, 0x31, 0x17, 0x30, 0x09, 0x06, 0x03, 0x55,
|
|
0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x30, 0x0a, 0x06,
|
|
0x03, 0x55, 0x04, 0x41, 0x13, 0x03, 0x41, 0x4e, 0x4f)));
|
|
/* C=CH, O=strongSwan (but instead of a 2nd OID -0x06- we got NULL -0x05) */
|
|
string_equals_id("C=CH, (invalid ID_DER_ASN1_DN)", identification_create_from_encoding(ID_DER_ASN1_DN,
|
|
chunk_from_chars(0x30, 0x20, 0x31, 0x1e, 0x30, 0x09, 0x06, 0x03, 0x55,
|
|
0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x30, 0x11, 0x05,
|
|
0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x73, 0x74, 0x72,
|
|
0x6f, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x6e)));
|
|
/* [email protected] as GN */
|
|
string_equals_id("(ASN.1 general name)", identification_create_from_encoding(ID_DER_ASN1_GN,
|
|
chunk_from_chars(0x81, 0x14, 0x6d, 0x6f, 0x6f, 0x6e, 0x40, 0x73, 0x74,
|
|
0x72, 0x6f, 0x6e, 0x67, 0x73, 0x77, 0x61, 0x6e, 0x2e,
|
|
0x6f, 0x72, 0x67)));
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_printf_hook_width)
|
|
{
|
|
identification_t *a;
|
|
char buf[128];
|
|
|
|
a = identification_create_from_string("[email protected]");
|
|
snprintf(buf, sizeof(buf), "%25Y", a);
|
|
ck_assert_str_eq(" [email protected]", buf);
|
|
snprintf(buf, sizeof(buf), "%-*Y", 25, a);
|
|
ck_assert_str_eq("[email protected] ", buf);
|
|
snprintf(buf, sizeof(buf), "%5Y", a);
|
|
ck_assert_str_eq("[email protected]", buf);
|
|
DESTROY_IF(a);
|
|
}
|
|
END_TEST
|
|
|
|
/*******************************************************************************
|
|
* equals
|
|
*/
|
|
|
|
static bool id_equals(identification_t *a, char *b_str)
|
|
{
|
|
identification_t *b;
|
|
bool equals;
|
|
|
|
b = identification_create_from_string(b_str);
|
|
equals = a->equals(a, b);
|
|
ck_assert_int_eq(equals, b->equals(b, a));
|
|
b->destroy(b);
|
|
return equals;
|
|
}
|
|
|
|
START_TEST(test_equals)
|
|
{
|
|
identification_t *a;
|
|
chunk_t encoding, fuzzed;
|
|
int i;
|
|
|
|
/* this test also tests identification_create_from_string with DNs */
|
|
a = identification_create_from_string(
|
|
"C=CH, [email protected], CN=moon");
|
|
|
|
ck_assert(id_equals(a, "C=CH, [email protected], CN=moon"));
|
|
ck_assert(id_equals(a, "C==CH, [email protected],,, CN==moon"));
|
|
ck_assert(id_equals(a, " C=CH, [email protected], CN=moon "));
|
|
ck_assert(id_equals(a, "C=ch, [email protected], CN=Moon"));
|
|
ck_assert(id_equals(a, "/C=CH/[email protected]/CN=moon"));
|
|
ck_assert(id_equals(a, "C=CH/[email protected]/CN=moon"));
|
|
ck_assert(id_equals(a, "C=CH/[email protected],CN=moon"));
|
|
ck_assert(id_equals(a, "C=CH / [email protected] , CN=moon"));
|
|
|
|
ck_assert(!id_equals(a, "C=CH [email protected] CN=moon"));
|
|
ck_assert(!id_equals(a, "C=CN, [email protected], CN=moon"));
|
|
ck_assert(!id_equals(a, "[email protected], C=CH, CN=moon"));
|
|
ck_assert(!id_equals(a, "[email protected], C=CH, CN=moon"));
|
|
|
|
encoding = chunk_clone(a->get_encoding(a));
|
|
a->destroy(a);
|
|
|
|
/* simple fuzzing, increment each byte of encoding */
|
|
for (i = 0; i < encoding.len; i++)
|
|
{
|
|
if (i == 11 || i == 30 || i == 60)
|
|
{ /* skip ASN.1 type fields, as equals() handles them graceful */
|
|
continue;
|
|
}
|
|
fuzzed = chunk_clone(encoding);
|
|
fuzzed.ptr[i]++;
|
|
a = identification_create_from_encoding(ID_DER_ASN1_DN, fuzzed);
|
|
if (id_equals(a, "C=CH, [email protected], CN=moon"))
|
|
{
|
|
printf("%d %B\n%B\n", i, &fuzzed, &encoding);
|
|
}
|
|
ck_assert(!id_equals(a, "C=CH, [email protected], CN=moon"));
|
|
a->destroy(a);
|
|
free(fuzzed.ptr);
|
|
}
|
|
|
|
/* and decrement each byte of encoding */
|
|
for (i = 0; i < encoding.len; i++)
|
|
{
|
|
if (i == 11 || i == 30 || i == 60)
|
|
{
|
|
continue;
|
|
}
|
|
fuzzed = chunk_clone(encoding);
|
|
fuzzed.ptr[i]--;
|
|
a = identification_create_from_encoding(ID_DER_ASN1_DN, fuzzed);
|
|
ck_assert(!id_equals(a, "C=CH, [email protected], CN=moon"));
|
|
a->destroy(a);
|
|
free(fuzzed.ptr);
|
|
}
|
|
free(encoding.ptr);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_equals_any)
|
|
{
|
|
identification_t *a, *b;
|
|
|
|
a = identification_create_from_string("%any");
|
|
b = identification_create_from_encoding(ID_ANY, chunk_empty);
|
|
ck_assert(a->equals(a, b));
|
|
ck_assert(b->equals(b, a));
|
|
b->destroy(b);
|
|
|
|
b = identification_create_from_string("C=CH, O=strongSwan, CN=strongswan.org");
|
|
ck_assert(!a->equals(a, b));
|
|
ck_assert(!b->equals(b, a));
|
|
a->destroy(a);
|
|
b->destroy(b);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_equals_binary)
|
|
{
|
|
identification_t *a, *b;
|
|
chunk_t encoding;
|
|
|
|
encoding = chunk_from_str("foobar=");
|
|
/* strings containing = are parsed as KEY_ID if they aren't valid ASN.1 DNs */
|
|
a = identification_create_from_string("foobar=");
|
|
ck_assert(a->get_type(a) == ID_KEY_ID);
|
|
b = identification_create_from_encoding(ID_KEY_ID, encoding);
|
|
ck_assert(a->equals(a, b));
|
|
a->destroy(a);
|
|
b->destroy(b);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_equals_fqdn)
|
|
{
|
|
identification_t *a;
|
|
|
|
a = identification_create_from_string("ipsec.strongswan.org");
|
|
ck_assert(id_equals(a, "IPSEC.strongswan.org"));
|
|
ck_assert(id_equals(a, "ipsec.strongSwan.org"));
|
|
ck_assert(id_equals(a, "ipsec.strongSwan.ORG"));
|
|
ck_assert(!id_equals(a, "strongswan.org"));
|
|
a->destroy(a);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_equals_empty)
|
|
{
|
|
identification_t *a;
|
|
|
|
a = identification_create_from_encoding(_i, chunk_empty);
|
|
|
|
switch (_i)
|
|
{
|
|
case ID_ANY:
|
|
ck_assert(id_equals(a, "%any"));
|
|
break;
|
|
case ID_IPV4_ADDR:
|
|
ck_assert(!id_equals(a, "192.168.1.1"));
|
|
break;
|
|
case ID_FQDN:
|
|
ck_assert(!id_equals(a, "moon.strongswan.org"));
|
|
break;
|
|
case ID_USER_FQDN:
|
|
ck_assert(!id_equals(a, "[email protected]"));
|
|
break;
|
|
case ID_IPV6_ADDR:
|
|
ck_assert(!id_equals(a, "fec0::1"));
|
|
break;
|
|
case ID_DER_ASN1_DN:
|
|
ck_assert(!id_equals(a, "C=CH, [email protected], CN=moon"));
|
|
break;
|
|
case ID_KEY_ID:
|
|
ck_assert(!id_equals(a, "@#12345678"));
|
|
break;
|
|
case ID_DER_ASN1_GN:
|
|
case ID_IPV4_ADDR_SUBNET:
|
|
case ID_IPV6_ADDR_SUBNET:
|
|
case ID_IPV4_ADDR_RANGE:
|
|
case ID_IPV6_ADDR_RANGE:
|
|
/* currently not tested */
|
|
break;
|
|
}
|
|
|
|
a->destroy(a);
|
|
}
|
|
END_TEST
|
|
|
|
/*******************************************************************************
|
|
* matches
|
|
*/
|
|
|
|
static bool id_matches(identification_t *a, char *b_str, id_match_t expected)
|
|
{
|
|
identification_t *b;
|
|
id_match_t match;
|
|
|
|
b = identification_create_from_string(b_str);
|
|
match = a->matches(a, b);
|
|
b->destroy(b);
|
|
return match == expected;
|
|
}
|
|
|
|
START_TEST(test_matches)
|
|
{
|
|
identification_t *a;
|
|
|
|
a = identification_create_from_string("C=CH, [email protected], CN=moon");
|
|
|
|
ck_assert(id_matches(a, "C=CH, [email protected], CN=moon", ID_MATCH_PERFECT));
|
|
ck_assert(id_matches(a, "C=CH, E=*, CN=moon", ID_MATCH_ONE_WILDCARD));
|
|
ck_assert(id_matches(a, "C=CH, E=*, CN=*", ID_MATCH_ONE_WILDCARD - 1));
|
|
ck_assert(id_matches(a, "C=*, E=*, CN=*", ID_MATCH_ONE_WILDCARD - 2));
|
|
ck_assert(id_matches(a, "C=*, E=*, CN=*, O=BADInc", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "C=*, E=*", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "C=*, [email protected], CN=*", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
|
|
|
|
a->destroy(a);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_matches_any)
|
|
{
|
|
identification_t *a;
|
|
|
|
a = identification_create_from_string("%any");
|
|
|
|
ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
|
|
ck_assert(id_matches(a, "", ID_MATCH_ANY));
|
|
ck_assert(id_matches(a, "*", ID_MATCH_ANY));
|
|
ck_assert(id_matches(a, "[email protected]", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "vpn.strongswan.org", ID_MATCH_NONE));
|
|
a->destroy(a);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_matches_binary)
|
|
{
|
|
identification_t *a;
|
|
|
|
/* strings containing = are parsed as KEY_ID if they aren't valid ASN.1 DNs */
|
|
a = identification_create_from_string("foo=bar");
|
|
ck_assert(a->get_type(a) == ID_KEY_ID);
|
|
ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
|
|
ck_assert(id_matches(a, "foo=bar", ID_MATCH_PERFECT));
|
|
ck_assert(id_matches(a, "bar=foo", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "*=bar", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "foo=*", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "foo@bar", ID_MATCH_NONE));
|
|
a->destroy(a);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_matches_string)
|
|
{
|
|
identification_t *a;
|
|
|
|
a = identification_create_from_string("[email protected]");
|
|
|
|
ck_assert(id_matches(a, "[email protected]", ID_MATCH_PERFECT));
|
|
ck_assert(id_matches(a, "*@strongswan.org", ID_MATCH_ONE_WILDCARD));
|
|
ck_assert(id_matches(a, "*@*.org", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "*@*", ID_MATCH_NONE));
|
|
/* the following two are parsed as ID_FQDN, so no match */
|
|
ck_assert(id_matches(a, "*strongswan.org", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "*.org", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "moon@*", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "**", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "*", ID_MATCH_ANY));
|
|
ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
|
|
a->destroy(a);
|
|
|
|
a = identification_create_from_string("vpn.strongswan.org");
|
|
|
|
ck_assert(id_matches(a, "vpn.strongswan.org", ID_MATCH_PERFECT));
|
|
ck_assert(id_matches(a, "*.strongswan.org", ID_MATCH_ONE_WILDCARD));
|
|
ck_assert(id_matches(a, "*strongswan.org", ID_MATCH_ONE_WILDCARD));
|
|
ck_assert(id_matches(a, "*.org", ID_MATCH_ONE_WILDCARD));
|
|
ck_assert(id_matches(a, "*.strongswan.*", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "*vpn.strongswan.org", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "vpn.strongswan.*", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "**", ID_MATCH_NONE));
|
|
ck_assert(id_matches(a, "*", ID_MATCH_ANY));
|
|
ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
|
|
a->destroy(a);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_matches_empty)
|
|
{
|
|
identification_t *a;
|
|
|
|
a = identification_create_from_encoding(_i, chunk_empty);
|
|
|
|
switch (_i)
|
|
{
|
|
case ID_ANY:
|
|
ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
|
|
break;
|
|
case ID_IPV4_ADDR:
|
|
ck_assert(id_matches(a, "192.168.1.1", ID_MATCH_NONE));
|
|
break;
|
|
case ID_FQDN:
|
|
ck_assert(id_matches(a, "moon.strongswan.org", ID_MATCH_NONE));
|
|
break;
|
|
case ID_USER_FQDN:
|
|
ck_assert(id_matches(a, "[email protected]", ID_MATCH_NONE));
|
|
break;
|
|
case ID_IPV6_ADDR:
|
|
ck_assert(id_matches(a, "fec0::1", ID_MATCH_NONE));
|
|
break;
|
|
case ID_DER_ASN1_DN:
|
|
ck_assert(id_matches(a, "C=CH, [email protected], CN=moon",
|
|
ID_MATCH_NONE));
|
|
break;
|
|
case ID_KEY_ID:
|
|
ck_assert(id_matches(a, "@#12345678", ID_MATCH_NONE));
|
|
break;
|
|
case ID_DER_ASN1_GN:
|
|
case ID_IPV4_ADDR_SUBNET:
|
|
case ID_IPV6_ADDR_SUBNET:
|
|
case ID_IPV4_ADDR_RANGE:
|
|
case ID_IPV6_ADDR_RANGE:
|
|
/* currently not tested */
|
|
break;
|
|
}
|
|
|
|
a->destroy(a);
|
|
}
|
|
END_TEST
|
|
|
|
static bool id_matches_rev(identification_t *a, char *b_str, id_match_t expected)
|
|
{
|
|
identification_t *b;
|
|
id_match_t match;
|
|
|
|
b = identification_create_from_string(b_str);
|
|
match = b->matches(b, a);
|
|
b->destroy(b);
|
|
return match == expected;
|
|
}
|
|
|
|
START_TEST(test_matches_empty_reverse)
|
|
{
|
|
identification_t *a;
|
|
|
|
a = identification_create_from_encoding(_i, chunk_empty);
|
|
|
|
switch (_i)
|
|
{
|
|
case ID_ANY:
|
|
ck_assert(id_matches_rev(a, "%any", ID_MATCH_ANY));
|
|
break;
|
|
case ID_IPV4_ADDR:
|
|
ck_assert(id_matches_rev(a, "192.168.1.1", ID_MATCH_NONE));
|
|
break;
|
|
case ID_FQDN:
|
|
ck_assert(id_matches_rev(a, "moon.strongswan.org", ID_MATCH_NONE));
|
|
break;
|
|
case ID_USER_FQDN:
|
|
ck_assert(id_matches_rev(a, "[email protected]", ID_MATCH_NONE));
|
|
break;
|
|
case ID_IPV6_ADDR:
|
|
ck_assert(id_matches_rev(a, "fec0::1", ID_MATCH_NONE));
|
|
break;
|
|
case ID_DER_ASN1_DN:
|
|
ck_assert(id_matches_rev(a, "C=CH, [email protected], CN=moon",
|
|
ID_MATCH_NONE));
|
|
break;
|
|
case ID_KEY_ID:
|
|
ck_assert(id_matches_rev(a, "@#12345678", ID_MATCH_NONE));
|
|
break;
|
|
case ID_DER_ASN1_GN:
|
|
case ID_IPV4_ADDR_SUBNET:
|
|
case ID_IPV6_ADDR_SUBNET:
|
|
case ID_IPV4_ADDR_RANGE:
|
|
case ID_IPV6_ADDR_RANGE:
|
|
/* currently not tested */
|
|
break;
|
|
}
|
|
|
|
a->destroy(a);
|
|
}
|
|
END_TEST
|
|
|
|
/*******************************************************************************
|
|
* identification part enumeration
|
|
*/
|
|
|
|
START_TEST(test_parts)
|
|
{
|
|
identification_t *id;
|
|
enumerator_t *enumerator;
|
|
id_part_t part;
|
|
chunk_t data;
|
|
int i = 0;
|
|
|
|
id = identification_create_from_string("C=CH, O=strongSwan, CN=tester");
|
|
|
|
enumerator = id->create_part_enumerator(id);
|
|
while (enumerator->enumerate(enumerator, &part, &data))
|
|
{
|
|
switch (i++)
|
|
{
|
|
case 0:
|
|
ck_assert(part == ID_PART_RDN_C &&
|
|
chunk_equals(data, chunk_create("CH", 2)));
|
|
break;
|
|
case 1:
|
|
ck_assert(part == ID_PART_RDN_O &&
|
|
chunk_equals(data, chunk_from_str("strongSwan")));
|
|
break;
|
|
case 2:
|
|
ck_assert(part == ID_PART_RDN_CN &&
|
|
chunk_equals(data, chunk_from_str("tester")));
|
|
break;
|
|
default:
|
|
fail("unexpected identification part %d", part);
|
|
}
|
|
}
|
|
ck_assert_int_eq(i, 3);
|
|
enumerator->destroy(enumerator);
|
|
id->destroy(id);
|
|
}
|
|
END_TEST
|
|
|
|
/*******************************************************************************
|
|
* wildcards
|
|
*/
|
|
|
|
static bool id_contains_wildcards(char *string)
|
|
{
|
|
identification_t *id;
|
|
bool contains;
|
|
|
|
id = identification_create_from_string(string);
|
|
contains = id->contains_wildcards(id);
|
|
id->destroy(id);
|
|
return contains;
|
|
}
|
|
|
|
START_TEST(test_contains_wildcards)
|
|
{
|
|
ck_assert(id_contains_wildcards("%any"));
|
|
ck_assert(id_contains_wildcards("C=*, O=strongSwan, CN=gw"));
|
|
ck_assert(id_contains_wildcards("C=CH, O=strongSwan, CN=*"));
|
|
ck_assert(id_contains_wildcards("*@strongswan.org"));
|
|
ck_assert(id_contains_wildcards("*.strongswan.org"));
|
|
ck_assert(!id_contains_wildcards("C=**, O=a*, CN=*a"));
|
|
}
|
|
END_TEST
|
|
|
|
/*******************************************************************************
|
|
* clone
|
|
*/
|
|
|
|
START_TEST(test_clone)
|
|
{
|
|
identification_t *a, *b;
|
|
chunk_t a_enc, b_enc;
|
|
|
|
a = identification_create_from_string("[email protected]");
|
|
a_enc = a->get_encoding(a);
|
|
b = a->clone(a);
|
|
ck_assert(b != NULL);
|
|
ck_assert(a != b);
|
|
b_enc = b->get_encoding(b);
|
|
ck_assert(a_enc.ptr != b_enc.ptr);
|
|
ck_assert(chunk_equals(a_enc, b_enc));
|
|
a->destroy(a);
|
|
b->destroy(b);
|
|
}
|
|
END_TEST
|
|
|
|
Suite *identification_suite_create()
|
|
{
|
|
Suite *s;
|
|
TCase *tc;
|
|
|
|
s = suite_create("identification");
|
|
|
|
tc = tcase_create("create");
|
|
tcase_add_test(tc, test_from_encoding);
|
|
tcase_add_test(tc, test_from_data);
|
|
tcase_add_test(tc, test_from_sockaddr);
|
|
tcase_add_loop_test(tc, test_from_string, 0, countof(string_data));
|
|
suite_add_tcase(s, tc);
|
|
|
|
tc = tcase_create("printf_hook");
|
|
tcase_add_test(tc, test_printf_hook);
|
|
tcase_add_test(tc, test_printf_hook_width);
|
|
suite_add_tcase(s, tc);
|
|
|
|
tc = tcase_create("equals");
|
|
tcase_add_test(tc, test_equals);
|
|
tcase_add_test(tc, test_equals_any);
|
|
tcase_add_test(tc, test_equals_binary);
|
|
tcase_add_test(tc, test_equals_fqdn);
|
|
tcase_add_loop_test(tc, test_equals_empty, ID_ANY, ID_KEY_ID + 1);
|
|
suite_add_tcase(s, tc);
|
|
|
|
tc = tcase_create("matches");
|
|
tcase_add_test(tc, test_matches);
|
|
tcase_add_test(tc, test_matches_any);
|
|
tcase_add_test(tc, test_matches_binary);
|
|
tcase_add_test(tc, test_matches_string);
|
|
tcase_add_loop_test(tc, test_matches_empty, ID_ANY, ID_KEY_ID + 1);
|
|
tcase_add_loop_test(tc, test_matches_empty_reverse, ID_ANY, ID_KEY_ID + 1);
|
|
suite_add_tcase(s, tc);
|
|
|
|
tc = tcase_create("part enumeration");
|
|
tcase_add_test(tc, test_parts);
|
|
suite_add_tcase(s, tc);
|
|
|
|
tc = tcase_create("wildcards");
|
|
tcase_add_test(tc, test_contains_wildcards);
|
|
suite_add_tcase(s, tc);
|
|
|
|
tc = tcase_create("clone");
|
|
tcase_add_test(tc, test_clone);
|
|
suite_add_tcase(s, tc);
|
|
|
|
return s;
|
|
}
|