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