Annotation of embedaddon/strongswan/src/libcharon/config/ike_cfg.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2012-2019 Tobias Brunner
3: * Copyright (C) 2005-2007 Martin Willi
4: * Copyright (C) 2005 Jan Hutter
5: * HSR Hochschule fuer Technik Rapperswil
6: *
7: * This program is free software; you can redistribute it and/or modify it
8: * under the terms of the GNU General Public License as published by the
9: * Free Software Foundation; either version 2 of the License, or (at your
10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11: *
12: * This program is distributed in the hope that it will be useful, but
13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15: * for more details.
16: */
17:
18: #define _GNU_SOURCE /* for stdndup() */
19: #include <string.h>
20:
21: #include "ike_cfg.h"
22:
23: #include <daemon.h>
24:
25: ENUM(ike_version_names, IKE_ANY, IKEV2,
26: "IKEv1/2",
27: "IKEv1",
28: "IKEv2",
29: );
30:
31: typedef struct private_ike_cfg_t private_ike_cfg_t;
32:
33: /**
34: * Private data of an ike_cfg_t object
35: */
36: struct private_ike_cfg_t {
37:
38: /**
39: * Public part
40: */
41: ike_cfg_t public;
42:
43: /**
44: * Number of references hold by others to this ike_cfg
45: */
46: refcount_t refcount;
47:
48: /**
49: * IKE version to use
50: */
51: ike_version_t version;
52:
53: /**
54: * Address list string for local host
55: */
56: char *me;
57:
58: /**
59: * Address list string for remote host
60: */
61: char *other;
62:
63: /**
64: * Local single host or DNS names, as allocated char*
65: */
66: linked_list_t *my_hosts;
67:
68: /**
69: * Remote single host or DNS names, as allocated char*
70: */
71: linked_list_t *other_hosts;
72:
73: /**
74: * Local ranges/subnets this config matches to, as traffic_selector_t*
75: */
76: linked_list_t *my_ranges;
77:
78: /**
79: * Remote ranges/subnets this config matches to, as traffic_selector_t*
80: */
81: linked_list_t *other_ranges;
82:
83: /**
84: * our source port
85: */
86: uint16_t my_port;
87:
88: /**
89: * destination port
90: */
91: uint16_t other_port;
92:
93: /**
94: * should we send a certificate request?
95: */
96: bool certreq;
97:
98: /**
99: * enforce UDP encapsulation
100: */
101: bool force_encap;
102:
103: /**
104: * use IKE fragmentation
105: */
106: fragmentation_t fragmentation;
107:
108: /**
109: * childless IKE_SAs
110: */
111: childless_t childless;
112:
113: /**
114: * DSCP value to use on sent IKE packets
115: */
116: uint8_t dscp;
117:
118: /**
119: * List of proposals to use
120: */
121: linked_list_t *proposals;
122: };
123:
124: METHOD(ike_cfg_t, get_version, ike_version_t,
125: private_ike_cfg_t *this)
126: {
127: return this->version;
128: }
129:
130: METHOD(ike_cfg_t, send_certreq, bool,
131: private_ike_cfg_t *this)
132: {
133: return this->certreq;
134: }
135:
136: METHOD(ike_cfg_t, force_encap_, bool,
137: private_ike_cfg_t *this)
138: {
139: return this->force_encap;
140: }
141:
142: METHOD(ike_cfg_t, fragmentation, fragmentation_t,
143: private_ike_cfg_t *this)
144: {
145: return this->fragmentation;
146: }
147:
148: METHOD(ike_cfg_t, childless, childless_t,
149: private_ike_cfg_t *this)
150: {
151: return this->childless;
152: }
153:
154: /**
155: * Common function for resolve_me/other
156: */
157: static host_t* resolve(linked_list_t *hosts, int family, uint16_t port)
158: {
159: enumerator_t *enumerator;
160: host_t *host = NULL;
161: bool tried = FALSE;
162: char *str;
163:
164: enumerator = hosts->create_enumerator(hosts);
165: while (enumerator->enumerate(enumerator, &str))
166: {
167: host = host_create_from_dns(str, family, port);
168: if (host)
169: {
170: break;
171: }
172: tried = TRUE;
173: }
174: enumerator->destroy(enumerator);
175:
176: if (!host && !tried)
177: {
178: /* we have no single host configured, return %any */
179: host = host_create_any(family ?: AF_INET);
180: host->set_port(host, port);
181: }
182: return host;
183: }
184:
185: METHOD(ike_cfg_t, resolve_me, host_t*,
186: private_ike_cfg_t *this, int family)
187: {
188: return resolve(this->my_hosts, family, this->my_port);
189: }
190:
191: METHOD(ike_cfg_t, resolve_other, host_t*,
192: private_ike_cfg_t *this, int family)
193: {
194: return resolve(this->other_hosts, family, this->other_port);
195: }
196:
197: /**
198: * Common function for match_me/other
199: */
200: static u_int match(linked_list_t *hosts, linked_list_t *ranges, host_t *cand)
201: {
202: enumerator_t *enumerator;
203: traffic_selector_t *ts;
204: char *str;
205: host_t *host;
206: uint8_t mask;
207: u_int quality = 0;
208:
209: /* try single hosts first */
210: enumerator = hosts->create_enumerator(hosts);
211: while (enumerator->enumerate(enumerator, &str))
212: {
213: host = host_create_from_dns(str, cand->get_family(cand), 0);
214: if (host)
215: {
216: if (host->ip_equals(host, cand))
217: {
218: quality = max(quality, 128 + 1);
219: }
220: if (host->is_anyaddr(host))
221: {
222: quality = max(quality, 1);
223: }
224: host->destroy(host);
225: }
226: }
227: enumerator->destroy(enumerator);
228:
229: /* then ranges/subnets */
230: enumerator = ranges->create_enumerator(ranges);
231: while (enumerator->enumerate(enumerator, &ts))
232: {
233: if (ts->includes(ts, cand))
234: {
235: if (ts->to_subnet(ts, &host, &mask))
236: {
237: quality = max(quality, mask + 1);
238: }
239: else
240: {
241: quality = max(quality, 1);
242: }
243: host->destroy(host);
244: }
245: }
246: enumerator->destroy(enumerator);
247:
248: return quality;
249: }
250:
251: METHOD(ike_cfg_t, match_me, u_int,
252: private_ike_cfg_t *this, host_t *host)
253: {
254: return match(this->my_hosts, this->my_ranges, host);
255: }
256:
257: METHOD(ike_cfg_t, match_other, u_int,
258: private_ike_cfg_t *this, host_t *host)
259: {
260: return match(this->other_hosts, this->other_ranges, host);
261: }
262:
263: METHOD(ike_cfg_t, get_my_addr, char*,
264: private_ike_cfg_t *this)
265: {
266: return this->me;
267: }
268:
269: METHOD(ike_cfg_t, get_other_addr, char*,
270: private_ike_cfg_t *this)
271: {
272: return this->other;
273: }
274:
275: METHOD(ike_cfg_t, get_my_port, uint16_t,
276: private_ike_cfg_t *this)
277: {
278: return this->my_port;
279: }
280:
281: METHOD(ike_cfg_t, get_other_port, uint16_t,
282: private_ike_cfg_t *this)
283: {
284: return this->other_port;
285: }
286:
287: METHOD(ike_cfg_t, get_dscp, uint8_t,
288: private_ike_cfg_t *this)
289: {
290: return this->dscp;
291: }
292:
293: METHOD(ike_cfg_t, add_proposal, void,
294: private_ike_cfg_t *this, proposal_t *proposal)
295: {
296: if (proposal)
297: {
298: this->proposals->insert_last(this->proposals, proposal);
299: }
300: }
301:
302: METHOD(ike_cfg_t, get_proposals, linked_list_t*,
303: private_ike_cfg_t *this)
304: {
305: enumerator_t *enumerator;
306: proposal_t *current;
307: linked_list_t *proposals;
308:
309: proposals = linked_list_create();
310: enumerator = this->proposals->create_enumerator(this->proposals);
311: while (enumerator->enumerate(enumerator, ¤t))
312: {
313: current = current->clone(current, 0);
314: proposals->insert_last(proposals, current);
315: }
316: enumerator->destroy(enumerator);
317:
318: DBG2(DBG_CFG, "configured proposals: %#P", proposals);
319:
320: return proposals;
321: }
322:
323: METHOD(ike_cfg_t, has_proposal, bool,
324: private_ike_cfg_t *this, proposal_t *match, bool private)
325: {
326: enumerator_t *enumerator;
327: proposal_t *proposal;
328:
329: enumerator = this->proposals->create_enumerator(this->proposals);
330: while (enumerator->enumerate(enumerator, &proposal))
331: {
332: if (proposal->matches(proposal, match,
333: private ? 0 : PROPOSAL_SKIP_PRIVATE))
334: {
335: enumerator->destroy(enumerator);
336: return TRUE;
337: }
338: }
339: enumerator->destroy(enumerator);
340: return FALSE;
341: }
342:
343: METHOD(ike_cfg_t, select_proposal, proposal_t*,
344: private_ike_cfg_t *this, linked_list_t *proposals,
345: proposal_selection_flag_t flags)
346: {
347: return proposal_select(this->proposals, proposals, flags);
348: }
349:
350: METHOD(ike_cfg_t, get_dh_group, diffie_hellman_group_t,
351: private_ike_cfg_t *this)
352: {
353: enumerator_t *enumerator;
354: proposal_t *proposal;
355: uint16_t dh_group = MODP_NONE;
356:
357: enumerator = this->proposals->create_enumerator(this->proposals);
358: while (enumerator->enumerate(enumerator, &proposal))
359: {
360: if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL))
361: {
362: break;
363: }
364: }
365: enumerator->destroy(enumerator);
366: return dh_group;
367: }
368:
369: METHOD(ike_cfg_t, equals, bool,
370: private_ike_cfg_t *this, ike_cfg_t *other_public)
371: {
372: private_ike_cfg_t *other = (private_ike_cfg_t*)other_public;
373:
374: if (this == other)
375: {
376: return TRUE;
377: }
378: if (this->public.equals != other->public.equals)
379: {
380: return FALSE;
381: }
382: if (!this->proposals->equals_offset(this->proposals, other->proposals,
383: offsetof(proposal_t, equals)))
384: {
385: return FALSE;
386: }
387: return
388: this->version == other->version &&
389: this->certreq == other->certreq &&
390: this->force_encap == other->force_encap &&
391: this->fragmentation == other->fragmentation &&
392: this->childless == other->childless &&
393: streq(this->me, other->me) &&
394: streq(this->other, other->other) &&
395: this->my_port == other->my_port &&
396: this->other_port == other->other_port;
397: }
398:
399: METHOD(ike_cfg_t, get_ref, ike_cfg_t*,
400: private_ike_cfg_t *this)
401: {
402: ref_get(&this->refcount);
403: return &this->public;
404: }
405:
406: METHOD(ike_cfg_t, destroy, void,
407: private_ike_cfg_t *this)
408: {
409: if (ref_put(&this->refcount))
410: {
411: this->proposals->destroy_offset(this->proposals,
412: offsetof(proposal_t, destroy));
413: free(this->me);
414: free(this->other);
415: this->my_hosts->destroy_function(this->my_hosts, free);
416: this->other_hosts->destroy_function(this->other_hosts, free);
417: this->my_ranges->destroy_offset(this->my_ranges,
418: offsetof(traffic_selector_t, destroy));
419: this->other_ranges->destroy_offset(this->other_ranges,
420: offsetof(traffic_selector_t, destroy));
421: free(this);
422: }
423: }
424:
425: /**
426: * Try to parse a string as subnet
427: */
428: static traffic_selector_t* make_subnet(char *str)
429: {
430: char *pos;
431:
432: pos = strchr(str, '/');
433: if (!pos)
434: {
435: return NULL;
436: }
437: return traffic_selector_create_from_cidr(str, 0, 0, 0);
438: }
439:
440: /**
441: * Try to parse a string as an IP range
442: */
443: static traffic_selector_t* make_range(char *str)
444: {
445: traffic_selector_t *ts;
446: ts_type_t type;
447: host_t *from, *to;
448:
449: if (!host_create_from_range(str, &from, &to))
450: {
451: return NULL;
452: }
453: if (to->get_family(to) == AF_INET)
454: {
455: type = TS_IPV4_ADDR_RANGE;
456: }
457: else
458: {
459: type = TS_IPV6_ADDR_RANGE;
460: }
461: ts = traffic_selector_create_from_bytes(0, type,
462: from->get_address(from), 0,
463: to->get_address(to), 0);
464: from->destroy(from);
465: to->destroy(to);
466: return ts;
467: }
468:
469: /**
470: * Parse address string into lists of single hosts and ranges/subnets
471: */
472: static void parse_addresses(char *str, linked_list_t *hosts,
473: linked_list_t *ranges)
474: {
475: enumerator_t *enumerator;
476: traffic_selector_t *ts;
477:
478: enumerator = enumerator_create_token(str, ",", " ");
479: while (enumerator->enumerate(enumerator, &str))
480: {
481: ts = make_subnet(str);
482: if (ts)
483: {
484: ranges->insert_last(ranges, ts);
485: continue;
486: }
487: ts = make_range(str);
488: if (ts)
489: {
490: ranges->insert_last(ranges, ts);
491: continue;
492: }
493: hosts->insert_last(hosts, strdup(str));
494: }
495: enumerator->destroy(enumerator);
496: }
497:
498: /**
499: * Described in header.
500: */
501: int ike_cfg_get_family(ike_cfg_t *cfg, bool local)
502: {
503: private_ike_cfg_t *this = (private_ike_cfg_t*)cfg;
504: enumerator_t *enumerator;
505: host_t *host;
506: char *str;
507: int family = AF_UNSPEC;
508:
509: if (local)
510: {
511: enumerator = this->my_hosts->create_enumerator(this->my_hosts);
512: }
513: else
514: {
515: enumerator = this->other_hosts->create_enumerator(this->other_hosts);
516: }
517: while (enumerator->enumerate(enumerator, &str))
518: {
519: if (streq(str, "%any"))
520: { /* ignore %any as its family is undetermined */
521: continue;
522: }
523: host = host_create_from_string(str, 0);
524: if (host)
525: {
526: if (family == AF_UNSPEC)
527: {
528: family = host->get_family(host);
529: }
530: else if (family != host->get_family(host))
531: {
532: /* more than one address family defined */
533: family = AF_UNSPEC;
534: host->destroy(host);
535: break;
536: }
537: }
538: DESTROY_IF(host);
539: }
540: enumerator->destroy(enumerator);
541: return family;
542: }
543:
544: /**
545: * Described in header.
546: */
547: bool ike_cfg_has_address(ike_cfg_t *cfg, host_t *addr, bool local)
548: {
549: private_ike_cfg_t *this = (private_ike_cfg_t*)cfg;
550: enumerator_t *enumerator;
551: host_t *host;
552: char *str;
553: bool found = FALSE;
554:
555: if (local)
556: {
557: enumerator = this->my_hosts->create_enumerator(this->my_hosts);
558: }
559: else
560: {
561: enumerator = this->other_hosts->create_enumerator(this->other_hosts);
562: }
563: while (enumerator->enumerate(enumerator, &str))
564: {
565: host = host_create_from_string(str, 0);
566: if (host && addr->ip_equals(addr, host))
567: {
568: host->destroy(host);
569: found = TRUE;
570: break;
571: }
572: DESTROY_IF(host);
573: }
574: enumerator->destroy(enumerator);
575: return found;
576: }
577:
578: /*
579: * Described in header
580: */
581: ike_cfg_t *ike_cfg_create(ike_cfg_create_t *data)
582: {
583: private_ike_cfg_t *this;
584:
585: INIT(this,
586: .public = {
587: .get_version = _get_version,
588: .send_certreq = _send_certreq,
589: .force_encap = _force_encap_,
590: .fragmentation = _fragmentation,
591: .childless = _childless,
592: .resolve_me = _resolve_me,
593: .resolve_other = _resolve_other,
594: .match_me = _match_me,
595: .match_other = _match_other,
596: .get_my_addr = _get_my_addr,
597: .get_other_addr = _get_other_addr,
598: .get_my_port = _get_my_port,
599: .get_other_port = _get_other_port,
600: .get_dscp = _get_dscp,
601: .add_proposal = _add_proposal,
602: .get_proposals = _get_proposals,
603: .select_proposal = _select_proposal,
604: .has_proposal = _has_proposal,
605: .get_dh_group = _get_dh_group,
606: .equals = _equals,
607: .get_ref = _get_ref,
608: .destroy = _destroy,
609: },
610: .refcount = 1,
611: .version = data->version,
612: .certreq = !data->no_certreq,
613: .force_encap = data->force_encap,
614: .fragmentation = data->fragmentation,
615: .childless = data->childless,
616: .me = strdup(data->local),
617: .my_ranges = linked_list_create(),
618: .my_hosts = linked_list_create(),
619: .other = strdup(data->remote),
620: .other_ranges = linked_list_create(),
621: .other_hosts = linked_list_create(),
622: .my_port = data->local_port,
623: .other_port = data->remote_port,
624: .dscp = data->dscp,
625: .proposals = linked_list_create(),
626: );
627:
628: parse_addresses(data->local, this->my_hosts, this->my_ranges);
629: parse_addresses(data->remote, this->other_hosts, this->other_ranges);
630:
631: return &this->public;
632: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>