Annotation of embedaddon/strongswan/src/libstrongswan/utils/identification.c, revision 1.1.1.2
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},
1.1.1.2 ! misho 70: {"SN", OID_SURNAME, ASN1_PRINTABLESTRING},
1.1 misho 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},
1.1.1.2 ! misho 219: {OID_SURNAME, ID_PART_RDN_SN},
! 220: {OID_SERIAL_NUMBER, ID_PART_RDN_SERIAL_NUMBER},
1.1 misho 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: /**
571: * Check if this is a wildcard value
572: */
573: static inline bool is_wildcard(chunk_t data)
574: {
575: return data.len == 1 && data.ptr[0] == '*';
576: }
577:
578: METHOD(identification_t, contains_wildcards_dn, bool,
579: private_identification_t *this)
580: {
581: enumerator_t *enumerator;
582: bool contains = FALSE;
583: id_part_t type;
584: chunk_t data;
585:
586: enumerator = create_part_enumerator(this);
587: while (enumerator->enumerate(enumerator, &type, &data))
588: {
589: if (is_wildcard(data))
590: {
591: contains = TRUE;
592: break;
593: }
594: }
595: enumerator->destroy(enumerator);
596: return contains;
597: }
598:
599: METHOD(identification_t, contains_wildcards_memchr, bool,
600: private_identification_t *this)
601: {
602: return memchr(this->encoded.ptr, '*', this->encoded.len) != NULL;
603: }
604:
605: METHOD(identification_t, hash_binary, u_int,
606: private_identification_t *this, u_int inc)
607: {
608: u_int hash;
609:
610: hash = chunk_hash_inc(chunk_from_thing(this->type), inc);
611: if (this->type != ID_ANY)
612: {
613: hash = chunk_hash_inc(this->encoded, hash);
614: }
615: return hash;
616: }
617:
618: METHOD(identification_t, equals_binary, bool,
619: private_identification_t *this, identification_t *other)
620: {
621: if (this->type == other->get_type(other))
622: {
623: if (this->type == ID_ANY)
624: {
625: return TRUE;
626: }
627: return chunk_equals(this->encoded, other->get_encoding(other));
628: }
629: return FALSE;
630: }
631:
632: /**
633: * Compare two RDNs for equality, comparing some string types case insensitive
634: */
635: static bool rdn_equals(chunk_t oid, u_char a_type, chunk_t a, u_char b_type,
636: chunk_t b)
637: {
638: if (a_type == b_type &&
639: (a_type == ASN1_PRINTABLESTRING ||
640: (a_type == ASN1_IA5STRING &&
641: asn1_known_oid(oid) == OID_EMAIL_ADDRESS)))
642: { /* ignore case for printableStrings and email RDNs */
643: return strncaseeq(a.ptr, b.ptr, a.len);
644: }
645: else
646: { /* respect case and length for everything else */
647: return memeq(a.ptr, b.ptr, a.len);
648: }
649: }
650:
651: /**
652: * RDNs when matching DNs
653: */
654: typedef struct {
655: chunk_t oid;
656: u_char type;
657: chunk_t data;
658: bool matched;
659: } rdn_t;
660:
661: /**
662: * Match DNs (o_dn may contain wildcards and RDNs in a different order, if
663: * allow_unmatched is TRUE, t_dn may contain unmatched RDNs)
664: */
665: static bool match_dn(chunk_t t_dn, chunk_t o_dn, int *wc, bool allow_unmatched)
666: {
667: enumerator_t *enumerator;
668: array_t *rdns;
669: rdn_t *rdn, *found;
670: chunk_t oid, data;
671: u_char type;
672: bool finished = FALSE;
673: int i, regular = 0;
674:
675: *wc = 0;
676:
677: /* try a binary compare */
678: if (chunk_equals(t_dn, o_dn))
679: {
680: return TRUE;
681: }
682:
683: rdns = array_create(0, 8);
684:
685: enumerator = create_rdn_enumerator(o_dn);
686: while (TRUE)
687: {
688: if (!enumerator->enumerate(enumerator, &oid, &type, &data))
689: {
690: break;
691: }
692: INIT(rdn,
693: .oid = oid,
694: .type = type,
695: .data = data,
696: );
697: if (is_wildcard(data))
698: {
699: /* insert wildcards at the end, to perform exact matches first */
700: array_insert(rdns, ARRAY_TAIL, rdn);
701: }
702: else
703: {
704: array_insert(rdns, regular++, rdn);
705: }
706: /* the enumerator returns FALSE on parse error, we are finished
707: * if we have reached the end of the DN only */
708: if ((data.ptr + data.len == o_dn.ptr + o_dn.len))
709: {
710: finished = TRUE;
711: }
712: }
713: enumerator->destroy(enumerator);
714:
715: if (!finished)
716: { /* invalid DN */
717: array_destroy_function(rdns, (void*)free, NULL);
718: return FALSE;
719: }
720: finished = FALSE;
721:
722: enumerator = create_rdn_enumerator(t_dn);
723: while (TRUE)
724: {
725: if (!enumerator->enumerate(enumerator, &oid, &type, &data))
726: {
727: break;
728: }
729: for (i = 0, found = NULL; i < array_count(rdns); i++)
730: {
731: array_get(rdns, i, &rdn);
732: if (!rdn->matched && chunk_equals(rdn->oid, oid))
733: {
734: if (is_wildcard(rdn->data))
735: {
736: (*wc)++;
737: }
738: else if (data.len != rdn->data.len ||
739: !rdn_equals(oid, type, data, rdn->type, rdn->data))
740: {
741: continue;
742: }
743: rdn->matched = TRUE;
744: found = rdn;
745: break;
746: }
747: }
748: if (!found)
749: {
750: /* treat unmatched RDNs like wildcards if allowed */
751: if (!allow_unmatched)
752: {
753: break;
754: }
755: (*wc)++;
756: }
757: /* the enumerator returns FALSE on parse error, we are finished
758: * if we have reached the end of the DN only */
759: if ((data.ptr + data.len == t_dn.ptr + t_dn.len))
760: {
761: finished = TRUE;
762: }
763: }
764: enumerator->destroy(enumerator);
765:
766: if (finished)
767: {
768: for (i = 0; i < array_count(rdns); i++)
769: {
770: array_get(rdns, i, &rdn);
771: if (!rdn->matched)
772: {
773: finished = FALSE;
774: }
775: }
776: }
777: array_destroy_function(rdns, (void*)free, NULL);
778: return finished;
779: }
780:
781: /**
782: * Reordered RDNs are fine, but match all
783: */
784: static bool match_dn_reordered(chunk_t t_dn, chunk_t o_dn, int *wc)
785: {
786: return match_dn(t_dn, o_dn, wc, FALSE);
787: }
788:
789: /**
790: * t_dn may contain more RDNs than o_dn
791: */
792: static bool match_dn_relaxed(chunk_t t_dn, chunk_t o_dn, int *wc)
793: {
794: return match_dn(t_dn, o_dn, wc, TRUE);
795: }
796:
797: /**
798: * Compare two DNs, for equality if wc == NULL, with wildcard matching otherwise
799: */
800: static bool compare_dn(chunk_t t_dn, chunk_t o_dn, int *wc)
801: {
802: enumerator_t *t, *o;
803: chunk_t t_oid, o_oid, t_data, o_data;
804: u_char t_type, o_type;
805: bool t_next, o_next, finished = FALSE;
806:
807: if (wc)
808: {
809: *wc = 0;
810: }
811: else if (t_dn.len != o_dn.len)
812: {
813: return FALSE;
814: }
815:
816: if (chunk_equals(t_dn, o_dn))
817: {
818: return TRUE;
819: }
820:
821: t = create_rdn_enumerator(t_dn);
822: o = create_rdn_enumerator(o_dn);
823: while (TRUE)
824: {
825: t_next = t->enumerate(t, &t_oid, &t_type, &t_data);
826: o_next = o->enumerate(o, &o_oid, &o_type, &o_data);
827:
828: if (!o_next && !t_next)
829: {
830: break;
831: }
832: finished = FALSE;
833: if (o_next != t_next)
834: {
835: break;
836: }
837: if (!chunk_equals(t_oid, o_oid))
838: {
839: break;
840: }
841: if (wc && is_wildcard(o_data))
842: {
843: (*wc)++;
844: }
845: else
846: {
847: if (t_data.len != o_data.len)
848: {
849: break;
850: }
851: if (!rdn_equals(t_oid, t_type, t_data, o_type, o_data))
852: {
853: break;
854: }
855: }
856: /* the enumerator returns FALSE on parse error, we are finished
857: * if we have reached the end of the DN only */
858: if ((t_data.ptr + t_data.len == t_dn.ptr + t_dn.len) &&
859: (o_data.ptr + o_data.len == o_dn.ptr + o_dn.len))
860: {
861: finished = TRUE;
862: }
863: }
864: t->destroy(t);
865: o->destroy(o);
866: return finished;
867: }
868:
1.1.1.2 ! misho 869: /**
! 870: * Check if the data in the given chunk represents a valid DN.
! 871: */
! 872: static bool is_valid_dn(chunk_t dn)
! 873: {
! 874: enumerator_t *enumerator;
! 875: chunk_t oid, data;
! 876: u_char type;
! 877: bool finished = FALSE;
! 878:
! 879: enumerator = create_rdn_enumerator(dn);
! 880: while (enumerator->enumerate(enumerator, &oid, &type, &data))
! 881: {
! 882: /* the enumerator returns FALSE on parse error, we are finished
! 883: * if we have reached the end of the DN only */
! 884: if ((data.ptr + data.len == dn.ptr + dn.len))
! 885: {
! 886: finished = TRUE;
! 887: }
! 888: }
! 889: enumerator->destroy(enumerator);
! 890:
! 891: return finished;
! 892: }
! 893:
1.1 misho 894: METHOD(identification_t, equals_dn, bool,
895: private_identification_t *this, identification_t *other)
896: {
897: return compare_dn(this->encoded, other->get_encoding(other), NULL);
898: }
899:
900: METHOD(identification_t, hash_dn, u_int,
901: private_identification_t *this, u_int inc)
902: {
903: enumerator_t *rdns;
904: chunk_t oid, data;
905: u_char type;
906: u_int hash;
907:
908: hash = chunk_hash_inc(chunk_from_thing(this->type), inc);
909: rdns = create_rdn_enumerator(this->encoded);
910: while (rdns->enumerate(rdns, &oid, &type, &data))
911: {
912: hash = chunk_hash_inc(data, chunk_hash_inc(oid, hash));
913: }
914: rdns->destroy(rdns);
915: return hash;
916: }
917:
918: METHOD(identification_t, equals_strcasecmp, bool,
919: private_identification_t *this, identification_t *other)
920: {
921: chunk_t encoded = other->get_encoding(other);
922:
923: /* we do some extra sanity checks to check for invalid IDs with a
924: * terminating null in it. */
925: if (this->type == other->get_type(other) &&
926: this->encoded.len == encoded.len &&
927: memchr(this->encoded.ptr, 0, this->encoded.len) == NULL &&
928: memchr(encoded.ptr, 0, encoded.len) == NULL &&
929: strncasecmp(this->encoded.ptr, encoded.ptr, this->encoded.len) == 0)
930: {
931: return TRUE;
932: }
933: return FALSE;
934: }
935:
936: METHOD(identification_t, matches_binary, id_match_t,
937: private_identification_t *this, identification_t *other)
938: {
939: if (other->get_type(other) == ID_ANY)
940: {
941: return ID_MATCH_ANY;
942: }
943: if (this->type == other->get_type(other) &&
944: chunk_equals(this->encoded, other->get_encoding(other)))
945: {
946: return ID_MATCH_PERFECT;
947: }
948: return ID_MATCH_NONE;
949: }
950:
951: METHOD(identification_t, matches_string, id_match_t,
952: private_identification_t *this, identification_t *other)
953: {
954: chunk_t encoded = other->get_encoding(other);
955: u_int len = encoded.len;
956:
957: if (other->get_type(other) == ID_ANY)
958: {
959: return ID_MATCH_ANY;
960: }
961: if (this->type != other->get_type(other))
962: {
963: return ID_MATCH_NONE;
964: }
965: /* try a equals check first */
966: if (equals_strcasecmp(this, other))
967: {
968: return ID_MATCH_PERFECT;
969: }
970: if (len == 0 || this->encoded.len < len)
971: {
972: return ID_MATCH_NONE;
973: }
974:
975: /* check for single wildcard at the head of the string */
976: if (*encoded.ptr == '*')
977: {
978: /* single asterisk matches any string */
979: if (len-- == 1)
980: { /* not better than ID_ANY */
981: return ID_MATCH_ANY;
982: }
983: if (strncasecmp(this->encoded.ptr + this->encoded.len - len,
984: encoded.ptr + 1, len) == 0)
985: {
986: return ID_MATCH_ONE_WILDCARD;
987: }
988: }
989: return ID_MATCH_NONE;
990: }
991:
992: METHOD(identification_t, matches_any, id_match_t,
993: private_identification_t *this, identification_t *other)
994: {
995: if (other->get_type(other) == ID_ANY)
996: {
997: return ID_MATCH_ANY;
998: }
999: return ID_MATCH_NONE;
1000: }
1001:
1002: /**
1003: * Match DNs given the matching function
1004: */
1005: static id_match_t matches_dn_internal(private_identification_t *this,
1006: identification_t *other,
1007: bool (*match)(chunk_t,chunk_t,int*))
1008: {
1009: int wc;
1010:
1011: if (other->get_type(other) == ID_ANY)
1012: {
1013: return ID_MATCH_ANY;
1014: }
1015:
1016: if (this->type == other->get_type(other))
1017: {
1018: if (match(this->encoded, other->get_encoding(other), &wc))
1019: {
1020: wc = min(wc, ID_MATCH_ONE_WILDCARD - ID_MATCH_MAX_WILDCARDS);
1021: return ID_MATCH_PERFECT - wc;
1022: }
1023: }
1024: return ID_MATCH_NONE;
1025: }
1026:
1027: METHOD(identification_t, matches_dn, id_match_t,
1028: private_identification_t *this, identification_t *other)
1029: {
1030: return matches_dn_internal(this, other, compare_dn);
1031: }
1032:
1033: METHOD(identification_t, matches_dn_reordered, id_match_t,
1034: private_identification_t *this, identification_t *other)
1035: {
1036: return matches_dn_internal(this, other, match_dn_reordered);
1037: }
1038:
1039: METHOD(identification_t, matches_dn_relaxed, id_match_t,
1040: private_identification_t *this, identification_t *other)
1041: {
1042: return matches_dn_internal(this, other, match_dn_relaxed);
1043: }
1044:
1045: /**
1046: * Transform netmask to CIDR bits
1047: */
1048: static int netmask_to_cidr(char *netmask, size_t address_size)
1049: {
1050: uint8_t byte;
1051: int i, netbits = 0;
1052:
1053: for (i = 0; i < address_size; i++)
1054: {
1055: byte = netmask[i];
1056:
1057: if (byte == 0x00)
1058: {
1059: break;
1060: }
1061: if (byte == 0xff)
1062: {
1063: netbits += 8;
1064: }
1065: else
1066: {
1067: while (byte & 0x80)
1068: {
1069: netbits++;
1070: byte <<= 1;
1071: }
1072: }
1073: }
1074: return netbits;
1075: }
1076:
1077: METHOD(identification_t, matches_range, id_match_t,
1078: private_identification_t *this, identification_t *other)
1079: {
1080: chunk_t other_encoding;
1081: uint8_t *address, *from, *to, *network, *netmask;
1082: size_t address_size = 0;
1083: int netbits, range_sign, i;
1084:
1085: if (other->get_type(other) == ID_ANY)
1086: {
1087: return ID_MATCH_ANY;
1088: }
1089: if (this->type == other->get_type(other) &&
1090: chunk_equals(this->encoded, other->get_encoding(other)))
1091: {
1092: return ID_MATCH_PERFECT;
1093: }
1094: if ((this->type == ID_IPV4_ADDR &&
1095: other->get_type(other) == ID_IPV4_ADDR_SUBNET))
1096: {
1097: address_size = sizeof(struct in_addr);
1098: }
1099: else if ((this->type == ID_IPV6_ADDR &&
1100: other->get_type(other) == ID_IPV6_ADDR_SUBNET))
1101: {
1102: address_size = sizeof(struct in6_addr);
1103: }
1104: if (address_size)
1105: {
1106: other_encoding = other->get_encoding(other);
1107: if (this->encoded.len != address_size ||
1108: other_encoding.len != 2 * address_size)
1109: {
1110: return ID_MATCH_NONE;
1111: }
1112: address = this->encoded.ptr;
1113: network = other_encoding.ptr;
1114: netmask = other_encoding.ptr + address_size;
1115: netbits = netmask_to_cidr(netmask, address_size);
1116:
1117: if (netbits == 0)
1118: {
1119: return ID_MATCH_MAX_WILDCARDS;
1120: }
1121: if (netbits == 8 * address_size)
1122: {
1123: return memeq(address, network, address_size) ?
1124: ID_MATCH_PERFECT : ID_MATCH_NONE;
1125: }
1126: for (i = 0; i < (netbits + 7)/8; i++)
1127: {
1128: if ((address[i] ^ network[i]) & netmask[i])
1129: {
1130: return ID_MATCH_NONE;
1131: }
1132: }
1133: return ID_MATCH_ONE_WILDCARD;
1134: }
1135: if ((this->type == ID_IPV4_ADDR &&
1136: other->get_type(other) == ID_IPV4_ADDR_RANGE))
1137: {
1138: address_size = sizeof(struct in_addr);
1139: }
1140: else if ((this->type == ID_IPV6_ADDR &&
1141: other->get_type(other) == ID_IPV6_ADDR_RANGE))
1142: {
1143: address_size = sizeof(struct in6_addr);
1144: }
1145: if (address_size)
1146: {
1147: other_encoding = other->get_encoding(other);
1148: if (this->encoded.len != address_size ||
1149: other_encoding.len != 2 * address_size)
1150: {
1151: return ID_MATCH_NONE;
1152: }
1153: address = this->encoded.ptr;
1154: from = other_encoding.ptr;
1155: to = other_encoding.ptr + address_size;
1156:
1157: range_sign = memcmp(to, from, address_size);
1158: if (range_sign < 0)
1159: { /* to is smaller than from */
1160: return ID_MATCH_NONE;
1161: }
1162:
1163: /* check lower bound */
1164: for (i = 0; i < address_size; i++)
1165: {
1166: if (address[i] != from[i])
1167: {
1168: if (address[i] < from[i])
1169: {
1170: return ID_MATCH_NONE;
1171: }
1172: break;
1173: }
1174: }
1175:
1176: /* check upper bound */
1177: for (i = 0; i < address_size; i++)
1178: {
1179: if (address[i] != to[i])
1180: {
1181: if (address[i] > to[i])
1182: {
1183: return ID_MATCH_NONE;
1184: }
1185: break;
1186: }
1187: }
1188: return range_sign ? ID_MATCH_ONE_WILDCARD : ID_MATCH_PERFECT;
1189: }
1190: return ID_MATCH_NONE;
1191: }
1192:
1193: /**
1194: * Described in header.
1195: */
1196: int identification_printf_hook(printf_hook_data_t *data,
1197: printf_hook_spec_t *spec, const void *const *args)
1198: {
1199: private_identification_t *this = *((private_identification_t**)(args[0]));
1200: chunk_t proper;
1201: char buf[BUF_LEN], *pos;
1202: size_t len, address_size;
1203: int written;
1204:
1205: if (this == NULL)
1206: {
1207: return print_in_hook(data, "%*s", spec->width, "(null)");
1208: }
1209:
1210: switch (this->type)
1211: {
1212: case ID_ANY:
1213: snprintf(buf, BUF_LEN, "%%any");
1214: break;
1215: case ID_IPV4_ADDR:
1216: if (this->encoded.len < sizeof(struct in_addr) ||
1217: inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
1218: {
1219: snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR)");
1220: }
1221: break;
1222: case ID_IPV4_ADDR_SUBNET:
1223: address_size = sizeof(struct in_addr);
1224: if (this->encoded.len < 2 * address_size ||
1225: inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
1226: {
1227: snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_SUBNET)");
1228: break;
1229: }
1230: written = strlen(buf);
1231: snprintf(buf + written, BUF_LEN - written, "/%d",
1232: netmask_to_cidr(this->encoded.ptr + address_size,
1233: address_size));
1234: break;
1235: case ID_IPV4_ADDR_RANGE:
1236: address_size = sizeof(struct in_addr);
1237: if (this->encoded.len < 2 * address_size ||
1238: inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
1239: {
1240: snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_RANGE)");
1241: break;
1242: }
1243: written = strlen(buf);
1244: pos = buf + written;
1245: len = BUF_LEN - written;
1246: written = snprintf(pos, len, "-");
1247: if (written < 0 || written >= len ||
1248: inet_ntop(AF_INET, this->encoded.ptr + address_size,
1249: pos + written, len - written) == NULL)
1250: {
1251: snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_RANGE)");
1252: }
1253: break;
1254: case ID_IPV6_ADDR:
1255: if (this->encoded.len < sizeof(struct in6_addr) ||
1256: inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
1257: {
1258: snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR)");
1259: }
1260: break;
1261: case ID_IPV6_ADDR_SUBNET:
1262: address_size = sizeof(struct in6_addr);
1263: if (this->encoded.len < 2 * address_size ||
1264: inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
1265: {
1266: snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_SUBNET)");
1267: }
1268: else
1269: {
1270: written = strlen(buf);
1271: snprintf(buf + written, BUF_LEN - written, "/%d",
1272: netmask_to_cidr(this->encoded.ptr + address_size,
1273: address_size));
1274: }
1275: break;
1276: case ID_IPV6_ADDR_RANGE:
1277: address_size = sizeof(struct in6_addr);
1278: if (this->encoded.len < 2 * address_size ||
1279: inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
1280: {
1281: snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_RANGE)");
1282: break;
1283: }
1284: written = strlen(buf);
1285: pos = buf + written;
1286: len = BUF_LEN - written;
1287: written = snprintf(pos, len, "-");
1288: if (written < 0 || written >= len ||
1289: inet_ntop(AF_INET6, this->encoded.ptr + address_size,
1290: pos + written, len - written) == NULL)
1291: {
1292: snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_RANGE)");
1293: }
1294: break;
1295: case ID_FQDN:
1296: case ID_RFC822_ADDR:
1297: case ID_DER_ASN1_GN_URI:
1298: chunk_printable(this->encoded, &proper, '?');
1299: snprintf(buf, BUF_LEN, "%.*s", (int)proper.len, proper.ptr);
1300: chunk_free(&proper);
1301: break;
1302: case ID_DER_ASN1_DN:
1303: dntoa(this->encoded, buf, BUF_LEN);
1304: break;
1305: case ID_DER_ASN1_GN:
1306: snprintf(buf, BUF_LEN, "(ASN.1 general name)");
1307: break;
1308: case ID_KEY_ID:
1309: if (chunk_printable(this->encoded, NULL, '?') &&
1310: this->encoded.len != HASH_SIZE_SHA1)
1311: { /* fully printable, use ascii version */
1312: snprintf(buf, BUF_LEN, "%.*s", (int)this->encoded.len,
1313: this->encoded.ptr);
1314: }
1315: else
1316: { /* not printable, hex dump */
1317: snprintf(buf, BUF_LEN, "%#B", &this->encoded);
1318: }
1319: break;
1320: default:
1321: snprintf(buf, BUF_LEN, "(unknown ID type: %d)", this->type);
1322: break;
1323: }
1324: if (spec->minus)
1325: {
1326: return print_in_hook(data, "%-*s", spec->width, buf);
1327: }
1328: return print_in_hook(data, "%*s", spec->width, buf);
1329: }
1330:
1331: METHOD(identification_t, clone_, identification_t*,
1332: private_identification_t *this)
1333: {
1334: private_identification_t *clone = malloc_thing(private_identification_t);
1335:
1336: memcpy(clone, this, sizeof(private_identification_t));
1337: if (this->encoded.len)
1338: {
1339: clone->encoded = chunk_clone(this->encoded);
1340: }
1341: return &clone->public;
1342: }
1343:
1344: METHOD(identification_t, destroy, void,
1345: private_identification_t *this)
1346: {
1347: chunk_free(&this->encoded);
1348: free(this);
1349: }
1350:
1351: /**
1352: * Generic constructor used for the other constructors.
1353: */
1354: static private_identification_t *identification_create(id_type_t type)
1355: {
1356: private_identification_t *this;
1357: char *rdn_matching;
1358:
1359: INIT(this,
1360: .public = {
1361: .get_encoding = _get_encoding,
1362: .get_type = _get_type,
1363: .create_part_enumerator = _create_part_enumerator,
1364: .clone = _clone_,
1365: .destroy = _destroy,
1366: },
1367: .type = type,
1368: );
1369:
1370: switch (type)
1371: {
1372: case ID_ANY:
1373: this->public.hash = _hash_binary;
1374: this->public.equals = _equals_binary;
1375: this->public.matches = _matches_any;
1376: this->public.contains_wildcards = return_true;
1377: break;
1378: case ID_FQDN:
1379: case ID_RFC822_ADDR:
1380: this->public.hash = _hash_binary;
1381: this->public.equals = _equals_strcasecmp;
1382: this->public.matches = _matches_string;
1383: this->public.contains_wildcards = _contains_wildcards_memchr;
1384: break;
1385: case ID_DER_ASN1_DN:
1386: this->public.hash = _hash_dn;
1387: this->public.equals = _equals_dn;
1388: this->public.matches = _matches_dn;
1389: this->public.contains_wildcards = _contains_wildcards_dn;
1390: /* check for more relaxed matching config */
1391: rdn_matching = lib->settings->get_str(lib->settings,
1392: "%s.rdn_matching", NULL, lib->ns);
1393: if (streq("reordered", rdn_matching))
1394: {
1395: this->public.matches = _matches_dn_reordered;
1396: }
1397: else if (streq("relaxed", rdn_matching))
1398: {
1399: this->public.matches = _matches_dn_relaxed;
1400: }
1401: break;
1402: case ID_IPV4_ADDR:
1403: case ID_IPV6_ADDR:
1404: this->public.hash = _hash_binary;
1405: this->public.equals = _equals_binary;
1406: this->public.matches = _matches_range;
1407: this->public.contains_wildcards = return_false;
1408: break;
1409: default:
1410: this->public.hash = _hash_binary;
1411: this->public.equals = _equals_binary;
1412: this->public.matches = _matches_binary;
1413: this->public.contains_wildcards = return_false;
1414: break;
1415: }
1416: return this;
1417: }
1418:
1419: /**
1420: * Create an identity for a specific type, determined by prefix
1421: */
1422: static private_identification_t* create_from_string_with_prefix_type(char *str)
1423: {
1424: struct {
1425: const char *str;
1426: id_type_t type;
1427: } prefixes[] = {
1428: { "ipv4:", ID_IPV4_ADDR },
1429: { "ipv6:", ID_IPV6_ADDR },
1430: { "ipv4net:", ID_IPV4_ADDR_SUBNET },
1431: { "ipv6net:", ID_IPV6_ADDR_SUBNET },
1432: { "ipv4range:", ID_IPV4_ADDR_RANGE },
1433: { "ipv6range:", ID_IPV6_ADDR_RANGE },
1434: { "rfc822:", ID_RFC822_ADDR },
1435: { "email:", ID_RFC822_ADDR },
1436: { "userfqdn:", ID_USER_FQDN },
1437: { "fqdn:", ID_FQDN },
1438: { "dns:", ID_FQDN },
1439: { "asn1dn:", ID_DER_ASN1_DN },
1440: { "asn1gn:", ID_DER_ASN1_GN },
1441: { "xmppaddr:", ID_DER_ASN1_GN },
1442: { "keyid:", ID_KEY_ID },
1443: };
1444: private_identification_t *this;
1445: int i;
1446:
1447: for (i = 0; i < countof(prefixes); i++)
1448: {
1449: if (strcasepfx(str, prefixes[i].str))
1450: {
1451: this = identification_create(prefixes[i].type);
1452: str += strlen(prefixes[i].str);
1453:
1454: if (*str == '#')
1455: {
1456: this->encoded = chunk_from_hex(chunk_from_str(str + 1), NULL);
1457: }
1458: else
1459: {
1460: this->encoded = chunk_clone(chunk_from_str(str));
1461: }
1462:
1463: if (prefixes[i].type == ID_DER_ASN1_GN &&
1464: strcasepfx(prefixes[i].str, "xmppaddr:"))
1465: {
1466: this->encoded = asn1_wrap(ASN1_CONTEXT_C_0, "mm",
1467: asn1_build_known_oid(OID_XMPP_ADDR),
1468: asn1_wrap(ASN1_CONTEXT_C_0, "m",
1469: asn1_wrap(ASN1_UTF8STRING, "m",
1470: this->encoded)));
1471: }
1472:
1473: return this;
1474: }
1475: }
1476: return NULL;
1477: }
1478:
1479: /**
1480: * Create an identity for a specific type, determined by a numerical prefix
1481: *
1482: * The prefix is of the form "{x}:", where x denotes the numerical identity
1483: * type.
1484: */
1485: static private_identification_t* create_from_string_with_num_type(char *str)
1486: {
1487: private_identification_t *this;
1488: u_long type;
1489:
1490: if (*str++ != '{')
1491: {
1492: return NULL;
1493: }
1494: errno = 0;
1495: type = strtoul(str, &str, 0);
1496: if (errno || *str++ != '}' || *str++ != ':')
1497: {
1498: return NULL;
1499: }
1500: this = identification_create(type);
1501: if (*str == '#')
1502: {
1503: this->encoded = chunk_from_hex(chunk_from_str(str + 1), NULL);
1504: }
1505: else
1506: {
1507: this->encoded = chunk_clone(chunk_from_str(str));
1508: }
1509: return this;
1510: }
1511:
1512: /**
1513: * Convert to an IPv4/IPv6 host address, subnet or address range
1514: */
1515: static private_identification_t* create_ip_address_from_string(char *string,
1516: bool is_ipv4)
1517: {
1518: private_identification_t *this;
1519: uint8_t encoding[32];
1520: uint8_t *str, *pos, *address, *to_address, *netmask;
1521: size_t address_size;
1522: int bits, bytes, i;
1523: bool has_subnet = FALSE, has_range = FALSE;
1524:
1525: address = encoding;
1526: address_size = is_ipv4 ? sizeof(struct in_addr) : sizeof(struct in6_addr);
1527:
1528: str = strdup(string);
1529: pos = strchr(str, '/');
1530: if (pos)
1531: { /* separate IP address from optional netmask */
1532:
1533: *pos = '\0';
1534: has_subnet = TRUE;
1535: }
1536: else
1537: {
1538: pos = strchr(str, '-');
1539: if (pos)
1540: { /* separate lower address from upper address of IP range */
1541: *pos = '\0';
1542: has_range = TRUE;
1543: }
1544: }
1545:
1546: if (inet_pton(is_ipv4 ? AF_INET : AF_INET6, str, address) != 1)
1547: {
1548: free(str);
1549: return NULL;
1550: }
1551:
1552: if (has_subnet)
1553: { /* is IP subnet */
1554: bits = atoi(pos + 1);
1555: if (bits > 8 * address_size)
1556: {
1557: free(str);
1558: return NULL;
1559: }
1560: bytes = bits / 8;
1561: bits -= 8 * bytes;
1562: netmask = encoding + address_size;
1563:
1564: for (i = 0; i < address_size; i++)
1565: {
1566: if (bytes)
1567: {
1568: *netmask = 0xff;
1569: bytes--;
1570: }
1571: else if (bits)
1572: {
1573: *netmask = 0xff << (8 - bits);
1574: bits = 0;
1575: }
1576: else
1577: {
1578: *netmask = 0x00;
1579: }
1580: *address++ &= *netmask++;
1581: }
1582: this = identification_create(is_ipv4 ? ID_IPV4_ADDR_SUBNET :
1583: ID_IPV6_ADDR_SUBNET);
1584: this->encoded = chunk_clone(chunk_create(encoding, 2 * address_size));
1585: }
1586: else if (has_range)
1587: { /* is IP range */
1588: to_address = encoding + address_size;
1589:
1590: if (inet_pton(is_ipv4 ? AF_INET : AF_INET6, pos + 1, to_address) != 1)
1591: {
1592: free(str);
1593: return NULL;
1594: }
1595: for (i = 0; i < address_size; i++)
1596: {
1597: if (address[i] != to_address[i])
1598: {
1599: if (address[i] > to_address[i])
1600: {
1601: free(str);
1602: return NULL;
1603: }
1604: break;
1605: }
1606: }
1607: this = identification_create(is_ipv4 ? ID_IPV4_ADDR_RANGE :
1608: ID_IPV6_ADDR_RANGE);
1609: this->encoded = chunk_clone(chunk_create(encoding, 2 * address_size));
1610: }
1611: else
1612: { /* is IP host address */
1613: this = identification_create(is_ipv4 ? ID_IPV4_ADDR : ID_IPV6_ADDR);
1614: this->encoded = chunk_clone(chunk_create(encoding, address_size));
1615: }
1616: free(str);
1617:
1618: return this;
1619: }
1620:
1621: /*
1622: * Described in header.
1623: */
1624: identification_t *identification_create_from_string(char *string)
1625: {
1626: private_identification_t *this;
1627: chunk_t encoded;
1628:
1629: if (string == NULL)
1630: {
1631: string = "%any";
1632: }
1633: this = create_from_string_with_prefix_type(string);
1634: if (this)
1635: {
1636: return &this->public;
1637: }
1638: this = create_from_string_with_num_type(string);
1639: if (this)
1640: {
1641: return &this->public;
1642: }
1643: if (strchr(string, '=') != NULL)
1644: {
1645: /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
1646: * convert from LDAP style or openssl x509 -subject style to ASN.1 DN
1647: */
1648: if (atodn(string, &encoded) == SUCCESS)
1649: {
1650: this = identification_create(ID_DER_ASN1_DN);
1651: this->encoded = encoded;
1652: }
1653: else
1654: {
1655: this = identification_create(ID_KEY_ID);
1656: this->encoded = chunk_from_str(strdup(string));
1657: }
1658: return &this->public;
1659: }
1660: else if (strchr(string, '@') == NULL)
1661: {
1662: if (streq(string, "")
1663: || streq(string, "%any")
1664: || streq(string, "%any6")
1665: || streq(string, "0.0.0.0")
1666: || streq(string, "*")
1667: || streq(string, "::")
1668: || streq(string, "0::0"))
1669: {
1670: /* any ID will be accepted */
1671: this = identification_create(ID_ANY);
1672: return &this->public;
1673: }
1674: else
1675: {
1676: if (strchr(string, ':') == NULL)
1677: {
1678: /* IPv4 address or subnet */
1679: this = create_ip_address_from_string(string, TRUE);
1680: if (!this)
1681: { /* not IPv4, mostly FQDN */
1682: this = identification_create(ID_FQDN);
1683: this->encoded = chunk_from_str(strdup(string));
1684: }
1685: return &this->public;
1686: }
1687: else
1688: {
1689: /* IPv6 address or subnet */
1690: this = create_ip_address_from_string(string, FALSE);
1691: if (!this)
1692: { /* not IPv4/6 fallback to KEY_ID */
1693: this = identification_create(ID_KEY_ID);
1694: this->encoded = chunk_from_str(strdup(string));
1695: }
1696: return &this->public;
1697: }
1698: }
1699: }
1700: else
1701: {
1702: if (*string == '@')
1703: {
1704: string++;
1705: if (*string == '#')
1706: {
1707: this = identification_create(ID_KEY_ID);
1708: this->encoded = chunk_from_hex(chunk_from_str(string + 1), NULL);
1709: return &this->public;
1710: }
1711: else if (*string == '@')
1712: {
1713: this = identification_create(ID_USER_FQDN);
1714: this->encoded = chunk_clone(chunk_from_str(string + 1));
1715: return &this->public;
1716: }
1717: else
1718: {
1719: this = identification_create(ID_FQDN);
1720: this->encoded = chunk_clone(chunk_from_str(string));
1721: return &this->public;
1722: }
1723: }
1724: else
1725: {
1726: this = identification_create(ID_RFC822_ADDR);
1727: this->encoded = chunk_from_str(strdup(string));
1728: return &this->public;
1729: }
1730: }
1731: }
1732:
1733: /*
1734: * Described in header.
1735: */
1736: identification_t * identification_create_from_data(chunk_t data)
1737: {
1738: char buf[data.len + 1];
1739:
1.1.1.2 ! misho 1740: if (is_asn1(data) && is_valid_dn(data))
1.1 misho 1741: {
1742: return identification_create_from_encoding(ID_DER_ASN1_DN, data);
1743: }
1744: else
1745: {
1746: /* use string constructor */
1747: snprintf(buf, sizeof(buf), "%.*s", (int)data.len, data.ptr);
1748: return identification_create_from_string(buf);
1749: }
1750: }
1751:
1752: /*
1753: * Described in header.
1754: */
1755: identification_t *identification_create_from_encoding(id_type_t type,
1756: chunk_t encoded)
1757: {
1758: private_identification_t *this = identification_create(type);
1759:
1760: /* apply encoded chunk */
1761: if (type != ID_ANY)
1762: {
1763: this->encoded = chunk_clone(encoded);
1764: }
1765: return &(this->public);
1766: }
1767:
1768: /*
1769: * Described in header.
1770: */
1771: identification_t *identification_create_from_sockaddr(sockaddr_t *sockaddr)
1772: {
1773: switch (sockaddr->sa_family)
1774: {
1775: case AF_INET:
1776: {
1777: struct in_addr *addr = &(((struct sockaddr_in*)sockaddr)->sin_addr);
1778:
1779: return identification_create_from_encoding(ID_IPV4_ADDR,
1780: chunk_create((u_char*)addr, sizeof(struct in_addr)));
1781: }
1782: case AF_INET6:
1783: {
1784: struct in6_addr *addr = &(((struct sockaddr_in6*)sockaddr)->sin6_addr);
1785:
1786: return identification_create_from_encoding(ID_IPV6_ADDR,
1787: chunk_create((u_char*)addr, sizeof(struct in6_addr)));
1788: }
1789: default:
1790: {
1791: private_identification_t *this = identification_create(ID_ANY);
1792:
1793: return &(this->public);
1794: }
1795: }
1796: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>