identification: Optionally match RDNs in any order and accept missing RDNs
[strongswan.git] / src / libstrongswan / tests / suites / test_identification.c
1 /*
2 * Copyright (C) 2013-2015 Tobias Brunner
3 * Copyright (C) 2016 Andreas Steffen
4 * Copyright (C) 2009 Martin Willi
5 * HSR Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include "test_suite.h"
19
20 #include <utils/identification.h>
21
22 /*******************************************************************************
23 * create (_from_encoding, _from_data, _from_string, _from_sockaddr)
24 */
25
26 START_TEST(test_from_encoding)
27 {
28 identification_t *a;
29 chunk_t expected, encoding;
30
31 /* only ID_ANY is handled differently, for all other types the following
32 * applies. should we perhaps test that this is in fact the case? */
33 expected = chunk_from_str("moon@strongswan.org");
34 a = identification_create_from_encoding(ID_RFC822_ADDR, expected);
35 ck_assert(ID_RFC822_ADDR == a->get_type(a));
36 encoding = a->get_encoding(a);
37 ck_assert(expected.ptr != encoding.ptr);
38 ck_assert(chunk_equals(expected, encoding));
39 a->destroy(a);
40
41 a = identification_create_from_encoding(ID_ANY, expected);
42 ck_assert(ID_ANY == a->get_type(a));
43 encoding = a->get_encoding(a);
44 ck_assert(encoding.ptr == NULL);
45 ck_assert(encoding.len == 0);
46 a->destroy(a);
47 }
48 END_TEST
49
50 START_TEST(test_from_data)
51 {
52 identification_t *a;
53 chunk_t expected, encoding;
54
55 /* this uses the DN parser (C=CH) */
56 expected = chunk_from_chars(0x30, 0x0d, 0x31, 0x0b, 0x30, 0x09, 0x06,
57 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48);
58 a = identification_create_from_data(expected);
59 ck_assert(ID_DER_ASN1_DN == a->get_type(a));
60 encoding = a->get_encoding(a);
61 ck_assert(expected.ptr != encoding.ptr);
62 ck_assert(chunk_equals(expected, encoding));
63 a->destroy(a);
64
65 /* everything else is handled by the string parser */
66 expected = chunk_from_str("moon@strongswan.org");
67 a = identification_create_from_data(expected);
68 ck_assert(ID_RFC822_ADDR == a->get_type(a));
69 encoding = a->get_encoding(a);
70 ck_assert(expected.ptr != encoding.ptr);
71 ck_assert(chunk_equals(expected, encoding));
72 a->destroy(a);
73 }
74 END_TEST
75
76 START_TEST(test_from_sockaddr)
77 {
78 identification_t *a;
79 chunk_t expected, encoding;
80 struct sockaddr_in in = {
81 .sin_family = AF_INET,
82 };
83 struct sockaddr_in6 in6 = {
84 .sin6_family = AF_INET6,
85 };
86
87 expected = chunk_from_chars(0xc0, 0xa8, 0x01, 0x01);
88 memcpy(&in.sin_addr, expected.ptr, sizeof(in.sin_addr));
89 a = identification_create_from_sockaddr((sockaddr_t*)&in);
90 ck_assert(ID_IPV4_ADDR == a->get_type(a));
91 encoding = a->get_encoding(a);
92 ck_assert(chunk_equals(expected, encoding));
93 a->destroy(a);
94
95 expected = chunk_from_chars(0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
97 memcpy(&in6.sin6_addr, expected.ptr, sizeof(in6.sin6_addr));
98 a = identification_create_from_sockaddr((sockaddr_t*)&in6);
99 ck_assert(ID_IPV6_ADDR == a->get_type(a));
100 encoding = a->get_encoding(a);
101 ck_assert(chunk_equals(expected, encoding));
102 a->destroy(a);
103
104 in6.sin6_family = AF_UNSPEC;
105 a = identification_create_from_sockaddr((sockaddr_t*)&in6);
106 ck_assert(ID_ANY == a->get_type(a));
107 a->destroy(a);
108 }
109 END_TEST
110
111 static struct {
112 char *id;
113 id_type_t type;
114 struct {
115 enum {
116 ENC_CHUNK,
117 ENC_STRING,
118 ENC_SIMPLE,
119 } type;
120 union {
121 chunk_t c;
122 char *s;
123 } data;
124 } result;
125 } string_data[] = {
126 {NULL, ID_ANY, { .type = ENC_CHUNK }},
127 {"", ID_ANY, { .type = ENC_CHUNK }},
128 {"%any", ID_ANY, { .type = ENC_CHUNK }},
129 {"%any6", ID_ANY, { .type = ENC_CHUNK }},
130 {"0.0.0.0", ID_ANY, { .type = ENC_CHUNK }},
131 {"0::0", ID_ANY, { .type = ENC_CHUNK }},
132 {"::", ID_ANY, { .type = ENC_CHUNK }},
133 {"*", ID_ANY, { .type = ENC_CHUNK }},
134 {"any", ID_FQDN, { .type = ENC_SIMPLE }},
135 {"any6", ID_FQDN, { .type = ENC_SIMPLE }},
136 {"0", ID_FQDN, { .type = ENC_SIMPLE }},
137 {"**", ID_FQDN, { .type = ENC_SIMPLE }},
138 {"192.168.1.1", ID_IPV4_ADDR, { .type = ENC_CHUNK,
139 .data.c = chunk_from_chars(0xc0,0xa8,0x01,0x01) }},
140 {"192.168.", ID_FQDN, { .type = ENC_SIMPLE }},
141 {".", ID_FQDN, { .type = ENC_SIMPLE }},
142 {"192.168.1.1/33", ID_FQDN, { .type = ENC_SIMPLE }},
143 {"192.168.1.1/32", ID_IPV4_ADDR_SUBNET, { .type = ENC_CHUNK,
144 .data.c = chunk_from_chars(0xc0,0xa8,0x01,0x01,0xff,0xff,0xff,0xff) }},
145 {"192.168.1.1/31", ID_IPV4_ADDR_SUBNET, { .type = ENC_CHUNK,
146 .data.c = chunk_from_chars(0xc0,0xa8,0x01,0x00,0xff,0xff,0xff,0xfe) }},
147 {"192.168.1.8/30", ID_IPV4_ADDR_SUBNET, { .type = ENC_CHUNK,
148 .data.c = chunk_from_chars(0xc0,0xa8,0x01,0x08,0xff,0xff,0xff,0xfc) }},
149 {"192.168.1.128/25", ID_IPV4_ADDR_SUBNET, { .type = ENC_CHUNK,
150 .data.c = chunk_from_chars(0xc0,0xa8,0x01,0x80,0xff,0xff,0xff,0x80) }},
151 {"192.168.1.0/24", ID_IPV4_ADDR_SUBNET, { .type = ENC_CHUNK,
152 .data.c = chunk_from_chars(0xc0,0xa8,0x01,0x00,0xff,0xff,0xff,0x00) }},
153 {"192.168.1.0/23", ID_IPV4_ADDR_SUBNET, { .type = ENC_CHUNK,
154 .data.c = chunk_from_chars(0xc0,0xa8,0x00,0x00,0xff,0xff,0xfe,0x00) }},
155 {"192.168.4.0/22", ID_IPV4_ADDR_SUBNET, { .type = ENC_CHUNK,
156 .data.c = chunk_from_chars(0xc0,0xa8,0x04,0x00,0xff,0xff,0xfc,0x00) }},
157 {"0.0.0.0/0", ID_IPV4_ADDR_SUBNET, { .type = ENC_CHUNK,
158 .data.c = chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00) }},
159 {"192.168.1.0-192.168.1.40",ID_IPV4_ADDR_RANGE, { .type = ENC_CHUNK,
160 .data.c = chunk_from_chars(0xc0,0xa8,0x01,0x00,0xc0,0xa8,0x01,0x28) }},
161 {"0.0.0.0-255.255.255.255", ID_IPV4_ADDR_RANGE, { .type = ENC_CHUNK,
162 .data.c = chunk_from_chars(0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff) }},
163 {"192.168.1.40-192.168.1.0",ID_FQDN, { .type = ENC_SIMPLE }},
164 {"fec0::1", ID_IPV6_ADDR, { .type = ENC_CHUNK,
165 .data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
166 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01) }},
167 {"fec0::", ID_IPV6_ADDR, { .type = ENC_CHUNK,
168 .data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
169 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00) }},
170 {"fec0:", ID_KEY_ID, { .type = ENC_SIMPLE }},
171 {":", ID_KEY_ID, { .type = ENC_SIMPLE }},
172 {"fec0::1/129", ID_KEY_ID, { .type = ENC_SIMPLE }},
173 {"fec0::1/128", ID_IPV6_ADDR_SUBNET, { .type = ENC_CHUNK,
174 .data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
175 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
176 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
177 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff ) }},
178 {"fec0::1/127", ID_IPV6_ADDR_SUBNET, { .type = ENC_CHUNK,
179 .data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
180 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
181 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
182 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe ) }},
183 {"fec0::4/126", ID_IPV6_ADDR_SUBNET, { .type = ENC_CHUNK,
184 .data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
185 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,
186 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
187 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc ) }},
188 {"fec0::100/120", ID_IPV6_ADDR_SUBNET, { .type = ENC_CHUNK,
189 .data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
190 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
191 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
192 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 ) }},
193 {"::/0", ID_IPV6_ADDR_SUBNET, { .type = ENC_CHUNK,
194 .data.c = chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
195 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
196 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
197 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ) }},
198 {"fec0::1-fec0::4fff", ID_IPV6_ADDR_RANGE, { .type = ENC_CHUNK,
199 .data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
200 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
201 0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
202 0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0xff ) }},
203 {"fec0::4fff-fec0::1", ID_KEY_ID, { .type = ENC_SIMPLE }},
204 {"fec0::1-", ID_KEY_ID, { .type = ENC_SIMPLE }},
205 {"alice@strongswan.org", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
206 {"alice@strongswan", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
207 {"alice@", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
208 {"alice", ID_FQDN, { .type = ENC_SIMPLE }},
209 {"@", ID_FQDN, { .type = ENC_CHUNK }},
210 {" @", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
211 {"@strongswan.org", ID_FQDN, { .type = ENC_STRING,
212 .data.s = "strongswan.org" }},
213 {"@#deadbeef", ID_KEY_ID, { .type = ENC_CHUNK,
214 .data.c = chunk_from_chars(0xde,0xad,0xbe,0xef) }},
215 {"@#deadbee", ID_KEY_ID, { .type = ENC_CHUNK,
216 .data.c = chunk_from_chars(0x0d,0xea,0xdb,0xee) }},
217 {"foo=bar", ID_KEY_ID, { .type = ENC_SIMPLE }},
218 {"foo=", ID_KEY_ID, { .type = ENC_SIMPLE }},
219 {"=bar", ID_KEY_ID, { .type = ENC_SIMPLE }},
220 {"C=", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
221 .data.c = chunk_from_chars(0x30,0x0b,0x31,0x09,0x30,0x07,0x06,
222 0x03,0x55,0x04,0x06,0x13,0x00) }},
223 {"C=CH", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
224 .data.c = chunk_from_chars(0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,
225 0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48) }},
226 {"C=CH,", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
227 .data.c = chunk_from_chars(0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,
228 0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48) }},
229 {"C=CH, ", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
230 .data.c = chunk_from_chars(0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,
231 0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48) }},
232 {"C=CH, O", ID_KEY_ID, { .type = ENC_SIMPLE }},
233 {"IPv4:#c0a80101", ID_IPV4_ADDR, { .type = ENC_CHUNK,
234 .data.c = chunk_from_chars(0xc0,0xa8,0x01,0x01) }},
235 { "email:tester", ID_RFC822_ADDR, { .type = ENC_STRING,
236 .data.s = "tester" }},
237 {"xmppaddr:bob@strongswan.org", ID_DER_ASN1_GN, { .type = ENC_CHUNK,
238 .data.c = chunk_from_chars(0xa0,0x20,0x06,0x08,0x2b,0x06,0x01,0x05,
239 0x05,0x07,0x08,0x05,0xa0,0x14,0x0c,0x12,
240 0x62,0x6f,0x62,0x40,0x73,0x74,0x72,0x6f,
241 0x6e,0x67,0x73,0x77,0x61,0x6e,0x2e,0x6f,
242 0x72,0x67) }},
243 { "{1}:#c0a80101", ID_IPV4_ADDR, { .type = ENC_CHUNK,
244 .data.c = chunk_from_chars(0xc0,0xa8,0x01,0x01) }},
245 { "{0x02}:tester", ID_FQDN, { .type = ENC_STRING,
246 .data.s = "tester" }},
247 { "{99}:somedata", 99, { .type = ENC_STRING,
248 .data.s = "somedata" }},
249 };
250
251 START_TEST(test_from_string)
252 {
253 identification_t *a;
254 chunk_t encoding, expected = chunk_empty;
255 char *id;
256
257 id = string_data[_i].id;
258 a = identification_create_from_string(id);
259 fail_unless(a->get_type(a) == string_data[_i].type,
260 "type of id '%s' is %N, %N expected", id,
261 id_type_names, a->get_type(a),
262 id_type_names, string_data[_i].type);
263
264 encoding = a->get_encoding(a);
265 switch (string_data[_i].result.type)
266 {
267 case ENC_SIMPLE:
268 expected = chunk_from_str(string_data[_i].id);
269 break;
270 case ENC_STRING:
271 expected = chunk_from_str(string_data[_i].result.data.s);
272 break;
273 case ENC_CHUNK:
274 expected = string_data[_i].result.data.c;
275 break;
276 default:
277 fail("unexpected result type");
278 }
279
280 ck_assert(!id || (char*)encoding.ptr != id);
281 if (expected.ptr)
282 {
283 fail_unless(chunk_equals(encoding, expected),
284 "parsing '%s' failed\nencoding %B\nexpected %B\n",
285 id, &encoding, &expected);
286 }
287 else
288 {
289 ck_assert(encoding.ptr == NULL);
290 ck_assert(encoding.len == 0);
291 }
292 a->destroy(a);
293 }
294 END_TEST
295
296 /*******************************************************************************
297 * printf_hook
298 */
299
300 static void string_equals(char *a_str, char *b_str)
301 {
302 identification_t *b;
303 char buf[128];
304
305 b = b_str ? identification_create_from_string(b_str) : NULL;
306 snprintf(buf, sizeof(buf), "%Y", b);
307 DESTROY_IF(b);
308 ck_assert_str_eq(a_str, buf);
309 }
310
311 static void string_equals_id(char *a_str, identification_t *b)
312 {
313 char buf[128];
314
315 snprintf(buf, sizeof(buf), "%Y", b);
316 DESTROY_IF(b);
317 ck_assert_str_eq(a_str, buf);
318 }
319
320 START_TEST(test_printf_hook)
321 {
322 string_equals("(null)", NULL);
323 string_equals("%any", "");
324 string_equals("%any", "%any");
325 string_equals("%any", "*");
326
327 string_equals("192.168.1.1", "192.168.1.1");
328 string_equals_id("(invalid ID_IPV4_ADDR)",
329 identification_create_from_encoding(ID_IPV4_ADDR, chunk_empty));
330 string_equals("192.168.1.1/32", "192.168.1.1/32");
331 string_equals("192.168.1.2/31", "192.168.1.2/31");
332 string_equals("192.168.1.0/24", "192.168.1.0/24");
333 string_equals("192.168.2.0/23", "192.168.2.0/23");
334 string_equals("0.0.0.0/0", "0.0.0.0/0");
335 string_equals_id("(invalid ID_IPV4_ADDR_SUBNET)",
336 identification_create_from_encoding(ID_IPV4_ADDR_SUBNET, chunk_empty));
337 string_equals("192.168.1.1-192.168.1.254", "192.168.1.1-192.168.1.254");
338 string_equals("0.0.0.0-255.255.255.255", "0.0.0.0-255.255.255.255");
339 string_equals_id("(invalid ID_IPV4_ADDR_RANGE)",
340 identification_create_from_encoding(ID_IPV4_ADDR_RANGE, chunk_empty));
341 string_equals("fec0::1", "fec0::1");
342 string_equals("fec0::1", "fec0:0:0::1");
343 string_equals_id("(invalid ID_IPV6_ADDR)",
344 identification_create_from_encoding(ID_IPV6_ADDR, chunk_empty));
345 string_equals("fec0::1/128", "fec0::1/128");
346 string_equals("fec0::2/127", "fec0::2/127");
347 string_equals("fec0::100/120", "fec0::100/120");
348 string_equals("::/0", "::/0");
349 string_equals_id("(invalid ID_IPV6_ADDR_SUBNET)",
350 identification_create_from_encoding(ID_IPV6_ADDR_SUBNET, chunk_empty));
351 string_equals("fec0::1-fec0::4fff", "fec0::1-fec0::4fff");
352 string_equals_id("(invalid ID_IPV6_ADDR_RANGE)",
353 identification_create_from_encoding(ID_IPV6_ADDR_RANGE, chunk_empty));
354 string_equals_id("(unknown ID type: 255)",
355 identification_create_from_encoding(255, chunk_empty));
356
357 string_equals("moon@strongswan.org", "moon@strongswan.org");
358 string_equals("MOON@STRONGSWAN.ORG", "MOON@STRONGSWAN.ORG");
359 /* non-printable characters */
360 string_equals_id("????@strongswan.org", identification_create_from_encoding(ID_RFC822_ADDR,
361 chunk_from_chars(0xfa, 0xfb, 0xfc, 0xfd, 0x40, 0x73, 0x74, 0x72,
362 0x6f, 0x6e, 0x67, 0x73, 0x77, 0x61, 0x6e, 0x2e,
363 0x6f, 0x72, 0x67)));
364
365 /* not a DN => ID_KEY_ID => no normalization */
366 string_equals("C=CH, AsdF=asdf", "C=CH, AsdF=asdf");
367 string_equals_id("moon@strongswan.org", identification_create_from_encoding(ID_KEY_ID,
368 chunk_from_str("moon@strongswan.org")));
369 /* non-printable characters */
370 string_equals_id("de:ad:be:ef", identification_create_from_encoding(ID_KEY_ID,
371 chunk_from_chars(0xde, 0xad, 0xbe, 0xef)));
372 /* printable characters */
373 string_equals_id("ABCDEFGHIJKLMNOPQRS",
374 identification_create_from_encoding(ID_KEY_ID,
375 chunk_from_chars(0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
376 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
377 0x51, 0x52, 0x53)));
378 /* ABCDEFGHIJKLMNOPQRST is printable but has the length of a SHA1 hash */
379 string_equals_id("41:42:43:44:45:46:47:48:49:4a:4b:4c:4d:4e:4f:50:51:52:53:54",
380 identification_create_from_encoding(ID_KEY_ID,
381 chunk_from_chars(0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
382 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
383 0x51, 0x52, 0x53, 0x54)));
384
385 string_equals_id("", identification_create_from_encoding(ID_DER_ASN1_DN, chunk_empty));
386 string_equals("C=", "C=");
387 string_equals("C=", "C=,");
388 string_equals("C=", "C=, ");
389 string_equals("C=", "C= , ");
390 string_equals("C=, O=strongSwan", "C=, O=strongSwan");
391 string_equals("C=CH, O=", "C=CH, O=");
392 string_equals("C=CH, O=strongSwan, CN=strongswan.org",
393 "C=CH, O=strongSwan, CN=strongswan.org");
394 string_equals("CN=strongswan.org, O=strongSwan, C=CH",
395 "cn=strongswan.org, o=strongSwan, c=CH");
396 string_equals("C=CH, O=strongSwan, CN=strongswan.org",
397 "C=CH,O=strongSwan,CN=strongswan.org");
398 string_equals("C=CH, O=strongSwan, CN=strongswan.org",
399 "/C=CH/O=strongSwan/CN=strongswan.org");
400 string_equals("CN=strongswan.org, O=strongSwan, C=CH",
401 "CN=strongswan.org,O=strongSwan,C=CH");
402
403 string_equals("C=CH, E=moon@strongswan.org, CN=moon",
404 "C=CH, email=moon@strongswan.org, CN=moon");
405 string_equals("C=CH, E=moon@strongswan.org, CN=moon",
406 "C=CH, emailAddress=moon@strongswan.org, CN=moon");
407
408 /* C=CH, telexNumber=123 (telexNumber is currently not recognized) */
409 string_equals_id("C=CH, 55:04:15=123", identification_create_from_encoding(ID_DER_ASN1_DN,
410 chunk_from_chars(0x30, 0x19, 0x31, 0x17, 0x30, 0x09, 0x06, 0x03, 0x55,
411 0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x30, 0x0a, 0x06,
412 0x03, 0x55, 0x04, 0x15, 0x13, 0x03, 0x31, 0x32, 0x33)));
413 /* C=CH, O=strongSwan (but instead of a 2nd OID -0x06- we got NULL -0x05) */
414 string_equals_id("C=CH, (invalid ID_DER_ASN1_DN)", identification_create_from_encoding(ID_DER_ASN1_DN,
415 chunk_from_chars(0x30, 0x20, 0x31, 0x1e, 0x30, 0x09, 0x06, 0x03, 0x55,
416 0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x30, 0x11, 0x05,
417 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x73, 0x74, 0x72,
418 0x6f, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x6e)));
419 /* moon@strongswan.org as GN */
420 string_equals_id("(ASN.1 general name)", identification_create_from_encoding(ID_DER_ASN1_GN,
421 chunk_from_chars(0x81, 0x14, 0x6d, 0x6f, 0x6f, 0x6e, 0x40, 0x73, 0x74,
422 0x72, 0x6f, 0x6e, 0x67, 0x73, 0x77, 0x61, 0x6e, 0x2e,
423 0x6f, 0x72, 0x67)));
424 }
425 END_TEST
426
427 START_TEST(test_printf_hook_width)
428 {
429 identification_t *a;
430 char buf[128];
431
432 a = identification_create_from_string("moon@strongswan.org");
433 snprintf(buf, sizeof(buf), "%25Y", a);
434 ck_assert_str_eq(" moon@strongswan.org", buf);
435 snprintf(buf, sizeof(buf), "%-*Y", 25, a);
436 ck_assert_str_eq("moon@strongswan.org ", buf);
437 snprintf(buf, sizeof(buf), "%5Y", a);
438 ck_assert_str_eq("moon@strongswan.org", buf);
439 DESTROY_IF(a);
440 }
441 END_TEST
442
443 /*******************************************************************************
444 * equals
445 */
446
447 static bool id_equals(identification_t *a, char *b_str)
448 {
449 identification_t *b;
450 bool equals;
451
452 b = identification_create_from_string(b_str);
453 equals = a->equals(a, b);
454 ck_assert_int_eq(equals, b->equals(b, a));
455 b->destroy(b);
456 return equals;
457 }
458
459 START_TEST(test_equals)
460 {
461 identification_t *a;
462 chunk_t encoding, fuzzed;
463 int i;
464
465 /* this test also tests identification_create_from_string with DNs */
466 a = identification_create_from_string(
467 "C=CH, E=moon@strongswan.org, CN=moon");
468
469 ck_assert(id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"));
470 ck_assert(id_equals(a, "C=CH, email=moon@strongswan.org, CN=moon"));
471 ck_assert(id_equals(a, "C=CH, emailAddress=moon@strongswan.org, CN=moon"));
472 ck_assert(id_equals(a, "C==CH , E==moon@strongswan.org , CN==moon"));
473 ck_assert(id_equals(a, " C=CH, E=moon@strongswan.org, CN=moon "));
474 ck_assert(id_equals(a, "C=ch, E=moon@STRONGSWAN.ORG, CN=Moon"));
475 ck_assert(id_equals(a, "/C=CH/E=moon@strongswan.org/CN=moon"));
476 ck_assert(id_equals(a, " / C=CH / E=moon@strongswan.org / CN=moon"));
477
478 ck_assert(!id_equals(a, "C=CH/E=moon@strongswan.org/CN=moon"));
479 ck_assert(!id_equals(a, "C=CH/E=moon@strongswan.org,CN=moon"));
480 ck_assert(!id_equals(a, "C=CH E=moon@strongswan.org CN=moon"));
481 ck_assert(!id_equals(a, "C=CN, E=moon@strongswan.org, CN=moon"));
482 ck_assert(!id_equals(a, "E=moon@strongswan.org, C=CH, CN=moon"));
483 ck_assert(!id_equals(a, "E=moon@strongswan.org, C=CH, CN=moon"));
484
485 encoding = chunk_clone(a->get_encoding(a));
486 a->destroy(a);
487
488 /* simple fuzzing, increment each byte of encoding */
489 for (i = 0; i < encoding.len; i++)
490 {
491 if (i == 11 || i == 30 || i == 60)
492 { /* skip ASN.1 type fields, as equals() handles them graceful */
493 continue;
494 }
495 fuzzed = chunk_clone(encoding);
496 fuzzed.ptr[i]++;
497 a = identification_create_from_encoding(ID_DER_ASN1_DN, fuzzed);
498 if (id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"))
499 {
500 printf("%d %B\n%B\n", i, &fuzzed, &encoding);
501 }
502 ck_assert(!id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"));
503 a->destroy(a);
504 free(fuzzed.ptr);
505 }
506
507 /* and decrement each byte of encoding */
508 for (i = 0; i < encoding.len; i++)
509 {
510 if (i == 11 || i == 30 || i == 60)
511 {
512 continue;
513 }
514 fuzzed = chunk_clone(encoding);
515 fuzzed.ptr[i]--;
516 a = identification_create_from_encoding(ID_DER_ASN1_DN, fuzzed);
517 ck_assert(!id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"));
518 a->destroy(a);
519 free(fuzzed.ptr);
520 }
521 free(encoding.ptr);
522 }
523 END_TEST
524
525 START_TEST(test_equals_any)
526 {
527 identification_t *a, *b;
528
529 a = identification_create_from_string("%any");
530 b = identification_create_from_encoding(ID_ANY, chunk_empty);
531 ck_assert(a->equals(a, b));
532 ck_assert(b->equals(b, a));
533 b->destroy(b);
534
535 b = identification_create_from_string("C=CH, O=strongSwan, CN=strongswan.org");
536 ck_assert(!a->equals(a, b));
537 ck_assert(!b->equals(b, a));
538 a->destroy(a);
539 b->destroy(b);
540 }
541 END_TEST
542
543 START_TEST(test_equals_binary)
544 {
545 identification_t *a, *b;
546 chunk_t encoding;
547
548 encoding = chunk_from_str("foobar=");
549 /* strings containing = are parsed as KEY_ID if they aren't valid ASN.1 DNs */
550 a = identification_create_from_string("foobar=");
551 ck_assert(a->get_type(a) == ID_KEY_ID);
552 b = identification_create_from_encoding(ID_KEY_ID, encoding);
553 ck_assert(a->equals(a, b));
554 a->destroy(a);
555 b->destroy(b);
556 }
557 END_TEST
558
559 START_TEST(test_equals_fqdn)
560 {
561 identification_t *a;
562
563 a = identification_create_from_string("ipsec.strongswan.org");
564 ck_assert(id_equals(a, "IPSEC.strongswan.org"));
565 ck_assert(id_equals(a, "ipsec.strongSwan.org"));
566 ck_assert(id_equals(a, "ipsec.strongSwan.ORG"));
567 ck_assert(!id_equals(a, "strongswan.org"));
568 a->destroy(a);
569 }
570 END_TEST
571
572 START_TEST(test_equals_empty)
573 {
574 identification_t *a;
575
576 a = identification_create_from_encoding(_i, chunk_empty);
577
578 switch (_i)
579 {
580 case ID_ANY:
581 ck_assert(id_equals(a, "%any"));
582 break;
583 case ID_IPV4_ADDR:
584 ck_assert(!id_equals(a, "192.168.1.1"));
585 break;
586 case ID_FQDN:
587 ck_assert(!id_equals(a, "moon.strongswan.org"));
588 break;
589 case ID_USER_FQDN:
590 ck_assert(!id_equals(a, "moon@strongswan.org"));
591 break;
592 case ID_IPV6_ADDR:
593 ck_assert(!id_equals(a, "fec0::1"));
594 break;
595 case ID_DER_ASN1_DN:
596 ck_assert(!id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"));
597 break;
598 case ID_KEY_ID:
599 ck_assert(!id_equals(a, "@#12345678"));
600 break;
601 case ID_DER_ASN1_GN:
602 case ID_IPV4_ADDR_SUBNET:
603 case ID_IPV6_ADDR_SUBNET:
604 case ID_IPV4_ADDR_RANGE:
605 case ID_IPV6_ADDR_RANGE:
606 /* currently not tested */
607 break;
608 }
609
610 a->destroy(a);
611 }
612 END_TEST
613
614 /*******************************************************************************
615 * matches
616 */
617
618 static bool id_matches(identification_t *a, char *b_str, id_match_t expected)
619 {
620 identification_t *b;
621 id_match_t match;
622
623 b = identification_create_from_string(b_str);
624 match = a->matches(a, b);
625 b->destroy(b);
626 return match == expected;
627 }
628
629 static char* rdn_matching[] = { NULL, "reordered", "relaxed" };
630
631 static struct {
632 char *id;
633 id_match_t match[3];
634 } matches_data[] = {
635 /* C=CH, E=moon@strongswan.org, CN=moon */
636 { "C=CH, E=moon@strongswan.org, CN=moon", {
637 ID_MATCH_PERFECT, ID_MATCH_PERFECT, ID_MATCH_PERFECT }},
638 { "C=CH, email=moon@strongswan.org, CN=moon", {
639 ID_MATCH_PERFECT, ID_MATCH_PERFECT, ID_MATCH_PERFECT }},
640 { "C=CH, emailAddress=moon@strongswan.org, CN=moon", {
641 ID_MATCH_PERFECT, ID_MATCH_PERFECT, ID_MATCH_PERFECT }},
642 { "CN=moon, C=CH, E=moon@strongswan.org", {
643 ID_MATCH_NONE, ID_MATCH_PERFECT, ID_MATCH_PERFECT }},
644 { "C=CH, E=*@strongswan.org, CN=moon", {
645 ID_MATCH_NONE, ID_MATCH_NONE, ID_MATCH_NONE }},
646 { "C=CH, E=*, CN=moon", {
647 ID_MATCH_ONE_WILDCARD, ID_MATCH_ONE_WILDCARD, ID_MATCH_ONE_WILDCARD }},
648 { "C=CH, E=*, CN=*", {
649 ID_MATCH_ONE_WILDCARD - 1, ID_MATCH_ONE_WILDCARD - 1, ID_MATCH_ONE_WILDCARD - 1 }},
650 { "C=*, E=*, CN=*", {
651 ID_MATCH_ONE_WILDCARD - 2, ID_MATCH_ONE_WILDCARD - 2, ID_MATCH_ONE_WILDCARD - 2 }},
652 { "C=*, E=*, CN=*, O=BADInc", {
653 ID_MATCH_NONE, ID_MATCH_NONE, ID_MATCH_NONE }},
654 { "C=CH, CN=*", {
655 ID_MATCH_NONE, ID_MATCH_NONE, ID_MATCH_ONE_WILDCARD - 1 }},
656 { "C=*, E=*", {
657 ID_MATCH_NONE, ID_MATCH_NONE, ID_MATCH_ONE_WILDCARD - 2 }},
658 { "C=*, E=a@b.c, CN=*", {
659 ID_MATCH_NONE, ID_MATCH_NONE, ID_MATCH_NONE }},
660 { "C=CH, O=strongSwan, E=*, CN=*", {
661 ID_MATCH_NONE, ID_MATCH_NONE, ID_MATCH_NONE }},
662 { "", {
663 ID_MATCH_ANY, ID_MATCH_ANY, ID_MATCH_ANY }},
664 { "%any", {
665 ID_MATCH_ANY, ID_MATCH_ANY, ID_MATCH_ANY }},
666 };
667
668 START_TEST(test_matches)
669 {
670 identification_t *a;
671 int i;
672
673 if (rdn_matching[_i])
674 {
675 lib->settings->set_str(lib->settings, "%s.rdn_matching",
676 rdn_matching[_i], lib->ns);
677 }
678
679 a = identification_create_from_string("C=CH, E=moon@strongswan.org, CN=moon");
680
681 for (i = 0; i < countof(matches_data); i++)
682 {
683 ck_assert(id_matches(a, matches_data[i].id, matches_data[i].match[_i]));
684 }
685
686 a->destroy(a);
687 }
688 END_TEST
689
690 static struct {
691 char *id;
692 id_match_t match[3];
693 } matches_two_ou_data[] = {
694 /* C=CH, OU=Research, OU=Floor A, CN=moon */
695 { "C=CH, OU=Research, OU=Floor A, CN=moon", {
696 ID_MATCH_PERFECT, ID_MATCH_PERFECT, ID_MATCH_PERFECT }},
697 { "C=CH, OU=Floor A, CN=moon", {
698 ID_MATCH_NONE, ID_MATCH_NONE, ID_MATCH_ONE_WILDCARD }},
699 { "C=CH, CN=moon", {
700 ID_MATCH_NONE, ID_MATCH_NONE, ID_MATCH_ONE_WILDCARD - 1 }},
701 { "C=CH, OU=*, CN=moon", {
702 ID_MATCH_NONE, ID_MATCH_NONE, ID_MATCH_ONE_WILDCARD - 1 }},
703 { "C=CH, OU=*, OU=*, CN=moon", {
704 ID_MATCH_ONE_WILDCARD - 1, ID_MATCH_ONE_WILDCARD - 1, ID_MATCH_ONE_WILDCARD - 1 }},
705 { "C=CH, OU=Research, OU=*, CN=moon", {
706 ID_MATCH_ONE_WILDCARD, ID_MATCH_ONE_WILDCARD, ID_MATCH_ONE_WILDCARD }},
707 { "C=CH, OU=*, OU=Floor A, CN=moon", {
708 ID_MATCH_ONE_WILDCARD, ID_MATCH_ONE_WILDCARD, ID_MATCH_ONE_WILDCARD }},
709 { "C=CH, OU=*, OU=Research, CN=moon", {
710 ID_MATCH_NONE, ID_MATCH_ONE_WILDCARD, ID_MATCH_ONE_WILDCARD }},
711 { "C=CH, OU=Floor A, OU=*, CN=moon", {
712 ID_MATCH_NONE, ID_MATCH_ONE_WILDCARD, ID_MATCH_ONE_WILDCARD }},
713 { "C=CH, OU=Floor A, OU=Research, CN=moon", {
714 ID_MATCH_NONE, ID_MATCH_PERFECT, ID_MATCH_PERFECT }},
715 };
716
717 START_TEST(test_matches_two_ou)
718 {
719 identification_t *a;
720 int i;
721
722 if (rdn_matching[_i])
723 {
724 lib->settings->set_str(lib->settings, "%s.rdn_matching",
725 rdn_matching[_i], lib->ns);
726 }
727
728 a = identification_create_from_string("C=CH, OU=Research, OU=Floor A, CN=moon");
729
730 for (i = 0; i < countof(matches_two_ou_data); i++)
731 {
732 ck_assert(id_matches(a, matches_two_ou_data[i].id, matches_two_ou_data[i].match[_i]));
733 }
734
735 a->destroy(a);
736 }
737 END_TEST
738
739 START_TEST(test_matches_any)
740 {
741 identification_t *a;
742
743 a = identification_create_from_string("%any");
744
745 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
746 ck_assert(id_matches(a, "", ID_MATCH_ANY));
747 ck_assert(id_matches(a, "*", ID_MATCH_ANY));
748 ck_assert(id_matches(a, "moon@strongswan.org", ID_MATCH_NONE));
749 ck_assert(id_matches(a, "vpn.strongswan.org", ID_MATCH_NONE));
750 a->destroy(a);
751 }
752 END_TEST
753
754 START_TEST(test_matches_binary)
755 {
756 identification_t *a;
757
758 /* strings containing = are parsed as KEY_ID if they aren't valid ASN.1 DNs */
759 a = identification_create_from_string("foo=bar");
760 ck_assert(a->get_type(a) == ID_KEY_ID);
761 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
762 ck_assert(id_matches(a, "foo=bar", ID_MATCH_PERFECT));
763 ck_assert(id_matches(a, "bar=foo", ID_MATCH_NONE));
764 ck_assert(id_matches(a, "*=bar", ID_MATCH_NONE));
765 ck_assert(id_matches(a, "foo=*", ID_MATCH_NONE));
766 ck_assert(id_matches(a, "foo@bar", ID_MATCH_NONE));
767 a->destroy(a);
768 }
769 END_TEST
770
771 START_TEST(test_matches_range)
772 {
773 identification_t *a, *b;
774
775 /* IPv4 addresses */
776 a = identification_create_from_string("192.168.1.1");
777 ck_assert(a->get_type(a) == ID_IPV4_ADDR);
778 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
779 ck_assert(id_matches(a, "0.0.0.0/0", ID_MATCH_MAX_WILDCARDS));
780 ck_assert(id_matches(a, "192.168.1.1", ID_MATCH_PERFECT));
781 ck_assert(id_matches(a, "192.168.1.2", ID_MATCH_NONE));
782 ck_assert(id_matches(a, "192.168.1.1/32", ID_MATCH_PERFECT));
783 ck_assert(id_matches(a, "192.168.1.0/32", ID_MATCH_NONE));
784 ck_assert(id_matches(a, "192.168.1.0/24", ID_MATCH_ONE_WILDCARD));
785 ck_assert(id_matches(a, "192.168.0.0/24", ID_MATCH_NONE));
786 ck_assert(id_matches(a, "192.168.1.1-192.168.1.1", ID_MATCH_PERFECT));
787 ck_assert(id_matches(a, "192.168.1.0-192.168.1.64", ID_MATCH_ONE_WILDCARD));
788 ck_assert(id_matches(a, "192.168.1.2-192.168.1.64", ID_MATCH_NONE));
789 ck_assert(id_matches(a, "192.168.0.240-192.168.1.0", ID_MATCH_NONE));
790 ck_assert(id_matches(a, "foo@bar", ID_MATCH_NONE));
791
792 /* Malformed IPv4 subnet and range encoding */
793 b = identification_create_from_encoding(ID_IPV4_ADDR_SUBNET, chunk_empty);
794 ck_assert(a->matches(a, b) == ID_MATCH_NONE);
795 b->destroy(b);
796 b = identification_create_from_encoding(ID_IPV4_ADDR_RANGE, chunk_empty);
797 ck_assert(a->matches(a, b) == ID_MATCH_NONE);
798 b->destroy(b);
799 b = identification_create_from_encoding(ID_IPV4_ADDR_RANGE,
800 chunk_from_chars(0xc0,0xa8,0x01,0x28,0xc0,0xa8,0x01,0x00));
801 ck_assert(a->matches(a, b) == ID_MATCH_NONE);
802 b->destroy(b);
803
804 a->destroy(a);
805
806 /* IPv6 addresses */
807 a = identification_create_from_string("fec0::1");
808 ck_assert(a->get_type(a) == ID_IPV6_ADDR);
809 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
810 ck_assert(id_matches(a, "::/0", ID_MATCH_MAX_WILDCARDS));
811 ck_assert(id_matches(a, "fec0::1", ID_MATCH_PERFECT));
812 ck_assert(id_matches(a, "fec0::2", ID_MATCH_NONE));
813 ck_assert(id_matches(a, "fec0::1/128", ID_MATCH_PERFECT));
814 ck_assert(id_matches(a, "fec0::/128", ID_MATCH_NONE));
815 ck_assert(id_matches(a, "fec0::/120", ID_MATCH_ONE_WILDCARD));
816 ck_assert(id_matches(a, "fec0::100/120", ID_MATCH_NONE));
817 ck_assert(id_matches(a, "fec0::1-fec0::1", ID_MATCH_PERFECT));
818 ck_assert(id_matches(a, "fec0::0-fec0::5", ID_MATCH_ONE_WILDCARD));
819 ck_assert(id_matches(a, "fec0::4001-fec0::4ffe", ID_MATCH_NONE));
820 ck_assert(id_matches(a, "feb0::1-fec0::0", ID_MATCH_NONE));
821 ck_assert(id_matches(a, "foo@bar", ID_MATCH_NONE));
822
823 /* Malformed IPv6 subnet and range encoding */
824 b = identification_create_from_encoding(ID_IPV6_ADDR_SUBNET, chunk_empty);
825 ck_assert(a->matches(a, b) == ID_MATCH_NONE);
826 b->destroy(b);
827 b = identification_create_from_encoding(ID_IPV6_ADDR_RANGE, chunk_empty);
828 ck_assert(a->matches(a, b) == ID_MATCH_NONE);
829 b->destroy(b);
830 b = identification_create_from_encoding(ID_IPV6_ADDR_RANGE,
831 chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
832 0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0xff,
833 0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
834 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 ));
835 ck_assert(a->matches(a, b) == ID_MATCH_NONE);
836 b->destroy(b);
837
838 a->destroy(a);
839
840 /* Malformed IPv4 address encoding */
841 a = identification_create_from_encoding(ID_IPV4_ADDR, chunk_empty);
842 ck_assert(id_matches(a, "0.0.0.0/0", ID_MATCH_NONE));
843 ck_assert(id_matches(a, "0.0.0.0-255.255.255.255", ID_MATCH_NONE));
844 a->destroy(a);
845
846 /* Malformed IPv6 address encoding */
847 a = identification_create_from_encoding(ID_IPV6_ADDR, chunk_empty);
848 ck_assert(id_matches(a, "::/0", ID_MATCH_NONE));
849 ck_assert(id_matches(a, "::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", ID_MATCH_NONE));
850 a->destroy(a);
851 }
852 END_TEST
853
854 START_TEST(test_matches_string)
855 {
856 identification_t *a;
857
858 a = identification_create_from_string("moon@strongswan.org");
859
860 ck_assert(id_matches(a, "moon@strongswan.org", ID_MATCH_PERFECT));
861 ck_assert(id_matches(a, "*@strongswan.org", ID_MATCH_ONE_WILDCARD));
862 ck_assert(id_matches(a, "*@*.org", ID_MATCH_NONE));
863 ck_assert(id_matches(a, "*@*", ID_MATCH_NONE));
864 /* the following two are parsed as ID_FQDN, so no match */
865 ck_assert(id_matches(a, "*strongswan.org", ID_MATCH_NONE));
866 ck_assert(id_matches(a, "*.org", ID_MATCH_NONE));
867 ck_assert(id_matches(a, "moon@*", ID_MATCH_NONE));
868 ck_assert(id_matches(a, "**", ID_MATCH_NONE));
869 ck_assert(id_matches(a, "*", ID_MATCH_ANY));
870 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
871 a->destroy(a);
872
873 a = identification_create_from_string("vpn.strongswan.org");
874
875 ck_assert(id_matches(a, "vpn.strongswan.org", ID_MATCH_PERFECT));
876 ck_assert(id_matches(a, "*.strongswan.org", ID_MATCH_ONE_WILDCARD));
877 ck_assert(id_matches(a, "*strongswan.org", ID_MATCH_ONE_WILDCARD));
878 ck_assert(id_matches(a, "*.org", ID_MATCH_ONE_WILDCARD));
879 ck_assert(id_matches(a, "*.strongswan.*", ID_MATCH_NONE));
880 ck_assert(id_matches(a, "*vpn.strongswan.org", ID_MATCH_NONE));
881 ck_assert(id_matches(a, "vpn.strongswan.*", ID_MATCH_NONE));
882 ck_assert(id_matches(a, "**", ID_MATCH_NONE));
883 ck_assert(id_matches(a, "*", ID_MATCH_ANY));
884 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
885 a->destroy(a);
886 }
887 END_TEST
888
889 START_TEST(test_matches_empty)
890 {
891 identification_t *a;
892
893 a = identification_create_from_encoding(_i, chunk_empty);
894
895 switch (_i)
896 {
897 case ID_ANY:
898 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
899 break;
900 case ID_IPV4_ADDR:
901 ck_assert(id_matches(a, "192.168.1.1", ID_MATCH_NONE));
902 break;
903 case ID_FQDN:
904 ck_assert(id_matches(a, "moon.strongswan.org", ID_MATCH_NONE));
905 break;
906 case ID_USER_FQDN:
907 ck_assert(id_matches(a, "moon@strongswan.org", ID_MATCH_NONE));
908 break;
909 case ID_IPV6_ADDR:
910 ck_assert(id_matches(a, "fec0::1", ID_MATCH_NONE));
911 break;
912 case ID_DER_ASN1_DN:
913 ck_assert(id_matches(a, "C=CH, E=moon@strongswan.org, CN=moon",
914 ID_MATCH_NONE));
915 break;
916 case ID_KEY_ID:
917 ck_assert(id_matches(a, "@#12345678", ID_MATCH_NONE));
918 break;
919 case ID_DER_ASN1_GN:
920 case ID_IPV4_ADDR_SUBNET:
921 case ID_IPV6_ADDR_SUBNET:
922 case ID_IPV4_ADDR_RANGE:
923 case ID_IPV6_ADDR_RANGE:
924 /* currently not tested */
925 break;
926 }
927
928 a->destroy(a);
929 }
930 END_TEST
931
932 static bool id_matches_rev(identification_t *a, char *b_str, id_match_t expected)
933 {
934 identification_t *b;
935 id_match_t match;
936
937 b = identification_create_from_string(b_str);
938 match = b->matches(b, a);
939 b->destroy(b);
940 return match == expected;
941 }
942
943 START_TEST(test_matches_empty_reverse)
944 {
945 identification_t *a;
946
947 a = identification_create_from_encoding(_i, chunk_empty);
948
949 switch (_i)
950 {
951 case ID_ANY:
952 ck_assert(id_matches_rev(a, "%any", ID_MATCH_ANY));
953 break;
954 case ID_IPV4_ADDR:
955 ck_assert(id_matches_rev(a, "192.168.1.1", ID_MATCH_NONE));
956 break;
957 case ID_FQDN:
958 ck_assert(id_matches_rev(a, "moon.strongswan.org", ID_MATCH_NONE));
959 break;
960 case ID_USER_FQDN:
961 ck_assert(id_matches_rev(a, "moon@strongswan.org", ID_MATCH_NONE));
962 break;
963 case ID_IPV6_ADDR:
964 ck_assert(id_matches_rev(a, "fec0::1", ID_MATCH_NONE));
965 break;
966 case ID_DER_ASN1_DN:
967 ck_assert(id_matches_rev(a, "C=CH, E=moon@strongswan.org, CN=moon",
968 ID_MATCH_NONE));
969 break;
970 case ID_KEY_ID:
971 ck_assert(id_matches_rev(a, "@#12345678", ID_MATCH_NONE));
972 break;
973 case ID_DER_ASN1_GN:
974 case ID_IPV4_ADDR_SUBNET:
975 case ID_IPV6_ADDR_SUBNET:
976 case ID_IPV4_ADDR_RANGE:
977 case ID_IPV6_ADDR_RANGE:
978 /* currently not tested */
979 break;
980 }
981
982 a->destroy(a);
983 }
984 END_TEST
985
986 /*******************************************************************************
987 * identification hashing
988 */
989
990 static bool id_hash_equals(char *str, char *b_str)
991 {
992 identification_t *a, *b;
993 bool success = FALSE;
994
995 a = identification_create_from_string(str);
996 b = identification_create_from_string(b_str ?: str);
997 success = a->hash(a, 0) == b->hash(b, 0);
998 a->destroy(a);
999 b->destroy(b);
1000 return success;
1001 }
1002
1003 START_TEST(test_hash)
1004 {
1005 ck_assert(id_hash_equals("moon@strongswan.org", NULL));
1006 ck_assert(id_hash_equals("vpn.strongswan.org", NULL));
1007 ck_assert(id_hash_equals("192.168.1.1", NULL));
1008 ck_assert(id_hash_equals("C=CH", NULL));
1009
1010 ck_assert(!id_hash_equals("moon@strongswan.org", "sun@strongswan.org"));
1011 ck_assert(!id_hash_equals("vpn.strongswan.org", "*.strongswan.org"));
1012 ck_assert(!id_hash_equals("192.168.1.1", "192.168.1.2"));
1013 ck_assert(!id_hash_equals("C=CH", "C=DE"));
1014 ck_assert(!id_hash_equals("fqdn:strongswan.org", "keyid:strongswan.org"));
1015 }
1016 END_TEST
1017
1018 START_TEST(test_hash_any)
1019 {
1020 ck_assert(id_hash_equals("%any", NULL));
1021 ck_assert(id_hash_equals("%any", "0.0.0.0"));
1022 ck_assert(id_hash_equals("%any", "*"));
1023 ck_assert(id_hash_equals("%any", ""));
1024
1025 ck_assert(!id_hash_equals("%any", "any"));
1026 }
1027 END_TEST
1028
1029 START_TEST(test_hash_dn)
1030 {
1031 identification_t *a, *b;
1032
1033 /* same DN (C=CH, O=strongSwan), different RDN type (PRINTABLESTRING vs.
1034 * UTF8STRING) */
1035 a = identification_create_from_data(chunk_from_chars(
1036 0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
1037 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x31,
1038 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a,
1039 0x13, 0x0a, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67,
1040 0x53, 0x77, 0x61, 0x6e));
1041 b = identification_create_from_data(chunk_from_chars(
1042 0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
1043 0x55, 0x04, 0x06, 0x0c, 0x02, 0x43, 0x48, 0x31,
1044 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a,
1045 0x0c, 0x0a, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67,
1046 0x53, 0x77, 0x61, 0x6e));
1047 ck_assert_int_eq(a->hash(a, 0), b->hash(b, 0));
1048 ck_assert(a->equals(a, b));
1049 a->destroy(a);
1050 b->destroy(b);
1051 }
1052 END_TEST
1053
1054 START_TEST(test_hash_inc)
1055 {
1056 identification_t *a;
1057
1058 a = identification_create_from_string("vpn.strongswan.org");
1059 ck_assert(a->hash(a, 0) != a->hash(a, 1));
1060 a->destroy(a);
1061
1062 a = identification_create_from_string("C=CH, O=strongSwan");
1063 ck_assert(a->hash(a, 0) != a->hash(a, 1));
1064 a->destroy(a);
1065 }
1066 END_TEST
1067
1068 /*******************************************************************************
1069 * identification part enumeration
1070 */
1071
1072 START_TEST(test_parts)
1073 {
1074 identification_t *id;
1075 enumerator_t *enumerator;
1076 id_part_t part;
1077 chunk_t data;
1078 int i = 0;
1079
1080 id = identification_create_from_string("C=CH, O=strongSwan, CN=tester");
1081
1082 enumerator = id->create_part_enumerator(id);
1083 while (enumerator->enumerate(enumerator, &part, &data))
1084 {
1085 switch (i++)
1086 {
1087 case 0:
1088 ck_assert(part == ID_PART_RDN_C &&
1089 chunk_equals(data, chunk_create("CH", 2)));
1090 break;
1091 case 1:
1092 ck_assert(part == ID_PART_RDN_O &&
1093 chunk_equals(data, chunk_from_str("strongSwan")));
1094 break;
1095 case 2:
1096 ck_assert(part == ID_PART_RDN_CN &&
1097 chunk_equals(data, chunk_from_str("tester")));
1098 break;
1099 default:
1100 fail("unexpected identification part %d", part);
1101 }
1102 }
1103 ck_assert_int_eq(i, 3);
1104 enumerator->destroy(enumerator);
1105 id->destroy(id);
1106 }
1107 END_TEST
1108
1109 /*******************************************************************************
1110 * wildcards
1111 */
1112
1113 static bool id_contains_wildcards(char *string)
1114 {
1115 identification_t *id;
1116 bool contains;
1117
1118 id = identification_create_from_string(string);
1119 contains = id->contains_wildcards(id);
1120 id->destroy(id);
1121 return contains;
1122 }
1123
1124 START_TEST(test_contains_wildcards)
1125 {
1126 ck_assert(id_contains_wildcards("%any"));
1127 ck_assert(id_contains_wildcards("C=*, O=strongSwan, CN=gw"));
1128 ck_assert(id_contains_wildcards("C=CH, O=strongSwan, CN=*"));
1129 ck_assert(id_contains_wildcards("*@strongswan.org"));
1130 ck_assert(id_contains_wildcards("*.strongswan.org"));
1131 ck_assert(!id_contains_wildcards("C=**, O=a*, CN=*a"));
1132 }
1133 END_TEST
1134
1135 /*******************************************************************************
1136 * clone
1137 */
1138
1139 START_TEST(test_clone)
1140 {
1141 identification_t *a, *b;
1142 chunk_t a_enc, b_enc;
1143
1144 a = identification_create_from_string("moon@strongswan.org");
1145 a_enc = a->get_encoding(a);
1146 b = a->clone(a);
1147 ck_assert(b != NULL);
1148 ck_assert(a != b);
1149 b_enc = b->get_encoding(b);
1150 ck_assert(a_enc.ptr != b_enc.ptr);
1151 ck_assert(chunk_equals(a_enc, b_enc));
1152 a->destroy(a);
1153 b->destroy(b);
1154 }
1155 END_TEST
1156
1157 Suite *identification_suite_create()
1158 {
1159 Suite *s;
1160 TCase *tc;
1161
1162 s = suite_create("identification");
1163
1164 tc = tcase_create("create");
1165 tcase_add_test(tc, test_from_encoding);
1166 tcase_add_test(tc, test_from_data);
1167 tcase_add_test(tc, test_from_sockaddr);
1168 tcase_add_loop_test(tc, test_from_string, 0, countof(string_data));
1169 suite_add_tcase(s, tc);
1170
1171 tc = tcase_create("printf_hook");
1172 tcase_add_test(tc, test_printf_hook);
1173 tcase_add_test(tc, test_printf_hook_width);
1174 suite_add_tcase(s, tc);
1175
1176 tc = tcase_create("equals");
1177 tcase_add_test(tc, test_equals);
1178 tcase_add_test(tc, test_equals_any);
1179 tcase_add_test(tc, test_equals_binary);
1180 tcase_add_test(tc, test_equals_fqdn);
1181 tcase_add_loop_test(tc, test_equals_empty, ID_ANY, ID_KEY_ID + 1);
1182 suite_add_tcase(s, tc);
1183
1184 tc = tcase_create("matches");
1185 tcase_add_loop_test(tc, test_matches, 0, countof(rdn_matching));
1186 tcase_add_loop_test(tc, test_matches_two_ou, 0, countof(rdn_matching));
1187 tcase_add_test(tc, test_matches_any);
1188 tcase_add_test(tc, test_matches_binary);
1189 tcase_add_test(tc, test_matches_range);
1190 tcase_add_test(tc, test_matches_string);
1191 tcase_add_loop_test(tc, test_matches_empty, ID_ANY, ID_KEY_ID + 1);
1192 tcase_add_loop_test(tc, test_matches_empty_reverse, ID_ANY, ID_KEY_ID + 1);
1193 suite_add_tcase(s, tc);
1194
1195 tc = tcase_create("hash");
1196 tcase_add_test(tc, test_hash);
1197 tcase_add_test(tc, test_hash_any);
1198 tcase_add_test(tc, test_hash_dn);
1199 tcase_add_test(tc, test_hash_inc);
1200 suite_add_tcase(s, tc);
1201
1202 tc = tcase_create("part enumeration");
1203 tcase_add_test(tc, test_parts);
1204 suite_add_tcase(s, tc);
1205
1206 tc = tcase_create("wildcards");
1207 tcase_add_test(tc, test_contains_wildcards);
1208 suite_add_tcase(s, tc);
1209
1210 tc = tcase_create("clone");
1211 tcase_add_test(tc, test_clone);
1212 suite_add_tcase(s, tc);
1213
1214 return s;
1215 }