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