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