]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
kernel-interface: Change reqid if seq. nos. are supported and narrowing occurred
authorTobias Brunner <tobias@strongswan.org>
Thu, 20 Mar 2025 13:52:32 +0000 (14:52 +0100)
committerTobias Brunner <tobias@strongswan.org>
Wed, 28 May 2025 08:01:19 +0000 (10:01 +0200)
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).

src/libcharon/kernel/kernel_interface.c
src/libcharon/kernel/kernel_interface.h
src/libcharon/sa/child_sa.c

index ba5c03b9bfc520f73e962f6409eed958ab8efb7e..b752ad744443ccb8866ebb78993d627b10259ad6 100644 (file)
@@ -392,12 +392,19 @@ METHOD(kernel_interface_t, alloc_reqid, status_t,
                /* search by reqid if given */
                entry = this->reqids->get(this->reqids, tmpl);
        }
-       if (entry && entry_equals_selectors(entry, tmpl))
+
+       /* if the IPsec stack supports sequence numbers for acquires, we can
+        * allocate a new reqid if narrowing occurred (otherwise, we get the same
+        * reqid back anyway).  if not, we want to reuse the existing reqid of
+        * the trap polices and explicitly don't want to match the traffic
+        * selectors.  another case where we want to reuse an existing reqid is
+        * when labels are used.  because we currently only install policies once
+        * with the generic label, the reqid has to stay the same even if narrowing
+        * occurs.  however, in either case we don't want to reuse the reqid if the
+        * additional selectors (e.g. marks) are different */
+       if (entry && (label || !(get_features(this) & KERNEL_ACQUIRE_SEQ)) &&
+               entry_equals_selectors(entry, tmpl))
        {
-               /* we don't require a traffic selector match for existing reqids,
-                * as we want to reuse a reqid for trap-triggered policies that
-                * got narrowed during negotiation, but we don't want to reuse the
-                * reqid if the additional selectors (e.g. marks) are different */
                reqid_entry_destroy(tmpl);
        }
        else
index a70e7f86066e53028f889800974e1e2af8e84b15..21cabe7f0951e9b82da198ce906c641b11ed0d63 100644 (file)
@@ -81,6 +81,8 @@ enum kernel_feature_t {
        KERNEL_POLICY_SPI = (1<<4),
        /** IPsec backend reports use time per SA via query_sa() */
        KERNEL_SA_USE_TIME = (1<<5),
+       /** IPsec backend associates acquires and SAs with a sequence number */
+       KERNEL_ACQUIRE_SEQ = (1<<6),
 };
 
 /**
index 3c4f721caebbec72c5aca04ee3bb910abde6a51d..abb98a2f4ed8efd62e9f94088f288ea3ccee2033 100644 (file)
@@ -2163,13 +2163,14 @@ child_sa_t *child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
        if (!this->reqid)
        {
                /* reuse old reqid if we are rekeying an existing CHILD_SA and when
-                * initiating a trap policy. While the reqid cache would find the same
-                * reqid for our selectors, this does not work in a special case: If an
-                * SA is triggered by a trap policy, but the negotiated TS get
-                * narrowed, we still must reuse the same reqid to successfully
-                * replace the temporary SA on the kernel level. Rekeying such an SA
-                * requires an explicit reqid, as the cache currently knows the original
-                * selectors only for that reqid. */
+                * initiating a trap policy. the reqid cache will generally find the
+                * same reqid for our selectors. but this does not work in a special
+                * case: if the IPsec stack does not use sequence numbers for acquires,
+                * an SA is triggered by a trap policy and the negotiated TS get
+                * narrowed, we still must reuse the same reqid to successfully replace
+                * the temporary SA on the kernel level. however, if sequence numbers
+                * are supported, the reqid will later get updated in case of narrowing
+                * when alloc_reqid() is called */
                if (data->reqid &&
                        charon->kernel->ref_reqid(charon->kernel, data->reqid) == SUCCESS)
                {