parse RDNs in multiple SEQUENCEs in all SETs of a DN
[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 /* 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 /**
137 * Implementation of rdn_enumerator_t.enumerate
138 */
139 static bool rdn_enumerate(rdn_enumerator_t *this, chunk_t *oid,
140 u_char *type, chunk_t *data)
141 {
142 chunk_t rdn;
143
144 /* a DN contains one or more SET, each containing one or more SEQUENCES,
145 * each containing a OID/value RDN */
146 if (!this->seqs.len)
147 {
148 /* no SEQUENCEs in current SET, parse next SET */
149 if (asn1_unwrap(&this->sets, &this->seqs) != ASN1_SET)
150 {
151 return FALSE;
152 }
153 }
154 if (asn1_unwrap(&this->seqs, &rdn) == ASN1_SEQUENCE &&
155 asn1_unwrap(&rdn, oid) == ASN1_OID)
156 {
157 int t = asn1_unwrap(&rdn, data);
158
159 if (t != ASN1_INVALID)
160 {
161 *type = t;
162 return TRUE;
163 }
164 }
165 return FALSE;
166 }
167
168 /**
169 * Create an enumerator over all RDNs (oid, string type, data) of a DN
170 */
171 static enumerator_t* create_rdn_enumerator(chunk_t dn)
172 {
173 rdn_enumerator_t *e = malloc_thing(rdn_enumerator_t);
174
175 e->public.enumerate = (void*)rdn_enumerate;
176 e->public.destroy = (void*)free;
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 /**
199 * Implementation of rdn_part_enumerator_t.enumerate().
200 */
201 static bool rdn_part_enumerate(rdn_part_enumerator_t *this,
202 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_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 /**
245 * Implementation of rdn_part_enumerator_t.destroy().
246 */
247 static void rdn_part_enumerator_destroy(rdn_part_enumerator_t *this)
248 {
249 this->inner->destroy(this->inner);
250 free(this);
251 }
252
253 /**
254 * Implementation of identification_t.create_part_enumerator
255 */
256 static enumerator_t* create_part_enumerator(private_identification_t *this)
257 {
258 switch (this->type)
259 {
260 case ID_DER_ASN1_DN:
261 {
262 rdn_part_enumerator_t *e = malloc_thing(rdn_part_enumerator_t);
263
264 e->inner = create_rdn_enumerator(this->encoded);
265 e->public.enumerate = (void*)rdn_part_enumerate;
266 e->public.destroy = (void*)rdn_part_enumerator_destroy;
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 DN with all its RDN in a buffer to present it to the user
281 */
282 static void dntoa(chunk_t dn, char *buf, size_t len)
283 {
284 enumerator_t *e;
285 chunk_t oid_data, data;
286 u_char type;
287 int oid, written;
288 bool finished = FALSE;
289
290 e = create_rdn_enumerator(dn);
291 while (e->enumerate(e, &oid_data, &type, &data))
292 {
293 oid = asn1_known_oid(oid_data);
294
295 if (oid == OID_UNKNOWN)
296 {
297 written = snprintf(buf, len, "%#B=", &oid_data);
298 }
299 else
300 {
301 written = snprintf(buf, len,"%s=", oid_names[oid].name);
302 }
303 buf += written;
304 len -= written;
305
306 if (chunk_printable(data, NULL, '?'))
307 {
308 written = snprintf(buf, len, "%.*s", data.len, data.ptr);
309 }
310 else
311 {
312 written = snprintf(buf, len, "%#B", &data);
313 }
314 buf += written;
315 len -= written;
316
317 if (data.ptr + data.len != dn.ptr + dn.len)
318 {
319 written = snprintf(buf, len, ", ");
320 buf += written;
321 len -= written;
322 }
323 else
324 {
325 finished = TRUE;
326 break;
327 }
328 }
329 if (!finished)
330 {
331 snprintf(buf, len, "(invalid ID_DER_ASN1_DN)");
332 }
333 e->destroy(e);
334 }
335
336 /**
337 * Converts an LDAP-style human-readable ASCII-encoded
338 * ASN.1 distinguished name into binary DER-encoded format
339 */
340 static status_t atodn(char *src, chunk_t *dn)
341 {
342 /* finite state machine for atodn */
343 typedef enum {
344 SEARCH_OID = 0,
345 READ_OID = 1,
346 SEARCH_NAME = 2,
347 READ_NAME = 3,
348 UNKNOWN_OID = 4
349 } state_t;
350
351 chunk_t oid = chunk_empty;
352 chunk_t name = chunk_empty;
353 chunk_t rdns[RDN_MAX];
354 int rdn_count = 0;
355 int dn_len = 0;
356 int whitespace = 0;
357 int i = 0;
358 asn1_t rdn_type;
359 state_t state = SEARCH_OID;
360 status_t status = SUCCESS;
361
362 do
363 {
364 switch (state)
365 {
366 case SEARCH_OID:
367 if (*src != ' ' && *src != '/' && *src != ',')
368 {
369 oid.ptr = src;
370 oid.len = 1;
371 state = READ_OID;
372 }
373 break;
374 case READ_OID:
375 if (*src != ' ' && *src != '=')
376 {
377 oid.len++;
378 }
379 else
380 {
381 bool found = FALSE;
382
383 for (i = 0; i < countof(x501rdns); i++)
384 {
385 if (strlen(x501rdns[i].name) == oid.len &&
386 strncasecmp(x501rdns[i].name, oid.ptr, oid.len) == 0)
387 {
388 found = TRUE;
389 break;
390 }
391 }
392 if (!found)
393 {
394 status = NOT_SUPPORTED;
395 state = UNKNOWN_OID;
396 break;
397 }
398 /* reset oid and change state */
399 oid = chunk_empty;
400 state = SEARCH_NAME;
401 }
402 break;
403 case SEARCH_NAME:
404 if (*src != ' ' && *src != '=')
405 {
406 name.ptr = src;
407 name.len = 1;
408 whitespace = 0;
409 state = READ_NAME;
410 }
411 break;
412 case READ_NAME:
413 if (*src != ',' && *src != '/' && *src != '\0')
414 {
415 name.len++;
416 if (*src == ' ')
417 whitespace++;
418 else
419 whitespace = 0;
420 }
421 else
422 {
423 name.len -= whitespace;
424 rdn_type = (x501rdns[i].type == ASN1_PRINTABLESTRING
425 && !asn1_is_printablestring(name))
426 ? ASN1_T61STRING : x501rdns[i].type;
427
428 if (rdn_count < RDN_MAX)
429 {
430 chunk_t rdn_oid;
431
432 rdn_oid = asn1_build_known_oid(x501rdns[i].oid);
433 if (rdn_oid.len)
434 {
435 rdns[rdn_count] =
436 asn1_wrap(ASN1_SET, "m",
437 asn1_wrap(ASN1_SEQUENCE, "mm",
438 rdn_oid,
439 asn1_wrap(rdn_type, "c", name)
440 )
441 );
442 dn_len += rdns[rdn_count++].len;
443 }
444 else
445 {
446 status = INVALID_ARG;
447 }
448 }
449 else
450 {
451 status = OUT_OF_RES;
452 }
453 /* reset name and change state */
454 name = chunk_empty;
455 state = SEARCH_OID;
456 }
457 break;
458 case UNKNOWN_OID:
459 break;
460 }
461 } while (*src++ != '\0');
462
463 /* build the distinguished name sequence */
464 {
465 int i;
466 u_char *pos = asn1_build_object(dn, ASN1_SEQUENCE, dn_len);
467
468 for (i = 0; i < rdn_count; i++)
469 {
470 memcpy(pos, rdns[i].ptr, rdns[i].len);
471 pos += rdns[i].len;
472 free(rdns[i].ptr);
473 }
474 }
475
476 if (status != SUCCESS)
477 {
478 free(dn->ptr);
479 *dn = chunk_empty;
480 }
481 return status;
482 }
483
484 /**
485 * Implementation of identification_t.get_encoding.
486 */
487 static chunk_t get_encoding(private_identification_t *this)
488 {
489 return this->encoded;
490 }
491
492 /**
493 * Implementation of identification_t.get_type.
494 */
495 static id_type_t get_type(private_identification_t *this)
496 {
497 return this->type;
498 }
499
500 /**
501 * Implementation of identification_t.contains_wildcards for ID_DER_ASN1_DN.
502 */
503 static bool contains_wildcards_dn(private_identification_t *this)
504 {
505 enumerator_t *enumerator;
506 bool contains = FALSE;
507 id_part_t type;
508 chunk_t data;
509
510 enumerator = create_part_enumerator(this);
511 while (enumerator->enumerate(enumerator, &type, &data))
512 {
513 if (data.len == 1 && data.ptr[0] == '*')
514 {
515 contains = TRUE;
516 break;
517 }
518 }
519 enumerator->destroy(enumerator);
520 return contains;
521 }
522
523 /**
524 * Implementation of identification_t.contains_wildcards using memchr(*).
525 */
526 static bool contains_wildcards_memchr(private_identification_t *this)
527 {
528 return memchr(this->encoded.ptr, '*', this->encoded.len) != NULL;
529 }
530
531 /**
532 * Default implementation of identification_t.equals.
533 * compares encoded chunk for equality.
534 */
535 static bool equals_binary(private_identification_t *this, private_identification_t *other)
536 {
537 if (this->type == other->type)
538 {
539 if (this->type == ID_ANY)
540 {
541 return TRUE;
542 }
543 return chunk_equals(this->encoded, other->encoded);
544 }
545 return FALSE;
546 }
547
548 /**
549 * Compare to DNs, for equality if wc == NULL, for match otherwise
550 */
551 static bool compare_dn(chunk_t t_dn, chunk_t o_dn, int *wc)
552 {
553 enumerator_t *t, *o;
554 chunk_t t_oid, o_oid, t_data, o_data;
555 u_char t_type, o_type;
556 bool t_next, o_next, finished = FALSE;
557
558 if (wc)
559 {
560 *wc = 0;
561 }
562 else
563 {
564 if (t_dn.len != o_dn.len)
565 {
566 return FALSE;
567 }
568 }
569 /* try a binary compare */
570 if (memeq(t_dn.ptr, o_dn.ptr, t_dn.len))
571 {
572 return TRUE;
573 }
574
575 t = create_rdn_enumerator(t_dn);
576 o = create_rdn_enumerator(o_dn);
577 while (TRUE)
578 {
579 t_next = t->enumerate(t, &t_oid, &t_type, &t_data);
580 o_next = o->enumerate(o, &o_oid, &o_type, &o_data);
581
582 if (!o_next && !t_next)
583 {
584 break;
585 }
586 finished = FALSE;
587 if (o_next != t_next)
588 {
589 break;
590 }
591 if (!chunk_equals(t_oid, o_oid))
592 {
593 break;
594 }
595 if (wc && o_data.len == 1 && o_data.ptr[0] == '*')
596 {
597 (*wc)++;
598 }
599 else
600 {
601 if (t_data.len != o_data.len)
602 {
603 break;
604 }
605 if (t_type == o_type &&
606 (t_type == ASN1_PRINTABLESTRING ||
607 (t_type == ASN1_IA5STRING &&
608 (asn1_known_oid(t_oid) == OID_PKCS9_EMAIL ||
609 asn1_known_oid(t_oid) == OID_EMAIL_ADDRESS))))
610 { /* ignore case for printableStrings and email RDNs */
611 if (strncasecmp(t_data.ptr, o_data.ptr, t_data.len) != 0)
612 {
613 break;
614 }
615 }
616 else
617 { /* respect case and length for everything else */
618 if (!memeq(t_data.ptr, o_data.ptr, t_data.len))
619 {
620 break;
621 }
622 }
623 }
624 /* the enumerator returns FALSE on parse error, we are finished
625 * if we have reached the end of the DN only */
626 if ((t_data.ptr + t_data.len == t_dn.ptr + t_dn.len) &&
627 (o_data.ptr + o_data.len == o_dn.ptr + o_dn.len))
628 {
629 finished = TRUE;
630 }
631 }
632 t->destroy(t);
633 o->destroy(o);
634 return finished;
635 }
636
637 /**
638 * Special implementation of identification_t.equals for ID_DER_ASN1_DN.
639 */
640 static bool equals_dn(private_identification_t *this,
641 private_identification_t *other)
642 {
643 return compare_dn(this->encoded, other->encoded, NULL);
644 }
645
646 /**
647 * Special implementation of identification_t.equals for RFC822 and FQDN.
648 */
649 static bool equals_strcasecmp(private_identification_t *this,
650 private_identification_t *other)
651 {
652 /* we do some extra sanity checks to check for invalid IDs with a
653 * terminating null in it. */
654 if (this->encoded.len == other->encoded.len &&
655 memchr(this->encoded.ptr, 0, this->encoded.len) == NULL &&
656 memchr(other->encoded.ptr, 0, other->encoded.len) == NULL &&
657 strncasecmp(this->encoded.ptr, other->encoded.ptr, this->encoded.len) == 0)
658 {
659 return TRUE;
660 }
661 return FALSE;
662 }
663
664 /**
665 * Default implementation of identification_t.matches.
666 */
667 static id_match_t matches_binary(private_identification_t *this,
668 private_identification_t *other)
669 {
670 if (other->type == ID_ANY)
671 {
672 return ID_MATCH_ANY;
673 }
674 if (this->type == other->type &&
675 chunk_equals(this->encoded, other->encoded))
676 {
677 return ID_MATCH_PERFECT;
678 }
679 return ID_MATCH_NONE;
680 }
681
682 /**
683 * Special implementation of identification_t.matches for ID_RFC822_ADDR/ID_FQDN.
684 * Checks for a wildcard in other-string, and compares it against this-string.
685 */
686 static id_match_t matches_string(private_identification_t *this,
687 private_identification_t *other)
688 {
689 u_int len = other->encoded.len;
690
691 if (other->type == ID_ANY)
692 {
693 return ID_MATCH_ANY;
694 }
695 if (this->type != other->type)
696 {
697 return ID_MATCH_NONE;
698 }
699 /* try a equals check first */
700 if (equals_strcasecmp(this, other))
701 {
702 return ID_MATCH_PERFECT;
703 }
704 if (len == 0 || this->encoded.len < len)
705 {
706 return ID_MATCH_NONE;
707 }
708
709 /* check for single wildcard at the head of the string */
710 if (*other->encoded.ptr == '*')
711 {
712 /* single asterisk matches any string */
713 if (len-- == 1)
714 { /* not better than ID_ANY */
715 return ID_MATCH_ANY;
716 }
717 if (strncasecmp(this->encoded.ptr + this->encoded.len - len,
718 other->encoded.ptr + 1, len) == 0)
719 {
720 return ID_MATCH_ONE_WILDCARD;
721 }
722 }
723 return ID_MATCH_NONE;
724 }
725
726 /**
727 * Special implementation of identification_t.matches for ID_ANY.
728 * ANY matches only another ANY, but nothing other
729 */
730 static id_match_t matches_any(private_identification_t *this,
731 private_identification_t *other)
732 {
733 if (other->type == ID_ANY)
734 {
735 return ID_MATCH_ANY;
736 }
737 return ID_MATCH_NONE;
738 }
739
740 /**
741 * Special implementation of identification_t.matches for ID_DER_ASN1_DN
742 */
743 static id_match_t matches_dn(private_identification_t *this,
744 private_identification_t *other)
745 {
746 int wc;
747
748 if (other->type == ID_ANY)
749 {
750 return ID_MATCH_ANY;
751 }
752
753 if (this->type == other->type)
754 {
755 if (compare_dn(this->encoded, other->encoded, &wc))
756 {
757 wc = min(wc, ID_MATCH_ONE_WILDCARD - ID_MATCH_MAX_WILDCARDS);
758 return ID_MATCH_PERFECT - wc;
759 }
760 }
761 return ID_MATCH_NONE;
762 }
763
764 /**
765 * Described in header.
766 */
767 int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
768 const void *const *args)
769 {
770 private_identification_t *this = *((private_identification_t**)(args[0]));
771 chunk_t proper;
772 char buf[512];
773
774 if (this == NULL)
775 {
776 return print_in_hook(dst, len, "%*s", spec->width, "(null)");
777 }
778
779 switch (this->type)
780 {
781 case ID_ANY:
782 snprintf(buf, sizeof(buf), "%%any");
783 break;
784 case ID_IPV4_ADDR:
785 if (this->encoded.len < sizeof(struct in_addr) ||
786 inet_ntop(AF_INET, this->encoded.ptr, buf, sizeof(buf)) == NULL)
787 {
788 snprintf(buf, sizeof(buf), "(invalid ID_IPV4_ADDR)");
789 }
790 break;
791 case ID_IPV6_ADDR:
792 if (this->encoded.len < sizeof(struct in6_addr) ||
793 inet_ntop(AF_INET6, this->encoded.ptr, buf, INET6_ADDRSTRLEN) == NULL)
794 {
795 snprintf(buf, sizeof(buf), "(invalid ID_IPV6_ADDR)");
796 }
797 break;
798 case ID_FQDN:
799 case ID_RFC822_ADDR:
800 case ID_DER_ASN1_GN_URI:
801 case ID_IETF_ATTR_STRING:
802 chunk_printable(this->encoded, &proper, '?');
803 snprintf(buf, sizeof(buf), "%.*s", proper.len, proper.ptr);
804 chunk_free(&proper);
805 break;
806 case ID_DER_ASN1_DN:
807 dntoa(this->encoded, buf, sizeof(buf));
808 break;
809 case ID_DER_ASN1_GN:
810 snprintf(buf, sizeof(buf), "(ASN.1 general Name");
811 break;
812 case ID_KEY_ID:
813 if (chunk_printable(this->encoded, NULL, '?'))
814 { /* fully printable, use ascii version */
815 snprintf(buf, sizeof(buf), "%.*s",
816 this->encoded.len, this->encoded.ptr);
817 }
818 else
819 { /* not printable, hex dump */
820 snprintf(buf, sizeof(buf), "%#B", &this->encoded);
821 }
822 break;
823 case ID_PUBKEY_INFO_SHA1:
824 case ID_PUBKEY_SHA1:
825 case ID_CERT_DER_SHA1:
826 snprintf(buf, sizeof(buf), "%#B", &this->encoded);
827 break;
828 default:
829 snprintf(buf, sizeof(buf), "(unknown ID type: %d)", this->type);
830 break;
831 }
832 if (spec->minus)
833 {
834 return print_in_hook(dst, len, "%-*s", spec->width, buf);
835 }
836 return print_in_hook(dst, len, "%*s", spec->width, buf);
837 }
838 /**
839 * Implementation of identification_t.clone.
840 */
841 static identification_t *clone_(private_identification_t *this)
842 {
843 private_identification_t *clone = malloc_thing(private_identification_t);
844
845 memcpy(clone, this, sizeof(private_identification_t));
846 if (this->encoded.len)
847 {
848 clone->encoded = chunk_clone(this->encoded);
849 }
850 return &clone->public;
851 }
852
853 /**
854 * Implementation of identification_t.destroy.
855 */
856 static void destroy(private_identification_t *this)
857 {
858 chunk_free(&this->encoded);
859 free(this);
860 }
861
862 /**
863 * Generic constructor used for the other constructors.
864 */
865 static private_identification_t *identification_create(id_type_t type)
866 {
867 private_identification_t *this = malloc_thing(private_identification_t);
868
869 this->public.get_encoding = (chunk_t (*) (identification_t*))get_encoding;
870 this->public.get_type = (id_type_t (*) (identification_t*))get_type;
871 this->public.create_part_enumerator = (enumerator_t*(*)(identification_t*))create_part_enumerator;
872 this->public.clone = (identification_t* (*) (identification_t*))clone_;
873 this->public.destroy = (void (*) (identification_t*))destroy;
874
875 switch (type)
876 {
877 case ID_ANY:
878 this->public.matches = (id_match_t (*)(identification_t*,identification_t*))matches_any;
879 this->public.equals = (bool (*) (identification_t*,identification_t*))equals_binary;
880 this->public.contains_wildcards = (bool (*) (identification_t *this))return_true;
881 break;
882 case ID_FQDN:
883 case ID_RFC822_ADDR:
884 this->public.matches = (id_match_t (*)(identification_t*,identification_t*))matches_string;
885 this->public.equals = (bool (*)(identification_t*,identification_t*))equals_strcasecmp;
886 this->public.contains_wildcards = (bool (*) (identification_t *this))contains_wildcards_memchr;
887 break;
888 case ID_DER_ASN1_DN:
889 this->public.equals = (bool (*)(identification_t*,identification_t*))equals_dn;
890 this->public.matches = (id_match_t (*)(identification_t*,identification_t*))matches_dn;
891 this->public.contains_wildcards = (bool (*) (identification_t *this))contains_wildcards_dn;
892 break;
893 default:
894 this->public.equals = (bool (*) (identification_t*,identification_t*))equals_binary;
895 this->public.matches = (id_match_t (*) (identification_t*,identification_t*))matches_binary;
896 this->public.contains_wildcards = (bool (*) (identification_t *this))return_false;
897 break;
898 }
899
900 this->type = type;
901 this->encoded = chunk_empty;
902
903 return this;
904 }
905
906 /*
907 * Described in header.
908 */
909 identification_t *identification_create_from_string(char *string)
910 {
911 private_identification_t *this;
912 chunk_t encoded;
913
914 if (string == NULL)
915 {
916 string = "%any";
917 }
918 if (strchr(string, '=') != NULL)
919 {
920 /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
921 * convert from LDAP style or openssl x509 -subject style to ASN.1 DN
922 */
923 if (atodn(string, &encoded) == SUCCESS)
924 {
925 this = identification_create(ID_DER_ASN1_DN);
926 this->encoded = encoded;
927 }
928 else
929 {
930 this = identification_create(ID_KEY_ID);
931 this->encoded = chunk_clone(chunk_create(string, strlen(string)));
932 }
933 return &this->public;
934 }
935 else if (strchr(string, '@') == NULL)
936 {
937 if (streq(string, "%any")
938 || streq(string, "%any6")
939 || streq(string, "0.0.0.0")
940 || streq(string, "*")
941 || streq(string, "::")
942 || streq(string, "0::0"))
943 {
944 /* any ID will be accepted */
945 this = identification_create(ID_ANY);
946 return &this->public;
947 }
948 else
949 {
950 if (strchr(string, ':') == NULL)
951 {
952 struct in_addr address;
953 chunk_t chunk = {(void*)&address, sizeof(address)};
954
955 if (inet_pton(AF_INET, string, &address) > 0)
956 { /* is IPv4 */
957 this = identification_create(ID_IPV4_ADDR);
958 this->encoded = chunk_clone(chunk);
959 }
960 else
961 { /* not IPv4, mostly FQDN */
962 this = identification_create(ID_FQDN);
963 this->encoded = chunk_create(strdup(string), strlen(string));
964 }
965 return &this->public;
966 }
967 else
968 {
969 struct in6_addr address;
970 chunk_t chunk = {(void*)&address, sizeof(address)};
971
972 if (inet_pton(AF_INET6, string, &address) > 0)
973 { /* is IPv6 */
974 this = identification_create(ID_IPV6_ADDR);
975 this->encoded = chunk_clone(chunk);
976 }
977 else
978 { /* not IPv4/6 fallback to KEY_ID */
979 this = identification_create(ID_KEY_ID);
980 this->encoded = chunk_create(strdup(string), strlen(string));
981 }
982 return &this->public;
983 }
984 }
985 }
986 else
987 {
988 if (*string == '@')
989 {
990 if (*(string + 1) == '#')
991 {
992 this = identification_create(ID_KEY_ID);
993 string += 2;
994 this->encoded = chunk_from_hex(
995 chunk_create(string, strlen(string)), NULL);
996 return &this->public;
997 }
998 else
999 {
1000 this = identification_create(ID_FQDN);
1001 string += 1;
1002 this->encoded = chunk_create(strdup(string), strlen(string));
1003 return &this->public;
1004 }
1005 }
1006 else
1007 {
1008 this = identification_create(ID_RFC822_ADDR);
1009 this->encoded = chunk_create(strdup(string), strlen(string));
1010 return &this->public;
1011 }
1012 }
1013 }
1014
1015 /*
1016 * Described in header.
1017 */
1018 identification_t *identification_create_from_encoding(id_type_t type,
1019 chunk_t encoded)
1020 {
1021 private_identification_t *this = identification_create(type);
1022
1023 /* apply encoded chunk */
1024 if (type != ID_ANY)
1025 {
1026 this->encoded = chunk_clone(encoded);
1027 }
1028 return &(this->public);
1029 }
1030