Send INITIAL_CONTACT for the first IKE_SA if it has a unique policy
This commit is contained in:
@@ -1320,9 +1320,8 @@ METHOD(ike_sa_manager_t, checkin, void,
|
|||||||
segment = put_entry(this, entry);
|
segment = put_entry(this, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply identities for duplicate test (only as responder) */
|
/* apply identities for duplicate test */
|
||||||
if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
|
if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
|
||||||
ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
|
|
||||||
entry->my_id == NULL && entry->other_id == NULL)
|
entry->my_id == NULL && entry->other_id == NULL)
|
||||||
{
|
{
|
||||||
entry->my_id = my_id->clone(my_id);
|
entry->my_id = my_id->clone(my_id);
|
||||||
@@ -1377,8 +1376,7 @@ METHOD(ike_sa_manager_t, checkin_and_destroy, void,
|
|||||||
{
|
{
|
||||||
remove_half_open(this, entry);
|
remove_half_open(this, entry);
|
||||||
}
|
}
|
||||||
if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
|
if (entry->my_id && entry->other_id)
|
||||||
entry->my_id && entry->other_id)
|
|
||||||
{
|
{
|
||||||
remove_connected_peers(this, entry);
|
remove_connected_peers(this, entry);
|
||||||
}
|
}
|
||||||
@@ -1502,6 +1500,34 @@ METHOD(ike_sa_manager_t, check_uniqueness, bool,
|
|||||||
return cancel;
|
return cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(ike_sa_manager_t, has_contact, bool,
|
||||||
|
private_ike_sa_manager_t *this, identification_t *me,
|
||||||
|
identification_t *other, int family)
|
||||||
|
{
|
||||||
|
linked_list_t *list;
|
||||||
|
u_int row, segment;
|
||||||
|
rwlock_t *lock;
|
||||||
|
bool found = FALSE;
|
||||||
|
|
||||||
|
row = chunk_hash_inc(other->get_encoding(other),
|
||||||
|
chunk_hash(me->get_encoding(me))) & this->table_mask;
|
||||||
|
segment = row & this->segment_mask;
|
||||||
|
lock = this->connected_peers_segments[segment & this->segment_mask].lock;
|
||||||
|
lock->read_lock(lock);
|
||||||
|
list = this->connected_peers_table[row];
|
||||||
|
if (list)
|
||||||
|
{
|
||||||
|
if (list->find_first(list, (linked_list_match_t)connected_peers_match,
|
||||||
|
NULL, me, other, family) == SUCCESS)
|
||||||
|
{
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lock->unlock(lock);
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(ike_sa_manager_t, get_half_open_count, int,
|
METHOD(ike_sa_manager_t, get_half_open_count, int,
|
||||||
private_ike_sa_manager_t *this, host_t *ip)
|
private_ike_sa_manager_t *this, host_t *ip)
|
||||||
{
|
{
|
||||||
@@ -1608,8 +1634,7 @@ METHOD(ike_sa_manager_t, flush, void,
|
|||||||
{
|
{
|
||||||
remove_half_open(this, entry);
|
remove_half_open(this, entry);
|
||||||
}
|
}
|
||||||
if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
|
if (entry->my_id && entry->other_id)
|
||||||
entry->my_id && entry->other_id)
|
|
||||||
{
|
{
|
||||||
remove_connected_peers(this, entry);
|
remove_connected_peers(this, entry);
|
||||||
}
|
}
|
||||||
@@ -1686,6 +1711,7 @@ ike_sa_manager_t *ike_sa_manager_create()
|
|||||||
.checkout_by_id = _checkout_by_id,
|
.checkout_by_id = _checkout_by_id,
|
||||||
.checkout_by_name = _checkout_by_name,
|
.checkout_by_name = _checkout_by_name,
|
||||||
.check_uniqueness = _check_uniqueness,
|
.check_uniqueness = _check_uniqueness,
|
||||||
|
.has_contact = _has_contact,
|
||||||
.create_enumerator = _create_enumerator,
|
.create_enumerator = _create_enumerator,
|
||||||
.checkin = _checkin,
|
.checkin = _checkin,
|
||||||
.checkin_and_destroy = _checkin_and_destroy,
|
.checkin_and_destroy = _checkin_and_destroy,
|
||||||
|
|||||||
@@ -111,6 +111,17 @@ struct ike_sa_manager_t {
|
|||||||
*/
|
*/
|
||||||
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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if we already have a connected IKE_SA between two identities.
|
||||||
|
*
|
||||||
|
* @param me own identity
|
||||||
|
* @param other remote identity
|
||||||
|
* @param family address family to include in uniqueness check
|
||||||
|
* @return TRUE if we have a connected IKE_SA
|
||||||
|
*/
|
||||||
|
bool (*has_contact)(ike_sa_manager_t *this, identification_t *me,
|
||||||
|
identification_t *other, int family);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check out an IKE_SA a unique ID.
|
* Check out an IKE_SA a unique ID.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -390,7 +390,7 @@ static status_t build_i(private_ike_auth_t *this, message_t *message)
|
|||||||
/* check if an authenticator is in progress */
|
/* check if an authenticator is in progress */
|
||||||
if (this->my_auth == NULL)
|
if (this->my_auth == NULL)
|
||||||
{
|
{
|
||||||
identification_t *id;
|
identification_t *idi, *idr = NULL;
|
||||||
id_payload_t *id_payload;
|
id_payload_t *id_payload;
|
||||||
|
|
||||||
/* clean up authentication config from a previous round */
|
/* clean up authentication config from a previous round */
|
||||||
@@ -401,29 +401,42 @@ static status_t build_i(private_ike_auth_t *this, message_t *message)
|
|||||||
cfg = get_auth_cfg(this, FALSE);
|
cfg = get_auth_cfg(this, FALSE);
|
||||||
if (cfg)
|
if (cfg)
|
||||||
{
|
{
|
||||||
id = cfg->get(cfg, AUTH_RULE_IDENTITY);
|
idr = cfg->get(cfg, AUTH_RULE_IDENTITY);
|
||||||
if (id && !id->contains_wildcards(id))
|
if (idr && !idr->contains_wildcards(idr))
|
||||||
{
|
{
|
||||||
this->ike_sa->set_other_id(this->ike_sa, id->clone(id));
|
this->ike_sa->set_other_id(this->ike_sa, idr->clone(idr));
|
||||||
id_payload = id_payload_create_from_identification(
|
id_payload = id_payload_create_from_identification(
|
||||||
ID_RESPONDER, id);
|
ID_RESPONDER, idr);
|
||||||
message->add_payload(message, (payload_t*)id_payload);
|
message->add_payload(message, (payload_t*)id_payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* add IDi */
|
/* add IDi */
|
||||||
cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
|
cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
|
||||||
cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
|
cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
|
||||||
id = cfg->get(cfg, AUTH_RULE_IDENTITY);
|
idi = cfg->get(cfg, AUTH_RULE_IDENTITY);
|
||||||
if (!id)
|
if (!idi)
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "configuration misses IDi");
|
DBG1(DBG_CFG, "configuration misses IDi");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
|
this->ike_sa->set_my_id(this->ike_sa, idi->clone(idi));
|
||||||
id_payload = id_payload_create_from_identification(ID_INITIATOR, id);
|
id_payload = id_payload_create_from_identification(ID_INITIATOR, idi);
|
||||||
get_reserved_id_bytes(this, id_payload);
|
get_reserved_id_bytes(this, id_payload);
|
||||||
message->add_payload(message, (payload_t*)id_payload);
|
message->add_payload(message, (payload_t*)id_payload);
|
||||||
|
|
||||||
|
if (idr && message->get_message_id(message) == 1 &&
|
||||||
|
this->peer_cfg->get_unique_policy(this->peer_cfg) != UNIQUE_NO)
|
||||||
|
{
|
||||||
|
host_t *host;
|
||||||
|
|
||||||
|
host = this->ike_sa->get_other_host(this->ike_sa);
|
||||||
|
if (!charon->ike_sa_manager->has_contact(charon->ike_sa_manager,
|
||||||
|
idi, idr, host->get_family(host)))
|
||||||
|
{
|
||||||
|
message->add_notify(message, FALSE, INITIAL_CONTACT, chunk_empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* build authentication data */
|
/* build authentication data */
|
||||||
this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
|
this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
|
||||||
this->other_nonce, this->my_nonce,
|
this->other_nonce, this->my_nonce,
|
||||||
|
|||||||
Reference in New Issue
Block a user