use an enumerator to parse RDNs, based on asn1_unwrap() function
[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 static private_identification_t *identification_create(void);
271
272 /**
273 * updates a chunk (!????)
274 * TODO: We should reconsider this stuff, its not really clear
275 */
276 static void update_chunk(chunk_t *ch, int n)
277 {
278 n = (n > -1 && n < (int)ch->len)? n : (int)ch->len-1;
279 ch->ptr += n; ch->len -= n;
280 }
281
282 /**
283 * Remove any malicious characters from a chunk. We are very restrictive, but
284 * whe use these strings only to present it to the user.
285 */
286 static bool sanitize_chunk(chunk_t chunk, chunk_t *clone)
287 {
288 char *pos;
289 bool all_printable = TRUE;
290
291 *clone = chunk_clone(chunk);
292
293 for (pos = clone->ptr; pos < (char*)(clone->ptr + clone->len); pos++)
294 {
295 if (!isprint(*pos))
296 {
297 *pos = '?';
298 all_printable = FALSE;
299 }
300 }
301 return all_printable;
302 }
303
304 /**
305 * Pointer is set to the first RDN in a DN
306 */
307 static bool init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next)
308 {
309 *rdn = chunk_empty;
310 *attribute = chunk_empty;
311
312 /* a DN is a SEQUENCE OF RDNs */
313 if (*dn.ptr != ASN1_SEQUENCE)
314 {
315 /* DN is not a SEQUENCE */
316 return FALSE;
317 }
318
319 rdn->len = asn1_length(&dn);
320
321 if (rdn->len == ASN1_INVALID_LENGTH)
322 {
323 /* Invalid RDN length */
324 return FALSE;
325 }
326
327 rdn->ptr = dn.ptr;
328
329 /* are there any RDNs ? */
330 *next = rdn->len > 0;
331
332 return TRUE;
333 }
334
335 /**
336 * Fetches the next RDN in a DN
337 */
338 static bool get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid,
339 chunk_t *value, asn1_t *type, bool *next)
340 {
341 chunk_t body;
342
343 /* initialize return values */
344 *oid = chunk_empty;
345 *value = chunk_empty;
346
347 /* if all attributes have been parsed, get next rdn */
348 if (attribute->len <= 0)
349 {
350 /* an RDN is a SET OF attributeTypeAndValue */
351 if (*rdn->ptr != ASN1_SET)
352 {
353 /* RDN is not a SET */
354 return FALSE;
355 }
356 attribute->len = asn1_length(rdn);
357 if (attribute->len == ASN1_INVALID_LENGTH)
358 {
359 /* Invalid attribute length */
360 return FALSE;
361 }
362 attribute->ptr = rdn->ptr;
363 /* advance to start of next RDN */
364 rdn->ptr += attribute->len;
365 rdn->len -= attribute->len;
366 }
367
368 /* an attributeTypeAndValue is a SEQUENCE */
369 if (*attribute->ptr != ASN1_SEQUENCE)
370 {
371 /* attributeTypeAndValue is not a SEQUENCE */
372 return FALSE;
373 }
374
375 /* extract the attribute body */
376 body.len = asn1_length(attribute);
377
378 if (body.len == ASN1_INVALID_LENGTH)
379 {
380 /* Invalid attribute body length */
381 return FALSE;
382 }
383
384 body.ptr = attribute->ptr;
385
386 /* advance to start of next attribute */
387 attribute->ptr += body.len;
388 attribute->len -= body.len;
389
390 /* attribute type is an OID */
391 if (*body.ptr != ASN1_OID)
392 {
393 /* attributeType is not an OID */
394 return FALSE;
395 }
396 /* extract OID */
397 oid->len = asn1_length(&body);
398
399 if (oid->len == ASN1_INVALID_LENGTH)
400 {
401 /* Invalid attribute OID length */
402 return FALSE;
403 }
404 oid->ptr = body.ptr;
405
406 /* advance to the attribute value */
407 body.ptr += oid->len;
408 body.len -= oid->len;
409
410 /* extract string type */
411 *type = *body.ptr;
412
413 /* extract string value */
414 value->len = asn1_length(&body);
415
416 if (value->len == ASN1_INVALID_LENGTH)
417 {
418 /* Invalid attribute string length */
419 return FALSE;
420 }
421 value->ptr = body.ptr;
422
423 /* are there any RDNs left? */
424 *next = rdn->len > 0 || attribute->len > 0;
425 return TRUE;
426 }
427
428 /**
429 * Parses an ASN.1 distinguished name int its OID/value pairs
430 */
431 static bool dntoa(chunk_t dn, chunk_t *str)
432 {
433 chunk_t rdn, oid, attribute, value, proper;
434 asn1_t type;
435 int oid_code;
436 bool next;
437 bool first = TRUE;
438
439 if (!init_rdn(dn, &rdn, &attribute, &next))
440 {
441 return FALSE;
442 }
443
444 while (next)
445 {
446 if (!get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next))
447 {
448 return FALSE;
449 }
450
451 if (first)
452 { /* first OID/value pair */
453 first = FALSE;
454 }
455 else
456 { /* separate OID/value pair by a comma */
457 update_chunk(str, snprintf(str->ptr,str->len,", "));
458 }
459
460 /* print OID */
461 oid_code = asn1_known_oid(oid);
462 if (oid_code == OID_UNKNOWN)
463 {
464 update_chunk(str, snprintf(str->ptr,str->len,"0x#B", &oid));
465 }
466 else
467 {
468 update_chunk(str, snprintf(str->ptr,str->len,"%s", oid_names[oid_code].name));
469 }
470 /* print value */
471 sanitize_chunk(value, &proper);
472 update_chunk(str, snprintf(str->ptr,str->len,"=%.*s", (int)proper.len, proper.ptr));
473 chunk_free(&proper);
474 }
475 return TRUE;
476 }
477
478 /**
479 * compare two distinguished names by
480 * comparing the individual RDNs
481 */
482 static bool same_dn(chunk_t a, chunk_t b)
483 {
484 chunk_t rdn_a, rdn_b, attribute_a, attribute_b;
485 chunk_t oid_a, oid_b, value_a, value_b;
486 asn1_t type_a, type_b;
487 bool next_a, next_b;
488
489 /* same lengths for the DNs */
490 if (a.len != b.len)
491 {
492 return FALSE;
493 }
494 /* try a binary comparison first */
495 if (memeq(a.ptr, b.ptr, b.len))
496 {
497 return TRUE;
498 }
499 /* initialize DN parsing */
500 if (!init_rdn(a, &rdn_a, &attribute_a, &next_a) ||
501 !init_rdn(b, &rdn_b, &attribute_b, &next_b))
502 {
503 return FALSE;
504 }
505
506 /* fetch next RDN pair */
507 while (next_a && next_b)
508 {
509 /* parse next RDNs and check for errors */
510 if (!get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) ||
511 !get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b))
512 {
513 return FALSE;
514 }
515
516 /* OIDs must agree */
517 if (oid_a.len != oid_b.len || !memeq(oid_a.ptr, oid_b.ptr, oid_b.len))
518 {
519 return FALSE;
520 }
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 are equal! */
551 return TRUE;
552 }
553
554
555 /**
556 * compare two distinguished names by comparing the individual RDNs.
557 * A single'*' character designates a wildcard RDN in DN b.
558 * TODO: Add support for different RDN order in DN !!
559 */
560 bool match_dn(chunk_t a, chunk_t b, int *wildcards)
561 {
562 chunk_t rdn_a, rdn_b, attribute_a, attribute_b;
563 chunk_t oid_a, oid_b, value_a, value_b;
564 asn1_t type_a, type_b;
565 bool next_a, next_b;
566
567 /* initialize wildcard counter */
568 *wildcards = 0;
569
570 /* initialize DN parsing */
571 if (!init_rdn(a, &rdn_a, &attribute_a, &next_a) ||
572 !init_rdn(b, &rdn_b, &attribute_b, &next_b))
573 {
574 return FALSE;
575 }
576
577 /* fetch next RDN pair */
578 while (next_a && next_b)
579 {
580 /* parse next RDNs and check for errors */
581 if (!get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) ||
582 !get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b))
583 {
584 return FALSE;
585 }
586 /* OIDs must agree */
587 if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)
588 {
589 return FALSE;
590 }
591
592 /* does rdn_b contain a wildcard? */
593 if (value_b.len == 1 && *value_b.ptr == '*')
594 {
595 (*wildcards)++;
596 continue;
597 }
598 /* same lengths for values */
599 if (value_a.len != value_b.len)
600 {
601 return FALSE;
602 }
603
604 /* printableStrings and email RDNs require uppercase comparison */
605 if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING ||
606 (type_a == ASN1_IA5STRING && asn1_known_oid(oid_a) == OID_PKCS9_EMAIL)))
607 {
608 if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
609 {
610 return FALSE;
611 }
612 }
613 else
614 {
615 if (!strneq(value_a.ptr, value_b.ptr, value_b.len))
616 {
617 return FALSE;
618 }
619 }
620 }
621 /* both DNs must have same number of RDNs */
622 if (next_a || next_b)
623 {
624 return FALSE;
625 }
626 /* the two DNs match! */
627 *wildcards = min(*wildcards, ID_MATCH_ONE_WILDCARD - ID_MATCH_MAX_WILDCARDS);
628 return TRUE;
629 }
630
631 /**
632 * Converts an LDAP-style human-readable ASCII-encoded
633 * ASN.1 distinguished name into binary DER-encoded format
634 */
635 static status_t atodn(char *src, chunk_t *dn)
636 {
637 /* finite state machine for atodn */
638 typedef enum {
639 SEARCH_OID = 0,
640 READ_OID = 1,
641 SEARCH_NAME = 2,
642 READ_NAME = 3,
643 UNKNOWN_OID = 4
644 } state_t;
645
646 chunk_t oid = chunk_empty;
647 chunk_t name = chunk_empty;
648 chunk_t rdns[RDN_MAX];
649 int rdn_count = 0;
650 int dn_len = 0;
651 int whitespace = 0;
652 int i = 0;
653 asn1_t rdn_type;
654 state_t state = SEARCH_OID;
655 status_t status = SUCCESS;
656
657 do
658 {
659 switch (state)
660 {
661 case SEARCH_OID:
662 if (*src != ' ' && *src != '/' && *src != ',')
663 {
664 oid.ptr = src;
665 oid.len = 1;
666 state = READ_OID;
667 }
668 break;
669 case READ_OID:
670 if (*src != ' ' && *src != '=')
671 {
672 oid.len++;
673 }
674 else
675 {
676 bool found = FALSE;
677
678 for (i = 0; i < countof(x501rdns); i++)
679 {
680 if (strlen(x501rdns[i].name) == oid.len &&
681 strncasecmp(x501rdns[i].name, oid.ptr, oid.len) == 0)
682 {
683 found = TRUE;
684 break;
685 }
686 }
687 if (!found)
688 {
689 status = NOT_SUPPORTED;
690 state = UNKNOWN_OID;
691 break;
692 }
693 /* reset oid and change state */
694 oid = chunk_empty;
695 state = SEARCH_NAME;
696 }
697 break;
698 case SEARCH_NAME:
699 if (*src != ' ' && *src != '=')
700 {
701 name.ptr = src;
702 name.len = 1;
703 whitespace = 0;
704 state = READ_NAME;
705 }
706 break;
707 case READ_NAME:
708 if (*src != ',' && *src != '/' && *src != '\0')
709 {
710 name.len++;
711 if (*src == ' ')
712 whitespace++;
713 else
714 whitespace = 0;
715 }
716 else
717 {
718 name.len -= whitespace;
719 rdn_type = (x501rdns[i].type == ASN1_PRINTABLESTRING
720 && !asn1_is_printablestring(name))
721 ? ASN1_T61STRING : x501rdns[i].type;
722
723 if (rdn_count < RDN_MAX)
724 {
725 chunk_t rdn_oid;
726
727 rdn_oid = asn1_build_known_oid(x501rdns[i].oid);
728 if (rdn_oid.len)
729 {
730 rdns[rdn_count] =
731 asn1_wrap(ASN1_SET, "m",
732 asn1_wrap(ASN1_SEQUENCE, "mm",
733 rdn_oid,
734 asn1_wrap(rdn_type, "c", name)
735 )
736 );
737 dn_len += rdns[rdn_count++].len;
738 }
739 else
740 {
741 status = INVALID_ARG;
742 }
743 }
744 else
745 {
746 status = OUT_OF_RES;
747 }
748 /* reset name and change state */
749 name = chunk_empty;
750 state = SEARCH_OID;
751 }
752 break;
753 case UNKNOWN_OID:
754 break;
755 }
756 } while (*src++ != '\0');
757
758 /* build the distinguished name sequence */
759 {
760 int i;
761 u_char *pos = asn1_build_object(dn, ASN1_SEQUENCE, dn_len);
762
763 for (i = 0; i < rdn_count; i++)
764 {
765 memcpy(pos, rdns[i].ptr, rdns[i].len);
766 pos += rdns[i].len;
767 free(rdns[i].ptr);
768 }
769 }
770
771 if (status != SUCCESS)
772 {
773 free(dn->ptr);
774 *dn = chunk_empty;
775 }
776 return status;
777 }
778
779 /**
780 * Implementation of identification_t.get_encoding.
781 */
782 static chunk_t get_encoding(private_identification_t *this)
783 {
784 return this->encoded;
785 }
786
787 /**
788 * Implementation of identification_t.get_type.
789 */
790 static id_type_t get_type(private_identification_t *this)
791 {
792 return this->type;
793 }
794
795 /**
796 * Implementation of identification_t.contains_wildcards fro ID_DER_ASN1_DN.
797 */
798 static bool contains_wildcards_dn(private_identification_t *this)
799 {
800 chunk_t rdn, attribute;
801 chunk_t oid, value;
802 asn1_t type;
803 bool next;
804
805 if (!init_rdn(this->encoded, &rdn, &attribute, &next))
806 {
807 return FALSE;
808 }
809 /* fetch next RDN */
810 while (next)
811 {
812 /* parse next RDN and check for errors */
813 if (!get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next))
814 {
815 return FALSE;
816 }
817 /* check if RDN is a wildcard */
818 if (value.len == 1 && *value.ptr == '*')
819 {
820 return TRUE;
821 }
822 }
823 return FALSE;
824 }
825
826 /**
827 * Implementation of identification_t.contains_wildcards.
828 */
829 static bool contains_wildcards(private_identification_t *this)
830 {
831 switch (this->type)
832 {
833 case ID_ANY:
834 return TRUE;
835 case ID_FQDN:
836 case ID_RFC822_ADDR:
837 return memchr(this->encoded.ptr, '*', this->encoded.len) != NULL;
838 case ID_DER_ASN1_DN:
839 return contains_wildcards_dn(this);
840 default:
841 return FALSE;
842 }
843 }
844
845 /**
846 * Default implementation of identification_t.equals.
847 * compares encoded chunk for equality.
848 */
849 static bool equals_binary(private_identification_t *this, private_identification_t *other)
850 {
851 if (this->type == other->type)
852 {
853 if (this->type == ID_ANY)
854 {
855 return TRUE;
856 }
857 return chunk_equals(this->encoded, other->encoded);
858 }
859 return FALSE;
860 }
861
862 /**
863 * Special implementation of identification_t.equals for ID_DER_ASN1_DN.
864 */
865 static bool equals_dn(private_identification_t *this,
866 private_identification_t *other)
867 {
868 return same_dn(this->encoded, other->encoded);
869 }
870
871 /**
872 * Special implementation of identification_t.equals for RFC822 and FQDN.
873 */
874 static bool equals_strcasecmp(private_identification_t *this,
875 private_identification_t *other)
876 {
877 /* we do some extra sanity checks to check for invalid IDs with a
878 * terminating null in it. */
879 if (this->encoded.len == other->encoded.len &&
880 memchr(this->encoded.ptr, 0, this->encoded.len) == NULL &&
881 memchr(other->encoded.ptr, 0, other->encoded.len) == NULL &&
882 strncasecmp(this->encoded.ptr, other->encoded.ptr, this->encoded.len) == 0)
883 {
884 return TRUE;
885 }
886 return FALSE;
887 }
888
889 /**
890 * Default implementation of identification_t.matches.
891 */
892 static id_match_t matches_binary(private_identification_t *this,
893 private_identification_t *other)
894 {
895 if (other->type == ID_ANY)
896 {
897 return ID_MATCH_ANY;
898 }
899 if (this->type == other->type &&
900 chunk_equals(this->encoded, other->encoded))
901 {
902 return ID_MATCH_PERFECT;
903 }
904 return ID_MATCH_NONE;
905 }
906
907 /**
908 * Special implementation of identification_t.matches for ID_RFC822_ADDR/ID_FQDN.
909 * Checks for a wildcard in other-string, and compares it against this-string.
910 */
911 static id_match_t matches_string(private_identification_t *this,
912 private_identification_t *other)
913 {
914 u_int len = other->encoded.len;
915
916 if (other->type == ID_ANY)
917 {
918 return ID_MATCH_ANY;
919 }
920 if (this->type != other->type)
921 {
922 return ID_MATCH_NONE;
923 }
924 /* try a equals check first */
925 if (equals_strcasecmp(this, other))
926 {
927 return ID_MATCH_PERFECT;
928 }
929 if (len == 0 || this->encoded.len < len)
930 {
931 return ID_MATCH_NONE;
932 }
933
934 /* check for single wildcard at the head of the string */
935 if (*other->encoded.ptr == '*')
936 {
937 /* single asterisk matches any string */
938 if (len-- == 1)
939 { /* not better than ID_ANY */
940 return ID_MATCH_ANY;
941 }
942 if (strncasecmp(this->encoded.ptr + this->encoded.len - len,
943 other->encoded.ptr + 1, len) == 0)
944 {
945 return ID_MATCH_ONE_WILDCARD;
946 }
947 }
948 return ID_MATCH_NONE;
949 }
950
951 /**
952 * Special implementation of identification_t.matches for ID_ANY.
953 * ANY matches only another ANY, but nothing other
954 */
955 static id_match_t matches_any(private_identification_t *this,
956 private_identification_t *other)
957 {
958 if (other->type == ID_ANY)
959 {
960 return ID_MATCH_ANY;
961 }
962 return ID_MATCH_NONE;
963 }
964
965 /**
966 * Special implementation of identification_t.matches for ID_DER_ASN1_DN
967 */
968 static id_match_t matches_dn(private_identification_t *this,
969 private_identification_t *other)
970 {
971 int wc;
972
973 if (other->type == ID_ANY)
974 {
975 return ID_MATCH_ANY;
976 }
977
978 if (this->type == other->type)
979 {
980 if (match_dn(this->encoded, other->encoded, &wc))
981 {
982 return ID_MATCH_PERFECT - wc;
983 }
984 }
985 return ID_MATCH_NONE;
986 }
987
988 /**
989 * Described in header.
990 */
991 int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
992 const void *const *args)
993 {
994 private_identification_t *this = *((private_identification_t**)(args[0]));
995 char buf[BUF_LEN];
996 chunk_t proper, buf_chunk = chunk_from_buf(buf);
997
998 if (this == NULL)
999 {
1000 return print_in_hook(dst, len, "%*s", spec->width, "(null)");
1001 }
1002
1003 switch (this->type)
1004 {
1005 case ID_ANY:
1006 snprintf(buf, sizeof(buf), "%%any");
1007 break;
1008 case ID_IPV4_ADDR:
1009 if (this->encoded.len < sizeof(struct in_addr) ||
1010 inet_ntop(AF_INET, this->encoded.ptr, buf, sizeof(buf)) == NULL)
1011 {
1012 snprintf(buf, sizeof(buf), "(invalid ID_IPV4_ADDR)");
1013 }
1014 break;
1015 case ID_IPV6_ADDR:
1016 if (this->encoded.len < sizeof(struct in6_addr) ||
1017 inet_ntop(AF_INET6, this->encoded.ptr, buf, INET6_ADDRSTRLEN) == NULL)
1018 {
1019 snprintf(buf, sizeof(buf), "(invalid ID_IPV6_ADDR)");
1020 }
1021 break;
1022 case ID_FQDN:
1023 case ID_RFC822_ADDR:
1024 case ID_DER_ASN1_GN_URI:
1025 case ID_IETF_ATTR_STRING:
1026 sanitize_chunk(this->encoded, &proper);
1027 snprintf(buf, sizeof(buf), "%.*s", proper.len, proper.ptr);
1028 chunk_free(&proper);
1029 break;
1030 case ID_DER_ASN1_DN:
1031 if (!dntoa(this->encoded, &buf_chunk))
1032 {
1033 snprintf(buf, sizeof(buf), "(invalid ID_DER_ASN1_DN)");
1034 }
1035 break;
1036 case ID_DER_ASN1_GN:
1037 snprintf(buf, sizeof(buf), "(ASN.1 general Name");
1038 break;
1039 case ID_KEY_ID:
1040 if (sanitize_chunk(this->encoded, &proper))
1041 { /* fully printable, use ascii version */
1042 snprintf(buf, sizeof(buf), "%.*s", proper.len, proper.ptr);
1043 }
1044 else
1045 { /* not printable, hex dump */
1046 snprintf(buf, sizeof(buf), "%#B", &this->encoded);
1047 }
1048 chunk_free(&proper);
1049 break;
1050 case ID_PUBKEY_INFO_SHA1:
1051 case ID_PUBKEY_SHA1:
1052 case ID_CERT_DER_SHA1:
1053 snprintf(buf, sizeof(buf), "%#B", &this->encoded);
1054 break;
1055 default:
1056 snprintf(buf, sizeof(buf), "(unknown ID type: %d)", this->type);
1057 break;
1058 }
1059 if (spec->minus)
1060 {
1061 return print_in_hook(dst, len, "%-*s", spec->width, buf);
1062 }
1063 return print_in_hook(dst, len, "%*s", spec->width, buf);
1064 }
1065 /**
1066 * Implementation of identification_t.clone.
1067 */
1068 static identification_t *clone_(private_identification_t *this)
1069 {
1070 private_identification_t *clone = identification_create();
1071
1072 clone->type = this->type;
1073 if (this->encoded.len)
1074 {
1075 clone->encoded = chunk_clone(this->encoded);
1076 }
1077 clone->public.equals = this->public.equals;
1078 clone->public.matches = this->public.matches;
1079
1080 return &clone->public;
1081 }
1082
1083 /**
1084 * Implementation of identification_t.destroy.
1085 */
1086 static void destroy(private_identification_t *this)
1087 {
1088 chunk_free(&this->encoded);
1089 free(this);
1090 }
1091
1092 /**
1093 * Generic constructor used for the other constructors.
1094 */
1095 static private_identification_t *identification_create(void)
1096 {
1097 private_identification_t *this = malloc_thing(private_identification_t);
1098
1099 this->public.get_encoding = (chunk_t (*) (identification_t*))get_encoding;
1100 this->public.get_type = (id_type_t (*) (identification_t*))get_type;
1101 this->public.contains_wildcards = (bool (*) (identification_t *this))contains_wildcards;
1102 this->public.create_part_enumerator = (enumerator_t*(*)(identification_t*))create_part_enumerator;
1103 this->public.clone = (identification_t* (*) (identification_t*))clone_;
1104 this->public.destroy = (void (*) (identification_t*))destroy;
1105 /* we use these as defaults, the may be overloaded for special ID types */
1106 this->public.equals = (bool (*) (identification_t*,identification_t*))equals_binary;
1107 this->public.matches = (id_match_t (*) (identification_t*,identification_t*))matches_binary;
1108
1109 this->encoded = chunk_empty;
1110
1111 return this;
1112 }
1113
1114 /*
1115 * Described in header.
1116 */
1117 identification_t *identification_create_from_string(char *string)
1118 {
1119 private_identification_t *this = identification_create();
1120
1121 if (string == NULL)
1122 {
1123 string = "%any";
1124 }
1125 if (strchr(string, '=') != NULL)
1126 {
1127 /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
1128 * convert from LDAP style or openssl x509 -subject style to ASN.1 DN
1129 */
1130 if (atodn(string, &this->encoded) != SUCCESS)
1131 {
1132 this->type = ID_KEY_ID;
1133 this->encoded = chunk_clone(chunk_create(string, strlen(string)));
1134 return &this->public;
1135 }
1136 this->type = ID_DER_ASN1_DN;
1137 this->public.equals = (bool (*) (identification_t*,identification_t*))equals_dn;
1138 this->public.matches = (id_match_t (*) (identification_t*,identification_t*))matches_dn;
1139 return &this->public;
1140 }
1141 else if (strchr(string, '@') == NULL)
1142 {
1143 if (streq(string, "%any")
1144 || streq(string, "%any6")
1145 || streq(string, "0.0.0.0")
1146 || streq(string, "*")
1147 || streq(string, "::")
1148 || streq(string, "0::0"))
1149 {
1150 /* any ID will be accepted */
1151 this->type = ID_ANY;
1152 this->public.matches = (id_match_t (*)
1153 (identification_t*,identification_t*))matches_any;
1154 return &this->public;
1155 }
1156 else
1157 {
1158 if (strchr(string, ':') == NULL)
1159 {
1160 /* try IPv4 */
1161 struct in_addr address;
1162 chunk_t chunk = {(void*)&address, sizeof(address)};
1163
1164 if (inet_pton(AF_INET, string, &address) <= 0)
1165 {
1166 /* not IPv4, mostly FQDN */
1167 this->type = ID_FQDN;
1168 this->encoded.ptr = strdup(string);
1169 this->encoded.len = strlen(string);
1170 this->public.matches = (id_match_t (*)
1171 (identification_t*,identification_t*))matches_string;
1172 this->public.equals = (bool (*)
1173 (identification_t*,identification_t*))equals_strcasecmp;
1174 return &this->public;
1175 }
1176 this->encoded = chunk_clone(chunk);
1177 this->type = ID_IPV4_ADDR;
1178 return &this->public;
1179 }
1180 else
1181 {
1182 /* try IPv6 */
1183 struct in6_addr address;
1184 chunk_t chunk = {(void*)&address, sizeof(address)};
1185
1186 if (inet_pton(AF_INET6, string, &address) <= 0)
1187 {
1188 this->type = ID_KEY_ID;
1189 this->encoded = chunk_clone(chunk_create(string,
1190 strlen(string)));
1191 return &this->public;
1192 }
1193 this->encoded = chunk_clone(chunk);
1194 this->type = ID_IPV6_ADDR;
1195 return &this->public;
1196 }
1197 }
1198 }
1199 else
1200 {
1201 if (*string == '@')
1202 {
1203 if (*(string + 1) == '#')
1204 {
1205 string += 2;
1206 this->type = ID_KEY_ID;
1207 this->encoded = chunk_from_hex(
1208 chunk_create(string, strlen(string)), NULL);
1209 return &this->public;
1210 }
1211 else
1212 {
1213 this->type = ID_FQDN;
1214 this->encoded.ptr = strdup(string + 1);
1215 this->encoded.len = strlen(string + 1);
1216 this->public.matches = (id_match_t (*)
1217 (identification_t*,identification_t*))matches_string;
1218 this->public.equals = (bool (*)
1219 (identification_t*,identification_t*))equals_strcasecmp;
1220 return &this->public;
1221 }
1222 }
1223 else
1224 {
1225 this->type = ID_RFC822_ADDR;
1226 this->encoded.ptr = strdup(string);
1227 this->encoded.len = strlen(string);
1228 this->public.matches = (id_match_t (*)
1229 (identification_t*,identification_t*))matches_string;
1230 this->public.equals = (bool (*)
1231 (identification_t*,identification_t*))equals_strcasecmp;
1232 return &this->public;
1233 }
1234 }
1235 }
1236
1237 /*
1238 * Described in header.
1239 */
1240 identification_t *identification_create_from_encoding(id_type_t type, chunk_t encoded)
1241 {
1242 private_identification_t *this = identification_create();
1243
1244 this->type = type;
1245 switch (type)
1246 {
1247 case ID_ANY:
1248 this->public.matches = (id_match_t (*)
1249 (identification_t*,identification_t*))matches_any;
1250 break;
1251 case ID_FQDN:
1252 case ID_RFC822_ADDR:
1253 this->public.matches = (id_match_t (*)
1254 (identification_t*,identification_t*))matches_string;
1255 this->public.equals = (bool (*)
1256 (identification_t*,identification_t*))equals_strcasecmp;
1257 break;
1258 case ID_DER_ASN1_DN:
1259 this->public.equals = (bool (*)
1260 (identification_t*,identification_t*))equals_dn;
1261 this->public.matches = (id_match_t (*)
1262 (identification_t*,identification_t*))matches_dn;
1263 break;
1264 case ID_IPV4_ADDR:
1265 case ID_IPV6_ADDR:
1266 case ID_DER_ASN1_GN:
1267 case ID_KEY_ID:
1268 case ID_DER_ASN1_GN_URI:
1269 case ID_PUBKEY_INFO_SHA1:
1270 case ID_PUBKEY_SHA1:
1271 case ID_CERT_DER_SHA1:
1272 case ID_IETF_ATTR_STRING:
1273 default:
1274 break;
1275 }
1276
1277 /* apply encoded chunk */
1278 if (type != ID_ANY)
1279 {
1280 this->encoded = chunk_clone(encoded);
1281 }
1282 return &(this->public);
1283 }
1284