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