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