Merge branch 'childless'
[strongswan.git] / src / libcharon / config / ike_cfg.c
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, &current))
312 {
313 current = current->clone(current);
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, private))
333 {
334 enumerator->destroy(enumerator);
335 return TRUE;
336 }
337 }
338 enumerator->destroy(enumerator);
339 return FALSE;
340 }
341
342 METHOD(ike_cfg_t, select_proposal, proposal_t*,
343 private_ike_cfg_t *this, linked_list_t *proposals, bool private,
344 bool prefer_self)
345 {
346 enumerator_t *prefer_enum, *match_enum;
347 proposal_t *proposal, *match, *selected = NULL;
348
349 if (prefer_self)
350 {
351 prefer_enum = this->proposals->create_enumerator(this->proposals);
352 match_enum = proposals->create_enumerator(proposals);
353 }
354 else
355 {
356 prefer_enum = proposals->create_enumerator(proposals);
357 match_enum = this->proposals->create_enumerator(this->proposals);
358 }
359
360 while (prefer_enum->enumerate(prefer_enum, (void**)&proposal))
361 {
362 if (prefer_self)
363 {
364 proposals->reset_enumerator(proposals, match_enum);
365 }
366 else
367 {
368 this->proposals->reset_enumerator(this->proposals, match_enum);
369 }
370 while (match_enum->enumerate(match_enum, (void**)&match))
371 {
372 selected = proposal->select(proposal, match, prefer_self, private);
373 if (selected)
374 {
375 DBG2(DBG_CFG, "received proposals: %#P", proposals);
376 DBG2(DBG_CFG, "configured proposals: %#P", this->proposals);
377 DBG1(DBG_CFG, "selected proposal: %P", selected);
378 break;
379 }
380 }
381 if (selected)
382 {
383 break;
384 }
385 }
386 prefer_enum->destroy(prefer_enum);
387 match_enum->destroy(match_enum);
388 if (!selected)
389 {
390 DBG1(DBG_CFG, "received proposals: %#P", proposals);
391 DBG1(DBG_CFG, "configured proposals: %#P", this->proposals);
392 }
393 return selected;
394 }
395
396 METHOD(ike_cfg_t, get_dh_group, diffie_hellman_group_t,
397 private_ike_cfg_t *this)
398 {
399 enumerator_t *enumerator;
400 proposal_t *proposal;
401 uint16_t dh_group = MODP_NONE;
402
403 enumerator = this->proposals->create_enumerator(this->proposals);
404 while (enumerator->enumerate(enumerator, &proposal))
405 {
406 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL))
407 {
408 break;
409 }
410 }
411 enumerator->destroy(enumerator);
412 return dh_group;
413 }
414
415 METHOD(ike_cfg_t, equals, bool,
416 private_ike_cfg_t *this, ike_cfg_t *other_public)
417 {
418 private_ike_cfg_t *other = (private_ike_cfg_t*)other_public;
419
420 if (this == other)
421 {
422 return TRUE;
423 }
424 if (this->public.equals != other->public.equals)
425 {
426 return FALSE;
427 }
428 if (!this->proposals->equals_offset(this->proposals, other->proposals,
429 offsetof(proposal_t, equals)))
430 {
431 return FALSE;
432 }
433 return
434 this->version == other->version &&
435 this->certreq == other->certreq &&
436 this->force_encap == other->force_encap &&
437 this->fragmentation == other->fragmentation &&
438 this->childless == other->childless &&
439 streq(this->me, other->me) &&
440 streq(this->other, other->other) &&
441 this->my_port == other->my_port &&
442 this->other_port == other->other_port;
443 }
444
445 METHOD(ike_cfg_t, get_ref, ike_cfg_t*,
446 private_ike_cfg_t *this)
447 {
448 ref_get(&this->refcount);
449 return &this->public;
450 }
451
452 METHOD(ike_cfg_t, destroy, void,
453 private_ike_cfg_t *this)
454 {
455 if (ref_put(&this->refcount))
456 {
457 this->proposals->destroy_offset(this->proposals,
458 offsetof(proposal_t, destroy));
459 free(this->me);
460 free(this->other);
461 this->my_hosts->destroy_function(this->my_hosts, free);
462 this->other_hosts->destroy_function(this->other_hosts, free);
463 this->my_ranges->destroy_offset(this->my_ranges,
464 offsetof(traffic_selector_t, destroy));
465 this->other_ranges->destroy_offset(this->other_ranges,
466 offsetof(traffic_selector_t, destroy));
467 free(this);
468 }
469 }
470
471 /**
472 * Try to parse a string as subnet
473 */
474 static traffic_selector_t* make_subnet(char *str)
475 {
476 char *pos;
477
478 pos = strchr(str, '/');
479 if (!pos)
480 {
481 return NULL;
482 }
483 return traffic_selector_create_from_cidr(str, 0, 0, 0);
484 }
485
486 /**
487 * Try to parse a string as an IP range
488 */
489 static traffic_selector_t* make_range(char *str)
490 {
491 traffic_selector_t *ts;
492 ts_type_t type;
493 host_t *from, *to;
494
495 if (!host_create_from_range(str, &from, &to))
496 {
497 return NULL;
498 }
499 if (to->get_family(to) == AF_INET)
500 {
501 type = TS_IPV4_ADDR_RANGE;
502 }
503 else
504 {
505 type = TS_IPV6_ADDR_RANGE;
506 }
507 ts = traffic_selector_create_from_bytes(0, type,
508 from->get_address(from), 0,
509 to->get_address(to), 0);
510 from->destroy(from);
511 to->destroy(to);
512 return ts;
513 }
514
515 /**
516 * Parse address string into lists of single hosts and ranges/subnets
517 */
518 static void parse_addresses(char *str, linked_list_t *hosts,
519 linked_list_t *ranges)
520 {
521 enumerator_t *enumerator;
522 traffic_selector_t *ts;
523
524 enumerator = enumerator_create_token(str, ",", " ");
525 while (enumerator->enumerate(enumerator, &str))
526 {
527 ts = make_subnet(str);
528 if (ts)
529 {
530 ranges->insert_last(ranges, ts);
531 continue;
532 }
533 ts = make_range(str);
534 if (ts)
535 {
536 ranges->insert_last(ranges, ts);
537 continue;
538 }
539 hosts->insert_last(hosts, strdup(str));
540 }
541 enumerator->destroy(enumerator);
542 }
543
544 /**
545 * Described in header.
546 */
547 int ike_cfg_get_family(ike_cfg_t *cfg, 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 int family = AF_UNSPEC;
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 if (streq(str, "%any"))
566 { /* ignore %any as its family is undetermined */
567 continue;
568 }
569 host = host_create_from_string(str, 0);
570 if (host)
571 {
572 if (family == AF_UNSPEC)
573 {
574 family = host->get_family(host);
575 }
576 else if (family != host->get_family(host))
577 {
578 /* more than one address family defined */
579 family = AF_UNSPEC;
580 host->destroy(host);
581 break;
582 }
583 }
584 DESTROY_IF(host);
585 }
586 enumerator->destroy(enumerator);
587 return family;
588 }
589
590 /**
591 * Described in header.
592 */
593 bool ike_cfg_has_address(ike_cfg_t *cfg, host_t *addr, bool local)
594 {
595 private_ike_cfg_t *this = (private_ike_cfg_t*)cfg;
596 enumerator_t *enumerator;
597 host_t *host;
598 char *str;
599 bool found = FALSE;
600
601 if (local)
602 {
603 enumerator = this->my_hosts->create_enumerator(this->my_hosts);
604 }
605 else
606 {
607 enumerator = this->other_hosts->create_enumerator(this->other_hosts);
608 }
609 while (enumerator->enumerate(enumerator, &str))
610 {
611 host = host_create_from_string(str, 0);
612 if (host && addr->ip_equals(addr, host))
613 {
614 host->destroy(host);
615 found = TRUE;
616 break;
617 }
618 DESTROY_IF(host);
619 }
620 enumerator->destroy(enumerator);
621 return found;
622 }
623
624 /*
625 * Described in header
626 */
627 ike_cfg_t *ike_cfg_create(ike_cfg_create_t *data)
628 {
629 private_ike_cfg_t *this;
630
631 INIT(this,
632 .public = {
633 .get_version = _get_version,
634 .send_certreq = _send_certreq,
635 .force_encap = _force_encap_,
636 .fragmentation = _fragmentation,
637 .childless = _childless,
638 .resolve_me = _resolve_me,
639 .resolve_other = _resolve_other,
640 .match_me = _match_me,
641 .match_other = _match_other,
642 .get_my_addr = _get_my_addr,
643 .get_other_addr = _get_other_addr,
644 .get_my_port = _get_my_port,
645 .get_other_port = _get_other_port,
646 .get_dscp = _get_dscp,
647 .add_proposal = _add_proposal,
648 .get_proposals = _get_proposals,
649 .select_proposal = _select_proposal,
650 .has_proposal = _has_proposal,
651 .get_dh_group = _get_dh_group,
652 .equals = _equals,
653 .get_ref = _get_ref,
654 .destroy = _destroy,
655 },
656 .refcount = 1,
657 .version = data->version,
658 .certreq = !data->no_certreq,
659 .force_encap = data->force_encap,
660 .fragmentation = data->fragmentation,
661 .childless = data->childless,
662 .me = strdup(data->local),
663 .my_ranges = linked_list_create(),
664 .my_hosts = linked_list_create(),
665 .other = strdup(data->remote),
666 .other_ranges = linked_list_create(),
667 .other_hosts = linked_list_create(),
668 .my_port = data->local_port,
669 .other_port = data->remote_port,
670 .dscp = data->dscp,
671 .proposals = linked_list_create(),
672 );
673
674 parse_addresses(data->local, this->my_hosts, this->my_ranges);
675 parse_addresses(data->remote, this->other_hosts, this->other_ranges);
676
677 return &this->public;
678 }