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