Derive a dynamic TS to multiple virtual IPs
[strongswan.git] / src / libcharon / config / peer_cfg.c
1 /*
2 * Copyright (C) 2007-2008 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * 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 #include <string.h>
19
20 #include "peer_cfg.h"
21
22 #include <daemon.h>
23
24 #include <threading/mutex.h>
25 #include <utils/linked_list.h>
26 #include <utils/identification.h>
27
28 ENUM(ike_version_names, IKE_ANY, IKEV2,
29 "IKEv1/2",
30 "IKEv1",
31 "IKEv2",
32 );
33
34 ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
35 "CERT_ALWAYS_SEND",
36 "CERT_SEND_IF_ASKED",
37 "CERT_NEVER_SEND",
38 );
39
40 ENUM(unique_policy_names, UNIQUE_NO, UNIQUE_KEEP,
41 "UNIQUE_NO",
42 "UNIQUE_REPLACE",
43 "UNIQUE_KEEP",
44 );
45
46 typedef struct private_peer_cfg_t private_peer_cfg_t;
47
48 /**
49 * Private data of an peer_cfg_t object
50 */
51 struct private_peer_cfg_t {
52
53 /**
54 * Public part
55 */
56 peer_cfg_t public;
57
58 /**
59 * Number of references hold by others to this peer_cfg
60 */
61 refcount_t refcount;
62
63 /**
64 * Name of the peer_cfg, used to query it
65 */
66 char *name;
67
68 /**
69 * IKE version to use for initiation
70 */
71 ike_version_t ike_version;
72
73 /**
74 * IKE config associated to this peer config
75 */
76 ike_cfg_t *ike_cfg;
77
78 /**
79 * list of child configs associated to this peer config
80 */
81 linked_list_t *child_cfgs;
82
83 /**
84 * mutex to lock access to list of child_cfgs
85 */
86 mutex_t *mutex;
87
88 /**
89 * should we send a certificate
90 */
91 cert_policy_t cert_policy;
92
93 /**
94 * uniqueness of an IKE_SA
95 */
96 unique_policy_t unique;
97
98 /**
99 * number of tries after giving up if peer does not respond
100 */
101 u_int32_t keyingtries;
102
103 /**
104 * enable support for MOBIKE
105 */
106 bool use_mobike;
107
108 /**
109 * Use aggressive mode?
110 */
111 bool aggressive;
112
113 /**
114 * Time before starting rekeying
115 */
116 u_int32_t rekey_time;
117
118 /**
119 * Time before starting reauthentication
120 */
121 u_int32_t reauth_time;
122
123 /**
124 * Time, which specifies the range of a random value subtracted from above.
125 */
126 u_int32_t jitter_time;
127
128 /**
129 * Delay before deleting a rekeying/reauthenticating SA
130 */
131 u_int32_t over_time;
132
133 /**
134 * DPD check intervall
135 */
136 u_int32_t dpd;
137
138 /**
139 * DPD timeout intervall (used for IKEv1 only)
140 */
141 u_int32_t dpd_timeout;
142
143 /**
144 * List of virtual IPs (host_t*) to request
145 */
146 linked_list_t *vips;
147
148 /**
149 * List of pool names to use for virtual IP lookup
150 */
151 linked_list_t *pools;
152
153 /**
154 * local authentication configs (rulesets)
155 */
156 linked_list_t *local_auth;
157
158 /**
159 * remote authentication configs (constraints)
160 */
161 linked_list_t *remote_auth;
162
163 #ifdef ME
164 /**
165 * Is this a mediation connection?
166 */
167 bool mediation;
168
169 /**
170 * Name of the mediation connection to mediate through
171 */
172 peer_cfg_t *mediated_by;
173
174 /**
175 * ID of our peer at the mediation server (= leftid of the peer's conn with
176 * the mediation server)
177 */
178 identification_t *peer_id;
179 #endif /* ME */
180 };
181
182 METHOD(peer_cfg_t, get_name, char*,
183 private_peer_cfg_t *this)
184 {
185 return this->name;
186 }
187
188 METHOD(peer_cfg_t, get_ike_version, ike_version_t,
189 private_peer_cfg_t *this)
190 {
191 return this->ike_version;
192 }
193
194 METHOD(peer_cfg_t, get_ike_cfg, ike_cfg_t*,
195 private_peer_cfg_t *this)
196 {
197 return this->ike_cfg;
198 }
199
200 METHOD(peer_cfg_t, add_child_cfg, void,
201 private_peer_cfg_t *this, child_cfg_t *child_cfg)
202 {
203 this->mutex->lock(this->mutex);
204 this->child_cfgs->insert_last(this->child_cfgs, child_cfg);
205 this->mutex->unlock(this->mutex);
206 }
207
208 /**
209 * child_cfg enumerator
210 */
211 typedef struct {
212 enumerator_t public;
213 enumerator_t *wrapped;
214 mutex_t *mutex;
215 } child_cfg_enumerator_t;
216
217 METHOD(peer_cfg_t, remove_child_cfg, void,
218 private_peer_cfg_t *this, child_cfg_enumerator_t *enumerator)
219 {
220 this->child_cfgs->remove_at(this->child_cfgs, enumerator->wrapped);
221 }
222
223 METHOD(enumerator_t, child_cfg_enumerator_destroy, void,
224 child_cfg_enumerator_t *this)
225 {
226 this->mutex->unlock(this->mutex);
227 this->wrapped->destroy(this->wrapped);
228 free(this);
229 }
230
231 METHOD(enumerator_t, child_cfg_enumerate, bool,
232 child_cfg_enumerator_t *this, child_cfg_t **chd)
233 {
234 return this->wrapped->enumerate(this->wrapped, chd);
235 }
236
237 METHOD(peer_cfg_t, create_child_cfg_enumerator, enumerator_t*,
238 private_peer_cfg_t *this)
239 {
240 child_cfg_enumerator_t *enumerator;
241
242 INIT(enumerator,
243 .public = {
244 .enumerate = (void*)_child_cfg_enumerate,
245 .destroy = (void*)_child_cfg_enumerator_destroy,
246 },
247 .mutex = this->mutex,
248 .wrapped = this->child_cfgs->create_enumerator(this->child_cfgs),
249 );
250
251 this->mutex->lock(this->mutex);
252 return &enumerator->public;
253 }
254
255 /**
256 * Check how good a list of TS matches a given child config
257 */
258 static int get_ts_match(child_cfg_t *cfg, bool local,
259 linked_list_t *sup_list, linked_list_t *hosts)
260 {
261 linked_list_t *cfg_list;
262 enumerator_t *sup_enum, *cfg_enum;
263 traffic_selector_t *sup_ts, *cfg_ts;
264 int match = 0, round;
265
266 /* fetch configured TS list, narrowing dynamic TS */
267 cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, hosts);
268
269 /* use a round counter to rate leading TS with higher priority */
270 round = sup_list->get_count(sup_list);
271
272 sup_enum = sup_list->create_enumerator(sup_list);
273 while (sup_enum->enumerate(sup_enum, &sup_ts))
274 {
275 cfg_enum = cfg_list->create_enumerator(cfg_list);
276 while (cfg_enum->enumerate(cfg_enum, &cfg_ts))
277 {
278 if (cfg_ts->equals(cfg_ts, sup_ts))
279 { /* equality is honored better than matches */
280 match += round * 5;
281 }
282 else if (cfg_ts->is_contained_in(cfg_ts, sup_ts) ||
283 sup_ts->is_contained_in(sup_ts, cfg_ts))
284 {
285 match += round * 1;
286 }
287 }
288 cfg_enum->destroy(cfg_enum);
289 round--;
290 }
291 sup_enum->destroy(sup_enum);
292
293 cfg_list->destroy_offset(cfg_list, offsetof(traffic_selector_t, destroy));
294
295 return match;
296 }
297
298 METHOD(peer_cfg_t, select_child_cfg, child_cfg_t*,
299 private_peer_cfg_t *this, linked_list_t *my_ts, linked_list_t *other_ts,
300 linked_list_t *my_hosts, linked_list_t *other_hosts)
301 {
302 child_cfg_t *current, *found = NULL;
303 enumerator_t *enumerator;
304 int best = 0;
305
306 DBG2(DBG_CFG, "looking for a child config for %#R=== %#R", my_ts, other_ts);
307 enumerator = create_child_cfg_enumerator(this);
308 while (enumerator->enumerate(enumerator, &current))
309 {
310 int my_prio, other_prio;
311
312 my_prio = get_ts_match(current, TRUE, my_ts, my_hosts);
313 other_prio = get_ts_match(current, FALSE, other_ts, other_hosts);
314
315 if (my_prio && other_prio)
316 {
317 DBG2(DBG_CFG, " candidate \"%s\" with prio %d+%d",
318 current->get_name(current), my_prio, other_prio);
319 if (my_prio + other_prio > best)
320 {
321 best = my_prio + other_prio;
322 DESTROY_IF(found);
323 found = current->get_ref(current);
324 }
325 }
326 }
327 enumerator->destroy(enumerator);
328 if (found)
329 {
330 DBG2(DBG_CFG, "found matching child config \"%s\" with prio %d",
331 found->get_name(found), best);
332 }
333 return found;
334 }
335
336 METHOD(peer_cfg_t, get_cert_policy, cert_policy_t,
337 private_peer_cfg_t *this)
338 {
339 return this->cert_policy;
340 }
341
342 METHOD(peer_cfg_t, get_unique_policy, unique_policy_t,
343 private_peer_cfg_t *this)
344 {
345 return this->unique;
346 }
347
348 METHOD(peer_cfg_t, get_keyingtries, u_int32_t,
349 private_peer_cfg_t *this)
350 {
351 return this->keyingtries;
352 }
353
354 METHOD(peer_cfg_t, get_rekey_time, u_int32_t,
355 private_peer_cfg_t *this, bool jitter)
356 {
357 if (this->rekey_time == 0)
358 {
359 return 0;
360 }
361 if (this->jitter_time == 0 || !jitter)
362 {
363 return this->rekey_time;
364 }
365 return this->rekey_time - (random() % this->jitter_time);
366 }
367
368 METHOD(peer_cfg_t, get_reauth_time, u_int32_t,
369 private_peer_cfg_t *this, bool jitter)
370 {
371 if (this->reauth_time == 0)
372 {
373 return 0;
374 }
375 if (this->jitter_time == 0 || !jitter)
376 {
377 return this->reauth_time;
378 }
379 return this->reauth_time - (random() % this->jitter_time);
380 }
381
382 METHOD(peer_cfg_t, get_over_time, u_int32_t,
383 private_peer_cfg_t *this)
384 {
385 return this->over_time;
386 }
387
388 METHOD(peer_cfg_t, use_mobike, bool,
389 private_peer_cfg_t *this)
390 {
391 return this->use_mobike;
392 }
393
394 METHOD(peer_cfg_t, use_aggressive, bool,
395 private_peer_cfg_t *this)
396 {
397 return this->aggressive;
398 }
399
400 METHOD(peer_cfg_t, get_dpd, u_int32_t,
401 private_peer_cfg_t *this)
402 {
403 return this->dpd;
404 }
405
406 METHOD(peer_cfg_t, get_dpd_timeout, u_int32_t,
407 private_peer_cfg_t *this)
408 {
409 return this->dpd_timeout;
410 }
411
412 METHOD(peer_cfg_t, add_virtual_ip, void,
413 private_peer_cfg_t *this, host_t *vip)
414 {
415 this->vips->insert_last(this->vips, vip);
416 }
417
418 METHOD(peer_cfg_t, create_virtual_ip_enumerator, enumerator_t*,
419 private_peer_cfg_t *this)
420 {
421 return this->vips->create_enumerator(this->vips);
422 }
423
424 METHOD(peer_cfg_t, add_pool, void,
425 private_peer_cfg_t *this, char *name)
426 {
427 this->pools->insert_last(this->pools, strdup(name));
428 }
429
430 METHOD(peer_cfg_t, create_pool_enumerator, enumerator_t*,
431 private_peer_cfg_t *this)
432 {
433 return this->pools->create_enumerator(this->pools);
434 }
435
436 METHOD(peer_cfg_t, add_auth_cfg, void,
437 private_peer_cfg_t *this, auth_cfg_t *cfg, bool local)
438 {
439 if (local)
440 {
441 this->local_auth->insert_last(this->local_auth, cfg);
442 }
443 else
444 {
445 this->remote_auth->insert_last(this->remote_auth, cfg);
446 }
447 }
448
449 METHOD(peer_cfg_t, create_auth_cfg_enumerator, enumerator_t*,
450 private_peer_cfg_t *this, bool local)
451 {
452 if (local)
453 {
454 return this->local_auth->create_enumerator(this->local_auth);
455 }
456 return this->remote_auth->create_enumerator(this->remote_auth);
457 }
458
459 #ifdef ME
460 METHOD(peer_cfg_t, is_mediation, bool,
461 private_peer_cfg_t *this)
462 {
463 return this->mediation;
464 }
465
466 METHOD(peer_cfg_t, get_mediated_by, peer_cfg_t*,
467 private_peer_cfg_t *this)
468 {
469 return this->mediated_by;
470 }
471
472 METHOD(peer_cfg_t, get_peer_id, identification_t*,
473 private_peer_cfg_t *this)
474 {
475 return this->peer_id;
476 }
477 #endif /* ME */
478
479 /**
480 * check auth configs for equality
481 */
482 static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
483 {
484 enumerator_t *e1, *e2;
485 auth_cfg_t *cfg1, *cfg2;
486 bool equal = TRUE;
487
488 if (this->local_auth->get_count(this->local_auth) !=
489 other->local_auth->get_count(other->local_auth))
490 {
491 return FALSE;
492 }
493 if (this->remote_auth->get_count(this->remote_auth) !=
494 other->remote_auth->get_count(other->remote_auth))
495 {
496 return FALSE;
497 }
498
499 e1 = this->local_auth->create_enumerator(this->local_auth);
500 e2 = other->local_auth->create_enumerator(other->local_auth);
501 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
502 {
503 if (!cfg1->equals(cfg1, cfg2))
504 {
505 equal = FALSE;
506 break;
507 }
508 }
509 e1->destroy(e1);
510 e2->destroy(e2);
511
512 if (!equal)
513 {
514 return FALSE;
515 }
516
517 e1 = this->remote_auth->create_enumerator(this->remote_auth);
518 e2 = other->remote_auth->create_enumerator(other->remote_auth);
519 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
520 {
521 if (!cfg1->equals(cfg1, cfg2))
522 {
523 equal = FALSE;
524 break;
525 }
526 }
527 e1->destroy(e1);
528 e2->destroy(e2);
529
530 return equal;
531 }
532
533 METHOD(peer_cfg_t, equals, bool,
534 private_peer_cfg_t *this, private_peer_cfg_t *other)
535 {
536 enumerator_t *e1, *e2;
537 host_t *vip1, *vip2;
538 char *pool1, *pool2;
539
540 if (this == other)
541 {
542 return TRUE;
543 }
544 if (this->public.equals != other->public.equals)
545 {
546 return FALSE;
547 }
548
549 if (this->vips->get_count(this->vips) != other->vips->get_count(other->vips))
550 {
551 return FALSE;
552 }
553 e1 = create_virtual_ip_enumerator(this);
554 e2 = create_virtual_ip_enumerator(other);
555 if (e1->enumerate(e1, &vip1) && e2->enumerate(e2, &vip2))
556 {
557 if (!vip1->ip_equals(vip1, vip2))
558 {
559 e1->destroy(e1);
560 e2->destroy(e2);
561 return FALSE;
562 }
563 }
564 e1->destroy(e1);
565 e2->destroy(e2);
566
567 if (this->pools->get_count(this->pools) !=
568 other->pools->get_count(other->pools))
569 {
570 return FALSE;
571 }
572 e1 = create_pool_enumerator(this);
573 e2 = create_pool_enumerator(other);
574 if (e1->enumerate(e1, &pool1) && e2->enumerate(e2, &pool2))
575 {
576 if (!streq(pool1, pool2))
577 {
578 e1->destroy(e1);
579 e2->destroy(e2);
580 return FALSE;
581 }
582 }
583 e1->destroy(e1);
584 e2->destroy(e2);
585
586 return (
587 this->ike_version == other->ike_version &&
588 this->cert_policy == other->cert_policy &&
589 this->unique == other->unique &&
590 this->keyingtries == other->keyingtries &&
591 this->use_mobike == other->use_mobike &&
592 this->rekey_time == other->rekey_time &&
593 this->reauth_time == other->reauth_time &&
594 this->jitter_time == other->jitter_time &&
595 this->over_time == other->over_time &&
596 this->dpd == other->dpd &&
597 auth_cfg_equal(this, other)
598 #ifdef ME
599 && this->mediation == other->mediation &&
600 this->mediated_by == other->mediated_by &&
601 (this->peer_id == other->peer_id ||
602 (this->peer_id && other->peer_id &&
603 this->peer_id->equals(this->peer_id, other->peer_id)))
604 #endif /* ME */
605 );
606 }
607
608 METHOD(peer_cfg_t, get_ref, peer_cfg_t*,
609 private_peer_cfg_t *this)
610 {
611 ref_get(&this->refcount);
612 return &this->public;
613 }
614
615 METHOD(peer_cfg_t, destroy, void,
616 private_peer_cfg_t *this)
617 {
618 if (ref_put(&this->refcount))
619 {
620 this->ike_cfg->destroy(this->ike_cfg);
621 this->child_cfgs->destroy_offset(this->child_cfgs,
622 offsetof(child_cfg_t, destroy));
623 this->local_auth->destroy_offset(this->local_auth,
624 offsetof(auth_cfg_t, destroy));
625 this->remote_auth->destroy_offset(this->remote_auth,
626 offsetof(auth_cfg_t, destroy));
627 this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
628 this->pools->destroy_function(this->pools, free);
629 #ifdef ME
630 DESTROY_IF(this->mediated_by);
631 DESTROY_IF(this->peer_id);
632 #endif /* ME */
633 this->mutex->destroy(this->mutex);
634 free(this->name);
635 free(this);
636 }
637 }
638
639 /*
640 * Described in header-file
641 */
642 peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version,
643 ike_cfg_t *ike_cfg, cert_policy_t cert_policy,
644 unique_policy_t unique, u_int32_t keyingtries,
645 u_int32_t rekey_time, u_int32_t reauth_time,
646 u_int32_t jitter_time, u_int32_t over_time,
647 bool mobike, bool aggressive, u_int32_t dpd,
648 u_int32_t dpd_timeout,
649 bool mediation, peer_cfg_t *mediated_by,
650 identification_t *peer_id)
651 {
652 private_peer_cfg_t *this;
653
654 if (rekey_time && jitter_time > rekey_time)
655 {
656 jitter_time = rekey_time;
657 }
658 if (reauth_time && jitter_time > reauth_time)
659 {
660 jitter_time = reauth_time;
661 }
662
663 INIT(this,
664 .public = {
665 .get_name = _get_name,
666 .get_ike_version = _get_ike_version,
667 .get_ike_cfg = _get_ike_cfg,
668 .add_child_cfg = _add_child_cfg,
669 .remove_child_cfg = (void*)_remove_child_cfg,
670 .create_child_cfg_enumerator = _create_child_cfg_enumerator,
671 .select_child_cfg = _select_child_cfg,
672 .get_cert_policy = _get_cert_policy,
673 .get_unique_policy = _get_unique_policy,
674 .get_keyingtries = _get_keyingtries,
675 .get_rekey_time = _get_rekey_time,
676 .get_reauth_time = _get_reauth_time,
677 .get_over_time = _get_over_time,
678 .use_mobike = _use_mobike,
679 .use_aggressive = _use_aggressive,
680 .get_dpd = _get_dpd,
681 .get_dpd_timeout = _get_dpd_timeout,
682 .add_virtual_ip = _add_virtual_ip,
683 .create_virtual_ip_enumerator = _create_virtual_ip_enumerator,
684 .add_pool = _add_pool,
685 .create_pool_enumerator = _create_pool_enumerator,
686 .add_auth_cfg = _add_auth_cfg,
687 .create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
688 .equals = (void*)_equals,
689 .get_ref = _get_ref,
690 .destroy = _destroy,
691 #ifdef ME
692 .is_mediation = _is_mediation,
693 .get_mediated_by = _get_mediated_by,
694 .get_peer_id = _get_peer_id,
695 #endif /* ME */
696 },
697 .name = strdup(name),
698 .ike_version = ike_version,
699 .ike_cfg = ike_cfg,
700 .child_cfgs = linked_list_create(),
701 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
702 .cert_policy = cert_policy,
703 .unique = unique,
704 .keyingtries = keyingtries,
705 .rekey_time = rekey_time,
706 .reauth_time = reauth_time,
707 .jitter_time = jitter_time,
708 .over_time = over_time,
709 .use_mobike = mobike,
710 .aggressive = aggressive,
711 .dpd = dpd,
712 .dpd_timeout = dpd_timeout,
713 .vips = linked_list_create(),
714 .pools = linked_list_create(),
715 .local_auth = linked_list_create(),
716 .remote_auth = linked_list_create(),
717 .refcount = 1,
718 );
719
720 #ifdef ME
721 this->mediation = mediation;
722 this->mediated_by = mediated_by;
723 this->peer_id = peer_id;
724 #else /* ME */
725 DESTROY_IF(mediated_by);
726 DESTROY_IF(peer_id);
727 #endif /* ME */
728
729 return &this->public;
730 }