Added a get_rekey/reauth_time() jitter parameter to get time without randomization
[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, IKEV1, IKEV2,
29 "IKEv1",
30 "IKEv2",
31 );
32
33 ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
34 "CERT_ALWAYS_SEND",
35 "CERT_SEND_IF_ASKED",
36 "CERT_NEVER_SEND",
37 );
38
39 ENUM(unique_policy_names, UNIQUE_NO, UNIQUE_KEEP,
40 "UNIQUE_NO",
41 "UNIQUE_REPLACE",
42 "UNIQUE_KEEP",
43 );
44
45 typedef struct private_peer_cfg_t private_peer_cfg_t;
46
47 /**
48 * Private data of an peer_cfg_t object
49 */
50 struct private_peer_cfg_t {
51
52 /**
53 * Public part
54 */
55 peer_cfg_t public;
56
57 /**
58 * Number of references hold by others to this peer_cfg
59 */
60 refcount_t refcount;
61
62 /**
63 * Name of the peer_cfg, used to query it
64 */
65 char *name;
66
67 /**
68 * IKE version to use for initiation
69 */
70 ike_version_t ike_version;
71
72 /**
73 * IKE config associated to this peer config
74 */
75 ike_cfg_t *ike_cfg;
76
77 /**
78 * list of child configs associated to this peer config
79 */
80 linked_list_t *child_cfgs;
81
82 /**
83 * mutex to lock access to list of child_cfgs
84 */
85 mutex_t *mutex;
86
87 /**
88 * should we send a certificate
89 */
90 cert_policy_t cert_policy;
91
92 /**
93 * uniqueness of an IKE_SA
94 */
95 unique_policy_t unique;
96
97 /**
98 * number of tries after giving up if peer does not respond
99 */
100 u_int32_t keyingtries;
101
102 /**
103 * enable support for MOBIKE
104 */
105 bool use_mobike;
106
107 /**
108 * Time before starting rekeying
109 */
110 u_int32_t rekey_time;
111
112 /**
113 * Time before starting reauthentication
114 */
115 u_int32_t reauth_time;
116
117 /**
118 * Time, which specifies the range of a random value subtracted from above.
119 */
120 u_int32_t jitter_time;
121
122 /**
123 * Delay before deleting a rekeying/reauthenticating SA
124 */
125 u_int32_t over_time;
126
127 /**
128 * DPD check intervall
129 */
130 u_int32_t dpd;
131
132 /**
133 * virtual IP to use locally
134 */
135 host_t *virtual_ip;
136
137 /**
138 * pool to acquire configuration attributes from
139 */
140 char *pool;
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_version;
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, host_t *host)
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, host);
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 host_t *my_host, host_t *other_host)
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_host);
302 other_prio = get_ts_match(current, FALSE, other_ts, other_host);
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, get_dpd, u_int32_t,
384 private_peer_cfg_t *this)
385 {
386 return this->dpd;
387 }
388
389 METHOD(peer_cfg_t, get_virtual_ip, host_t*,
390 private_peer_cfg_t *this)
391 {
392 return this->virtual_ip;
393 }
394
395 METHOD(peer_cfg_t, get_pool, char*,
396 private_peer_cfg_t *this)
397 {
398 return this->pool;
399 }
400
401 METHOD(peer_cfg_t, add_auth_cfg, void,
402 private_peer_cfg_t *this, auth_cfg_t *cfg, bool local)
403 {
404 if (local)
405 {
406 this->local_auth->insert_last(this->local_auth, cfg);
407 }
408 else
409 {
410 this->remote_auth->insert_last(this->remote_auth, cfg);
411 }
412 }
413
414 METHOD(peer_cfg_t, create_auth_cfg_enumerator, enumerator_t*,
415 private_peer_cfg_t *this, bool local)
416 {
417 if (local)
418 {
419 return this->local_auth->create_enumerator(this->local_auth);
420 }
421 return this->remote_auth->create_enumerator(this->remote_auth);
422 }
423
424 #ifdef ME
425 METHOD(peer_cfg_t, is_mediation, bool,
426 private_peer_cfg_t *this)
427 {
428 return this->mediation;
429 }
430
431 METHOD(peer_cfg_t, get_mediated_by, peer_cfg_t*,
432 private_peer_cfg_t *this)
433 {
434 return this->mediated_by;
435 }
436
437 METHOD(peer_cfg_t, get_peer_id, identification_t*,
438 private_peer_cfg_t *this)
439 {
440 return this->peer_id;
441 }
442 #endif /* ME */
443
444 /**
445 * check auth configs for equality
446 */
447 static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
448 {
449 enumerator_t *e1, *e2;
450 auth_cfg_t *cfg1, *cfg2;
451 bool equal = TRUE;
452
453 if (this->local_auth->get_count(this->local_auth) !=
454 other->local_auth->get_count(other->local_auth))
455 {
456 return FALSE;
457 }
458 if (this->remote_auth->get_count(this->remote_auth) !=
459 other->remote_auth->get_count(other->remote_auth))
460 {
461 return FALSE;
462 }
463
464 e1 = this->local_auth->create_enumerator(this->local_auth);
465 e2 = other->local_auth->create_enumerator(other->local_auth);
466 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
467 {
468 if (!cfg1->equals(cfg1, cfg2))
469 {
470 equal = FALSE;
471 break;
472 }
473 }
474 e1->destroy(e1);
475 e2->destroy(e2);
476
477 if (!equal)
478 {
479 return FALSE;
480 }
481
482 e1 = this->remote_auth->create_enumerator(this->remote_auth);
483 e2 = other->remote_auth->create_enumerator(other->remote_auth);
484 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
485 {
486 if (!cfg1->equals(cfg1, cfg2))
487 {
488 equal = FALSE;
489 break;
490 }
491 }
492 e1->destroy(e1);
493 e2->destroy(e2);
494
495 return equal;
496 }
497
498 METHOD(peer_cfg_t, equals, bool,
499 private_peer_cfg_t *this, private_peer_cfg_t *other)
500 {
501 if (this == other)
502 {
503 return TRUE;
504 }
505 if (this->public.equals != other->public.equals)
506 {
507 return FALSE;
508 }
509
510 return (
511 this->ike_version == other->ike_version &&
512 this->cert_policy == other->cert_policy &&
513 this->unique == other->unique &&
514 this->keyingtries == other->keyingtries &&
515 this->use_mobike == other->use_mobike &&
516 this->rekey_time == other->rekey_time &&
517 this->reauth_time == other->reauth_time &&
518 this->jitter_time == other->jitter_time &&
519 this->over_time == other->over_time &&
520 this->dpd == other->dpd &&
521 (this->virtual_ip == other->virtual_ip ||
522 (this->virtual_ip && other->virtual_ip &&
523 this->virtual_ip->equals(this->virtual_ip, other->virtual_ip))) &&
524 (this->pool == other->pool ||
525 (this->pool && other->pool && streq(this->pool, other->pool))) &&
526 auth_cfg_equal(this, other)
527 #ifdef ME
528 && this->mediation == other->mediation &&
529 this->mediated_by == other->mediated_by &&
530 (this->peer_id == other->peer_id ||
531 (this->peer_id && other->peer_id &&
532 this->peer_id->equals(this->peer_id, other->peer_id)))
533 #endif /* ME */
534 );
535 }
536
537 METHOD(peer_cfg_t, get_ref, peer_cfg_t*,
538 private_peer_cfg_t *this)
539 {
540 ref_get(&this->refcount);
541 return &this->public;
542 }
543
544 METHOD(peer_cfg_t, destroy, void,
545 private_peer_cfg_t *this)
546 {
547 if (ref_put(&this->refcount))
548 {
549 this->ike_cfg->destroy(this->ike_cfg);
550 this->child_cfgs->destroy_offset(this->child_cfgs,
551 offsetof(child_cfg_t, destroy));
552 DESTROY_IF(this->virtual_ip);
553 this->local_auth->destroy_offset(this->local_auth,
554 offsetof(auth_cfg_t, destroy));
555 this->remote_auth->destroy_offset(this->remote_auth,
556 offsetof(auth_cfg_t, destroy));
557 #ifdef ME
558 DESTROY_IF(this->mediated_by);
559 DESTROY_IF(this->peer_id);
560 #endif /* ME */
561 this->mutex->destroy(this->mutex);
562 free(this->name);
563 free(this->pool);
564 free(this);
565 }
566 }
567
568 /*
569 * Described in header-file
570 */
571 peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version,
572 ike_cfg_t *ike_cfg, cert_policy_t cert_policy,
573 unique_policy_t unique, u_int32_t keyingtries,
574 u_int32_t rekey_time, u_int32_t reauth_time,
575 u_int32_t jitter_time, u_int32_t over_time,
576 bool mobike, u_int32_t dpd, host_t *virtual_ip,
577 char *pool, bool mediation, peer_cfg_t *mediated_by,
578 identification_t *peer_id)
579 {
580 private_peer_cfg_t *this;
581
582 if (rekey_time && jitter_time > rekey_time)
583 {
584 jitter_time = rekey_time;
585 }
586 if (reauth_time && jitter_time > reauth_time)
587 {
588 jitter_time = reauth_time;
589 }
590
591 INIT(this,
592 .public = {
593 .get_name = _get_name,
594 .get_ike_version = _get_ike_version,
595 .get_ike_cfg = _get_ike_cfg,
596 .add_child_cfg = _add_child_cfg,
597 .remove_child_cfg = (void*)_remove_child_cfg,
598 .create_child_cfg_enumerator = _create_child_cfg_enumerator,
599 .select_child_cfg = _select_child_cfg,
600 .get_cert_policy = _get_cert_policy,
601 .get_unique_policy = _get_unique_policy,
602 .get_keyingtries = _get_keyingtries,
603 .get_rekey_time = _get_rekey_time,
604 .get_reauth_time = _get_reauth_time,
605 .get_over_time = _get_over_time,
606 .use_mobike = _use_mobike,
607 .get_dpd = _get_dpd,
608 .get_virtual_ip = _get_virtual_ip,
609 .get_pool = _get_pool,
610 .add_auth_cfg = _add_auth_cfg,
611 .create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
612 .equals = (void*)_equals,
613 .get_ref = _get_ref,
614 .destroy = _destroy,
615 #ifdef ME
616 .is_mediation = _is_mediation,
617 .get_mediated_by = _get_mediated_by,
618 .get_peer_id = _get_peer_id,
619 #endif /* ME */
620 },
621 .name = strdup(name),
622 .ike_version = ike_version,
623 .ike_cfg = ike_cfg,
624 .child_cfgs = linked_list_create(),
625 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
626 .cert_policy = cert_policy,
627 .unique = unique,
628 .keyingtries = keyingtries,
629 .rekey_time = rekey_time,
630 .reauth_time = reauth_time,
631 .jitter_time = jitter_time,
632 .over_time = over_time,
633 .use_mobike = mobike,
634 .dpd = dpd,
635 .virtual_ip = virtual_ip,
636 .pool = strdupnull(pool),
637 .local_auth = linked_list_create(),
638 .remote_auth = linked_list_create(),
639 .refcount = 1,
640 );
641
642 #ifdef ME
643 this->mediation = mediation;
644 this->mediated_by = mediated_by;
645 this->peer_id = peer_id;
646 #else /* ME */
647 DESTROY_IF(mediated_by);
648 DESTROY_IF(peer_id);
649 #endif /* ME */
650
651 return &this->public;
652 }