identification_t.matches() supports multiple wildcard counts
[strongswan.git] / src / libstrongswan / utils / identification.c
1 /**
2 * @file identification.c
3 *
4 * @brief Implementation of identification_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #define _GNU_SOURCE
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 #include <string.h>
29 #include <stdio.h>
30 #include <ctype.h>
31
32 #include "definitions.h"
33 #include "identification.h"
34
35 #include <asn1/asn1.h>
36
37 /**
38 * String mappings for id_type_t.
39 */
40
41 static const char *const id_type_name[] = {
42 "ID_ANY",
43 "ID_IPV4_ADDR",
44 "ID_FQDN",
45 "ID_RFC822_ADDR",
46 "ID_IPV4_ADDR_SUBNET",
47 "ID_IPV6_ADDR",
48 "ID_IPV6_ADDR_SUBNET",
49 "ID_IPV4_ADDR_RANGE",
50 "ID_IPV6_ADDR_RANGE",
51 "ID_DER_ASN1_DN",
52 "ID_DER_ASN1_GN",
53 "ID_KEY_ID",
54 };
55
56 enum_names id_type_names =
57 { ID_ANY, ID_KEY_ID, id_type_name, NULL };
58
59 /**
60 * X.501 acronyms for well known object identifiers (OIDs)
61 */
62 static u_char oid_ND[] = {
63 0x02, 0x82, 0x06, 0x01, 0x0A, 0x07, 0x14
64 };
65 static u_char oid_UID[] = {
66 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x01
67 };
68 static u_char oid_DC[] = {
69 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19
70 };
71 static u_char oid_CN[] = {
72 0x55, 0x04, 0x03
73 };
74 static u_char oid_S[] = {
75 0x55, 0x04, 0x04
76 };
77 static u_char oid_SN[] = {
78 0x55, 0x04, 0x05
79 };
80 static u_char oid_C[] = {
81 0x55, 0x04, 0x06
82 };
83 static u_char oid_L[] = {
84 0x55, 0x04, 0x07
85 };
86 static u_char oid_ST[] = {
87 0x55, 0x04, 0x08
88 };
89 static u_char oid_O[] = {
90 0x55, 0x04, 0x0A
91 };
92 static u_char oid_OU[] = {
93 0x55, 0x04, 0x0B
94 };
95 static u_char oid_T[] = {
96 0x55, 0x04, 0x0C
97 };
98 static u_char oid_D[] = {
99 0x55, 0x04, 0x0D
100 };
101 static u_char oid_N[] = {
102 0x55, 0x04, 0x29
103 };
104 static u_char oid_G[] = {
105 0x55, 0x04, 0x2A
106 };
107 static u_char oid_I[] = {
108 0x55, 0x04, 0x2B
109 };
110 static u_char oid_ID[] = {
111 0x55, 0x04, 0x2D
112 };
113 static u_char oid_EN[] = {
114 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x42, 0x03, 0x01, 0x03
115 };
116 static u_char oid_E[] = {
117 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01
118 };
119 static u_char oid_UN[] = {
120 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x02
121 };
122 static u_char oid_TCGID[] = {
123 0x2B, 0x06, 0x01, 0x04, 0x01, 0x89, 0x31, 0x01, 0x01, 0x02, 0x02, 0x4B
124 };
125
126 /**
127 * coding of X.501 distinguished name
128 */
129 typedef struct {
130 const u_char *name;
131 chunk_t oid;
132 u_char type;
133 } x501rdn_t;
134
135 static const x501rdn_t x501rdns[] = {
136 {"ND", {oid_ND, 7}, ASN1_PRINTABLESTRING},
137 {"UID", {oid_UID, 10}, ASN1_PRINTABLESTRING},
138 {"DC", {oid_DC, 10}, ASN1_PRINTABLESTRING},
139 {"CN", {oid_CN, 3}, ASN1_PRINTABLESTRING},
140 {"S", {oid_S, 3}, ASN1_PRINTABLESTRING},
141 {"SN", {oid_SN, 3}, ASN1_PRINTABLESTRING},
142 {"serialNumber", {oid_SN, 3}, ASN1_PRINTABLESTRING},
143 {"C", {oid_C, 3}, ASN1_PRINTABLESTRING},
144 {"L", {oid_L, 3}, ASN1_PRINTABLESTRING},
145 {"ST", {oid_ST, 3}, ASN1_PRINTABLESTRING},
146 {"O", {oid_O, 3}, ASN1_PRINTABLESTRING},
147 {"OU", {oid_OU, 3}, ASN1_PRINTABLESTRING},
148 {"T", {oid_T, 3}, ASN1_PRINTABLESTRING},
149 {"D", {oid_D, 3}, ASN1_PRINTABLESTRING},
150 {"N", {oid_N, 3}, ASN1_PRINTABLESTRING},
151 {"G", {oid_G, 3}, ASN1_PRINTABLESTRING},
152 {"I", {oid_I, 3}, ASN1_PRINTABLESTRING},
153 {"ID", {oid_ID, 3}, ASN1_PRINTABLESTRING},
154 {"EN", {oid_EN, 10}, ASN1_PRINTABLESTRING},
155 {"employeeNumber", {oid_EN, 10}, ASN1_PRINTABLESTRING},
156 {"E", {oid_E, 9}, ASN1_IA5STRING},
157 {"Email", {oid_E, 9}, ASN1_IA5STRING},
158 {"emailAddress", {oid_E, 9}, ASN1_IA5STRING},
159 {"UN", {oid_UN, 9}, ASN1_IA5STRING},
160 {"unstructuredName",{oid_UN, 9}, ASN1_IA5STRING},
161 {"TCGID", {oid_TCGID, 12}, ASN1_PRINTABLESTRING}
162 };
163 #define X501_RDN_ROOF 26
164
165 /**
166 * maximum number of RDNs in atodn()
167 */
168 #define RDN_MAX 20
169
170
171 typedef struct private_identification_t private_identification_t;
172
173 /**
174 * Private data of an identification_t object.
175 */
176 struct private_identification_t {
177 /**
178 * Public interface.
179 */
180 identification_t public;
181
182 /**
183 * String representation of this ID.
184 */
185 char *string;
186
187 /**
188 * Encoded representation of this ID.
189 */
190 chunk_t encoded;
191
192 /**
193 * Type of this ID.
194 */
195 id_type_t type;
196 };
197
198 static private_identification_t *identification_create(void);
199
200 /**
201 * updates a chunk (!????)
202 * TODO: We should reconsider this stuff, its not really clear
203 */
204 static void update_chunk(chunk_t *ch, int n)
205 {
206 n = (n > -1 && n < (int)ch->len)? n : (int)ch->len-1;
207 ch->ptr += n; ch->len -= n;
208 }
209
210 /**
211 * Prints a binary string in hexadecimal form
212 */
213 void hex_str(chunk_t bin, chunk_t *str)
214 {
215 u_int i;
216 update_chunk(str, snprintf(str->ptr,str->len,"0x"));
217 for (i = 0; i < bin.len; i++)
218 {
219 update_chunk(str, snprintf(str->ptr,str->len,"%02X",*bin.ptr++));
220 }
221 }
222
223 /**
224 * Pointer is set to the first RDN in a DN
225 */
226 static status_t init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next)
227 {
228 *rdn = CHUNK_INITIALIZER;
229 *attribute = CHUNK_INITIALIZER;
230
231 /* a DN is a SEQUENCE OF RDNs */
232 if (*dn.ptr != ASN1_SEQUENCE)
233 {
234 /* DN is not a SEQUENCE */
235 return FAILED;
236 }
237
238 rdn->len = asn1_length(&dn);
239
240 if (rdn->len == ASN1_INVALID_LENGTH)
241 {
242 /* Invalid RDN length */
243 return FAILED;
244 }
245
246 rdn->ptr = dn.ptr;
247
248 /* are there any RDNs ? */
249 *next = rdn->len > 0;
250
251 return SUCCESS;
252 }
253
254 /**
255 * Fetches the next RDN in a DN
256 */
257 static status_t get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, chunk_t *value, asn1_t *type, bool *next)
258 {
259 chunk_t body;
260
261 /* initialize return values */
262 *oid = CHUNK_INITIALIZER;
263 *value = CHUNK_INITIALIZER;
264
265 /* if all attributes have been parsed, get next rdn */
266 if (attribute->len <= 0)
267 {
268 /* an RDN is a SET OF attributeTypeAndValue */
269 if (*rdn->ptr != ASN1_SET)
270 {
271 /* RDN is not a SET */
272 return FAILED;
273 }
274 attribute->len = asn1_length(rdn);
275 if (attribute->len == ASN1_INVALID_LENGTH)
276 {
277 /* Invalid attribute length */
278 return FAILED;
279 }
280 attribute->ptr = rdn->ptr;
281 /* advance to start of next RDN */
282 rdn->ptr += attribute->len;
283 rdn->len -= attribute->len;
284 }
285
286 /* an attributeTypeAndValue is a SEQUENCE */
287 if (*attribute->ptr != ASN1_SEQUENCE)
288 {
289 /* attributeTypeAndValue is not a SEQUENCE */
290 return FAILED;
291 }
292
293 /* extract the attribute body */
294 body.len = asn1_length(attribute);
295
296 if (body.len == ASN1_INVALID_LENGTH)
297 {
298 /* Invalid attribute body length */
299 return FAILED;
300 }
301
302 body.ptr = attribute->ptr;
303
304 /* advance to start of next attribute */
305 attribute->ptr += body.len;
306 attribute->len -= body.len;
307
308 /* attribute type is an OID */
309 if (*body.ptr != ASN1_OID)
310 {
311 /* attributeType is not an OID */
312 return FAILED;
313 }
314 /* extract OID */
315 oid->len = asn1_length(&body);
316
317 if (oid->len == ASN1_INVALID_LENGTH)
318 {
319 /* Invalid attribute OID length */
320 return FAILED;
321 }
322 oid->ptr = body.ptr;
323
324 /* advance to the attribute value */
325 body.ptr += oid->len;
326 body.len -= oid->len;
327
328 /* extract string type */
329 *type = *body.ptr;
330
331 /* extract string value */
332 value->len = asn1_length(&body);
333
334 if (value->len == ASN1_INVALID_LENGTH)
335 {
336 /* Invalid attribute string length */
337 return FAILED;
338 }
339 value->ptr = body.ptr;
340
341 /* are there any RDNs left? */
342 *next = rdn->len > 0 || attribute->len > 0;
343 return SUCCESS;
344 }
345
346 /**
347 * Parses an ASN.1 distinguished name int its OID/value pairs
348 */
349 static status_t dntoa(chunk_t dn, chunk_t *str)
350 {
351 chunk_t rdn, oid, attribute, value;
352 asn1_t type;
353 int oid_code;
354 bool next;
355 bool first = TRUE;
356
357 status_t status = init_rdn(dn, &rdn, &attribute, &next);
358
359 if (status != SUCCESS)
360 return status;
361
362 while (next)
363 {
364 status = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next);
365
366 if (status != SUCCESS)
367 return status;
368
369 if (first)
370 { /* first OID/value pair */
371 first = FALSE;
372 }
373 else
374 { /* separate OID/value pair by a comma */
375 update_chunk(str, snprintf(str->ptr,str->len,", "));
376 }
377
378 /* print OID */
379 oid_code = known_oid(oid);
380 if (oid_code == OID_UNKNOWN)
381 { /* OID not found in list */
382 hex_str(oid, str);
383 }
384 else
385 {
386 update_chunk(str, snprintf(str->ptr,str->len,"%s", oid_names[oid_code].name));
387 }
388 /* print value */
389 update_chunk(str, snprintf(str->ptr,str->len,"=%.*s", (int)value.len,value.ptr));
390 }
391 return SUCCESS;
392 }
393
394 /**
395 * compare two distinguished names by
396 * comparing the individual RDNs
397 */
398 static bool same_dn(chunk_t a, chunk_t b)
399 {
400 chunk_t rdn_a, rdn_b, attribute_a, attribute_b;
401 chunk_t oid_a, oid_b, value_a, value_b;
402 asn1_t type_a, type_b;
403 bool next_a, next_b;
404
405 /* same lengths for the DNs */
406 if (a.len != b.len)
407 return FALSE;
408
409 /* try a binary comparison first */
410 if (memeq(a.ptr, b.ptr, b.len))
411 return TRUE;
412
413 /* initialize DN parsing */
414 if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != SUCCESS
415 || init_rdn(b, &rdn_b, &attribute_b, &next_b) != SUCCESS)
416 {
417 return FALSE;
418 }
419
420 /* fetch next RDN pair */
421 while (next_a && next_b)
422 {
423 /* parse next RDNs and check for errors */
424 if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != SUCCESS
425 || get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != SUCCESS)
426 {
427 return FALSE;
428 }
429
430 /* OIDs must agree */
431 if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)
432 return FALSE;
433
434 /* same lengths for values */
435 if (value_a.len != value_b.len)
436 return FALSE;
437
438 /* printableStrings and email RDNs require uppercase comparison */
439 if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING
440 || (type_a == ASN1_IA5STRING && known_oid(oid_a) == OID_PKCS9_EMAIL)))
441 {
442 if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
443 return FALSE;
444 }
445 else
446 {
447 if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
448 return FALSE;
449 }
450 }
451 /* both DNs must have same number of RDNs */
452 if (next_a || next_b)
453 return FALSE;
454
455 /* the two DNs are equal! */
456 return TRUE;
457 }
458
459
460 /**
461 * compare two distinguished names by comparing the individual RDNs.
462 * A single'*' character designates a wildcard RDN in DN b.
463 * TODO: Add support for different RDN order in DN !!
464 */
465 bool match_dn(chunk_t a, chunk_t b, int *wildcards)
466 {
467 chunk_t rdn_a, rdn_b, attribute_a, attribute_b;
468 chunk_t oid_a, oid_b, value_a, value_b;
469 asn1_t type_a, type_b;
470 bool next_a, next_b;
471
472 /* initialize wildcard counter */
473 *wildcards = 0;
474
475 /* initialize DN parsing */
476 if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != SUCCESS
477 || init_rdn(b, &rdn_b, &attribute_b, &next_b) != SUCCESS)
478 {
479 return FALSE;
480 }
481
482 /* fetch next RDN pair */
483 while (next_a && next_b)
484 {
485 /* parse next RDNs and check for errors */
486 if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != SUCCESS
487 || get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != SUCCESS)
488 {
489 return FALSE;
490 }
491 /* OIDs must agree */
492 if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)
493 return FALSE;
494
495 /* does rdn_b contain a wildcard? */
496 if (value_b.len == 1 && *value_b.ptr == '*')
497 {
498 (*wildcards)++;
499 continue;
500 }
501 /* same lengths for values */
502 if (value_a.len != value_b.len)
503 return FALSE;
504
505 /* printableStrings and email RDNs require uppercase comparison */
506 if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING
507 || (type_a == ASN1_IA5STRING && known_oid(oid_a) == OID_PKCS9_EMAIL)))
508 {
509 if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
510 return FALSE;
511 }
512 else
513 {
514 if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
515 return FALSE;
516 }
517 }
518 /* both DNs must have same number of RDNs */
519 if (next_a || next_b)
520 {
521 return FALSE;
522 }
523
524 /* the two DNs match! */
525 *wildcards = min(*wildcards, MAX_WILDCARDS);
526 return TRUE;
527 }
528
529 /**
530 * Converts an LDAP-style human-readable ASCII-encoded
531 * ASN.1 distinguished name into binary DER-encoded format
532 */
533 static status_t atodn(char *src, chunk_t *dn)
534 {
535 /* finite state machine for atodn */
536 typedef enum {
537 SEARCH_OID = 0,
538 READ_OID = 1,
539 SEARCH_NAME = 2,
540 READ_NAME = 3,
541 UNKNOWN_OID = 4
542 } state_t;
543
544 chunk_t oid = CHUNK_INITIALIZER;
545 chunk_t name = CHUNK_INITIALIZER;
546 chunk_t rdns[RDN_MAX];
547 int rdn_count = 0;
548 int dn_len = 0;
549 int whitespace = 0;
550 int i;
551 asn1_t rdn_type;
552 state_t state = SEARCH_OID;
553 status_t status = SUCCESS;
554
555 do
556 {
557 switch (state)
558 {
559 case SEARCH_OID:
560 if (*src != ' ' && *src != '/' && *src != ',')
561 {
562 oid.ptr = src;
563 oid.len = 1;
564 state = READ_OID;
565 }
566 break;
567 case READ_OID:
568 if (*src != ' ' && *src != '=')
569 {
570 oid.len++;
571 }
572 else
573 {
574 for (i = 0; i < X501_RDN_ROOF; i++)
575 {
576 if (strlen(x501rdns[i].name) == oid.len
577 && strncasecmp(x501rdns[i].name, oid.ptr, oid.len) == 0)
578 {
579 break; /* found a valid OID */
580 }
581 }
582 if (i == X501_RDN_ROOF)
583 {
584 status = NOT_SUPPORTED;
585 state = UNKNOWN_OID;
586 break;
587 }
588 /* reset oid and change state */
589 oid = CHUNK_INITIALIZER;
590 state = SEARCH_NAME;
591 }
592 break;
593 case SEARCH_NAME:
594 if (*src != ' ' && *src != '=')
595 {
596 name.ptr = src;
597 name.len = 1;
598 whitespace = 0;
599 state = READ_NAME;
600 }
601 break;
602 case READ_NAME:
603 if (*src != ',' && *src != '/' && *src != '\0')
604 {
605 name.len++;
606 if (*src == ' ')
607 whitespace++;
608 else
609 whitespace = 0;
610 }
611 else
612 {
613 name.len -= whitespace;
614 rdn_type = (x501rdns[i].type == ASN1_PRINTABLESTRING
615 && !is_printablestring(name))? ASN1_T61STRING : x501rdns[i].type;
616
617 if (rdn_count < RDN_MAX)
618 {
619 rdns[rdn_count] =
620 asn1_wrap(ASN1_SET, "m",
621 asn1_wrap(ASN1_SEQUENCE, "mm",
622 asn1_wrap(ASN1_OID, "c", x501rdns[i].oid),
623 asn1_wrap(rdn_type, "c", name)
624 )
625 );
626 dn_len += rdns[rdn_count++].len;
627 }
628 else
629 {
630 status = OUT_OF_RES;
631 }
632 /* reset name and change state */
633 name = CHUNK_INITIALIZER;
634 state = SEARCH_OID;
635 }
636 break;
637 case UNKNOWN_OID:
638 break;
639 }
640 } while (*src++ != '\0');
641
642 /* build the distinguished name sequence */
643 {
644 int i;
645 u_char *pos = build_asn1_object(dn, ASN1_SEQUENCE, dn_len);
646
647 for (i = 0; i < rdn_count; i++)
648 {
649 memcpy(pos, rdns[i].ptr, rdns[i].len);
650 pos += rdns[i].len;
651 free(rdns[i].ptr);
652 }
653 }
654
655 if (status != SUCCESS)
656 {
657 free(dn->ptr);
658 *dn = CHUNK_INITIALIZER;
659 }
660 return status;
661 }
662
663 /**
664 * Implementation of identification_t.get_encoding.
665 */
666 static chunk_t get_encoding(private_identification_t *this)
667 {
668 return this->encoded;
669 }
670
671 /**
672 * Implementation of identification_t.get_type.
673 */
674 static id_type_t get_type(private_identification_t *this)
675 {
676 return this->type;
677 }
678
679 /**
680 * Implementation of identification_t.get_string.
681 */
682 static char *get_string(private_identification_t *this)
683 {
684 return this->string;
685 }
686
687 /**
688 * Implementation of identification_t.contains_wildcards.
689 */
690 static bool contains_wildcards(private_identification_t *this)
691 {
692 return this->type == ID_ANY || strchr(this->string, '*') != NULL;
693 }
694
695 /**
696 * Default implementation of identification_t.equals.
697 * compares encoded chunk for equality.
698 */
699 static bool equals_binary(private_identification_t *this, private_identification_t *other)
700 {
701 return this->type == other->type && chunk_equals(this->encoded, other->encoded);
702 }
703
704 /**
705 * Special implementation of identification_t.equals for ID_DER_ASN1_DN.
706 */
707 static bool equals_dn(private_identification_t *this, private_identification_t *other)
708 {
709 return same_dn(this->encoded, other->encoded);
710 }
711
712 /**
713 * Default implementation of identification_t.matches.
714 */
715 static bool matches_binary(private_identification_t *this, private_identification_t *other,
716 int *wildcards)
717 {
718 *wildcards = 0;
719 return this->type == other->type && chunk_equals(this->encoded, other->encoded);
720 }
721
722 /**
723 * Special implementation of identification_t.matches for ID_RFC822_ADDR/ID_FQDN.
724 * Checks for a wildcard in other-string, and compares it against this-string.
725 */
726 static bool matches_string(private_identification_t *this, private_identification_t *other,
727 int *wildcards)
728 {
729 u_int len = other->encoded.len;
730
731 if (other->type == ID_ANY)
732 {
733 *wildcards = MAX_WILDCARDS;
734 return TRUE;
735 }
736
737 if (this->type != other->type)
738 return FALSE;
739
740 /* try a binary comparison first */
741 if (equals_binary(this, other))
742 {
743 *wildcards = 0;
744 return TRUE;
745 }
746
747 if (len == 0 || this->encoded.len < len)
748 return FALSE;
749
750 /* check for single wildcard at the head of the string */
751 if (*other->encoded.ptr == '*')
752 {
753 *wildcards = 1;
754
755 /* single asterisk matches any string */
756 if (len-- == 1)
757 return TRUE;
758
759 if (memeq(this->encoded.ptr + this->encoded.len - len, other->encoded.ptr + 1, len))
760 return TRUE;
761 }
762
763 return FALSE;
764 }
765
766 /**
767 * Special implementation of identification_t.matches for ID_ANY.
768 * ANY matches only another ANY, but nothing other
769 */
770 static bool matches_any(private_identification_t *this, private_identification_t *other,
771 int *wildcards)
772 {
773 *wildcards = 0;
774 return other->type == ID_ANY;
775 }
776
777 /**
778 * Special implementation of identification_t.matches for ID_DER_ASN1_DN.
779 * ANY matches any, even ANY, thats why its there...
780 */
781 static bool matches_dn(private_identification_t *this, private_identification_t *other,
782 int *wildcards)
783 {
784 if (other->type == ID_ANY)
785 {
786 *wildcards = MAX_WILDCARDS;
787 return TRUE;
788 }
789
790 if (this->type == other->type)
791 {
792 return match_dn(this->encoded, other->encoded, wildcards);
793 }
794 return FALSE;
795 }
796
797 /**
798 * Implementation of identification_t.clone.
799 */
800 static identification_t *clone(private_identification_t *this)
801 {
802 private_identification_t *clone = identification_create();
803
804 clone->type = this->type;
805 clone->encoded = chunk_clone(this->encoded);
806 clone->string = malloc(strlen(this->string) + 1);
807 strcpy(clone->string, this->string);
808
809 clone->public.equals = this->public.equals;
810 clone->public.matches = this->public.matches;
811
812 return &clone->public;
813 }
814
815 /**
816 * Implementation of identification_t.destroy.
817 */
818 static void destroy(private_identification_t *this)
819 {
820 free(this->string);
821 free(this->encoded.ptr);
822 free(this);
823 }
824
825 /**
826 * Generic constructor used for the other constructors.
827 */
828 static private_identification_t *identification_create(void)
829 {
830 private_identification_t *this = malloc_thing(private_identification_t);
831
832 this->public.get_encoding = (chunk_t (*) (identification_t*))get_encoding;
833 this->public.get_type = (id_type_t (*) (identification_t*))get_type;
834 this->public.get_string = (char* (*) (identification_t*))get_string;
835 this->public.contains_wildcards = (bool (*) (identification_t *this))contains_wildcards;
836 this->public.clone = (identification_t* (*) (identification_t*))clone;
837 this->public.destroy = (void (*) (identification_t*))destroy;
838 /* we use these as defaults, the may be overloaded for special ID types */
839 this->public.equals = (bool (*) (identification_t*,identification_t*))equals_binary;
840 this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_binary;
841
842 this->string = NULL;
843 this->encoded = CHUNK_INITIALIZER;
844
845 return this;
846 }
847
848 /*
849 * Described in header.
850 */
851 identification_t *identification_create_from_string(char *string)
852 {
853 private_identification_t *this = identification_create();
854
855 if (string == NULL)
856 string = "%any";
857
858 if (strchr(string, '=') != NULL)
859 {
860 /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
861 * convert from LDAP style or openssl x509 -subject style to ASN.1 DN
862 */
863 if (atodn(string, &this->encoded) != SUCCESS)
864 {
865 free(this);
866 return NULL;
867 }
868 this->string = strdup(string);
869 this->type = ID_DER_ASN1_DN;
870 this->public.equals = (bool (*) (identification_t*,identification_t*))equals_dn;
871 this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_dn;
872 return &this->public;
873 }
874 else if (strchr(string, '@') == NULL)
875 {
876 if (streq(string, "%any")
877 || streq(string, "0.0.0.0")
878 || streq(string, "*")
879 || streq(string, "::")
880 || streq(string, "0::0"))
881 {
882 /* any ID will be accepted */
883 this->type = ID_ANY;
884 this->string = strdup("%any");
885 this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_any;
886 return &this->public;
887 }
888 else
889 {
890 if (strchr(string, ':') == NULL)
891 {
892 /* try IPv4 */
893 struct in_addr address;
894 chunk_t chunk = {(void*)&address, sizeof(address)};
895
896 if (inet_pton(AF_INET, string, &address) <= 0)
897 {
898 free(this);
899 return NULL;
900 }
901 this->encoded = chunk_clone(chunk);
902 this->string = strdup(string);
903 this->type = ID_IPV4_ADDR;
904 return &(this->public);
905 }
906 else
907 {
908 /* try IPv6 */
909 struct in6_addr address;
910 chunk_t chunk = {(void*)&address, sizeof(address)};
911
912 if (inet_pton(AF_INET6, string, &address) <= 0)
913 {
914 free(this);
915 return NULL;
916 }
917 this->encoded = chunk_clone(chunk);
918 this->string = strdup(string);
919 this->type = ID_IPV6_ADDR;
920 return &(this->public);
921 }
922 }
923 }
924 else
925 {
926 if (*string == '@')
927 {
928 if (*(string + 1) == '#')
929 {
930 /* TODO: Pluto handles '#' as hex encoded ID_KEY_ID. */
931 free(this);
932 return NULL;
933 }
934 else
935 {
936 this->type = ID_FQDN;
937 this->string = strdup(string);
938 this->encoded.ptr = strdup(string + 1);
939 this->encoded.len = strlen(string + 1);
940 this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_string;
941 return &(this->public);
942 }
943 }
944 else
945 {
946 this->type = ID_RFC822_ADDR;
947 this->string = strdup(string);
948 this->encoded.ptr = strdup(string);
949 this->encoded.len = strlen(string);
950 this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_string;
951 return &(this->public);
952 }
953 }
954 }
955
956 /*
957 * Described in header.
958 */
959 identification_t *identification_create_from_encoding(id_type_t type, chunk_t encoded)
960 {
961 char *pos;
962 char buf[BUF_LEN];
963 chunk_t buf_chunk = chunk_from_buf(buf);
964 private_identification_t *this = identification_create();
965
966 this->type = type;
967
968 switch (type)
969 {
970 case ID_ANY:
971 this->string = strdup("%any");
972 this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_any;
973 break;
974 case ID_IPV4_ADDR:
975 if (encoded.len < sizeof(struct in_addr) ||
976 inet_ntop(AF_INET, encoded.ptr, buf, sizeof(buf)) == NULL)
977 {
978 this->string = strdup("(invalid ID_IPV4_ADDR)");
979 }
980 else
981 {
982 this->string = strdup(buf);
983 }
984 break;
985 case ID_IPV6_ADDR:
986 if (encoded.len < sizeof(struct in6_addr) ||
987 inet_ntop(AF_INET6, encoded.ptr, buf, INET6_ADDRSTRLEN) == NULL)
988 {
989 this->string = strdup("(invalid ID_IPV6_ADDR)");
990 }
991 else
992 {
993 this->string = strdup(buf);
994 }
995 break;
996 case ID_FQDN:
997 snprintf(buf, sizeof(buf), "@%.*s", encoded.len, encoded.ptr);
998 this->string = strdup(buf);
999 this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_string;
1000 break;
1001 case ID_RFC822_ADDR:
1002 snprintf(buf, sizeof(buf), "%.*s", encoded.len, encoded.ptr);
1003 this->string = strdup(buf);
1004 this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_string;
1005 break;
1006 case ID_DER_ASN1_DN:
1007 snprintf(buf, sizeof(buf), "%.*s", encoded.len, encoded.ptr);
1008 /* TODO: whats returned on failure */
1009 dntoa(encoded, &buf_chunk);
1010 this->string = strdup(buf);
1011 this->public.equals = (bool (*) (identification_t*,identification_t*))equals_dn;
1012 this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_dn;
1013 break;
1014 case ID_DER_ASN1_GN:
1015 this->string = strdup("ASN.1 coded generalName");
1016 break;
1017 case ID_KEY_ID:
1018 this->string = strdup("(KEY_ID)");
1019 break;
1020 case ID_DER_ASN1_GN_URI:
1021 snprintf(buf, sizeof(buf), "%.*s", encoded.len, encoded.ptr);
1022 this->string = strdup(buf);
1023 break;
1024 default:
1025 snprintf(buf, sizeof(buf), "(invalid ID type: %d)", type);
1026 this->string = strdup(buf);
1027 break;
1028 }
1029
1030 /* apply encoded chunk */
1031 if (type != ID_ANY)
1032 {
1033 this->encoded = chunk_clone(encoded);
1034 }
1035
1036 /* remove unprintable chars in string */
1037 for (pos = this->string; *pos != '\0'; pos++)
1038 {
1039 if (!isprint(*pos))
1040 {
1041 *pos = '?';
1042 }
1043 }
1044 return &(this->public);
1045 }