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