1dc6776d162169bb88282b469e43f58d52c162f7
[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 };
178
179 START_TEST(test_from_string)
180 {
181 identification_t *a;
182 chunk_t encoding, expected;
183 char *id;
184
185 id = string_data[_i].id;
186 a = identification_create_from_string(id);
187 fail_unless(a->get_type(a) == string_data[_i].type,
188 "type of id '%s' is %N, %N expected", id,
189 id_type_names, a->get_type(a),
190 id_type_names, string_data[_i].type);
191
192 encoding = a->get_encoding(a);
193 switch (string_data[_i].result.type)
194 {
195 case ENC_SIMPLE:
196 expected = chunk_from_str(string_data[_i].id);
197 break;
198 case ENC_STRING:
199 expected = chunk_from_str(string_data[_i].result.data.s);
200 break;
201 case ENC_CHUNK:
202 expected = string_data[_i].result.data.c;
203 break;
204 default:
205 fail("unexpected result type");
206 }
207
208 ck_assert(!id || (char*)encoding.ptr != id);
209 if (expected.ptr)
210 {
211 fail_unless(chunk_equals(encoding, expected),
212 "parsing '%s' failed\nencoding %B\nexpected %B\n",
213 id, &encoding, &expected);
214 }
215 else
216 {
217 ck_assert(encoding.ptr == NULL);
218 ck_assert(encoding.len == 0);
219 }
220 a->destroy(a);
221 }
222 END_TEST
223
224 /*******************************************************************************
225 * printf_hook
226 */
227
228 static void string_equals(char *a_str, char *b_str)
229 {
230 identification_t *b;
231 char buf[128];
232
233 b = b_str ? identification_create_from_string(b_str) : NULL;
234 snprintf(buf, sizeof(buf), "%Y", b);
235 DESTROY_IF(b);
236 ck_assert_str_eq(a_str, buf);
237 }
238
239 static void string_equals_id(char *a_str, identification_t *b)
240 {
241 char buf[128];
242
243 snprintf(buf, sizeof(buf), "%Y", b);
244 DESTROY_IF(b);
245 ck_assert_str_eq(a_str, buf);
246 }
247
248 START_TEST(test_printf_hook)
249 {
250 string_equals("(null)", NULL);
251 string_equals("%any", "");
252 string_equals("%any", "%any");
253 string_equals("%any", "*");
254
255 string_equals("192.168.1.1", "192.168.1.1");
256 string_equals_id("(invalid ID_IPV4_ADDR)",
257 identification_create_from_encoding(ID_IPV4_ADDR, chunk_empty));
258 string_equals("fec0::1", "fec0::1");
259 string_equals("fec0::1", "fec0:0:0::1");
260 string_equals_id("(invalid ID_IPV6_ADDR)",
261 identification_create_from_encoding(ID_IPV6_ADDR, chunk_empty));
262
263 string_equals_id("(unknown ID type: 255)",
264 identification_create_from_encoding(255, chunk_empty));
265
266 string_equals("moon@strongswan.org", "moon@strongswan.org");
267 string_equals("MOON@STRONGSWAN.ORG", "MOON@STRONGSWAN.ORG");
268 /* non-printable characters */
269 string_equals_id("????@strongswan.org", identification_create_from_encoding(ID_RFC822_ADDR,
270 chunk_from_chars(0xfa, 0xfb, 0xfc, 0xfd, 0x40, 0x73, 0x74, 0x72,
271 0x6f, 0x6e, 0x67, 0x73, 0x77, 0x61, 0x6e, 0x2e,
272 0x6f, 0x72, 0x67)));
273
274 /* not a DN => ID_KEY_ID => no normalization */
275 string_equals("C=CH, AsdF=asdf", "C=CH, AsdF=asdf");
276 string_equals_id("moon@strongswan.org", identification_create_from_encoding(ID_KEY_ID,
277 chunk_from_str("moon@strongswan.org")));
278 /* non-printable characters */
279 string_equals_id("de:ad:be:ef", identification_create_from_encoding(ID_KEY_ID,
280 chunk_from_chars(0xde, 0xad, 0xbe, 0xef)));
281 /* printable characters */
282 string_equals_id("ABCDEFGHIJKLMNOPQRS",
283 identification_create_from_encoding(ID_KEY_ID,
284 chunk_from_chars(0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
285 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
286 0x51, 0x52, 0x53)));
287 /* ABCDEFGHIJKLMNOPQRST is printable but has the length of a SHA1 hash */
288 string_equals_id("41:42:43:44:45:46:47:48:49:4a:4b:4c:4d:4e:4f:50:51:52:53:54",
289 identification_create_from_encoding(ID_KEY_ID,
290 chunk_from_chars(0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
291 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
292 0x51, 0x52, 0x53, 0x54)));
293
294 string_equals_id("", identification_create_from_encoding(ID_DER_ASN1_DN, chunk_empty));
295 string_equals("C=", "C=");
296 string_equals("C=", "C=,");
297 string_equals("C=", "C=, ");
298 string_equals("C=", "C= , ");
299 string_equals("C=, O=strongSwan", "C=, O=strongSwan");
300 string_equals("C=CH, O=", "C=CH, O=");
301 string_equals("C=CH, O=strongSwan, CN=strongswan.org",
302 "C=CH, O=strongSwan, CN=strongswan.org");
303 string_equals("CN=strongswan.org, O=strongSwan, C=CH",
304 "cn=strongswan.org, o=strongSwan, c=CH");
305 string_equals("C=CH, O=strongSwan, CN=strongswan.org",
306 "C=CH,O=strongSwan,CN=strongswan.org");
307 string_equals("C=CH, O=strongSwan, CN=strongswan.org",
308 "/C=CH/O=strongSwan/CN=strongswan.org");
309 string_equals("CN=strongswan.org, O=strongSwan, C=CH",
310 "CN=strongswan.org,O=strongSwan,C=CH");
311
312 string_equals("C=CH, E=moon@strongswan.org, CN=moon",
313 "C=CH, email=moon@strongswan.org, CN=moon");
314 string_equals("C=CH, E=moon@strongswan.org, CN=moon",
315 "C=CH, emailAddress=moon@strongswan.org, CN=moon");
316
317 /* C=CH, pseudonym=ANO (pseudonym is currently not recognized) */
318 string_equals_id("C=CH, 55:04:41=ANO", identification_create_from_encoding(ID_DER_ASN1_DN,
319 chunk_from_chars(0x30, 0x19, 0x31, 0x17, 0x30, 0x09, 0x06, 0x03, 0x55,
320 0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x30, 0x0a, 0x06,
321 0x03, 0x55, 0x04, 0x41, 0x13, 0x03, 0x41, 0x4e, 0x4f)));
322 /* C=CH, O=strongSwan (but instead of a 2nd OID -0x06- we got NULL -0x05) */
323 string_equals_id("C=CH, (invalid ID_DER_ASN1_DN)", identification_create_from_encoding(ID_DER_ASN1_DN,
324 chunk_from_chars(0x30, 0x20, 0x31, 0x1e, 0x30, 0x09, 0x06, 0x03, 0x55,
325 0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x30, 0x11, 0x05,
326 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x73, 0x74, 0x72,
327 0x6f, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x6e)));
328 /* moon@strongswan.org as GN */
329 string_equals_id("(ASN.1 general name)", identification_create_from_encoding(ID_DER_ASN1_GN,
330 chunk_from_chars(0x81, 0x14, 0x6d, 0x6f, 0x6f, 0x6e, 0x40, 0x73, 0x74,
331 0x72, 0x6f, 0x6e, 0x67, 0x73, 0x77, 0x61, 0x6e, 0x2e,
332 0x6f, 0x72, 0x67)));
333 }
334 END_TEST
335
336 START_TEST(test_printf_hook_width)
337 {
338 identification_t *a;
339 char buf[128];
340
341 a = identification_create_from_string("moon@strongswan.org");
342 snprintf(buf, sizeof(buf), "%25Y", a);
343 ck_assert_str_eq(" moon@strongswan.org", buf);
344 snprintf(buf, sizeof(buf), "%-*Y", 25, a);
345 ck_assert_str_eq("moon@strongswan.org ", buf);
346 snprintf(buf, sizeof(buf), "%5Y", a);
347 ck_assert_str_eq("moon@strongswan.org", buf);
348 DESTROY_IF(a);
349 }
350 END_TEST
351
352 /*******************************************************************************
353 * equals
354 */
355
356 static bool id_equals(identification_t *a, char *b_str)
357 {
358 identification_t *b;
359 bool equals;
360
361 b = identification_create_from_string(b_str);
362 equals = a->equals(a, b);
363 ck_assert_int_eq(equals, b->equals(b, a));
364 b->destroy(b);
365 return equals;
366 }
367
368 START_TEST(test_equals)
369 {
370 identification_t *a;
371 chunk_t encoding, fuzzed;
372 int i;
373
374 /* this test also tests identification_create_from_string with DNs */
375 a = identification_create_from_string(
376 "C=CH, E=moon@strongswan.org, CN=moon");
377
378 ck_assert(id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"));
379 ck_assert(id_equals(a, "C==CH, E==moon@strongswan.org,,, CN==moon"));
380 ck_assert(id_equals(a, " C=CH, E=moon@strongswan.org, CN=moon "));
381 ck_assert(id_equals(a, "C=ch, E=moon@STRONGSWAN.ORG, CN=Moon"));
382 ck_assert(id_equals(a, "/C=CH/E=moon@strongswan.org/CN=moon"));
383 ck_assert(id_equals(a, "C=CH/E=moon@strongswan.org/CN=moon"));
384 ck_assert(id_equals(a, "C=CH/E=moon@strongswan.org,CN=moon"));
385 ck_assert(id_equals(a, "C=CH / E=moon@strongswan.org , CN=moon"));
386
387 ck_assert(!id_equals(a, "C=CH E=moon@strongswan.org CN=moon"));
388 ck_assert(!id_equals(a, "C=CN, E=moon@strongswan.org, CN=moon"));
389 ck_assert(!id_equals(a, "E=moon@strongswan.org, C=CH, CN=moon"));
390 ck_assert(!id_equals(a, "E=moon@strongswan.org, C=CH, CN=moon"));
391
392 encoding = chunk_clone(a->get_encoding(a));
393 a->destroy(a);
394
395 /* simple fuzzing, increment each byte of encoding */
396 for (i = 0; i < encoding.len; i++)
397 {
398 if (i == 11 || i == 30 || i == 60)
399 { /* skip ASN.1 type fields, as equals() handles them graceful */
400 continue;
401 }
402 fuzzed = chunk_clone(encoding);
403 fuzzed.ptr[i]++;
404 a = identification_create_from_encoding(ID_DER_ASN1_DN, fuzzed);
405 if (id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"))
406 {
407 printf("%d %B\n%B\n", i, &fuzzed, &encoding);
408 }
409 ck_assert(!id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"));
410 a->destroy(a);
411 free(fuzzed.ptr);
412 }
413
414 /* and decrement each byte of encoding */
415 for (i = 0; i < encoding.len; i++)
416 {
417 if (i == 11 || i == 30 || i == 60)
418 {
419 continue;
420 }
421 fuzzed = chunk_clone(encoding);
422 fuzzed.ptr[i]--;
423 a = identification_create_from_encoding(ID_DER_ASN1_DN, fuzzed);
424 ck_assert(!id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"));
425 a->destroy(a);
426 free(fuzzed.ptr);
427 }
428 free(encoding.ptr);
429 }
430 END_TEST
431
432 START_TEST(test_equals_any)
433 {
434 identification_t *a, *b;
435
436 a = identification_create_from_string("%any");
437 b = identification_create_from_encoding(ID_ANY, chunk_empty);
438 ck_assert(a->equals(a, b));
439 ck_assert(b->equals(b, a));
440 b->destroy(b);
441
442 b = identification_create_from_string("C=CH, O=strongSwan, CN=strongswan.org");
443 ck_assert(!a->equals(a, b));
444 ck_assert(!b->equals(b, a));
445 a->destroy(a);
446 b->destroy(b);
447 }
448 END_TEST
449
450 START_TEST(test_equals_binary)
451 {
452 identification_t *a, *b;
453 chunk_t encoding;
454
455 encoding = chunk_from_str("foobar=");
456 /* strings containing = are parsed as KEY_ID if they aren't valid ASN.1 DNs */
457 a = identification_create_from_string("foobar=");
458 ck_assert(a->get_type(a) == ID_KEY_ID);
459 b = identification_create_from_encoding(ID_KEY_ID, encoding);
460 ck_assert(a->equals(a, b));
461 a->destroy(a);
462 b->destroy(b);
463 }
464 END_TEST
465
466 START_TEST(test_equals_fqdn)
467 {
468 identification_t *a;
469
470 a = identification_create_from_string("ipsec.strongswan.org");
471 ck_assert(id_equals(a, "IPSEC.strongswan.org"));
472 ck_assert(id_equals(a, "ipsec.strongSwan.org"));
473 ck_assert(id_equals(a, "ipsec.strongSwan.ORG"));
474 ck_assert(!id_equals(a, "strongswan.org"));
475 a->destroy(a);
476 }
477 END_TEST
478
479 START_TEST(test_equals_empty)
480 {
481 identification_t *a;
482
483 a = identification_create_from_encoding(_i, chunk_empty);
484
485 switch (_i)
486 {
487 case ID_ANY:
488 ck_assert(id_equals(a, "%any"));
489 break;
490 case ID_IPV4_ADDR:
491 ck_assert(!id_equals(a, "192.168.1.1"));
492 break;
493 case ID_FQDN:
494 ck_assert(!id_equals(a, "moon.strongswan.org"));
495 break;
496 case ID_USER_FQDN:
497 ck_assert(!id_equals(a, "moon@strongswan.org"));
498 break;
499 case ID_IPV6_ADDR:
500 ck_assert(!id_equals(a, "fec0::1"));
501 break;
502 case ID_DER_ASN1_DN:
503 ck_assert(!id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"));
504 break;
505 case ID_KEY_ID:
506 ck_assert(!id_equals(a, "@#12345678"));
507 break;
508 case ID_DER_ASN1_GN:
509 case ID_IPV4_ADDR_SUBNET:
510 case ID_IPV6_ADDR_SUBNET:
511 case ID_IPV4_ADDR_RANGE:
512 case ID_IPV6_ADDR_RANGE:
513 /* currently not tested */
514 break;
515 }
516
517 a->destroy(a);
518 }
519 END_TEST
520
521 /*******************************************************************************
522 * matches
523 */
524
525 static bool id_matches(identification_t *a, char *b_str, id_match_t expected)
526 {
527 identification_t *b;
528 id_match_t match;
529
530 b = identification_create_from_string(b_str);
531 match = a->matches(a, b);
532 b->destroy(b);
533 return match == expected;
534 }
535
536 START_TEST(test_matches)
537 {
538 identification_t *a;
539
540 a = identification_create_from_string("C=CH, E=moon@strongswan.org, CN=moon");
541
542 ck_assert(id_matches(a, "C=CH, E=moon@strongswan.org, CN=moon", ID_MATCH_PERFECT));
543 ck_assert(id_matches(a, "C=CH, E=*, CN=moon", ID_MATCH_ONE_WILDCARD));
544 ck_assert(id_matches(a, "C=CH, E=*, CN=*", ID_MATCH_ONE_WILDCARD - 1));
545 ck_assert(id_matches(a, "C=*, E=*, CN=*", ID_MATCH_ONE_WILDCARD - 2));
546 ck_assert(id_matches(a, "C=*, E=*, CN=*, O=BADInc", ID_MATCH_NONE));
547 ck_assert(id_matches(a, "C=*, E=*", ID_MATCH_NONE));
548 ck_assert(id_matches(a, "C=*, E=a@b.c, CN=*", ID_MATCH_NONE));
549 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
550
551 a->destroy(a);
552 }
553 END_TEST
554
555 START_TEST(test_matches_any)
556 {
557 identification_t *a;
558
559 a = identification_create_from_string("%any");
560
561 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
562 ck_assert(id_matches(a, "", ID_MATCH_ANY));
563 ck_assert(id_matches(a, "*", ID_MATCH_ANY));
564 ck_assert(id_matches(a, "moon@strongswan.org", ID_MATCH_NONE));
565 ck_assert(id_matches(a, "vpn.strongswan.org", ID_MATCH_NONE));
566 a->destroy(a);
567 }
568 END_TEST
569
570 START_TEST(test_matches_binary)
571 {
572 identification_t *a;
573
574 /* strings containing = are parsed as KEY_ID if they aren't valid ASN.1 DNs */
575 a = identification_create_from_string("foo=bar");
576 ck_assert(a->get_type(a) == ID_KEY_ID);
577 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
578 ck_assert(id_matches(a, "foo=bar", ID_MATCH_PERFECT));
579 ck_assert(id_matches(a, "bar=foo", ID_MATCH_NONE));
580 ck_assert(id_matches(a, "*=bar", ID_MATCH_NONE));
581 ck_assert(id_matches(a, "foo=*", ID_MATCH_NONE));
582 ck_assert(id_matches(a, "foo@bar", ID_MATCH_NONE));
583 a->destroy(a);
584 }
585 END_TEST
586
587 START_TEST(test_matches_string)
588 {
589 identification_t *a;
590
591 a = identification_create_from_string("moon@strongswan.org");
592
593 ck_assert(id_matches(a, "moon@strongswan.org", ID_MATCH_PERFECT));
594 ck_assert(id_matches(a, "*@strongswan.org", ID_MATCH_ONE_WILDCARD));
595 ck_assert(id_matches(a, "*@*.org", ID_MATCH_NONE));
596 ck_assert(id_matches(a, "*@*", ID_MATCH_NONE));
597 /* the following two are parsed as ID_FQDN, so no match */
598 ck_assert(id_matches(a, "*strongswan.org", ID_MATCH_NONE));
599 ck_assert(id_matches(a, "*.org", ID_MATCH_NONE));
600 ck_assert(id_matches(a, "moon@*", ID_MATCH_NONE));
601 ck_assert(id_matches(a, "**", ID_MATCH_NONE));
602 ck_assert(id_matches(a, "*", ID_MATCH_ANY));
603 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
604 a->destroy(a);
605
606 a = identification_create_from_string("vpn.strongswan.org");
607
608 ck_assert(id_matches(a, "vpn.strongswan.org", ID_MATCH_PERFECT));
609 ck_assert(id_matches(a, "*.strongswan.org", ID_MATCH_ONE_WILDCARD));
610 ck_assert(id_matches(a, "*strongswan.org", ID_MATCH_ONE_WILDCARD));
611 ck_assert(id_matches(a, "*.org", ID_MATCH_ONE_WILDCARD));
612 ck_assert(id_matches(a, "*.strongswan.*", ID_MATCH_NONE));
613 ck_assert(id_matches(a, "*vpn.strongswan.org", ID_MATCH_NONE));
614 ck_assert(id_matches(a, "vpn.strongswan.*", ID_MATCH_NONE));
615 ck_assert(id_matches(a, "**", ID_MATCH_NONE));
616 ck_assert(id_matches(a, "*", ID_MATCH_ANY));
617 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
618 a->destroy(a);
619 }
620 END_TEST
621
622 START_TEST(test_matches_empty)
623 {
624 identification_t *a;
625
626 a = identification_create_from_encoding(_i, chunk_empty);
627
628 switch (_i)
629 {
630 case ID_ANY:
631 ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
632 break;
633 case ID_IPV4_ADDR:
634 ck_assert(id_matches(a, "192.168.1.1", ID_MATCH_NONE));
635 break;
636 case ID_FQDN:
637 ck_assert(id_matches(a, "moon.strongswan.org", ID_MATCH_NONE));
638 break;
639 case ID_USER_FQDN:
640 ck_assert(id_matches(a, "moon@strongswan.org", ID_MATCH_NONE));
641 break;
642 case ID_IPV6_ADDR:
643 ck_assert(id_matches(a, "fec0::1", ID_MATCH_NONE));
644 break;
645 case ID_DER_ASN1_DN:
646 ck_assert(id_matches(a, "C=CH, E=moon@strongswan.org, CN=moon",
647 ID_MATCH_NONE));
648 break;
649 case ID_KEY_ID:
650 ck_assert(id_matches(a, "@#12345678", ID_MATCH_NONE));
651 break;
652 case ID_DER_ASN1_GN:
653 case ID_IPV4_ADDR_SUBNET:
654 case ID_IPV6_ADDR_SUBNET:
655 case ID_IPV4_ADDR_RANGE:
656 case ID_IPV6_ADDR_RANGE:
657 /* currently not tested */
658 break;
659 }
660
661 a->destroy(a);
662 }
663 END_TEST
664
665 static bool id_matches_rev(identification_t *a, char *b_str, id_match_t expected)
666 {
667 identification_t *b;
668 id_match_t match;
669
670 b = identification_create_from_string(b_str);
671 match = b->matches(b, a);
672 b->destroy(b);
673 return match == expected;
674 }
675
676 START_TEST(test_matches_empty_reverse)
677 {
678 identification_t *a;
679
680 a = identification_create_from_encoding(_i, chunk_empty);
681
682 switch (_i)
683 {
684 case ID_ANY:
685 ck_assert(id_matches_rev(a, "%any", ID_MATCH_ANY));
686 break;
687 case ID_IPV4_ADDR:
688 ck_assert(id_matches_rev(a, "192.168.1.1", ID_MATCH_NONE));
689 break;
690 case ID_FQDN:
691 ck_assert(id_matches_rev(a, "moon.strongswan.org", ID_MATCH_NONE));
692 break;
693 case ID_USER_FQDN:
694 ck_assert(id_matches_rev(a, "moon@strongswan.org", ID_MATCH_NONE));
695 break;
696 case ID_IPV6_ADDR:
697 ck_assert(id_matches_rev(a, "fec0::1", ID_MATCH_NONE));
698 break;
699 case ID_DER_ASN1_DN:
700 ck_assert(id_matches_rev(a, "C=CH, E=moon@strongswan.org, CN=moon",
701 ID_MATCH_NONE));
702 break;
703 case ID_KEY_ID:
704 ck_assert(id_matches_rev(a, "@#12345678", ID_MATCH_NONE));
705 break;
706 case ID_DER_ASN1_GN:
707 case ID_IPV4_ADDR_SUBNET:
708 case ID_IPV6_ADDR_SUBNET:
709 case ID_IPV4_ADDR_RANGE:
710 case ID_IPV6_ADDR_RANGE:
711 /* currently not tested */
712 break;
713 }
714
715 a->destroy(a);
716 }
717 END_TEST
718
719 /*******************************************************************************
720 * identification part enumeration
721 */
722
723 START_TEST(test_parts)
724 {
725 identification_t *id;
726 enumerator_t *enumerator;
727 id_part_t part;
728 chunk_t data;
729 int i = 0;
730
731 id = identification_create_from_string("C=CH, O=strongSwan, CN=tester");
732
733 enumerator = id->create_part_enumerator(id);
734 while (enumerator->enumerate(enumerator, &part, &data))
735 {
736 switch (i++)
737 {
738 case 0:
739 ck_assert(part == ID_PART_RDN_C &&
740 chunk_equals(data, chunk_create("CH", 2)));
741 break;
742 case 1:
743 ck_assert(part == ID_PART_RDN_O &&
744 chunk_equals(data, chunk_from_str("strongSwan")));
745 break;
746 case 2:
747 ck_assert(part == ID_PART_RDN_CN &&
748 chunk_equals(data, chunk_from_str("tester")));
749 break;
750 default:
751 fail("unexpected identification part %d", part);
752 }
753 }
754 ck_assert_int_eq(i, 3);
755 enumerator->destroy(enumerator);
756 id->destroy(id);
757 }
758 END_TEST
759
760 /*******************************************************************************
761 * wildcards
762 */
763
764 static bool id_contains_wildcards(char *string)
765 {
766 identification_t *id;
767 bool contains;
768
769 id = identification_create_from_string(string);
770 contains = id->contains_wildcards(id);
771 id->destroy(id);
772 return contains;
773 }
774
775 START_TEST(test_contains_wildcards)
776 {
777 ck_assert(id_contains_wildcards("%any"));
778 ck_assert(id_contains_wildcards("C=*, O=strongSwan, CN=gw"));
779 ck_assert(id_contains_wildcards("C=CH, O=strongSwan, CN=*"));
780 ck_assert(id_contains_wildcards("*@strongswan.org"));
781 ck_assert(id_contains_wildcards("*.strongswan.org"));
782 ck_assert(!id_contains_wildcards("C=**, O=a*, CN=*a"));
783 }
784 END_TEST
785
786 /*******************************************************************************
787 * clone
788 */
789
790 START_TEST(test_clone)
791 {
792 identification_t *a, *b;
793 chunk_t a_enc, b_enc;
794
795 a = identification_create_from_string("moon@strongswan.org");
796 a_enc = a->get_encoding(a);
797 b = a->clone(a);
798 ck_assert(b != NULL);
799 ck_assert(a != b);
800 b_enc = b->get_encoding(b);
801 ck_assert(a_enc.ptr != b_enc.ptr);
802 ck_assert(chunk_equals(a_enc, b_enc));
803 a->destroy(a);
804 b->destroy(b);
805 }
806 END_TEST
807
808 Suite *identification_suite_create()
809 {
810 Suite *s;
811 TCase *tc;
812
813 s = suite_create("identification");
814
815 tc = tcase_create("create");
816 tcase_add_test(tc, test_from_encoding);
817 tcase_add_test(tc, test_from_data);
818 tcase_add_test(tc, test_from_sockaddr);
819 tcase_add_loop_test(tc, test_from_string, 0, countof(string_data));
820 suite_add_tcase(s, tc);
821
822 tc = tcase_create("printf_hook");
823 tcase_add_test(tc, test_printf_hook);
824 tcase_add_test(tc, test_printf_hook_width);
825 suite_add_tcase(s, tc);
826
827 tc = tcase_create("equals");
828 tcase_add_test(tc, test_equals);
829 tcase_add_test(tc, test_equals_any);
830 tcase_add_test(tc, test_equals_binary);
831 tcase_add_test(tc, test_equals_fqdn);
832 tcase_add_loop_test(tc, test_equals_empty, ID_ANY, ID_KEY_ID + 1);
833 suite_add_tcase(s, tc);
834
835 tc = tcase_create("matches");
836 tcase_add_test(tc, test_matches);
837 tcase_add_test(tc, test_matches_any);
838 tcase_add_test(tc, test_matches_binary);
839 tcase_add_test(tc, test_matches_string);
840 tcase_add_loop_test(tc, test_matches_empty, ID_ANY, ID_KEY_ID + 1);
841 tcase_add_loop_test(tc, test_matches_empty_reverse, ID_ANY, ID_KEY_ID + 1);
842 suite_add_tcase(s, tc);
843
844 tc = tcase_create("part enumeration");
845 tcase_add_test(tc, test_parts);
846 suite_add_tcase(s, tc);
847
848 tc = tcase_create("wildcards");
849 tcase_add_test(tc, test_contains_wildcards);
850 suite_add_tcase(s, tc);
851
852 tc = tcase_create("clone");
853 tcase_add_test(tc, test_clone);
854 suite_add_tcase(s, tc);
855
856 return s;
857 }