Tobias Brunner [Mon, 9 Jan 2023 14:19:43 +0000 (15:19 +0100)]
charon-nm: Use an XFRM interface if available
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.
Tobias Brunner [Mon, 9 Jan 2023 14:10:55 +0000 (15:10 +0100)]
kernel-netlink: Add an option to install routes for SAs with XFRM interfaces
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.
Tobias Brunner [Thu, 5 Jan 2023 15:24:42 +0000 (16:24 +0100)]
charon-nm: Tie lifetime of dummy TUN device to connection
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.
Tobias Brunner [Fri, 12 Feb 2021 12:25:05 +0000 (13:25 +0100)]
tls-crypto: Fix MSK calculation for TLS 1.3
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")
Tobias Brunner [Wed, 22 Feb 2023 12:21:31 +0000 (13:21 +0100)]
Merge branch 'kernel-netlink-sa-lastused'
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.
Tobias Brunner [Thu, 23 Jun 2022 14:38:02 +0000 (16:38 +0200)]
android: Announce support for TFC padding
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.
Tobias Brunner [Thu, 23 Jun 2022 14:15:45 +0000 (16:15 +0200)]
kernel-netlink: Read last use time from SA if possible
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.
Tobias Brunner [Thu, 23 Jun 2022 13:59:56 +0000 (15:59 +0200)]
kernel-interface: Add feature to indicate if query_sa() returns last use time
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).
Tobias Brunner [Fri, 17 Feb 2023 15:28:07 +0000 (16:28 +0100)]
openssl: Add curve25519 and curve448 after ECDH groups
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.
Tobias Brunner [Fri, 17 Feb 2023 14:07:20 +0000 (15:07 +0100)]
libtls: Fix double-free for untrusted peer certificates
`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")
Tobias Brunner [Fri, 17 Feb 2023 12:27:37 +0000 (13:27 +0100)]
Merge branch 'hw-packet-offload'
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.
Tobias Brunner [Fri, 27 Jan 2023 13:08:41 +0000 (14:08 +0100)]
kernel-netlink: Offload bypass policies for IKE ports on interfaces
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.
Tobias Brunner [Fri, 10 Feb 2023 09:36:50 +0000 (10:36 +0100)]
android: Clean up plugin list after switching to OpenSSL
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.
Tobias Brunner [Thu, 9 Feb 2023 15:39:08 +0000 (16:39 +0100)]
android: Add a script to build OpenSSL's libcrypto as needed by the app
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).
Tobias Brunner [Fri, 13 Jan 2023 16:17:06 +0000 (17:17 +0100)]
curl: Add an option to select the SSL/TLS backend (if available)
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.
Tobias Brunner [Fri, 13 Jan 2023 16:11:50 +0000 (17:11 +0100)]
curl: Don't ignore unknown SSL/TLS backends
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.
Tobias Brunner [Mon, 9 Jan 2023 15:57:53 +0000 (16:57 +0100)]
kernel-netlink: Define SOL_NETLINK for old versions of socket.h
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.
Tobias Brunner [Fri, 6 Jan 2023 13:17:29 +0000 (14:17 +0100)]
github: Workaround for Python conflict in macOS image
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
Tobias Brunner [Fri, 6 Jan 2023 10:28:37 +0000 (11:28 +0100)]
dh-speed: Don't reuse DH object
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.
Tobias Brunner [Tue, 13 Dec 2022 09:50:06 +0000 (10:50 +0100)]
resolve: Don't install individual servers via resolvconf
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.
Tobias Brunner [Wed, 19 Oct 2022 13:55:04 +0000 (15:55 +0200)]
resolve: Avoid dots in protocol part of interface names when using resolvconf
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).
Tobias Brunner [Thu, 1 Dec 2022 16:58:08 +0000 (17:58 +0100)]
charon-tkm: Use built-in plugins instead of OpenSSL
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).
Martin Willi [Mon, 14 Nov 2022 10:55:30 +0000 (11:55 +0100)]
vici: Gracefully consume/ignore incoming events in Python event deregistration
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)
Martin Willi [Fri, 4 Nov 2022 11:00:28 +0000 (12:00 +0100)]
vici: Allow the Python event listen() operation to optionally time out
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.
Tobias Brunner [Tue, 6 Dec 2022 16:33:20 +0000 (17:33 +0100)]
vici: Base default soft lifetime on hard lifetime if configured
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.
child-cfg: Fix apply_jitter() in case jitter is bigger than rekey value
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).