Support multiple virtual IPs on peer_cfg and ike_sa classes
[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 * pool to acquire configuration attributes from
150 */
151 char *pool;
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, host_t *host)
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, host);
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 host_t *my_host, host_t *other_host)
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_host);
313 other_prio = get_ts_match(current, FALSE, other_ts, other_host);
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, get_pool, char*,
425 private_peer_cfg_t *this)
426 {
427 return this->pool;
428 }
429
430 METHOD(peer_cfg_t, add_auth_cfg, void,
431 private_peer_cfg_t *this, auth_cfg_t *cfg, bool local)
432 {
433 if (local)
434 {
435 this->local_auth->insert_last(this->local_auth, cfg);
436 }
437 else
438 {
439 this->remote_auth->insert_last(this->remote_auth, cfg);
440 }
441 }
442
443 METHOD(peer_cfg_t, create_auth_cfg_enumerator, enumerator_t*,
444 private_peer_cfg_t *this, bool local)
445 {
446 if (local)
447 {
448 return this->local_auth->create_enumerator(this->local_auth);
449 }
450 return this->remote_auth->create_enumerator(this->remote_auth);
451 }
452
453 #ifdef ME
454 METHOD(peer_cfg_t, is_mediation, bool,
455 private_peer_cfg_t *this)
456 {
457 return this->mediation;
458 }
459
460 METHOD(peer_cfg_t, get_mediated_by, peer_cfg_t*,
461 private_peer_cfg_t *this)
462 {
463 return this->mediated_by;
464 }
465
466 METHOD(peer_cfg_t, get_peer_id, identification_t*,
467 private_peer_cfg_t *this)
468 {
469 return this->peer_id;
470 }
471 #endif /* ME */
472
473 /**
474 * check auth configs for equality
475 */
476 static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
477 {
478 enumerator_t *e1, *e2;
479 auth_cfg_t *cfg1, *cfg2;
480 bool equal = TRUE;
481
482 if (this->local_auth->get_count(this->local_auth) !=
483 other->local_auth->get_count(other->local_auth))
484 {
485 return FALSE;
486 }
487 if (this->remote_auth->get_count(this->remote_auth) !=
488 other->remote_auth->get_count(other->remote_auth))
489 {
490 return FALSE;
491 }
492
493 e1 = this->local_auth->create_enumerator(this->local_auth);
494 e2 = other->local_auth->create_enumerator(other->local_auth);
495 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
496 {
497 if (!cfg1->equals(cfg1, cfg2))
498 {
499 equal = FALSE;
500 break;
501 }
502 }
503 e1->destroy(e1);
504 e2->destroy(e2);
505
506 if (!equal)
507 {
508 return FALSE;
509 }
510
511 e1 = this->remote_auth->create_enumerator(this->remote_auth);
512 e2 = other->remote_auth->create_enumerator(other->remote_auth);
513 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
514 {
515 if (!cfg1->equals(cfg1, cfg2))
516 {
517 equal = FALSE;
518 break;
519 }
520 }
521 e1->destroy(e1);
522 e2->destroy(e2);
523
524 return equal;
525 }
526
527 METHOD(peer_cfg_t, equals, bool,
528 private_peer_cfg_t *this, private_peer_cfg_t *other)
529 {
530 enumerator_t *e1, *e2;
531 host_t *vip1, *vip2;
532
533 if (this == other)
534 {
535 return TRUE;
536 }
537 if (this->public.equals != other->public.equals)
538 {
539 return FALSE;
540 }
541
542 if (this->vips->get_count(this->vips) != other->vips->get_count(other->vips))
543 {
544 return FALSE;
545 }
546 e1 = create_virtual_ip_enumerator(this);
547 e2 = create_virtual_ip_enumerator(other);
548 if (e1->enumerate(e1, &vip1) && e2->enumerate(e2, &vip2))
549 {
550 if (!vip1->ip_equals(vip1, vip2))
551 {
552 e1->destroy(e1);
553 e2->destroy(e2);
554 return FALSE;
555 }
556 }
557 e1->destroy(e1);
558 e2->destroy(e2);
559
560 return (
561 this->ike_version == other->ike_version &&
562 this->cert_policy == other->cert_policy &&
563 this->unique == other->unique &&
564 this->keyingtries == other->keyingtries &&
565 this->use_mobike == other->use_mobike &&
566 this->rekey_time == other->rekey_time &&
567 this->reauth_time == other->reauth_time &&
568 this->jitter_time == other->jitter_time &&
569 this->over_time == other->over_time &&
570 this->dpd == other->dpd &&
571 (this->pool == other->pool ||
572 (this->pool && other->pool && streq(this->pool, other->pool))) &&
573 auth_cfg_equal(this, other)
574 #ifdef ME
575 && this->mediation == other->mediation &&
576 this->mediated_by == other->mediated_by &&
577 (this->peer_id == other->peer_id ||
578 (this->peer_id && other->peer_id &&
579 this->peer_id->equals(this->peer_id, other->peer_id)))
580 #endif /* ME */
581 );
582 }
583
584 METHOD(peer_cfg_t, get_ref, peer_cfg_t*,
585 private_peer_cfg_t *this)
586 {
587 ref_get(&this->refcount);
588 return &this->public;
589 }
590
591 METHOD(peer_cfg_t, destroy, void,
592 private_peer_cfg_t *this)
593 {
594 if (ref_put(&this->refcount))
595 {
596 this->ike_cfg->destroy(this->ike_cfg);
597 this->child_cfgs->destroy_offset(this->child_cfgs,
598 offsetof(child_cfg_t, destroy));
599 this->local_auth->destroy_offset(this->local_auth,
600 offsetof(auth_cfg_t, destroy));
601 this->remote_auth->destroy_offset(this->remote_auth,
602 offsetof(auth_cfg_t, destroy));
603 this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
604 #ifdef ME
605 DESTROY_IF(this->mediated_by);
606 DESTROY_IF(this->peer_id);
607 #endif /* ME */
608 this->mutex->destroy(this->mutex);
609 free(this->name);
610 free(this->pool);
611 free(this);
612 }
613 }
614
615 /*
616 * Described in header-file
617 */
618 peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version,
619 ike_cfg_t *ike_cfg, cert_policy_t cert_policy,
620 unique_policy_t unique, u_int32_t keyingtries,
621 u_int32_t rekey_time, u_int32_t reauth_time,
622 u_int32_t jitter_time, u_int32_t over_time,
623 bool mobike, bool aggressive, u_int32_t dpd,
624 u_int32_t dpd_timeout, char *pool,
625 bool mediation, peer_cfg_t *mediated_by,
626 identification_t *peer_id)
627 {
628 private_peer_cfg_t *this;
629
630 if (rekey_time && jitter_time > rekey_time)
631 {
632 jitter_time = rekey_time;
633 }
634 if (reauth_time && jitter_time > reauth_time)
635 {
636 jitter_time = reauth_time;
637 }
638
639 INIT(this,
640 .public = {
641 .get_name = _get_name,
642 .get_ike_version = _get_ike_version,
643 .get_ike_cfg = _get_ike_cfg,
644 .add_child_cfg = _add_child_cfg,
645 .remove_child_cfg = (void*)_remove_child_cfg,
646 .create_child_cfg_enumerator = _create_child_cfg_enumerator,
647 .select_child_cfg = _select_child_cfg,
648 .get_cert_policy = _get_cert_policy,
649 .get_unique_policy = _get_unique_policy,
650 .get_keyingtries = _get_keyingtries,
651 .get_rekey_time = _get_rekey_time,
652 .get_reauth_time = _get_reauth_time,
653 .get_over_time = _get_over_time,
654 .use_mobike = _use_mobike,
655 .use_aggressive = _use_aggressive,
656 .get_dpd = _get_dpd,
657 .get_dpd_timeout = _get_dpd_timeout,
658 .add_virtual_ip = _add_virtual_ip,
659 .create_virtual_ip_enumerator = _create_virtual_ip_enumerator,
660 .get_pool = _get_pool,
661 .add_auth_cfg = _add_auth_cfg,
662 .create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
663 .equals = (void*)_equals,
664 .get_ref = _get_ref,
665 .destroy = _destroy,
666 #ifdef ME
667 .is_mediation = _is_mediation,
668 .get_mediated_by = _get_mediated_by,
669 .get_peer_id = _get_peer_id,
670 #endif /* ME */
671 },
672 .name = strdup(name),
673 .ike_version = ike_version,
674 .ike_cfg = ike_cfg,
675 .child_cfgs = linked_list_create(),
676 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
677 .cert_policy = cert_policy,
678 .unique = unique,
679 .keyingtries = keyingtries,
680 .rekey_time = rekey_time,
681 .reauth_time = reauth_time,
682 .jitter_time = jitter_time,
683 .over_time = over_time,
684 .use_mobike = mobike,
685 .aggressive = aggressive,
686 .dpd = dpd,
687 .dpd_timeout = dpd_timeout,
688 .vips = linked_list_create(),
689 .pool = strdupnull(pool),
690 .local_auth = linked_list_create(),
691 .remote_auth = linked_list_create(),
692 .refcount = 1,
693 );
694
695 #ifdef ME
696 this->mediation = mediation;
697 this->mediated_by = mediated_by;
698 this->peer_id = peer_id;
699 #else /* ME */
700 DESTROY_IF(mediated_by);
701 DESTROY_IF(peer_id);
702 #endif /* ME */
703
704 return &this->public;
705 }