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