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