When serving as a responder and receiving an INFORMATIONAL exchange
containing INVALID_SYNTAX after IKE_AUTH, the IKE_SA should be deleted.
Currently, it only gets deleted after receiving AUTHENTICATION_FAILED.
RFC7296 section 2.21.2 says:
In an IKE_AUTH exchange, or in the INFORMATIONAL exchange immediately
following it (in case an error happened when processing a response to
IKE_AUTH), the UNSUPPORTED_CRITICAL_PAYLOAD, INVALID_SYNTAX, and
AUTHENTICATION_FAILED notifications are the only ones to cause the
IKE SA to be deleted or not created, without a Delete payload.
Closesstrongswan/strongswan#2636
If a migrate of a child-create occurs then labels_i and labels_r are
freed, but the pointers are left set. If the task is subsequently
destroyed without being reused, then both of these will be double
freed.
Fix this by setting labels_i and labels_r to NULL in the migrate
method after freeing, similar to other fields that are freed.
Closesstrongswan/strongswan#2552
Fixes: f9b895b49f ("child-create: Add support to handle security labels")
Both variables `inbound_installed` and `outbound_state` are used in
`child_sa_t::destroy()` to determine whether inbound and outbound state
have to be deleted. They are assigned prior to the call to
`kernel_interface_t::add_sa()`. As this call may fail, the destructor may
try to delete a state which it has not been added.
By making the assignment of these variables dependent on the success of
the state addition, we can make sure, a `child_sa_t::destroy()` only
deletes states it has added.
Also removed the redundant checks for `my_spi` and `other_spi` being set
along with the check for the above flags. It seems that when the flags
are set, the SPIs *must* be set.
Signed-off-by: Thomas Egerer <thomas.egerer@secunet.com>
As the winner of a rekey collision, we previously always triggered the
child_rekey() event once when creating the redundant SA on behalf of the
peer in the passive child-rekey task and then a second time when
creating the winning SA in the active task. However, both calls passed
the replaced CHILD_SA as "old". This made tracking CHILD_SAs impossible
because there was no transition from the redundant, "new" SA of the
first event to the "new", winning SA of the second. Of course, when the
second event was triggered, the redundant SA might not have existed
anymore because the peer is expected to delete it, which could happen
before the CREATE_CHILD_SA response arrives at the initiator.
This refactoring ensures that the child_rekey() event is triggered in
a way that makes the CHILD_SAs trackable in all reasonable (and even
some unreasonable) scenarios. The event is generally only triggered
once after installing the outbound SA for the new/winning CHILD_SA.
This can be when processing the CREATE_CHILD_SA in the active child-rekey
task, or when processing the DELETE for the old SA in a passive
child-delete task. There are some cases where the event is still
triggered twice, but it is now ensured that listeners can properly
transition to the winning SA.
Some corner cases are now also handled correctly, e.g. if a responder's
DELETE for the new CHILD_SA arrives before its CREATE_CHILD_SA response
that actually creates it on the initiator. Also handled properly are
responders of rekeyings that incorrectly send a DELETE for the old
CHILD_SA (previously this caused both, the new and the old SA, to get
deleted).
It also changes that payloads are built before installing the CHILD_SA
on the responder, that is, the KE payload is generated before keys are
derived, so that key_exchange_t::get_public_key() is called before
get_shared_secret(), or its internal equivalent, which could be relevant
for KE implementations that want to ensure that the key can't be
accessed again after the key derivation.
Initially, this is handled with a key derivation for each
IKE_INTERMEDIATE exchange. When rekeying, the keys are derived only
once all IKE_FOLLOWUP_KE exchanges are done.
The message ID of the first IKE_AUTH exchange is a safe-guard against
potential truncation attacks if IKE_INTERMEDIATE exchanges are not used
for multiple key exchanges but some other future use where the number of
exchanges might not depend on the selected proposal.
We currently only support these exchanges for additional key exchanges,
so once we have the final keys derived and the ike-init task is removed,
we don't expect any more of them.
The IKE_SA might be busy with a different task while a request to
terminate it is getting queued, we don't want to use such an IKE_SA to
initiate new CHILD_SAs as these tasks will get lost once the IKE_SA is
terminated.
CHILD_SA unique identifier allocation starts at 1. If the counter overflows,
a unique ID of 0 is assigned to an CHILD_SA, which may have unclear
consequences.
Overflowing the unique ID counter is theoretical for most setups, but on
a Gateway terminating 100'000 tunnels and rekeying CHILD_SAs every 60s
overflows the counter after a month uptime. So avoid a 0 unique identifier
by using ref_get_nonzero().
IKE_SA unique identifier allocation starts at 1. If the counter overflows,
a unique ID of 0 is assigned to an IKE_SA, which may have unclear consequences.
Overflowing the unique ID counter is theoretical for most setups, but on
a Gateway terminating 100'000 tunnels and rekeying the IKE_SA every 60s
overflows the counter after a month uptime. So avoid a 0 unique identifier
by using ref_get_nonzero().
Maintaining the reqid when recreating a CHILD_SA from scratch night not
strictly be necessary as we usually don't have to replace any temporary
states in the kernel. However, there could be concurrent acquires that
might actually make it necessary (we use the reqid to keep track of
acquires and it's also part of the duplicate check).
Keeping a reference ensures that if the old SA expires before the new
one is installed, the previous reqid isn't reallocated to a concurrently
established CHILD_SA with different selectors.
The reference is kept until the reqid is either confirmed (i.e.
re-allocated) or replaced by a different reqid, which happens only once
we know the final traffic selectors, or the SA is destroyed without
installing it.
Since the referenced commit, the state switch to IKE_ESTABLISHED doesn't
happen immediately after completing the authentication but only after
the remaining tasks have finished. Due to that redirects during IKE_AUTH
were treated like those during IKE_SA_INIT causing the IKE_SA and task
manager to get reset. However, unlike the ike-init task, the ike-auth
task returned SUCCESS and, therefore, got destroyed, while a different
task was removed from the array that was modified during the reset.
This later caused a dereference of the freed ike-auth task and a crash.
Fixes: 5ce1c91b58 ("ikev2: Trigger ike_updown() event after all IKE-specific tasks ran")