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 <utils/linked_list.h>
26 #include <utils/identification.h>
28 ENUM(ike_version_names
, IKE_ANY
, IKEV2
,
34 ENUM(cert_policy_names
, CERT_ALWAYS_SEND
, CERT_NEVER_SEND
,
40 ENUM(unique_policy_names
, UNIQUE_NO
, UNIQUE_KEEP
,
46 typedef struct private_peer_cfg_t private_peer_cfg_t
;
49 * Private data of an peer_cfg_t object
51 struct private_peer_cfg_t
{
59 * Number of references hold by others to this peer_cfg
64 * Name of the peer_cfg, used to query it
69 * IKE version to use for initiation
71 ike_version_t ike_version
;
74 * IKE config associated to this peer config
79 * list of child configs associated to this peer config
81 linked_list_t
*child_cfgs
;
84 * mutex to lock access to list of child_cfgs
89 * should we send a certificate
91 cert_policy_t cert_policy
;
94 * uniqueness of an IKE_SA
96 unique_policy_t unique
;
99 * number of tries after giving up if peer does not respond
101 u_int32_t keyingtries
;
104 * enable support for MOBIKE
109 * Use aggressive mode?
114 * Time before starting rekeying
116 u_int32_t rekey_time
;
119 * Time before starting reauthentication
121 u_int32_t reauth_time
;
124 * Time, which specifies the range of a random value subtracted from above.
126 u_int32_t jitter_time
;
129 * Delay before deleting a rekeying/reauthenticating SA
134 * DPD check intervall
139 * virtual IP to use locally
144 * pool to acquire configuration attributes from
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_version
;
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
, host_t
*host
)
256 linked_list_t
*cfg_list
;
257 enumerator_t
*sup_enum
, *cfg_enum
;
258 traffic_selector_t
*sup_ts
, *cfg_ts
;
259 int match
= 0, round
;
261 /* fetch configured TS list, narrowing dynamic TS */
262 cfg_list
= cfg
->get_traffic_selectors(cfg
, local
, NULL
, host
);
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 */
277 else if (cfg_ts
->is_contained_in(cfg_ts
, sup_ts
) ||
278 sup_ts
->is_contained_in(sup_ts
, cfg_ts
))
283 cfg_enum
->destroy(cfg_enum
);
286 sup_enum
->destroy(sup_enum
);
288 cfg_list
->destroy_offset(cfg_list
, offsetof(traffic_selector_t
, destroy
));
293 METHOD(peer_cfg_t
, select_child_cfg
, child_cfg_t
*,
294 private_peer_cfg_t
*this, linked_list_t
*my_ts
, linked_list_t
*other_ts
,
295 host_t
*my_host
, host_t
*other_host
)
297 child_cfg_t
*current
, *found
= NULL
;
298 enumerator_t
*enumerator
;
301 DBG2(DBG_CFG
, "looking for a child config for %#R=== %#R", my_ts
, other_ts
);
302 enumerator
= create_child_cfg_enumerator(this);
303 while (enumerator
->enumerate(enumerator
, ¤t
))
305 int my_prio
, other_prio
;
307 my_prio
= get_ts_match(current
, TRUE
, my_ts
, my_host
);
308 other_prio
= get_ts_match(current
, FALSE
, other_ts
, other_host
);
310 if (my_prio
&& other_prio
)
312 DBG2(DBG_CFG
, " candidate \"%s\" with prio %d+%d",
313 current
->get_name(current
), my_prio
, other_prio
);
314 if (my_prio
+ other_prio
> best
)
316 best
= my_prio
+ other_prio
;
318 found
= current
->get_ref(current
);
322 enumerator
->destroy(enumerator
);
325 DBG2(DBG_CFG
, "found matching child config \"%s\" with prio %d",
326 found
->get_name(found
), best
);
331 METHOD(peer_cfg_t
, get_cert_policy
, cert_policy_t
,
332 private_peer_cfg_t
*this)
334 return this->cert_policy
;
337 METHOD(peer_cfg_t
, get_unique_policy
, unique_policy_t
,
338 private_peer_cfg_t
*this)
343 METHOD(peer_cfg_t
, get_keyingtries
, u_int32_t
,
344 private_peer_cfg_t
*this)
346 return this->keyingtries
;
349 METHOD(peer_cfg_t
, get_rekey_time
, u_int32_t
,
350 private_peer_cfg_t
*this, bool jitter
)
352 if (this->rekey_time
== 0)
356 if (this->jitter_time
== 0 || !jitter
)
358 return this->rekey_time
;
360 return this->rekey_time
- (random() % this->jitter_time
);
363 METHOD(peer_cfg_t
, get_reauth_time
, u_int32_t
,
364 private_peer_cfg_t
*this, bool jitter
)
366 if (this->reauth_time
== 0)
370 if (this->jitter_time
== 0 || !jitter
)
372 return this->reauth_time
;
374 return this->reauth_time
- (random() % this->jitter_time
);
377 METHOD(peer_cfg_t
, get_over_time
, u_int32_t
,
378 private_peer_cfg_t
*this)
380 return this->over_time
;
383 METHOD(peer_cfg_t
, use_mobike
, bool,
384 private_peer_cfg_t
*this)
386 return this->use_mobike
;
389 METHOD(peer_cfg_t
, use_aggressive
, bool,
390 private_peer_cfg_t
*this)
392 return this->aggressive
;
395 METHOD(peer_cfg_t
, get_dpd
, u_int32_t
,
396 private_peer_cfg_t
*this)
401 METHOD(peer_cfg_t
, get_virtual_ip
, host_t
*,
402 private_peer_cfg_t
*this)
404 return this->virtual_ip
;
407 METHOD(peer_cfg_t
, get_pool
, char*,
408 private_peer_cfg_t
*this)
413 METHOD(peer_cfg_t
, add_auth_cfg
, void,
414 private_peer_cfg_t
*this, auth_cfg_t
*cfg
, bool local
)
418 this->local_auth
->insert_last(this->local_auth
, cfg
);
422 this->remote_auth
->insert_last(this->remote_auth
, cfg
);
426 METHOD(peer_cfg_t
, create_auth_cfg_enumerator
, enumerator_t
*,
427 private_peer_cfg_t
*this, bool local
)
431 return this->local_auth
->create_enumerator(this->local_auth
);
433 return this->remote_auth
->create_enumerator(this->remote_auth
);
437 METHOD(peer_cfg_t
, is_mediation
, bool,
438 private_peer_cfg_t
*this)
440 return this->mediation
;
443 METHOD(peer_cfg_t
, get_mediated_by
, peer_cfg_t
*,
444 private_peer_cfg_t
*this)
446 return this->mediated_by
;
449 METHOD(peer_cfg_t
, get_peer_id
, identification_t
*,
450 private_peer_cfg_t
*this)
452 return this->peer_id
;
457 * check auth configs for equality
459 static bool auth_cfg_equal(private_peer_cfg_t
*this, private_peer_cfg_t
*other
)
461 enumerator_t
*e1
, *e2
;
462 auth_cfg_t
*cfg1
, *cfg2
;
465 if (this->local_auth
->get_count(this->local_auth
) !=
466 other
->local_auth
->get_count(other
->local_auth
))
470 if (this->remote_auth
->get_count(this->remote_auth
) !=
471 other
->remote_auth
->get_count(other
->remote_auth
))
476 e1
= this->local_auth
->create_enumerator(this->local_auth
);
477 e2
= other
->local_auth
->create_enumerator(other
->local_auth
);
478 while (e1
->enumerate(e1
, &cfg1
) && e2
->enumerate(e2
, &cfg2
))
480 if (!cfg1
->equals(cfg1
, cfg2
))
494 e1
= this->remote_auth
->create_enumerator(this->remote_auth
);
495 e2
= other
->remote_auth
->create_enumerator(other
->remote_auth
);
496 while (e1
->enumerate(e1
, &cfg1
) && e2
->enumerate(e2
, &cfg2
))
498 if (!cfg1
->equals(cfg1
, cfg2
))
510 METHOD(peer_cfg_t
, equals
, bool,
511 private_peer_cfg_t
*this, private_peer_cfg_t
*other
)
517 if (this->public.equals
!= other
->public.equals
)
523 this->ike_version
== other
->ike_version
&&
524 this->cert_policy
== other
->cert_policy
&&
525 this->unique
== other
->unique
&&
526 this->keyingtries
== other
->keyingtries
&&
527 this->use_mobike
== other
->use_mobike
&&
528 this->rekey_time
== other
->rekey_time
&&
529 this->reauth_time
== other
->reauth_time
&&
530 this->jitter_time
== other
->jitter_time
&&
531 this->over_time
== other
->over_time
&&
532 this->dpd
== other
->dpd
&&
533 (this->virtual_ip
== other
->virtual_ip
||
534 (this->virtual_ip
&& other
->virtual_ip
&&
535 this->virtual_ip
->equals(this->virtual_ip
, other
->virtual_ip
))) &&
536 (this->pool
== other
->pool
||
537 (this->pool
&& other
->pool
&& streq(this->pool
, other
->pool
))) &&
538 auth_cfg_equal(this, other
)
540 && this->mediation
== other
->mediation
&&
541 this->mediated_by
== other
->mediated_by
&&
542 (this->peer_id
== other
->peer_id
||
543 (this->peer_id
&& other
->peer_id
&&
544 this->peer_id
->equals(this->peer_id
, other
->peer_id
)))
549 METHOD(peer_cfg_t
, get_ref
, peer_cfg_t
*,
550 private_peer_cfg_t
*this)
552 ref_get(&this->refcount
);
553 return &this->public;
556 METHOD(peer_cfg_t
, destroy
, void,
557 private_peer_cfg_t
*this)
559 if (ref_put(&this->refcount
))
561 this->ike_cfg
->destroy(this->ike_cfg
);
562 this->child_cfgs
->destroy_offset(this->child_cfgs
,
563 offsetof(child_cfg_t
, destroy
));
564 DESTROY_IF(this->virtual_ip
);
565 this->local_auth
->destroy_offset(this->local_auth
,
566 offsetof(auth_cfg_t
, destroy
));
567 this->remote_auth
->destroy_offset(this->remote_auth
,
568 offsetof(auth_cfg_t
, destroy
));
570 DESTROY_IF(this->mediated_by
);
571 DESTROY_IF(this->peer_id
);
573 this->mutex
->destroy(this->mutex
);
581 * Described in header-file
583 peer_cfg_t
*peer_cfg_create(char *name
, ike_version_t ike_version
,
584 ike_cfg_t
*ike_cfg
, cert_policy_t cert_policy
,
585 unique_policy_t unique
, u_int32_t keyingtries
,
586 u_int32_t rekey_time
, u_int32_t reauth_time
,
587 u_int32_t jitter_time
, u_int32_t over_time
,
588 bool mobike
, bool aggressive
, u_int32_t dpd
,
589 host_t
*virtual_ip
, char *pool
, bool mediation
,
590 peer_cfg_t
*mediated_by
, identification_t
*peer_id
)
592 private_peer_cfg_t
*this;
594 if (rekey_time
&& jitter_time
> rekey_time
)
596 jitter_time
= rekey_time
;
598 if (reauth_time
&& jitter_time
> reauth_time
)
600 jitter_time
= reauth_time
;
605 .get_name
= _get_name
,
606 .get_ike_version
= _get_ike_version
,
607 .get_ike_cfg
= _get_ike_cfg
,
608 .add_child_cfg
= _add_child_cfg
,
609 .remove_child_cfg
= (void*)_remove_child_cfg
,
610 .create_child_cfg_enumerator
= _create_child_cfg_enumerator
,
611 .select_child_cfg
= _select_child_cfg
,
612 .get_cert_policy
= _get_cert_policy
,
613 .get_unique_policy
= _get_unique_policy
,
614 .get_keyingtries
= _get_keyingtries
,
615 .get_rekey_time
= _get_rekey_time
,
616 .get_reauth_time
= _get_reauth_time
,
617 .get_over_time
= _get_over_time
,
618 .use_mobike
= _use_mobike
,
619 .use_aggressive
= _use_aggressive
,
621 .get_virtual_ip
= _get_virtual_ip
,
622 .get_pool
= _get_pool
,
623 .add_auth_cfg
= _add_auth_cfg
,
624 .create_auth_cfg_enumerator
= _create_auth_cfg_enumerator
,
625 .equals
= (void*)_equals
,
629 .is_mediation
= _is_mediation
,
630 .get_mediated_by
= _get_mediated_by
,
631 .get_peer_id
= _get_peer_id
,
634 .name
= strdup(name
),
635 .ike_version
= ike_version
,
637 .child_cfgs
= linked_list_create(),
638 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
639 .cert_policy
= cert_policy
,
641 .keyingtries
= keyingtries
,
642 .rekey_time
= rekey_time
,
643 .reauth_time
= reauth_time
,
644 .jitter_time
= jitter_time
,
645 .over_time
= over_time
,
646 .use_mobike
= mobike
,
647 .aggressive
= aggressive
,
649 .virtual_ip
= virtual_ip
,
650 .pool
= strdupnull(pool
),
651 .local_auth
= linked_list_create(),
652 .remote_auth
= linked_list_create(),
657 this->mediation
= mediation
;
658 this->mediated_by
= mediated_by
;
659 this->peer_id
= peer_id
;
661 DESTROY_IF(mediated_by
);
665 return &this->public;