proposal: correctly enumerate registered AEADs to build default IKE proposal
[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, *subset;
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
272 {
273 subset = cfg_ts->get_subset(cfg_ts, sup_ts);
274 if (subset)
275 {
276 subset->destroy(subset);
277 match += round * 1;
278 }
279 }
280 }
281 cfg_enum->destroy(cfg_enum);
282 round--;
283 }
284 sup_enum->destroy(sup_enum);
285
286 cfg_list->destroy_offset(cfg_list, offsetof(traffic_selector_t, destroy));
287
288 return match;
289 }
290
291 METHOD(peer_cfg_t, select_child_cfg, child_cfg_t*,
292 private_peer_cfg_t *this, linked_list_t *my_ts, linked_list_t *other_ts,
293 linked_list_t *my_hosts, linked_list_t *other_hosts)
294 {
295 child_cfg_t *current, *found = NULL;
296 enumerator_t *enumerator;
297 int best = 0;
298
299 DBG2(DBG_CFG, "looking for a child config for %#R=== %#R", my_ts, other_ts);
300 enumerator = create_child_cfg_enumerator(this);
301 while (enumerator->enumerate(enumerator, &current))
302 {
303 int my_prio, other_prio;
304
305 my_prio = get_ts_match(current, TRUE, my_ts, my_hosts);
306 other_prio = get_ts_match(current, FALSE, other_ts, other_hosts);
307
308 if (my_prio && other_prio)
309 {
310 DBG2(DBG_CFG, " candidate \"%s\" with prio %d+%d",
311 current->get_name(current), my_prio, other_prio);
312 if (my_prio + other_prio > best)
313 {
314 best = my_prio + other_prio;
315 DESTROY_IF(found);
316 found = current->get_ref(current);
317 }
318 }
319 }
320 enumerator->destroy(enumerator);
321 if (found)
322 {
323 DBG2(DBG_CFG, "found matching child config \"%s\" with prio %d",
324 found->get_name(found), best);
325 }
326 return found;
327 }
328
329 METHOD(peer_cfg_t, get_cert_policy, cert_policy_t,
330 private_peer_cfg_t *this)
331 {
332 return this->cert_policy;
333 }
334
335 METHOD(peer_cfg_t, get_unique_policy, unique_policy_t,
336 private_peer_cfg_t *this)
337 {
338 return this->unique;
339 }
340
341 METHOD(peer_cfg_t, get_keyingtries, u_int32_t,
342 private_peer_cfg_t *this)
343 {
344 return this->keyingtries;
345 }
346
347 METHOD(peer_cfg_t, get_rekey_time, u_int32_t,
348 private_peer_cfg_t *this, bool jitter)
349 {
350 if (this->rekey_time == 0)
351 {
352 return 0;
353 }
354 if (this->jitter_time == 0 || !jitter)
355 {
356 return this->rekey_time;
357 }
358 return this->rekey_time - (random() % this->jitter_time);
359 }
360
361 METHOD(peer_cfg_t, get_reauth_time, u_int32_t,
362 private_peer_cfg_t *this, bool jitter)
363 {
364 if (this->reauth_time == 0)
365 {
366 return 0;
367 }
368 if (this->jitter_time == 0 || !jitter)
369 {
370 return this->reauth_time;
371 }
372 return this->reauth_time - (random() % this->jitter_time);
373 }
374
375 METHOD(peer_cfg_t, get_over_time, u_int32_t,
376 private_peer_cfg_t *this)
377 {
378 return this->over_time;
379 }
380
381 METHOD(peer_cfg_t, use_mobike, bool,
382 private_peer_cfg_t *this)
383 {
384 return this->use_mobike;
385 }
386
387 METHOD(peer_cfg_t, use_aggressive, bool,
388 private_peer_cfg_t *this)
389 {
390 return this->aggressive;
391 }
392
393 METHOD(peer_cfg_t, get_dpd, u_int32_t,
394 private_peer_cfg_t *this)
395 {
396 return this->dpd;
397 }
398
399 METHOD(peer_cfg_t, get_dpd_timeout, u_int32_t,
400 private_peer_cfg_t *this)
401 {
402 return this->dpd_timeout;
403 }
404
405 METHOD(peer_cfg_t, add_virtual_ip, void,
406 private_peer_cfg_t *this, host_t *vip)
407 {
408 this->vips->insert_last(this->vips, vip);
409 }
410
411 METHOD(peer_cfg_t, create_virtual_ip_enumerator, enumerator_t*,
412 private_peer_cfg_t *this)
413 {
414 return this->vips->create_enumerator(this->vips);
415 }
416
417 METHOD(peer_cfg_t, add_pool, void,
418 private_peer_cfg_t *this, char *name)
419 {
420 this->pools->insert_last(this->pools, strdup(name));
421 }
422
423 METHOD(peer_cfg_t, create_pool_enumerator, enumerator_t*,
424 private_peer_cfg_t *this)
425 {
426 return this->pools->create_enumerator(this->pools);
427 }
428
429 METHOD(peer_cfg_t, add_auth_cfg, void,
430 private_peer_cfg_t *this, auth_cfg_t *cfg, bool local)
431 {
432 if (local)
433 {
434 this->local_auth->insert_last(this->local_auth, cfg);
435 }
436 else
437 {
438 this->remote_auth->insert_last(this->remote_auth, cfg);
439 }
440 }
441
442 METHOD(peer_cfg_t, create_auth_cfg_enumerator, enumerator_t*,
443 private_peer_cfg_t *this, bool local)
444 {
445 if (local)
446 {
447 return this->local_auth->create_enumerator(this->local_auth);
448 }
449 return this->remote_auth->create_enumerator(this->remote_auth);
450 }
451
452 #ifdef ME
453 METHOD(peer_cfg_t, is_mediation, bool,
454 private_peer_cfg_t *this)
455 {
456 return this->mediation;
457 }
458
459 METHOD(peer_cfg_t, get_mediated_by, peer_cfg_t*,
460 private_peer_cfg_t *this)
461 {
462 return this->mediated_by;
463 }
464
465 METHOD(peer_cfg_t, get_peer_id, identification_t*,
466 private_peer_cfg_t *this)
467 {
468 return this->peer_id;
469 }
470 #endif /* ME */
471
472 /**
473 * check auth configs for equality
474 */
475 static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
476 {
477 enumerator_t *e1, *e2;
478 auth_cfg_t *cfg1, *cfg2;
479 bool equal = TRUE;
480
481 if (this->local_auth->get_count(this->local_auth) !=
482 other->local_auth->get_count(other->local_auth))
483 {
484 return FALSE;
485 }
486 if (this->remote_auth->get_count(this->remote_auth) !=
487 other->remote_auth->get_count(other->remote_auth))
488 {
489 return FALSE;
490 }
491
492 e1 = this->local_auth->create_enumerator(this->local_auth);
493 e2 = other->local_auth->create_enumerator(other->local_auth);
494 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
495 {
496 if (!cfg1->equals(cfg1, cfg2))
497 {
498 equal = FALSE;
499 break;
500 }
501 }
502 e1->destroy(e1);
503 e2->destroy(e2);
504
505 if (!equal)
506 {
507 return FALSE;
508 }
509
510 e1 = this->remote_auth->create_enumerator(this->remote_auth);
511 e2 = other->remote_auth->create_enumerator(other->remote_auth);
512 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
513 {
514 if (!cfg1->equals(cfg1, cfg2))
515 {
516 equal = FALSE;
517 break;
518 }
519 }
520 e1->destroy(e1);
521 e2->destroy(e2);
522
523 return equal;
524 }
525
526 METHOD(peer_cfg_t, equals, bool,
527 private_peer_cfg_t *this, private_peer_cfg_t *other)
528 {
529 enumerator_t *e1, *e2;
530 host_t *vip1, *vip2;
531 char *pool1, *pool2;
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 if (this->pools->get_count(this->pools) !=
561 other->pools->get_count(other->pools))
562 {
563 return FALSE;
564 }
565 e1 = create_pool_enumerator(this);
566 e2 = create_pool_enumerator(other);
567 if (e1->enumerate(e1, &pool1) && e2->enumerate(e2, &pool2))
568 {
569 if (!streq(pool1, pool2))
570 {
571 e1->destroy(e1);
572 e2->destroy(e2);
573 return FALSE;
574 }
575 }
576 e1->destroy(e1);
577 e2->destroy(e2);
578
579 return (
580 get_ike_version(this) == get_ike_version(other) &&
581 this->cert_policy == other->cert_policy &&
582 this->unique == other->unique &&
583 this->keyingtries == other->keyingtries &&
584 this->use_mobike == other->use_mobike &&
585 this->rekey_time == other->rekey_time &&
586 this->reauth_time == other->reauth_time &&
587 this->jitter_time == other->jitter_time &&
588 this->over_time == other->over_time &&
589 this->dpd == other->dpd &&
590 this->aggressive == other->aggressive &&
591 auth_cfg_equal(this, other)
592 #ifdef ME
593 && this->mediation == other->mediation &&
594 this->mediated_by == other->mediated_by &&
595 (this->peer_id == other->peer_id ||
596 (this->peer_id && other->peer_id &&
597 this->peer_id->equals(this->peer_id, other->peer_id)))
598 #endif /* ME */
599 );
600 }
601
602 METHOD(peer_cfg_t, get_ref, peer_cfg_t*,
603 private_peer_cfg_t *this)
604 {
605 ref_get(&this->refcount);
606 return &this->public;
607 }
608
609 METHOD(peer_cfg_t, destroy, void,
610 private_peer_cfg_t *this)
611 {
612 if (ref_put(&this->refcount))
613 {
614 this->ike_cfg->destroy(this->ike_cfg);
615 this->child_cfgs->destroy_offset(this->child_cfgs,
616 offsetof(child_cfg_t, destroy));
617 this->local_auth->destroy_offset(this->local_auth,
618 offsetof(auth_cfg_t, destroy));
619 this->remote_auth->destroy_offset(this->remote_auth,
620 offsetof(auth_cfg_t, destroy));
621 this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
622 this->pools->destroy_function(this->pools, free);
623 #ifdef ME
624 DESTROY_IF(this->mediated_by);
625 DESTROY_IF(this->peer_id);
626 #endif /* ME */
627 this->mutex->destroy(this->mutex);
628 free(this->name);
629 free(this);
630 }
631 }
632
633 /*
634 * Described in header-file
635 */
636 peer_cfg_t *peer_cfg_create(char *name,
637 ike_cfg_t *ike_cfg, cert_policy_t cert_policy,
638 unique_policy_t unique, u_int32_t keyingtries,
639 u_int32_t rekey_time, u_int32_t reauth_time,
640 u_int32_t jitter_time, u_int32_t over_time,
641 bool mobike, bool aggressive, u_int32_t dpd,
642 u_int32_t dpd_timeout,
643 bool mediation, peer_cfg_t *mediated_by,
644 identification_t *peer_id)
645 {
646 private_peer_cfg_t *this;
647
648 if (rekey_time && jitter_time > rekey_time)
649 {
650 jitter_time = rekey_time;
651 }
652 if (reauth_time && jitter_time > reauth_time)
653 {
654 jitter_time = reauth_time;
655 }
656
657 INIT(this,
658 .public = {
659 .get_name = _get_name,
660 .get_ike_version = _get_ike_version,
661 .get_ike_cfg = _get_ike_cfg,
662 .add_child_cfg = _add_child_cfg,
663 .remove_child_cfg = (void*)_remove_child_cfg,
664 .create_child_cfg_enumerator = _create_child_cfg_enumerator,
665 .select_child_cfg = _select_child_cfg,
666 .get_cert_policy = _get_cert_policy,
667 .get_unique_policy = _get_unique_policy,
668 .get_keyingtries = _get_keyingtries,
669 .get_rekey_time = _get_rekey_time,
670 .get_reauth_time = _get_reauth_time,
671 .get_over_time = _get_over_time,
672 .use_mobike = _use_mobike,
673 .use_aggressive = _use_aggressive,
674 .get_dpd = _get_dpd,
675 .get_dpd_timeout = _get_dpd_timeout,
676 .add_virtual_ip = _add_virtual_ip,
677 .create_virtual_ip_enumerator = _create_virtual_ip_enumerator,
678 .add_pool = _add_pool,
679 .create_pool_enumerator = _create_pool_enumerator,
680 .add_auth_cfg = _add_auth_cfg,
681 .create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
682 .equals = (void*)_equals,
683 .get_ref = _get_ref,
684 .destroy = _destroy,
685 #ifdef ME
686 .is_mediation = _is_mediation,
687 .get_mediated_by = _get_mediated_by,
688 .get_peer_id = _get_peer_id,
689 #endif /* ME */
690 },
691 .name = strdup(name),
692 .ike_cfg = ike_cfg,
693 .child_cfgs = linked_list_create(),
694 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
695 .cert_policy = cert_policy,
696 .unique = unique,
697 .keyingtries = keyingtries,
698 .rekey_time = rekey_time,
699 .reauth_time = reauth_time,
700 .jitter_time = jitter_time,
701 .over_time = over_time,
702 .use_mobike = mobike,
703 .aggressive = aggressive,
704 .dpd = dpd,
705 .dpd_timeout = dpd_timeout,
706 .vips = linked_list_create(),
707 .pools = linked_list_create(),
708 .local_auth = linked_list_create(),
709 .remote_auth = linked_list_create(),
710 .refcount = 1,
711 );
712
713 #ifdef ME
714 this->mediation = mediation;
715 this->mediated_by = mediated_by;
716 this->peer_id = peer_id;
717 #else /* ME */
718 DESTROY_IF(mediated_by);
719 DESTROY_IF(peer_id);
720 #endif /* ME */
721
722 return &this->public;
723 }