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