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