}
METHOD(ike_sa_manager_t, check_uniqueness, bool,
- private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
+ private_ike_sa_manager_t *this, ike_sa_t *ike_sa, bool force_replace)
{
bool cancel = FALSE;
peer_cfg_t *peer_cfg;
peer_cfg = ike_sa->get_peer_cfg(ike_sa);
policy = peer_cfg->get_unique_policy(peer_cfg);
- if (policy == UNIQUE_NO)
+ if (policy == UNIQUE_NO && !force_replace)
{
return FALSE;
}
{
continue;
}
+ if (force_replace)
+ {
+ DBG1(DBG_IKE, "destroying duplicate IKE_SA for peer '%Y', "
+ "received INITIAL_CONTACT", other);
+ checkin_and_destroy(this, duplicate);
+ continue;
+ }
peer_cfg = duplicate->get_peer_cfg(duplicate);
if (peer_cfg && peer_cfg->equals(peer_cfg, ike_sa->get_peer_cfg(ike_sa)))
{
* deadlocks occur otherwise.
*
* @param ike_sa ike_sa to check
+ * @param force_replace replace existing SAs, regardless of unique policy
* @return TRUE, if the given IKE_SA has duplicates and
* should be deleted
*/
- bool (*check_uniqueness)(ike_sa_manager_t *this, ike_sa_t *ike_sa);
+ bool (*check_uniqueness)(ike_sa_manager_t *this, ike_sa_t *ike_sa,
+ bool force_replace);
/**
* Check if we already have a connected IKE_SA between two identities.
* should we send a AUTHENTICATION_FAILED notify?
*/
bool authentication_failed;
+
+ /**
+ * received an INITIAL_CONTACT?
+ */
+ bool initial_contact;
};
/**
return NEED_MORE;
}
+ /* If authenticated (with non-EAP) and received INITIAL_CONTACT,
+ * delete any existing IKE_SAs with that peer. */
+ if (message->get_message_id(message) == 1 &&
+ message->get_notify(message, INITIAL_CONTACT))
+ {
+ this->initial_contact = TRUE;
+ }
+
/* store authentication information */
cfg = auth_cfg_create();
cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
get_reserved_id_bytes(this, id_payload);
message->add_payload(message, (payload_t*)id_payload);
+ if (this->initial_contact)
+ {
+ charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
+ this->ike_sa, TRUE);
+ this->initial_contact = FALSE;
+ }
+
if ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS) == AUTH_CLASS_EAP)
{ /* EAP-only authentication */
if (!this->ike_sa->supports_extension(this->ike_sa,
if (!this->do_another_auth && !this->expect_another_auth)
{
if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
- this->ike_sa))
+ this->ike_sa, FALSE))
{
DBG1(DBG_IKE, "cancelling IKE_SA setup due uniqueness policy");
message->add_notify(message, TRUE, AUTHENTICATION_FAILED,