After establishing an IKE_SA, we check if any of its child configs
define generic SELinux labels and install trap policies for them if
necessary narrowed to the current (virtual) IPs.
This allows managing trap policies outside of the trap manager.
We'll use this to create trap policies with generic labels if trap policies
can't (or won't) be used (e.g. as responder for roadwarriors).
If update_sa() is called and dynamic traffic selectors are changed using
new addresses, this might cause issues if we continue to use a reqid that
doesn't match the updated traffic selectors. For instance, if the initiator
then uses make-before-break reauth from the new IP. It's also a particular
problem in the SELinux case where multiple CHILD_SAs with specific labels
all share the same (trap) policy with generic label. However, SAs created
after the update would not match due to the new reqid.
This was originally added with 1551d8b13d ("kernel-netlink: reject
policy refcount if the reqid differs"). Since then we added code to
allocate constant reqids for the same TS, which pretty much avoids the
previous issues.
However, the reqid might have to be changed due to MOBIKE updates. And
because reqids are allocated for a complete set of traffic selectors and
not individual pairs, this can create a problem with drop policies as
those will use the old reqid (they are installed with the same priority,
reqid etc. to replace the actual IPsec policies), while unmodified
replacement policies will use the new one. A similar issue exists for
CHILD_SAs with SELinux contexts as those all use duplicate policies (same
generic label) but can't all be updated concurrently.
With SELinux and without a specific label from an acquire, we abort
establishing the CHILD_SA (for the first one we prefer a childless IKE_SA,
but since that's a separate extension, we fall back to letting the initial
CHILD_SA fail as we won't propose a label).
If trap policies are not installed already (e.g. because it's impossible to
do so like as responder for roadwarriors), this will require installing
them dynamically once the IKE_SA is established.
In SELinux mode we install the configured label on the policies and the
negotiated one on the SAs. This is how it usually is configured where the
policy/configuration has a generic context and the SAs will get the actual
context of the flows assigned (the latter matches the former, so flows
match the policies but will trigger an acquire if no matching SA exists).
In the simple mode we don't pass the label to the kernel and to avoid
duplicate policy errors we also don't use it to acquire unique reqids.
The security labels can be retrieved in a separate list from the
regular traffic selectors. We currently only plan to support a single
security label ourselves, so when generating we don't expect a list.
Changes how regular address range traffic selectors are parsed as the
IKE parser currently doesn't provide sub-type parsing.
Also removed a lot of unused method definitions.
While combining the actions could cause duplicates (while the SA is
initiated, traffic might trigger the trap and the initiation of another
CHILD_SA), the previous commit should avoid most duplicates. If reuse_ikesa
is disabled, duplicates can't be prevented, though.
This could happen if an acquire is triggered while we respond to a
CREATE_CHILD_SA request from the peer, or if an acquire is triggered
while an IKE_SA (with its existing CHILD_SAs) is reestablished (also
with break-before-make reauthentication). Also catches multiple
manual initiations.
Note that this ignores the traffic selectors from acquires (narrowing to
them seems rare in practice anyway).
Duplicates can still get created if e.g. both peers initiate them
concurrently.
If a policy with IPComp template triggers an acquire, we get two, one for
an IPComp, one for ESP/AH SA. However, the triggering template of the trap
policy (where we get the reqid from), will be the same in both acquires,
IPComp, which we ignore, so no acquire was actually forwarded.
These are set via methods, which are not called again after migration
(e.g. when retrying due to INVALID_KE or when moving queued tasks), so we
don't want to clear these values.
This should fix this error thrown by autoreconf:
ld-elf.so.1: /usr/local/lib/perl5/5.32/mach/CORE/libperl.so.5.32: Undefined symbol "strerror_l@FBSD_1.6"
This should make the DoS limits (cookie_threshold[_ip] and block_threshold)
more accurate so that it won't be possible to create lots of jobs from
spoofed IP addresses before half-open IKE_SAs are actually created from
these jobs to enforce those limits.
Note that retransmits are tracked as half-open SAs until they are
processed/dismissed as the check only happens in checkout_by_message().
Increasing the count in process_message_job_create() avoids issues with
missing calls to track_init() before calling checkout_by_message() (e.g.
when processing fragmented IKEv1 messages, which are reinjected via a
process message job).
Because the global cookie threshold is higher than the per-IP block
threshold, it was previously possible for an attacker to block a legitimate
user by sending spoofed IKE_SA_INIT packets from that user's IP.
The timespan for requiring cookies is now also not extended anymore with
every IKE_SA_INIT received during the calm down period. Because this
allowed an attacker, after initially triggering the global cookie threshold,
to force cookies for all clients by sending just a single spoofed
IKE_SA_INIT every 10 seconds.
We keep track of reaching the per-IP threshold in segments of the hashed
IP addresses, so only a (random, due to chunk_hash()'s random key) subset
of clients will receive cookies, if single IPs are targeted.
The default global threshold is increased a bit.
If we are under attack and there are lots of requests, we might hit
the previous use count limit pretty quickly and may switch secrets multiple
times a second, which renders the 10 second default lifetime of COOKIEs
pointless and prevents legitimate clients from sending requests with valid
COOKIEs.
This happens for `/0` subnet masks. In practice, it's not an issue because
if `bytes` is 0, then so are `netbits`, `bits` and `mask`. So the two
incorrectly addressed array elements are not actually modified. The first
operation is a `&= 0xff` and the second a `|= 0`, so nothing changes.
But some tools might not consider the values and report this as undefined
behavior, which it technically is.
Such routes with a gateway that equals the peer's address are problematic
on FreeBSD. And since there is most likely a narrow route for the local
subnet anyway, the exclude routes would be redundant.
When installing routes based on remote traffic selectors, it can be
necessary to install an exclude route for the remote peer to avoid a
routing loop and continue to be able to reach it via IKE/ESP.
However, such routes are only necessary, if the routes we install don't
go via outbound interface. That's the case when using VIPs and routing
via TUN devices, or when using internal source IPs and routing via
their interfaces.
Installing such exclude routes if not necessary can cause issues on
FreeBSD (EINVAL when sending packets to the peer).
There is a conflict between atexit() handlers registered by OpenSSL and
some executables (e.g. swanctl or pki) to deinitialize libstrongswan.
Because plugins are usually loaded after atexit() has been called, the
handler registered by OpenSSL will run before our handler. So when the
latter destroys the plugins it's a bad idea to try to access any OpenSSL
objects as they might already be invalid.
Fixes: f556fce16b ("openssl: Load "legacy" provider in OpenSSL 3 for algorithms like MD4, DES etc.")
Closesstrongswan/strongswan#921
has_subject() already matches the identity against the subject DN and
all the SANs (it actually already did when this check was added with
c811479986 ("Strictly check if the server certificate matches the TLS
server identity")).
The client already enforces that the server identity is contained in the
received certificate. But on the server, the referenced commit changed
the lookup from the configured (or adopted if %any was configured) client
identity to the subject DN of the received client certificate. So any
client with a trusted certificate was accepted.
Fixes: d2fc9b0961 ("tls-server: Mutual authentication support for TLS 1.3")
Closesstrongswan/strongswan#873
This adds some modifications to NAT-D in case the source IP can't be
determined before generating NAT-D notifies. If this happens when using
IPv4, a local NAT is faked (UDP-encap can be disabled later via MOBIKE
if no NAT is actually detected). If it happens when using IPv6, NAT-T
is disabled completely.
It also removes the old fallbacks for source NAT-D notifies, which were
generally unused but could lead to incorrect results in the above
scenario.
Closesstrongswan/strongswan#861
This can happen if an IKE_SA is initiated to a static IP before DHCP is
done. Instead of failing the initiation, we either fake a NAT situation
(for IPv4) or disable NAT-D (for IPv6 where NATs and UDP-encap are not
widely used or supported).
This also removes the old fallbacks to determine the source address(es).
A source address lookup is done in ike_sa_t::resolve_hosts() (wasn't the
case initially) and enumerating local IPs (which was added even earlier)
could still lead to issues if e.g. LAN addresses are available but the
WAN address that's later used is not yet (in which case only the responder
would detect a NAT and UDP-encap would be configured asymmetrically).
To force UDP-encap locally in case there is no actual NAT, we store this
as COND_NAT_HERE instead of COND_NAT_FAKE. This ensures DPDs will contain
NAT-D notifies and we can later remove the state via MOBIKE. We trigger
a MOBIKE update after such a DPD by registering a changed NAT mapping after
checking for a disappearing local NAT, which is very unlikely to happen
outside of a MOBIKE update (where that flag is not checked).
On the recently updated 2019 image, autoreconf is not found anymore, as
recent versions of msys2 don't ship autools with base-devel aymore, so
install the autotools package explicitly.
Without this, the authentication succeeded if the server sent an early
EAP-Success message for mutual, key-generating EAP methods like EAP-TLS,
which may be used in EAP-only scenarios but would complete without server
or client authentication. For clients configured for such EAP-only
scenarios, a rogue server could capture traffic after the tunnel is
established or even access hosts behind the client. For non-mutual EAP
methods, public key server authentication has been enforced for a while.
A server previously could also crash a client by sending an EAP-Success
immediately without initiating an actual EAP method.
Fixes: 0706c39cda ("added support for EAP methods not establishing an MSK")
Fixes: CVE-2021-45079
Optionally load the legacy provider in OpenSSL 3 (enabled, by default) to
make algorithms like MD4 and DES available, which we require for
EAP-MSCHAPv2. Allow explicitly loading the fips provider via existing
fips_mode option. The loaded providers, whether influenced by the above
options or not, are logged.
Closesstrongswan/strongswan#759
We still require these algorithms for e.g. EAP-MSCHAPv2, so the option is
enabled, by default. To use other providers (e.g. fips or even custom
ones), the option can be disabled and the providers to load/activate can
be configured in openssl.cnf. For instance, the following has the same
effect as enabling the option:
openssl_conf = openssl_init
[openssl_init]
providers = providers
[providers]
default = activate
legacy = activate
[activate]
activate = yes
Improves handling failures during unit tests of libtls and includes a
change for the openssl plugin so it only announces ECDH groups for which
the library provides the required ECC curve.
Closesstrongswan/strongswan#752
Determined by whether the library provides curves for it or not.
For instance, in the OpenSSL 3 FIPS provider the Brainpool curves are
not included. And in the Fedora package several weak curves are
explicitly patched out and the Brainpool curves are omitted even in
non-FIPS mode.
In particular as server, the previous code might cause it to hang in
recv() if this case wasn't triggered by a close notify (followed by a
shutdown of the socket) but it e.g. failed processing a ServerHello and
responded with a fatal alert.
Fixes: 09fbaad6bd ("tls-socket: Don't fail reading if sending data failed")
This is useful for kernel implementations where the ordering of SAs
is unpredictable and the new SA might otherwise not be used until the
DELETE response has been received, which is not ideal as the responder
might not keep the old SA around that long. On Linux, it makes no
difference as we switch to the new outbound SA immediately because the
updated outbound policy references its SPI.
Use a Debian-based Docker container to run the unit tests for charon-tkm,
once without and once with TKM running. The container can also be used
locally to run the tests (see comments in the Dockerfile).
This way we can run many unit tests without having to run the TKM in the
background and as regular user. To run the other tests, TESTS_TKM can
optionally be defined when running `make check`.
The default MTU of 1500 is too high if kernel-libipsec is used (considering
the overhead of UDP-encapsulated ESP), but might also have an effect if
a TUN device is only used to install a virtual IP (the route points to it,
so the system might use its MTU and 1500 would still be too high).
This also works around an issue on macOS 12 where no RTM_IFINFO event
is sent for the newly created TUN device (neither for the creation,
setting it "up", nor adding the address). Changing the MTU, however,
triggers such an event and we can detect the virtual IP.
Closesstrongswan/strongswan#707