2 * Copyright (C) 2007-2018 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * HSR 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/rwlock.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 * lock to access 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
94 * enable support for MOBIKE
99 * Use aggressive mode?
104 * Use pull or push in mode config?
109 * Time before starting rekeying
114 * Time before starting reauthentication
116 uint32_t reauth_time
;
119 * Time, which specifies the range of a random value subtracted from above.
121 uint32_t jitter_time
;
124 * Delay before deleting a rekeying/reauthenticating SA
134 * DPD timeout interval (used for IKEv1 only)
136 uint32_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
;
161 identification_t
*ppk_id
;
164 * Whether a PPK is required
170 * Is this a mediation connection?
175 * Name of the mediation connection to mediate through
180 * ID of our peer at the mediation server (= leftid of the peer's conn with
181 * the mediation server)
183 identification_t
*peer_id
;
187 METHOD(peer_cfg_t
, get_name
, char*,
188 private_peer_cfg_t
*this)
193 METHOD(peer_cfg_t
, get_ike_version
, ike_version_t
,
194 private_peer_cfg_t
*this)
196 return this->ike_cfg
->get_version(this->ike_cfg
);
199 METHOD(peer_cfg_t
, get_ike_cfg
, ike_cfg_t
*,
200 private_peer_cfg_t
*this)
202 return this->ike_cfg
;
205 METHOD(peer_cfg_t
, add_child_cfg
, void,
206 private_peer_cfg_t
*this, child_cfg_t
*child_cfg
)
208 this->lock
->write_lock(this->lock
);
209 this->child_cfgs
->insert_last(this->child_cfgs
, child_cfg
);
210 this->lock
->unlock(this->lock
);
215 linked_list_t
*removed
;
216 linked_list_t
*added
;
217 enumerator_t
*wrapped
;
219 } child_cfgs_replace_enumerator_t
;
221 METHOD(enumerator_t
, child_cfgs_replace_enumerate
, bool,
222 child_cfgs_replace_enumerator_t
*this, va_list args
)
224 child_cfg_t
*child_cfg
, **chd
;
227 VA_ARGS_VGET(args
, chd
, added
);
231 this->wrapped
= this->removed
->create_enumerator(this->removed
);
235 if (this->wrapped
->enumerate(this->wrapped
, &child_cfg
))
251 this->wrapped
->destroy(this->wrapped
);
252 this->wrapped
= this->added
->create_enumerator(this->added
);
258 METHOD(enumerator_t
, child_cfgs_replace_enumerator_destroy
, void,
259 child_cfgs_replace_enumerator_t
*this)
261 DESTROY_IF(this->wrapped
);
262 this->removed
->destroy_offset(this->removed
, offsetof(child_cfg_t
, destroy
));
263 this->added
->destroy_offset(this->added
, offsetof(child_cfg_t
, destroy
));
267 METHOD(peer_cfg_t
, replace_child_cfgs
, enumerator_t
*,
268 private_peer_cfg_t
*this, peer_cfg_t
*other_pub
)
270 private_peer_cfg_t
*other
= (private_peer_cfg_t
*)other_pub
;
271 linked_list_t
*new_cfgs
, *removed
, *added
;
272 enumerator_t
*mine
, *others
;
273 child_cfg_t
*my_cfg
, *other_cfg
;
274 child_cfgs_replace_enumerator_t
*enumerator
;
277 added
= linked_list_create();
279 other
->lock
->read_lock(other
->lock
);
280 new_cfgs
= linked_list_create_from_enumerator(
281 other
->child_cfgs
->create_enumerator(other
->child_cfgs
));
282 new_cfgs
->invoke_offset(new_cfgs
, offsetof(child_cfg_t
, get_ref
));
283 other
->lock
->unlock(other
->lock
);
285 this->lock
->write_lock(this->lock
);
286 removed
= this->child_cfgs
;
287 this->child_cfgs
= new_cfgs
;
288 others
= new_cfgs
->create_enumerator(new_cfgs
);
289 mine
= removed
->create_enumerator(removed
);
290 while (others
->enumerate(others
, &other_cfg
))
293 while (mine
->enumerate(mine
, &my_cfg
))
295 if (my_cfg
->equals(my_cfg
, other_cfg
))
297 removed
->remove_at(removed
, mine
);
298 my_cfg
->destroy(my_cfg
);
303 removed
->reset_enumerator(removed
, mine
);
306 added
->insert_last(added
, other_cfg
->get_ref(other_cfg
));
309 others
->destroy(others
);
311 this->lock
->unlock(this->lock
);
315 .enumerate
= enumerator_enumerate_default
,
316 .venumerate
= _child_cfgs_replace_enumerate
,
317 .destroy
= _child_cfgs_replace_enumerator_destroy
,
322 return &enumerator
->public;
326 * child_cfg enumerator
330 enumerator_t
*wrapped
;
332 } child_cfg_enumerator_t
;
334 METHOD(peer_cfg_t
, remove_child_cfg
, void,
335 private_peer_cfg_t
*this, child_cfg_enumerator_t
*enumerator
)
337 this->child_cfgs
->remove_at(this->child_cfgs
, enumerator
->wrapped
);
340 METHOD(enumerator_t
, child_cfg_enumerator_destroy
, void,
341 child_cfg_enumerator_t
*this)
343 this->lock
->unlock(this->lock
);
344 this->wrapped
->destroy(this->wrapped
);
348 METHOD(enumerator_t
, child_cfg_enumerate
, bool,
349 child_cfg_enumerator_t
*this, va_list args
)
353 VA_ARGS_VGET(args
, chd
);
354 return this->wrapped
->enumerate(this->wrapped
, chd
);
357 METHOD(peer_cfg_t
, create_child_cfg_enumerator
, enumerator_t
*,
358 private_peer_cfg_t
*this)
360 child_cfg_enumerator_t
*enumerator
;
364 .enumerate
= enumerator_enumerate_default
,
365 .venumerate
= _child_cfg_enumerate
,
366 .destroy
= _child_cfg_enumerator_destroy
,
369 .wrapped
= this->child_cfgs
->create_enumerator(this->child_cfgs
),
372 this->lock
->read_lock(this->lock
);
373 return &enumerator
->public;
377 * Check how good a list of TS matches a given child config
379 static int get_ts_match(child_cfg_t
*cfg
, bool local
,
380 linked_list_t
*sup_list
, linked_list_t
*hosts
)
382 linked_list_t
*cfg_list
;
383 enumerator_t
*sup_enum
, *cfg_enum
;
384 traffic_selector_t
*sup_ts
, *cfg_ts
, *subset
;
385 int match
= 0, round
;
387 /* fetch configured TS list, narrowing dynamic TS */
388 cfg_list
= cfg
->get_traffic_selectors(cfg
, local
, NULL
, hosts
, TRUE
);
390 /* use a round counter to rate leading TS with higher priority */
391 round
= sup_list
->get_count(sup_list
);
393 sup_enum
= sup_list
->create_enumerator(sup_list
);
394 while (sup_enum
->enumerate(sup_enum
, &sup_ts
))
396 cfg_enum
= cfg_list
->create_enumerator(cfg_list
);
397 while (cfg_enum
->enumerate(cfg_enum
, &cfg_ts
))
399 if (cfg_ts
->equals(cfg_ts
, sup_ts
))
400 { /* equality is honored better than matches */
405 subset
= cfg_ts
->get_subset(cfg_ts
, sup_ts
);
408 subset
->destroy(subset
);
413 cfg_enum
->destroy(cfg_enum
);
416 sup_enum
->destroy(sup_enum
);
418 cfg_list
->destroy_offset(cfg_list
, offsetof(traffic_selector_t
, destroy
));
423 METHOD(peer_cfg_t
, select_child_cfg
, child_cfg_t
*,
424 private_peer_cfg_t
*this, linked_list_t
*my_ts
, linked_list_t
*other_ts
,
425 linked_list_t
*my_hosts
, linked_list_t
*other_hosts
)
427 child_cfg_t
*current
, *found
= NULL
;
428 enumerator_t
*enumerator
;
431 DBG2(DBG_CFG
, "looking for a child config for %#R === %#R", my_ts
, other_ts
);
432 enumerator
= create_child_cfg_enumerator(this);
433 while (enumerator
->enumerate(enumerator
, ¤t
))
435 int my_prio
, other_prio
;
437 my_prio
= get_ts_match(current
, TRUE
, my_ts
, my_hosts
);
438 other_prio
= get_ts_match(current
, FALSE
, other_ts
, other_hosts
);
440 if (my_prio
&& other_prio
)
442 DBG2(DBG_CFG
, " candidate \"%s\" with prio %d+%d",
443 current
->get_name(current
), my_prio
, other_prio
);
444 if (my_prio
+ other_prio
> best
)
446 best
= my_prio
+ other_prio
;
448 found
= current
->get_ref(current
);
452 enumerator
->destroy(enumerator
);
455 DBG2(DBG_CFG
, "found matching child config \"%s\" with prio %d",
456 found
->get_name(found
), best
);
461 METHOD(peer_cfg_t
, get_cert_policy
, cert_policy_t
,
462 private_peer_cfg_t
*this)
464 return this->cert_policy
;
467 METHOD(peer_cfg_t
, get_unique_policy
, unique_policy_t
,
468 private_peer_cfg_t
*this)
473 METHOD(peer_cfg_t
, get_keyingtries
, uint32_t,
474 private_peer_cfg_t
*this)
476 return this->keyingtries
;
479 METHOD(peer_cfg_t
, get_rekey_time
, uint32_t,
480 private_peer_cfg_t
*this, bool jitter
)
482 if (this->rekey_time
== 0)
486 if (this->jitter_time
== 0 || !jitter
)
488 return this->rekey_time
;
490 return this->rekey_time
- (random() % this->jitter_time
);
493 METHOD(peer_cfg_t
, get_reauth_time
, uint32_t,
494 private_peer_cfg_t
*this, bool jitter
)
496 if (this->reauth_time
== 0)
500 if (this->jitter_time
== 0 || !jitter
)
502 return this->reauth_time
;
504 return this->reauth_time
- (random() % this->jitter_time
);
507 METHOD(peer_cfg_t
, get_over_time
, uint32_t,
508 private_peer_cfg_t
*this)
510 return this->over_time
;
513 METHOD(peer_cfg_t
, use_mobike
, bool,
514 private_peer_cfg_t
*this)
516 return this->use_mobike
;
519 METHOD(peer_cfg_t
, use_aggressive
, bool,
520 private_peer_cfg_t
*this)
522 return this->aggressive
;
525 METHOD(peer_cfg_t
, use_pull_mode
, bool,
526 private_peer_cfg_t
*this)
528 return this->pull_mode
;
531 METHOD(peer_cfg_t
, get_dpd
, uint32_t,
532 private_peer_cfg_t
*this)
537 METHOD(peer_cfg_t
, get_dpd_timeout
, uint32_t,
538 private_peer_cfg_t
*this)
540 return this->dpd_timeout
;
543 METHOD(peer_cfg_t
, add_virtual_ip
, void,
544 private_peer_cfg_t
*this, host_t
*vip
)
546 this->vips
->insert_last(this->vips
, vip
);
549 METHOD(peer_cfg_t
, create_virtual_ip_enumerator
, enumerator_t
*,
550 private_peer_cfg_t
*this)
552 return this->vips
->create_enumerator(this->vips
);
555 METHOD(peer_cfg_t
, add_pool
, void,
556 private_peer_cfg_t
*this, char *name
)
558 this->pools
->insert_last(this->pools
, strdup(name
));
561 METHOD(peer_cfg_t
, create_pool_enumerator
, enumerator_t
*,
562 private_peer_cfg_t
*this)
564 return this->pools
->create_enumerator(this->pools
);
567 METHOD(peer_cfg_t
, add_auth_cfg
, void,
568 private_peer_cfg_t
*this, auth_cfg_t
*cfg
, bool local
)
572 this->local_auth
->insert_last(this->local_auth
, cfg
);
576 this->remote_auth
->insert_last(this->remote_auth
, cfg
);
580 METHOD(peer_cfg_t
, create_auth_cfg_enumerator
, enumerator_t
*,
581 private_peer_cfg_t
*this, bool local
)
585 return this->local_auth
->create_enumerator(this->local_auth
);
587 return this->remote_auth
->create_enumerator(this->remote_auth
);
590 METHOD(peer_cfg_t
, get_ppk_id
, identification_t
*,
591 private_peer_cfg_t
*this)
596 METHOD(peer_cfg_t
, ppk_required
, bool,
597 private_peer_cfg_t
*this)
599 return this->ppk_required
;
603 METHOD(peer_cfg_t
, is_mediation
, bool,
604 private_peer_cfg_t
*this)
606 return this->mediation
;
609 METHOD(peer_cfg_t
, get_mediated_by
, char*,
610 private_peer_cfg_t
*this)
612 return this->mediated_by
;
615 METHOD(peer_cfg_t
, get_peer_id
, identification_t
*,
616 private_peer_cfg_t
*this)
618 return this->peer_id
;
623 * check auth configs for equality
625 static bool auth_cfg_equal(private_peer_cfg_t
*this, private_peer_cfg_t
*other
)
627 enumerator_t
*e1
, *e2
;
628 auth_cfg_t
*cfg1
, *cfg2
;
631 if (this->local_auth
->get_count(this->local_auth
) !=
632 other
->local_auth
->get_count(other
->local_auth
))
636 if (this->remote_auth
->get_count(this->remote_auth
) !=
637 other
->remote_auth
->get_count(other
->remote_auth
))
642 e1
= this->local_auth
->create_enumerator(this->local_auth
);
643 e2
= other
->local_auth
->create_enumerator(other
->local_auth
);
644 while (e1
->enumerate(e1
, &cfg1
) && e2
->enumerate(e2
, &cfg2
))
646 if (!cfg1
->equals(cfg1
, cfg2
))
660 e1
= this->remote_auth
->create_enumerator(this->remote_auth
);
661 e2
= other
->remote_auth
->create_enumerator(other
->remote_auth
);
662 while (e1
->enumerate(e1
, &cfg1
) && e2
->enumerate(e2
, &cfg2
))
664 if (!cfg1
->equals(cfg1
, cfg2
))
677 * Check if two identities are equal, or both are not set
679 static bool id_equal(identification_t
*this, identification_t
*other
)
681 return this == other
|| (this && other
&& this->equals(this, other
));
684 METHOD(peer_cfg_t
, equals
, bool,
685 private_peer_cfg_t
*this, private_peer_cfg_t
*other
)
691 if (this->public.equals
!= other
->public.equals
)
695 if (!this->vips
->equals_offset(this->vips
, other
->vips
,
696 offsetof(host_t
, ip_equals
)))
700 if (!this->pools
->equals_function(this->pools
, other
->pools
, (void*)streq
))
705 get_ike_version(this) == get_ike_version(other
) &&
706 this->cert_policy
== other
->cert_policy
&&
707 this->unique
== other
->unique
&&
708 this->keyingtries
== other
->keyingtries
&&
709 this->use_mobike
== other
->use_mobike
&&
710 this->rekey_time
== other
->rekey_time
&&
711 this->reauth_time
== other
->reauth_time
&&
712 this->jitter_time
== other
->jitter_time
&&
713 this->over_time
== other
->over_time
&&
714 this->dpd
== other
->dpd
&&
715 this->aggressive
== other
->aggressive
&&
716 this->pull_mode
== other
->pull_mode
&&
717 auth_cfg_equal(this, other
) &&
718 this->ppk_required
== other
->ppk_required
&&
719 id_equal(this->ppk_id
, other
->ppk_id
)
721 && this->mediation
== other
->mediation
&&
722 streq(this->mediated_by
, other
->mediated_by
) &&
723 id_equal(this->peer_id
, other
->peer_id
)
728 METHOD(peer_cfg_t
, get_ref
, peer_cfg_t
*,
729 private_peer_cfg_t
*this)
731 ref_get(&this->refcount
);
732 return &this->public;
735 METHOD(peer_cfg_t
, destroy
, void,
736 private_peer_cfg_t
*this)
738 if (ref_put(&this->refcount
))
740 this->ike_cfg
->destroy(this->ike_cfg
);
741 this->child_cfgs
->destroy_offset(this->child_cfgs
,
742 offsetof(child_cfg_t
, destroy
));
743 this->local_auth
->destroy_offset(this->local_auth
,
744 offsetof(auth_cfg_t
, destroy
));
745 this->remote_auth
->destroy_offset(this->remote_auth
,
746 offsetof(auth_cfg_t
, destroy
));
747 this->vips
->destroy_offset(this->vips
, offsetof(host_t
, destroy
));
748 this->pools
->destroy_function(this->pools
, free
);
750 DESTROY_IF(this->peer_id
);
751 free(this->mediated_by
);
753 DESTROY_IF(this->ppk_id
);
754 this->lock
->destroy(this->lock
);
761 * Described in header-file
763 peer_cfg_t
*peer_cfg_create(char *name
, ike_cfg_t
*ike_cfg
,
764 peer_cfg_create_t
*data
)
766 private_peer_cfg_t
*this;
768 if (data
->rekey_time
&& data
->jitter_time
> data
->rekey_time
)
770 data
->jitter_time
= data
->rekey_time
;
772 if (data
->reauth_time
&& data
->jitter_time
> data
->reauth_time
)
774 data
->jitter_time
= data
->reauth_time
;
776 if (data
->dpd
&& data
->dpd_timeout
&& data
->dpd
> data
->dpd_timeout
)
778 data
->dpd_timeout
= data
->dpd
;
783 .get_name
= _get_name
,
784 .get_ike_version
= _get_ike_version
,
785 .get_ike_cfg
= _get_ike_cfg
,
786 .add_child_cfg
= _add_child_cfg
,
787 .remove_child_cfg
= (void*)_remove_child_cfg
,
788 .replace_child_cfgs
= _replace_child_cfgs
,
789 .create_child_cfg_enumerator
= _create_child_cfg_enumerator
,
790 .select_child_cfg
= _select_child_cfg
,
791 .get_cert_policy
= _get_cert_policy
,
792 .get_unique_policy
= _get_unique_policy
,
793 .get_keyingtries
= _get_keyingtries
,
794 .get_rekey_time
= _get_rekey_time
,
795 .get_reauth_time
= _get_reauth_time
,
796 .get_over_time
= _get_over_time
,
797 .use_mobike
= _use_mobike
,
798 .use_aggressive
= _use_aggressive
,
799 .use_pull_mode
= _use_pull_mode
,
801 .get_dpd_timeout
= _get_dpd_timeout
,
802 .add_virtual_ip
= _add_virtual_ip
,
803 .create_virtual_ip_enumerator
= _create_virtual_ip_enumerator
,
804 .add_pool
= _add_pool
,
805 .create_pool_enumerator
= _create_pool_enumerator
,
806 .add_auth_cfg
= _add_auth_cfg
,
807 .create_auth_cfg_enumerator
= _create_auth_cfg_enumerator
,
808 .get_ppk_id
= _get_ppk_id
,
809 .ppk_required
= _ppk_required
,
810 .equals
= (void*)_equals
,
814 .is_mediation
= _is_mediation
,
815 .get_mediated_by
= _get_mediated_by
,
816 .get_peer_id
= _get_peer_id
,
819 .name
= strdup(name
),
821 .child_cfgs
= linked_list_create(),
822 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
823 .cert_policy
= data
->cert_policy
,
824 .unique
= data
->unique
,
825 .keyingtries
= data
->keyingtries
,
826 .rekey_time
= data
->rekey_time
,
827 .reauth_time
= data
->reauth_time
,
828 .jitter_time
= data
->jitter_time
,
829 .over_time
= data
->over_time
,
830 .use_mobike
= !data
->no_mobike
,
831 .aggressive
= data
->aggressive
,
832 .pull_mode
= !data
->push_mode
,
834 .dpd_timeout
= data
->dpd_timeout
,
835 .ppk_id
= data
->ppk_id
,
836 .ppk_required
= data
->ppk_required
,
837 .vips
= linked_list_create(),
838 .pools
= linked_list_create(),
839 .local_auth
= linked_list_create(),
840 .remote_auth
= linked_list_create(),
843 .mediation
= data
->mediation
,
844 .mediated_by
= strdupnull(data
->mediated_by
),
845 .peer_id
= data
->peer_id
,
849 return &this->public;