x509: Add flag that marks compliance with RFC 4945
According to RFC 4945, section 5.1.3.2, a certificate for IKE must
either not contain the keyUsage extension, or, if it does, have at least
one of the digitalSignature or nonReputiation bits set.
Tobias Brunner [Tue, 22 May 2018 07:44:51 +0000 (09:44 +0200)]
Merge branch 'dhcp-fixes'
Fixes some issues in the dhcp plugin like avoiding ICMP port unreachables
when setting a specific server address, or increasing the maximum size for
options e.g. for DNs in the client identifier option. The latter is also
only sent now if identity_lease is enabled (for most DHCP servers it
serves the same function as a unique MAC address does).
dhcp: Only send client identifier if identity_lease is enabled
The client identifier serves as unique identifier just like a unique MAC
address would, so even with identity_leases disabled some DHCP servers
might assign unique leases per identity.
dhcp: Increase maximum size of client identification option
This increases the chances that subject DNs that might have been cut
off with the arbitrary previous limit of 64 bytes might now be sent
successfully.
The REQUEST message has the most static overhead in terms of other
options (17 bytes) as compared to DISCOVER (5) and RELEASE (7).
Added to that are 3 bytes for the DHCP message type, which means we have
288 bytes left for the two options based on the client identity (host
name and client identification). Since both contain the same value, a
FQDN identity, which causes a host name option to get added, may be
142 bytes long, other identities like subject DNs may be 255 bytes
long (the maximum for a DHCP option).
dhcp: Increase buffer size for options in DHCP messages
According to RFC 2131, the minimum size of the 'options' field is 312
bytes, including the 4 byte magic cookie. There also does not seem to
be any restriction regarding the message length, previously the length
was rounded to a multiple of 64 bytes. The latter might have been
because in BOOTP the options field (or rather vendor-specific area as it
was called back then) had a fixed length of 64 bytes (so max(optlen+4, 64)
might actually have been what was intended), but for DHCP the field is
explicitly variable length, so I don't think it's necessary to pad it.
Since we won't read from the socket reducing the receive buffer saves
some memory and it should also minimize the impact on other processes that
bind the same port (Linux distributes packets to the sockets round-robin).
dhcp: Bind server port when a specific server address is specified
DHCP servers will respond to port 67 if giaddr is non-zero, which we set
if we are not broadcasting. While such messages are received fine via
RAW socket the kernel will respond with an ICMP port unreachable if no
socket is bound to that port. Instead of opening a dummy socket on port
67 just to avoid the ICMPs we can also just operate with a single
socket, bind it to port 67 and send our requests from that port.
Since SO_REUSEADDR behaves on Linux like SO_REUSEPORT does on other
systems we can bind that port even if a DHCP server is running on the
same host as the daemon (this might have to be adapted to make this work
on other systems, but due to the raw socket the plugin is not that portable
anyway).
Tobias Brunner [Fri, 16 Mar 2018 08:59:25 +0000 (09:59 +0100)]
dhcp: Fix destination port check in packet filter
The previous code compared the port in the packet to the client port and, if
successful, checked it also against the server port, which, therefore, never
matched, but due to incorrect offsets did skip the BPF_JA. If the client port
didn't match the code also skipped to the instruction after the BPF_JA.
However, the latter was incorrect also and processing would have continued at
the next instruction anyway. Basically, DHCP packets to any port were accepted.
What's not fixed with this is that the kernel returns an ICMP Port
unreachable for packets sent to the server port (67) because we don't
have a socket bound to it.
Fixes: f0212e8837b5 ("Accept DHCP replies on bootps port, as we act as a relay agent if server address configured")
This patch allows for giving strongSwan only the runtime capabilities it
needs, rather than full root privileges.
Adds preprocessor directives which allow strongSwan to be configured to
1) start up as a non-root user
2) avoid modprobe()'ing IPsec kernel modules into the kernel, which
would normally require root or CAP_SYS_MODULE
Additionally, some small mods to charon/libstrongswan ensure that charon
fully supports starting as a non-root user.
We don't have MOBIKE and the fallback to reauthentication does also not
make much sense as that doesn't affect the CHILD_SAs for IKEv1. So
instead of complicating the code we just ignore roam events for IKEv1
for now.
controller: Remove special handling for routed CHILD_SAs when terminating
In very early versions routed CHILD_SAs were attached to IKE_SAs, since
that's not the case anymore (they are handled via trap manager), we can
remove this special handling.
proposal: Don't specify key length for ChaCha20/Poly1305
This algorithm uses a fixed-length key and we MUST NOT send a key length
attribute when proposing such algorithms.
While we could accept transforms with key length this would only work as
responder, as original initiator it wouldn't because we won't know if a
peer requires the key length. And as exchange initiator (e.g. for
rekeyings), while being original responder, we'd have to go to great
lengths to store the condition and modify the sent proposal to patch in
the key length. This doesn't seem worth it for only a partial fix.
This means, however, that ChaCha20/Poly1305 can't be used with previous
releases (5.3.3 an newer) that don't contain this fix.
ikev2: Reuse marks and reqid of CHILD_SAs during MBB reauthentication
Since these are installed overlapping (like during a rekeying) we have to use
the same (unique) marks (and possibly reqid) that were used previously,
otherwise, the policy installation will fail.
Tobias Brunner [Thu, 29 Mar 2018 09:23:15 +0000 (11:23 +0200)]
ike: Float to port 4500 if either port is 500
If the responder is behind a NAT that remaps the response from the
statically forwarded port 500 to a new external port (as Azure seems to be
doing) we should still switch to port 4500 if we used port 500 so far as
it would not have been possible to send any messages to it if it wasn't
really port 500 (we only add a non-ESP marker if neither port is 500).
traffic-selector: Always print protocol if either protocol or port is set
This helps to distinguish between port and protocol if only one of them
is set. If no protocol is set it's printed as 0, if the traffic
selector covers any port (0-65535) the slash that separates the two values
and the port is omitted.
This adds a new state for CHILD_SAs that we deleted but still keep
around to process delayed packets (IKEv2 only). This allows us to treat
them specially in some cases (e.g. to avoid triggering child_updown()
events as we already did that when we deleted such SAs).
ikev1: Unify child_updown calls when having duplicate QMs
If a Quick mode is initiated for a CHILD_SA that is already installed
we can identify this situation and rekey the already installed CHILD_SA.
Otherwise we end up with several CHILD_SAs in state INSTALLED which
means multiple calls of child_updown are done. Unfortunately,
the deduplication code later does not call child_updown() (so up and down
were not even).
Tobias Brunner [Wed, 21 Mar 2018 09:32:48 +0000 (10:32 +0100)]
Merge branch 'hw-offload-auto'
This lets IPsec SA installation explicitly fail if HW offload is enabled
but either the kernel or the device don't support it. And it adds a new
configuration mode 'auto', which enables HW offload, if supported, but
does not fail the installation otherwise.
Adi Nissim [Mon, 12 Mar 2018 14:34:20 +0000 (16:34 +0200)]
kernel-netlink: Add new automatic hw_offload mode
Until now there were 2 hw_offload modes: no/yes
* hw_offload = no : Configure the SA without HW offload.
* hw_offload = yes : Configure the SA with HW offload.
In this case, if the device does not support
offloading, SA creation will fail.
This commit introduces a new mode: hw_offload = auto
----------------------------------------------------
If the device and kernel support HW offload, configure
the SA with HW offload, but do not fail SA creation otherwise.
Signed-off-by: Adi Nissim <adin@mellanox.com> Reviewed-by: Aviv Heller <avivh@mellanox.com>
Martin Willi [Mon, 12 Mar 2018 06:16:52 +0000 (07:16 +0100)]
charon: Ignore an existing PID file if it references ourself
If a daemon PID file references the process that does the check, it is safe
to ignore it; no running process can have the same PID. While this is rather
unlikely to get restarted with the same PID under normal conditions, it is
quite common when running inside PID namespaced containers: If a container
gets stopped and restarted with a PID file remaining, it is very likely that
the PID namespace assigns the same PID to our service, as they are assigned
sequentially starting from 1.
Tobias Brunner [Tue, 13 Mar 2018 11:13:47 +0000 (12:13 +0100)]
diffie-hellman: Don't set exponent length for DH groups with prime order subgroups
According to RFC 5114 the exponent length for these groups should always equal
the size of their prime order subgroup.
This was handled correctly before the initialization was done during
library initialization.
Fixes: 46184b07c163 ("diffie-hellman: Explicitly initialize DH exponent sizes during initialization")
Tobias Brunner [Tue, 6 Mar 2018 16:28:33 +0000 (17:28 +0100)]
ikev2: Use correct type to check for selected signature scheme
The previous code was obviously incorrect and caused strange side effects
depending on the compiler and its optimization flags (infinite looping seen
with GCC 4.8.4, segfault when destroying the private key in build() seen
with clang 4.0.0 on FreeBSD).
Tobias Brunner [Mon, 5 Mar 2018 08:45:34 +0000 (09:45 +0100)]
pkcs5: Parse PRF algorithms if given in PBKDF2-params as defined in RFC 8018
We can't use ASN1_DEF, which would technically be more correct, as the
ASN.1 parser currently can't handle that. For algorithm identifiers we
often use ASN1_EOC as type (with ASN1_RAW), however, that doesn't work with
ASN1_DEF because the element is assumed missing if the type doesn't match.
On the other hand, we can't set the type to ASN1_SEQUENCE because then the
parser skips the following rule if the element is missing (it does so for
all constructed types, but I guess is mainly intended for context tags),
which in this case overruns the parser rules array.
Tobias Brunner [Wed, 7 Mar 2018 13:25:48 +0000 (14:25 +0100)]
Merge branch 'unknown-transform-types'
This changes how unknown transform types are handled in proposals. In
particular we make sure not to accept a proposal if it contains unknown
transform types (they were just ignored previously, which could have
resulted in an invalid selected proposal).
Tobias Brunner [Fri, 23 Feb 2018 08:02:49 +0000 (09:02 +0100)]
proposal: Make sure to consider all transform types when selecting proposals
This way there will be a mismatch if one of the proposals contains
transform types not contained in the other (the fix list of transform
types used previously resulted in a match if unknown transform types
were contained in one of the proposals). Merging the sets of types
makes comparing proposals with optional transform types easier (e.g.
DH for ESP with MODP_NONE).
Tobias Brunner [Fri, 23 Feb 2018 08:28:08 +0000 (09:28 +0100)]
Merge branch 'incorrect-inval-ke'
This improves the behavior during CREATE_CHILD_SA exchanges if the peer
sends an INVALID_KE_PAYLOAD with a DH group we didn't request or continues
to return the same notify even if we use the requested group.
Tobias Brunner [Fri, 9 Feb 2018 14:16:24 +0000 (15:16 +0100)]
child-create: Make sure we actually propose the requested DH group
If we receive an INVALID_KE_PAYLOAD notify we should not just retry
with the requested DH group without checking first if we actually propose
the group (or any at all).
Tobias Brunner [Wed, 21 Feb 2018 10:04:45 +0000 (11:04 +0100)]
child-sa: Don't update outbound policies if they are not installed
After a rekeying we keep the inbound SA and policies installed for a
while, but the outbound SA and policies are already removed. Attempting
to update them could get the refcount in the kernel interface out of sync
as the additional policy won't be removed when the CHILD_SA object is
eventually destroyed.
Tobias Brunner [Thu, 22 Feb 2018 10:31:14 +0000 (11:31 +0100)]
Merge branch 'trap-manager-uninstall'
This changes how trap policies are deleted in order to avoid conflicts if a
trap policy with changed peer config is concurrently removed and reinstalled
under a different name (the reqid will be the same, so the wrong policy
could have been deleted by the old code).
Tobias Brunner [Fri, 3 Nov 2017 10:49:45 +0000 (11:49 +0100)]
child-sa: No need to find reqid of existing trap policy
When initiating a trap policy we explicitly pass the reqid along. I guess
the lookup was useful to get the same reqid if a trapped CHILD_SA is manually
initiated. However, we now get the same reqid anyway if there is no
narrowing. And if the traffic selectors do get narrowed the reqid will be
different but that shouldn't be a problem as that doesn't cause an issue with
any temporary SAs in the kernel (this is why we pass the reqid to the
triggered CHILD_SA, otherwise, no new acquire would get triggered for
traffic that doesn't match the wider trap policy).
Tobias Brunner [Fri, 3 Nov 2017 10:32:04 +0000 (11:32 +0100)]
trap-manager: Remove reqid parameter from install() and change return type
Reqids for the same traffic selectors are now stable so we don't have to
pass reqids of previously installed CHILD_SAs. Likewise, we don't need
to know the reqid of the newly installed trap policy as we now uninstall
by name.