446c01492dd135e4afd04ebe88eb94d8762902de
[strongswan.git] / src / libstrongswan / utils / identification.c
1 /*
2 * Copyright (C) 2009 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #define _GNU_SOURCE
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <ctype.h>
25
26 #include "identification.h"
27
28 #include <asn1/oid.h>
29 #include <asn1/asn1.h>
30
31 ENUM_BEGIN(id_match_names, ID_MATCH_NONE, ID_MATCH_MAX_WILDCARDS,
32 "MATCH_NONE",
33 "MATCH_ANY",
34 "MATCH_MAX_WILDCARDS");
35 ENUM_NEXT(id_match_names, ID_MATCH_PERFECT, ID_MATCH_PERFECT, ID_MATCH_MAX_WILDCARDS,
36 "MATCH_PERFECT");
37 ENUM_END(id_match_names, ID_MATCH_PERFECT);
38
39 ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID,
40 "ID_ANY",
41 "ID_IPV4_ADDR",
42 "ID_FQDN",
43 "ID_RFC822_ADDR",
44 "ID_IPV4_ADDR_SUBNET",
45 "ID_IPV6_ADDR",
46 "ID_IPV6_ADDR_SUBNET",
47 "ID_IPV4_ADDR_RANGE",
48 "ID_IPV6_ADDR_RANGE",
49 "ID_DER_ASN1_DN",
50 "ID_DER_ASN1_GN",
51 "ID_KEY_ID");
52 ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_CERT_DER_SHA1, ID_KEY_ID,
53 "ID_DER_ASN1_GN_URI",
54 "ID_PUBKEY_INFO_SHA1",
55 "ID_PUBKEY_SHA1",
56 "ID_CERT_DER_SHA1");
57 ENUM_END(id_type_names, ID_CERT_DER_SHA1);
58
59 /**
60 * coding of X.501 distinguished name
61 */
62 typedef struct {
63 const u_char *name;
64 int oid;
65 u_char type;
66 } x501rdn_t;
67
68 static const x501rdn_t x501rdns[] = {
69 {"ND", OID_NAME_DISTINGUISHER, ASN1_PRINTABLESTRING},
70 {"UID", OID_PILOT_USERID, ASN1_PRINTABLESTRING},
71 {"DC", OID_PILOT_DOMAIN_COMPONENT, ASN1_PRINTABLESTRING},
72 {"CN", OID_COMMON_NAME, ASN1_PRINTABLESTRING},
73 {"S", OID_SURNAME, ASN1_PRINTABLESTRING},
74 {"SN", OID_SERIAL_NUMBER, ASN1_PRINTABLESTRING},
75 {"serialNumber", OID_SERIAL_NUMBER, ASN1_PRINTABLESTRING},
76 {"C", OID_COUNTRY, ASN1_PRINTABLESTRING},
77 {"L", OID_LOCALITY, ASN1_PRINTABLESTRING},
78 {"ST", OID_STATE_OR_PROVINCE, ASN1_PRINTABLESTRING},
79 {"O", OID_ORGANIZATION, ASN1_PRINTABLESTRING},
80 {"OU", OID_ORGANIZATION_UNIT, ASN1_PRINTABLESTRING},
81 {"T", OID_TITLE, ASN1_PRINTABLESTRING},
82 {"D", OID_DESCRIPTION, ASN1_PRINTABLESTRING},
83 {"N", OID_NAME, ASN1_PRINTABLESTRING},
84 {"G", OID_GIVEN_NAME, ASN1_PRINTABLESTRING},
85 {"I", OID_INITIALS, ASN1_PRINTABLESTRING},
86 {"ID", OID_UNIQUE_IDENTIFIER, ASN1_PRINTABLESTRING},
87 {"EN", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING},
88 {"employeeNumber", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING},
89 {"E", OID_EMAIL_ADDRESS, ASN1_IA5STRING},
90 {"Email", OID_EMAIL_ADDRESS, ASN1_IA5STRING},
91 {"emailAddress", OID_EMAIL_ADDRESS, ASN1_IA5STRING},
92 {"UN", OID_UNSTRUCTURED_NAME, ASN1_IA5STRING},
93 {"unstructuredName",OID_UNSTRUCTURED_NAME, ASN1_IA5STRING},
94 {"TCGID", OID_TCGID, ASN1_PRINTABLESTRING}
95 };
96
97 /**
98 * maximum number of RDNs in atodn()
99 */
100 #define RDN_MAX 20
101
102
103 typedef struct private_identification_t private_identification_t;
104
105 /**
106 * Private data of an identification_t object.
107 */
108 struct private_identification_t {
109 /**
110 * Public interface.
111 */
112 identification_t public;
113
114 /**
115 * Encoded representation of this ID.
116 */
117 chunk_t encoded;
118
119 /**
120 * Type of this ID.
121 */
122 id_type_t type;
123 };
124
125 /**
126 * Enumerator over RDNs
127 */
128 typedef struct {
129 /* implements enumerator interface */
130 enumerator_t public;
131 /* RDNs left to parse */
132 chunk_t left;
133 } rdn_enumerator_t;
134
135 /**
136 * Implementation of rdn_enumerator_t.enumerate
137 */
138 static bool rdn_enumerate(rdn_enumerator_t *this, chunk_t *oid,
139 u_char *type, chunk_t *data)
140 {
141 chunk_t rdn;
142
143 /* a RDN is a SET of attribute-values, each is a SEQUENCE ... */
144 if (asn1_unwrap(&this->left, &rdn) == ASN1_SET &&
145 asn1_unwrap(&rdn, &rdn) == ASN1_SEQUENCE)
146 {
147 /* ... of an OID */
148 if (asn1_unwrap(&rdn, oid) == ASN1_OID)
149 {
150 /* and a specific string type */
151 *type = asn1_unwrap(&rdn, data);
152 if (*type != ASN1_INVALID)
153 {
154 return TRUE;
155 }
156 }
157 }
158 return FALSE;
159 }
160
161 /**
162 * Create an enumerator over all RDNs (oid, string type, data) of a DN
163 */
164 static enumerator_t* create_rdn_enumerator(chunk_t dn)
165 {
166 rdn_enumerator_t *e = malloc_thing(rdn_enumerator_t);
167
168 e->public.enumerate = (void*)rdn_enumerate;
169 e->public.destroy = (void*)free;
170
171 /* a DN is a sequence of RDNs */
172 if (asn1_unwrap(&dn, &e->left) == ASN1_SEQUENCE)
173 {
174 return &e->public;
175 }
176 free(e);
177 return enumerator_create_empty();
178 }
179
180 /**
181 * Part enumerator over RDNs
182 */
183 typedef struct {
184 /* implements enumerator interface */
185 enumerator_t public;
186 /* inner RDN enumerator */
187 enumerator_t *inner;
188 } rdn_part_enumerator_t;
189
190 /**
191 * Implementation of rdn_part_enumerator_t.enumerate().
192 */
193 static bool rdn_part_enumerate(rdn_part_enumerator_t *this,
194 id_part_t *type, chunk_t *data)
195 {
196 int i, known_oid, strtype;
197 chunk_t oid, inner_data;
198 static const struct {
199 int oid;
200 id_part_t type;
201 } oid2part[] = {
202 {OID_COMMON_NAME, ID_PART_RDN_CN},
203 {OID_SURNAME, ID_PART_RDN_S},
204 {OID_SERIAL_NUMBER, ID_PART_RDN_SN},
205 {OID_COUNTRY, ID_PART_RDN_C},
206 {OID_LOCALITY, ID_PART_RDN_L},
207 {OID_STATE_OR_PROVINCE, ID_PART_RDN_ST},
208 {OID_ORGANIZATION, ID_PART_RDN_O},
209 {OID_ORGANIZATION_UNIT, ID_PART_RDN_OU},
210 {OID_TITLE, ID_PART_RDN_T},
211 {OID_DESCRIPTION, ID_PART_RDN_D},
212 {OID_NAME, ID_PART_RDN_N},
213 {OID_GIVEN_NAME, ID_PART_RDN_G},
214 {OID_INITIALS, ID_PART_RDN_I},
215 {OID_UNIQUE_IDENTIFIER, ID_PART_RDN_ID},
216 {OID_EMAIL_ADDRESS, ID_PART_RDN_E},
217 {OID_EMPLOYEE_NUMBER, ID_PART_RDN_EN},
218 };
219
220 while (this->inner->enumerate(this->inner, &oid, &strtype, &inner_data))
221 {
222 known_oid = asn1_known_oid(oid);
223 for (i = 0; i < countof(oid2part); i++)
224 {
225 if (oid2part[i].oid == known_oid)
226 {
227 *type = oid2part[i].type;
228 *data = inner_data;
229 return TRUE;
230 }
231 }
232 }
233 return FALSE;
234 }
235
236 /**
237 * Implementation of rdn_part_enumerator_t.destroy().
238 */
239 static void rdn_part_enumerator_destroy(rdn_part_enumerator_t *this)
240 {
241 this->inner->destroy(this->inner);
242 free(this);
243 }
244
245 /**
246 * Implementation of identification_t.create_part_enumerator
247 */
248 static enumerator_t* create_part_enumerator(private_identification_t *this)
249 {
250 switch (this->type)
251 {
252 case ID_DER_ASN1_DN:
253 {
254 rdn_part_enumerator_t *e = malloc_thing(rdn_part_enumerator_t);
255
256 e->inner = create_rdn_enumerator(this->encoded);
257 e->public.enumerate = (void*)rdn_part_enumerate;
258 e->public.destroy = (void*)rdn_part_enumerator_destroy;
259
260 return &e->public;
261 }
262 case ID_RFC822_ADDR:
263 /* TODO */
264 case ID_FQDN:
265 /* TODO */
266 default:
267 return enumerator_create_empty();
268 }
269 }
270
271 /**
272 * updates a chunk (!????)
273 * TODO: We should reconsider this stuff, its not really clear
274 */
275 static void update_chunk(chunk_t *ch, int n)
276 {
277 n = (n > -1 && n < (int)ch->len)? n : (int)ch->len-1;
278 ch->ptr += n; ch->len -= n;
279 }
280
281 /**
282 * Remove any malicious characters from a chunk. We are very restrictive, but
283 * whe use these strings only to present it to the user.
284 */
285 static bool sanitize_chunk(chunk_t chunk, chunk_t *clone)
286 {
287 char *pos;
288 bool all_printable = TRUE;
289
290 *clone = chunk_clone(chunk);
291
292 for (pos = clone->ptr; pos < (char*)(clone->ptr + clone->len); pos++)
293 {
294 if (!isprint(*pos))
295 {
296 *pos = '?';
297 all_printable = FALSE;
298 }
299 }
300 return all_printable;
301 }
302
303 /**
304 * Pointer is set to the first RDN in a DN
305 */
306 static bool init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next)
307 {
308 *rdn = chunk_empty;
309 *attribute = chunk_empty;
310
311 /* a DN is a SEQUENCE OF RDNs */
312 if (*dn.ptr != ASN1_SEQUENCE)
313 {
314 /* DN is not a SEQUENCE */
315 return FALSE;
316 }
317
318 rdn->len = asn1_length(&dn);
319
320 if (rdn->len == ASN1_INVALID_LENGTH)
321 {
322 /* Invalid RDN length */
323 return FALSE;
324 }
325
326 rdn->ptr = dn.ptr;
327
328 /* are there any RDNs ? */
329 *next = rdn->len > 0;
330
331 return TRUE;
332 }
333
334 /**
335 * Fetches the next RDN in a DN
336 */
337 static bool get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid,
338 chunk_t *value, asn1_t *type, bool *next)
339 {
340 chunk_t body;
341
342 /* initialize return values */
343 *oid = chunk_empty;
344 *value = chunk_empty;
345
346 /* if all attributes have been parsed, get next rdn */
347 if (attribute->len <= 0)
348 {
349 /* an RDN is a SET OF attributeTypeAndValue */
350 if (*rdn->ptr != ASN1_SET)
351 {
352 /* RDN is not a SET */
353 return FALSE;
354 }
355 attribute->len = asn1_length(rdn);
356 if (attribute->len == ASN1_INVALID_LENGTH)
357 {
358 /* Invalid attribute length */
359 return FALSE;
360 }
361 attribute->ptr = rdn->ptr;
362 /* advance to start of next RDN */
363 rdn->ptr += attribute->len;
364 rdn->len -= attribute->len;
365 }
366
367 /* an attributeTypeAndValue is a SEQUENCE */
368 if (*attribute->ptr != ASN1_SEQUENCE)
369 {
370 /* attributeTypeAndValue is not a SEQUENCE */
371 return FALSE;
372 }
373
374 /* extract the attribute body */
375 body.len = asn1_length(attribute);
376
377 if (body.len == ASN1_INVALID_LENGTH)
378 {
379 /* Invalid attribute body length */
380 return FALSE;
381 }
382
383 body.ptr = attribute->ptr;
384
385 /* advance to start of next attribute */
386 attribute->ptr += body.len;
387 attribute->len -= body.len;
388
389 /* attribute type is an OID */
390 if (*body.ptr != ASN1_OID)
391 {
392 /* attributeType is not an OID */
393 return FALSE;
394 }
395 /* extract OID */
396 oid->len = asn1_length(&body);
397
398 if (oid->len == ASN1_INVALID_LENGTH)
399 {
400 /* Invalid attribute OID length */
401 return FALSE;
402 }
403 oid->ptr = body.ptr;
404
405 /* advance to the attribute value */
406 body.ptr += oid->len;
407 body.len -= oid->len;
408
409 /* extract string type */
410 *type = *body.ptr;
411
412 /* extract string value */
413 value->len = asn1_length(&body);
414
415 if (value->len == ASN1_INVALID_LENGTH)
416 {
417 /* Invalid attribute string length */
418 return FALSE;
419 }
420 value->ptr = body.ptr;
421
422 /* are there any RDNs left? */
423 *next = rdn->len > 0 || attribute->len > 0;
424 return TRUE;
425 }
426
427 /**
428 * Parses an ASN.1 distinguished name int its OID/value pairs
429 */
430 static bool dntoa(chunk_t dn, chunk_t *str)
431 {
432 chunk_t rdn, oid, attribute, value, proper;
433 asn1_t type;
434 int oid_code;
435 bool next;
436 bool first = TRUE;
437
438 if (!init_rdn(dn, &rdn, &attribute, &next))
439 {
440 return FALSE;
441 }
442
443 while (next)
444 {
445 if (!get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next))
446 {
447 return FALSE;
448 }
449
450 if (first)
451 { /* first OID/value pair */
452 first = FALSE;
453 }
454 else
455 { /* separate OID/value pair by a comma */
456 update_chunk(str, snprintf(str->ptr,str->len,", "));
457 }
458
459 /* print OID */
460 oid_code = asn1_known_oid(oid);
461 if (oid_code == OID_UNKNOWN)
462 {
463 update_chunk(str, snprintf(str->ptr,str->len,"0x#B", &oid));
464 }
465 else
466 {
467 update_chunk(str, snprintf(str->ptr,str->len,"%s", oid_names[oid_code].name));
468 }
469 /* print value */
470 sanitize_chunk(value, &proper);
471 update_chunk(str, snprintf(str->ptr,str->len,"=%.*s", (int)proper.len, proper.ptr));
472 chunk_free(&proper);
473 }
474 return TRUE;
475 }
476
477 /**
478 * Converts an LDAP-style human-readable ASCII-encoded
479 * ASN.1 distinguished name into binary DER-encoded format
480 */
481 static status_t atodn(char *src, chunk_t *dn)
482 {
483 /* finite state machine for atodn */
484 typedef enum {
485 SEARCH_OID = 0,
486 READ_OID = 1,
487 SEARCH_NAME = 2,
488 READ_NAME = 3,
489 UNKNOWN_OID = 4
490 } state_t;
491
492 chunk_t oid = chunk_empty;
493 chunk_t name = chunk_empty;
494 chunk_t rdns[RDN_MAX];
495 int rdn_count = 0;
496 int dn_len = 0;
497 int whitespace = 0;
498 int i = 0;
499 asn1_t rdn_type;
500 state_t state = SEARCH_OID;
501 status_t status = SUCCESS;
502
503 do
504 {
505 switch (state)
506 {
507 case SEARCH_OID:
508 if (*src != ' ' && *src != '/' && *src != ',')
509 {
510 oid.ptr = src;
511 oid.len = 1;
512 state = READ_OID;
513 }
514 break;
515 case READ_OID:
516 if (*src != ' ' && *src != '=')
517 {
518 oid.len++;
519 }
520 else
521 {
522 bool found = FALSE;
523
524 for (i = 0; i < countof(x501rdns); i++)
525 {
526 if (strlen(x501rdns[i].name) == oid.len &&
527 strncasecmp(x501rdns[i].name, oid.ptr, oid.len) == 0)
528 {
529 found = TRUE;
530 break;
531 }
532 }
533 if (!found)
534 {
535 status = NOT_SUPPORTED;
536 state = UNKNOWN_OID;
537 break;
538 }
539 /* reset oid and change state */
540 oid = chunk_empty;
541 state = SEARCH_NAME;
542 }
543 break;
544 case SEARCH_NAME:
545 if (*src != ' ' && *src != '=')
546 {
547 name.ptr = src;
548 name.len = 1;
549 whitespace = 0;
550 state = READ_NAME;
551 }
552 break;
553 case READ_NAME:
554 if (*src != ',' && *src != '/' && *src != '\0')
555 {
556 name.len++;
557 if (*src == ' ')
558 whitespace++;
559 else
560 whitespace = 0;
561 }
562 else
563 {
564 name.len -= whitespace;
565 rdn_type = (x501rdns[i].type == ASN1_PRINTABLESTRING
566 && !asn1_is_printablestring(name))
567 ? ASN1_T61STRING : x501rdns[i].type;
568
569 if (rdn_count < RDN_MAX)
570 {
571 chunk_t rdn_oid;
572
573 rdn_oid = asn1_build_known_oid(x501rdns[i].oid);
574 if (rdn_oid.len)
575 {
576 rdns[rdn_count] =
577 asn1_wrap(ASN1_SET, "m",
578 asn1_wrap(ASN1_SEQUENCE, "mm",
579 rdn_oid,
580 asn1_wrap(rdn_type, "c", name)
581 )
582 );
583 dn_len += rdns[rdn_count++].len;
584 }
585 else
586 {
587 status = INVALID_ARG;
588 }
589 }
590 else
591 {
592 status = OUT_OF_RES;
593 }
594 /* reset name and change state */
595 name = chunk_empty;
596 state = SEARCH_OID;
597 }
598 break;
599 case UNKNOWN_OID:
600 break;
601 }
602 } while (*src++ != '\0');
603
604 /* build the distinguished name sequence */
605 {
606 int i;
607 u_char *pos = asn1_build_object(dn, ASN1_SEQUENCE, dn_len);
608
609 for (i = 0; i < rdn_count; i++)
610 {
611 memcpy(pos, rdns[i].ptr, rdns[i].len);
612 pos += rdns[i].len;
613 free(rdns[i].ptr);
614 }
615 }
616
617 if (status != SUCCESS)
618 {
619 free(dn->ptr);
620 *dn = chunk_empty;
621 }
622 return status;
623 }
624
625 /**
626 * Implementation of identification_t.get_encoding.
627 */
628 static chunk_t get_encoding(private_identification_t *this)
629 {
630 return this->encoded;
631 }
632
633 /**
634 * Implementation of identification_t.get_type.
635 */
636 static id_type_t get_type(private_identification_t *this)
637 {
638 return this->type;
639 }
640
641 /**
642 * Implementation of identification_t.contains_wildcards fro ID_DER_ASN1_DN.
643 */
644 static bool contains_wildcards_dn(private_identification_t *this)
645 {
646 enumerator_t *enumerator;
647 bool contains = FALSE;
648 id_part_t type;
649 chunk_t data;
650
651 enumerator = create_part_enumerator(this);
652 while (enumerator->enumerate(enumerator, &type, &data))
653 {
654 if (data.len == 1 && data.ptr[0] == '*')
655 {
656 contains = TRUE;
657 break;
658 }
659 }
660 enumerator->destroy(enumerator);
661 return contains;
662 }
663
664 /**
665 * Implementation of identification_t.contains_wildcards.
666 */
667 static bool contains_wildcards(private_identification_t *this)
668 {
669 switch (this->type)
670 {
671 case ID_ANY:
672 return TRUE;
673 case ID_FQDN:
674 case ID_RFC822_ADDR:
675 return memchr(this->encoded.ptr, '*', this->encoded.len) != NULL;
676 case ID_DER_ASN1_DN:
677 return contains_wildcards_dn(this);
678 default:
679 return FALSE;
680 }
681 }
682
683 /**
684 * Default implementation of identification_t.equals.
685 * compares encoded chunk for equality.
686 */
687 static bool equals_binary(private_identification_t *this, private_identification_t *other)
688 {
689 if (this->type == other->type)
690 {
691 if (this->type == ID_ANY)
692 {
693 return TRUE;
694 }
695 return chunk_equals(this->encoded, other->encoded);
696 }
697 return FALSE;
698 }
699
700 /**
701 * Compare to DNs, for equality if wc == NULL, for match otherwise
702 */
703 static bool compare_dn(chunk_t t_dn, chunk_t o_dn, int *wc)
704 {
705 enumerator_t *t, *o;
706 chunk_t t_oid, o_oid, t_data, o_data;
707 u_char t_type, o_type;
708 bool t_next, o_next, finished = FALSE;
709
710 if (wc)
711 {
712 *wc = 0;
713 }
714 else
715 {
716 if (t_dn.len != o_dn.len)
717 {
718 return FALSE;
719 }
720 }
721 /* try a binary compare */
722 if (memeq(t_dn.ptr, o_dn.ptr, t_dn.len))
723 {
724 return TRUE;
725 }
726
727 t = create_rdn_enumerator(t_dn);
728 o = create_rdn_enumerator(o_dn);
729 while (TRUE)
730 {
731 t_next = t->enumerate(t, &t_oid, &t_type, &t_data);
732 o_next = o->enumerate(o, &o_oid, &o_type, &o_data);
733
734 if (!o_next && !t_next)
735 {
736 break;
737 }
738 finished = FALSE;
739 if (o_next != t_next)
740 {
741 break;
742 }
743 if (!chunk_equals(t_oid, o_oid))
744 {
745 break;
746 }
747 if (wc && o_data.len == 1 && o_data.ptr[0] == '*')
748 {
749 (*wc)++;
750 }
751 else
752 {
753 if (t_data.len != o_data.len)
754 {
755 break;
756 }
757 if (t_type == o_type &&
758 (t_type == ASN1_PRINTABLESTRING ||
759 (t_type == ASN1_IA5STRING &&
760 (asn1_known_oid(t_oid) == OID_PKCS9_EMAIL ||
761 asn1_known_oid(t_oid) == OID_EMAIL_ADDRESS))))
762 { /* ignore case for printableStrings and email RDNs */
763 if (strncasecmp(t_data.ptr, o_data.ptr, t_data.len) != 0)
764 {
765 break;
766 }
767 }
768 else
769 { /* respect case and length for everything else */
770 if (!memeq(t_data.ptr, o_data.ptr, t_data.len))
771 {
772 break;
773 }
774 }
775 }
776 /* the enumerator returns FALSE on parse error, we are finished
777 * if we have reached the end of the DN only */
778 if ((t_data.ptr + t_data.len == t_dn.ptr + t_dn.len) &&
779 (o_data.ptr + o_data.len == o_dn.ptr + o_dn.len))
780 {
781 finished = TRUE;
782 }
783 }
784 t->destroy(t);
785 o->destroy(o);
786 return finished;
787 }
788
789 /**
790 * Special implementation of identification_t.equals for ID_DER_ASN1_DN.
791 */
792 static bool equals_dn(private_identification_t *this,
793 private_identification_t *other)
794 {
795 return compare_dn(this->encoded, other->encoded, NULL);
796 }
797
798 /**
799 * Special implementation of identification_t.equals for RFC822 and FQDN.
800 */
801 static bool equals_strcasecmp(private_identification_t *this,
802 private_identification_t *other)
803 {
804 /* we do some extra sanity checks to check for invalid IDs with a
805 * terminating null in it. */
806 if (this->encoded.len == other->encoded.len &&
807 memchr(this->encoded.ptr, 0, this->encoded.len) == NULL &&
808 memchr(other->encoded.ptr, 0, other->encoded.len) == NULL &&
809 strncasecmp(this->encoded.ptr, other->encoded.ptr, this->encoded.len) == 0)
810 {
811 return TRUE;
812 }
813 return FALSE;
814 }
815
816 /**
817 * Default implementation of identification_t.matches.
818 */
819 static id_match_t matches_binary(private_identification_t *this,
820 private_identification_t *other)
821 {
822 if (other->type == ID_ANY)
823 {
824 return ID_MATCH_ANY;
825 }
826 if (this->type == other->type &&
827 chunk_equals(this->encoded, other->encoded))
828 {
829 return ID_MATCH_PERFECT;
830 }
831 return ID_MATCH_NONE;
832 }
833
834 /**
835 * Special implementation of identification_t.matches for ID_RFC822_ADDR/ID_FQDN.
836 * Checks for a wildcard in other-string, and compares it against this-string.
837 */
838 static id_match_t matches_string(private_identification_t *this,
839 private_identification_t *other)
840 {
841 u_int len = other->encoded.len;
842
843 if (other->type == ID_ANY)
844 {
845 return ID_MATCH_ANY;
846 }
847 if (this->type != other->type)
848 {
849 return ID_MATCH_NONE;
850 }
851 /* try a equals check first */
852 if (equals_strcasecmp(this, other))
853 {
854 return ID_MATCH_PERFECT;
855 }
856 if (len == 0 || this->encoded.len < len)
857 {
858 return ID_MATCH_NONE;
859 }
860
861 /* check for single wildcard at the head of the string */
862 if (*other->encoded.ptr == '*')
863 {
864 /* single asterisk matches any string */
865 if (len-- == 1)
866 { /* not better than ID_ANY */
867 return ID_MATCH_ANY;
868 }
869 if (strncasecmp(this->encoded.ptr + this->encoded.len - len,
870 other->encoded.ptr + 1, len) == 0)
871 {
872 return ID_MATCH_ONE_WILDCARD;
873 }
874 }
875 return ID_MATCH_NONE;
876 }
877
878 /**
879 * Special implementation of identification_t.matches for ID_ANY.
880 * ANY matches only another ANY, but nothing other
881 */
882 static id_match_t matches_any(private_identification_t *this,
883 private_identification_t *other)
884 {
885 if (other->type == ID_ANY)
886 {
887 return ID_MATCH_ANY;
888 }
889 return ID_MATCH_NONE;
890 }
891
892 /**
893 * Special implementation of identification_t.matches for ID_DER_ASN1_DN
894 */
895 static id_match_t matches_dn(private_identification_t *this,
896 private_identification_t *other)
897 {
898 int wc;
899
900 if (other->type == ID_ANY)
901 {
902 return ID_MATCH_ANY;
903 }
904
905 if (this->type == other->type)
906 {
907 if (compare_dn(this->encoded, other->encoded, &wc))
908 {
909 wc = min(wc, ID_MATCH_ONE_WILDCARD - ID_MATCH_MAX_WILDCARDS);
910 return ID_MATCH_PERFECT - wc;
911 }
912 }
913 return ID_MATCH_NONE;
914 }
915
916 /**
917 * Described in header.
918 */
919 int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
920 const void *const *args)
921 {
922 private_identification_t *this = *((private_identification_t**)(args[0]));
923 char buf[BUF_LEN];
924 chunk_t proper, buf_chunk = chunk_from_buf(buf);
925
926 if (this == NULL)
927 {
928 return print_in_hook(dst, len, "%*s", spec->width, "(null)");
929 }
930
931 switch (this->type)
932 {
933 case ID_ANY:
934 snprintf(buf, sizeof(buf), "%%any");
935 break;
936 case ID_IPV4_ADDR:
937 if (this->encoded.len < sizeof(struct in_addr) ||
938 inet_ntop(AF_INET, this->encoded.ptr, buf, sizeof(buf)) == NULL)
939 {
940 snprintf(buf, sizeof(buf), "(invalid ID_IPV4_ADDR)");
941 }
942 break;
943 case ID_IPV6_ADDR:
944 if (this->encoded.len < sizeof(struct in6_addr) ||
945 inet_ntop(AF_INET6, this->encoded.ptr, buf, INET6_ADDRSTRLEN) == NULL)
946 {
947 snprintf(buf, sizeof(buf), "(invalid ID_IPV6_ADDR)");
948 }
949 break;
950 case ID_FQDN:
951 case ID_RFC822_ADDR:
952 case ID_DER_ASN1_GN_URI:
953 case ID_IETF_ATTR_STRING:
954 sanitize_chunk(this->encoded, &proper);
955 snprintf(buf, sizeof(buf), "%.*s", proper.len, proper.ptr);
956 chunk_free(&proper);
957 break;
958 case ID_DER_ASN1_DN:
959 if (!dntoa(this->encoded, &buf_chunk))
960 {
961 snprintf(buf, sizeof(buf), "(invalid ID_DER_ASN1_DN)");
962 }
963 break;
964 case ID_DER_ASN1_GN:
965 snprintf(buf, sizeof(buf), "(ASN.1 general Name");
966 break;
967 case ID_KEY_ID:
968 if (sanitize_chunk(this->encoded, &proper))
969 { /* fully printable, use ascii version */
970 snprintf(buf, sizeof(buf), "%.*s", proper.len, proper.ptr);
971 }
972 else
973 { /* not printable, hex dump */
974 snprintf(buf, sizeof(buf), "%#B", &this->encoded);
975 }
976 chunk_free(&proper);
977 break;
978 case ID_PUBKEY_INFO_SHA1:
979 case ID_PUBKEY_SHA1:
980 case ID_CERT_DER_SHA1:
981 snprintf(buf, sizeof(buf), "%#B", &this->encoded);
982 break;
983 default:
984 snprintf(buf, sizeof(buf), "(unknown ID type: %d)", this->type);
985 break;
986 }
987 if (spec->minus)
988 {
989 return print_in_hook(dst, len, "%-*s", spec->width, buf);
990 }
991 return print_in_hook(dst, len, "%*s", spec->width, buf);
992 }
993 /**
994 * Implementation of identification_t.clone.
995 */
996 static identification_t *clone_(private_identification_t *this)
997 {
998 private_identification_t *clone = malloc_thing(private_identification_t);
999
1000 memcpy(clone, this, sizeof(private_identification_t));
1001 if (this->encoded.len)
1002 {
1003 clone->encoded = chunk_clone(this->encoded);
1004 }
1005 return &clone->public;
1006 }
1007
1008 /**
1009 * Implementation of identification_t.destroy.
1010 */
1011 static void destroy(private_identification_t *this)
1012 {
1013 chunk_free(&this->encoded);
1014 free(this);
1015 }
1016
1017 /**
1018 * Generic constructor used for the other constructors.
1019 */
1020 static private_identification_t *identification_create(void)
1021 {
1022 private_identification_t *this = malloc_thing(private_identification_t);
1023
1024 this->public.get_encoding = (chunk_t (*) (identification_t*))get_encoding;
1025 this->public.get_type = (id_type_t (*) (identification_t*))get_type;
1026 this->public.contains_wildcards = (bool (*) (identification_t *this))contains_wildcards;
1027 this->public.create_part_enumerator = (enumerator_t*(*)(identification_t*))create_part_enumerator;
1028 this->public.clone = (identification_t* (*) (identification_t*))clone_;
1029 this->public.destroy = (void (*) (identification_t*))destroy;
1030 /* we use these as defaults, the may be overloaded for special ID types */
1031 this->public.equals = (bool (*) (identification_t*,identification_t*))equals_binary;
1032 this->public.matches = (id_match_t (*) (identification_t*,identification_t*))matches_binary;
1033
1034 this->encoded = chunk_empty;
1035
1036 return this;
1037 }
1038
1039 /*
1040 * Described in header.
1041 */
1042 identification_t *identification_create_from_string(char *string)
1043 {
1044 private_identification_t *this = identification_create();
1045
1046 if (string == NULL)
1047 {
1048 string = "%any";
1049 }
1050 if (strchr(string, '=') != NULL)
1051 {
1052 /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
1053 * convert from LDAP style or openssl x509 -subject style to ASN.1 DN
1054 */
1055 if (atodn(string, &this->encoded) != SUCCESS)
1056 {
1057 this->type = ID_KEY_ID;
1058 this->encoded = chunk_clone(chunk_create(string, strlen(string)));
1059 return &this->public;
1060 }
1061 this->type = ID_DER_ASN1_DN;
1062 this->public.equals = (bool (*) (identification_t*,identification_t*))equals_dn;
1063 this->public.matches = (id_match_t (*) (identification_t*,identification_t*))matches_dn;
1064 return &this->public;
1065 }
1066 else if (strchr(string, '@') == NULL)
1067 {
1068 if (streq(string, "%any")
1069 || streq(string, "%any6")
1070 || streq(string, "0.0.0.0")
1071 || streq(string, "*")
1072 || streq(string, "::")
1073 || streq(string, "0::0"))
1074 {
1075 /* any ID will be accepted */
1076 this->type = ID_ANY;
1077 this->public.matches = (id_match_t (*)
1078 (identification_t*,identification_t*))matches_any;
1079 return &this->public;
1080 }
1081 else
1082 {
1083 if (strchr(string, ':') == NULL)
1084 {
1085 /* try IPv4 */
1086 struct in_addr address;
1087 chunk_t chunk = {(void*)&address, sizeof(address)};
1088
1089 if (inet_pton(AF_INET, string, &address) <= 0)
1090 {
1091 /* not IPv4, mostly FQDN */
1092 this->type = ID_FQDN;
1093 this->encoded.ptr = strdup(string);
1094 this->encoded.len = strlen(string);
1095 this->public.matches = (id_match_t (*)
1096 (identification_t*,identification_t*))matches_string;
1097 this->public.equals = (bool (*)
1098 (identification_t*,identification_t*))equals_strcasecmp;
1099 return &this->public;
1100 }
1101 this->encoded = chunk_clone(chunk);
1102 this->type = ID_IPV4_ADDR;
1103 return &this->public;
1104 }
1105 else
1106 {
1107 /* try IPv6 */
1108 struct in6_addr address;
1109 chunk_t chunk = {(void*)&address, sizeof(address)};
1110
1111 if (inet_pton(AF_INET6, string, &address) <= 0)
1112 {
1113 this->type = ID_KEY_ID;
1114 this->encoded = chunk_clone(chunk_create(string,
1115 strlen(string)));
1116 return &this->public;
1117 }
1118 this->encoded = chunk_clone(chunk);
1119 this->type = ID_IPV6_ADDR;
1120 return &this->public;
1121 }
1122 }
1123 }
1124 else
1125 {
1126 if (*string == '@')
1127 {
1128 if (*(string + 1) == '#')
1129 {
1130 string += 2;
1131 this->type = ID_KEY_ID;
1132 this->encoded = chunk_from_hex(
1133 chunk_create(string, strlen(string)), NULL);
1134 return &this->public;
1135 }
1136 else
1137 {
1138 this->type = ID_FQDN;
1139 this->encoded.ptr = strdup(string + 1);
1140 this->encoded.len = strlen(string + 1);
1141 this->public.matches = (id_match_t (*)
1142 (identification_t*,identification_t*))matches_string;
1143 this->public.equals = (bool (*)
1144 (identification_t*,identification_t*))equals_strcasecmp;
1145 return &this->public;
1146 }
1147 }
1148 else
1149 {
1150 this->type = ID_RFC822_ADDR;
1151 this->encoded.ptr = strdup(string);
1152 this->encoded.len = strlen(string);
1153 this->public.matches = (id_match_t (*)
1154 (identification_t*,identification_t*))matches_string;
1155 this->public.equals = (bool (*)
1156 (identification_t*,identification_t*))equals_strcasecmp;
1157 return &this->public;
1158 }
1159 }
1160 }
1161
1162 /*
1163 * Described in header.
1164 */
1165 identification_t *identification_create_from_encoding(id_type_t type, chunk_t encoded)
1166 {
1167 private_identification_t *this = identification_create();
1168
1169 this->type = type;
1170 switch (type)
1171 {
1172 case ID_ANY:
1173 this->public.matches = (id_match_t (*)
1174 (identification_t*,identification_t*))matches_any;
1175 break;
1176 case ID_FQDN:
1177 case ID_RFC822_ADDR:
1178 this->public.matches = (id_match_t (*)
1179 (identification_t*,identification_t*))matches_string;
1180 this->public.equals = (bool (*)
1181 (identification_t*,identification_t*))equals_strcasecmp;
1182 break;
1183 case ID_DER_ASN1_DN:
1184 this->public.equals = (bool (*)
1185 (identification_t*,identification_t*))equals_dn;
1186 this->public.matches = (id_match_t (*)
1187 (identification_t*,identification_t*))matches_dn;
1188 break;
1189 case ID_IPV4_ADDR:
1190 case ID_IPV6_ADDR:
1191 case ID_DER_ASN1_GN:
1192 case ID_KEY_ID:
1193 case ID_DER_ASN1_GN_URI:
1194 case ID_PUBKEY_INFO_SHA1:
1195 case ID_PUBKEY_SHA1:
1196 case ID_CERT_DER_SHA1:
1197 case ID_IETF_ATTR_STRING:
1198 default:
1199 break;
1200 }
1201
1202 /* apply encoded chunk */
1203 if (type != ID_ANY)
1204 {
1205 this->encoded = chunk_clone(encoded);
1206 }
1207 return &(this->public);
1208 }
1209