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