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