diff options
Diffstat (limited to 'src/libstrongswan/tests/suites/test_identification.c')
-rw-r--r-- | src/libstrongswan/tests/suites/test_identification.c | 857 |
1 files changed, 857 insertions, 0 deletions
diff --git a/src/libstrongswan/tests/suites/test_identification.c b/src/libstrongswan/tests/suites/test_identification.c new file mode 100644 index 000000000..edf53f0fd --- /dev/null +++ b/src/libstrongswan/tests/suites/test_identification.c @@ -0,0 +1,857 @@ +/* + * 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("moon@strongswan.org"); + 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("moon@strongswan.org"); + 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 }}, + {"alice@strongswan.org", 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("moon@strongswan.org", "moon@strongswan.org"); + string_equals("MOON@STRONGSWAN.ORG", "MOON@STRONGSWAN.ORG"); + /* non-printable characters */ + string_equals_id("????@strongswan.org", 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("moon@strongswan.org", identification_create_from_encoding(ID_KEY_ID, + chunk_from_str("moon@strongswan.org"))); + /* 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, E=moon@strongswan.org, CN=moon", + "C=CH, email=moon@strongswan.org, CN=moon"); + string_equals("C=CH, E=moon@strongswan.org, CN=moon", + "C=CH, emailAddress=moon@strongswan.org, 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))); + /* moon@strongswan.org 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("moon@strongswan.org"); + snprintf(buf, sizeof(buf), "%25Y", a); + ck_assert_str_eq(" moon@strongswan.org", buf); + snprintf(buf, sizeof(buf), "%-*Y", 25, a); + ck_assert_str_eq("moon@strongswan.org ", buf); + snprintf(buf, sizeof(buf), "%5Y", a); + ck_assert_str_eq("moon@strongswan.org", 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, E=moon@strongswan.org, CN=moon"); + + ck_assert(id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon")); + ck_assert(id_equals(a, "C==CH, E==moon@strongswan.org,,, CN==moon")); + ck_assert(id_equals(a, " C=CH, E=moon@strongswan.org, CN=moon ")); + ck_assert(id_equals(a, "C=ch, E=moon@STRONGSWAN.ORG, CN=Moon")); + ck_assert(id_equals(a, "/C=CH/E=moon@strongswan.org/CN=moon")); + ck_assert(id_equals(a, "C=CH/E=moon@strongswan.org/CN=moon")); + ck_assert(id_equals(a, "C=CH/E=moon@strongswan.org,CN=moon")); + ck_assert(id_equals(a, "C=CH / E=moon@strongswan.org , CN=moon")); + + ck_assert(!id_equals(a, "C=CH E=moon@strongswan.org CN=moon")); + ck_assert(!id_equals(a, "C=CN, E=moon@strongswan.org, CN=moon")); + ck_assert(!id_equals(a, "E=moon@strongswan.org, C=CH, CN=moon")); + ck_assert(!id_equals(a, "E=moon@strongswan.org, 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, E=moon@strongswan.org, CN=moon")) + { + printf("%d %B\n%B\n", i, &fuzzed, &encoding); + } + ck_assert(!id_equals(a, "C=CH, E=moon@strongswan.org, 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, E=moon@strongswan.org, 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, "moon@strongswan.org")); + 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, E=moon@strongswan.org, 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, E=moon@strongswan.org, CN=moon"); + + ck_assert(id_matches(a, "C=CH, E=moon@strongswan.org, 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=*, E=a@b.c, 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, "moon@strongswan.org", 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("moon@strongswan.org"); + + ck_assert(id_matches(a, "moon@strongswan.org", 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, "moon@strongswan.org", 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, E=moon@strongswan.org, 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, "moon@strongswan.org", 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, E=moon@strongswan.org, 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("moon@strongswan.org"); + 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; +} |