Removed strayed code fragment
[strongswan.git] / src / charon / 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(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 version to use for initiation
64 */
65 u_int ike_version;
66
67 /**
68 * IKE config associated to this peer config
69 */
70 ike_cfg_t *ike_cfg;
71
72 /**
73 * list of child configs associated to this peer config
74 */
75 linked_list_t *child_cfgs;
76
77 /**
78 * mutex to lock access to list of child_cfgs
79 */
80 mutex_t *mutex;
81
82 /**
83 * should we send a certificate
84 */
85 cert_policy_t cert_policy;
86
87 /**
88 * uniqueness of an IKE_SA
89 */
90 unique_policy_t unique;
91
92 /**
93 * number of tries after giving up if peer does not respond
94 */
95 u_int32_t keyingtries;
96
97 /**
98 * enable support for MOBIKE
99 */
100 bool use_mobike;
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 substracted 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 * virtual IP to use locally
129 */
130 host_t *virtual_ip;
131
132 /**
133 * pool to acquire configuration attributes from
134 */
135 char *pool;
136
137 /**
138 * local authentication configs (rulesets)
139 */
140 linked_list_t *local_auth;
141
142 /**
143 * remote authentication configs (constraints)
144 */
145 linked_list_t *remote_auth;
146
147 #ifdef ME
148 /**
149 * Is this a mediation connection?
150 */
151 bool mediation;
152
153 /**
154 * Name of the mediation connection to mediate through
155 */
156 peer_cfg_t *mediated_by;
157
158 /**
159 * ID of our peer at the mediation server (= leftid of the peer's conn with
160 * the mediation server)
161 */
162 identification_t *peer_id;
163 #endif /* ME */
164 };
165
166 /**
167 * Implementation of peer_cfg_t.get_name
168 */
169 static char *get_name(private_peer_cfg_t *this)
170 {
171 return this->name;
172 }
173
174 /**
175 * Implementation of peer_cfg_t.get_ike_version
176 */
177 static u_int get_ike_version(private_peer_cfg_t *this)
178 {
179 return this->ike_version;
180 }
181
182 /**
183 * Implementation of peer_cfg_t.get_ike_cfg
184 */
185 static ike_cfg_t* get_ike_cfg(private_peer_cfg_t *this)
186 {
187 return this->ike_cfg;
188 }
189
190 /**
191 * Implementation of peer_cfg_t.add_child_cfg.
192 */
193 static void add_child_cfg(private_peer_cfg_t *this, child_cfg_t *child_cfg)
194 {
195 this->mutex->lock(this->mutex);
196 this->child_cfgs->insert_last(this->child_cfgs, child_cfg);
197 this->mutex->unlock(this->mutex);
198 }
199
200 /**
201 * child_cfg enumerator
202 */
203 typedef struct {
204 enumerator_t public;
205 enumerator_t *wrapped;
206 mutex_t *mutex;
207 } child_cfg_enumerator_t;
208
209 /**
210 * Implementation of peer_cfg_t.remove_child_cfg.
211 */
212 static void remove_child_cfg(private_peer_cfg_t *this,
213 child_cfg_enumerator_t *enumerator)
214 {
215 this->child_cfgs->remove_at(this->child_cfgs, enumerator->wrapped);
216 }
217
218 /**
219 * Implementation of child_cfg_enumerator_t.destroy
220 */
221 static void child_cfg_enumerator_destroy(child_cfg_enumerator_t *this)
222 {
223 this->mutex->unlock(this->mutex);
224 this->wrapped->destroy(this->wrapped);
225 free(this);
226 }
227
228 /**
229 * Implementation of child_cfg_enumerator_t.enumerate
230 */
231 static bool child_cfg_enumerate(child_cfg_enumerator_t *this, child_cfg_t **chd)
232 {
233 return this->wrapped->enumerate(this->wrapped, chd);
234 }
235
236 /**
237 * Implementation of peer_cfg_t.create_child_cfg_enumerator.
238 */
239 static enumerator_t* create_child_cfg_enumerator(private_peer_cfg_t *this)
240 {
241 child_cfg_enumerator_t *enumerator = malloc_thing(child_cfg_enumerator_t);
242
243 enumerator->public.enumerate = (void*)child_cfg_enumerate;
244 enumerator->public.destroy = (void*)child_cfg_enumerator_destroy;
245 enumerator->mutex = this->mutex;
246 enumerator->wrapped = this->child_cfgs->create_enumerator(this->child_cfgs);
247
248 this->mutex->lock(this->mutex);
249 return &enumerator->public;
250 }
251
252 /**
253 * Check how good a list of TS matches a given child config
254 */
255 static int get_ts_match(child_cfg_t *cfg, bool local,
256 linked_list_t *sup_list, host_t *host)
257 {
258 linked_list_t *cfg_list;
259 enumerator_t *sup_enum, *cfg_enum;
260 traffic_selector_t *sup_ts, *cfg_ts;
261 int match = 0, round;
262
263 /* fetch configured TS list, narrowing dynamic TS */
264 cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, host);
265
266 /* use a round counter to rate leading TS with higher priority */
267 round = sup_list->get_count(sup_list);
268
269 sup_enum = sup_list->create_enumerator(sup_list);
270 while (sup_enum->enumerate(sup_enum, &sup_ts))
271 {
272 cfg_enum = cfg_list->create_enumerator(cfg_list);
273 while (cfg_enum->enumerate(cfg_enum, &cfg_ts))
274 {
275 if (cfg_ts->equals(cfg_ts, sup_ts))
276 { /* equality is honored better than matches */
277 match += round * 5;
278 }
279 else if (cfg_ts->is_contained_in(cfg_ts, sup_ts) ||
280 sup_ts->is_contained_in(sup_ts, cfg_ts))
281 {
282 match += round * 1;
283 }
284 }
285 cfg_enum->destroy(cfg_enum);
286 round--;
287 }
288 sup_enum->destroy(sup_enum);
289
290 cfg_list->destroy_offset(cfg_list, offsetof(traffic_selector_t, destroy));
291
292 return match;
293 }
294
295 /**
296 * Implementation of peer_cfg_t.select_child_cfg
297 */
298 static child_cfg_t* select_child_cfg(private_peer_cfg_t *this,
299 linked_list_t *my_ts,
300 linked_list_t *other_ts,
301 host_t *my_host, host_t *other_host)
302 {
303 child_cfg_t *current, *found = NULL;
304 enumerator_t *enumerator;
305 int best = 0;
306
307 DBG2(DBG_CFG, "looking for a child config for %#R=== %#R", my_ts, other_ts);
308 enumerator = create_child_cfg_enumerator(this);
309 while (enumerator->enumerate(enumerator, &current))
310 {
311 int my_prio, other_prio;
312
313 my_prio = get_ts_match(current, TRUE, my_ts, my_host);
314 other_prio = get_ts_match(current, FALSE, other_ts, other_host);
315
316 if (my_prio && other_prio)
317 {
318 DBG2(DBG_CFG, " candidate \"%s\" with prio %d+%d",
319 current->get_name(current), my_prio, other_prio);
320 if (my_prio + other_prio > best)
321 {
322 best = my_prio + other_prio;
323 DESTROY_IF(found);
324 found = current->get_ref(current);
325 }
326 }
327 }
328 enumerator->destroy(enumerator);
329 if (found)
330 {
331 DBG2(DBG_CFG, "found matching child config \"%s\" with prio %d",
332 found->get_name(found), best);
333 }
334 return found;
335 }
336
337 /**
338 * Implementation of peer_cfg_t.get_cert_policy.
339 */
340 static cert_policy_t get_cert_policy(private_peer_cfg_t *this)
341 {
342 return this->cert_policy;
343 }
344
345 /**
346 * Implementation of peer_cfg_t.get_unique_policy.
347 */
348 static unique_policy_t get_unique_policy(private_peer_cfg_t *this)
349 {
350 return this->unique;
351 }
352
353 /**
354 * Implementation of peer_cfg_t.get_keyingtries.
355 */
356 static u_int32_t get_keyingtries(private_peer_cfg_t *this)
357 {
358 return this->keyingtries;
359 }
360
361 /**
362 * Implementation of peer_cfg_t.get_rekey_time.
363 */
364 static u_int32_t get_rekey_time(private_peer_cfg_t *this)
365 {
366 if (this->rekey_time == 0)
367 {
368 return 0;
369 }
370 if (this->jitter_time == 0)
371 {
372 return this->rekey_time;
373 }
374 return this->rekey_time - (random() % this->jitter_time);
375 }
376
377 /**
378 * Implementation of peer_cfg_t.get_reauth_time.
379 */
380 static u_int32_t get_reauth_time(private_peer_cfg_t *this)
381 {
382 if (this->reauth_time == 0)
383 {
384 return 0;
385 }
386 if (this->jitter_time == 0)
387 {
388 return this->reauth_time;
389 }
390 return this->reauth_time - (random() % this->jitter_time);
391 }
392
393 /**
394 * Implementation of peer_cfg_t.get_over_time.
395 */
396 static u_int32_t get_over_time(private_peer_cfg_t *this)
397 {
398 return this->over_time;
399 }
400
401 /**
402 * Implementation of peer_cfg_t.use_mobike.
403 */
404 static bool use_mobike(private_peer_cfg_t *this)
405 {
406 return this->use_mobike;
407 }
408
409 /**
410 * Implements peer_cfg_t.get_dpd
411 */
412 static u_int32_t get_dpd(private_peer_cfg_t *this)
413 {
414 return this->dpd;
415 }
416
417 /**
418 * Implementation of peer_cfg_t.get_virtual_ip.
419 */
420 static host_t* get_virtual_ip(private_peer_cfg_t *this)
421 {
422 return this->virtual_ip;
423 }
424
425 /**
426 * Implementation of peer_cfg_t.get_pool.
427 */
428 static char* get_pool(private_peer_cfg_t *this)
429 {
430 return this->pool;
431 }
432
433 /**
434 * Implementation of peer_cfg_t.add_auth_cfg
435 */
436 static void add_auth_cfg(private_peer_cfg_t *this,
437 auth_cfg_t *cfg, bool local)
438 {
439 if (local)
440 {
441 this->local_auth->insert_last(this->local_auth, cfg);
442 }
443 else
444 {
445 this->remote_auth->insert_last(this->remote_auth, cfg);
446 }
447 }
448
449 /**
450 * Implementation of peer_cfg_t.create_auth_cfg_enumerator
451 */
452 static enumerator_t* create_auth_cfg_enumerator(private_peer_cfg_t *this,
453 bool local)
454 {
455 if (local)
456 {
457 return this->local_auth->create_enumerator(this->local_auth);
458 }
459 return this->remote_auth->create_enumerator(this->remote_auth);
460 }
461
462 #ifdef ME
463 /**
464 * Implementation of peer_cfg_t.is_mediation.
465 */
466 static bool is_mediation(private_peer_cfg_t *this)
467 {
468 return this->mediation;
469 }
470
471 /**
472 * Implementation of peer_cfg_t.get_mediated_by.
473 */
474 static peer_cfg_t* get_mediated_by(private_peer_cfg_t *this)
475 {
476 return this->mediated_by;
477 }
478
479 /**
480 * Implementation of peer_cfg_t.get_peer_id.
481 */
482 static identification_t* get_peer_id(private_peer_cfg_t *this)
483 {
484 return this->peer_id;
485 }
486 #endif /* ME */
487
488 /**
489 * check auth configs for equality
490 */
491 static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
492 {
493 enumerator_t *e1, *e2;
494 auth_cfg_t *cfg1, *cfg2;
495 bool equal = TRUE;
496
497 if (this->local_auth->get_count(this->local_auth) !=
498 other->local_auth->get_count(other->local_auth))
499 {
500 return FALSE;
501 }
502 if (this->remote_auth->get_count(this->remote_auth) !=
503 other->remote_auth->get_count(other->remote_auth))
504 {
505 return FALSE;
506 }
507
508 e1 = this->local_auth->create_enumerator(this->local_auth);
509 e2 = other->local_auth->create_enumerator(other->local_auth);
510 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
511 {
512 if (!cfg1->equals(cfg1, cfg2))
513 {
514 equal = FALSE;
515 break;
516 }
517 }
518 e1->destroy(e1);
519 e2->destroy(e2);
520
521 if (!equal)
522 {
523 return FALSE;
524 }
525
526 e1 = this->remote_auth->create_enumerator(this->remote_auth);
527 e2 = other->remote_auth->create_enumerator(other->remote_auth);
528 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
529 {
530 if (!cfg1->equals(cfg1, cfg2))
531 {
532 equal = FALSE;
533 break;
534 }
535 }
536 e1->destroy(e1);
537 e2->destroy(e2);
538
539 return equal;
540 }
541
542 /**
543 * Implementation of peer_cfg_t.equals.
544 */
545 static bool equals(private_peer_cfg_t *this, private_peer_cfg_t *other)
546 {
547 if (this == other)
548 {
549 return TRUE;
550 }
551 if (this->public.equals != other->public.equals)
552 {
553 return FALSE;
554 }
555
556 return (
557 this->ike_version == other->ike_version &&
558 this->cert_policy == other->cert_policy &&
559 this->unique == other->unique &&
560 this->keyingtries == other->keyingtries &&
561 this->use_mobike == other->use_mobike &&
562 this->rekey_time == other->rekey_time &&
563 this->reauth_time == other->reauth_time &&
564 this->jitter_time == other->jitter_time &&
565 this->over_time == other->over_time &&
566 this->dpd == other->dpd &&
567 (this->virtual_ip == other->virtual_ip ||
568 (this->virtual_ip && other->virtual_ip &&
569 this->virtual_ip->equals(this->virtual_ip, other->virtual_ip))) &&
570 (this->pool == other->pool ||
571 (this->pool && other->pool && streq(this->pool, other->pool))) &&
572 auth_cfg_equal(this, other)
573 #ifdef ME
574 && this->mediation == other->mediation &&
575 this->mediated_by == other->mediated_by &&
576 (this->peer_id == other->peer_id ||
577 (this->peer_id && other->peer_id &&
578 this->peer_id->equals(this->peer_id, other->peer_id)))
579 #endif /* ME */
580 );
581 }
582
583 /**
584 * Implements peer_cfg_t.get_ref.
585 */
586 static peer_cfg_t* get_ref(private_peer_cfg_t *this)
587 {
588 ref_get(&this->refcount);
589 return &this->public;
590 }
591
592 /**
593 * Implements peer_cfg_t.destroy.
594 */
595 static void destroy(private_peer_cfg_t *this)
596 {
597 if (ref_put(&this->refcount))
598 {
599 this->ike_cfg->destroy(this->ike_cfg);
600 this->child_cfgs->destroy_offset(this->child_cfgs,
601 offsetof(child_cfg_t, destroy));
602 DESTROY_IF(this->virtual_ip);
603 this->local_auth->destroy_offset(this->local_auth,
604 offsetof(auth_cfg_t, destroy));
605 this->remote_auth->destroy_offset(this->remote_auth,
606 offsetof(auth_cfg_t, destroy));
607 #ifdef ME
608 DESTROY_IF(this->mediated_by);
609 DESTROY_IF(this->peer_id);
610 #endif /* ME */
611 this->mutex->destroy(this->mutex);
612 free(this->name);
613 free(this->pool);
614 free(this);
615 }
616 }
617
618 /*
619 * Described in header-file
620 */
621 peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
622 cert_policy_t cert_policy, unique_policy_t unique,
623 u_int32_t keyingtries, u_int32_t rekey_time,
624 u_int32_t reauth_time, u_int32_t jitter_time,
625 u_int32_t over_time, bool mobike, u_int32_t dpd,
626 host_t *virtual_ip, char *pool,
627 bool mediation, peer_cfg_t *mediated_by,
628 identification_t *peer_id)
629 {
630 private_peer_cfg_t *this = malloc_thing(private_peer_cfg_t);
631
632 /* public functions */
633 this->public.get_name = (char* (*) (peer_cfg_t *))get_name;
634 this->public.get_ike_version = (u_int(*) (peer_cfg_t *))get_ike_version;
635 this->public.get_ike_cfg = (ike_cfg_t* (*) (peer_cfg_t *))get_ike_cfg;
636 this->public.add_child_cfg = (void (*) (peer_cfg_t *, child_cfg_t*))add_child_cfg;
637 this->public.remove_child_cfg = (void(*)(peer_cfg_t*, enumerator_t*))remove_child_cfg;
638 this->public.create_child_cfg_enumerator = (enumerator_t* (*) (peer_cfg_t *))create_child_cfg_enumerator;
639 this->public.select_child_cfg = (child_cfg_t* (*) (peer_cfg_t *,linked_list_t*,linked_list_t*,host_t*,host_t*))select_child_cfg;
640 this->public.get_cert_policy = (cert_policy_t (*) (peer_cfg_t *))get_cert_policy;
641 this->public.get_unique_policy = (unique_policy_t (*) (peer_cfg_t *))get_unique_policy;
642 this->public.get_keyingtries = (u_int32_t (*) (peer_cfg_t *))get_keyingtries;
643 this->public.get_rekey_time = (u_int32_t(*)(peer_cfg_t*))get_rekey_time;
644 this->public.get_reauth_time = (u_int32_t(*)(peer_cfg_t*))get_reauth_time;
645 this->public.get_over_time = (u_int32_t(*)(peer_cfg_t*))get_over_time;
646 this->public.use_mobike = (bool (*) (peer_cfg_t *))use_mobike;
647 this->public.get_dpd = (u_int32_t (*) (peer_cfg_t *))get_dpd;
648 this->public.get_virtual_ip = (host_t* (*) (peer_cfg_t *))get_virtual_ip;
649 this->public.get_pool = (char*(*)(peer_cfg_t*))get_pool;
650 this->public.add_auth_cfg = (void(*)(peer_cfg_t*, auth_cfg_t *cfg, bool local))add_auth_cfg;
651 this->public.create_auth_cfg_enumerator = (enumerator_t*(*)(peer_cfg_t*, bool local))create_auth_cfg_enumerator;
652 this->public.equals = (bool(*)(peer_cfg_t*, peer_cfg_t *other))equals;
653 this->public.get_ref = (peer_cfg_t*(*)(peer_cfg_t *))get_ref;
654 this->public.destroy = (void(*)(peer_cfg_t *))destroy;
655 #ifdef ME
656 this->public.is_mediation = (bool (*) (peer_cfg_t *))is_mediation;
657 this->public.get_mediated_by = (peer_cfg_t* (*) (peer_cfg_t *))get_mediated_by;
658 this->public.get_peer_id = (identification_t* (*) (peer_cfg_t *))get_peer_id;
659 #endif /* ME */
660
661 /* apply init values */
662 this->name = strdup(name);
663 this->ike_version = ike_version;
664 this->ike_cfg = ike_cfg;
665 this->child_cfgs = linked_list_create();
666 this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
667 this->cert_policy = cert_policy;
668 this->unique = unique;
669 this->keyingtries = keyingtries;
670 this->rekey_time = rekey_time;
671 this->reauth_time = reauth_time;
672 if (rekey_time && jitter_time > rekey_time)
673 {
674 jitter_time = rekey_time;
675 }
676 if (reauth_time && jitter_time > reauth_time)
677 {
678 jitter_time = reauth_time;
679 }
680 this->jitter_time = jitter_time;
681 this->over_time = over_time;
682 this->use_mobike = mobike;
683 this->dpd = dpd;
684 this->virtual_ip = virtual_ip;
685 this->pool = pool ? strdup(pool) : NULL;
686 this->local_auth = linked_list_create();
687 this->remote_auth = linked_list_create();
688 this->refcount = 1;
689 #ifdef ME
690 this->mediation = mediation;
691 this->mediated_by = mediated_by;
692 this->peer_id = peer_id;
693 #else /* ME */
694 DESTROY_IF(mediated_by);
695 DESTROY_IF(peer_id);
696 #endif /* ME */
697
698 return &this->public;
699 }