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