identification: Support custom types in string constructor prefixes
[strongswan.git] / src / libstrongswan / tests / suites / test_identification.c
1 /*
2 * Copyright (C) 2013 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, pseudonym=ANO (pseudonym is currently not recognized) */
328 string_equals_id("C=CH, 55:04:41=ANO", 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, 0x41, 0x13, 0x03, 0x41, 0x4e, 0x4f)));
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=*, CN=moon", ID_MATCH_ONE_WILDCARD));
554 ck_assert(id_matches(a, "C=CH, E=*, CN=*", ID_MATCH_ONE_WILDCARD - 1));
555 ck_assert(id_matches(a, "C=*, E=*, CN=*", ID_MATCH_ONE_WILDCARD - 2));
556 ck_assert(id_matches(a, "C=*, E=*, CN=*, O=BADInc", ID_MATCH_NONE));
557 ck_assert(id_matches(a, "C=*, E=*", ID_MATCH_NONE));
558 ck_assert(id_matches(a, "C=*, E=a@b.c, CN=*", ID_MATCH_NONE));
559 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
560
561 a->destroy(a);
562 }
563 END_TEST
564
565 START_TEST(test_matches_any)
566 {
567 identification_t *a;
568
569 a = identification_create_from_string("%any");
570
571 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
572 ck_assert(id_matches(a, "", ID_MATCH_ANY));
573 ck_assert(id_matches(a, "*", ID_MATCH_ANY));
574 ck_assert(id_matches(a, "moon@strongswan.org", ID_MATCH_NONE));
575 ck_assert(id_matches(a, "vpn.strongswan.org", ID_MATCH_NONE));
576 a->destroy(a);
577 }
578 END_TEST
579
580 START_TEST(test_matches_binary)
581 {
582 identification_t *a;
583
584 /* strings containing = are parsed as KEY_ID if they aren't valid ASN.1 DNs */
585 a = identification_create_from_string("foo=bar");
586 ck_assert(a->get_type(a) == ID_KEY_ID);
587 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
588 ck_assert(id_matches(a, "foo=bar", ID_MATCH_PERFECT));
589 ck_assert(id_matches(a, "bar=foo", ID_MATCH_NONE));
590 ck_assert(id_matches(a, "*=bar", ID_MATCH_NONE));
591 ck_assert(id_matches(a, "foo=*", ID_MATCH_NONE));
592 ck_assert(id_matches(a, "foo@bar", ID_MATCH_NONE));
593 a->destroy(a);
594 }
595 END_TEST
596
597 START_TEST(test_matches_string)
598 {
599 identification_t *a;
600
601 a = identification_create_from_string("moon@strongswan.org");
602
603 ck_assert(id_matches(a, "moon@strongswan.org", ID_MATCH_PERFECT));
604 ck_assert(id_matches(a, "*@strongswan.org", ID_MATCH_ONE_WILDCARD));
605 ck_assert(id_matches(a, "*@*.org", ID_MATCH_NONE));
606 ck_assert(id_matches(a, "*@*", ID_MATCH_NONE));
607 /* the following two are parsed as ID_FQDN, so no match */
608 ck_assert(id_matches(a, "*strongswan.org", ID_MATCH_NONE));
609 ck_assert(id_matches(a, "*.org", ID_MATCH_NONE));
610 ck_assert(id_matches(a, "moon@*", ID_MATCH_NONE));
611 ck_assert(id_matches(a, "**", ID_MATCH_NONE));
612 ck_assert(id_matches(a, "*", ID_MATCH_ANY));
613 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
614 a->destroy(a);
615
616 a = identification_create_from_string("vpn.strongswan.org");
617
618 ck_assert(id_matches(a, "vpn.strongswan.org", ID_MATCH_PERFECT));
619 ck_assert(id_matches(a, "*.strongswan.org", ID_MATCH_ONE_WILDCARD));
620 ck_assert(id_matches(a, "*strongswan.org", ID_MATCH_ONE_WILDCARD));
621 ck_assert(id_matches(a, "*.org", ID_MATCH_ONE_WILDCARD));
622 ck_assert(id_matches(a, "*.strongswan.*", ID_MATCH_NONE));
623 ck_assert(id_matches(a, "*vpn.strongswan.org", ID_MATCH_NONE));
624 ck_assert(id_matches(a, "vpn.strongswan.*", ID_MATCH_NONE));
625 ck_assert(id_matches(a, "**", ID_MATCH_NONE));
626 ck_assert(id_matches(a, "*", ID_MATCH_ANY));
627 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
628 a->destroy(a);
629 }
630 END_TEST
631
632 START_TEST(test_matches_empty)
633 {
634 identification_t *a;
635
636 a = identification_create_from_encoding(_i, chunk_empty);
637
638 switch (_i)
639 {
640 case ID_ANY:
641 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
642 break;
643 case ID_IPV4_ADDR:
644 ck_assert(id_matches(a, "192.168.1.1", ID_MATCH_NONE));
645 break;
646 case ID_FQDN:
647 ck_assert(id_matches(a, "moon.strongswan.org", ID_MATCH_NONE));
648 break;
649 case ID_USER_FQDN:
650 ck_assert(id_matches(a, "moon@strongswan.org", ID_MATCH_NONE));
651 break;
652 case ID_IPV6_ADDR:
653 ck_assert(id_matches(a, "fec0::1", ID_MATCH_NONE));
654 break;
655 case ID_DER_ASN1_DN:
656 ck_assert(id_matches(a, "C=CH, E=moon@strongswan.org, CN=moon",
657 ID_MATCH_NONE));
658 break;
659 case ID_KEY_ID:
660 ck_assert(id_matches(a, "@#12345678", ID_MATCH_NONE));
661 break;
662 case ID_DER_ASN1_GN:
663 case ID_IPV4_ADDR_SUBNET:
664 case ID_IPV6_ADDR_SUBNET:
665 case ID_IPV4_ADDR_RANGE:
666 case ID_IPV6_ADDR_RANGE:
667 /* currently not tested */
668 break;
669 }
670
671 a->destroy(a);
672 }
673 END_TEST
674
675 static bool id_matches_rev(identification_t *a, char *b_str, id_match_t expected)
676 {
677 identification_t *b;
678 id_match_t match;
679
680 b = identification_create_from_string(b_str);
681 match = b->matches(b, a);
682 b->destroy(b);
683 return match == expected;
684 }
685
686 START_TEST(test_matches_empty_reverse)
687 {
688 identification_t *a;
689
690 a = identification_create_from_encoding(_i, chunk_empty);
691
692 switch (_i)
693 {
694 case ID_ANY:
695 ck_assert(id_matches_rev(a, "%any", ID_MATCH_ANY));
696 break;
697 case ID_IPV4_ADDR:
698 ck_assert(id_matches_rev(a, "192.168.1.1", ID_MATCH_NONE));
699 break;
700 case ID_FQDN:
701 ck_assert(id_matches_rev(a, "moon.strongswan.org", ID_MATCH_NONE));
702 break;
703 case ID_USER_FQDN:
704 ck_assert(id_matches_rev(a, "moon@strongswan.org", ID_MATCH_NONE));
705 break;
706 case ID_IPV6_ADDR:
707 ck_assert(id_matches_rev(a, "fec0::1", ID_MATCH_NONE));
708 break;
709 case ID_DER_ASN1_DN:
710 ck_assert(id_matches_rev(a, "C=CH, E=moon@strongswan.org, CN=moon",
711 ID_MATCH_NONE));
712 break;
713 case ID_KEY_ID:
714 ck_assert(id_matches_rev(a, "@#12345678", ID_MATCH_NONE));
715 break;
716 case ID_DER_ASN1_GN:
717 case ID_IPV4_ADDR_SUBNET:
718 case ID_IPV6_ADDR_SUBNET:
719 case ID_IPV4_ADDR_RANGE:
720 case ID_IPV6_ADDR_RANGE:
721 /* currently not tested */
722 break;
723 }
724
725 a->destroy(a);
726 }
727 END_TEST
728
729 /*******************************************************************************
730 * identification part enumeration
731 */
732
733 START_TEST(test_parts)
734 {
735 identification_t *id;
736 enumerator_t *enumerator;
737 id_part_t part;
738 chunk_t data;
739 int i = 0;
740
741 id = identification_create_from_string("C=CH, O=strongSwan, CN=tester");
742
743 enumerator = id->create_part_enumerator(id);
744 while (enumerator->enumerate(enumerator, &part, &data))
745 {
746 switch (i++)
747 {
748 case 0:
749 ck_assert(part == ID_PART_RDN_C &&
750 chunk_equals(data, chunk_create("CH", 2)));
751 break;
752 case 1:
753 ck_assert(part == ID_PART_RDN_O &&
754 chunk_equals(data, chunk_from_str("strongSwan")));
755 break;
756 case 2:
757 ck_assert(part == ID_PART_RDN_CN &&
758 chunk_equals(data, chunk_from_str("tester")));
759 break;
760 default:
761 fail("unexpected identification part %d", part);
762 }
763 }
764 ck_assert_int_eq(i, 3);
765 enumerator->destroy(enumerator);
766 id->destroy(id);
767 }
768 END_TEST
769
770 /*******************************************************************************
771 * wildcards
772 */
773
774 static bool id_contains_wildcards(char *string)
775 {
776 identification_t *id;
777 bool contains;
778
779 id = identification_create_from_string(string);
780 contains = id->contains_wildcards(id);
781 id->destroy(id);
782 return contains;
783 }
784
785 START_TEST(test_contains_wildcards)
786 {
787 ck_assert(id_contains_wildcards("%any"));
788 ck_assert(id_contains_wildcards("C=*, O=strongSwan, CN=gw"));
789 ck_assert(id_contains_wildcards("C=CH, O=strongSwan, CN=*"));
790 ck_assert(id_contains_wildcards("*@strongswan.org"));
791 ck_assert(id_contains_wildcards("*.strongswan.org"));
792 ck_assert(!id_contains_wildcards("C=**, O=a*, CN=*a"));
793 }
794 END_TEST
795
796 /*******************************************************************************
797 * clone
798 */
799
800 START_TEST(test_clone)
801 {
802 identification_t *a, *b;
803 chunk_t a_enc, b_enc;
804
805 a = identification_create_from_string("moon@strongswan.org");
806 a_enc = a->get_encoding(a);
807 b = a->clone(a);
808 ck_assert(b != NULL);
809 ck_assert(a != b);
810 b_enc = b->get_encoding(b);
811 ck_assert(a_enc.ptr != b_enc.ptr);
812 ck_assert(chunk_equals(a_enc, b_enc));
813 a->destroy(a);
814 b->destroy(b);
815 }
816 END_TEST
817
818 Suite *identification_suite_create()
819 {
820 Suite *s;
821 TCase *tc;
822
823 s = suite_create("identification");
824
825 tc = tcase_create("create");
826 tcase_add_test(tc, test_from_encoding);
827 tcase_add_test(tc, test_from_data);
828 tcase_add_test(tc, test_from_sockaddr);
829 tcase_add_loop_test(tc, test_from_string, 0, countof(string_data));
830 suite_add_tcase(s, tc);
831
832 tc = tcase_create("printf_hook");
833 tcase_add_test(tc, test_printf_hook);
834 tcase_add_test(tc, test_printf_hook_width);
835 suite_add_tcase(s, tc);
836
837 tc = tcase_create("equals");
838 tcase_add_test(tc, test_equals);
839 tcase_add_test(tc, test_equals_any);
840 tcase_add_test(tc, test_equals_binary);
841 tcase_add_test(tc, test_equals_fqdn);
842 tcase_add_loop_test(tc, test_equals_empty, ID_ANY, ID_KEY_ID + 1);
843 suite_add_tcase(s, tc);
844
845 tc = tcase_create("matches");
846 tcase_add_test(tc, test_matches);
847 tcase_add_test(tc, test_matches_any);
848 tcase_add_test(tc, test_matches_binary);
849 tcase_add_test(tc, test_matches_string);
850 tcase_add_loop_test(tc, test_matches_empty, ID_ANY, ID_KEY_ID + 1);
851 tcase_add_loop_test(tc, test_matches_empty_reverse, ID_ANY, ID_KEY_ID + 1);
852 suite_add_tcase(s, tc);
853
854 tc = tcase_create("part enumeration");
855 tcase_add_test(tc, test_parts);
856 suite_add_tcase(s, tc);
857
858 tc = tcase_create("wildcards");
859 tcase_add_test(tc, test_contains_wildcards);
860 suite_add_tcase(s, tc);
861
862 tc = tcase_create("clone");
863 tcase_add_test(tc, test_clone);
864 suite_add_tcase(s, tc);
865
866 return s;
867 }