implement proper handling of most simultaneous IKE_SA rekeying cases

This commit is contained in:
Martin Willi
2006-08-23 07:30:43 +00:00
parent c3f97102f1
commit 3183006de2
8 changed files with 288 additions and 57 deletions
+3 -1
View File
@@ -79,12 +79,14 @@ static void send_notify_response(private_incoming_packet_job_t *this,
src = request->get_destination(request);
response->set_source(response, src->clone(src));
response->set_destination(response, dst->clone(dst));
response->set_exchange_type(response, IKE_SA_INIT);
response->set_exchange_type(response, request->get_exchange_type(request));
response->set_request(response, FALSE);
response->set_message_id(response, 0);
response->set_ike_sa_id(response, ike_sa_id);
notify = notify_payload_create_from_protocol_and_type(PROTO_NONE, type);
response->add_payload(response, (payload_t *)notify);
/* generation may fail, as most messages need a crypter/signer.
* TODO: Use transforms implementing the "NULL" algorithm */
if (response->generate(response, NULL, NULL, &packet) != SUCCESS)
{
response->destroy(response);
+52 -13
View File
@@ -64,6 +64,7 @@ mapping_t ike_sa_state_m[] = {
{IKE_CREATED, "CREATED"},
{IKE_CONNECTING, "CONNECTING"},
{IKE_ESTABLISHED, "ESTABLISHED"},
{IKE_REKEYING, "REKEYING"},
{IKE_DELETING, "DELETING"},
{MAPPING_END, NULL}
};
@@ -225,6 +226,11 @@ struct private_ike_sa_t {
* do multi transaction operations.
*/
transaction_t *transaction_in_next;
/**
* Transaction which rekeys this IKE_SA, used do detect simultaneus rekeying
*/
rekey_ike_sa_t *rekeying_transaction;
};
/**
@@ -840,10 +846,12 @@ static status_t initiate(private_ike_sa_t *this,
return queue_transaction(this, (transaction_t*)ike_sa_init, TRUE);
}
case IKE_DELETING:
case IKE_REKEYING:
{
/* if we are in DELETING, we deny set up of a policy. */
/* if we are in DELETING/REKEYING, we deny set up of a policy. */
this->logger->log(this->logger, CONTROL,
"creating CHILD_SA discarded, as IKE_SA is deleting");
"creating CHILD_SA discarded, as IKE_SA is in state %s",
mapping_find(ike_sa_state_m, this->state));
policy->destroy(policy);
connection->destroy(connection);
return FAILED;
@@ -1084,7 +1092,9 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t
set_name(this, connection->get_name(connection));
break;
case IKE_ESTABLISHED:
/* nothing to do */
case IKE_REKEYING:
/* nothing to do. We allow it for rekeying, as it will be
* adopted by the new IKE_SA */
break;
case IKE_DELETING:
/* deny */
@@ -1331,7 +1341,7 @@ static void set_other_id(private_ike_sa_t *this, identification_t *other)
static status_t derive_keys(private_ike_sa_t *this,
proposal_t *proposal, diffie_hellman_t *dh,
chunk_t nonce_i, chunk_t nonce_r,
bool initiator, prf_t *rekey_prf)
bool initiator, prf_t *child_prf, prf_t *old_prf)
{
prf_plus_t *prf_plus;
chunk_t skeyseed, secret, key, nonces, prf_plus_seed;
@@ -1368,7 +1378,7 @@ static status_t derive_keys(private_ike_sa_t *this,
*
* if we are rekeying, SKEYSEED built on another way
*/
if (rekey_prf == NULL) /* not rekeying */
if (child_prf == NULL) /* not rekeying */
{
/* SKEYSEED = prf(Ni | Nr, g^ir) */
this->prf->set_key(this->prf, nonces);
@@ -1381,14 +1391,15 @@ static status_t derive_keys(private_ike_sa_t *this,
}
else
{
/* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr) */
/* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
* use OLD SAs PRF functions for both prf_plus and prf */
secret = chunk_cat("mc", secret, nonces);
rekey_prf->allocate_bytes(rekey_prf, secret, &skeyseed);
child_prf->allocate_bytes(child_prf, secret, &skeyseed);
this->logger->log_chunk(this->logger, PRIVATE|LEVEL1, "SKEYSEED", skeyseed);
rekey_prf->set_key(rekey_prf, skeyseed); /* abuse of rekeyed SAs child_prf */
old_prf->set_key(old_prf, skeyseed);
chunk_free(&skeyseed);
chunk_free(&secret);
prf_plus = prf_plus_create(rekey_prf, prf_plus_seed);
prf_plus = prf_plus_create(old_prf, prf_plus_seed);
}
chunk_free(&nonces);
chunk_free(&prf_plus_seed);
@@ -1421,12 +1432,12 @@ static status_t derive_keys(private_ike_sa_t *this,
key_size = signer_i->get_key_size(signer_i);
prf_plus->allocate_bytes(prf_plus, key_size, &key);
this->logger->log_chunk(this->logger, CONTROL|LEVEL1, "Sk_ai secret", key);
this->logger->log_chunk(this->logger, PRIVATE, "Sk_ai secret", key);
signer_i->set_key(signer_i, key);
chunk_free(&key);
prf_plus->allocate_bytes(prf_plus, key_size, &key);
this->logger->log_chunk(this->logger, CONTROL|LEVEL1, "Sk_ar secret", key);
this->logger->log_chunk(this->logger, PRIVATE, "Sk_ar secret", key);
signer_r->set_key(signer_r, key);
chunk_free(&key);
@@ -1547,7 +1558,7 @@ static child_sa_t* get_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
{
iterator->current(iterator, (void**)&current);
if (current->get_spi(current, inbound) == spi &&
current->get_protocol(current) == protocol)
current->get_protocol(current) == protocol)
{
found = current;
}
@@ -1556,6 +1567,14 @@ static child_sa_t* get_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
return found;
}
/**
* Implementation of ike_sa_t.create_child_sa_iterator.
*/
static iterator_t* create_child_sa_iterator(private_ike_sa_t *this)
{
return this->child_sas->create_iterator(this->child_sas, TRUE);
}
/**
* Implementation of ike_sa_t.rekey_child_sa.
*/
@@ -1670,6 +1689,22 @@ static status_t rekey(private_ike_sa_t *this)
return queue_transaction(this, (transaction_t*)rekey_ike_sa, FALSE);
}
/**
* Implementation of ike_sa_t.get_rekeying_transaction.
*/
static rekey_ike_sa_t* get_rekeying_transaction(private_ike_sa_t *this)
{
return this->rekeying_transaction;
}
/**
* Implementation of ike_sa_t.set_rekeying_transaction.
*/
static void set_rekeying_transaction(private_ike_sa_t *this, rekey_ike_sa_t *rekey)
{
this->rekeying_transaction = rekey;
}
/**
* Implementation of ike_sa_t.adopt_children.
*/
@@ -1883,10 +1918,11 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.get_child_prf = (prf_t *(*) (ike_sa_t *)) get_child_prf;
this->public.get_prf_auth_i = (prf_t *(*) (ike_sa_t *)) get_prf_auth_i;
this->public.get_prf_auth_r = (prf_t *(*) (ike_sa_t *)) get_prf_auth_r;
this->public.derive_keys = (status_t (*) (ike_sa_t *,proposal_t*,diffie_hellman_t*,chunk_t,chunk_t,bool,prf_t*)) derive_keys;
this->public.derive_keys = (status_t (*) (ike_sa_t *,proposal_t*,diffie_hellman_t*,chunk_t,chunk_t,bool,prf_t*,prf_t*)) derive_keys;
this->public.add_child_sa = (void (*) (ike_sa_t*,child_sa_t*)) add_child_sa;
this->public.has_child_sa = (bool(*)(ike_sa_t*,u_int32_t)) has_child_sa;
this->public.get_child_sa = (child_sa_t* (*)(ike_sa_t*,protocol_id_t,u_int32_t,bool)) get_child_sa;
this->public.create_child_sa_iterator = (iterator_t* (*)(ike_sa_t*)) create_child_sa_iterator;
this->public.rekey_child_sa = (status_t(*)(ike_sa_t*,protocol_id_t,u_int32_t)) rekey_child_sa;
this->public.delete_child_sa = (status_t(*)(ike_sa_t*,protocol_id_t,u_int32_t)) delete_child_sa;
this->public.destroy_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t))destroy_child_sa;
@@ -1894,6 +1930,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.is_natt_enabled = (bool(*)(ike_sa_t*)) is_natt_enabled;
this->public.set_lifetimes = (void(*)(ike_sa_t*,u_int32_t,u_int32_t))set_lifetimes;
this->public.rekey = (status_t(*)(ike_sa_t*))rekey;
this->public.get_rekeying_transaction = (void*(*)(ike_sa_t*))get_rekeying_transaction;
this->public.set_rekeying_transaction = (void(*)(ike_sa_t*,void*))set_rekeying_transaction;
this->public.adopt_children = (void(*)(ike_sa_t*,ike_sa_t*))adopt_children;
/* initialize private fields */
@@ -1919,6 +1957,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->transaction_in = NULL;
this->transaction_in_next = NULL;
this->transaction_out = NULL;
this->rekeying_transaction = NULL;
this->state = IKE_CREATED;
this->message_id_out = 0;
/* set to NOW, as when we rekey an existing IKE_SA no message is exchanged */
+56 -22
View File
@@ -51,30 +51,32 @@ typedef enum ike_sa_state_t ike_sa_state_t;
* SA is in the state CREATED.
* @verbatim
+----------------+
¦ SA_CREATED ¦
¦ SA_CREATED ¦
+----------------+
¦
on initiate()---> ¦ <----- on IKE_SA_INIT received
¦
¦
on initiate()---> ¦ <----- on IKE_SA_INIT received
V
+----------------+
¦ SA_CONNECTING ¦
¦ SA_CONNECTING ¦
+----------------+
¦
¦ <----- on IKE_AUTH successfully completed
¦
¦
¦ <----- on IKE_AUTH successfully completed
V
+----------------+
¦ SA_ESTABLISHED ¦
¦ SA_ESTABLISHED ¦-------------------------+ <-- on rekeying
+----------------+ ¦
¦ V
on delete()---> ¦ <----- on IKE_SA +-------------+
¦ delete request ¦ SA_REKEYING ¦
¦ received +-------------+
V ¦
+----------------+ ¦
¦ SA_DELETING ¦<------------------------+ <-- after rekeying
+----------------+
¦
on delete()---> ¦ <----- on IKE_SA delete request received
¦
+----------------+
¦ SA_DELETING ¦
+----------------+
¦
¦ <----- after delete() acknowledged
¦
\¦/
¦
¦ <----- after delete() acknowledged
¦
\V/
X
/ \
@endverbatim
@@ -98,6 +100,11 @@ enum ike_sa_state_t {
*/
IKE_ESTABLISHED,
/**
* IKE_SA rekeying in progress
*/
IKE_REKEYING,
/**
* IKE_SA is in progress of deletion
*/
@@ -279,7 +286,7 @@ struct ike_sa_t {
* @brief Acquire connection setup for a policy.
*
* If an installed policy raises an acquire, the kernel calls
* this function to establsh the CHILD_SA (and maybe the IKE_SA).
* this function to establish the CHILD_SA (and maybe the IKE_SA).
*
* @param this calling object
* @param reqid reqid of the CHILD_SA the policy belongs to.
@@ -418,12 +425,13 @@ struct ike_sa_t {
* @param nonce_i initiators nonce
* @param nonce_r responders nonce
* @param initiator TRUE if initiator, FALSE otherwise
* @param rekey_prf PRF with SK_d key when rekeying, NULL otherwise
* @param child_prf PRF with SK_d key when rekeying, NULL otherwise
* @param old_prf general purpose PRF of old SA when rekeying
*/
status_t (*derive_keys)(ike_sa_t *this, proposal_t* proposal,
diffie_hellman_t *dh,
chunk_t nonce_i, chunk_t nonce_r,
bool initiator, prf_t *rekey_prf);
bool initiator, prf_t *child_prf, prf_t *old_prf);
/**
* @brief Get the multi purpose prf.
@@ -486,6 +494,14 @@ struct ike_sa_t {
child_sa_t* (*get_child_sa) (ike_sa_t *this, protocol_id_t protocol,
u_int32_t spi, bool inbound);
/**
* @brief Create an iterator over all CHILD_SAs.
*
* @param this calling object
* @return iterator
*/
iterator_t* (*create_child_sa_iterator) (ike_sa_t *this);
/**
* @brief Rekey the CHILD SA with the specified reqid.
*
@@ -555,6 +571,24 @@ struct ike_sa_t {
*/
status_t (*rekey) (ike_sa_t *this);
/**
* @brief Get the transaction which rekeys this IKE_SA.
*
* @todo Fix include for rekey_ike_sa.h
*
* @param this calling object
* @return rekey_ike_sa_t transaction or NULL
*/
void* (*get_rekeying_transaction) (ike_sa_t *this);
/**
* @brief Set the transaction which rekeys this IKE_SA.
*
* @param this calling object
* @param rekey rekey_ike_sa_t transaction or NULL
*/
void (*set_rekeying_transaction) (ike_sa_t *this, void *rekey);
/**
* @brief Move all children from other IKE_SA to this IKE_SA.
*
+12 -1
View File
@@ -406,7 +406,7 @@ static status_t process_notifys(private_create_child_sa_t *this, notify_payload_
if (notify_type < 16383)
{
this->logger->log(this->logger, AUDIT,
"received %s notify error (%d), deleting IKE_SA",
"received %s notify error (%d), CHILD_SA creation failed",
mapping_find(notify_type_m, notify_type),
notify_type);
return FAILED;
@@ -540,6 +540,17 @@ static status_t get_response(private_create_child_sa_t *this, message_t *request
return FAILED;
}
/* we do not allow the creation of new CHILDren/rekeying when IKE_SA is
* rekeying */
if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING ||
this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
{
build_notify(NO_ADDITIONAL_SAS, CHUNK_INITIALIZER, response, TRUE);
this->logger->log(this->logger, AUDIT,
"unable to create new CHILD_SAs, as rekeying in progress");
return FAILED;
}
/* Iterate over all payloads. */
payloads = request->get_payload_iterator(request);
while (payloads->has_next(payloads))
@@ -256,6 +256,17 @@ static status_t get_response(private_delete_child_sa_t *this, message_t *request
return FAILED;
}
/* we can't handle a delete for a CHILD when we are rekeying. There
* is no proper solution for this. We send a empty informational response,
* as described in ikev2-clarifications draft */
if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING ||
this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
{
this->logger->log(this->logger, AUDIT,
"unable to delete CHILD_SA, as rekeying in progress");
return FAILED;
}
/* iterate over all payloads */
payloads = request->get_payload_iterator(request);
while (payloads->has_next(payloads))
+2 -2
View File
@@ -775,7 +775,7 @@ static status_t get_response(private_ike_sa_init_t *this,
if (this->ike_sa->derive_keys(this->ike_sa, this->proposal,
this->diffie_hellman,
this->nonce_i, this->nonce_r,
FALSE, NULL) != SUCCESS)
FALSE, NULL, NULL) != SUCCESS)
{
notify_payload_t *notify = notify_payload_create();
notify->set_notify_type(notify, NO_PROPOSAL_CHOSEN);
@@ -1019,7 +1019,7 @@ static status_t conclude(private_ike_sa_init_t *this, message_t *response,
if (this->ike_sa->derive_keys(this->ike_sa, this->proposal,
this->diffie_hellman,
this->nonce_i, this->nonce_r,
TRUE, NULL) != SUCCESS)
TRUE, NULL, NULL) != SUCCESS)
{
this->logger->log(this->logger, AUDIT,
"transform objects could not be created from selected proposal, deleting IKE_SA");
+150 -16
View File
@@ -190,6 +190,15 @@ static status_t get_request(private_rekey_ike_sa_t *this, message_t **result)
return SUCCESS;
}
if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
{
this->logger->log(this->logger, ERROR,
"tried to rekey in state %s, aborted",
mapping_find(ike_sa_state_m,
this->ike_sa->get_state(this->ike_sa)));
return FAILED;
}
me = this->ike_sa->get_my_host(this->ike_sa);
other = this->ike_sa->get_other_host(this->ike_sa);
@@ -274,7 +283,7 @@ static status_t get_request(private_rekey_ike_sa_t *this, message_t **result)
this->logger->log(this->logger, AUDIT,
"DH group %s (%d) not supported, aborting",
mapping_find(diffie_hellman_group_m, dh_group), dh_group);
return DESTROY_ME;
return FAILED;
}
}
@@ -288,6 +297,10 @@ static status_t get_request(private_rekey_ike_sa_t *this, message_t **result)
this->message_id = this->ike_sa->get_next_message_id(this->ike_sa);
request->set_message_id(request, this->message_id);
/* register us as rekeying to detect multiple rekeying */
this->ike_sa->set_state(this->ike_sa, IKE_REKEYING);
this->ike_sa->set_rekeying_transaction(this->ike_sa, &this->public);
return SUCCESS;
}
@@ -380,7 +393,8 @@ static status_t switchto_new_sa(private_rekey_ike_sa_t* this, bool initiator)
if (this->new_sa->derive_keys(this->new_sa, this->proposal,
this->diffie_hellman,
this->nonce_i, this->nonce_r, initiator,
this->ike_sa->get_child_prf(this->ike_sa)
this->ike_sa->get_child_prf(this->ike_sa),
this->ike_sa->get_prf(this->ike_sa)
) != SUCCESS)
{
return FAILED;
@@ -388,14 +402,9 @@ static status_t switchto_new_sa(private_rekey_ike_sa_t* this, bool initiator)
this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED);
this->new_sa->adopt_children(this->new_sa, this->ike_sa);
this->new_sa->set_lifetimes(this->new_sa,
this->connection->get_soft_lifetime(this->connection),
this->connection->get_hard_lifetime(this->connection));
charon->ike_sa_manager->checkin(charon->ike_sa_manager, this->new_sa);
this->new_sa = NULL;
return SUCCESS;
}
@@ -433,7 +442,8 @@ static status_t get_response(private_rekey_ike_sa_t *this, message_t *request,
host_t *me, *other;
message_t *response;
status_t status;
iterator_t *payloads;
iterator_t *payloads, *iterator;
child_sa_t *child_sa;
sa_payload_t *sa_request = NULL;
nonce_payload_t *nonce_request = NULL;
ke_payload_t *ke_request = NULL;
@@ -469,6 +479,33 @@ static status_t get_response(private_rekey_ike_sa_t *this, message_t *request,
return FAILED;
}
/* if we already initiate a delete, we do not allow rekeying */
if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
{
build_notify(NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER, response, TRUE);
this->logger->log(this->logger, CONTROL,
"unable to rekey, as delete in progress. Sending NO_PROPOSAL_CHOSEN");
return FAILED;
}
/* if we have a CHILD which is "half-open", we do not allow rekeying */
iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
while (iterator->iterate(iterator, (void**)&child_sa))
{
child_sa_state_t state = child_sa->get_state(child_sa);
if (state == CHILD_CREATED ||
state == CHILD_REKEYING ||
state == CHILD_DELETING)
{
build_notify(NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER, response, TRUE);
this->logger->log(this->logger, CONTROL,
"unable to rekey, one CHILD_SA is half open. Sending NO_PROPOSAL_CHOSEN");
iterator->destroy(iterator);
return FAILED;
}
}
iterator->destroy(iterator);
/* apply for notify processing */
this->next = next;
@@ -622,7 +659,49 @@ static status_t get_response(private_rekey_ike_sa_t *this, message_t *request,
response->add_payload(response, (payload_t*)ke_response);
}
return switchto_new_sa(this, FALSE);
status = switchto_new_sa(this, FALSE);
if (status != SUCCESS)
{
return status;
}
/* IKE_SA successfully created. If another transaction is already rekeying
* this SA, our lower nonce must be registered for a later nonce compare. */
{
private_rekey_ike_sa_t *other;
other = this->ike_sa->get_rekeying_transaction(this->ike_sa);
if (other)
{
/* store our lower nonce in the simultaneus transaction, we
* will later compare it against his nonces when we calls conclude().
* We do not adopt childrens yet, as we don't know if we'll win
* the race...
*/
if (memcmp(this->nonce_i.ptr, this->nonce_r.ptr,
min(this->nonce_i.len, this->nonce_r.len)) < 0)
{
other->nonce_s = chunk_clone(this->nonce_i);
}
else
{
other->nonce_s = chunk_clone(this->nonce_r);
}
/* overwrite "other" in IKE_SA, allows "other" to access "this" */
this->ike_sa->set_rekeying_transaction(this->ike_sa, &this->public);
}
else
{
/* if we have no simultaneus transaction, we can safely adopt
* all children and complete. */
this->new_sa->adopt_children(this->new_sa, this->ike_sa);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, this->new_sa);
this->new_sa = NULL;
}
this->ike_sa->set_state(this->ike_sa, IKE_REKEYING);
}
return SUCCESS;
}
/**
@@ -636,6 +715,7 @@ static status_t conclude(private_rekey_ike_sa_t *this, message_t *response,
sa_payload_t *sa_payload = NULL;
nonce_payload_t *nonce_payload = NULL;
ke_payload_t *ke_payload = NULL;
private_rekey_ike_sa_t *other_trans;
status_t status;
/* check message type */
@@ -726,18 +806,72 @@ static status_t conclude(private_rekey_ike_sa_t *this, message_t *response,
ke_payload->get_key_exchange_data(ke_payload));
}
if (switchto_new_sa(this, TRUE) == SUCCESS)
{
/* new IKE_SA is in use now, delete old */
*next = (transaction_t*)delete_ike_sa_create(this->ike_sa);
return SUCCESS;
}
else
if (switchto_new_sa(this, TRUE) != SUCCESS)
{
/* this should not happen. But if, we destroy both SAs */
*next = (transaction_t*)delete_ike_sa_create(this->new_sa);
return DESTROY_ME;
}
/* IKE_SA successfully created. If the other peer initiated rekeying
* in the meantime, we detect this by comparing the rekeying_transaction
* of the SA. If it changed, we are not alone. Then we must compare the nonces.
* If no simultaneous rekeying is going on, we just initiate the delete of
* the superseded SA. */
other_trans = this->ike_sa->get_rekeying_transaction(this->ike_sa);
this->ike_sa->set_rekeying_transaction(this->ike_sa, NULL);
if (this->nonce_s.ptr)
{ /* simlutaneous rekeying is going on, not so good */
chunk_t this_lowest;
/* first get our lowest nonce */
if (memcmp(this->nonce_i.ptr, this->nonce_r.ptr,
min(this->nonce_i.len, this->nonce_r.len)) < 0)
{
this_lowest = this->nonce_i;
}
else
{
this_lowest = this->nonce_r;
}
/* then compare against other lowest nonce */
if (memcmp(this_lowest.ptr, this->nonce_s.ptr,
min(this_lowest.len, this->nonce_s.len)) < 0)
{
this->logger->log(this->logger, ERROR,
"detected simultaneous IKE_SA rekeying, deleting ours");
this->lost = TRUE;
}
else
{
this->logger->log(this->logger, ERROR,
"detected simultaneous IKE_SA rekeying, but ours is preferred");
}
if (this->lost)
{
/* the other has won, he gets our children */
other_trans->new_sa->adopt_children(other_trans->new_sa, this->ike_sa);
/* we have lost simlutaneous rekeying, delete the SA we just have created */
this->new_sa->delete(this->new_sa);
}
/* other trans' SA is still not checked in, so do it now. It's SA will get
* deleted by remote peer. */
charon->ike_sa_manager->checkin(charon->ike_sa_manager, other_trans->new_sa);
other_trans->new_sa = NULL;
}
if (!this->lost)
{
/* we have won. delete old IKE_SA, and migrate all children */
*next = (transaction_t*)delete_ike_sa_create(this->ike_sa);
this->new_sa->adopt_children(this->new_sa, this->ike_sa);
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager, this->new_sa);
this->new_sa = NULL;
return SUCCESS;
}
/**
+2 -2
View File
@@ -70,7 +70,7 @@ transaction_t *transaction_create(ike_sa_t *ike_sa, message_t *request)
}
case CREATE_CHILD_SA:
{
if (ike_sa->get_state(ike_sa) != IKE_ESTABLISHED)
if (ike_sa->get_state(ike_sa) < IKE_ESTABLISHED)
{
break;
}
@@ -114,7 +114,7 @@ transaction_t *transaction_create(ike_sa_t *ike_sa, message_t *request)
}
case INFORMATIONAL:
{
if (ike_sa->get_state(ike_sa) == IKE_CREATED)
if (ike_sa->get_state(ike_sa) < IKE_ESTABLISHED)
{
break;
}