When sending a TS_UNACCEPTABLE notify, a ALERT_TS_MISMATCH is sent, but
not when receiving one. This seems inconsistent compared to proposal
mismatch handling, so extend the child_create task to raise such an alert.
The bus alert infrastructure is currently exposed through the error-notify
plugin using a dedicated socket using a rather archaic message format.
Vici clients would need a dedicated socket connection just to receive such
alert messages, making their implementation more complex.
With vici, it is rather trivial to expose bus alerts through a dedicated
event message that vici clients may subscribe to. Add such an "alert"
event type to vici. Alert names are mapped to strings for simple consumption by
clients.
For now, the error-notify string message is omitted from events, as it mostly
contains static information without much value; instead add the IKE_SA details
for alerts associated to an IKE_SA. Other alert specific data may be added in
the future if needed; preferably using a structured format instead of the
arbitrary string messages used by error-notify. To allow future extensions,
wrap IKE_SA details under a dedicated "ike-sa" property.
The Homebrew formula has been using OpenSSL 3 for a while. The eap-peap
and pkcs11 plugins also have been enabled in the formula. The dhcp plugin
is enabled to test the port (the farp plugin was already enabled since
its port to FreeBSD/macOS). The drbg plugin is enabled to run the ML-KEM
test vectors.
While macos-13 was running on Intel, both macos-latest (macOS 15) and
macos-14 run on ARM64. While there are Intel-based images for 14 and 15,
they will only be available until August 2027 (and there aren't any Intel
devices anymore anyway).
This fixes GUI-related compatibility issues with Android 16 and allows
(pre-)selecting on-device certificates/keys with managed profiles. Also
fixes a typo in the managed config description that prevented
split-tunneling settings from working.
This allows associating a pre-installed certificate/key with a VPN
profile. For instance, one locally generated on the device via
SCEP/ETS by the MDM. It only works if the app is granted access to the
certificate/key (alias) by the MDM.
For now, users may still select a different certificate if one is
available (since this requires the certificate to be installed as
user-selectable there might not be).
Seems to not get pulled in automatically anymore. This has actually been
deprecated for years apparently. Unfortunately, it's not that easy to
replace, so keep it for now.
When targeting Android 15, edge-to-edge is the default and when targeting
Android 16, apps can't opt-out from this anymore. So we update our views
and enable edge-to-edge also for older versions (avoids the black bar
behind the system UI at the bottom). For most views we just use automatic
margins via android:fitsSystemWindows (or programmatically via
setDecorFitsSystemWindows). However, for the profile lists and log views,
we take some extra measures that allow the lists to go behind the bottom
system UI. Appropriate padding is applied at the bottom of the lists so
the last item(s) can be scrolled into full view.
No part of IKE/IPsec or X.509 uses MD2 anymore, so there really is no
reason to still support it (unlike MD4 that is used in EAP-MSCHAPv2,
MD5 that's used in EAP-MD5, or SHA-1 that's used for e.g. NAT-D hashes).
It caused test vectors to fail on systems where OpenSSL is built with
MD2 support but has it disabled at runtime.
Seems that there is a delay before the disk can be used when using newer
QEMU versions (e.g. on Debian trixie). We get errors like these:
sfdisk: cannot open /dev/nbd0: Inappropriate ioctl for device
or
mount: /srv/strongswan-testing/build/loop: special device /dev/nbd0p1 does not exist.
A sleep before the next command seems to help.
Also see [1].
[1] https://gitlab.com/qemu-project/qemu/-/issues/1413
This new option allows to disable leak detective to reduce the runtime
during development. Either only for the command line (swanctl, pki etc.)
or optionally also for the daemon(s).
Disabling leak detective only for the CLI tools already brings a
considerable reduction in runtime (from 48m to 38m on my dev host) as
there are many such calls in the post-test stage. Any leaks in those
tools are also a lot less of an issue than leaks in the daemon. So using
this during development should be fine as long as a full test run is done
regularly (in particular before releases). Disabling leak detective
completely further reduces the runtime (to 30m on my dev host). But that
should probably only be used for functional regression tests after
verifying new code didn't introduce new leaks.
This also fixes the service script which is used for charon-tkm since
16fcdb460afd ("charon-tkm: Don't use starter/stroke with charon-tkm anymore").
While some increase was necessary anyway because the idle system requires
about 5-10 MiB more memory, the main issue is resolving the code line and
function name in case of a memory leak. Calling addr2line requires a lot
more memory than before. Using backtraces via libbfd doesn't help either
because the trigger is the bfd_find_nearest_line() call we use as well.
And because we'd try to resolve all symbols that way (for whitelisting),
the memory overhead would be even higher and affect every shutdown, even
if no leak occurred. It also causes a significant time overhead (running
all tests took 75m instead of 48m).
I also tested switching to ASAN/LSAN. The peak memory usage is slightly
higher than when using libbfd, but enabling it also increased the runtime
overhead a lot (the daemon and swanctl both required about 10-20 MiB more
memory, not just during the shutdown).
Update revision for some dependency updates. While python3-setuptools is
installed on the system, the venv apparently can't use it. legacy-cgi is
required to use that old Django version with newer Python releases.
The API for libgmpada has change with 1.6 in a way that's not
backwards-compatible. So we use a different revision that includes
the required changes depending on the Debian version.
This also adds support for esa_select(), to support seamless rekeyings,
which requires updating xfrm-ada as well.
apt-key add is deprecated (and not available in trixie) as it makes the
available for all sources. The recommended approach makes the key very
specifically available for just our repository.
Debian trixie doesn't provide a 99-sysctl.conf symlink in that directory
anymore. The memory settings are also useful there as the default of
one changed and overbooking helps when forking a process with large
memory footprint (e.g. the IKE daemon).
While host_create_from_string_and_family() usually replaces %any*
keywords, this fails if the address family doesn't match (e.g. %any4 with
AF_INET6). There is no point in trying to resolve these keywords via
DNS as % is no valid character for host names.
Closesstrongswan/strongswan#2880
This adds a symbol with the current version number to all existing
plugins (the PLUGIN_DEFINE() macro makes this easy). The version is
checked when a plugin is loaded from a file in order to prevent loading
old plugins from any previous build, which could cause all sorts of
issues.
References strongswan/strongswan#2835
This prevents loading plugins from older builds that can cause all sorts
of issues as they might access struct members in different locations.
We don't check the version for statically linked plugins.
When built with static plugins and constructors, we might still want to
be able to load external plugins.
Fixes: d860c26e9533 ("plugin-loader: Properly support compilation without dlopen()/dlsym() etc.")
If an uncompressed point is already unwrapped (incorrect but some tokens/
modules do this) and therefore still looks like an ASN.1 octet string,
there could be false positives with the previous checks that lead to
mangled points.
By ensuring that we unwrapped the complete ASN.1 chunk, we can already
reduce the false positive rate when the assumed length is smaller than
the chunk, which we previously accepted but isn't the case in correctly
encoded points.
And while we already checked that the first byte indicates a valid point
type/encoding, there could still be false positives. We can avoid those
with some checks on the length of the unwrapped point. In particular,
enforcing a multiple of 4/8 should fail for valid unwrapped points where
three bytes were removed in the process (ASN.1 tag and length, point
encoding).
Closesstrongswan/strongswan#2872
If an entry is added while we wait for a checked out SA in flush() (e.g.
due to an action performed by that SA), new entries might get inserted
before the one we wait for. If that was the first entry in the row, we
didn't correctly update the table and the new entries were basically lost
by overwriting the first entry in the row. As the SA count was still
increased but the new entries couldn't get enumerated, the daemon wasn't
terminated properly but was stuck in the loop in flush().
We keep MD5 enabled for now as we need it for TLS 1.0/1.1. Once we
remove that we can reconsider (although, it's also needed for EAP-MD5
and since MD4 is disabled as well, which means EAP-MSCHAPv2 won't
be available, we'd be left with only EAP-GTC for simple username/password
authentication, which nobody else supports).
This will allow us to compare new library versions against previous ones,
so we don't suddenly loose some algorithms like it happened with KDFs
recently after updating OpenSSL to 3.5.1.
If a unit test times out while generating a private key (e.g. because of
a lack of entropy), this avoids a deadlock by still releasing the read
lock that'd prevent acquiring the write lock when plugins are unloaded.
Closesstrongswan/strongswan#2850
Was apparently forgotten when support was added to the attr plugin
with 98a3ba8a5a16 ("attr: Add p-cscf keyword for P-CSCF server addresses").
For consistency, using an underscore like the `split*` options and not a
dash like in the attr plugin.
References strongswan/strongswan#2396
Apparently, some clients (e.g. native Android) just send an empty
EAP-Identity response. We silently ignored that previously and then
used the IKE identity for the actual EAP method. This change tries to
do something similar (i.e. don't fail if the response is empty), but by
assuming the IKE identity as EAP-Identity, we match that and possibly
can switch configs.
Closesstrongswan/strongswan#2833
Fixes: 2f2e4abe3c52 ("ikev2: Add support to switch peer configs based on EAP-Identities")
Avoid generating versioned shared objects which would need to be
installed along with the version-independent symlink by specifying
"-avoid-version" in the libtool LDFLAGS for the plugin. Avoid any
unwanted surprises by also specifying the "-module" option, making the
LDFLAGS consistent with all other libstrongswan plugins.
Closesstrongswan/strongswan#2844
Use watcher and non-blocking I/O for client connections to avoid issues
with clients that stay connected for a long time.
Closesstrongswan/strongswan#2827
This now adds some state (basically a message buffer), but simplifies
error handling as we don't have to handle two potential failure paths
and could avoid some potential issues by still calling the blocking
read_all().
It also fixes a memory leak when clients disconnect.
Performing a stream read_all call (which is a blocking read) from
within the accept callback has the issue that if a whitelist client is
still connected whilst a shutdown of the charon deamon is triggered
then that shutdown won't complete gracefully due to the accept task
never exiting.
So fix shutting down gracefully by using the socket watcher rather than
a blocking read upon connection accept. Fall back to a blocking read
for partial messages to avoid the complexity associated (i.e. storing
state) for incomplete reads, which shouldn't block and cause the
original problem if the client only sends whole messages.
With a long delay, the retransmit might not get sent before further tests
are evaluated on faster machines, while more retransmits should still allow
the scenario to succeed on slower ones.
Setting the salt to NULL now fails, so we set it to hash length's zeroes,
which is the default value for HKDF-Extract if no salt is passed.
Fixesstrongswan/strongswan#2828
This copies the AC_SEARCH_LIBS check from the main strongSwan
configure.ac.
When building networkmanager-strongswan with slibtool if fails.
ld: cannot find none: No such file or directory
ld: cannot find required: No such file or directory
This is because configure.ac uses AC_SEARCH_LIBS to find dlopen which
sets the value of $ac_cv_search_dlopen to 'none required' which then
gets set in DL_LIBS and passed to slibtool.
With GNU libtool it silently ignores the unknown arguments.
Gentoo issue: https://bugs.gentoo.org/914100Closesstrongswan/strongswan#2141
Signed-off-by: orbea <orbea@riseup.net>
Also removed on Play so the app does not show up when people search
for these keywords (they tend to not read the actual description and
then are surprised that neither protocol is supported).
We now support OpenSSL's implementation in the openssl plugin. This
makes sure our plugin is used on at least one of the hosts if we ever
switch to an OpenSSL version that supports ML-KEM.
In the ikev2/rw-mlkem scenario the logic is reversed. There the ml plugin
is preferred on moon to test the responder side (and carol for the
initiator) and dave will switch to OpenSSL if it ever provides ML-KEM.
As mentioned in 0f141fb095a41a9fdfe5c111269eb643dc643494, we can't
really whitelist the "leaks" in GLib, so don't even try to do anything
with libsoup3.x.
Wrap the functions that require it in PRIVATE_KEY_UNLOCK/PRIVATE_KEY_LOCK.
This can't be done at plugin initialization because it needs to be done
for every thread. strongSwan currently doesn't provide on-thread-create
callbacks for plugins so we need to wrap each direct call. Another reason
to do so is that some functions we call (e.g. wc_EccKeyToDer) internally
call PRIVATE_KEY_UNLOCK/PRIVATE_KEY_LOCK and would leave the keys locked
for that particular thread.
Some implementations enforce a minimum key size (e.g. wolfSSL in FIPS
mode) and in practice, the keys will be longer anyway (e.g. our nonces
are 32 bytes).
This adds basic support for IP-TFS/AGGFRAG (RFC 9347). The Linux kernel,
since 6.14, only supports aggregation/fragmentation so far. The actual
TFS features will get added later.
Tests transport mode and UDP encapsulation with random source ports.
Interestingly, the responder always uses the same SA to respond (maybe
due to the cache on the policy).
As we set the remote port to 0, we'd get a mapping change message with
every packet. Setting the threshold avoids all kernel messages after the
first, which we suppress explicitly as well.
This might make debugging easier and also ensures that a possible
fallback SA without CPU ID is established first when reestablishing
an IKE_SA. Because even if such an SA is established first initially,
that might change later depending on when per-CPU SAs are rekeyed.
Not sure if this combination does make sense as the plugin itself would
be a major bottleneck.
Similar to the connmark plugin, PREROUTING rules list SPIs or UDP ports,
which would be necessary for all SAs while the OUTPUT rules would only be
required once.
The combination probably doesn't make much sense.
The OUTPUT rules would definitely only be required once, while the INPUT
and PREROUTING rules list individual SPIs and/or UDP ports, which would
be necessary for all SAs.
By the way, the rules in PREROUTING might actually not be necessary
anymore if the set_mark_in option was used for such SAs.
This uses the sequence number from acquires when installing the SA. This
allows handling narrowing properly by changing the reqid and still
removing the temporary state in the kernel. It also changes that
traffic selectors are reused during rekeying/recreation/reauthentication,
so narrowed selectors won't return to the wider configured TS because
there won't be any TS from triggering packets to narrow again.
Besides the previous key exchange method, this will allow us to also
reuse the previous traffic selectors. Some data is still passed in
separate methods as some are set even when there is no previous SA and
others are not set in all cases.
The interface for queue_child() now optionally takes the previous
Child SA to handle both recreations and initiations from scratch.
This fixes cases where `start_action = trap|start` is used and an acquire
is triggered while the SA is initiated (granted if narrowing is expected,
that's not a recommended configuration as the responder can only use
the first config when there is no packet TS). The resulting second
create-child task will potentially get dropped by the duplicate check,
so the temporary state won't get removed and traffic is blocked until
that expires, neither can acquires get triggered for traffic that doesn't
match the initial SA's policies.
This was the case before bce0c5fd74a0 ("child-create: Update CHILD_SA IP
addresses before installation") and allows listeners to consider the
traffic selectors of the SA that's about to get installed.
The addresses are actually the endpoints of the SA, not information on
the matched packet (except that the RFC says to set the ports and
protocol of the packet in the source address, which the Linux kernel
doesn't do). So these are useless, unless transport mode is used, where
the addresses are needed for the wildcard trap policy use case.
The RFC mentions a PROXY address (a single one, not two), that could
apparently be something like the source address in tunnel mode.
However, the description of how this is used in the RFC is quite weird
and neither Linux nor FreeBSD send such an attribute in SADB_ACQUIRE.
Note that while PF_KEYv2 also uses sequence numbers to identify acquires,
which we currently don't use correctly by the way, it does not include
information about the packet that triggered an acquire. What we receive
in src and dst, and currently forward as traffic selectors, are actually
the designated endpoints of the SA. So especially in tunnel mode this is
useless to do narrowing on the responder (these addresses might not even
match the configured TS).
With the sequence numbers we don't have to maintain the reqid to delete
the temporary state.
One exception is with labels. There we currently only install trap
policies with the generic label. SAs created from those don't have
policies installed, so we have to reuse the reqid of the trap even if
narrowing occurs.
And as before, we reuse the reqid without checking traffic selectors if
sequence numbers are not supported.
Note that if a CHILD_SA is manually initiated (i.e. has no sequence
number assigned) right before an acquire is triggered, there are several
possible outcomes depending on whether narrowing occurs. If there is no
narrowing, the same reqid is assigned and the kernel will remove the
temporary SA when the SA is installed (no seq => reqid match).
Afterwards, the queued duplicate CHILD_SA is destroyed and the acquire
state in the trap manager gets removed. If there is narrowing, a new
reqid is allocated, so the installation of the SA will not remove the
temporary state. However, due to the narrowing, the duplicate check
fails and when the duplicate is installed (with sequence number), the
temporary state is deleted (as is the state in the trap manager).
Optionally with "dynamic" traffic selectors resolved. A new method
is added for those cases where we actually want to select potentially
narrowed traffic selectors using a supplied list. The latter now also
always logs details, while the former does not.
Either use the sequence number from the kernel (and potentially update
it if the acquire was retriggered), or generate our own sequence
numbers, which simplifies matching acquires to established/destroyed
CHILD_SAs.
When cross-compiling for Windows on Ubuntu, we don't have POSIX regular
expressions available (there does not seem to be any alternative libraries
either), but since the tests are not executed that's OK. On AppVeyor,
MSYS2 has libgnurx installed, which works fine but requires explicit
linking with `-lregex`.
This is loosely based on a patch by Thomas Egerer.
Threads initiating SAs can get stuck on the semaphore in
wait_for_listener() during shutdown if the corresponding job is never
executed. A particular case when this can happen is if more initiations
are triggered than worker threads are available. This causes a (known)
deadlock as no workers are free anymore to process jobs (for inbound
messages or timeouts etc.), including the one to initiate an SA.
This change at least allows a proper shutdown.
The plugin was apparently broken for years because it uses functions that
don't exist anymore. It was quite limited anyway, so it was never really
used in OpenWrt to begin with (instead they generate configs in a custom
init script).
The `crypt` functions defined here conflict with the `crypt` function
defined in `unistd.h` and trigger compilation errors when building
against the latest version of AWS-LC, which introduced a new transitive
include of `unistd.h` via `bio.h`.
This simply renames the function to avoid the error.
Closesstrongswan/strongswan#2786
A recent gettext release (0.25 via Homebrew) installs the M4 macros in a
different location (<prefix>/share/gettext/m4 instead of
<prefix>/share/aclocal). According to the commit messages to avoid "bad
interactions between autoreconf and autopoint". Since we only depend
on gettext for that macro and this move makes it complicated, we can also
just integrate the macro from gnulib directly (which gettext 0.18+ relies
on anyway).
This changes how EAP identities are used from the config. Instead of
setting a statically configured identity != %any, an EAP-Identity
exchange is now always initiated (and required). If the received identity
doesn't match, the peer config is switched to one with a matching
identity (wildcards are supported for that match). This allows switching
to a config with a different EAP method or child settings based on the
EAP identity.
There is currently no "best" match. The configs are evaluated based on
the order returned from the initial peer config lookup.
References strongswan/strongswan#2702
Newer NDKs have RISC-V as experimental ABI (not enabled by default, see
next commit). If we don't have a mapping for a specific target, OpenSSL
falls back to 'android-arm', so that won't really work (interestingly,
it does build).
These sockets are closed immediately again, so no need to re-protect them
during roaming events.
References strongswan/strongswan#1691
Fixes: 6d87a8651068 ("android: Use new sockets to determine source IP")
If this is not set, it looks like NM shuts down the VPN connection and
calls disconnect() if there is any connectivity change.
References strongswan/strongswan#2707
This enables GRO offload for inbound ESP-in-UDP packets if the
esp4|6_offload modules are loaded. Note that inbound ESP or ESP-in-UDP
packets won't be visible on layer 3 in Netfilter or tcpdump.
Increase buffer to 32 bytes to hold uint64_t completely and check for
overflows after multiplication with size modifiers.
Signed-off-by: Thomas Egerer <thomas.egerer@secunet.com>
This allows accepting clients that send proposals with non-optional KE
methods during rekeying, while still accepting clients that use the
previous non-KE default proposals.
This requires a new protocol version as private extensions would enable
unrelated regular extensions, even when sending the private extension
as second attribute (which would work for conditions as they are
explicitly enabled/disabled).
This was originally added with b0e40caafbd7 ("NAT-T conditions were not
inherited during IKE_SA rekeying") in 2008 when there was only a single
inherit() method. Later the inherit_pre() method was added and then
with 094963d1b160 ("ikev2: Apply extensions and conditions before
starting rekeying") in 2014 the extensions and conditions were set
already there.
This avoids conflicts with upstream changes if patched versions of
strongSwan require a number of private extensions and conditions. For
example, the following extensions can be used as usual via the
`enable|supports_extension()` methods:
#define PRIVATE_EXT_1 (EXT_PRIVATE_MARKER | (1<<0))
#define PRIVATE_EXT_2 (EXT_PRIVATE_MARKER | (1<<1))
Defining an enum would also be possible but because the type won't match
the values would have to be cast to `ike_extension_t` when using the
methods.
Similarly, `COND_PRIVATE_MARKER` may be used to define private conditions
that can be used with the `set|has_condition()` methods.
Because the MSB is explicitly not set in `private_extensions|conditions`,
these members may directly be checked against private values, e.g.:
if (this->private_extensions & PRIVATE_EXT_1)
{
}
If this is used, the functionality to set a private key/value/seed for
key exchange methods is removed (including from the interface to avoid
accidentally forgetting to wrap implementations and uses of set_seed()).
The set_seed() method is assigned outside the INIT() macro to avoid
potentially undefined behavior (preprocessing directives in macro
arguments).
The test done by the crypto tester is a simple functionality test.
So far, the timeout value was only used as connect timeout while a
malicious server could accept the connection and then starve us. So use
the timeout for LDAP_OPT_TIMEOUT, too, which affects all synchronous
calls. In particular, ldap_simple_bind_s(), which has no timeout
argument like ldap_search_st().
Signed-off-by: Thomas Egerer <thomas.egerer@secunet.com>
It seems that scp is sometimes very slow (unclear what causes it as it's
not always the same). Packing up the files with tar performs a lot
better in these situations. And copying the files to multiple hosts
in parallel additionally helps to reduce the time required for these
steps.
Using --overwrite and -h preserves existing symlinks (e.g. for the users
file in /etc/freeradius/3.0) and overwrites the target file instead.
The -m option ignores timestamps when extracting the files as some target
files will be newer than the source. Using -h when packing up files in
load-testconfig allows using symlinks in the test config dirs to files
on the host running the tests.
The file won't exist in the previous location until load-testconfig was
executed once. Since it's not modified by the script it's fine to
load it directly from the original location.
Fixes: a103f3a2849f ("testing: Add options to only run pre- or posttest scripts of a scenario")
The callbacks provided via ProcessLifecycleOwner are only triggered when
Activities are started. However, when Android triggers the Always-on
VPN it directly starts our VpnService subclass, no Activity. So the
configs were not loaded and the VPN couldn't be initiated with a managed
profile. This ensures the config is loaded right from the start of
the app. And by registering for modifications in onCreate() we can also
use the correct config if the app is never started in-between changes to
the managed profiles and triggering the Always-on VPN.
As described in the previous commit, GCC 15 uses C23 by default and that
changes the meaning of such argument-less function declarations. So
whenever we assign such a function to a pointer that expects a function
with arguments it causes an incompatible pointer type warning. We
could define dedicated functions/callbacks whenever necessary, but this
seems like the simpler approach for now (especially since most uses of
these functions have already been cast).
Besides being clearer, this fixes issues with GCC 15. The latter uses
C23 by default, which changes the meaning of function declarations
without parameters such as
bool return false();
Instead of "this function takes an unknown number of arguments", this
now equals (void), that is, "this function takes no arguments". So we
run into incompatible pointer type warnings all over when using such
functions. They could be cast to (void*) but this seems the cleaner
solution for this use case.
This allows to manually do some testing without having to type commands
to set up a scenario.
Also changes how arguments are parsed (allowing to pass options mixed
with test dirs) and adds some usage output.
This reverts commit f717bb5249caea550bc6e2baeb09ca309ad83b39.
Causes issues in our testing environment. Default route via host is
preferred if no gateway is set in the installed routes. Needs some
investigation.
References strongswan/strongswan#2548
If the client's network goes down for a while but the same IP address
is assigned later, it won't be aware if the server killed the IKE_SA
while it wasn't reachable. This way, a DPD is triggered and the client
can reestablish the SA if necessary. When roaming to a different IP,
a MOBIKE update is triggered with the same effect.
References strongswan/strongswan#2696
These have specific values for charon-nm's use case but might have to be
changed for special setups or because of conflicts.
References strongswan/strongswan#2683
Listeners can't track those IKE_SAs otherwise. For break-before-make
reauthentications, these events are already triggered because that is
implemented by calling reestablish() on the old IKE_SA.
When using port 4500 for IKE_SA_INIT, Windows Server 2016, 2025 and
possibly others send back all packets to the port initially used by the
client, not the one floated to before sending IKE_AUTH. So if UDP
encapsulation is used, no traffic can be received as the initial socket
can't have UDP decapsulation enabled.
tcpdump output:
```
IP <client-ip>.47547 > <server-ip>.4500: UDP-encap: ESP(spi=0xfd4e5fc2,seq=...)
IP <server-ip>.4500 > <client-ip>.57962: UDP-encap: ESP(spi=0xccc5e213,seq=...)
```
Avoid this by floating early if a non-default destination port is used.
This also ensures we don't send packets from port 500 (without non-ESP
marker) if ephemeral source ports are not used.
Closesstrongswan/strongswan#2664
Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
Co-authored-by: Tobias Brunner <tobias@strongswan.org>
Without UDP-encapsulation, the IKE and ESP traffic is not directly related
(other than via IPs), so firewalls might no keep the state for IKE traffic
alive if there is no IKE traffic for a while and constant ESP traffic
prevents DPDs from being exchanged because inbound ESP traffic is
considered.
Closesstrongswan/strongswan#1759
Using a specific address can be useful in scenarios where dynamic routing
could change the path to the RADIUS server and a changing source address
is a problem for the server.
Closesstrongswan/strongswan#2598
Adds support for multiple key exchanges to the ha plugin. Also,
because of the delayed key derivation and the not synced IntAuth
values, incomplete IKE_SAs are now destroyed during a failover.
Closesstrongswan/strongswan#2550
The node that gets activated usually won't be able to complete the
IKE_SA mainly because the IKE keys are now derived delayed, so the key
material required to process a message often won't be available (only
later IKE_AUTH messages and retransmits of earlier messages that the
active node already received and synced the keys for may be decrypted).
A second issue affects IKE_SAs with multiple key exchanges. Because the
IntAuth value(s) are currently not synced, which are necessary to
verify/create the AUTH payloads, the IKE_AUTH exchange couldn't be
completed.
Synchronization for the additional transforms in the IKE and Child SA
proposals is added. Details of the IKE_SA synchronization are changed
to support IKE_INTERMEDIATE exchanges that cause multiple HA_IKE_ADD
messages and key derivations. The cache has been extended to handle
multiple such messages.
Co-authored-by: Thomas Egerer <thomas.egerer@secunet.com>
This doesn't really seem useful (perhaps it was before we started to
configure the outbound interface on our routes). And it can actually
cause the route installation to fail e.g. for routes over point-to-point
interfaces where we'd get "Error: Nexthop has invalid gateway" errors.
Closesstrongswan/strongswan#2548
Currently, the runner images enable break-system-packages globally.
However, this workaround will be removed by the end of March. So
we switch to installing these packages as intended via distro (the
alternative would be to use pipx, at least for tox).
Fixes issues with reauthentication, in particular, to reestablish the
SA if MOBIKE is disabled. The app currently can't handle
make-before-break reauthentication. In part because necessary events are
currently not triggered. So for now, we switch back to the classic
reauthentication approach.
The service implementation with its handling of reauth callbacks and
no-DNS TUN device etc. can't handle make-before-break reauthentication
at the moment.
There was an issue with OPENSSL_armcap_P in Android's static build for
OpenSSL 3.1.1+. This was finally fixed with this release (and was also
backported to older versions).
Unspecified settings should be set to null, while some MDMs might send
them as empty strings, which could cause issues (like an empty password
or trying to parse an empty DNS server address).
This can happen with empty strings, which might be set for managed
profiles, which caused the refcounting to be askew and the resolver not
to work after connecting once because it was flushed and disabled.
This fixes a regression introduced with pf_handler_t in 5.9.14. It also
binds the packet sockets correctly to the configured interface, and adds
an option for the dhcp plugin that allows binding the send and receive
sockets to different interfaces.
This can be useful if the DHCP server runs on the same server. On Linux,
the response is then sent via `lo`, so packets won't be received if both
sockets are bound to e.g. a bridge interface.
In some setups the responses from the DHCP server are sent via lo, which
does not have an address of type `ARPHRD_ETHER` (the address length is
the same, though, just all zeros, by default). Note that the dhcp plugin
doesn't actually care for the MAC address or interface details, that's
only used by the farp plugin.
Fixes: 187c72d1afdc ("dhcp: Port the plugin to FreeBSD/macOS")
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
Also enables the `kdf` plugin automatically if building against an older
version of OpenSSL.
Closesstrongswan/strongswan#2602
Co-authored-by: Tobias Brunner <tobias@strongswan.org>
This avoids the following warning/error:
tnc_imv_manager.c:244:39: error: passing arguments to 'tnc_imv_recommendations_create' without a prototype is deprecated in all versions of C and is not supported in C23 [-Werror,-Wdeprecated-non-prototype]
244 | return tnc_imv_recommendations_create(this->imvs);
| ^
Useless and causes a compiler warning/error:
error: a function declaration without a prototype is deprecated in all versions of C and is treated as a zero-parameter prototype in C23, conflicting with a subsequent declaration [-Werror,-Wdeprecated-non-prototype]
The lines in the gperf-generated proposal_keywords_static.c are now
mapped to the (much shorter) .txt source file, which causes mismatches
like these:
genhtml: ERROR: no data for line:190, TLA:GNC, file:/home/runner/work/strongswan/strongswan/src/libstrongswan/crypto/proposal/proposal_keywords_static.txt
We could ignore "unmapped" errors in genhtml, but since the file is
generated anyway, we can also exclude it from the results and still
get such errors in case this happens for other files. Another alternative
would be to remove the `#line` macros in the generated file. Then the
coverage of the actual C file would get reported (but again, it's
generated, so there isn't much value in it).
Also updated the branch coverage option as the one with `lcov_` prefix
is deprecated.
On Ubuntu 24.04, llvm-symbolizer-18, which is used to resolve symbols
in backtraces, links libcurl.so.4 for some reason. And that in turn
requires SRP. If our custom build doesn't provide it, we get stuff
like this
/usr/bin/llvm-symbolizer-18: symbol lookup error: /lib/x86_64-linux-gnu/libcurl.so.4: undefined symbol: SSL_CTX_set_srp_password, version OPENSSL_3.0.0
and the symbols are not resolved and can't be whitelisted.
This also makes sure ASan is actually disabled if our own leak-detective
is used.
Self-signed trust anchors are not part of the certificate path validation
according to RFC 8280, section 6.1:
When the trust anchor is provided in the form of a self-signed
certificate, this self-signed certificate is not included as part of
the prospective certification path.
But policies in them could still be used, as stated in section 6.2:
Where a CA distributes self-signed certificates to specify trust
anchor information, certificate extensions can be used to specify
recommended inputs to path validation. For example, a policy
constraints extension could be included in the self-signed
certificate to indicate that paths beginning with this trust anchor
should be trusted only for the specified policies. [...]
Implementations that use self-signed certificates to specify trust
anchor information are free to process or ignore such information.
So unconditionally enforcing that self-signed root certificates contain
the policies is probably too strict. Often they won't contain the
extension at all. With this change, we allow that but still enforce the
policies in case such a certificate contains them. The other
policy-related constraints are also enforced still should they be
contained.
Closesstrongswan/strongswan#2601
Some scenarios disable route installation and if they are executed before
any scenarios that don't, there won't be a rule for table 220 and we get
"FIB table does not exist" errors.
Directly calling setup.py is deprecated (apparently has been for a while,
but now we get large warnings). Direct installation is also discouraged.
So this removes that option. The built wheel (the old egg format is not
used/built anymore) can be installed manually in a venv or the like.
The previous approach had two drawbacks:
First, it caused duplicate public keys because when the `certificate_t`
object was created and added to the credential set it had no subject
assigned yet. So it defaulted to the key ID. However, all previously
loaded keys had their subject already changed to an identity, so there
never was a match and new objects were always added whenever a config
with raw public keys was loaded.
Second, the subject was replaced in a way that's not thread-safe on an
object that's already shared in the public credential set. So other
threads could potentially access the `identification_t` object that's
destroyed during that process.
References strongswan/strongswan#853Closesstrongswan/strongswan#2561
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: f9b895b49f49 ("child-create: Add support to handle security labels")
There are a lot of files without patterns and running them all through
sed is quite slow. Using grep first makes this quicker (about 0.5s per
test). Ignoring PEM files is also helpful.
In particular the swanctl calls all take a while and this allows doing
them in parallel if multiple hosts are involved. This reduces the runtime
of each test by 1-3 seconds.
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>
If the lifetime of an issuing or sub CA is twice the lifetime of
the end entity certificates issued by it and the renewal cycle of
the issuing CAs is a little shorter than the validity of the end
entity certificates then three generations of CA certificates have
to be handled by the cert-enroll scripts.
These have been discouraged for a long time and there are now more and
more crypto libraries that have them disabled by default. However, for
some we only can detect this at runtime, in particular in FIPS mode, so
tests would fail as the plugins would still announce them. So instead
we just remove the schemes from these tests for now (at least for RSA,
removing signatures with SHA-1 completely isn't an option yet as that's
still the default with some clients).
Closesstrongswan/strongswan#2523
In particular for the first one randomization could trigger an additional
rekeying, which let the "Adding ESA ..." check fail. But even without
randomization (could be seen in the second scenario that already uses
`rand_time=0`) 4 seconds can apparently be too low some time.
When compiling with -O3 with GCC 14, we get the following warning/error:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:29:10: error: '__builtin_memcpy' offset [0, 3] is out of the bounds [0, 0] [-Werror=array-bounds=]
29 | return __builtin___memcpy_chk (__dest, __src, __len,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30 | __glibc_objsize0 (__dest));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
Which seems completely bogus as that array has a fixed size of 16 and
some weird workarounds remove the warning (e.g. adding an assignment
to `subset->netbits` before the `memcpy()`). This is also the only
place GCC complains about and we use `memcpy()` all over the place
in this file to set those addresses.
Closesstrongswan/strongswan#2509
While this does require quite a bit of memory, on initiators there are
usually fewer concurrent SAs getting created so this should be less of
an issue than on a gateway that handles lots of SAs as responder.
The speed up is about 30% on the initiator during the decapsulation,
while the key generation does take a bit more time (about 3%).
This follows FIPS 203 relatively closely but takes some ideas from the
reference implementation. In particular, how to avoid potential
side-channels via direct C division/modulo operations. However, it just
uses Barrett reduction (no Montgomery reduction) and no negative
coefficients to avoid number format conversions and keep the
implementation clearer.
This registers support for the ML_KEM_{512,768,1024} key exchange
algorithms in the `openssl` plugin when built using AWS-LC as the
libcrypto. To do this, we introduce the `openssl_kem` source files
which implement the key exchange algorithm using the Key Encapsulation
Mechanism (KEM) API. Future KEM algorithms can be implemented
generically using this interface by substituting the appropriate NIDs.
It also supports both seeded (via DRBG) and unseeded modes depending
on the user's requirements for KATs or entropy sources.
It should be noted that this does not add support for KEM algorithms
within upstream OpenSSL and is API incompatible. Future work will need
to condition out the incompatibilities as-appropriate. However, the
high-level logic should be the same for all KEMs and KEM APIs.
References strongswan/strongswan#2228Closesstrongswan/strongswan#2490
Both Diffie-Hellman (DH) and Key Encapsulation Mechanism (KEM) based
key exchange methods use a common ke_test_vector format. The
set_seed() function is used to provide deterministic private key
material for the crypto tests.
If uniqueness checks are disabled and multiple IKE_SAs with the same
identities are created, an offline lease could have gotten reassigned
during a make-before-break reauthentication if such an SA was closed
earlier. Checking for an online lease for the same client (IP/port)
first ensures that the correct IP is reassigned during the
reauthentication.
References strongswan/strongswan#2472
Since we now open sockets for each address family independently (via
IPV6_V6ONLY) and without SO_REUSEADDR, it could happen with the previous
order on Linux that opening the port that was allocated as ephemeral
port for IPv6 was already used by a different process for IPv4.
Most IPv6 sockets on ephemeral ports will not have IPV6_V6ONLY set, so
the same port is also reserved for IPv4. Therefore, it's save to assume
that any ephemeral port we first get for IPv4 is free for IPv6.
References strongswan/strongswan#2494
This reverts commit 84a3077e780e7b25bf536da42a583bdc18448362.
Support for dots in names of settings was removed quite a while ago and
now the \. sequence caused `SyntaxWarning: invalid escape sequence`.
The order was different when not setting `esp_proposals` or explicitly
configuring `default`.
Fixes: 33412158f58c ("ike: Send AEAD ESP default proposal first")
Similar to the previous commit. Instead of
generating rule 10 (1258)
followed by (or not if the list is empty)
generating payload of type PROPOSAL_SUBSTRUCTURE
we now get
generating rule 10 LIST of PROPOSAL_SUBSTRUCTURE
in the debug log.
Instead of this
parsing rule 10 (1258)
we now see this
parsing rule 10 LIST of PROPOSAL_SUBSTRUCTURE
in the debug log. Particularly useful if the list is empty as there won't
be a message like this following it:
x bytes left, parsing recursively PROPOSAL_SUBSTRUCTURE
struct ifreq can't be used for IPv6 as the ifr_addr member is not large
enough. Actually, configuring an IPv6 address via an AF_INET socket won't
work anyway. And unfortunately, it's not standardized how IPv6 addresses
are installed, so we have to do this quite differently on Linux and on BSD.
However, we already use SIOCAIFADDR for IPv4 on newer FreeBSD systems,
which wasn't the case when this patch was originally created in 2014.
Consider queued child-creating tasks when reloading configs that have
`start` as start action. Besides some possible corner cases it fixes
handling IKE_SAs that are current getting established and have no
established CHILD_SAs yet.
Closesstrongswan/strongswan#2418
This is particularly important for IKE_SAs that are not yet established,
which would get terminated as they have no established CHILD_SAs yet.
Fixes: 72f9a21b22e9 ("Merge branch 'vici-reload-actions'")
The behavior of realloc(3) with zero size was apparently implementation
defined. While glibc documents the behavior as equivalent to free(3),
that might not apply to other C libraries. With C17, this behavior has
been deprecated, and with C23, the behavior is now undefined. It's also
why valgrind warns about this use.
Hence, when array_compress() would call realloc() with a zero size, we
now call free() explicitly and set the pointer to NULL.
Signed-off-by: Thomas Egerer <thomas.egerer@secunet.com>
Otherwise, all configs would be considered to even some degree as the
ports usually match.
Closesstrongswan/strongswan#2441
Fixes: 9228a5109b8d ("ike-cfg: Consider port information in IKE config match")
This adds support for multiple key exchanges (no KEMs yet as none are
standardized so far). Work on this started over five years ago and went
through multiple iterations (first our own protocol, then standardized
extensions in different variations).
IKE_INTERMEDIATE exchanges, defined RFC 9242, are used to transport
multiple KE payloads between the IKE_SA_INIT and IKE_AUTH exchanges.
To rekey IKE and CHILD_SAs with multiple key exchanges, IKE_FOLLOWUP_KE
exchanges are used, as defined in RFC 9370.
In proposals, additional key exchange methods are configured via `keX_`
prefix, where X is a number between 1 and 7. For example, `ke1_ecp256`
adds ECP_256 as additional KE method. As with regular key exchanges,
peers have to agree on a method for each round unless no algorithms are
defined by both or `keX_none` is configured to make that round explicitly
optional.
Also changed is how rekey collisions are handled, which makes CHILD_SAs
properly trackable via child_rekey() hook.
Previously, it could happen that child_rekey() was triggered twice for
the same "old" SA. For listeners that would mean they'd loose track as
they'd be tracking a new SA that wasn't relevant anymore and for which
no updown event would ever get triggered (it was the redundant SA in a
collision). This new assert ensures that events are triggered in a
predictable way and listeners can track SAs properly.
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 kernel now allows a 0 replay window with ESN for SAs that are
explicitly tagged as outbound SAs. But not just that, it actually
rejects outbound SAs with replay windows > 0. So we add a version check
to control the replay window size. Note that adding the attribute
unconditionally would be fine even for older kernels, but if somebody
backports the direction patches, the installation of outbound SAs might
fail if the replay window is not adjusted accordingly.
When targeting Android 14, we get a "Background activity launch blocked!"
exception when trying to start the connection in the background (closing
the drawer works). Which is apparently a bug:
https://issuetracker.google.com/issues/305035828
The workaround here is kinda ugly. In particular, because it's not
possible anymore since a few versions to open a dialog that allows users
to directly grant the required permission to the app. We can only open
the generic settings dialog where users have to search for the app and
grant the permission themselves (we could add a dialog with an explanation
similar to the one for the power whitelist if necessary). Hopefully this
gets fixed at some point (the current beta of Android 15 still has the
same bug, though).
If no other units have dependencies on network-online.target or
syslog.target they might not get initialized resulting in a possibly
non-ideal startup order.
Closesstrongswan/strongswan#2279
This improves the behavior when reloading or unloading connections that
have `start` included in their `start_actiton`.
Closesstrongswan/strongswan#2324
The previous code had some issues because it handled each child config
separately. Not only was this quite inefficient because all IKE_SAs had
to be enumerated for every config, it also caused problems with the check
for other CHILD_SAs in order to decide whether to delete the IKE_SA or
not. Because CHILD_SAs are deleted with an INFORMATIONAL exchange, they
are not immediately gone. This caused a race condition and with more
than one child config and SAs the IKE_SA could be kept because it
could appear as if other, unrelated CHILD_SAs were still there.
Another race condition, which is fixed by the previous commit, occurred
when only changing child configs. Then it could happen that the code
deemed the IKE_SA empty and a delete for it was queued. If that happened
while the IKE_SA was deleting one of the CHILD_SAs (or was busy with some
other exchange), the IKE_SA was not switched to IKE_DELETING. So it
looked usable and create-child tasks for the updated configs might have
gotten queued. Unfortunately, once the ike-delete task is eventually
executed, these tasks would be gone and the replacement CHILD_SAs never
created. This commit additionally avoids actually deleting the IKE_SA
even if all child configs change or get removed if any new CHILD_SAs are
to be initiated.
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.
The empty array of rules for `assert_message_empty()` and the resulting
size 0 triggers warnings like these:
allocation of insufficient size '0' for type 'listener_message_rule_t' with size '12'
Using calloc() with `nmemb` set to 0 triggers the same warning.
The number of elements is the first argument, their size the second.
The previous code triggered the following warning:
'calloc' sizes specified with 'sizeof' in the earlier argument and not in the later argument
Looks like a cipher suite without DHE was selected previously.
Could be a side-effect of dc1085734f34 ("testing: Remove unnecessary
FreeRADIUS dh_file option as recommended in the log").
Errors in load-testconfig are hidden due to not checking scp
return code and mute all errors. Add -e to trap script on
any errors in this script.
References strongswan/strongswan#2310
Signed-off-by: Maxim Uvarov <muvarov@gmail.com>
OpenSSH defaults have changed and scp stopped to work with newer versions.
There are 2 options to fix it, either use -O (legacy scp protocol)
with scp, or enable the sftp subsystem in the SSH server config.
This fix uses the second variant.
Closesstrongswan/strongswan#2310
Signed-off-by: Maxim Uvarov <muvarov@gmail.com>
Instead of just adding the offset internally, this way the reported
base address is always the first assignable address (e.g. for
192.168.0.0/24 vs. 192.168.0.1/24).
Closesstrongswan/strongswan#2264
If the regular daemon is running, it creates an unconditional routing
rule for the routing table. The rule that charon-nm tries to create,
which excludes marked IKE/ESP traffic to avoid a routing loop, then
can't be installed and we'd end up with said loop.
Closesstrongswan/strongswan#2230
As recommended by RFC 2985, section 5.4.1:
ChallengePassword attribute values generated in accordance with this
version of this document SHOULD use the PrintableString encoding
whenever possible. If internationalization issues make this
impossible, the UTF8String alternative SHOULD be used.
Even though the RFC continues with
PKCS #9-attribute processing systems MUST be able to recognize and
process all string types in DirectoryString values.
there might be older SCEP server implementations that don't accept
UTF8String-encoded passwords. In particular because previous versions of
PKCS#9 defined this attribute's type as a CHOICE between PrintableString
and T61String.
References strongswan/strongswan#1831
Can be useful if the CID inside the VM is not known.
The \htmlonly\endhtmlonly hack is used to avoid compiler warnings due
to /* inside a block comment.
These allow, for instance, a vici client on a host to communicate with
an IKE daemon running in a VM.
Signed-off-by: Thomas Egerer <thomas.egerer@secunet.com>
If somebody copies our .gitignore and tries to import the source code,
the proposal_keywords.c file will not be added as it's ignored by the
`*keywords.c` pattern we use to ignore gperf-generated source files.
Closesstrongswan/strongswan#2014
If a base address is configured, we don't expect the pool to be empty,
so reject the creation (e.g. with the broadcast address as base).
References strongswan/strongswan#2205
We explicitly pass the final .info file prepared with lcov, so there is
no need to search for other files (that then won't work anyway). The
search also finds the uncleaned .info file, which includes the test code.
The latter should have gotten ignored anyway, but the patterns are
apparently not correct anymore. So fixing that as well just to be sure.
There are definitions of RNG in <wolfssl/wolfcrypt/settings.h> and
<wolfssl/wolfcrypt/random.h> that play havoc with the literal RNG being
used in the expansions of PLUGIN_*(RNG, ...) when ##-concatenated to
build the enum value FEATURE_RNG.
The #undef in wolfssl_cmmon.h only had an effect if wolfSSL was built
with EdDSA or FIPS enabled, otherwise, the headers that define RNG were
not pulled in before it.
Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
This is a patch from the OpenWrt package sources necessary to adapt to
changes from 2008 that abstracted the option datatype (added a list
type).
Signed-off-by: Noel Kuntze <noel.kuntze@thermi.consulting>
Reviewed-by: Philip Prindeville <philipp@redfish-solutions.com>
With GCC 13, the compiler apparently applies new aliasing optimizations
when compiled with -O2 and without -fno-strict-aliasing. This caused
the application of the second padding bit, where the state was accessed
via uint8_t[], to be moved before the loop that absorbs the buffer into
the state, where the state is accessed via uint64_t[], resulting in
incorrect output. By only accessing the state via uint64_t[] here the
compiler won't reorder the instructions.
musl's headers define a lot of networking structs. For some, the
definition in the Linux UAPI headers is then suppressed by e.g.
__UAPI_DEF_ETHHDR.
Since we included musl's net/ethernet.h, which includes netinet/if_ether.h
that defines `struct ethhdr` (and the above constant), **after** we
include linux/if_ether.h, there was a compilation error because the
struct was defined multiple times.
However, simply moving that include doesn't fix the problem because for
ARP-specific structs the Linux headers don't provide __UAPI_DEF* checks.
So instead of directly including the linux/ headers, we include those
provided by the C library. For glibc these usually just include the
Linux headers, but for musl this allows them to define the struct
directly. We also need to move if.h and add packet.h, which define
other structs (or include headers that do so) that we use.
Fixes: 187c72d1afdc ("dhcp: Port the plugin to FreeBSD/macOS")
The previous option caused such requests to be enabled if not explicitly
disabled, which only the vici plugin did, for all other backends requests
would have been sent.
References strongswan/strongswan#2016
Only the vici plugin previously set OCSP_SEND_REPLY explicitly, all other
backends would have defaulted to OCSP_SEND_BOTH.
References strongswan/strongswan#2016
In particular for static code analyzers. The previous nesting of case
statements inside of a while loop that's inside a switch statement and
a wrapping block with declaration was quite weird and Coverity didn't
like it (it figured that `type` was uninitialized even when it assumed
that get_type() returned a known type for which a case statement
existed).
AWS-LC rejects public keys with explicitly encoded parameters but allows
private keys that use explicit encodings of the NIST curves. Since the
more important aspect is that public keys are rejected, this addition to
the warning message points that out.
References strongswan/strongswan#1907
This refactors the name constraints validation in the revocation plugin
so it aligns with what's specified in RFC 5820.
It also expands the subnet/range matching for identities.
Closesstrongswan/strongswan#2114
The previous code was in a way too simple which resulted in it being too
strict. For instance, it enforced that intermediate CA certificates
inherited the name constraints of their parents. That's not required by
RFC 5280 and prevented e.g. adding constraints in an intermediate CA
certificate that's followed by another that doesn't contain any
name constraints. That's perfectly fine as the set of constraints
specified by the parent continue to apply to that CA certificate and
the children it issues.
Name constraints were previously also applied to all identities of a
matching type, which is way too strict except for some very simple
cases. It basically prevented multiple constraints of the same type
as e.g. an intermediate CA certificate that has permitted name constraints
for example.org and example.com couldn't issue acceptable certificates
because any SAN with one domain would get rejected by the other
constraint. According to RFC 5280 matching one constraint is enough.
Also fixed is an issue with name constraints for IP addresses which were
previously only supported for a single level.
AWS-LC is an OpenSSL derivative which can be used with the openssl plugin.
This adds a CI job that resembles the openssl-3 test case. It downloads
the source tarball for an AWS-LC release, builds that source using
CMake/Ninja, and then builds/tests strongSwan using the same technique
used by openssl-3.
References strongswan/strongswan#1907Closesstrongswan/strongswan#2151
Enum arguments (ARG_ENUM with .list != LST_bool) are assumed to be of
type/size int in assign_args() in args.c.
Fixes: 0644ebd3de62 ("implemented IKE_SA uniqueness using ipsec.conf uniqueids paramater additionally supports a "keep" value to keep the old IKE_SA")
Closesstrongswan/strongswan#2148
AWS-LC (and likely BoringSSL) uses thread specific data to store internal
library state which gets freed via a registered destructor when the thread
terminates. If this thread happens to be the main thread, which runs the
leak-detective evaluation, the detective won't observe the corresponding free
of the related memory and erroneously reports it as a leak.
The two places this happens are:
- `RAND_bytes` for storing internal RNG state.
- `ERR_put_error` for storing the per-thread OpenSSL error queue.
References strongswan/strongswan#1907Closesstrongswan/strongswan#2147
OpenSSL stores the serial number for an X509 certificate as an
`ASN1_INTEGER` type. Within BoringSSL (and AWS-LC), the library
represents the value of zero as an empty array [1] which is different
from OpenSSL which represents it as the 1-byte array [0x00]. Though the
value of zero for the certificate serial number is illegal under
X.509 [2], we need to handle/encode it consistently within strongSwan.
From 18082ce2b061 ("certificates: Retrieve serial numbers in canonical
form"), we infer that the canonical representation of the zero serial
is [0x00]. To do this, we introduce `openssl_asn1_int2chunk` to
complement the existing string version that allows us to handle the
special case for zero instead of always returning a reference to the
library-dependent encodings.
References strongswan/strongswan#1907Closesstrongswan/strongswan#2138
[1] bdc35b6361
[2] https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.2
This reverts commit 8b9b11919d92e9738bb52901c9dbcc72e35b9fed.
Since ESN was negotiated via proposal, just configuring the SA without
ESN won't work as the ICV will be incorrect if the peer enabled ESN
on its SA. While the Linux kernel currently doesn't support disabling
replay protection for SAs that use ESN, this at least gets users an
explicit error not just dropped packets, and it will automatically work
if the kernel supports this combination at some point.
References strongswan/strongswan#2117
This is used to install, replace or delete currently installed trusted
certificates based on the app's current managed configuration.
Certificates that are shared between multiple profiles are protected
and not uninstalled if a profile that uses it remains.
This installs the configured user certificate into Android's key store
using the DevicePolicyManager.
This is only accessible if the app is installed on an enrolled device and
has been granted the CERT_INSTALL delegate scope.
While it seems to be possible to cast Context.getApplicationContext()
to the application class, there really is no documented reason why that
should actually be the same object.
Triggers a broadcast if the configuration changed and updates the
profile list accordingly (previously only handled removal of multiple
profiles).
If the app resumes, the configuration is also loaded and listeners are
notified in case the config was updated while the app was in the
background.
AWS-LC lacks support for a number of elliptic curve algorithms so this
adds some conditional macros to avoid registering the related plugin
features. Support for curves ed448 and x448 is completely absent and are
not planned for implementation as they are no longer recommended for use.
While ed25519 is supported by the library, a single missing API for
ASN.1 DER encoding of its private keys is missing which prevents its
use in strongSwan. Future work may remove this limitation, but for now
we will disable the functionality.
Closesstrongswan/strongswan#2109
AWS-LC is a BoringSSL-based libcrypto implementation. SHA_CTX is declared with
the hash data specified as an array rather than as a field in upstream OpenSSL.
Since AWS-LC builds against C99, we are unable to handle this with anonymous
unions like BoringSSL. The workaround I propose is to add these conditional
macros around the accessors within openssl_sha1_prf. After this change,
everything builds successfully with AWS-LC headers.
Closesstrongswan/strongswan#2103
This also refactors the BPF handling so it can be shared between the
dhcp and farp plugins. The latter is adapted accordingly.
Closesstrongswan/strongswan#2047
Co-authored-by: Tobias Brunner <tobias@strongswan.org>
Different users in the strongSwan code base use the refcount helpers to
allocate incrementing unique values. So far the risk of overflows for
these unsigned 32-bit values has been considered mostly theoretical, as
it requires a longer uptime and a lot of activity to hit such an overflow.
At least for the Netlink sequence numbers, this is not only theoretical,
though, and an overflow has been hit on a productive setup. Unfortunately,
the consequences are rather unpleasant, as the response with a zero
sequence number can't be matched to the request. This results in the
offending thread to block indefinitely while holding the Netlink mutex.
So add a helper to allocate incrementing unique identifiers that checks
for overflows and never returns 0. Use it for Netlink sequence numbers
and some other potential users affected, namely those allocating
IKE_SA/CHILD_SA unique identifiers, marks and interface identifiers.
Closesstrongswan/strongswan#2062
The refcount_t for allocating unique marks and interface IDs may overflow or
hit the special value for unique marks/if_ids, in the worst case not setting it
on CHILD_SAs that should have one.
As (potentially two) marks/if_ids are allocated only for newly created CHILD_SAs,
but not for rekeying, this not very likely. Still, if a setup uses
aggressive re-authentication and or re-creates CHILD_SAs every minute,
a gateway with 100'000 tunnels may hit the overflow within a month uptime.
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().
A refcount variable is used to allocate sequential unique identifiers for
Netlink sequence numbers, subject to overflows. The risk of an overflow
has so far not been considered practical, as it requires 2^32 netlink
requests.
It seems that this issue is not only theoretical. A host with thousands
of tunnels doing aggressive rekeying and/or aggressive status checking
(via vici list-sas) may trigger the overflow after a few weeks uptime.
The consequences are rather devastating: Once the refcount overflows, a
Netlink request is sent with sequence number 0. This request is answered
by the kernel, but can't be matched to the request, resulting in the error:
"received unknown netlink seq 0, ignored". Without Netlink timeouts, the
thread indefinitely waits for a response while holding the Netlink mutex,
bringing all threads to a halt.
So at all costs avoid zero sequence numbers. Also, start at sequence number
1 instead of the arbitrary 201, so the same range is used on start and after
an overflow.
Also fix the path to the sdkmanager (the old one was removed in the latest
images and the incorrect path caused a weird sudo error) and install
Java 17 as that's necessary for newer versions of the Gradle plugin.
PowerMock isn't maintained anymore and causes issues with newer Java
versions. We only used it to mock static methods, which Mockito now
supports as well. Instead of using the try-with-resources construct,
this uses a @Before and @After method so we don't have to change all the
test methods.
This also references the NDK via ndkVersion and replaces the custom
ndk-build tasks. It also replaces the deprecated compileSdkVersion and
increases it because dependencies of updated dependencies require that.
targetSdkVersion is not yet updated because there might be some work
required for Android 14 compatibility.
The gperf version that's already available on the system generates
function declarations with K&R syntax (separate arguments) for which newer
compilers produce a warning as C23 doesn't support that syntax anymore.
These functions are declared without arguments, passing arguments to them
causes warnings such as the following with newer compilers:
passing arguments to 'return_null' without a prototype is deprecated in all versions of C and is not supported in C2x [-Werror,-Wdeprecated-non-prototype]
We only use them via function pointers, which doesn't trigger any warnings
and hopefully continues to work.
Newer curl versions (as used on macOS via Homebrew) add attributes like
__attribute__ ((format(printf, a, b)))
to their `curl_*printf*` functions, which fails if we redefine `printf`
as e.g. `builtin_printf` (pulled in via library.h). We could disable
these checks via CURL_NO_FMT_CHECKS, but reordering the headers should
do the trick as well.
Bison generates code that only increases the yynerrs counter, it's never
read. This causes a warning in newer compilers (in particular clang).
Newer versions of bison mark yynerrs with __attribute__((unused)), but
at least on FreeBSD 14 that's not yet available.
systemd seems to use this and if we indirectly use libraries provided
by it, which can e.g. happen via getgrnam_r() and nss-systemd, this may
be called on pointers returned by leak detective's malloc(), which will
not point to the original start of the block and cause a segmentation
fault.
Closesstrongswan/strongswan#2045
Fixes a regression with handling OCSP error responses and adds a new
option to specify the length of nonces in OCSP requests. Also adds some
other improvements for OCSP handling and fuzzers for OCSP
requests/responses.
Closesstrongswan/strongswan#2011
Some servers might not support a length of 32 and return a malformed
request error. Lowering the value to the previous default of 16 could
help in that case.
The two OPTs that were used previously allowed to omit it completely (hence
the fallback to ID_ANY), but that's invalid, so it's better to fail
parsing.
The has_issuer() and issued_by() methods relied on it to be defined, so
if the OCSP response wasn't successful (i.e. OCSP status indicates an
error and no OCSP response is parsed), a null-pointer dereference was
caused if the caller checked if the OCSP response was issued by a
specific certificate.
That's a side-effect of the referenced commit. Previously, error codes
caused the OCSP response to not get parsed successfully, which technically
wasn't correct as it's well formed and successfully parsed, it's just
indicating an error state.
Fixes: 00ab8d62c089 ("x509: Support generation of OCSP responses")
Seems this was forgotten in the referenced commit and actually could lead
to a buffer overflow. Since charon-tkm is untrusted this isn't that
much of an issue but could at least be easily exploited for a DoS attack
as DH public values are set when handling IKE_SA_INIT requests.
Fixes: 0356089d0f94 ("diffie-hellman: Verify public DH values in backends")
Fixes: CVE-2023-41913
Instead of the CA certificate's subjectKeyIdentifier erroneously
the CA's authorityKeyIdentifier was used as the authorityKeyIdentfier
of the certificate to be issued. This might work with a root CA
where the authorityKeyIdentifier equals its subjectKeyIdentfier
but introduces a severe regression when an intermediate CA is used.
Adds support for multiple OCSP responders in `pki --ocsp` and one that
is based on OpenSSL-style index.txt files. The parser for these files
also accepts simplified files that only specify the status, serial number
and optional revocation date/reason. The OCSP test scenarios are also
updated to use this OCSP responder including one that shows the multi-CA
capabilities of the --ocsp command and the --index option.
The only exception is the ikev2/ocsp-no-signer-cert scenario as the
pki command won't sign an OCSP response with a certificate that isn't
the CA certificate or marked as an OCSP signer.
Registered OCSP responders should return VALIDATION_SKIPPED for issuer
certificates they are not responsible for. However, VALIDATION_FAILED is
currently treated the same way, so that's fine as well.
Implements a new --ocsp command for the pki tool that can produce OCSP
responses based on information provided by a plugin. A first plugin
that accesses the OpenXPKI database is also added.
Closesstrongswan/strongswan#1958
The openxpki plugin directly access the certificates table in
the OpenXPKI's MariaDB in order to retrieve the status of an
issued X.509 certificate based on its serial number.
The kernel includes the XFRMA_REPLAY_ESN_VAL attribute when dumping
SAs since it was added with 2.6.39. So we basically added this attribute
twice to the message sent to the kernel, potentially exceeding the
message buffer if the window size is large.
The XFRMA_REPLAY_VAL attribute is only dumped since 3.19, so that might
still be relevant (Google seems to maintain a 3.18 kernel) and since we
have to query the current lifetime stats anyway, we can just avoid adding
this attribute twice.
Closesstrongswan/strongswan#1967
Adds support to encode SANs of type uniformResourceIdentifier in
certificates. They currently don't have any use in strongSwan, but
might be required for other applications.
Closesstrongswan/strongswan#1983
Instead of just generating an authorityKeyIdentifier based on the
issuer's public key, this allows CA certificates to be issued by a
different tool that doesn't use a SHA-1 hash of the subjectPublicKey
for the subjectKeyIdentifier.
Closesstrongswan/strongswan#1992
References strongswan/strongswan#1975
This adds support for password-less PKCS#12 containers and PKCS#8 files.
A new option for charon-cmd also allows loading private keys of any
type (previously only RSA keys were supported).
References strongswan/strongswan#1955
Adds support for nameConstraints of type iPAddress, which represent a
subnet, to the x509, openssl and constraints plugins. SANs of type
iPAddress are matched against such constraints.
Closesstrongswan/strongswan#1991
This fixes issues with CHILD_SAs getting reestablished concurrently.
We intend to reuse the reqid of the previous CHILD_SA, however, previously
the reqids were released and up for reassignment to any other CHILD_SA
or trap policy. This could cause the reqid to get associated with
completely different traffic selectors, as the reestablished CHILD_SA
would eventually get the requested reqid because the traffic selectors
explicitly don't have to match (to allow narrowing for CHILD_SAs based
on trap policies).
Closesstrongswan/strongswan#1855
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.
Every reqid is allocated once, we don't store the same reqid with e.g.
different marks or interface IDs that would make it necessary to make
them part of the key in that table (that's different in the other table).
To preserve the current behavior, that is, allocating a new reqid if e.g.
the marks are different, the additional selector values (which will
result in an additional policy in the Linux kernel) are compared after
the initial lookup.
This allows preventing peers from authenticating with certificates
that are locally trusted, in particular, our own local certificate (which
safeguards against accidental reuse of certificates on multiple peers).
On the other hand, if this option is enabled, end-entity certificates
for peers can't be configured anymore explicitly (e.g. via remote.certs
in swanctl.conf).
If we initially selected a group the peer doesn't support (e.g. because
curve25519 is the first ECDH group provided by plugins), then found
a supported curve, we previously still instantiated a DH object for the
original group and might have formatted the parameters incorrectly.
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: 5ce1c91b58a2 ("ikev2: Trigger ike_updown() event after all IKE-specific tasks ran")
There is a relatively recent NIAP requirement to reject certificates with
ECDSA keys that explicitly encode the curve parameters (TD0527, Test 8b).
Since explicit encoding is pretty rare (if used at all and e.g. wolfSSL
already rejects it, by default), we should follow that requirement and
just reject such keys/certificates completely.
This currently can be enforced in all crypto plugins except when using
older versions of OpenSSL (< 1.1.1h) and Botan (< 3.2.0).
Closesstrongswan/strongswan#1949
References strongswan/strongswan#1796
These are not allowed in X.509 certificates according to RFC 5480 and
some newer validations apparently explicitly check for this.
Note that WolfSSL rejects such keys, by default. Only when compiled with
WOLFSSL_NO_ASN_STRICT are they accepted.
The cert-enroll script handles the initial enrollment of an X.509
host certificate with a PKI server via the EST or SCEP protocols.
Run as a systemd timer or via a crontab entry the script daily
checks the expiration date of the host certificate. When a given
deadline is reached, the host certificate is automatically renewed
via EST or SCEP re-enrollment based on the possession of the old
private key and the matching certificate.
This works around an issue that occurs when recreating an IKE_SA with
multiple CHILD_SAs that use dynamically allocated reqids.
We currently try to preserve the reqid when reestablishing, so the
create-child task gets the reqid of the previous CHILD_SA and will try
to reallocate that once the CHILD_SA is installed. Before that, the old
CHILD_SA is destroyed and the reqid is released and added to the array
of reqids to get reused. However, because of the reverse order used here,
the first reqid in the array is the one of the last CHILD_SA.
So it can happen that a newly created CHILD_SA gets a reqid reassigned
that a later CHILD_SA will then also claim for itself and get assigned
because an entry with that reqid exists. So multiple CHILD_SAs with
different traffic selectors could then share the same reqid.
References strongswan/strongswan#1855
Fixes a problem installing policies with source traffic selectors that do
not contain/match any of the local addresses.
When installing a route for a source TS that does contain one or more
local addresses, a preferred source address should be set in the route
(analogous to the `src` option in `ip route add`). This address is used
when the host itself sends traffic via that route (in contrast to
forwarding it).
When the source TS does not encompass any of the local addresses, the
host is not allowed to send traffic via this route and does not need to
set the preferred source address. However, the code would just return a
failure because it could not find a matching local address. This commit
changes this so routes without preferred source IP are installed to
allow non-local traffic to get forwarded via TUN device.
Closesstrongswan/strongswan#1766
This commit fixes auto detection of in6_pktinfo.
When negotiating an IPv6 IKE session charon reported an error
"Jun 30 16:42:49 03[NET] error reading IP header"
The cause of error was missing in6_pktinfo declaration, which is
auto detected. This auto detection may fail with an error depending
on compiler flags:
configure:19850: checking for in6_pktinfo
configure:19870: gcc -c -g -O0 -Wall -Wno-format -Wno-format-security
-Wno-pointer-sign -Werror -Wfatal-errors -Wno-error=stringop-truncation
conftest.c >&5
conftest.c: In function 'main':
conftest.c:73:11: error: 'pi.ipi6_ifindex' is used uninitialized in this
function [-Werror=uninitialized]
73 | if (pi.ipi6_ifindex)
| ~~^~~~~~~~~~~~~
compilation terminated due to -Wfatal-errors.
cc1: all warnings being treated as errors
Signed-off-by: Antony Antony <antony.antony@secunet.com>
socket.connect() takes a single argument with the address that depends
on the address family, for TCP it's a tuple with IP and port.
Fixes: 00a75e332f29 ("vici: Create default TCP socket on Windows in Python bindings")
Closesstrongswan/strongswan#1874
Note that displaying the notification for the background service is
apparently not strictly necessary. So it's fine if the user wants to
hide it. That the service is running can still be seen in the task
manager (pull down the status drawer twice, there is a bullet with a number
at the bottom if the service is running).
Simply use the system dialog. If the user denies it twice, it won't show
up again. The explanation dialog would not show up the first time (i.e.
shouldShowRequestPermissionRationale() returns false), only once the user
denied the permission once. Currently seems like a bit much work
as we don't need the user to allow notifications.
Particularly on Samsung devices, the connect() call to dissolve the
previous connection on an existing socket via AF_UNSPEC does fail in
some situations with ECONNREFUSED:
[KNL] failed to disconnect socket: Connection refused
While creating a new socket is potentially a bit more overhead, this
should avoid the issue.
Closesstrongswan/strongswan#1691
When adding a virtual IP on a TUN interface, the interface might get
activated (in terms of receiving the event) after we've already set the
virtual flag for the added address. As the activation repopulates the
addresses on the interface, this cleared the flag and the address would
no longer be treated as virtual IP when installing routes for CHILD_SAs
that reference it in their local traffic selectors.
Closesstrongswan/strongswan#1807
Fixes an infinite loop if e.g. Netlink event sockets get too many
packets queued and poll() just returns POLLERR for the socket. Also
increases the default receive buffer size for Netlink sockets to better
support systems with lots of route updates.
Closesstrongswan/strongswan#1757
We can't actually explicitly listen for errors by passing POLLERR in
`events` (the man page for poll() clearly states it's ignored). On the
other hand, POLLERR can be returned for any FD and, even worse, it might
be the only event indicated.
The latter caused an infinite loop as we didn't notify the callback nor
clear the error by calling `getsockopt(..., SOL_SOCKET, SO_ERROR, ...)`.
And while the latter would be able to reset the state to break the loop,
it seems to leave the FD in a defunct state where no further events will
be returned by poll(). Notifying the callback works better (the error
is then reported by e.g. recvfrom()) and automatically happened already
if POLLERR was returned together with e.g. POLLIN.
So we now treat POLLERR like the other error indicators we handle (POLLHUP
and POLLINVAL) and just notify the callbacks.
Also simplify how we try to exceed the system-wide maximum. We basically
just try to force the value and simply fall back to the regular call.
The kernel actually won't let the latter fail if the value is too big,
it just caps it at the internal maximum.
We track all IKE_SA_INIT requests as half-open IKE_SAs but didn't
correctly untrack them if their message ID or responder SPI was non-zero.
References strongswan/strongswan#1775
Fixes: b866ee88bf54 ("ike: Track unprocessed initial IKE messages like half-open IKE_SAs")
As specified in RFC 7296, section 2.25:
The SA that the initiator attempted to rekey is indicated by the SPI
field in the Notify payload, which is copied from the SPI field in
the REKEY_SA notification.
So we copy that and the protocol verbatim.
The get_spi_data() method is currently not used, so that has been
simplified so it can be used for any protocol type and any SPI length.
Same for set_spi_data(), which is currently used for IKEv1 to encode
two SPIs.
The created XFRM interface was not actually used (no interface IDs on the
SAs, no routes via interface). It was basically treated like the dummy
TUN device. To actually install the routes via XFRM interface, we have
to create it before we install the SAs and policies, signal_ip_config()
happens too late. We also have to mark the ESP packets the same as IKE
the packets to avoid a routing loop if the server's IP is included in
the remote traffic selector (in particular if it's 0.0.0.0/0 or ::/0).
Fixes: 58f278f93239 ("charon-nm: Use an XFRM interface if available")
The all-zero Ed25519 public key is rejected by botan_pubkey_check_key()
when the key is loaded.
Note that Botan 3 requires GCC 11 or CLANG 14, i.e. can't easily be built
on Debian bullseye or Ubuntu 20.04.
The thread-local storage function gets flagged via various botan FFI
functions when using Botan 3, whitelist that instead of all of them.
The services running on alice seem to require a bit more memory with
Debian bookworm, so increase the memory allocation. But at the same
time reduce winnetou's allocation by the same amount as it really doesn't
require that much memory.
The unit change makes it easier to read.
Because do-tests runs the restore-defaults script, fstab would get reset
to the default version and the mount point wouldn't be available anymore
after stopping and restarting the guests (unless the guest images were
rebuilt in between).
By default, rsyslog is not installed anymore to avoid storing everything
twice (since journald is the default). If this becomes an issue, we
could delete /var/log/journal to only log via rsyslog.
System-wide installation via pip isn't easily possible anymore on Debian
bookworm, so just use the Debian package for this (is available in old
releases as well).
Because libcrypto and libssl are measured, we need a new group for Debian
versions with OpenSSL 3 (I've rather added a suffix to the old group as
that could eventually get removed, although we might need a 3.1 variant
in the future - maybe we should measure some other files?).
OOM-killer is now already triggered with `import daemon`, so set the
limit before that. Also some PEP8 fixes (including an exclusion for
the above fix as that causes imports to not be at the beginning of the
file).
Without this, Git refuses to operate on the build dirs that are mounted
with weird ownership. When running as root in the chroot, Git checks
SUDO_UID, which won't match.
This is necessary because TKM can't read PKCS#8 files and in some
scenarios we don't have the pkcs8 plugin loaded that would be required
to read/decrypt the non-traditional files.
The wrapper called the command twice for any unit but "strongswan" and
it didn't return the correct exit code. This was noticed when an
if-updown script tried to check if systemd-resolved is active and always
succeeded, which caused failing attempts to configure it.
But now that the return code is correct, trying to enable bind9 won't
fail silently anymore if the unit doesn't exist (similar on older systems
for named), so this is adapted.
With Debian bookworm, the PQC KE sntrup761x25519-sha512 is negotiated, by
default. This increases the overhead significantly, in particular, the
size of the KE message, which wouldn't get through IPsec tunnels without
MSS clamping.
Since 17fd304e60df ("resolve: Don't install individual servers via
resolvconf"), DNS servers were sorted if getting installed via resolvconf.
In some setups the order might be important (even though relying on it
isn't a good idea in general as stub resolvers are free to use all of
the servers as they please).
The previous code was problematic if a certificate request for a known
but unrelated CA was received and the local trust chain was incomplete.
Due to the received anchor, the incomplete trust chain was dismissed and
any intermediate CA certificates were, therefore, not sent to the peer.
This new approach doesn't dismiss an incomplete trust chain, but prefers
one that can be resolved to a received anchor. If no such chain is found,
the first one is used.
This adds support for sending/receiving ESP packets without UDP
encapsulation to libipsec and kernel-libipsec. Only Linux is currently
supported and the feature is disabled by default.
This is currently only supported on Linux and with the appropriate
permissions.
Since it's experimental, it's disabled by default.
The log messages for each sent and received ESP message are logged in NET
like the ones in the socket-default plugin for UDP-encapsulated messages.
Currently just based on the reqid. An acquire for the same reqid is
triggered at most every 10 seconds (gets ignored in trap_manager_t if
the SA is still getting established).
Entries are only cleaned up if an SA is eventually installed (similar to
the allocated SPIs). Should that ever be a problem, we could probably
schedule a job that regularly flushes old entries.
The calculation of the timeout is also shared now and the total
timeout in seconds is corrected in case retransmit_base is <= 1.
This could make it easier in the future to apply different retransmission
settings to messages/exchanges.
When using OpenXPKI, the subject DN in the renewal request has to match
the previous DN exactly. However, because OpenXPKI may add a bunch of
DC/O RDNs to subjects of issued certificates, running --scep with the
same --dn that was used for the original request won't work (results in
a "Client error / malformed request badRequest" error even after enabling
`renewal_via_pkcs_req`). This simplifies renewals as --dn can just be
omitted and extracted from the original certificate to avoid this issue.
References strongswan/strongswan#1689
This fixes the build with DEBUG_LEVEL < 4, which was broken when building
from the repository since --enable-warnings was made the default.
Although, most issues only occurred with the level reduced to 0/-1. And
while removing debug statements at compile time completely is probably
not useful in production, there might be use cases in certain benchmarking
scenarios. Also, with the recent changes to the controller there should
only rarely be a listener registered at a higher log level so the overhead
for those higher-level DBG statements is minimal.
Anyway, reducing the log level at compile time is a documented feature and
at least DEBUG_LEVEL=3 could be useful to prevent leaking sensitive
information via logs from the outset. So we should make sure compilation
doesn't fail.
Some variables that are only assigned to be used in DBG statements
will otherwise trigger a "set but not used" warning/error if DEBUG_LEVEL
is too low.
When we reset the initiator SPI, we have to migrate the adopted children
again so the correct IKE_SA can later be checked out.
Closesstrongswan/strongswan#1663
As long as any `child*` selector is received, only CHILD_SAs will be
terminated or rekeyed. Any passed `ike*` selectors will only be used to
filter the IKE_SAs when looking for matching CHILD_SAs. However, the
previous log messages seemed to indicate that IKE_SAs will also be
terminated/rekeyed.
References strongswan/strongswan#1655
While there is a status message sent to systemd (can be seen e.g. in
systemctl status), the version etc. is currently not logged to the
journal, syslog or any log files.
Previously, the logger installed by the controller always announced
LEVEL_PRIVATE(4), which produced completely useless logging calls with
the common clients (vici/stroke) whose default log level is LEVEL_CTRL(1).
This can produce quite some overhead if there are e.g. a lot of concurrent
initiate() calls.
Until we know which IKE_SA is affected by an initiate() or terminate_*()
command, unrelated log messages that don't have any IKE context (i.e.
the passed `ike_sa` is NULL) would previously get logged.
Exiting the loop previously could cause watcher to busy wait (i.e.
rebuild the array and call poll() repeatedly) until the active callback
was done.
Assume watcher observes two FDs 15 and 22, which are in the list in that
order. FD 15 is signaled and its callback gets triggered. The array of
FDs is rebuilt and does not include 15 anymore. Now FD 22 is ready for
reading. However, when enumerating all registered FDs, the loop previously
was exited when reaching FD 15 and seeing that it's active. FD 22 was
never checked and the array was immediately rebuilt and poll() called.
If the callback for 15 took longer, this was repeated over and over.
This basically reverts d16d5a245f0b ("watcher: Avoid queueing multiple
watcher callbacks at the same time"), whose goal is quite unclear to me.
If it really wanted to allow only a single callback for all FDs, it didn't
achieve that as any FD before an active one would get notified and if
multiple FDs are ready concurrently, they'd all get triggered too.
Skipping entries with active callback makes sense as it avoids a lookup
in the FD array and subsequent revents checks. But why would we need to
rebuild the array if we see such an entry? Once the callback is done,
the watcher is notified and the array rebuilt anyway (also if any other
FD was ready and jobs get queued).
The list of FDs is recreated quite often (e.g. due to the kernel-netlink
event sockets) and if a logger depends on watcher_t in some way this
might cause conflicts if the mutex is held.
Since the same FD may be added multiple times (e.g. with separate
callbacks for WATCHER_READ and WATCHER_WRITE), the previous check
might not have found the correct entry. As the entry can't be removed
while in a callback, the pointer comparison is fine.
This could be problematic in case loggers in some way rely on watcher_t
themselves. This particular log message should rarely occur if at all,
but still avoid holding the mutex.
This should prevent a deadlock that could previously be caused when a
control-log event was raised. The deadlock looked something like this:
* Thread A holds the read lock on bus_t and raises the control-log event.
This requires acquiring the connection entry in write mode to queue the
outgoing message. If it is already held by another thread, this blocks
on a condvar.
* Thread B is registering the on_write() callback on the same connection's
stream due to a previous log message. Before this change, the code
acquired the entry in write mode as well, thus, blocking thread A. To
remove/add the stream, the mutex in watcher_t needs to be acquired.
* Thread C is in watcher_t's watch() and holds the mutex while logging on
level 2 or 3. The latter requires the read lock on bus_t, which should
usually be acquirable even if thread A holds it. Unless writers are
concurrently waiting on the lock and the implementation is blocking
new readers to prevent writer starvation.
* Thread D is removing a logger from the bus (e.g. after an initiate()
call) and is waiting to acquire the write lock on bus_t and is thereby
blocking thread C.
With this change, thread B should not block thread A anymore. So thread D
and thread C should eventually be able to proceed as well.
Thread A could be held up a bit if there is a thread already sending
messages for the same connection, but that should only cause a delay, no
deadlock, as on_write() and do_write() don't log (or lock) anything while
keeping the entry locked in write mode.
Closesstrongswan/strongswan#566
This triggers an error for functions that take chunk_t as variadic
arguments (cat, debug, builders, ASN.1 wrap).
Since we are not using C++, this should be fine as we are only passing
POD types anyway.
Adds support for CMS-style signatures in PKCS#7 containers, which allows
verifying RSA-PSS and ECDSA signatures.
Ed25519 signatures should be supported when verifying, however, they
currently can't be created. Ed448 signatures are currently not supported.
That's because RFC 8419 has very strict requirements in regards to the
hash algorithms used for signed attributes. With Ed25519 only SHA-512 is
allowed (pki currently has an issue with Ed25519 in combination with
SHA-512 due to its associated HASH_IDENTITY) and with Ed448 only SHAKE256
with 512-bit output, which has to be encoded in the algorithmIdentifier
parameters (something we currently don't support at all).
Closesstrongswan/strongswan#1615
For the legacy schemes with rsaEncryption nothing changes, but if an
actual signature scheme is encoded we use that to find the key and
verify the signature.
The descriptions for the PKCS#7 structure are adapted for CMS.
Some encoders, like those provided by the dnskey and sshkey plugins,
require these separately when encoding keys.
Also fixes the type for the ASN.1 encoding (which is a subjectPublicKeyInfo
structure) depending on the key type. This worked fine for PEM encoding
as the pem plugin doesn't care what the actual type of the key is (which
is encoded in the SPKI structure), but other plugins do (e.g. the sshkey
plugin).
The `--enable-heapmath` configure option has been deprecated. As
already described in eae30af029b1 ("Use wolfSSL 5.4.0 for tests"), the
alternative is to configure `--with-max-rsa-bits=8192` instead in order
to test the modp6144 and modp8192 DH groups.
We don't have any information on the issuer of cached OCSP responses, in
particular if the OCSP response is issued by a dedicated OCSP signer,
whose certificate might not be contained in the response or even signed
by the same CA but could just be locally installed. So the only way to
determine if a response applies to the current certificate and its CA
is searching for the response's issuer certificate and verifying that.
However, when using multiple CAs that provide revocation checking via
OCSP, in particular with multi-level CAs (e.g. like the
ikev2-multi-ca/ocsp-signers test scenario), we might have unrelated OCSP
responses in the cache when verifying a particular certificate. In this
case we don't need any confusing
ocsp response verification failed, no signer certificate '...' found
error messages because the response was for a different CA.
Similarly, if lots of clients of the same CA connect there could be lots
of OCSP responses in the cache that, while being applicable to the current
CA, don't have any information on the certificate we are currently
checking. In this case all the
ocsp response correctly signed by "..."
ocsp response contains no status on our certificate
messages don't provide any value.
In the mentioned test scenario, we suppress the
ocsp response verification failed, no signer certificate 'C=CH, O=strongSwan Project, OU=Research OCSP Signing Authority, CN=ocsp.research.strongswan.org' found
message from the cached OCSP response for carol's end-entity certificate
when verifying the "Research" intermediate CA certificate that issued
carol's certificate.
Then the
ocsp response verification failed, no signer certificate 'C=CH, O=strongSwan Project, OU=Research OCSP Signing Authority, CN=ocsp.research.strongswan.org' found
ocsp response verification failed, no signer certificate 'C=CH, O=strongSwan Project, OU=OCSP Signing Authority, CN=ocsp.strongswan.org' found
messages from the cached OCSP responses for carol's end-entity and
intermediate CA certificates when verifying dave's end-entity certificate.
And finally the
ocsp response verification failed, no signer certificate 'C=CH, O=strongSwan Project, OU=Research OCSP Signing Authority, CN=ocsp.research.strongswan.org' found
ocsp response correctly signed by "C=CH, O=strongSwan Project, OU=OCSP Signing Authority, CN=ocsp.strongswan.org"
ocsp response contains no status on our certificate
ocsp response verification failed, no signer certificate 'C=CH, O=strongSwan Project, OU=Sales OCSP Signing Authority, CN=ocsp.sales.strongswan.org' found
messages from the cached OCSP responses for carol's end-entity
certificate, the applicable but unrelated response for carol's "Research"
intermediate CA certificate and the response for dave's end-entity
certificate when verifying dave's "Sales" intermediate CA.
With version 60.0.0 setuptools changed to a local installation of
distutils. This seems to break the installation of swid-generator (causing
an `importlib.metadata.PackageNotFoundError: swid-generator` error).
Note that while Debian ships setuptools 52.0.0, `python-daemon` recently
added a dependency on `setuptools>=62.4.0`, which installs that version
that's then later used to install swid-generator.
The main difference seems to be that the local version installs the
package in `/usr/lib/python3.9/site-packages`, while the stdlib version
does so in `/usr/local/lib/python3.9/dist-packages` (similarly for the
`swid_generator` script and the `distro` dependency).
Not sure if there is a better/proper way to fix this. Might just be an
issue with Debian bullseye and mixing system packages with those installed
via pip3.
Enforces that the certificate that signed a CRL either encodes the
cRLSign keyUsage (even if it is a CA certificate) or is a CA certificate
without a keyUsage extension (which should rarely be the case nowadays).
This is in compliance with RFC 5280, section 6.3.3. (f):
If a key usage extension is present in the CRL issuer's certificate,
verify that the cRLSign bit is set.
strongSwan encodes a keyUsage extension with cRLSign bit set in all CA
certificates it generates since 1ec8f22de222 ("set Certificate Sign and
CRL Sign flags in keyUsage extension if CA is true"), which was 13 years
ago. Before that the extension was not encoded so those CA certificates
would also still be accepted as CRL issuer (if they are still valid, but
considering the SHA-1 deprecation that happened since then, they were
most likely replaced anyway).
References strongswan/strongswan#1548
When running as a service, the libraries are initialized/deinitialized
not by the main thread but by a separate thread that runs the registered
main service procedure. When the service is stopped, the libraries are
deinitialized by that thread and the thread lock and hashtable are
destroyed. But afterwards the DllMain callback is also triggered for
that thread so we have to prevent it from accessing these objects again.
References strongswan/strongswan#1567
If no CHILD_SA is initiated, we wait for a state change to IKE_ESTABLISHED
but that will never happen for already established IKE_SAs.
References strongswan/strongswan#1553
Also adds error reporting via VICI for issues with mediation settings.
Fixes: 229cdf6bc8f2 ("vici: Order auth rounds by optional `round` parameter instead of by position in the request")
References strongswan/strongswan#1569
That method is subject to interface filtering, which isn't ideal for
DHCP traffic that probably uses an internal interface on which the IKE
daemon might be disabled. In that case `giaddr` is set to an incorrect
public IP, which in turn might prevent the plugin from receiving the
DHCP server's unicast response, in particular if the DHCP socket
is bound to the internal interface.
This new approach connects the client socket and thereby determines the
source address to reach the DHCP server.
Closesstrongswan/strongswan#1573
As indicated by the comparisons and the parsing in scep_parse_caps()
this should be a bitmask.
Fixes: 7c7a5a0260ca ("pki: Enroll an X.509 certificate with a SCEP server")
Closesstrongswan/strongswan#1607
With 5401a74d3608 ("eap-tls: Add support for TLS 1.3") a TLS application
was added to implement TLS 1.3's protected success indication. For
earlier TLS versions, its build() method simply returned SUCCESS as
there was nothing to send. However, that had the unintended side-effect
of also not sending the final TLS handshake messages (ChangeCipherSpec
and Finished).
The reason is that the TLS stack first checks for remaining handshake
messages but then also asks the registered application for data to
piggyback to that response (before the commit there was no application,
so that step was skipped). The problem is that the status returned by
the application is directly forwarded through the TLS stack. So not
returning INVALID_STATE caused the session to get concluded immediately
instead of resulting in ALREADY_DONE that would trigger sending the
final EAP message instead of an EAP-Success.
Fixes: 5401a74d3608 ("eap-tls: Add support for TLS 1.3")
The MSK is generated when the keys are derived. For TLS 1.3 that's also
when the handshake is complete. However, for TLS 1.2 it happens when
generating or processing the ClientKeyExchange message, which, on the
client, happens before the final Finished handshake message has been
received from the server. This caused the EAP-TLS client to accept an
EAP-Success message instead of the server's final TLS handshake
messages, unintentionally allowing servers to cut the exchange short by
two EAP messages (in the regular exchange the response to the server's
final handshake messages is an empty EAP-Response, which is then
followed by the server's EAP-Success).
While this is not correct, it does not seem to pose a security issue.
If DH is used as key exchange, the server signs the ServerKeyExchange
message and the client is sure to communicate with a trusted server
before it derives the MSK. If RSA encryption is used as key exchange,
the client sends the premaster secret, on which the MSK is based,
encrypted with the server's public key (as extracted from the trusted
certificate). An attacker won't be able to decrypt this and, therefore,
can't derive the same MSK to generate a valid AUTH payload and the IKE
authentication will fail.
This was removed with 0fea6a7f8e7e ("github: Adapt to switch to Ubuntu
22.04 for ubuntu-latest") as it didn't seem necessary anymore. But
recently there have been such random crashes again with the 20.04 image.
Since 3dd5dc50119d ("Merge branch 'vici-python-timeout'"), any timeout
set directly on the socket is reset by `vici.Transport.receive()` unless
called by `vici.Session.listen()`. This prevents configuring a default
timeout directly on the socket.
However, setting a timeout directly on the socket also had drawbacks
since it can cause `vici.Transport.receive()` to raise a timeout error
while a subset of the data have been received, with no way to recover.
This commit merges both approaches by considering the timeout configured
on the socket by default (when no timeout is explicitly set) and
keeping the switch to blocking receive once the first byte has been
received. When the full expected data have been received, the timeout
configured on the socket is restored.
Co-authored-by: Tobias Brunner <tobias@strongswan.org>
Signed-off-by: Jean-Tiare Le Bigot <jt@yadutaf.fr>
Closesstrongswan/strongswan#1562
The Ubuntu 18.04 image is deprecated and builds will start to fail
temporarily during four 24 hour periods from now until the final
deprecation on April 1st. So better remove these runs now.
With newer OpenSSL builds, the DLL files contain parts of the version
number and the architecture in their name, e.g. for OpenSSL 1.1.1 the
DLL for libcrypto is called libcrypto-1_1-x64.dll. So referencing that
directly could be kinda tricky. And by using `-lcrypto` we therefore
didn't link those DLLs but the OpenSSL version installed by msys2.
Since the latter ships OpenSSL 3 since January and the VS 2019 image
was updated recently, our builds broke as we used the headers from
the 1.1.1 installation but then tried to link OpenSSL 3.
Luckily, in the lib/ directory of the OpenSSL installation, there is a
libcrypto.lib file, which is an import library (containing the symbols
and a reference to the DLL). We can use that to link the right library
via `-lcrypto`.
With the old OpenSSL 1.0.2 build on the VS 2015 image, there is also
such a .lib file but it seems the linker is too old or otherwise incapable
of finding the DLL. But since the DLL is just called libeay32.dll there,
we use that directly and don't reference the lib/ dir.
Also removed a superfluous AC_MSG_RESULT() if libeay32 isn't found.
Before TLS 1.3, the server sent the last handshake message and had the
option to piggyback the EAP-Identity request directly onto the packet
with the TLS Finished message, or wait for the empty message by the
client that acknowledges the completion of the handshake. With TLS 1.3,
the client finishes the handshake after the server. So this option
is irrelevant there and we immediately start with Phase 2.
The flags encoded in the PKCS#10 structure (or derived from the encoded
profile name) might not be appropriate in some instances. This allows
overriding them without having to issue a new certificate request.
This allows NM more freedom in regards to how it wants to use the passed
device. In particular, if dnsmasq is used with NM as that binds to the
interface to send requests via VPN.
Installing the VIPs on lo avoids weird address removal/addition events
that happen for IPv6 on the physical interface (which would cause the VIP
to get incorrectly detected as non-VIP address and ignored during
deletion).
We could let NM install routes via XFRM interface, however, that causes
problems with e.g. the bypass-lan plugin (the throw routes in table 220
wouldn't have any effect). We could let it install regular routes in
the main table, but determining the physical interface would be tricky
as the routes installed by NM, also in the main table, would conflict.
So instead we let the kernel-netlink interface install routes via XFRM
interface and to avoid routing the IKE traffic that way, we set a mark
on the IKE socket and exclude traffic with that mark from our routing
table.
Since these might conflict with IKE traffic, this requires special care.
One option is to install bypass policies for the peer, which install
appropriate (throw) routes. However, that won't work if the traffic to
the gateway itself should be protected, in particular, for host-to-host
tunnels. So an alternative is to set a mark for the IKE socket and then
exclude that traffic from table 220 via the kernel-netlink plugin's
fwmark option.
The manager will allow charon-nm to create XFRM interfaces if supported
by the kernel instead of creating an unused dummy TUN interface.
The xfrmi tool is mostly obsolete nowadays as iproute2 supports creating
XFRM interfaces since 5.1.0 (2019-05). Older Debians don't ship that and
early versions didn't list the interface IDs. So there might still be
some uses for this tool.
NM doesn't terminate charon-nm after disconnecting, so the TUN device
previously stayed around even if no connection was established. This
might be a bit more what users expect.
As defined in RFC 9190, a "protected success indication" (0x00) is sent
from the server to the client over the TLS connection when using TLS 1.3.
The client responds with an empty EAP message, which is interpreted as
acknowledgement in our stack.
If we ever support session resumption with tunneled methods such as
EAP-TTLS, we'd have to send such an indication there too.
As noted in 121ac4b9e37e ("tls-crypto: Generate MSK for TLS 1.3"), the
calculation was only preliminary. It is now fixed according to RFC 9190
and draft-ietf-emu-tls-eap-types (soon to become an RFC, currently in
the RFC editor queue).
Fixes: 121ac4b9e37e ("tls-crypto: Generate MSK for TLS 1.3")
Adds support for a change in Linux kernel 6.2 that allows retrieving
the last use time of an SA from the SA itself instead of having to query
the policies.
Has been supported by libipsec for a long time (since 5.1.1). UDP encap
is already enforced via config, this just makes the flags the same as
in kernel-libipsec.
Since 6.2 the Linux kernel updates the last use time per SA. In
previous releases the attribute was only updated and reported for
specific outbound IPv6 SAs.
Using this reduces the number of kernel queries per CHILD_SA: for DPDs
from two policy queries (IN/FWD) to a single query of the inbound SA,
and for status reports the three policy queries (IN/FWD/OUT) can be
omitted and only the two SAs have to be queried. For NAT keepalives the
number of queries doesn't change but a policy query (OUT) is replaced by
a query for the outbound SA.
While we could use the existence of the attribute as indicator for its
support, we don't know this until we queried an SA. By using a version
check we can announce the feature from the start.
Currently supported by libipsec and PF_KEY on macOS (FreeBSD, like Linux,
reports the time the SA was first used in sadb_lifetime_usetime - it also
triggers rekeyings based on that, which Linux doesn't, it also triggers
them if an SA is never used).
Apparently not installed anymore in the latest build image. If it's
missing, we see errors like these:
configure.ac:38: error: possibly undefined macro: AC_DEFINE
This was the order before 46a6b062822c ("openssl: Only announce ECDH
groups actually supported by OpenSSL") but that's not really the reason
for this change. It's related to the Android app, where we previously
didn't support these DH groups in BoringSSL and added the curve25519
plugin after the openssl plugin instead. This resulted in the same
order, i.e. ECDH groups before curve25519. With the switch to OpenSSL
and the mentioned commit, this changed and curve25519 was now the first
group that was proposed and used for the KE payload. Not really an
issue you'd think, however, there are apparently Zyxel Firewalls with
older firmware versions (some forum posts mentioned a fix in V5.31) that
can't handle KE payloads with DH groups > 21 (ecp521). So with
curve25519 (31) proposed in the KE payload, they silently dropped the
IKE_SA_INIT request and no connection could be established.
`public` is returned, but previously only if a trusted key was found.
We obviously don't want to return untrusted keys and since the reference
was correctly destroyed after determining the key type, this later caused
a double-free.
Fixes: 63fd718915b5 ("libtls: call create_public_enumerator() with key_type")
This adds support for the new "packet" hardware offload feature that's
added to the Linux kernel with 6.2. In this mode, the device handles
the complete framing of the ESP packet as well as the policy checks,
in addition to the crypto.
For the IKE sockets, port-based bypass policies are automatically
offloaded to devices that support it.
Closesstrongswan/strongswan#1462
While this uses the same mechanism, it's not necessary to explicitly
enable port_bypass, the regular socket policies work fine to bypass any
software policies.
Keep the kdf plugin because of AES-XCBC (and CAMELLIA-XCBC, which is now
supported due to OpenSSL). Other plugins like fips-prf, pubkey or pkcs8
were never actually used by the app. The random plugin might have been
necessary with early versions.
The build script requires the paths to the NDK and OpenSSL sources.
It runs the build in a Docker container, by default. But if the required
tools are installed on the system (currently jq, make and perl) it can
also be run directly on the system by defining NO_DOCKER.
A relatively recent version of the NDK is required (the pre-built
toolchains are required).
If libcurl is built with MultiSSL support (not the case for e.g.
Debian/Ubuntu, which ship separate, conflicting libraries), this allows
selecting the SSL/TLS backend libcurl uses.
Only older versions of OpenSSL and GnuTLS need special treatment, so we
now accept all other backends (e.g. "(SecureTransport) OpenSSL/1.1.1s"
on macOS).
Whenever we remove support for the affected versions of the mentioned
libraries, we can remove the corresponding *-threading plugin feature
and the code here.
While the kernel defines it since 2005 (2.6.14), some older versions of
socket.h shipped with C libraries might not. In particular, glibc only
added it with 2.24 in 2016.
Closesstrongswan/strongswan#1503
The Python versions installed in the system image in
`/Library/Frameworks/Python.framework/` have symlinks in `/usr/local/bin/`
that conflict with symlinks that `brew` tries to create, which causes
errors like these:
==> Pouring python@3.11--3.11.1.monterey.bottle.tar.gz
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink bin/2to3-3.11
Target /usr/local/bin/2to3-3.11
already exists. You may want to remove it:
rm '/usr/local/bin/2to3-3.11'
To force the link and overwrite all conflicting files:
brew link --overwrite python@3.11
To list all files that would be deleted:
brew link --overwrite --dry-run python@3.11
Possible conflicting files are:
/usr/local/bin/2to3-3.11 -> /Library/Frameworks/Python.framework/Versions/3.11/bin/2to3-3.11
/usr/local/bin/idle3.11 -> /Library/Frameworks/Python.framework/Versions/3.11/bin/idle3.11
/usr/local/bin/pydoc3.11 -> /Library/Frameworks/Python.framework/Versions/3.11/bin/pydoc3.11
/usr/local/bin/python3.11 -> /Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11
/usr/local/bin/python3.11-config -> /Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11-config
Since the changes to the DH implementations that were merged with
30faf04e92dc ("Merge branch 'multi-ke-backport'"), most implementations
don't support deriving different shared secrets for the same private key
by calling set_public_key() with another public key anymore (some prevent
it explicitly, but reusing DH private keys is not something we want to
support anyway). So we can't reuse the DH object on one side for every
round.
With newer kernels (basic support for extended ACKs is there since 4.12
but some messages for XFRM were only added with 6.1) this gives more
detailed error messages to the user than e.g. a generic EINVAL or ENOSYS
error would.
Also enabled omitting the request payload in NLMSG_ERROR messages.
The resolvconf implementation provided by systemd via resolvectl strips
everything after the interface name, so each additional server that's
installed replaces the previous one. And even for other resolvconf
implementations installing them individually doesn't seem necessary as
we track and refcount them anyway.
Closesstrongswan/strongswan#1353
Newer releases of systemd contain a change that removes not the part
after the first dot but the part after the last when determining the
interface name (apparently some interface names actually contain a dot).
This changes the default prefix to only contain one dot and avoids the
dots added by IPv4 addresses to create a unique interface/protocol for
each DNS server (it also replaces the `:` in IPv6 addresses with
something that might cause less conflicts).
References strongswan/strongswan#1353
Since the encryption has been moved into the TKM we don't rely on many
cryptographic operations. Mainly SHA-1 that's used in IKEv2 (NAT-D) and
for some internal hashes (cookies, message duplicate detection), and
certificate and public key parsing (not the actual signature/chain
verification, which is done by the TKM).
When issuing a deregistration message, some last events may still be sent
by the daemon before deregistration completes. Ignore such event messages
silently during deregistration, avoiding exceptions like:
vici.exception.SessionException:
Unexpected response type 7, expected '5' (EVENT_CONFIRM)
The architecture of the Python client is completely blocking, which is fine
for many simple scripts. For more complex applications that do other I/O
and listen for vici events, the most feasible way to integrate the client is
to use a dedicated thread.
Unfortunately, Python has no simple support for thread cancellation. And
having that thread in a blocking recv() does not allow to terminate the
thread gracefully with an Event or the like.
As a way out, add a timeout to the listen() call, so the thread can
periodically do other things, like checking for termination Event and
react on it. Returning from listen() on timeout can be suboptimal, though,
as it involves registration/deregistration for events, including the risk
for missing events while not registered. So return a (None, None) tuple
instead on timeout, allowing the caller to periodically do other things
while staying registered for the events and continue in listen().
The timeout applies to the socket recv() for the start of the header, only,
so a message is either read in full or times out, avoiding the risk
of breaking message framing on the stream with partial reads.
Depending on the configured hard lifetime the default soft lifetime
might not make sense and could even cause rekeying to get disabled.
To avoid that, derive the soft lifetime from the hard lifetime so it's
10% higher than the soft lifetime.
References strongswan/strongswan#1414
Also avoid returning 0 and disabling rekeying in the rare case of
`jitter = rekey` and the `1/jitter` chance of that happening (returning
1 at least doesn't disable rekeying).
Co-authored-by: Tobias Brunner <tobias@strongswan.org>
Closesstrongswan/strongswan#1414
The x509 plugin retrieves serial numbers with two's complement
encoding whereas the openssl plugin partially returns them without
leading zeroes.
Serial numbers in X.509 certificates, X.509 CRL, X.509 attribute
certificates, OCSP Requests and OCSP responses are now returned in
canonical form without prepended zero octets.
Ubuntu 22.04 ships OpenSSL 3, which requires debug symbols so we can
whitelist leaks because we don't deinitialize the library. And because
the shipped library is not built with `-fno-omit-frame-pointer`, the
build with AddressSanitizer can't use its fast stack unwind method.
However, the previous workaround for DTLS handling with glibc apparently
isn't necessary anymore.
In the custom OpenSSL build we drop no-stdio as that lets the configure
check for libldns fail because ERR_print_errors_fp@OPENSSL_3.0.0 is not
found.
For ccache, the default path to the cache directory has changed.
Also simplified the NM tests as there is only one build since
085daf474330 ("nm: Remove old libnm-glib compat stuff").
At least since Ubuntu 22.04 there are lots of (apparently non-fatal)
"DWARF error: could not find variable specification" errors generated
by bfd_find_nearest_line(). This also happens with addr2line, which
internally uses libbfd. No idea what the actual issue is (it still
happens with binutils 2.39 in Ubuntu 22.10), but since it doesn't seem
to affect the functionality we need this avoids filling the test logs
with useless messages.
The wolfSSL's OpenSSL compatibility layer is not used by the plugin at
all and preventing its inclusion avoids conflicts with ASN1_ constants.
The inclusion of wolfssl/ssl.h is moved to the only file that requires
it as older wolfSSL versions defined a conflicting ASN1_GENERALIZEDTIME.
Other changes address issues with the FIPS use case.
Closesstrongswan/strongswan#1332
A recent change added CALLBACK to PENUM_PAGE_FILE_CALLBACKW/A in psapi.h,
which conflicts with our own macro of the same name. Our compat/windows.h
header undefs the Windows definition, but that only works if Windows
headers are included before ours, which wasn't the case for psapi.h.
This avoids a conflicts as mysql80-client has a dependency on either
openldap24-client (FreeBSD 12) or openldap26-client (FreeBSD 13) so e.g.
installing openldap24-client on FreeBSD 13 causes
openldap26-client-2.6.3 conflicts with openldap24-client-2.4.59_4 on /usr/local/bin/ldapadd
Similarly, when installing openldap26-client on FreeBSD 12. So just let
the mysql80-client package decide which version is installed.
There are spurious crashes after test runs (during the reporting phase
of LeakSanitizer) that are triggered by seemingly unrelated code changes.
It seems to be related to how glibc handles dynamic TLS allocations.
Malicious servers could otherwise block the fetching thread indefinitely
after the initial TCP handshake (which has a default timeout of 10s
in the curl and winhttp plugins, the soup plugin actually has a default
overall timeout of 10s).
This avoids querying URLs of potentially untrusted certificates, e.g. if
an attacker sends a specially crafted end-entity and intermediate CA
certificate with a CDP that points to a server that completes the
TCP handshake but then does not send any further data, which will block
the fetcher thread (depending on the plugin) for as long as the default
timeout for TCP. Doing that multiple times will block all worker threads,
leading to a DoS attack.
The logging during the certificate verification obviously changes. The
following example shows the output of `pki --verify` for the current
strongswan.org certificate:
new:
using certificate "CN=www.strongswan.org"
using trusted intermediate ca certificate "C=US, O=Let's Encrypt, CN=R3"
using trusted ca certificate "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
reached self-signed root ca with a path length of 1
checking certificate status of "CN=www.strongswan.org"
requesting ocsp status from 'http://r3.o.lencr.org' ...
ocsp response correctly signed by "C=US, O=Let's Encrypt, CN=R3"
ocsp response is valid: until Jul 27 12:59:58 2022
certificate status is good
checking certificate status of "C=US, O=Let's Encrypt, CN=R3"
ocsp response verification failed, no signer certificate 'C=US, O=Let's Encrypt, CN=R3' found
fetching crl from 'http://x1.c.lencr.org/' ...
using trusted certificate "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
crl correctly signed by "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
crl is valid: until Apr 18 01:59:59 2023
certificate status is good
certificate trusted, lifetimes valid, certificate not revoked
old:
using certificate "CN=www.strongswan.org"
using trusted intermediate ca certificate "C=US, O=Let's Encrypt, CN=R3"
checking certificate status of "CN=www.strongswan.org"
requesting ocsp status from 'http://r3.o.lencr.org' ...
ocsp response correctly signed by "C=US, O=Let's Encrypt, CN=R3"
ocsp response is valid: until Jul 27 12:59:58 2022
certificate status is good
using trusted ca certificate "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
checking certificate status of "C=US, O=Let's Encrypt, CN=R3"
ocsp response verification failed, no signer certificate 'C=US, O=Let's Encrypt, CN=R3' found
fetching crl from 'http://x1.c.lencr.org/' ...
using trusted certificate "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
crl correctly signed by "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
crl is valid: until Apr 18 01:59:59 2023
certificate status is good
reached self-signed root ca with a path length of 1
certificate trusted, lifetimes valid, certificate not revoked
Note that this also fixes an issue with the previous dual-use of the
`trusted` flag. It not only indicated whether the chain is trusted but
also whether the current issuer is the root anchor (the corresponding
flag in the `cert_validator_t` interface is called `anchor`). This was
a problem when building multi-level trust chains for pre-trusted
end-entity certificates (i.e. where `trusted` is TRUE from the start).
This caused the main loop to get aborted after the first intermediate CA
certificate and the mentioned `anchor` flag wasn't correct in any calls
to `cert_validator_t` implementations.
Fixes: CVE-2022-40617
This forces the use of a semicolon after INIT() and makes existing ones,
which was the case for basically all instances, necessary so e.g.
sonarcloud won't complain about an empty statement after every one of
them.
By evaluating to the allocated object, it would theoretically also allow
constructs like this:
struct_t *this;
return INIT(this,
.a = x,
.b = y,
);
or this:
array_insert(a, ARRAY_TAIL, INIT(this,
.a = x,
.b = y,
));
If e.g. the hmac plugin is loaded before the third-party crypto lib
plugin, we might not use the latter's HMAC implementation in some
cases (e.g. in the libtls tests).
This makes sure the event is only triggered after the IKE_SA is fully
established and e.g. virtual IPs, additional peer addresses or
a modified reauth time (on the initiator) are assigned to it. This was
e.g. a problem for the selinux plugin if virtual IPs are used.
We use a separate task to trigger the event that's queued before the
child-create task so the event is triggered before the child_updown()
event. Same goes for the state change to IKE_ESTABLISHED.
A new condition is used to indicate the successful completion of all
authentication rounds, so we don't have to set the IKE_ESTABLISHED state
in the ike-auth task (it was used as condition in other tasks).
Since set_state() also sets the rekey and reauth times, this required
some minor changes in regards to how AUTH_LIFETIME notifies are handled.
Since e334bd46b184 ("ike-auth: Move packet collection to post_build()
method") tasks and plugins can modify the IKE_SA_INIT message independent
of the ike-auth task.
Otherwise, we can't open a dedicated IPv4 socket on the same port as the
IPv6 socket already is set up do receive IPv4 packets (unless we'd again
enable SO_REUSEADDR).
Fixes: 83da13371292 ("socket-default: Don't set SO_REUSEADDR on IKE sockets anymore")
The default is apparently "Connection: keep-alive", which somehow keeps
the socket around, which leaks file descriptors with every connection
that fetches OCSP and/or CRLs. Over time that could result in the number
of FDs reaching a limit e.g. imposed by FD_SET().
Closesstrongswan/strongswan#1160
The linter complained that two of the strings don't actually contain any
printf-specifiers (i.e. don't expect any arguments) and therefore
shouldn't be used with String.format().
This was originally required when pluto and charon both bound sockets to
the same port to send messages. Pluto also received messages on them but
charon didn't and used a raw socket instead. Since the removal of pluto
we don't need to set this option anymore, which might actually mask
mistakes like running charon and charon-systemd concurrently (that could
result in messages getting sent fine by both daemons but only received
by one).
Note that a failure to create/bind the sockets will not immediately
result in a shutdown of the daemon. Instead, there will be an error
once the receiver tries to read any messages and also whenever the sender
attempts to send a request.
Changes the type for EAP vendor IDs from uint32_t to pen_t, which has
explicitly been added to represent three-byte IANA-allocated Private
Enterprise Numbers (PEN), which the EAP RFC called "SMI Network
Management Private Enterprise Codes".
References strongswan/strongswan#581
Content-Transfer-Encoding is actually not a valid HTTP header, but a MIME
header, and must not be used. The original RFC7030 specifies this wrong,
and an errata discusses this issue.
The use of base64 encoding has been clarified in RFC8951, and the
recommendation is to always use/expect base64 encoding, but not send/expect
the Content-Transfer-Encoding header.
There should be no need for such a persistent documentation on a removed
component in the repository. The commit history is enough. And besides
that, there is user-facing documentation about it in the docs and the
changelog/NEWS.
There are a lot of calls like this:
this->dispatcher->raise_event(this->dispatcher, "...", 0,
b->finalize(b));
However, if finalize() fails, e.g. because a previous call to add()
failed due to the size limit, it returns NULL. This then caused a
segmentation fault in raise_event() when it interacted with that value.
Closesstrongswan/strongswan#1278
This fixes a race condition during shutdown between the main thread
flushing the IKE_SA manager and worker threads still creating IKE_SAs.
Closesstrongswan/strongswan#1252
Because flush() has to release the segment locks intermittently, threads
might add new entries (even with the change in the previous commit as the
IKE_SA might already be created, just not registered/checked in yet).
Since those entries are added to the front of the segment lists, the
enumerator in the previous step 2 didn't notice them and did not wait
for them to get checked in. However, step 3 and 4 then proceeded to
delete and destroy the entry and IKE_SA, which could lead to a crash
once the other thread attempts to check in the already destroyed IKE_SA.
This change combines the three loops of steps 2-4 but then loops over
the whole table until it's actually empty. This way we wait for and
destroy newly added entries.
Without ability to create SPIs, other threads are prevented from creating
new IKE_SAs while we are flushing existing IKE_SAs. However, there could
still be IKE_SAs already created that might get checked in while the
segments are temporarily unlocked to wait for threads to check existing
SAs in.
This is more consistent and e.g. allows to properly take into account
some settings that are also relevant during IKE_AUTH (e.g. childless).
We also already use the peer_cfg_t's ike_cfg_t when rekeying,
reauthenticating and reestablishing an IKE_SA (and e.g. for DSCP).
Also changed are some IKEv1 cases where get_ike_cfg() is called before
set_peer_cfg() without taking a reference to the ike_cfg_t that might
get replaced/destroyed (none of the cases were problematic, though, but
it also wasn't necessary to keep the ike_cfg_t around).
Closesstrongswan/strongswan#1238
The pattern currently is to call get_cache(), generate the encoding
if that failed and then store it with cache(). The latter adopts the
passed encoding and frees any stored encoding. However, the latter means
that if two threads concurrently fail to get a cached encoding and then
both generate and store one, one of the threads might use an encoding
that was freed by the other thread.
Since encodings are not expected to change, we can avoid this issue by
not replacing an existing cache entry and instead return that (while
freeing the passed value instead of the cached one).
Closesstrongswan/strongswan#1231
When watching the output of `swanctl -l` during debugging, the debug
messages in query_sa/policy() cause a lot of noise in the logs (level 2
for DBG_KNL still has actually useful information that we want to see
in the logs) and they're not very useful.
Compared to the messages in the functions above, the ones in update_sa()
and get_replay_state() are not seen often. But since there already is a
log message on level 2 in update_sa(), they're kinda redundant.
Closesstrongswan/strongswan#1271
At least for the tests where it is available and works. It conflicts
with the instrumentation used by the coverage and fuzzing (and possibly
sonarcloud) tests, the toolchain for the Windows builds doesn't seem to
support it, and on FreeBSD the test executables hang due to a
compatibility issue with FreeBSD's qsort(), which has been fixed [1],
but that has not made it into the clang version in the base system.
For the custom OpenSSL build, debug symbols are enabled so we can
suppress some leaks properly.
[1] https://github.com/llvm/llvm-project/issues/46176
Only the second was reported by the compiler (depending on the version
and similarly to the previous commit only with AddressSanitizer active).
The strncpy() call for UTUN_CONTROL_NAME was simply wrong.
Normally, GCC sees that we terminate the destination with a zero byte.
However, when using `-fsanitize=address`, there seems to be additional
instrumentation code after strncpy() so GCC produces warnings like
these:
‘__builtin_strncpy’ specified bound 16 equals destination size [-Wstringop-truncation]
This causes odr-violation errors with libasan as some symbols will be
defined twice, once in the linked libimcv and once in the test
executable itself.
When using the statement expression and a stack object along with
clang-11 and libasan, we get quite a lot of errors about reading
invalid memory. This is due to clang making the actual listener_t local
to the block, such that the access outside of the macros using
_assert_payload is (correctly) considered an error.
By using a heap allocated object, we can destroy it once the listener
returns FALSE (cleaning up properly), and since bus_t does not touch the
listener after that, we don't get any errors from libasan.
Co-authored-by: Tobias Brunner <tobias@strongswan.org>
As the cleanup function reads from the correct address on the parent frame,
it is currently unclear why AddressSanitizer complains about that pointer
dereference.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.