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