Run gperf with --output-file instead of output redirection
[strongswan.git] / src / libstrongswan / utils / identification.c
1 /*
2 * Copyright (C) 2016 Andreas Steffen
3 * Copyright (C) 2009-2015 Tobias Brunner
4 * Copyright (C) 2005-2009 Martin Willi
5 * Copyright (C) 2005 Jan Hutter
6 * HSR Hochschule fuer Technik Rapperswil
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include <string.h>
20 #include <stdio.h>
21 #include <errno.h>
22
23 #include "identification.h"
24
25 #include <utils/utils.h>
26 #include <asn1/oid.h>
27 #include <asn1/asn1.h>
28 #include <crypto/hashers/hasher.h>
29
30 ENUM_BEGIN(id_match_names, ID_MATCH_NONE, ID_MATCH_MAX_WILDCARDS,
31 "MATCH_NONE",
32 "MATCH_ANY",
33 "MATCH_MAX_WILDCARDS");
34 ENUM_NEXT(id_match_names, ID_MATCH_PERFECT, ID_MATCH_PERFECT, ID_MATCH_MAX_WILDCARDS,
35 "MATCH_PERFECT");
36 ENUM_END(id_match_names, ID_MATCH_PERFECT);
37
38 ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID,
39 "ID_ANY",
40 "ID_IPV4_ADDR",
41 "ID_FQDN",
42 "ID_RFC822_ADDR",
43 "ID_IPV4_ADDR_SUBNET",
44 "ID_IPV6_ADDR",
45 "ID_IPV6_ADDR_SUBNET",
46 "ID_IPV4_ADDR_RANGE",
47 "ID_IPV6_ADDR_RANGE",
48 "ID_DER_ASN1_DN",
49 "ID_DER_ASN1_GN",
50 "ID_KEY_ID");
51 ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_DER_ASN1_GN_URI, ID_KEY_ID,
52 "ID_DER_ASN1_GN_URI");
53 ENUM_END(id_type_names, ID_DER_ASN1_GN_URI);
54
55 /**
56 * coding of X.501 distinguished name
57 */
58 typedef struct {
59 const u_char *name;
60 int oid;
61 u_char type;
62 } x501rdn_t;
63
64 static const x501rdn_t x501rdns[] = {
65 {"ND", OID_NAME_DISTINGUISHER, ASN1_PRINTABLESTRING},
66 {"UID", OID_PILOT_USERID, ASN1_PRINTABLESTRING},
67 {"DC", OID_PILOT_DOMAIN_COMPONENT, ASN1_PRINTABLESTRING},
68 {"CN", OID_COMMON_NAME, ASN1_PRINTABLESTRING},
69 {"S", OID_SURNAME, ASN1_PRINTABLESTRING},
70 {"SN", OID_SERIAL_NUMBER, ASN1_PRINTABLESTRING},
71 {"serialNumber", OID_SERIAL_NUMBER, ASN1_PRINTABLESTRING},
72 {"C", OID_COUNTRY, ASN1_PRINTABLESTRING},
73 {"L", OID_LOCALITY, ASN1_PRINTABLESTRING},
74 {"ST", OID_STATE_OR_PROVINCE, ASN1_PRINTABLESTRING},
75 {"STREET", OID_STREET_ADDRESS, ASN1_PRINTABLESTRING},
76 {"O", OID_ORGANIZATION, ASN1_PRINTABLESTRING},
77 {"OU", OID_ORGANIZATION_UNIT, ASN1_PRINTABLESTRING},
78 {"T", OID_TITLE, ASN1_PRINTABLESTRING},
79 {"D", OID_DESCRIPTION, ASN1_PRINTABLESTRING},
80 {"postalAddress", OID_POSTAL_ADDRESS, ASN1_PRINTABLESTRING},
81 {"postalCode", OID_POSTAL_CODE, ASN1_PRINTABLESTRING},
82 {"N", OID_NAME, ASN1_PRINTABLESTRING},
83 {"G", OID_GIVEN_NAME, ASN1_PRINTABLESTRING},
84 {"I", OID_INITIALS, ASN1_PRINTABLESTRING},
85 {"dnQualifier", OID_DN_QUALIFIER, ASN1_PRINTABLESTRING},
86 {"dmdName", OID_DMD_NAME, ASN1_PRINTABLESTRING},
87 {"pseudonym", OID_PSEUDONYM, ASN1_PRINTABLESTRING},
88 {"ID", OID_UNIQUE_IDENTIFIER, ASN1_PRINTABLESTRING},
89 {"EN", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING},
90 {"employeeNumber", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING},
91 {"E", OID_EMAIL_ADDRESS, ASN1_IA5STRING},
92 {"Email", OID_EMAIL_ADDRESS, ASN1_IA5STRING},
93 {"emailAddress", OID_EMAIL_ADDRESS, ASN1_IA5STRING},
94 {"UN", OID_UNSTRUCTURED_NAME, ASN1_IA5STRING},
95 {"unstructuredName", OID_UNSTRUCTURED_NAME, ASN1_IA5STRING},
96 {"UA", OID_UNSTRUCTURED_ADDRESS, ASN1_PRINTABLESTRING},
97 {"unstructuredAddress", OID_UNSTRUCTURED_ADDRESS, ASN1_PRINTABLESTRING},
98 {"TCGID", OID_TCGID, ASN1_PRINTABLESTRING}
99 };
100
101 /**
102 * maximum number of RDNs in atodn()
103 */
104 #define RDN_MAX 20
105
106
107 typedef struct private_identification_t private_identification_t;
108
109 /**
110 * Private data of an identification_t object.
111 */
112 struct private_identification_t {
113 /**
114 * Public interface.
115 */
116 identification_t public;
117
118 /**
119 * Encoded representation of this ID.
120 */
121 chunk_t encoded;
122
123 /**
124 * Type of this ID.
125 */
126 id_type_t type;
127 };
128
129 /**
130 * Enumerator over RDNs
131 */
132 typedef struct {
133 /* implements enumerator interface */
134 enumerator_t public;
135 /* next set to parse, if any */
136 chunk_t sets;
137 /* next sequence in set, if any */
138 chunk_t seqs;
139 } rdn_enumerator_t;
140
141 METHOD(enumerator_t, rdn_enumerate, bool,
142 rdn_enumerator_t *this, va_list args)
143 {
144 chunk_t rdn, *oid, *data;
145 u_char *type;
146
147 VA_ARGS_VGET(args, oid, type, data);
148
149 /* a DN contains one or more SET, each containing one or more SEQUENCES,
150 * each containing a OID/value RDN */
151 if (!this->seqs.len)
152 {
153 /* no SEQUENCEs in current SET, parse next SET */
154 if (asn1_unwrap(&this->sets, &this->seqs) != ASN1_SET)
155 {
156 return FALSE;
157 }
158 }
159 if (asn1_unwrap(&this->seqs, &rdn) == ASN1_SEQUENCE &&
160 asn1_unwrap(&rdn, oid) == ASN1_OID)
161 {
162 int t = asn1_unwrap(&rdn, data);
163
164 if (t != ASN1_INVALID)
165 {
166 *type = t;
167 return TRUE;
168 }
169 }
170 return FALSE;
171 }
172
173 /**
174 * Create an enumerator over all RDNs (oid, string type, data) of a DN
175 */
176 static enumerator_t* create_rdn_enumerator(chunk_t dn)
177 {
178 rdn_enumerator_t *e;
179
180 INIT(e,
181 .public = {
182 .enumerate = enumerator_enumerate_default,
183 .venumerate = _rdn_enumerate,
184 .destroy = (void*)free,
185 },
186 );
187
188 /* a DN is a SEQUENCE, get the first SET of it */
189 if (asn1_unwrap(&dn, &e->sets) == ASN1_SEQUENCE)
190 {
191 e->seqs = chunk_empty;
192 return &e->public;
193 }
194 free(e);
195 return enumerator_create_empty();
196 }
197
198 /**
199 * Part enumerator over RDNs
200 */
201 typedef struct {
202 /* implements enumerator interface */
203 enumerator_t public;
204 /* inner RDN enumerator */
205 enumerator_t *inner;
206 } rdn_part_enumerator_t;
207
208 METHOD(enumerator_t, rdn_part_enumerate, bool,
209 rdn_part_enumerator_t *this, va_list args)
210 {
211 int i, known_oid, strtype;
212 chunk_t oid, inner_data, *data;
213 id_part_t *type;
214 static const struct {
215 int oid;
216 id_part_t type;
217 } oid2part[] = {
218 {OID_COMMON_NAME, ID_PART_RDN_CN},
219 {OID_SURNAME, ID_PART_RDN_S},
220 {OID_SERIAL_NUMBER, ID_PART_RDN_SN},
221 {OID_COUNTRY, ID_PART_RDN_C},
222 {OID_LOCALITY, ID_PART_RDN_L},
223 {OID_STATE_OR_PROVINCE, ID_PART_RDN_ST},
224 {OID_ORGANIZATION, ID_PART_RDN_O},
225 {OID_ORGANIZATION_UNIT, ID_PART_RDN_OU},
226 {OID_TITLE, ID_PART_RDN_T},
227 {OID_DESCRIPTION, ID_PART_RDN_D},
228 {OID_NAME, ID_PART_RDN_N},
229 {OID_GIVEN_NAME, ID_PART_RDN_G},
230 {OID_INITIALS, ID_PART_RDN_I},
231 {OID_DN_QUALIFIER, ID_PART_RDN_DNQ},
232 {OID_DMD_NAME, ID_PART_RDN_DMDN},
233 {OID_PSEUDONYM, ID_PART_RDN_PN},
234 {OID_UNIQUE_IDENTIFIER, ID_PART_RDN_ID},
235 {OID_EMAIL_ADDRESS, ID_PART_RDN_E},
236 {OID_EMPLOYEE_NUMBER, ID_PART_RDN_EN},
237 };
238
239 VA_ARGS_VGET(args, type, data);
240
241 while (this->inner->enumerate(this->inner, &oid, &strtype, &inner_data))
242 {
243 known_oid = asn1_known_oid(oid);
244 for (i = 0; i < countof(oid2part); i++)
245 {
246 if (oid2part[i].oid == known_oid)
247 {
248 *type = oid2part[i].type;
249 *data = inner_data;
250 return TRUE;
251 }
252 }
253 }
254 return FALSE;
255 }
256
257 METHOD(enumerator_t, rdn_part_enumerator_destroy, void,
258 rdn_part_enumerator_t *this)
259 {
260 this->inner->destroy(this->inner);
261 free(this);
262 }
263
264 METHOD(identification_t, create_part_enumerator, enumerator_t*,
265 private_identification_t *this)
266 {
267 switch (this->type)
268 {
269 case ID_DER_ASN1_DN:
270 {
271 rdn_part_enumerator_t *e;
272
273 INIT(e,
274 .inner = create_rdn_enumerator(this->encoded),
275 .public = {
276 .enumerate = enumerator_enumerate_default,
277 .venumerate = _rdn_part_enumerate,
278 .destroy = _rdn_part_enumerator_destroy,
279 },
280 );
281 return &e->public;
282 }
283 case ID_RFC822_ADDR:
284 /* TODO */
285 case ID_FQDN:
286 /* TODO */
287 default:
288 return enumerator_create_empty();
289 }
290 }
291
292 /**
293 * Print a separator between two RDNs
294 */
295 static inline bool print_separator(char **buf, size_t *len)
296 {
297 int written;
298
299 written = snprintf(*buf, *len, ", ");
300 if (written < 0 || written >= *len)
301 {
302 return FALSE;
303 }
304 *buf += written;
305 *len -= written;
306 return TRUE;
307 }
308
309 /**
310 * Print a DN with all its RDN in a buffer to present it to the user
311 */
312 static void dntoa(chunk_t dn, char *buf, size_t len)
313 {
314 enumerator_t *e;
315 chunk_t oid_data, data, printable;
316 u_char type;
317 int oid, written;
318 bool finished = FALSE, empty = TRUE;
319
320 e = create_rdn_enumerator(dn);
321 while (e->enumerate(e, &oid_data, &type, &data))
322 {
323 empty = FALSE;
324
325 /* previous RDN was empty but it wasn't the last one */
326 if (finished && !print_separator(&buf, &len))
327 {
328 break;
329 }
330 finished = FALSE;
331
332 oid = asn1_known_oid(oid_data);
333 if (oid == OID_UNKNOWN)
334 {
335 written = snprintf(buf, len, "%#B=", &oid_data);
336 }
337 else
338 {
339 written = snprintf(buf, len,"%s=", oid_names[oid].name);
340 }
341 if (written < 0 || written >= len)
342 {
343 break;
344 }
345 buf += written;
346 len -= written;
347
348 written = 0;
349 chunk_printable(data, &printable, '?');
350 if (printable.ptr)
351 {
352 written = snprintf(buf, len, "%.*s", (int)printable.len,
353 printable.ptr);
354 }
355 chunk_free(&printable);
356 if (written < 0 || written >= len)
357 {
358 break;
359 }
360 buf += written;
361 len -= written;
362
363 if (!data.ptr)
364 { /* we can't calculate if we're finished, assume we are */
365 finished = TRUE;
366 }
367 else if (data.ptr + data.len == dn.ptr + dn.len)
368 {
369 finished = TRUE;
370 break;
371 }
372 else if (!print_separator(&buf, &len))
373 {
374 break;
375 }
376 }
377 if (empty)
378 {
379 snprintf(buf, len, "");
380 }
381 else if (!finished)
382 {
383 snprintf(buf, len, "(invalid ID_DER_ASN1_DN)");
384 }
385 e->destroy(e);
386 }
387
388 /**
389 * Converts an LDAP-style human-readable ASCII-encoded
390 * ASN.1 distinguished name into binary DER-encoded format
391 */
392 static status_t atodn(char *src, chunk_t *dn)
393 {
394 /* finite state machine for atodn */
395 typedef enum {
396 SEARCH_OID = 0,
397 READ_OID = 1,
398 SEARCH_NAME = 2,
399 READ_NAME = 3,
400 UNKNOWN_OID = 4
401 } state_t;
402
403 chunk_t oid = chunk_empty;
404 chunk_t name = chunk_empty;
405 chunk_t rdns[RDN_MAX];
406 int rdn_count = 0;
407 int dn_len = 0;
408 int whitespace = 0;
409 int i = 0;
410 asn1_t rdn_type;
411 state_t state = SEARCH_OID;
412 status_t status = SUCCESS;
413 char sep = '\0';
414
415 do
416 {
417 switch (state)
418 {
419 case SEARCH_OID:
420 if (!sep && *src == '/')
421 { /* use / as separator if the string starts with a slash */
422 sep = '/';
423 break;
424 }
425 if (*src != ' ' && *src != '\0')
426 {
427 if (!sep)
428 { /* use , as separator by default */
429 sep = ',';
430 }
431 oid.ptr = src;
432 oid.len = 1;
433 state = READ_OID;
434 }
435 break;
436 case READ_OID:
437 if (*src != ' ' && *src != '=')
438 {
439 oid.len++;
440 }
441 else
442 {
443 bool found = FALSE;
444
445 for (i = 0; i < countof(x501rdns); i++)
446 {
447 if (strlen(x501rdns[i].name) == oid.len &&
448 strncasecmp(x501rdns[i].name, oid.ptr, oid.len) == 0)
449 {
450 found = TRUE;
451 break;
452 }
453 }
454 if (!found)
455 {
456 status = NOT_SUPPORTED;
457 state = UNKNOWN_OID;
458 break;
459 }
460 /* reset oid and change state */
461 oid = chunk_empty;
462 state = SEARCH_NAME;
463 }
464 break;
465 case SEARCH_NAME:
466 if (*src == ' ' || *src == '=')
467 {
468 break;
469 }
470 else if (*src != sep && *src != '\0')
471 {
472 name.ptr = src;
473 name.len = 1;
474 whitespace = 0;
475 state = READ_NAME;
476 break;
477 }
478 name = chunk_empty;
479 whitespace = 0;
480 state = READ_NAME;
481 /* fall-through */
482 case READ_NAME:
483 if (*src != sep && *src != '\0')
484 {
485 name.len++;
486 if (*src == ' ')
487 whitespace++;
488 else
489 whitespace = 0;
490 }
491 else
492 {
493 name.len -= whitespace;
494 rdn_type = (x501rdns[i].type == ASN1_PRINTABLESTRING
495 && !asn1_is_printablestring(name))
496 ? ASN1_UTF8STRING : x501rdns[i].type;
497
498 if (rdn_count < RDN_MAX)
499 {
500 chunk_t rdn_oid;
501
502 rdn_oid = asn1_build_known_oid(x501rdns[i].oid);
503 if (rdn_oid.len)
504 {
505 rdns[rdn_count] =
506 asn1_wrap(ASN1_SET, "m",
507 asn1_wrap(ASN1_SEQUENCE, "mm",
508 rdn_oid,
509 asn1_wrap(rdn_type, "c", name)
510 )
511 );
512 dn_len += rdns[rdn_count++].len;
513 }
514 else
515 {
516 status = INVALID_ARG;
517 }
518 }
519 else
520 {
521 status = OUT_OF_RES;
522 }
523 /* reset name and change state */
524 name = chunk_empty;
525 state = SEARCH_OID;
526 }
527 break;
528 case UNKNOWN_OID:
529 break;
530 }
531 } while (*src++ != '\0');
532
533 if (state == READ_OID)
534 { /* unterminated OID */
535 status = INVALID_ARG;
536 }
537
538 /* build the distinguished name sequence */
539 {
540 int i;
541 u_char *pos = asn1_build_object(dn, ASN1_SEQUENCE, dn_len);
542
543 for (i = 0; i < rdn_count; i++)
544 {
545 memcpy(pos, rdns[i].ptr, rdns[i].len);
546 pos += rdns[i].len;
547 free(rdns[i].ptr);
548 }
549 }
550 if (status != SUCCESS)
551 {
552 free(dn->ptr);
553 *dn = chunk_empty;
554 }
555 return status;
556 }
557
558 METHOD(identification_t, get_encoding, chunk_t,
559 private_identification_t *this)
560 {
561 return this->encoded;
562 }
563
564 METHOD(identification_t, get_type, id_type_t,
565 private_identification_t *this)
566 {
567 return this->type;
568 }
569
570 METHOD(identification_t, contains_wildcards_dn, bool,
571 private_identification_t *this)
572 {
573 enumerator_t *enumerator;
574 bool contains = FALSE;
575 id_part_t type;
576 chunk_t data;
577
578 enumerator = create_part_enumerator(this);
579 while (enumerator->enumerate(enumerator, &type, &data))
580 {
581 if (data.len == 1 && data.ptr[0] == '*')
582 {
583 contains = TRUE;
584 break;
585 }
586 }
587 enumerator->destroy(enumerator);
588 return contains;
589 }
590
591 METHOD(identification_t, contains_wildcards_memchr, bool,
592 private_identification_t *this)
593 {
594 return memchr(this->encoded.ptr, '*', this->encoded.len) != NULL;
595 }
596
597 METHOD(identification_t, hash_binary, u_int,
598 private_identification_t *this, u_int inc)
599 {
600 u_int hash;
601
602 hash = chunk_hash_inc(chunk_from_thing(this->type), inc);
603 if (this->type != ID_ANY)
604 {
605 hash = chunk_hash_inc(this->encoded, hash);
606 }
607 return hash;
608 }
609
610 METHOD(identification_t, equals_binary, bool,
611 private_identification_t *this, identification_t *other)
612 {
613 if (this->type == other->get_type(other))
614 {
615 if (this->type == ID_ANY)
616 {
617 return TRUE;
618 }
619 return chunk_equals(this->encoded, other->get_encoding(other));
620 }
621 return FALSE;
622 }
623
624 /**
625 * Compare to DNs, for equality if wc == NULL, for match otherwise
626 */
627 static bool compare_dn(chunk_t t_dn, chunk_t o_dn, int *wc)
628 {
629 enumerator_t *t, *o;
630 chunk_t t_oid, o_oid, t_data, o_data;
631 u_char t_type, o_type;
632 bool t_next, o_next, finished = FALSE;
633
634 if (wc)
635 {
636 *wc = 0;
637 }
638 else
639 {
640 if (t_dn.len != o_dn.len)
641 {
642 return FALSE;
643 }
644 }
645 /* try a binary compare */
646 if (chunk_equals(t_dn, o_dn))
647 {
648 return TRUE;
649 }
650
651 t = create_rdn_enumerator(t_dn);
652 o = create_rdn_enumerator(o_dn);
653 while (TRUE)
654 {
655 t_next = t->enumerate(t, &t_oid, &t_type, &t_data);
656 o_next = o->enumerate(o, &o_oid, &o_type, &o_data);
657
658 if (!o_next && !t_next)
659 {
660 break;
661 }
662 finished = FALSE;
663 if (o_next != t_next)
664 {
665 break;
666 }
667 if (!chunk_equals(t_oid, o_oid))
668 {
669 break;
670 }
671 if (wc && o_data.len == 1 && o_data.ptr[0] == '*')
672 {
673 (*wc)++;
674 }
675 else
676 {
677 if (t_data.len != o_data.len)
678 {
679 break;
680 }
681 if (t_type == o_type &&
682 (t_type == ASN1_PRINTABLESTRING ||
683 (t_type == ASN1_IA5STRING &&
684 asn1_known_oid(t_oid) == OID_EMAIL_ADDRESS)))
685 { /* ignore case for printableStrings and email RDNs */
686 if (strncasecmp(t_data.ptr, o_data.ptr, t_data.len) != 0)
687 {
688 break;
689 }
690 }
691 else
692 { /* respect case and length for everything else */
693 if (!memeq(t_data.ptr, o_data.ptr, t_data.len))
694 {
695 break;
696 }
697 }
698 }
699 /* the enumerator returns FALSE on parse error, we are finished
700 * if we have reached the end of the DN only */
701 if ((t_data.ptr + t_data.len == t_dn.ptr + t_dn.len) &&
702 (o_data.ptr + o_data.len == o_dn.ptr + o_dn.len))
703 {
704 finished = TRUE;
705 }
706 }
707 t->destroy(t);
708 o->destroy(o);
709 return finished;
710 }
711
712 METHOD(identification_t, equals_dn, bool,
713 private_identification_t *this, identification_t *other)
714 {
715 return compare_dn(this->encoded, other->get_encoding(other), NULL);
716 }
717
718 METHOD(identification_t, hash_dn, u_int,
719 private_identification_t *this, u_int inc)
720 {
721 enumerator_t *rdns;
722 chunk_t oid, data;
723 u_char type;
724 u_int hash;
725
726 hash = chunk_hash_inc(chunk_from_thing(this->type), inc);
727 rdns = create_rdn_enumerator(this->encoded);
728 while (rdns->enumerate(rdns, &oid, &type, &data))
729 {
730 hash = chunk_hash_inc(data, chunk_hash_inc(oid, hash));
731 }
732 rdns->destroy(rdns);
733 return hash;
734 }
735
736 METHOD(identification_t, equals_strcasecmp, bool,
737 private_identification_t *this, identification_t *other)
738 {
739 chunk_t encoded = other->get_encoding(other);
740
741 /* we do some extra sanity checks to check for invalid IDs with a
742 * terminating null in it. */
743 if (this->type == other->get_type(other) &&
744 this->encoded.len == encoded.len &&
745 memchr(this->encoded.ptr, 0, this->encoded.len) == NULL &&
746 memchr(encoded.ptr, 0, encoded.len) == NULL &&
747 strncasecmp(this->encoded.ptr, encoded.ptr, this->encoded.len) == 0)
748 {
749 return TRUE;
750 }
751 return FALSE;
752 }
753
754 METHOD(identification_t, matches_binary, id_match_t,
755 private_identification_t *this, identification_t *other)
756 {
757 if (other->get_type(other) == ID_ANY)
758 {
759 return ID_MATCH_ANY;
760 }
761 if (this->type == other->get_type(other) &&
762 chunk_equals(this->encoded, other->get_encoding(other)))
763 {
764 return ID_MATCH_PERFECT;
765 }
766 return ID_MATCH_NONE;
767 }
768
769 METHOD(identification_t, matches_string, id_match_t,
770 private_identification_t *this, identification_t *other)
771 {
772 chunk_t encoded = other->get_encoding(other);
773 u_int len = encoded.len;
774
775 if (other->get_type(other) == ID_ANY)
776 {
777 return ID_MATCH_ANY;
778 }
779 if (this->type != other->get_type(other))
780 {
781 return ID_MATCH_NONE;
782 }
783 /* try a equals check first */
784 if (equals_strcasecmp(this, other))
785 {
786 return ID_MATCH_PERFECT;
787 }
788 if (len == 0 || this->encoded.len < len)
789 {
790 return ID_MATCH_NONE;
791 }
792
793 /* check for single wildcard at the head of the string */
794 if (*encoded.ptr == '*')
795 {
796 /* single asterisk matches any string */
797 if (len-- == 1)
798 { /* not better than ID_ANY */
799 return ID_MATCH_ANY;
800 }
801 if (strncasecmp(this->encoded.ptr + this->encoded.len - len,
802 encoded.ptr + 1, len) == 0)
803 {
804 return ID_MATCH_ONE_WILDCARD;
805 }
806 }
807 return ID_MATCH_NONE;
808 }
809
810 METHOD(identification_t, matches_any, id_match_t,
811 private_identification_t *this, identification_t *other)
812 {
813 if (other->get_type(other) == ID_ANY)
814 {
815 return ID_MATCH_ANY;
816 }
817 return ID_MATCH_NONE;
818 }
819
820 METHOD(identification_t, matches_dn, id_match_t,
821 private_identification_t *this, identification_t *other)
822 {
823 int wc;
824
825 if (other->get_type(other) == ID_ANY)
826 {
827 return ID_MATCH_ANY;
828 }
829
830 if (this->type == other->get_type(other))
831 {
832 if (compare_dn(this->encoded, other->get_encoding(other), &wc))
833 {
834 wc = min(wc, ID_MATCH_ONE_WILDCARD - ID_MATCH_MAX_WILDCARDS);
835 return ID_MATCH_PERFECT - wc;
836 }
837 }
838 return ID_MATCH_NONE;
839 }
840
841 /**
842 * Transform netmask to CIDR bits
843 */
844 static int netmask_to_cidr(char *netmask, size_t address_size)
845 {
846 uint8_t byte;
847 int i, netbits = 0;
848
849 for (i = 0; i < address_size; i++)
850 {
851 byte = netmask[i];
852
853 if (byte == 0x00)
854 {
855 break;
856 }
857 if (byte == 0xff)
858 {
859 netbits += 8;
860 }
861 else
862 {
863 while (byte & 0x80)
864 {
865 netbits++;
866 byte <<= 1;
867 }
868 }
869 }
870 return netbits;
871 }
872
873 METHOD(identification_t, matches_range, id_match_t,
874 private_identification_t *this, identification_t *other)
875 {
876 chunk_t other_encoding;
877 uint8_t *address, *from, *to, *network, *netmask;
878 size_t address_size = 0;
879 int netbits, range_sign, i;
880
881 if (other->get_type(other) == ID_ANY)
882 {
883 return ID_MATCH_ANY;
884 }
885 if (this->type == other->get_type(other) &&
886 chunk_equals(this->encoded, other->get_encoding(other)))
887 {
888 return ID_MATCH_PERFECT;
889 }
890 if ((this->type == ID_IPV4_ADDR &&
891 other->get_type(other) == ID_IPV4_ADDR_SUBNET))
892 {
893 address_size = sizeof(struct in_addr);
894 }
895 else if ((this->type == ID_IPV6_ADDR &&
896 other->get_type(other) == ID_IPV6_ADDR_SUBNET))
897 {
898 address_size = sizeof(struct in6_addr);
899 }
900 if (address_size)
901 {
902 other_encoding = other->get_encoding(other);
903 if (this->encoded.len != address_size ||
904 other_encoding.len != 2 * address_size)
905 {
906 return ID_MATCH_NONE;
907 }
908 address = this->encoded.ptr;
909 network = other_encoding.ptr;
910 netmask = other_encoding.ptr + address_size;
911 netbits = netmask_to_cidr(netmask, address_size);
912
913 if (netbits == 0)
914 {
915 return ID_MATCH_MAX_WILDCARDS;
916 }
917 if (netbits == 8 * address_size)
918 {
919 return memeq(address, network, address_size) ?
920 ID_MATCH_PERFECT : ID_MATCH_NONE;
921 }
922 for (i = 0; i < (netbits + 7)/8; i++)
923 {
924 if ((address[i] ^ network[i]) & netmask[i])
925 {
926 return ID_MATCH_NONE;
927 }
928 }
929 return ID_MATCH_ONE_WILDCARD;
930 }
931 if ((this->type == ID_IPV4_ADDR &&
932 other->get_type(other) == ID_IPV4_ADDR_RANGE))
933 {
934 address_size = sizeof(struct in_addr);
935 }
936 else if ((this->type == ID_IPV6_ADDR &&
937 other->get_type(other) == ID_IPV6_ADDR_RANGE))
938 {
939 address_size = sizeof(struct in6_addr);
940 }
941 if (address_size)
942 {
943 other_encoding = other->get_encoding(other);
944 if (this->encoded.len != address_size ||
945 other_encoding.len != 2 * address_size)
946 {
947 return ID_MATCH_NONE;
948 }
949 address = this->encoded.ptr;
950 from = other_encoding.ptr;
951 to = other_encoding.ptr + address_size;
952
953 range_sign = memcmp(to, from, address_size);
954 if (range_sign < 0)
955 { /* to is smaller than from */
956 return ID_MATCH_NONE;
957 }
958
959 /* check lower bound */
960 for (i = 0; i < address_size; i++)
961 {
962 if (address[i] != from[i])
963 {
964 if (address[i] < from[i])
965 {
966 return ID_MATCH_NONE;
967 }
968 break;
969 }
970 }
971
972 /* check upper bound */
973 for (i = 0; i < address_size; i++)
974 {
975 if (address[i] != to[i])
976 {
977 if (address[i] > to[i])
978 {
979 return ID_MATCH_NONE;
980 }
981 break;
982 }
983 }
984 return range_sign ? ID_MATCH_ONE_WILDCARD : ID_MATCH_PERFECT;
985 }
986 return ID_MATCH_NONE;
987 }
988
989 /**
990 * Described in header.
991 */
992 int identification_printf_hook(printf_hook_data_t *data,
993 printf_hook_spec_t *spec, const void *const *args)
994 {
995 private_identification_t *this = *((private_identification_t**)(args[0]));
996 chunk_t proper;
997 char buf[BUF_LEN], *pos;
998 size_t len, address_size;
999 int written;
1000
1001 if (this == NULL)
1002 {
1003 return print_in_hook(data, "%*s", spec->width, "(null)");
1004 }
1005
1006 switch (this->type)
1007 {
1008 case ID_ANY:
1009 snprintf(buf, BUF_LEN, "%%any");
1010 break;
1011 case ID_IPV4_ADDR:
1012 if (this->encoded.len < sizeof(struct in_addr) ||
1013 inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
1014 {
1015 snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR)");
1016 }
1017 break;
1018 case ID_IPV4_ADDR_SUBNET:
1019 address_size = sizeof(struct in_addr);
1020 if (this->encoded.len < 2 * address_size ||
1021 inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
1022 {
1023 snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_SUBNET)");
1024 break;
1025 }
1026 written = strlen(buf);
1027 snprintf(buf + written, BUF_LEN - written, "/%d",
1028 netmask_to_cidr(this->encoded.ptr + address_size,
1029 address_size));
1030 break;
1031 case ID_IPV4_ADDR_RANGE:
1032 address_size = sizeof(struct in_addr);
1033 if (this->encoded.len < 2 * address_size ||
1034 inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
1035 {
1036 snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_RANGE)");
1037 break;
1038 }
1039 written = strlen(buf);
1040 pos = buf + written;
1041 len = BUF_LEN - written;
1042 written = snprintf(pos, len, "-");
1043 if (written < 0 || written >= len ||
1044 inet_ntop(AF_INET, this->encoded.ptr + address_size,
1045 pos + written, len - written) == NULL)
1046 {
1047 snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_RANGE)");
1048 }
1049 break;
1050 case ID_IPV6_ADDR:
1051 if (this->encoded.len < sizeof(struct in6_addr) ||
1052 inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
1053 {
1054 snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR)");
1055 }
1056 break;
1057 case ID_IPV6_ADDR_SUBNET:
1058 address_size = sizeof(struct in6_addr);
1059 if (this->encoded.len < 2 * address_size ||
1060 inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
1061 {
1062 snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_SUBNET)");
1063 }
1064 else
1065 {
1066 written = strlen(buf);
1067 snprintf(buf + written, BUF_LEN - written, "/%d",
1068 netmask_to_cidr(this->encoded.ptr + address_size,
1069 address_size));
1070 }
1071 break;
1072 case ID_IPV6_ADDR_RANGE:
1073 address_size = sizeof(struct in6_addr);
1074 if (this->encoded.len < 2 * address_size ||
1075 inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
1076 {
1077 snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_RANGE)");
1078 break;
1079 }
1080 written = strlen(buf);
1081 pos = buf + written;
1082 len = BUF_LEN - written;
1083 written = snprintf(pos, len, "-");
1084 if (written < 0 || written >= len ||
1085 inet_ntop(AF_INET6, this->encoded.ptr + address_size,
1086 pos + written, len - written) == NULL)
1087 {
1088 snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_RANGE)");
1089 }
1090 break;
1091 case ID_FQDN:
1092 case ID_RFC822_ADDR:
1093 case ID_DER_ASN1_GN_URI:
1094 chunk_printable(this->encoded, &proper, '?');
1095 snprintf(buf, BUF_LEN, "%.*s", (int)proper.len, proper.ptr);
1096 chunk_free(&proper);
1097 break;
1098 case ID_DER_ASN1_DN:
1099 dntoa(this->encoded, buf, BUF_LEN);
1100 break;
1101 case ID_DER_ASN1_GN:
1102 snprintf(buf, BUF_LEN, "(ASN.1 general name)");
1103 break;
1104 case ID_KEY_ID:
1105 if (chunk_printable(this->encoded, NULL, '?') &&
1106 this->encoded.len != HASH_SIZE_SHA1)
1107 { /* fully printable, use ascii version */
1108 snprintf(buf, BUF_LEN, "%.*s", (int)this->encoded.len,
1109 this->encoded.ptr);
1110 }
1111 else
1112 { /* not printable, hex dump */
1113 snprintf(buf, BUF_LEN, "%#B", &this->encoded);
1114 }
1115 break;
1116 default:
1117 snprintf(buf, BUF_LEN, "(unknown ID type: %d)", this->type);
1118 break;
1119 }
1120 if (spec->minus)
1121 {
1122 return print_in_hook(data, "%-*s", spec->width, buf);
1123 }
1124 return print_in_hook(data, "%*s", spec->width, buf);
1125 }
1126
1127 METHOD(identification_t, clone_, identification_t*,
1128 private_identification_t *this)
1129 {
1130 private_identification_t *clone = malloc_thing(private_identification_t);
1131
1132 memcpy(clone, this, sizeof(private_identification_t));
1133 if (this->encoded.len)
1134 {
1135 clone->encoded = chunk_clone(this->encoded);
1136 }
1137 return &clone->public;
1138 }
1139
1140 METHOD(identification_t, destroy, void,
1141 private_identification_t *this)
1142 {
1143 chunk_free(&this->encoded);
1144 free(this);
1145 }
1146
1147 /**
1148 * Generic constructor used for the other constructors.
1149 */
1150 static private_identification_t *identification_create(id_type_t type)
1151 {
1152 private_identification_t *this;
1153
1154 INIT(this,
1155 .public = {
1156 .get_encoding = _get_encoding,
1157 .get_type = _get_type,
1158 .create_part_enumerator = _create_part_enumerator,
1159 .clone = _clone_,
1160 .destroy = _destroy,
1161 },
1162 .type = type,
1163 );
1164
1165 switch (type)
1166 {
1167 case ID_ANY:
1168 this->public.hash = _hash_binary;
1169 this->public.equals = _equals_binary;
1170 this->public.matches = _matches_any;
1171 this->public.contains_wildcards = return_true;
1172 break;
1173 case ID_FQDN:
1174 case ID_RFC822_ADDR:
1175 this->public.hash = _hash_binary;
1176 this->public.equals = _equals_strcasecmp;
1177 this->public.matches = _matches_string;
1178 this->public.contains_wildcards = _contains_wildcards_memchr;
1179 break;
1180 case ID_DER_ASN1_DN:
1181 this->public.hash = _hash_dn;
1182 this->public.equals = _equals_dn;
1183 this->public.matches = _matches_dn;
1184 this->public.contains_wildcards = _contains_wildcards_dn;
1185 break;
1186 case ID_IPV4_ADDR:
1187 case ID_IPV6_ADDR:
1188 this->public.hash = _hash_binary;
1189 this->public.equals = _equals_binary;
1190 this->public.matches = _matches_range;
1191 this->public.contains_wildcards = return_false;
1192 break;
1193 default:
1194 this->public.hash = _hash_binary;
1195 this->public.equals = _equals_binary;
1196 this->public.matches = _matches_binary;
1197 this->public.contains_wildcards = return_false;
1198 break;
1199 }
1200 return this;
1201 }
1202
1203 /**
1204 * Create an identity for a specific type, determined by prefix
1205 */
1206 static private_identification_t* create_from_string_with_prefix_type(char *str)
1207 {
1208 struct {
1209 const char *str;
1210 id_type_t type;
1211 } prefixes[] = {
1212 { "ipv4:", ID_IPV4_ADDR },
1213 { "ipv6:", ID_IPV6_ADDR },
1214 { "ipv4net:", ID_IPV4_ADDR_SUBNET },
1215 { "ipv6net:", ID_IPV6_ADDR_SUBNET },
1216 { "ipv4range:", ID_IPV4_ADDR_RANGE },
1217 { "ipv6range:", ID_IPV6_ADDR_RANGE },
1218 { "rfc822:", ID_RFC822_ADDR },
1219 { "email:", ID_RFC822_ADDR },
1220 { "userfqdn:", ID_USER_FQDN },
1221 { "fqdn:", ID_FQDN },
1222 { "dns:", ID_FQDN },
1223 { "asn1dn:", ID_DER_ASN1_DN },
1224 { "asn1gn:", ID_DER_ASN1_GN },
1225 { "xmppaddr:", ID_DER_ASN1_GN },
1226 { "keyid:", ID_KEY_ID },
1227 };
1228 private_identification_t *this;
1229 int i;
1230
1231 for (i = 0; i < countof(prefixes); i++)
1232 {
1233 if (strcasepfx(str, prefixes[i].str))
1234 {
1235 this = identification_create(prefixes[i].type);
1236 str += strlen(prefixes[i].str);
1237
1238 if (*str == '#')
1239 {
1240 this->encoded = chunk_from_hex(chunk_from_str(str + 1), NULL);
1241 }
1242 else
1243 {
1244 this->encoded = chunk_clone(chunk_from_str(str));
1245 }
1246
1247 if (prefixes[i].type == ID_DER_ASN1_GN &&
1248 strcasepfx(prefixes[i].str, "xmppaddr:"))
1249 {
1250 this->encoded = asn1_wrap(ASN1_CONTEXT_C_0, "mm",
1251 asn1_build_known_oid(OID_XMPP_ADDR),
1252 asn1_wrap(ASN1_CONTEXT_C_0, "m",
1253 asn1_wrap(ASN1_UTF8STRING, "m",
1254 this->encoded)));
1255 }
1256
1257 return this;
1258 }
1259 }
1260 return NULL;
1261 }
1262
1263 /**
1264 * Create an identity for a specific type, determined by a numerical prefix
1265 *
1266 * The prefix is of the form "{x}:", where x denotes the numerical identity
1267 * type.
1268 */
1269 static private_identification_t* create_from_string_with_num_type(char *str)
1270 {
1271 private_identification_t *this;
1272 u_long type;
1273
1274 if (*str++ != '{')
1275 {
1276 return NULL;
1277 }
1278 errno = 0;
1279 type = strtoul(str, &str, 0);
1280 if (errno || *str++ != '}' || *str++ != ':')
1281 {
1282 return NULL;
1283 }
1284 this = identification_create(type);
1285 if (*str == '#')
1286 {
1287 this->encoded = chunk_from_hex(chunk_from_str(str + 1), NULL);
1288 }
1289 else
1290 {
1291 this->encoded = chunk_clone(chunk_from_str(str));
1292 }
1293 return this;
1294 }
1295
1296 /**
1297 * Convert to an IPv4/IPv6 host address, subnet or address range
1298 */
1299 static private_identification_t* create_ip_address_from_string(char *string,
1300 bool is_ipv4)
1301 {
1302 private_identification_t *this;
1303 uint8_t encoding[32];
1304 uint8_t *str, *pos, *address, *to_address, *netmask;
1305 size_t address_size;
1306 int bits, bytes, i;
1307 bool has_subnet = FALSE, has_range = FALSE;
1308
1309 address = encoding;
1310 address_size = is_ipv4 ? sizeof(struct in_addr) : sizeof(struct in6_addr);
1311
1312 str = strdup(string);
1313 pos = strchr(str, '/');
1314 if (pos)
1315 { /* separate IP address from optional netmask */
1316
1317 *pos = '\0';
1318 has_subnet = TRUE;
1319 }
1320 else
1321 {
1322 pos = strchr(str, '-');
1323 if (pos)
1324 { /* separate lower address from upper address of IP range */
1325 *pos = '\0';
1326 has_range = TRUE;
1327 }
1328 }
1329
1330 if (inet_pton(is_ipv4 ? AF_INET : AF_INET6, str, address) != 1)
1331 {
1332 free(str);
1333 return NULL;
1334 }
1335
1336 if (has_subnet)
1337 { /* is IP subnet */
1338 bits = atoi(pos + 1);
1339 if (bits > 8 * address_size)
1340 {
1341 free(str);
1342 return NULL;
1343 }
1344 bytes = bits / 8;
1345 bits -= 8 * bytes;
1346 netmask = encoding + address_size;
1347
1348 for (i = 0; i < address_size; i++)
1349 {
1350 if (bytes)
1351 {
1352 *netmask = 0xff;
1353 bytes--;
1354 }
1355 else if (bits)
1356 {
1357 *netmask = 0xff << (8 - bits);
1358 bits = 0;
1359 }
1360 else
1361 {
1362 *netmask = 0x00;
1363 }
1364 *address++ &= *netmask++;
1365 }
1366 this = identification_create(is_ipv4 ? ID_IPV4_ADDR_SUBNET :
1367 ID_IPV6_ADDR_SUBNET);
1368 this->encoded = chunk_clone(chunk_create(encoding, 2 * address_size));
1369 }
1370 else if (has_range)
1371 { /* is IP range */
1372 to_address = encoding + address_size;
1373
1374 if (inet_pton(is_ipv4 ? AF_INET : AF_INET6, pos + 1, to_address) != 1)
1375 {
1376 free(str);
1377 return NULL;
1378 }
1379 for (i = 0; i < address_size; i++)
1380 {
1381 if (address[i] != to_address[i])
1382 {
1383 if (address[i] > to_address[i])
1384 {
1385 free(str);
1386 return NULL;
1387 }
1388 break;
1389 }
1390 }
1391 this = identification_create(is_ipv4 ? ID_IPV4_ADDR_RANGE :
1392 ID_IPV6_ADDR_RANGE);
1393 this->encoded = chunk_clone(chunk_create(encoding, 2 * address_size));
1394 }
1395 else
1396 { /* is IP host address */
1397 this = identification_create(is_ipv4 ? ID_IPV4_ADDR : ID_IPV6_ADDR);
1398 this->encoded = chunk_clone(chunk_create(encoding, address_size));
1399 }
1400 free(str);
1401
1402 return this;
1403 }
1404
1405 /*
1406 * Described in header.
1407 */
1408 identification_t *identification_create_from_string(char *string)
1409 {
1410 private_identification_t *this;
1411 chunk_t encoded;
1412
1413 if (string == NULL)
1414 {
1415 string = "%any";
1416 }
1417 this = create_from_string_with_prefix_type(string);
1418 if (this)
1419 {
1420 return &this->public;
1421 }
1422 this = create_from_string_with_num_type(string);
1423 if (this)
1424 {
1425 return &this->public;
1426 }
1427 if (strchr(string, '=') != NULL)
1428 {
1429 /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
1430 * convert from LDAP style or openssl x509 -subject style to ASN.1 DN
1431 */
1432 if (atodn(string, &encoded) == SUCCESS)
1433 {
1434 this = identification_create(ID_DER_ASN1_DN);
1435 this->encoded = encoded;
1436 }
1437 else
1438 {
1439 this = identification_create(ID_KEY_ID);
1440 this->encoded = chunk_from_str(strdup(string));
1441 }
1442 return &this->public;
1443 }
1444 else if (strchr(string, '@') == NULL)
1445 {
1446 if (streq(string, "")
1447 || streq(string, "%any")
1448 || streq(string, "%any6")
1449 || streq(string, "0.0.0.0")
1450 || streq(string, "*")
1451 || streq(string, "::")
1452 || streq(string, "0::0"))
1453 {
1454 /* any ID will be accepted */
1455 this = identification_create(ID_ANY);
1456 return &this->public;
1457 }
1458 else
1459 {
1460 if (strchr(string, ':') == NULL)
1461 {
1462 /* IPv4 address or subnet */
1463 this = create_ip_address_from_string(string, TRUE);
1464 if (!this)
1465 { /* not IPv4, mostly FQDN */
1466 this = identification_create(ID_FQDN);
1467 this->encoded = chunk_from_str(strdup(string));
1468 }
1469 return &this->public;
1470 }
1471 else
1472 {
1473 /* IPv6 address or subnet */
1474 this = create_ip_address_from_string(string, FALSE);
1475 if (!this)
1476 { /* not IPv4/6 fallback to KEY_ID */
1477 this = identification_create(ID_KEY_ID);
1478 this->encoded = chunk_from_str(strdup(string));
1479 }
1480 return &this->public;
1481 }
1482 }
1483 }
1484 else
1485 {
1486 if (*string == '@')
1487 {
1488 string++;
1489 if (*string == '#')
1490 {
1491 this = identification_create(ID_KEY_ID);
1492 this->encoded = chunk_from_hex(chunk_from_str(string + 1), NULL);
1493 return &this->public;
1494 }
1495 else if (*string == '@')
1496 {
1497 this = identification_create(ID_USER_FQDN);
1498 this->encoded = chunk_clone(chunk_from_str(string + 1));
1499 return &this->public;
1500 }
1501 else
1502 {
1503 this = identification_create(ID_FQDN);
1504 this->encoded = chunk_clone(chunk_from_str(string));
1505 return &this->public;
1506 }
1507 }
1508 else
1509 {
1510 this = identification_create(ID_RFC822_ADDR);
1511 this->encoded = chunk_from_str(strdup(string));
1512 return &this->public;
1513 }
1514 }
1515 }
1516
1517 /*
1518 * Described in header.
1519 */
1520 identification_t * identification_create_from_data(chunk_t data)
1521 {
1522 char buf[data.len + 1];
1523
1524 if (is_asn1(data))
1525 {
1526 return identification_create_from_encoding(ID_DER_ASN1_DN, data);
1527 }
1528 else
1529 {
1530 /* use string constructor */
1531 snprintf(buf, sizeof(buf), "%.*s", (int)data.len, data.ptr);
1532 return identification_create_from_string(buf);
1533 }
1534 }
1535
1536 /*
1537 * Described in header.
1538 */
1539 identification_t *identification_create_from_encoding(id_type_t type,
1540 chunk_t encoded)
1541 {
1542 private_identification_t *this = identification_create(type);
1543
1544 /* apply encoded chunk */
1545 if (type != ID_ANY)
1546 {
1547 this->encoded = chunk_clone(encoded);
1548 }
1549 return &(this->public);
1550 }
1551
1552 /*
1553 * Described in header.
1554 */
1555 identification_t *identification_create_from_sockaddr(sockaddr_t *sockaddr)
1556 {
1557 switch (sockaddr->sa_family)
1558 {
1559 case AF_INET:
1560 {
1561 struct in_addr *addr = &(((struct sockaddr_in*)sockaddr)->sin_addr);
1562
1563 return identification_create_from_encoding(ID_IPV4_ADDR,
1564 chunk_create((u_char*)addr, sizeof(struct in_addr)));
1565 }
1566 case AF_INET6:
1567 {
1568 struct in6_addr *addr = &(((struct sockaddr_in6*)sockaddr)->sin6_addr);
1569
1570 return identification_create_from_encoding(ID_IPV6_ADDR,
1571 chunk_create((u_char*)addr, sizeof(struct in6_addr)));
1572 }
1573 default:
1574 {
1575 private_identification_t *this = identification_create(ID_ANY);
1576
1577 return &(this->public);
1578 }
1579 }
1580 }