Hello,

I've prepared strongswan 5.9.8-5+deb12u6 for bookworm-security, and it's ready 
for review.

DSA-6487-1 already shipped these fixes in strongswan 6.0.1-6+deb13u7 in Trixie. 
CVE-2026-78133 is on that list too, but the code it fixes arrived in 6.0.0, so 
strongswan 5.9.8 in Bookworm doesn't have it. The debdiff against 
5.9.8-5+deb12u5 is attached.

- CVE-2026-78123: Checking a PKCS#7 signature could read past the end of a 
buffer when the signer was identified by a subject key instead of an issuer and 
serial. This build makes sure that structure is actually there.
- CVE-2026-78124: Enumerating certificates out of a PKCS#7 container leaked 
them, and IKEv1 can trigger that. This build frees them.
- CVE-2026-78126: EAP-AKA crashed if the client sent a synchronization failure 
before the server had issued a challenge. This build ignores that message 
unless a challenge is in progress.
- CVE-2026-78127: Logging an IKE message leaked a small amount of memory when 
the debug string didn't fit in the buffer. This build frees that enumerator.
- CVE-2026-78129: A PKCS#5 blob with a huge iteration count, key length, or 
salt could stall a thread. strongswan 6.0.1-6+deb13u7 in Trixie already rejects 
iteration counts above 1000000, keys above 64 bytes, and salts above 128 bytes, 
and this build does the same.
- CVE-2026-78130: An attribute certificate with no issuer name and no authority 
key identifier crashed while it was being checked. This build treats that 
certificate as untrusted.
- CVE-2026-78131: Parsing an attribute certificate with a lot of names or key 
identifiers leaked. This build frees those.
- CVE-2026-78132: A crafted attribute certificate could make the parser loop 
forever. This build rejects it.
- CVE-2026-78134: EAP-TTLS and EAP-PEAP could leave the IKE SA bound to the 
identity the peer claimed, instead of the one the inner method authenticated. 
This build returns that inner identity. get_auth was already on the EAP method 
struct, and the extra pointer sits at the end of the plugin's private struct, 
so there are no new exported symbols.
- CVE-2026-78135: The old CREATE_CHILD_SA check only ran when no tasks were 
queued, so during EAP it never fired and a Child SA could be installed on an 
IKE SA that wasn't up yet. This build rejects that request while the IKE SA is 
still coming up.

I built this in a Bookworm schroot. Against strongswan 5.9.8-5+deb12u5 from the 
archive, the PKCS#7 and attribute-certificate bugs still fire, EAP-AKA still 
crashes, a huge PKCS#5 iteration count still stalls, the IKE log still leaks, 
EAP-TTLS still keeps the outer identity, and a CREATE_CHILD_SA during EAP still 
installs a Child SA. None of that happens with 5.9.8-5+deb12u6. The package 
test suite is clean on both versions, and a normal connection still comes up.

Here is my Salsa fork: 
https://salsa.debian.org/tsimonq2/strongswan/-/tree/debian/bookworm

Here is the Debusine work request: 
https://debusine.debian.net/debian/developers/work-request/1558827/

Feedback is welcome. If nothing showstopping comes up, I'll upload this and 
issue the DLA on Monday morning (November 2nd, 2026).

Best regards,
Simon Quigley
[email protected]
diff -Nru strongswan-5.9.8/debian/changelog strongswan-5.9.8/debian/changelog
--- strongswan-5.9.8/debian/changelog   2026-05-27 01:58:30.000000000 -0500
+++ strongswan-5.9.8/debian/changelog   2026-10-29 11:10:51.000000000 -0500
@@ -1,3 +1,25 @@
+strongswan (5.9.8-5+deb12u6) bookworm-security; urgency=high
+
+  * Non-maintainer upload by the LTS Team.
+  * CVE-2026-78123: Fix undefined memory access when verifying PKCS#7
+    containers.
+  * CVE-2026-78124: Fix memory leaks after enumerating certificates in
+    PKCS#7 containers.
+  * CVE-2026-78126: Fix a NULL-pointer dereference in EAP-AKA.
+  * CVE-2026-78127: Fix a memory leak in IKE message logging.
+  * CVE-2026-78129: Reject oversized PKCS#5 parameters that can stall
+    a thread.
+  * CVE-2026-78130: Fix a NULL-pointer dereference when an attribute
+    certificate has no issuer.
+  * CVE-2026-78131: Fix memory leaks when parsing x509 attribute
+    certificates.
+  * CVE-2026-78132: Fix an infinite loop when parsing x509 attribute
+    certificates.
+  * CVE-2026-78134: Bind the inner EAP identity to the IKE SA.
+  * CVE-2026-78135: Reject CREATE_CHILD_SA on an unestablished IKE SA.
+
+ -- Simon Quigley <[email protected]>  Thu, 29 Oct 2026 11:10:51 -0500
+
 strongswan (5.9.8-5+deb12u5) bookworm-security; urgency=medium
 
   * d/patches: add fix for double-free when cloning empty IDs (CVE-2026-47895)
diff -Nru 
strongswan-5.9.8/debian/patches/0017-openssl-Fix-undefined-memory-access-when-verifying-P.patch
 
strongswan-5.9.8/debian/patches/0017-openssl-Fix-undefined-memory-access-when-verifying-P.patch
--- 
strongswan-5.9.8/debian/patches/0017-openssl-Fix-undefined-memory-access-when-verifying-P.patch
     1969-12-31 18:00:00.000000000 -0600
+++ 
strongswan-5.9.8/debian/patches/0017-openssl-Fix-undefined-memory-access-when-verifying-P.patch
     2026-10-27 11:22:33.000000000 -0500
@@ -0,0 +1,48 @@
+Origin: 
https://download.strongswan.org/security/CVE-2026-78123/strongswan-5.0.2-6.0.7_openssl_pkcs7_info_init.patch
+Reviewed-by: Simon Quigley <[email protected]>
+Last-Update: 2026-10-26
+
+From 2918eb8a6d4b3167f26ac011e87c3a7ecc7dbe56 Mon Sep 17 00:00:00 2001
+From: Tobias Brunner <[email protected]>
+Date: Mon, 1 Jun 2026 17:51:35 +0200
+Subject: [PATCH] openssl: Fix undefined memory access when verifying PKCS#7
+ containers
+
+If the signerInfo or recipientInfo structure doesn't contain
+issuerAndSerialNumber but instead a subjectKeyIdentifier, then the called
+functions will leave the passed name and serial numbers unchanged.  While
+openssl_x509_name2id() prevents a NULL-pointer dereference, it tries to
+DER-encode the object at the passed pointer via i2d_X509_NAME().
+Depending on the stack contents, this likely causes a segmentation fault.
+
+Fixes: 3c820cdc232a ("Implement PKCS#7 decryption using openssl")
+Fixes: c61723c69fb5 ("Implement OpenSSL PKCS#7 signed-data parsing and 
verification")
+Fixes: CVE-2026-78123
+---
+ src/libstrongswan/plugins/openssl/openssl_pkcs7.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c
++++ b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c
+@@ -221,8 +221,8 @@ static auth_cfg_t *verify_signature(CMS_
+       auth_cfg_t *auth, *found = NULL;
+       identification_t *issuer, *serial;
+       chunk_t attrs = chunk_empty, sig, attr;
+-      X509_NAME *name;
+-      ASN1_INTEGER *snr;
++      X509_NAME *name = NULL;
++      ASN1_INTEGER *snr = NULL;
+       int i;
+ 
+       if (CMS_SignerInfo_get0_signer_id(si, NULL, &name, &snr) != 1)
+@@ -612,8 +612,8 @@ static bool decrypt(private_openssl_pkcs
+                       identification_t *serial, *issuer;
+                       private_key_t *private;
+                       X509_ALGOR *alg;
+-                      X509_NAME *name;
+-                      ASN1_INTEGER *sn;
++                      X509_NAME *name = NULL;
++                      ASN1_INTEGER *sn = NULL;
+                       u_char zero = 0;
+                       int oid;
+ 
diff -Nru 
strongswan-5.9.8/debian/patches/0018-openssl-Fix-memory-leaks-after-enumerating-certifica.patch
 
strongswan-5.9.8/debian/patches/0018-openssl-Fix-memory-leaks-after-enumerating-certifica.patch
--- 
strongswan-5.9.8/debian/patches/0018-openssl-Fix-memory-leaks-after-enumerating-certifica.patch
     1969-12-31 18:00:00.000000000 -0600
+++ 
strongswan-5.9.8/debian/patches/0018-openssl-Fix-memory-leaks-after-enumerating-certifica.patch
     2026-10-27 11:22:34.000000000 -0500
@@ -0,0 +1,31 @@
+Origin: 
https://download.strongswan.org/security/CVE-2026-78124/strongswan-5.0.2-6.0.7_openssl_pkcs7_certs_leak.patch
+Reviewed-by: Simon Quigley <[email protected]>
+Last-Update: 2026-10-26
+
+From 2a3a678be189e51465d17c611982a9e5f379b016 Mon Sep 17 00:00:00 2001
+From: Tobias Brunner <[email protected]>
+Date: Mon, 15 Jun 2026 16:02:01 +0200
+Subject: [PATCH] openssl: Fix memory leaks after enumerating certificates in
+ PKCS#7 container
+
+This can be triggered via IKEv1.
+
+Fixes: 04884be3b5f7 ("Implement openssl PKCS#7 certficiate enumeration")
+Fixes: CVE-2026-78124
+---
+ src/libstrongswan/plugins/openssl/openssl_pkcs7.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c
++++ b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c
+@@ -132,6 +132,10 @@ typedef struct {
+ METHOD(enumerator_t, cert_destroy, void,
+       cert_enumerator_t *this)
+ {
++      if (this->certs)
++      {
++              sk_X509_pop_free(this->certs, X509_free);
++      }
+       DESTROY_IF(this->cert);
+       free(this);
+ }
diff -Nru 
strongswan-5.9.8/debian/patches/0019-eap-aka-Only-accept-AKA-Synchronization-Failure-if-e.patch
 
strongswan-5.9.8/debian/patches/0019-eap-aka-Only-accept-AKA-Synchronization-Failure-if-e.patch
--- 
strongswan-5.9.8/debian/patches/0019-eap-aka-Only-accept-AKA-Synchronization-Failure-if-e.patch
     1969-12-31 18:00:00.000000000 -0600
+++ 
strongswan-5.9.8/debian/patches/0019-eap-aka-Only-accept-AKA-Synchronization-Failure-if-e.patch
     2026-10-27 11:22:34.000000000 -0500
@@ -0,0 +1,34 @@
+Origin: 
https://download.strongswan.org/security/CVE-2026-78126/strongswan-4.4.0-6.0.7_eap_aka_sync_fail.patch
+Reviewed-by: Simon Quigley <[email protected]>
+Last-Update: 2026-10-26
+
+From 632a7498f834ff07ecf7a3dd604c06f6b89dd768 Mon Sep 17 00:00:00 2001
+From: Tobias Brunner <[email protected]>
+Date: Thu, 4 Jun 2026 10:00:02 +0200
+Subject: [PATCH] eap-aka: Only accept AKA-Synchronization-Failure if expected
+
+This fixes a NULL-pointer dereference if the client sends such an error
+before the server issued a challenge and allocated this->rand.
+
+Fixes: 26e246769224 ("ported EAP-AKA branch into trunk")
+Fixes: 4735965fc048 ("EAP servers check if the received EAP message was 
expected")
+Fixes: CVE-2026-78126
+---
+ src/libcharon/plugins/eap_aka/eap_aka_server.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/src/libcharon/plugins/eap_aka/eap_aka_server.c
++++ b/src/libcharon/plugins/eap_aka/eap_aka_server.c
+@@ -505,6 +505,12 @@ static status_t process_synchronize(priv
+       simaka_attribute_t type;
+       chunk_t data, auts = chunk_empty;
+ 
++      if (this->pending != AKA_CHALLENGE)
++      {
++              DBG1(DBG_IKE, "received %N, but not expected",
++                       simaka_subtype_names, AKA_SYNCHRONIZATION_FAILURE);
++              return FAILED;
++      }
+       if (this->synchronized)
+       {
+               DBG1(DBG_IKE, "received %N, but peer did already resynchronize",
diff -Nru 
strongswan-5.9.8/debian/patches/0020-message-Avoid-memory-leak-if-string-buffer-for-messa.patch
 
strongswan-5.9.8/debian/patches/0020-message-Avoid-memory-leak-if-string-buffer-for-messa.patch
--- 
strongswan-5.9.8/debian/patches/0020-message-Avoid-memory-leak-if-string-buffer-for-messa.patch
     1969-12-31 18:00:00.000000000 -0600
+++ 
strongswan-5.9.8/debian/patches/0020-message-Avoid-memory-leak-if-string-buffer-for-messa.patch
     2026-10-27 11:22:34.000000000 -0500
@@ -0,0 +1,112 @@
+Origin: 
https://download.strongswan.org/security/CVE-2026-78127/strongswan-5.3.1-6.0.7_message_log_leak.patch
+Reviewed-by: Simon Quigley <[email protected]>
+Last-Update: 2026-10-26
+
+From 1d758b2cd2f13af02319274c4e48cd7a2dc62e42 Mon Sep 17 00:00:00 2001
+From: Tobias Brunner <[email protected]>
+Date: Mon, 8 Jun 2026 09:19:42 +0200
+Subject: [PATCH] message: Avoid memory leak if string buffer for message is
+ too small
+
+This leaked 40 or 80 bytes per parsed message for the enumerators that
+were not destroyed.  While triggering an OOM condition will require quite
+a lot of messages and the DoS protection also helps avoiding that this
+is triggered quickly, it all depends on the memory constraints of the
+system and the time available to the attacker.  Also, if IKEv1 is allowed,
+it could get quicker as the lack of message IDs doesn't allow dismissing
+unexpected messages before parsing them.
+
+Fixes: 092958c89d52 ("fixed payload debug message")
+Fixes: 6a4a47511f75 ("Show contents of the CP payload in message_t 
stringification")
+Fixes: CVE-2026-78127
+---
+ src/libcharon/encoding/message.c | 23 ++++++++++++-----------
+ 1 file changed, 12 insertions(+), 11 deletions(-)
+
+--- a/src/libcharon/encoding/message.c
++++ b/src/libcharon/encoding/message.c
+@@ -1301,7 +1301,7 @@ static char* get_string(private_message_
+                                                  payload->get_type(payload));
+               if (written >= len || written < 0)
+               {
+-                      return buf;
++                      goto err;
+               }
+               pos += written;
+               len -= written;
+@@ -1327,7 +1327,7 @@ static char* get_string(private_message_
+                       }
+                       if (written >= len || written < 0)
+                       {
+-                              return buf;
++                              goto err;
+                       }
+                       pos += written;
+                       len -= written;
+@@ -1357,7 +1357,7 @@ static char* get_string(private_message_
+                                                          eap->get_code(eap), 
method);
+                       if (written >= len || written < 0)
+                       {
+-                              return buf;
++                              goto err;
+                       }
+                       pos += written;
+                       len -= written;
+@@ -1398,7 +1398,8 @@ static char* get_string(private_message_
+                                                                  
attribute->get_type(attribute));
+                               if (written >= len || written < 0)
+                               {
+-                                      return buf;
++                                      attributes->destroy(attributes);
++                                      goto err;
+                               }
+                               pos += written;
+                               len -= written;
+@@ -1410,7 +1411,7 @@ static char* get_string(private_message_
+                               written = snprintf(pos, len, ")");
+                               if (written >= len || written < 0)
+                               {
+-                                      return buf;
++                                      goto err;
+                               }
+                               pos += written;
+                               len -= written;
+@@ -1432,7 +1433,7 @@ static char* get_string(private_message_
+                       }
+                       if (written >= len || written < 0)
+                       {
+-                              return buf;
++                              goto err;
+                       }
+                       pos += written;
+                       len -= written;
+@@ -1447,7 +1448,7 @@ static char* get_string(private_message_
+                                                          
frag->get_total_fragments(frag));
+                       if (written >= len || written < 0)
+                       {
+-                              return buf;
++                              goto err;
+                       }
+                       pos += written;
+                       len -= written;
+@@ -1460,16 +1461,16 @@ static char* get_string(private_message_
+                       written = snprintf(pos, len, "(%d)", 
unknown->get_type(unknown));
+                       if (written >= len || written < 0)
+                       {
+-                              return buf;
++                              goto err;
+                       }
+                       pos += written;
+                       len -= written;
+               }
+       }
+-      enumerator->destroy(enumerator);
+-
+-      /* remove last space */
+       snprintf(pos, len, " ]");
++
++err:
++      enumerator->destroy(enumerator);
+       return buf;
+ }
+ 
diff -Nru 
strongswan-5.9.8/debian/patches/0021-pkcs5-Validate-parsed-parameters-to-avoid-DoS-attack.patch
 
strongswan-5.9.8/debian/patches/0021-pkcs5-Validate-parsed-parameters-to-avoid-DoS-attack.patch
--- 
strongswan-5.9.8/debian/patches/0021-pkcs5-Validate-parsed-parameters-to-avoid-DoS-attack.patch
     1969-12-31 18:00:00.000000000 -0600
+++ 
strongswan-5.9.8/debian/patches/0021-pkcs5-Validate-parsed-parameters-to-avoid-DoS-attack.patch
     2026-10-27 11:22:34.000000000 -0500
@@ -0,0 +1,152 @@
+Origin: 
https://download.strongswan.org/security/CVE-2026-78129/strongswan-5.6.3-6.0.7_pkcs5_params_dos.patch
+Reviewed-by: Simon Quigley <[email protected]>
+Last-Update: 2026-10-26
+
+From e7a3a51459e795136c249bfe83978b41d7d5ecdd Mon Sep 17 00:00:00 2001
+From: Tobias Brunner <[email protected]>
+Date: Tue, 23 Jun 2026 11:55:31 +0200
+Subject: [PATCH] pkcs5: Validate parsed parameters to avoid DoS attacks
+
+With the unbounded iterations, an attacker can craft a PKCS#7 file and
+send it during IKEv1 to block the processing thread practically for an
+unlimited amount of time.
+
+As the key length is used for an allocation on the stack, not limiting
+it could cause a crash.  We validate it after parsing the params, but
+since `encryption_algorithm_from_oid()` only returns trusted key lengths
+that are lower than the limit, that's fine.
+
+The unlimited salt length had no direct impact (the maximum is bound by
+the accepted message size), but we now limit it as well before cloning.
+
+Fixes: 4076e3ee9121 ("Extract PKCS#5 handling from pkcs8 plugin to separate 
helper class")
+Fixes: fd1ff46f6143 ("Added support for PKCS#5 v2 schemes when decrypting 
PKCS#8 files.")
+Fixes: cab127cba66c ("Added support for encrypted PKCS#8 files (for some 
PKCS#5 v1.5 schemes).")
+Fixes: CVE-2026-78129
+---
+ src/libstrongswan/crypto/pkcs5.c | 65 +++++++++++++++++++++++++++++++-
+ 1 file changed, 64 insertions(+), 1 deletion(-)
+
+--- a/src/libstrongswan/crypto/pkcs5.c
++++ b/src/libstrongswan/crypto/pkcs5.c
+@@ -14,6 +14,8 @@
+  * for more details.
+  */
+ 
++#include <inttypes.h>
++
+ #include "pkcs5.h"
+ 
+ #include <utils/debug.h>
+@@ -22,6 +24,15 @@
+ #include <asn1/asn1_parser.h>
+ #include <credentials/containers/pkcs12.h>
+ 
++/** maximum accepted length for salts in parsed parameters */
++#define PKCS5_SALT_LEN_MAX                    128
++
++/** maximum accepted iteration count in parsed parameters */
++#define PKCS5_ITERATIONS_MAX          1000000
++
++/** maximum key length accepted in parsed parameters */
++#define PKCS5_KEY_LEN_MAX                     64
++
+ typedef struct private_pkcs5_t private_pkcs5_t;
+ 
+ /**
+@@ -380,6 +391,41 @@ METHOD(pkcs5_t, decrypt, bool,
+ }
+ 
+ /**
++ * Make sure the salt has an appropriate length
++ */
++static bool validate_salt_length(chunk_t salt)
++{
++      if (salt.len > PKCS5_SALT_LEN_MAX)
++      {
++              DBG1(DBG_ASN, "  salt length %zu exceeds maximum of %zu bytes",
++                       salt.len, (size_t)PKCS5_SALT_LEN_MAX);
++              return FALSE;
++      }
++      return TRUE;
++}
++
++/**
++ * Validate that parsed parameters are in an allowed range
++ */
++static bool validate_params(private_pkcs5_t *this)
++{
++      if (!this->iterations || this->iterations > PKCS5_ITERATIONS_MAX)
++      {
++              DBG1(DBG_ASN, "  iteration count %" PRIu64 " is out of range "
++                       "(1-%" PRIu64 ")", this->iterations,
++                       (uint64_t)PKCS5_ITERATIONS_MAX);
++              return FALSE;
++      }
++      if (this->keylen > PKCS5_KEY_LEN_MAX)
++      {
++              DBG1(DBG_ASN, "  key length %zu exceeds maximum of %zu bytes",
++                       this->keylen, (size_t)PKCS5_KEY_LEN_MAX);
++              return FALSE;
++      }
++      return TRUE;
++}
++
++/**
+  * ASN.1 definition of a PBEParameter structure
+  */
+ static const asn1Object_t pbeParameterObjects[] = {
+@@ -399,7 +445,7 @@ static bool parse_pbes1_params(private_p
+       asn1_parser_t *parser;
+       chunk_t object;
+       int objectID;
+-      bool success;
++      bool success = FALSE;
+ 
+       parser = asn1_parser_create(pbeParameterObjects, blob);
+       parser->set_top_level(parser, level0);
+@@ -410,6 +456,10 @@ static bool parse_pbes1_params(private_p
+               {
+                       case PBEPARAM_SALT:
+                       {
++                              if (!validate_salt_length(object))
++                              {
++                                      goto end;
++                              }
+                               this->salt = chunk_clone(object);
+                               break;
+                       }
+@@ -421,6 +471,11 @@ static bool parse_pbes1_params(private_p
+               }
+       }
+       success = parser->success(parser);
++      if (success)
++      {
++              success = validate_params(this);
++      }
++end:
+       parser->destroy(parser);
+       return success;
+ }
+@@ -471,6 +526,10 @@ static bool parse_pbkdf2_params(private_
+               {
+                       case PBKDF2_SALT:
+                       {
++                              if (!validate_salt_length(object))
++                              {
++                                      goto end;
++                              }
+                               this->salt = chunk_clone(object);
+                               break;
+                       }
+@@ -500,6 +559,10 @@ static bool parse_pbkdf2_params(private_
+               }
+       }
+       success = parser->success(parser);
++      if (success)
++      {
++              success = validate_params(this);
++      }
+ end:
+       parser->destroy(parser);
+       return success;
diff -Nru 
strongswan-5.9.8/debian/patches/0022-x509-Avoid-NULL-pointer-dereference-if-issuerName-is.patch
 
strongswan-5.9.8/debian/patches/0022-x509-Avoid-NULL-pointer-dereference-if-issuerName-is.patch
--- 
strongswan-5.9.8/debian/patches/0022-x509-Avoid-NULL-pointer-dereference-if-issuerName-is.patch
     1969-12-31 18:00:00.000000000 -0600
+++ 
strongswan-5.9.8/debian/patches/0022-x509-Avoid-NULL-pointer-dereference-if-issuerName-is.patch
     2026-10-27 11:22:34.000000000 -0500
@@ -0,0 +1,46 @@
+Origin: 
https://download.strongswan.org/security/CVE-2026-78130/strongswan-5.1.3-6.0.7_x509_ac_issuer_null.patch
+Reviewed-by: Simon Quigley <[email protected]>
+Last-Update: 2026-10-26
+
+From 4dae392b32a2c56441fd7ca50ad32a0874455995 Mon Sep 17 00:00:00 2001
+From: Tobias Brunner <[email protected]>
+Date: Fri, 19 Jun 2026 11:57:48 +0200
+Subject: [PATCH] x509: Avoid NULL-pointer dereference if issuerName is missing
+ in attribute certificate
+
+If neither authoritiyKeyIdentifier nor issuerName are encoded in an
+attribute certificate, the validation in `acert_validator.c:verify()`
+will cause a NULL-pointer dereference via `issued_by()` (the lookup
+with NULL identity will enumerate all trusted certificates).
+
+Fixes: 26930a8c3e42 ("certificate factory can load certs from file")
+Fixes: CVE-2026-78130
+---
+ src/libstrongswan/plugins/x509/x509_ac.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/src/libstrongswan/plugins/x509/x509_ac.c
++++ b/src/libstrongswan/plugins/x509/x509_ac.c
+@@ -911,7 +911,11 @@ METHOD(certificate_t, has_issuer, id_mat
+       {
+               return ID_MATCH_PERFECT;
+       }
+-      return this->issuerName->matches(this->issuerName, issuer);
++      if (this->issuerName)
++      {
++              return this->issuerName->matches(this->issuerName, issuer);
++      }
++      return ID_MATCH_NONE;
+ }
+ 
+ METHOD(certificate_t, issued_by, bool,
+@@ -948,7 +952,8 @@ METHOD(certificate_t, issued_by, bool,
+       }
+       else
+       {
+-              if (!this->issuerName->equals(this->issuerName,
++              if (!this->issuerName ||
++                      !this->issuerName->equals(this->issuerName,
+                                                                         
issuer->get_subject(issuer)))
+               {
+                       return FALSE;
diff -Nru 
strongswan-5.9.8/debian/patches/0023-x509-Fix-memory-leaks-when-parsing-attribute-certifi.patch
 
strongswan-5.9.8/debian/patches/0023-x509-Fix-memory-leaks-when-parsing-attribute-certifi.patch
--- 
strongswan-5.9.8/debian/patches/0023-x509-Fix-memory-leaks-when-parsing-attribute-certifi.patch
     1969-12-31 18:00:00.000000000 -0600
+++ 
strongswan-5.9.8/debian/patches/0023-x509-Fix-memory-leaks-when-parsing-attribute-certifi.patch
     2026-10-27 11:22:34.000000000 -0500
@@ -0,0 +1,80 @@
+Origin: 
https://download.strongswan.org/security/CVE-2026-78131/strongswan-5.5.3-6.0.7_x509_ac_leaks.patch
+Reviewed-by: Simon Quigley <[email protected]>
+Last-Update: 2026-10-26
+
+From 7012f6263df493b62268954675b0311248780309 Mon Sep 17 00:00:00 2001
+From: Tobias Brunner <[email protected]>
+Date: Fri, 12 Jun 2026 15:55:43 +0200
+Subject: [PATCH] x509: Fix memory leaks when parsing attribute certificates
+
+This can be triggered by an attribute certificate with lots of GeneralName
+entries or AuthorityKeyIdentifier extensions.  There is no verification
+before the certificate is parsed.
+
+Fixes: 3134379ac7f1 ("x509: Fix some whitespaces and do some minor style 
cleanups in acert")
+Fixes: 26930a8c3e42 ("certificate factory can load certs from file")
+Fixes: CVE-2026-78131
+---
+ src/libstrongswan/plugins/x509/x509_ac.c | 33 +++++++-----------------
+ 1 file changed, 9 insertions(+), 24 deletions(-)
+
+--- a/src/libstrongswan/plugins/x509/x509_ac.c
++++ b/src/libstrongswan/plugins/x509/x509_ac.c
+@@ -186,41 +186,25 @@ extern bool x509_parse_generalNames(chun
+ static bool parse_directoryName(chunk_t blob, int level, bool implicit,
+                                                               
identification_t **name)
+ {
+-      identification_t *directoryName;
+-      enumerator_t *enumerator;
+-      bool first = TRUE;
+       linked_list_t *list;
+ 
+       list = linked_list_create();
+       if (!x509_parse_generalNames(blob, level, implicit, list))
+       {
+-              list->destroy(list);
++              list->destroy_offset(list, offsetof(identification_t, destroy));
+               return FALSE;
+       }
+-
+-      enumerator = list->create_enumerator(list);
+-      while (enumerator->enumerate(enumerator, &directoryName))
+-      {
+-              if (first)
+-              {
+-                      *name = directoryName;
+-                      first = FALSE;
+-              }
+-              else
+-              {
+-                      DBG1(DBG_ASN, "more than one directory name - first 
selected");
+-                      directoryName->destroy(directoryName);
+-                      break;
+-              }
+-      }
+-      enumerator->destroy(enumerator);
+-      list->destroy(list);
+-
+-      if (first)
++      if (list->remove_first(list, (void**)name) != SUCCESS)
+       {
+               DBG1(DBG_ASN, "no directoryName found");
++              list->destroy(list);
+               return FALSE;
+       }
++      if (list->get_count(list))
++      {
++              DBG1(DBG_ASN, "more than one directory name - first selected");
++      }
++      list->destroy_offset(list, offsetof(identification_t, destroy));
+       return TRUE;
+ }
+ 
+@@ -540,6 +524,7 @@ static bool parse_certificate(private_x5
+                                               DBG2(DBG_ASN, "  need to parse 
crlDistributionPoints");
+                                               break;
+                                       case OID_AUTHORITY_KEY_ID:
++                                              
chunk_free(&this->authKeyIdentifier);
+                                               this->authKeyIdentifier =
+                                                               
x509_parse_authorityKeyIdentifier(object,
+                                                                               
        level, &this->authKeySerialNumber);
diff -Nru 
strongswan-5.9.8/debian/patches/0024-x509-Prevent-infinite-loop-when-parsing-ietfAttrSynt.patch
 
strongswan-5.9.8/debian/patches/0024-x509-Prevent-infinite-loop-when-parsing-ietfAttrSynt.patch
--- 
strongswan-5.9.8/debian/patches/0024-x509-Prevent-infinite-loop-when-parsing-ietfAttrSynt.patch
     1969-12-31 18:00:00.000000000 -0600
+++ 
strongswan-5.9.8/debian/patches/0024-x509-Prevent-infinite-loop-when-parsing-ietfAttrSynt.patch
     2026-10-27 11:22:34.000000000 -0500
@@ -0,0 +1,72 @@
+Origin: 
https://download.strongswan.org/security/CVE-2026-78132/strongswan-5.1.3-6.0.7_x509_ac_ietfattr_loop.patch
+Reviewed-by: Simon Quigley <[email protected]>
+Last-Update: 2026-10-26
+
+From d925e4625626a70611a979d4ab231c6e2d313e4a Mon Sep 17 00:00:00 2001
+From: Tobias Brunner <[email protected]>
+Date: Wed, 1 Jul 2026 16:24:23 +0200
+Subject: [PATCH] x509: Prevent infinite loop when parsing ietfAttrSyntax in
+ attribute certificates
+
+This is the same issue that was fixed with 407fcca200fd ("asn1-parser:
+Fix CHOICE parsing") for other CHOICE elements.  This one was missed and
+can be triggered pre-auth by sending an attribute certificate to a peer.
+Since it's parsed before verifying it, the certificate doesn't have to
+be valid.
+
+For versions older than 5.5.3, this patch requires prior application of
+the fix for CVE-2017-9023, which introduced proper CHOICE handling in
+the ASN.1 parser.
+
+Fixes: a17598bc6992 ("x509: Integrate IETF attribute handling, and obsolete 
ietf_attributes_t")
+Fixes: CVE-2026-78132
+---
+ src/libstrongswan/plugins/x509/x509_ac.c | 36 +++++++++++-------------
+ 1 file changed, 17 insertions(+), 19 deletions(-)
+
+--- a/src/libstrongswan/plugins/x509/x509_ac.c
++++ b/src/libstrongswan/plugins/x509/x509_ac.c
+@@ -249,26 +249,24 @@ static void parse_roleSyntax(chunk_t blo
+  */
+ static const asn1Object_t ietfAttrSyntaxObjects[] =
+ {
+-      { 0, "ietfAttrSyntax",          ASN1_SEQUENCE,          ASN1_NONE }, /* 
 0 */
+-      { 1,   "policyAuthority",       ASN1_CONTEXT_C_0,       ASN1_OPT |
+-                                                                              
                        ASN1_BODY }, /*  1 */
+-      { 1,   "end opt",                       ASN1_EOC,                       
ASN1_END  }, /*  2 */
+-      { 1,   "values",                        ASN1_SEQUENCE,          
ASN1_LOOP }, /*  3 */
+-      { 2,     "octets",                      ASN1_OCTET_STRING,      
ASN1_OPT |
+-                                                                              
                        ASN1_BODY }, /*  4 */
+-      { 2,     "end choice",          ASN1_EOC,                       
ASN1_END  }, /*  5 */
+-      { 2,     "oid",                         ASN1_OID,                       
ASN1_OPT |
+-                                                                              
                        ASN1_BODY }, /*  6 */
+-      { 2,     "end choice",          ASN1_EOC,                       
ASN1_END  }, /*  7 */
+-      { 2,     "string",                      ASN1_UTF8STRING,        
ASN1_OPT |
+-                                                                              
                        ASN1_BODY }, /*  8 */
+-      { 2,     "end choice",          ASN1_EOC,                       
ASN1_END  }, /*  9 */
+-      { 1,   "end loop",                      ASN1_EOC,                       
ASN1_END  }, /* 10 */
+-      { 0, "exit",                            ASN1_EOC,                       
ASN1_EXIT }
++      { 0, "ietfAttrSyntax",          ASN1_SEQUENCE,          ASN1_NONE       
     }, /*  0 */
++      { 1,   "policyAuthority",       ASN1_CONTEXT_C_0,       
ASN1_OPT|ASN1_BODY   }, /*  1 */
++      { 1,   "end opt",                       ASN1_EOC,                       
ASN1_END             }, /*  2 */
++      { 1,   "values",                        ASN1_SEQUENCE,          
ASN1_LOOP            }, /*  3 */
++      { 2,     "value choice",        ASN1_EOC,                       
ASN1_CHOICE          }, /*  4 */
++      { 3,       "octets",            ASN1_OCTET_STRING,      
ASN1_OPT|ASN1_BODY   }, /*  5 */
++      { 3,       "end choice",        ASN1_EOC,                       
ASN1_END|ASN1_CH     }, /*  6 */
++      { 3,       "oid",                       ASN1_OID,                       
ASN1_OPT|ASN1_BODY   }, /*  7 */
++      { 3,       "end choice",        ASN1_EOC,                       
ASN1_END|ASN1_CH     }, /*  8 */
++      { 3,       "string",            ASN1_UTF8STRING,        
ASN1_OPT|ASN1_BODY   }, /*  9 */
++      { 3,       "end choice",        ASN1_EOC,                       
ASN1_END|ASN1_CH     }, /* 10 */
++      { 2,     "end choices",         ASN1_EOC,                       
ASN1_END|ASN1_CHOICE }, /* 11 */
++      { 1,   "end loop",                      ASN1_EOC,                       
ASN1_END             }, /* 12 */
++      { 0, "exit",                            ASN1_EOC,                       
ASN1_EXIT            }
+ };
+-#define IETF_ATTR_OCTETS       4
+-#define IETF_ATTR_OID          6
+-#define IETF_ATTR_STRING       8
++#define IETF_ATTR_OCTETS       5
++#define IETF_ATTR_OID          7
++#define IETF_ATTR_STRING       9
+ 
+ /**
+  * Parse group memberships, IETF attributes
diff -Nru 
strongswan-5.9.8/debian/patches/0025-eap-ttls-peap-Return-auth-cfg-with-details-on-TLS-an.patch
 
strongswan-5.9.8/debian/patches/0025-eap-ttls-peap-Return-auth-cfg-with-details-on-TLS-an.patch
--- 
strongswan-5.9.8/debian/patches/0025-eap-ttls-peap-Return-auth-cfg-with-details-on-TLS-an.patch
     1969-12-31 18:00:00.000000000 -0600
+++ 
strongswan-5.9.8/debian/patches/0025-eap-ttls-peap-Return-auth-cfg-with-details-on-TLS-an.patch
     2026-10-27 11:22:34.000000000 -0500
@@ -0,0 +1,688 @@
+Origin: 
https://download.strongswan.org/security/CVE-2026-78134/strongswan-5.5.1-5.9.9_eap_inner_auth_cfg.patch
+Reviewed-by: Simon Quigley <[email protected]>
+Last-Update: 2026-10-26
+
+From 7926256cacd4526264107cc8198d16b452a28673 Mon Sep 17 00:00:00 2001
+From: Tobias Brunner <[email protected]>
+Date: Mon, 27 Jul 2026 15:05:45 +0200
+Subject: [PATCH] eap-ttls/peap: Return auth-cfg with details on TLS and inner
+ EAP method
+
+This fixes several issues with binding identities to the IKE SA.
+
+If the client is authenticated with a certificate, the previous code still
+used the client's proclaimed inner EAP-Identity when starting the EAP-TNC
+method.  So that method would potentially operate on an unverified
+identity.
+
+Second, if the inner EAP method overrides the client identity (the only
+one is currently EAP-MSCHAPV2), the missing merge meant that the outer
+IKE/EAP identity could potentially be unconfirmed.
+
+For inner methods that don't override the identity (e.g. EAP-MD5), not
+propagating the inner EAP-Identity could potentially have the same
+effect.
+
+While the EAP-TTLS implementation returned the auth-cfg of the TLS
+exchange since the first referenced commit, this was mainly intended to
+enforce public key constraints.  So it didn't cover the phase 2 EAP
+methods.  For some reason EAP-PEAP did not get that method at all in that
+changeset, so we'll add that now.
+
+Additionally, the EAP-PEAP implementation now forwards the phase 2 EAP
+method type to EAP-TNC like the EAP-TTLS implementation already did,
+which allows a more informed decision on the client's identity.
+
+Fixes: 0864a31d13ff ("eap-ttls: Support EAP auth information getter in 
EAP-TTLS")
+Fixes: 79f2102cb442 ("implemented server side support for EAP-TTLS")
+Fixes: 2a421163bf4f ("make TNC client authentication type available to IMVs")
+Fixes: 1be296dfb2af ("implemented the PEAP tunneling protocol as an EAP 
plugin")
+Fixes: CVE-2026-78134
+---
+ src/libcharon/plugins/eap_peap/eap_peap.c     | 49 ++++++++++-
+ .../plugins/eap_peap/eap_peap_peer.c          | 20 +++++
+ .../plugins/eap_peap/eap_peap_peer.h          |  7 ++
+ .../plugins/eap_peap/eap_peap_server.c        | 81 ++++++++++++++++---
+ .../plugins/eap_peap/eap_peap_server.h        |  7 ++
+ src/libcharon/plugins/eap_ttls/eap_ttls.c     | 43 +++++++++-
+ .../plugins/eap_ttls/eap_ttls_peer.c          | 19 +++++
+ .../plugins/eap_ttls/eap_ttls_peer.h          |  7 ++
+ .../plugins/eap_ttls/eap_ttls_server.c        | 56 +++++++++++--
+ .../plugins/eap_ttls/eap_ttls_server.h        |  7 ++
+ 10 files changed, 278 insertions(+), 18 deletions(-)
+
+--- a/src/libcharon/plugins/eap_peap/eap_peap.c
++++ b/src/libcharon/plugins/eap_peap/eap_peap.c
+@@ -40,6 +40,25 @@ struct private_eap_peap_t {
+        * TLS stack, wrapped by EAP helper
+        */
+       tls_eap_t *tls_eap;
++
++      /**
++       * Role
++       */
++      bool is_server;
++
++      /**
++       * Actual server/client implementation
++       */
++      union {
++              tls_application_t *application;
++              eap_peap_server_t *server;
++              eap_peap_peer_t *client;
++      } impl;
++
++      /**
++       * Cached auth data for TLS and inner EAP methods
++       */
++      auth_cfg_t *auth;
+ };
+ 
+ /** Maximum number of EAP-PEAP messages/fragments allowed */
+@@ -113,10 +132,34 @@ METHOD(eap_method_t, is_mutual, bool,
+       return TRUE;
+ }
+ 
++METHOD(eap_method_t, get_auth, auth_cfg_t*,
++      private_eap_peap_t *this)
++{
++      if (!this->auth)
++      {
++              auth_cfg_t *inner;
++
++              this->auth = auth_cfg_create();
++              this->auth->merge(this->auth,
++                                                
this->tls_eap->get_auth(this->tls_eap), FALSE);
++              if (this->is_server)
++              {
++                      inner = this->impl.server->get_auth(this->impl.server);
++              }
++              else
++              {
++                      inner = this->impl.client->get_auth(this->impl.client);
++              }
++              this->auth->merge(this->auth, inner, FALSE);
++      }
++      return this->auth;
++}
++
+ METHOD(eap_method_t, destroy, void,
+       private_eap_peap_t *this)
+ {
+       this->tls_eap->destroy(this->tls_eap);
++      DESTROY_IF(this->auth);
+       free(this);
+ }
+ 
+@@ -135,6 +178,7 @@ static private_eap_peap_t *eap_peap_crea
+                               .get_type = _get_type,
+                               .is_mutual = _is_mutual,
+                               .get_msk = _get_msk,
++                              .get_auth = _get_auth,
+                               .get_identifier = _get_identifier,
+                               .set_identifier = _set_identifier,
+                               .destroy = _destroy,
+@@ -147,7 +191,7 @@ static private_eap_peap_t *eap_peap_crea
+ /**
+  * Generic private constructor
+  */
+-static eap_peap_t *eap_peap_create(private_eap_peap_t * this,
++static eap_peap_t *eap_peap_create(private_eap_peap_t *this,
+                                                                  
identification_t *server,
+                                                                  
identification_t *peer, bool is_server,
+                                                                  
tls_application_t *application)
+@@ -157,6 +201,9 @@ static eap_peap_t *eap_peap_create(priva
+       bool include_length;
+       tls_t *tls;
+ 
++      this->is_server = is_server;
++      this->impl.application = application;
++
+       if (is_server && !lib->settings->get_bool(lib->settings,
+                                                               
"%s.plugins.eap-peap.request_peer_auth", FALSE,
+                                                               lib->ns))
+--- a/src/libcharon/plugins/eap_peap/eap_peap_peer.c
++++ b/src/libcharon/plugins/eap_peap/eap_peap_peer.c
+@@ -53,6 +53,11 @@ struct private_eap_peap_peer_t {
+       eap_method_t *ph2_method;
+ 
+       /**
++       * Auth data for phase 2 methods
++       */
++      auth_cfg_t *auth;
++
++      /**
+      * Pending outbound EAP message
+        */
+       eap_payload_t *out;
+@@ -166,6 +171,12 @@ METHOD(tls_application_t, process, statu
+       switch (status)
+       {
+               case SUCCESS:
++                      if (this->ph2_method->get_auth)
++                      {
++                              this->auth->merge(this->auth,
++                                                                
this->ph2_method->get_auth(this->ph2_method),
++                                                                FALSE);
++                      }
+                       this->ph2_method->destroy(this->ph2_method);
+                       this->ph2_method = NULL;
+                       /* fall through to NEED_MORE */
+@@ -220,11 +231,18 @@ METHOD(tls_application_t, build, status_
+       return INVALID_STATE;
+ }
+ 
++METHOD(eap_peap_peer_t, get_auth, auth_cfg_t*,
++      private_eap_peap_peer_t *this)
++{
++      return this->auth;
++}
++
+ METHOD(tls_application_t, destroy, void,
+       private_eap_peap_peer_t *this)
+ {
+       this->server->destroy(this->server);
+       this->peer->destroy(this->peer);
++      this->auth->destroy(this->auth);
+       DESTROY_IF(this->ph2_method);
+       DESTROY_IF(this->out);
+       this->avp->destroy(this->avp);
+@@ -247,10 +265,12 @@ eap_peap_peer_t *eap_peap_peer_create(id
+                               .build = _build,
+                               .destroy = _destroy,
+                       },
++                      .get_auth = _get_auth,
+               },
+               .server = server->clone(server),
+               .peer = peer->clone(peer),
+               .ph1_method = eap_method,
++              .auth = auth_cfg_create(),
+               .avp = eap_peap_avp_create(FALSE),
+       );
+ 
+--- a/src/libcharon/plugins/eap_peap/eap_peap_peer.h
++++ b/src/libcharon/plugins/eap_peap/eap_peap_peer.h
+@@ -38,6 +38,13 @@ struct eap_peap_peer_t {
+        * Implements the TLS application data handler.
+        */
+       tls_application_t application;
++
++      /**
++       * Get authentication details of this EAP method and its inner 
method(s).
++       *
++       * @return                              auth method, internal data
++       */
++      auth_cfg_t *(*get_auth)(eap_peap_peer_t *this);
+ };
+ 
+ /**
+--- a/src/libcharon/plugins/eap_peap/eap_peap_server.c
++++ b/src/libcharon/plugins/eap_peap/eap_peap_server.c
+@@ -20,6 +20,8 @@
+ #include <utils/debug.h>
+ #include <daemon.h>
+ 
++#include <sa/eap/eap_inner_method.h>
++
+ typedef struct private_eap_peap_server_t private_eap_peap_server_t;
+ 
+ /**
+@@ -73,6 +75,16 @@ struct private_eap_peap_server_t {
+       eap_method_t *ph2_method;
+ 
+       /**
++       * Type of the completed phase 2 EAP method
++       */
++      eap_type_t phase2_type;
++
++      /**
++       * Auth data for phase 2 method
++       */
++      auth_cfg_t *auth;
++
++      /**
+      * Pending outbound EAP message
+        */
+       eap_payload_t *out;
+@@ -127,8 +139,11 @@ static status_t start_phase2_auth(privat
+ /**
+  * If configured, start EAP-TNC protocol
+  */
+-static status_t start_phase2_tnc(private_eap_peap_server_t *this)
++static status_t start_phase2_tnc(private_eap_peap_server_t *this,
++                                                               eap_type_t 
auth_type)
+ {
++      eap_inner_method_t *inner_method;
++
+       if (this->start_phase2_tnc && lib->settings->get_bool(lib->settings,
+                                               
"%s.plugins.eap-peap.phase2_tnc", FALSE, lib->ns))
+       {
+@@ -140,6 +155,8 @@ static status_t start_phase2_tnc(private
+                       DBG1(DBG_IKE, "%N method not available", 
eap_type_names, EAP_TNC);
+                       return FAILED;
+               }
++              inner_method = (eap_inner_method_t *)this->ph2_method;
++              inner_method->set_auth_type(inner_method, auth_type);
+               this->start_phase2_tnc = FALSE;
+ 
+               /* synchronize EAP message identifiers of inner protocol with 
outer */
+@@ -213,9 +230,13 @@ METHOD(tls_application_t, process, statu
+               DBG1(DBG_IKE, "received tunneled EAP-PEAP AVP [EAP/%N]",
+                                                               
eap_code_short_names, code);
+               in->destroy(in);
+-              /* if EAP_SUCCESS check if to continue phase2 with EAP-TNC */
+-              return (this->phase2_result == EAP_SUCCESS && code == 
EAP_SUCCESS) ?
+-                         start_phase2_tnc(this) : FAILED;
++              if (this->phase2_result == EAP_SUCCESS && code == EAP_SUCCESS)
++              {
++                      /* only accept SUCCESS once after a successful inner 
method */
++                      this->phase2_result = EAP_FAILURE;
++                      return start_phase2_tnc(this, this->phase2_type);
++              }
++              return FAILED;
+       }
+ 
+       if (this->ph2_method)
+@@ -240,6 +261,10 @@ METHOD(tls_application_t, process, statu
+       if (!received_vendor && received_type == EAP_IDENTITY)
+       {
+               chunk_t eap_id;
++              bool peer_auth;
++
++              peer_auth = lib->settings->get_bool(lib->settings,
++                                      
"%s.plugins.eap-peap.request_peer_auth", FALSE, lib->ns);
+ 
+               if (this->ph2_method == NULL)
+               {
+@@ -266,9 +291,22 @@ METHOD(tls_application_t, process, statu
+ 
+               if (this->ph2_method->get_msk(this->ph2_method, &eap_id) == 
SUCCESS)
+               {
+-                      this->peer->destroy(this->peer);
+-                      this->peer = identification_create_from_data(eap_id);
+-                      DBG1(DBG_IKE, "received EAP identity '%Y'", this->peer);
++                      identification_t *id;
++
++                      id = identification_create_from_data(eap_id);
++                      if (peer_auth && !id->equals(id, this->peer))
++                      {
++                              DBG1(DBG_IKE, "received tunneled EAP identity 
'%Y', keeping "
++                                       "certificate-authenticated identity 
'%Y'", id, this->peer);
++                              id->destroy(id);
++                      }
++                      else
++                      {
++                              DBG1(DBG_IKE, "received EAP identity '%Y'", id);
++                              this->auth->add(this->auth, 
AUTH_RULE_EAP_IDENTITY, id);
++                              this->peer->destroy(this->peer);
++                              this->peer = id->clone(id);
++                      }
+               }
+ 
+               in->destroy(in);
+@@ -276,10 +314,9 @@ METHOD(tls_application_t, process, statu
+               this->ph2_method = NULL;
+ 
+               /* Start Phase 2 of EAP-PEAP authentication */
+-              if (lib->settings->get_bool(lib->settings,
+-                                      
"%s.plugins.eap-peap.request_peer_auth", FALSE, lib->ns))
++              if (peer_auth)
+               {
+-                      return start_phase2_tnc(this);
++                      return start_phase2_tnc(this, EAP_TLS);
+               }
+               else
+               {
+@@ -300,11 +337,26 @@ METHOD(tls_application_t, process, statu
+       switch (status)
+       {
+               case SUCCESS:
++                      if (this->ph2_method->get_auth)
++                      {
++                              identification_t *id;
++                              auth_cfg_t *auth;
++
++                              auth = 
this->ph2_method->get_auth(this->ph2_method);
++                              id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
++                              if (id)
++                              {
++                                      this->peer->destroy(this->peer);
++                                      this->peer = id->clone(id);
++                              }
++                              this->auth->merge(this->auth, auth, FALSE);
++                      }
+                       DBG1(DBG_IKE, "%N phase2 authentication of '%Y' with %N 
successful",
+                                                       eap_type_names, 
EAP_PEAP, this->peer,
+                                                       eap_type_names, type);
+                       this->ph2_method->destroy(this->ph2_method);
+                       this->ph2_method = NULL;
++                      this->phase2_type = type;
+ 
+                       /* EAP-PEAP requires the sending of an inner 
EAP_SUCCESS message */
+                       this->phase2_result = EAP_SUCCESS;
+@@ -393,11 +445,18 @@ METHOD(tls_application_t, build, status_
+       return INVALID_STATE;
+ }
+ 
++METHOD(eap_peap_server_t, get_auth, auth_cfg_t*,
++      private_eap_peap_server_t *this)
++{
++      return this->auth;
++}
++
+ METHOD(tls_application_t, destroy, void,
+       private_eap_peap_server_t *this)
+ {
+       this->server->destroy(this->server);
+       this->peer->destroy(this->peer);
++      this->auth->destroy(this->auth);
+       DESTROY_IF(this->ph2_method);
+       DESTROY_IF(this->out);
+       this->avp->destroy(this->avp);
+@@ -420,10 +479,12 @@ eap_peap_server_t *eap_peap_server_creat
+                               .build = _build,
+                               .destroy = _destroy,
+                       },
++                      .get_auth = _get_auth,
+               },
+               .server = server->clone(server),
+               .peer = peer->clone(peer),
+               .ph1_method = eap_method,
++              .auth = auth_cfg_create(),
+               .start_phase2 = TRUE,
+               .start_phase2_tnc = TRUE,
+               .start_phase2_id = lib->settings->get_bool(lib->settings,
+--- a/src/libcharon/plugins/eap_peap/eap_peap_server.h
++++ b/src/libcharon/plugins/eap_peap/eap_peap_server.h
+@@ -38,6 +38,13 @@ struct eap_peap_server_t {
+        * Implements the TLS application data handler.
+        */
+       tls_application_t application;
++
++      /**
++       * Get authentication details of this EAP method and its inner 
method(s).
++       *
++       * @return                              auth method, internal data
++       */
++      auth_cfg_t *(*get_auth)(eap_peap_server_t *this);
+ };
+ 
+ /**
+--- a/src/libcharon/plugins/eap_ttls/eap_ttls.c
++++ b/src/libcharon/plugins/eap_ttls/eap_ttls.c
+@@ -40,6 +40,25 @@ struct private_eap_ttls_t {
+        * TLS stack, wrapped by EAP helper
+        */
+       tls_eap_t *tls_eap;
++
++      /**
++       * Role
++       */
++      bool is_server;
++
++      /**
++       * Actual server/client implementation
++       */
++      union {
++              tls_application_t *application;
++              eap_ttls_server_t *server;
++              eap_ttls_peer_t *client;
++      } impl;
++
++      /**
++       * Cached auth data for TLS and inner EAP methods
++       */
++      auth_cfg_t *auth;
+ };
+ 
+ /** Maximum number of EAP-TTLS messages/fragments allowed */
+@@ -116,13 +135,31 @@ METHOD(eap_method_t, is_mutual, bool,
+ METHOD(eap_method_t, get_auth, auth_cfg_t*,
+       private_eap_ttls_t *this)
+ {
+-      return this->tls_eap->get_auth(this->tls_eap);
++      if (!this->auth)
++      {
++              auth_cfg_t *inner;
++
++              this->auth = auth_cfg_create();
++              this->auth->merge(this->auth,
++                                                
this->tls_eap->get_auth(this->tls_eap), FALSE);
++              if (this->is_server)
++              {
++                      inner = this->impl.server->get_auth(this->impl.server);
++              }
++              else
++              {
++                      inner = this->impl.client->get_auth(this->impl.client);
++              }
++              this->auth->merge(this->auth, inner, FALSE);
++      }
++      return this->auth;
+ }
+ 
+ METHOD(eap_method_t, destroy, void,
+       private_eap_ttls_t *this)
+ {
+       this->tls_eap->destroy(this->tls_eap);
++      DESTROY_IF(this->auth);
+       free(this);
+ }
+ 
+@@ -153,6 +190,10 @@ static eap_ttls_t *eap_ttls_create(ident
+                               .destroy = _destroy,
+                       },
+               },
++              .is_server = is_server,
++              .impl = {
++                      .application = application,
++              },
+       );
+       if (is_server && !lib->settings->get_bool(lib->settings,
+                                                               
"%s.plugins.eap-ttls.request_peer_auth", FALSE,
+--- a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
++++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
+@@ -55,6 +55,11 @@ struct private_eap_ttls_peer_t {
+       eap_method_t *method;
+ 
+       /**
++       * Auth data for phase 2 method
++       */
++      auth_cfg_t *auth;
++
++      /**
+      * Pending outbound EAP message
+        */
+       eap_payload_t *out;
+@@ -215,6 +220,11 @@ METHOD(tls_application_t, process, statu
+       switch (status)
+       {
+               case SUCCESS:
++                      if (this->method->get_auth)
++                      {
++                              this->auth->merge(this->auth,
++                                                                
this->method->get_auth(this->method), FALSE);
++                      }
+                       this->method->destroy(this->method);
+                       this->method = NULL;
+                       /* fall through to NEED_MORE */
+@@ -276,11 +286,18 @@ METHOD(tls_application_t, build, status_
+       return INVALID_STATE;
+ }
+ 
++METHOD(eap_ttls_peer_t, get_auth, auth_cfg_t*,
++      private_eap_ttls_peer_t *this)
++{
++      return this->auth;
++}
++
+ METHOD(tls_application_t, destroy, void,
+       private_eap_ttls_peer_t *this)
+ {
+       this->server->destroy(this->server);
+       this->peer->destroy(this->peer);
++      this->auth->destroy(this->auth);
+       DESTROY_IF(this->method);
+       DESTROY_IF(this->out);
+       this->avp->destroy(this->avp);
+@@ -302,10 +319,12 @@ eap_ttls_peer_t *eap_ttls_peer_create(id
+                               .build = _build,
+                               .destroy = _destroy,
+                       },
++                      .get_auth = _get_auth,
+               },
+               .server = server->clone(server),
+               .peer = peer->clone(peer),
+               .start_phase2 = TRUE,
++              .auth = auth_cfg_create(),
+               .avp = eap_ttls_avp_create(),
+       );
+ 
+--- a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.h
++++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.h
+@@ -37,6 +37,13 @@ struct eap_ttls_peer_t {
+        * Implements the TLS application data handler.
+        */
+       tls_application_t application;
++
++      /**
++       * Get authentication details of this EAP method and its inner 
method(s).
++       *
++       * @return                              auth method, internal data
++       */
++      auth_cfg_t *(*get_auth)(eap_ttls_peer_t *this);
+ };
+ 
+ /**
+--- a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
++++ b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
+@@ -61,6 +61,11 @@ struct private_eap_ttls_server_t {
+       eap_method_t *method;
+ 
+       /**
++       * Auth data for phase 2 method
++       */
++      auth_cfg_t *auth;
++
++      /**
+      * Pending outbound EAP message
+        */
+       eap_payload_t *out;
+@@ -220,6 +225,10 @@ METHOD(tls_application_t, process, statu
+       if (!received_vendor && received_type == EAP_IDENTITY)
+       {
+               chunk_t eap_id;
++              bool peer_auth;
++
++              peer_auth = lib->settings->get_bool(lib->settings,
++                                      
"%s.plugins.eap-ttls.request_peer_auth", FALSE, lib->ns);
+ 
+               if (this->method == NULL)
+               {
+@@ -244,9 +253,22 @@ METHOD(tls_application_t, process, statu
+ 
+               if (this->method->get_msk(this->method, &eap_id) == SUCCESS)
+               {
+-                      this->peer->destroy(this->peer);
+-                      this->peer = identification_create_from_data(eap_id);
+-                      DBG1(DBG_IKE, "received EAP identity '%Y'", this->peer);
++                      identification_t *id;
++
++                      id = identification_create_from_data(eap_id);
++                      if (peer_auth && !id->equals(id, this->peer))
++                      {
++                              DBG1(DBG_IKE, "received tunneled EAP identity 
'%Y', keeping "
++                                       "certificate-authenticated identity 
'%Y'", id, this->peer);
++                              id->destroy(id);
++                      }
++                      else
++                      {
++                              DBG1(DBG_IKE, "received EAP identity '%Y'", id);
++                              this->auth->add(this->auth, 
AUTH_RULE_EAP_IDENTITY, id);
++                              this->peer->destroy(this->peer);
++                              this->peer = id->clone(id);
++                      }
+               }
+ 
+               in->destroy(in);
+@@ -254,8 +276,7 @@ METHOD(tls_application_t, process, statu
+               this->method = NULL;
+ 
+               /* Start Phase 2 of EAP-TTLS authentication */
+-              if (lib->settings->get_bool(lib->settings,
+-                                      
"%s.plugins.eap-ttls.request_peer_auth", FALSE, lib->ns))
++              if (peer_auth)
+               {
+                       return start_phase2_tnc(this, EAP_TLS);
+               }
+@@ -278,6 +299,20 @@ METHOD(tls_application_t, process, statu
+       switch (status)
+       {
+               case SUCCESS:
++                      if (this->method->get_auth)
++                      {
++                              identification_t *id;
++                              auth_cfg_t *auth;
++
++                              auth = this->method->get_auth(this->method);
++                              id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
++                              if (id)
++                              {
++                                      this->peer->destroy(this->peer);
++                                      this->peer = id->clone(id);
++                              }
++                              this->auth->merge(this->auth, auth, FALSE);
++                      }
+                       DBG1(DBG_IKE, "%N phase2 authentication of '%Y' with %N 
successful",
+                                                       eap_type_names, 
EAP_TTLS, this->peer,
+                                                       eap_type_names, type);
+@@ -348,11 +383,18 @@ METHOD(tls_application_t, build, status_
+       return INVALID_STATE;
+ }
+ 
++METHOD(eap_ttls_server_t, get_auth, auth_cfg_t*,
++      private_eap_ttls_server_t *this)
++{
++      return this->auth;
++}
++
+ METHOD(tls_application_t, destroy, void,
+       private_eap_ttls_server_t *this)
+ {
+       this->server->destroy(this->server);
+       this->peer->destroy(this->peer);
++      this->auth->destroy(this->auth);
+       DESTROY_IF(this->method);
+       DESTROY_IF(this->out);
+       this->avp->destroy(this->avp);
+@@ -374,11 +416,13 @@ eap_ttls_server_t *eap_ttls_server_creat
+                               .build = _build,
+                               .destroy = _destroy,
+                       },
++                      .get_auth = _get_auth,
+               },
+               .server = server->clone(server),
+-              .peer = peer->clone(peer),
++              .auth = auth_cfg_create(),
+               .start_phase2 = TRUE,
+               .start_phase2_tnc = TRUE,
++              .peer = peer->clone(peer),
+               .avp = eap_ttls_avp_create(),
+       );
+ 
+--- a/src/libcharon/plugins/eap_ttls/eap_ttls_server.h
++++ b/src/libcharon/plugins/eap_ttls/eap_ttls_server.h
+@@ -37,6 +37,13 @@ struct eap_ttls_server_t {
+        * Implements the TLS application data handler.
+        */
+       tls_application_t application;
++
++      /**
++       * Get authentication details of this EAP method and its inner 
method(s).
++       *
++       * @return                              auth method, internal data
++       */
++      auth_cfg_t *(*get_auth)(eap_ttls_server_t *this);
+ };
+ 
+ /**
diff -Nru 
strongswan-5.9.8/debian/patches/0026-ikev2-Properly-reject-CREATE_CHILD_SA-requests-on-un.patch
 
strongswan-5.9.8/debian/patches/0026-ikev2-Properly-reject-CREATE_CHILD_SA-requests-on-un.patch
--- 
strongswan-5.9.8/debian/patches/0026-ikev2-Properly-reject-CREATE_CHILD_SA-requests-on-un.patch
     1969-12-31 18:00:00.000000000 -0600
+++ 
strongswan-5.9.8/debian/patches/0026-ikev2-Properly-reject-CREATE_CHILD_SA-requests-on-un.patch
     2026-10-27 11:22:34.000000000 -0500
@@ -0,0 +1,69 @@
+Origin: 
https://download.strongswan.org/security/CVE-2026-78135/strongswan-5.9.7-6.0.7_early_create_child_sa.patch
+Reviewed-by: Simon Quigley <[email protected]>
+Last-Update: 2026-10-26
+
+From a34fb034926ccfebe556eb66aae5572a3b0b7e14 Mon Sep 17 00:00:00 2001
+From: Tobias Brunner <[email protected]>
+Date: Mon, 27 Jul 2026 08:53:50 +0200
+Subject: [PATCH] ikev2: Properly reject CREATE_CHILD_SA requests on
+ unestablished IKE_SAs
+
+The previous check was not actually enforced as long as there were still
+tasks in the passive queue (it was originally added to fix an issue on
+initiators, so the passive queue was expected to be empty).  This allowed
+an unauthenticated attacker to potentially establish a usable Child SA
+if certain preconditions were met.
+
+First, it required that the initiator is authenticated with EAP so the
+authentication and the creation of the first Child SA is deferred.
+Second, the responder must either not configure an IP address pool or
+an explicit remote TS, otherwise, traffic selector negotiation fails.
+
+Note that the half-open IKE SA and the installed IPsec SA will be removed
+after the default timeout of 30 seconds.
+
+Fixes: 8503077175cd ("ikev2: Reject CREATE_CHILD_SA exchange on unestablished 
IKE_SAs")
+Fixes: c60c7694d2d8 ("merged tasking branch into trunk")
+Fixes: CVE-2026-78135
+---
+ src/libcharon/sa/ikev2/task_manager_v2.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+--- a/src/libcharon/sa/ikev2/task_manager_v2.c
++++ b/src/libcharon/sa/ikev2/task_manager_v2.c
+@@ -1129,9 +1129,18 @@ static status_t process_request(private_
+       delete_payload_t *delete;
+       ike_sa_state_t state;
+ 
++      state = this->ike_sa->get_state(this->ike_sa);
++      if (message->get_exchange_type(message) == CREATE_CHILD_SA &&
++              (state == IKE_CREATED || state == IKE_CONNECTING))
++      {
++              DBG1(DBG_IKE, "received CREATE_CHILD_SA request for "
++                       "unestablished IKE_SA, rejected");
++              return FAILED;
++      }
++
++      /* create tasks depending on request type, if not already some queued */
+       if (array_count(this->passive_tasks) == 0)
+-      {       /* create tasks depending on request type, if not already some 
queued */
+-              state = this->ike_sa->get_state(this->ike_sa);
++      {
+               switch (message->get_exchange_type(message))
+               {
+                       case IKE_SA_INIT:
+@@ -1172,14 +1181,6 @@ static status_t process_request(private_
+                       {       /* FIXME: we should prevent this on mediation 
connections */
+                               bool notify_found = FALSE, ts_found = FALSE;
+ 
+-                              if (state == IKE_CREATED ||
+-                                      state == IKE_CONNECTING)
+-                              {
+-                                      DBG1(DBG_IKE, "received CREATE_CHILD_SA 
request for "
+-                                               "unestablished IKE_SA, 
rejected");
+-                                      return FAILED;
+-                              }
+-
+                               enumerator = 
message->create_payload_enumerator(message);
+                               while (enumerator->enumerate(enumerator, 
&payload))
+                               {
diff -Nru strongswan-5.9.8/debian/patches/series 
strongswan-5.9.8/debian/patches/series
--- strongswan-5.9.8/debian/patches/series      2026-05-27 01:58:30.000000000 
-0500
+++ strongswan-5.9.8/debian/patches/series      2026-10-27 11:22:34.000000000 
-0500
@@ -14,3 +14,13 @@
 0014-constraints-Case-insensitive-matching-and-reject-exc.patch
 0015-gmp-Avoid-crash-and-timing-leaks-in-PKCS-1-v1.5-decr.patch
 0016-identification-Fix-double-free-when-cloning-empty-ID.patch
+0017-openssl-Fix-undefined-memory-access-when-verifying-P.patch
+0018-openssl-Fix-memory-leaks-after-enumerating-certifica.patch
+0019-eap-aka-Only-accept-AKA-Synchronization-Failure-if-e.patch
+0020-message-Avoid-memory-leak-if-string-buffer-for-messa.patch
+0021-pkcs5-Validate-parsed-parameters-to-avoid-DoS-attack.patch
+0022-x509-Avoid-NULL-pointer-dereference-if-issuerName-is.patch
+0023-x509-Fix-memory-leaks-when-parsing-attribute-certifi.patch
+0024-x509-Prevent-infinite-loop-when-parsing-ietfAttrSynt.patch
+0025-eap-ttls-peap-Return-auth-cfg-with-details-on-TLS-an.patch
+0026-ikev2-Properly-reject-CREATE_CHILD_SA-requests-on-un.patch

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to