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