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
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>.
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
24 #include <threading/mutex.h>
25 #include <collections/linked_list.h>
26 #include <utils/identification.h>
28 ENUM(cert_policy_names
, CERT_ALWAYS_SEND
, CERT_NEVER_SEND
,
34 ENUM(unique_policy_names
, UNIQUE_NEVER
, UNIQUE_KEEP
,
41 typedef struct private_peer_cfg_t private_peer_cfg_t
;
44 * Private data of an peer_cfg_t object
46 struct private_peer_cfg_t
{
54 * Number of references hold by others to this peer_cfg
59 * Name of the peer_cfg, used to query it
64 * IKE config associated to this peer config
69 * list of child configs associated to this peer config
71 linked_list_t
*child_cfgs
;
74 * mutex to lock access to list of child_cfgs
79 * should we send a certificate
81 cert_policy_t cert_policy
;
84 * uniqueness of an IKE_SA
86 unique_policy_t unique
;
89 * number of tries after giving up if peer does not respond
91 u_int32_t keyingtries
;
94 * enable support for MOBIKE
99 * Use aggressive mode?
104 * Use pull or push in mode config?
109 * Time before starting rekeying
111 u_int32_t rekey_time
;
114 * Time before starting reauthentication
116 u_int32_t reauth_time
;
119 * Time, which specifies the range of a random value subtracted from above.
121 u_int32_t jitter_time
;
124 * Delay before deleting a rekeying/reauthenticating SA
129 * DPD check intervall
134 * DPD timeout intervall (used for IKEv1 only)
136 u_int32_t dpd_timeout
;
139 * List of virtual IPs (host_t*) to request
144 * List of pool names to use for virtual IP lookup
146 linked_list_t
*pools
;
149 * local authentication configs (rulesets)
151 linked_list_t
*local_auth
;
154 * remote authentication configs (constraints)
156 linked_list_t
*remote_auth
;
160 * Is this a mediation connection?
165 * Name of the mediation connection to mediate through
167 peer_cfg_t
*mediated_by
;
170 * ID of our peer at the mediation server (= leftid of the peer's conn with
171 * the mediation server)
173 identification_t
*peer_id
;
177 METHOD(peer_cfg_t
, get_name
, char*,
178 private_peer_cfg_t
*this)
183 METHOD(peer_cfg_t
, get_ike_version
, ike_version_t
,
184 private_peer_cfg_t
*this)
186 return this->ike_cfg
->get_version(this->ike_cfg
);
189 METHOD(peer_cfg_t
, get_ike_cfg
, ike_cfg_t
*,
190 private_peer_cfg_t
*this)
192 return this->ike_cfg
;
195 METHOD(peer_cfg_t
, add_child_cfg
, void,
196 private_peer_cfg_t
*this, child_cfg_t
*child_cfg
)
198 this->mutex
->lock(this->mutex
);
199 this->child_cfgs
->insert_last(this->child_cfgs
, child_cfg
);
200 this->mutex
->unlock(this->mutex
);
204 * child_cfg enumerator
208 enumerator_t
*wrapped
;
210 } child_cfg_enumerator_t
;
212 METHOD(peer_cfg_t
, remove_child_cfg
, void,
213 private_peer_cfg_t
*this, child_cfg_enumerator_t
*enumerator
)
215 this->child_cfgs
->remove_at(this->child_cfgs
, enumerator
->wrapped
);
218 METHOD(enumerator_t
, child_cfg_enumerator_destroy
, void,
219 child_cfg_enumerator_t
*this)
221 this->mutex
->unlock(this->mutex
);
222 this->wrapped
->destroy(this->wrapped
);
226 METHOD(enumerator_t
, child_cfg_enumerate
, bool,
227 child_cfg_enumerator_t
*this, child_cfg_t
**chd
)
229 return this->wrapped
->enumerate(this->wrapped
, chd
);
232 METHOD(peer_cfg_t
, create_child_cfg_enumerator
, enumerator_t
*,
233 private_peer_cfg_t
*this)
235 child_cfg_enumerator_t
*enumerator
;
239 .enumerate
= (void*)_child_cfg_enumerate
,
240 .destroy
= (void*)_child_cfg_enumerator_destroy
,
242 .mutex
= this->mutex
,
243 .wrapped
= this->child_cfgs
->create_enumerator(this->child_cfgs
),
246 this->mutex
->lock(this->mutex
);
247 return &enumerator
->public;
251 * Check how good a list of TS matches a given child config
253 static int get_ts_match(child_cfg_t
*cfg
, bool local
,
254 linked_list_t
*sup_list
, linked_list_t
*hosts
)
256 linked_list_t
*cfg_list
;
257 enumerator_t
*sup_enum
, *cfg_enum
;
258 traffic_selector_t
*sup_ts
, *cfg_ts
, *subset
;
259 int match
= 0, round
;
261 /* fetch configured TS list, narrowing dynamic TS */
262 cfg_list
= cfg
->get_traffic_selectors(cfg
, local
, NULL
, hosts
);
264 /* use a round counter to rate leading TS with higher priority */
265 round
= sup_list
->get_count(sup_list
);
267 sup_enum
= sup_list
->create_enumerator(sup_list
);
268 while (sup_enum
->enumerate(sup_enum
, &sup_ts
))
270 cfg_enum
= cfg_list
->create_enumerator(cfg_list
);
271 while (cfg_enum
->enumerate(cfg_enum
, &cfg_ts
))
273 if (cfg_ts
->equals(cfg_ts
, sup_ts
))
274 { /* equality is honored better than matches */
279 subset
= cfg_ts
->get_subset(cfg_ts
, sup_ts
);
282 subset
->destroy(subset
);
287 cfg_enum
->destroy(cfg_enum
);
290 sup_enum
->destroy(sup_enum
);
292 cfg_list
->destroy_offset(cfg_list
, offsetof(traffic_selector_t
, destroy
));
297 METHOD(peer_cfg_t
, select_child_cfg
, child_cfg_t
*,
298 private_peer_cfg_t
*this, linked_list_t
*my_ts
, linked_list_t
*other_ts
,
299 linked_list_t
*my_hosts
, linked_list_t
*other_hosts
)
301 child_cfg_t
*current
, *found
= NULL
;
302 enumerator_t
*enumerator
;
305 DBG2(DBG_CFG
, "looking for a child config for %#R === %#R", my_ts
, other_ts
);
306 enumerator
= create_child_cfg_enumerator(this);
307 while (enumerator
->enumerate(enumerator
, ¤t
))
309 int my_prio
, other_prio
;
311 my_prio
= get_ts_match(current
, TRUE
, my_ts
, my_hosts
);
312 other_prio
= get_ts_match(current
, FALSE
, other_ts
, other_hosts
);
314 if (my_prio
&& other_prio
)
316 DBG2(DBG_CFG
, " candidate \"%s\" with prio %d+%d",
317 current
->get_name(current
), my_prio
, other_prio
);
318 if (my_prio
+ other_prio
> best
)
320 best
= my_prio
+ other_prio
;
322 found
= current
->get_ref(current
);
326 enumerator
->destroy(enumerator
);
329 DBG2(DBG_CFG
, "found matching child config \"%s\" with prio %d",
330 found
->get_name(found
), best
);
335 METHOD(peer_cfg_t
, get_cert_policy
, cert_policy_t
,
336 private_peer_cfg_t
*this)
338 return this->cert_policy
;
341 METHOD(peer_cfg_t
, get_unique_policy
, unique_policy_t
,
342 private_peer_cfg_t
*this)
347 METHOD(peer_cfg_t
, get_keyingtries
, u_int32_t
,
348 private_peer_cfg_t
*this)
350 return this->keyingtries
;
353 METHOD(peer_cfg_t
, get_rekey_time
, u_int32_t
,
354 private_peer_cfg_t
*this, bool jitter
)
356 if (this->rekey_time
== 0)
360 if (this->jitter_time
== 0 || !jitter
)
362 return this->rekey_time
;
364 return this->rekey_time
- (random() % this->jitter_time
);
367 METHOD(peer_cfg_t
, get_reauth_time
, u_int32_t
,
368 private_peer_cfg_t
*this, bool jitter
)
370 if (this->reauth_time
== 0)
374 if (this->jitter_time
== 0 || !jitter
)
376 return this->reauth_time
;
378 return this->reauth_time
- (random() % this->jitter_time
);
381 METHOD(peer_cfg_t
, get_over_time
, u_int32_t
,
382 private_peer_cfg_t
*this)
384 return this->over_time
;
387 METHOD(peer_cfg_t
, use_mobike
, bool,
388 private_peer_cfg_t
*this)
390 return this->use_mobike
;
393 METHOD(peer_cfg_t
, use_aggressive
, bool,
394 private_peer_cfg_t
*this)
396 return this->aggressive
;
399 METHOD(peer_cfg_t
, use_pull_mode
, bool,
400 private_peer_cfg_t
*this)
402 return this->pull_mode
;
405 METHOD(peer_cfg_t
, get_dpd
, u_int32_t
,
406 private_peer_cfg_t
*this)
411 METHOD(peer_cfg_t
, get_dpd_timeout
, u_int32_t
,
412 private_peer_cfg_t
*this)
414 return this->dpd_timeout
;
417 METHOD(peer_cfg_t
, add_virtual_ip
, void,
418 private_peer_cfg_t
*this, host_t
*vip
)
420 this->vips
->insert_last(this->vips
, vip
);
423 METHOD(peer_cfg_t
, create_virtual_ip_enumerator
, enumerator_t
*,
424 private_peer_cfg_t
*this)
426 return this->vips
->create_enumerator(this->vips
);
429 METHOD(peer_cfg_t
, add_pool
, void,
430 private_peer_cfg_t
*this, char *name
)
432 this->pools
->insert_last(this->pools
, strdup(name
));
435 METHOD(peer_cfg_t
, create_pool_enumerator
, enumerator_t
*,
436 private_peer_cfg_t
*this)
438 return this->pools
->create_enumerator(this->pools
);
441 METHOD(peer_cfg_t
, add_auth_cfg
, void,
442 private_peer_cfg_t
*this, auth_cfg_t
*cfg
, bool local
)
446 this->local_auth
->insert_last(this->local_auth
, cfg
);
450 this->remote_auth
->insert_last(this->remote_auth
, cfg
);
454 METHOD(peer_cfg_t
, create_auth_cfg_enumerator
, enumerator_t
*,
455 private_peer_cfg_t
*this, bool local
)
459 return this->local_auth
->create_enumerator(this->local_auth
);
461 return this->remote_auth
->create_enumerator(this->remote_auth
);
465 METHOD(peer_cfg_t
, is_mediation
, bool,
466 private_peer_cfg_t
*this)
468 return this->mediation
;
471 METHOD(peer_cfg_t
, get_mediated_by
, peer_cfg_t
*,
472 private_peer_cfg_t
*this)
474 return this->mediated_by
;
477 METHOD(peer_cfg_t
, get_peer_id
, identification_t
*,
478 private_peer_cfg_t
*this)
480 return this->peer_id
;
485 * check auth configs for equality
487 static bool auth_cfg_equal(private_peer_cfg_t
*this, private_peer_cfg_t
*other
)
489 enumerator_t
*e1
, *e2
;
490 auth_cfg_t
*cfg1
, *cfg2
;
493 if (this->local_auth
->get_count(this->local_auth
) !=
494 other
->local_auth
->get_count(other
->local_auth
))
498 if (this->remote_auth
->get_count(this->remote_auth
) !=
499 other
->remote_auth
->get_count(other
->remote_auth
))
504 e1
= this->local_auth
->create_enumerator(this->local_auth
);
505 e2
= other
->local_auth
->create_enumerator(other
->local_auth
);
506 while (e1
->enumerate(e1
, &cfg1
) && e2
->enumerate(e2
, &cfg2
))
508 if (!cfg1
->equals(cfg1
, cfg2
))
522 e1
= this->remote_auth
->create_enumerator(this->remote_auth
);
523 e2
= other
->remote_auth
->create_enumerator(other
->remote_auth
);
524 while (e1
->enumerate(e1
, &cfg1
) && e2
->enumerate(e2
, &cfg2
))
526 if (!cfg1
->equals(cfg1
, cfg2
))
538 METHOD(peer_cfg_t
, equals
, bool,
539 private_peer_cfg_t
*this, private_peer_cfg_t
*other
)
541 enumerator_t
*e1
, *e2
;
549 if (this->public.equals
!= other
->public.equals
)
554 if (this->vips
->get_count(this->vips
) != other
->vips
->get_count(other
->vips
))
558 e1
= create_virtual_ip_enumerator(this);
559 e2
= create_virtual_ip_enumerator(other
);
560 if (e1
->enumerate(e1
, &vip1
) && e2
->enumerate(e2
, &vip2
))
562 if (!vip1
->ip_equals(vip1
, vip2
))
572 if (this->pools
->get_count(this->pools
) !=
573 other
->pools
->get_count(other
->pools
))
577 e1
= create_pool_enumerator(this);
578 e2
= create_pool_enumerator(other
);
579 if (e1
->enumerate(e1
, &pool1
) && e2
->enumerate(e2
, &pool2
))
581 if (!streq(pool1
, pool2
))
592 get_ike_version(this) == get_ike_version(other
) &&
593 this->cert_policy
== other
->cert_policy
&&
594 this->unique
== other
->unique
&&
595 this->keyingtries
== other
->keyingtries
&&
596 this->use_mobike
== other
->use_mobike
&&
597 this->rekey_time
== other
->rekey_time
&&
598 this->reauth_time
== other
->reauth_time
&&
599 this->jitter_time
== other
->jitter_time
&&
600 this->over_time
== other
->over_time
&&
601 this->dpd
== other
->dpd
&&
602 this->aggressive
== other
->aggressive
&&
603 this->pull_mode
== other
->pull_mode
&&
604 auth_cfg_equal(this, other
)
606 && this->mediation
== other
->mediation
&&
607 this->mediated_by
== other
->mediated_by
&&
608 (this->peer_id
== other
->peer_id
||
609 (this->peer_id
&& other
->peer_id
&&
610 this->peer_id
->equals(this->peer_id
, other
->peer_id
)))
615 METHOD(peer_cfg_t
, get_ref
, peer_cfg_t
*,
616 private_peer_cfg_t
*this)
618 ref_get(&this->refcount
);
619 return &this->public;
622 METHOD(peer_cfg_t
, destroy
, void,
623 private_peer_cfg_t
*this)
625 if (ref_put(&this->refcount
))
627 this->ike_cfg
->destroy(this->ike_cfg
);
628 this->child_cfgs
->destroy_offset(this->child_cfgs
,
629 offsetof(child_cfg_t
, destroy
));
630 this->local_auth
->destroy_offset(this->local_auth
,
631 offsetof(auth_cfg_t
, destroy
));
632 this->remote_auth
->destroy_offset(this->remote_auth
,
633 offsetof(auth_cfg_t
, destroy
));
634 this->vips
->destroy_offset(this->vips
, offsetof(host_t
, destroy
));
635 this->pools
->destroy_function(this->pools
, free
);
637 DESTROY_IF(this->mediated_by
);
638 DESTROY_IF(this->peer_id
);
640 this->mutex
->destroy(this->mutex
);
647 * Described in header-file
649 peer_cfg_t
*peer_cfg_create(char *name
,
650 ike_cfg_t
*ike_cfg
, cert_policy_t cert_policy
,
651 unique_policy_t unique
, u_int32_t keyingtries
,
652 u_int32_t rekey_time
, u_int32_t reauth_time
,
653 u_int32_t jitter_time
, u_int32_t over_time
,
654 bool mobike
, bool aggressive
, bool pull_mode
,
655 u_int32_t dpd
, u_int32_t dpd_timeout
,
656 bool mediation
, peer_cfg_t
*mediated_by
,
657 identification_t
*peer_id
)
659 private_peer_cfg_t
*this;
661 if (rekey_time
&& jitter_time
> rekey_time
)
663 jitter_time
= rekey_time
;
665 if (reauth_time
&& jitter_time
> reauth_time
)
667 jitter_time
= reauth_time
;
672 .get_name
= _get_name
,
673 .get_ike_version
= _get_ike_version
,
674 .get_ike_cfg
= _get_ike_cfg
,
675 .add_child_cfg
= _add_child_cfg
,
676 .remove_child_cfg
= (void*)_remove_child_cfg
,
677 .create_child_cfg_enumerator
= _create_child_cfg_enumerator
,
678 .select_child_cfg
= _select_child_cfg
,
679 .get_cert_policy
= _get_cert_policy
,
680 .get_unique_policy
= _get_unique_policy
,
681 .get_keyingtries
= _get_keyingtries
,
682 .get_rekey_time
= _get_rekey_time
,
683 .get_reauth_time
= _get_reauth_time
,
684 .get_over_time
= _get_over_time
,
685 .use_mobike
= _use_mobike
,
686 .use_aggressive
= _use_aggressive
,
687 .use_pull_mode
= _use_pull_mode
,
689 .get_dpd_timeout
= _get_dpd_timeout
,
690 .add_virtual_ip
= _add_virtual_ip
,
691 .create_virtual_ip_enumerator
= _create_virtual_ip_enumerator
,
692 .add_pool
= _add_pool
,
693 .create_pool_enumerator
= _create_pool_enumerator
,
694 .add_auth_cfg
= _add_auth_cfg
,
695 .create_auth_cfg_enumerator
= _create_auth_cfg_enumerator
,
696 .equals
= (void*)_equals
,
700 .is_mediation
= _is_mediation
,
701 .get_mediated_by
= _get_mediated_by
,
702 .get_peer_id
= _get_peer_id
,
705 .name
= strdup(name
),
707 .child_cfgs
= linked_list_create(),
708 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
709 .cert_policy
= cert_policy
,
711 .keyingtries
= keyingtries
,
712 .rekey_time
= rekey_time
,
713 .reauth_time
= reauth_time
,
714 .jitter_time
= jitter_time
,
715 .over_time
= over_time
,
716 .use_mobike
= mobike
,
717 .aggressive
= aggressive
,
718 .pull_mode
= pull_mode
,
720 .dpd_timeout
= dpd_timeout
,
721 .vips
= linked_list_create(),
722 .pools
= linked_list_create(),
723 .local_auth
= linked_list_create(),
724 .remote_auth
= linked_list_create(),
729 this->mediation
= mediation
;
730 this->mediated_by
= mediated_by
;
731 this->peer_id
= peer_id
;
733 DESTROY_IF(mediated_by
);
737 return &this->public;