Version in base suite: 6.0.1-6+deb13u6 Base version: strongswan_6.0.1-6+deb13u6 Target version: strongswan_6.0.1-6+deb13u7 Base file: /srv/ftp-master.debian.org/ftp/pool/main/s/strongswan/strongswan_6.0.1-6+deb13u6.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/s/strongswan/strongswan_6.0.1-6+deb13u7.dsc changelog | 23 patches/0018-openssl-Fix-undefined-memory-access-when-verifying-P.patch | 45 patches/0019-openssl-Fix-memory-leaks-after-enumerating-certifica.patch | 28 patches/0020-eap-aka-Only-accept-AKA-Synchronization-Failure-if-e.patch | 31 patches/0021-message-Avoid-memory-leak-if-string-buffer-for-messa.patch | 108 + patches/0022-pkcs5-Validate-parsed-parameters-to-avoid-DoS-attack.patch | 149 ++ patches/0023-x509-Avoid-NULL-pointer-dereference-if-issuerName-is.patch | 43 patches/0024-x509-Fix-memory-leaks-when-parsing-attribute-certifi.patch | 77 + patches/0025-x509-Prevent-infinite-loop-when-parsing-ietfAttrSynt.patch | 69 patches/0026-ikev2-Prevent-use-after-free-during-collision-after-.patch | 614 ++++++++ patches/0027-eap-ttls-peap-Return-auth-cfg-with-details-on-TLS-an.patch | 703 ++++++++++ patches/0028-ikev2-Properly-reject-CREATE_CHILD_SA-requests-on-un.patch | 66 patches/series | 11 po/ca.po | 2 po/cs.po | 2 po/da.po | 2 po/de.po | 2 po/es.po | 2 po/eu.po | 2 po/fi.po | 2 po/fr.po | 2 po/gl.po | 2 po/it.po | 2 po/ja.po | 2 po/nb.po | 2 po/nl.po | 2 po/pl.po | 2 po/pt.po | 2 po/pt_BR.po | 2 po/ru.po | 2 po/sv.po | 2 po/templates.pot | 2 po/tr.po | 2 po/vi.po | 2 34 files changed, 1988 insertions(+), 21 deletions(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpkeb63bnz/strongswan_6.0.1-6+deb13u6.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpkeb63bnz/strongswan_6.0.1-6+deb13u7.dsc: no acceptable signature found diff -Nru strongswan-6.0.1/debian/changelog strongswan-6.0.1/debian/changelog --- strongswan-6.0.1/debian/changelog 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/changelog 2026-09-01 11:29:28.000000000 +0000 @@ -1,3 +1,26 @@ +strongswan (6.0.1-6+deb13u7) trixie-security; urgency=medium + + * d/patches: add fix for undefined memory access when verifying PKCS#7 + containers (CVE-2026-78123) + * d/patches: add patch to fix memory leaks after enumerating certificates in + PKCS#7 containers (CVE-2026-78124) + * d/patches: fix NULL-pointer dereference in EAP-AKA (CVE-2026-78126) + * d/patches: avoid memory leak in IKE message logging (CVE-2026-78127) + * d/patches: fix potential DoS by validating PKCS#5 parsed parameters + (CVE-2026-78129) + * d/patches: fix NULL-pointer dereference in x509 code (CVE-2026-78130) + * d/patches: fix memory leak when parsing x509 attribute certificates + (CVE-2026-78131) + * d/patches: fix infinite loop when parsing x509 attribute certificates + (CVE-2026-78132) + * d/patches: fix use-after-free in IKEv2 rekeying (CVE-2026-78133) + * d/patches: fix several issues with binding identities to the IKE SA + (CVE-2026-78134) + * d/patches: properly reject CREATE_CHILD_SA requests on unestablished + IKE_SA (CVE-2026-78135) + + -- Yves-Alexis Perez Tue, 01 Sep 2026 13:29:28 +0200 + strongswan (6.0.1-6+deb13u6) trixie-security; urgency=medium * d/patches: add fix for double-free when cloning empty IDs (CVE-2026-47895) diff -Nru strongswan-6.0.1/debian/patches/0018-openssl-Fix-undefined-memory-access-when-verifying-P.patch strongswan-6.0.1/debian/patches/0018-openssl-Fix-undefined-memory-access-when-verifying-P.patch --- strongswan-6.0.1/debian/patches/0018-openssl-Fix-undefined-memory-access-when-verifying-P.patch 1970-01-01 00:00:00.000000000 +0000 +++ strongswan-6.0.1/debian/patches/0018-openssl-Fix-undefined-memory-access-when-verifying-P.patch 2026-09-01 11:29:28.000000000 +0000 @@ -0,0 +1,45 @@ +From: Tobias Brunner +Date: Mon, 1 Jun 2026 17:51:35 +0200 +Subject: 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(-) + +diff --git a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c +index d9abcf8..b15c8d7 100644 +--- a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c ++++ b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c +@@ -222,8 +222,8 @@ static auth_cfg_t *verify_signature(CMS_SignerInfo *si, + 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) +@@ -628,8 +628,8 @@ static bool decrypt(private_openssl_pkcs7_t *this, + 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-6.0.1/debian/patches/0019-openssl-Fix-memory-leaks-after-enumerating-certifica.patch strongswan-6.0.1/debian/patches/0019-openssl-Fix-memory-leaks-after-enumerating-certifica.patch --- strongswan-6.0.1/debian/patches/0019-openssl-Fix-memory-leaks-after-enumerating-certifica.patch 1970-01-01 00:00:00.000000000 +0000 +++ strongswan-6.0.1/debian/patches/0019-openssl-Fix-memory-leaks-after-enumerating-certifica.patch 2026-09-01 11:29:28.000000000 +0000 @@ -0,0 +1,28 @@ +From: Tobias Brunner +Date: Mon, 15 Jun 2026 16:02:01 +0200 +Subject: 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(+) + +diff --git a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c +index b15c8d7..cefe1ae 100644 +--- 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-6.0.1/debian/patches/0020-eap-aka-Only-accept-AKA-Synchronization-Failure-if-e.patch strongswan-6.0.1/debian/patches/0020-eap-aka-Only-accept-AKA-Synchronization-Failure-if-e.patch --- strongswan-6.0.1/debian/patches/0020-eap-aka-Only-accept-AKA-Synchronization-Failure-if-e.patch 1970-01-01 00:00:00.000000000 +0000 +++ strongswan-6.0.1/debian/patches/0020-eap-aka-Only-accept-AKA-Synchronization-Failure-if-e.patch 2026-09-01 11:29:28.000000000 +0000 @@ -0,0 +1,31 @@ +From: Tobias Brunner +Date: Thu, 4 Jun 2026 10:00:02 +0200 +Subject: 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(+) + +diff --git a/src/libcharon/plugins/eap_aka/eap_aka_server.c b/src/libcharon/plugins/eap_aka/eap_aka_server.c +index 0712ccc..95d4b03 100644 +--- 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(private_eap_aka_server_t *this, + 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-6.0.1/debian/patches/0021-message-Avoid-memory-leak-if-string-buffer-for-messa.patch strongswan-6.0.1/debian/patches/0021-message-Avoid-memory-leak-if-string-buffer-for-messa.patch --- strongswan-6.0.1/debian/patches/0021-message-Avoid-memory-leak-if-string-buffer-for-messa.patch 1970-01-01 00:00:00.000000000 +0000 +++ strongswan-6.0.1/debian/patches/0021-message-Avoid-memory-leak-if-string-buffer-for-messa.patch 2026-09-01 11:29:28.000000000 +0000 @@ -0,0 +1,108 @@ +From: Tobias Brunner +Date: Mon, 8 Jun 2026 09:19:42 +0200 +Subject: 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(-) + +diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c +index 5d05e20..7b1ad2b 100644 +--- a/src/libcharon/encoding/message.c ++++ b/src/libcharon/encoding/message.c +@@ -1398,7 +1398,7 @@ static char* get_string(private_message_t *this, char *buf, int len) + payload->get_type(payload)); + if (written >= len || written < 0) + { +- return buf; ++ goto err; + } + pos += written; + len -= written; +@@ -1424,7 +1424,7 @@ static char* get_string(private_message_t *this, char *buf, int len) + } + if (written >= len || written < 0) + { +- return buf; ++ goto err; + } + pos += written; + len -= written; +@@ -1454,7 +1454,7 @@ static char* get_string(private_message_t *this, char *buf, int len) + eap->get_code(eap), method); + if (written >= len || written < 0) + { +- return buf; ++ goto err; + } + pos += written; + len -= written; +@@ -1495,7 +1495,8 @@ static char* get_string(private_message_t *this, char *buf, int len) + attribute->get_type(attribute)); + if (written >= len || written < 0) + { +- return buf; ++ attributes->destroy(attributes); ++ goto err; + } + pos += written; + len -= written; +@@ -1507,7 +1508,7 @@ static char* get_string(private_message_t *this, char *buf, int len) + written = snprintf(pos, len, ")"); + if (written >= len || written < 0) + { +- return buf; ++ goto err; + } + pos += written; + len -= written; +@@ -1529,7 +1530,7 @@ static char* get_string(private_message_t *this, char *buf, int len) + } + if (written >= len || written < 0) + { +- return buf; ++ goto err; + } + pos += written; + len -= written; +@@ -1544,7 +1545,7 @@ static char* get_string(private_message_t *this, char *buf, int len) + frag->get_total_fragments(frag)); + if (written >= len || written < 0) + { +- return buf; ++ goto err; + } + pos += written; + len -= written; +@@ -1557,16 +1558,16 @@ static char* get_string(private_message_t *this, char *buf, int len) + 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; + } + #endif diff -Nru strongswan-6.0.1/debian/patches/0022-pkcs5-Validate-parsed-parameters-to-avoid-DoS-attack.patch strongswan-6.0.1/debian/patches/0022-pkcs5-Validate-parsed-parameters-to-avoid-DoS-attack.patch --- strongswan-6.0.1/debian/patches/0022-pkcs5-Validate-parsed-parameters-to-avoid-DoS-attack.patch 1970-01-01 00:00:00.000000000 +0000 +++ strongswan-6.0.1/debian/patches/0022-pkcs5-Validate-parsed-parameters-to-avoid-DoS-attack.patch 2026-09-01 11:29:28.000000000 +0000 @@ -0,0 +1,149 @@ +From: Tobias Brunner +Date: Tue, 23 Jun 2026 11:55:31 +0200 +Subject: 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(-) + +diff --git a/src/libstrongswan/crypto/pkcs5.c b/src/libstrongswan/crypto/pkcs5.c +index 4851d3f..d2e3f39 100644 +--- a/src/libstrongswan/crypto/pkcs5.c ++++ b/src/libstrongswan/crypto/pkcs5.c +@@ -14,6 +14,8 @@ + * for more details. + */ + ++#include ++ + #include "pkcs5.h" + + #include +@@ -22,6 +24,15 @@ + #include + #include + ++/** 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; + + /** +@@ -379,6 +390,41 @@ METHOD(pkcs5_t, decrypt, bool, + keymat, key, iv); + } + ++/** ++ * 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 + */ +@@ -399,7 +445,7 @@ static bool parse_pbes1_params(private_pkcs5_t *this, chunk_t blob, int level0) + 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_pkcs5_t *this, chunk_t blob, int level0) + { + 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_pkcs5_t *this, chunk_t blob, int level0) + } + } + 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_pkcs5_t *this, chunk_t blob, int level0) + { + 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_pkcs5_t *this, chunk_t blob, int level0) + } + } + success = parser->success(parser); ++ if (success) ++ { ++ success = validate_params(this); ++ } + end: + parser->destroy(parser); + return success; diff -Nru strongswan-6.0.1/debian/patches/0023-x509-Avoid-NULL-pointer-dereference-if-issuerName-is.patch strongswan-6.0.1/debian/patches/0023-x509-Avoid-NULL-pointer-dereference-if-issuerName-is.patch --- strongswan-6.0.1/debian/patches/0023-x509-Avoid-NULL-pointer-dereference-if-issuerName-is.patch 1970-01-01 00:00:00.000000000 +0000 +++ strongswan-6.0.1/debian/patches/0023-x509-Avoid-NULL-pointer-dereference-if-issuerName-is.patch 2026-09-01 11:29:28.000000000 +0000 @@ -0,0 +1,43 @@ +From: Tobias Brunner +Date: Fri, 19 Jun 2026 11:57:48 +0200 +Subject: 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(-) + +diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c +index 3fc5de2..8765ad0 100644 +--- a/src/libstrongswan/plugins/x509/x509_ac.c ++++ b/src/libstrongswan/plugins/x509/x509_ac.c +@@ -913,7 +913,11 @@ METHOD(certificate_t, has_issuer, id_match_t, + { + 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, +@@ -950,7 +954,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-6.0.1/debian/patches/0024-x509-Fix-memory-leaks-when-parsing-attribute-certifi.patch strongswan-6.0.1/debian/patches/0024-x509-Fix-memory-leaks-when-parsing-attribute-certifi.patch --- strongswan-6.0.1/debian/patches/0024-x509-Fix-memory-leaks-when-parsing-attribute-certifi.patch 1970-01-01 00:00:00.000000000 +0000 +++ strongswan-6.0.1/debian/patches/0024-x509-Fix-memory-leaks-when-parsing-attribute-certifi.patch 2026-09-01 11:29:28.000000000 +0000 @@ -0,0 +1,77 @@ +From: Tobias Brunner +Date: Fri, 12 Jun 2026 15:55:43 +0200 +Subject: 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(-) + +diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c +index 8765ad0..11a847e 100644 +--- 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(chunk_t blob, int level0, bool implicit, + 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; + } + +@@ -539,6 +523,7 @@ static bool parse_certificate(private_x509_ac_t *this) + 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-6.0.1/debian/patches/0025-x509-Prevent-infinite-loop-when-parsing-ietfAttrSynt.patch strongswan-6.0.1/debian/patches/0025-x509-Prevent-infinite-loop-when-parsing-ietfAttrSynt.patch --- strongswan-6.0.1/debian/patches/0025-x509-Prevent-infinite-loop-when-parsing-ietfAttrSynt.patch 1970-01-01 00:00:00.000000000 +0000 +++ strongswan-6.0.1/debian/patches/0025-x509-Prevent-infinite-loop-when-parsing-ietfAttrSynt.patch 2026-09-01 11:29:28.000000000 +0000 @@ -0,0 +1,69 @@ +From: Tobias Brunner +Date: Wed, 1 Jul 2026 16:24:23 +0200 +Subject: 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(-) + +diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c +index 11a847e..46c1f58 100644 +--- 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 blob, int level0) + */ + 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-6.0.1/debian/patches/0026-ikev2-Prevent-use-after-free-during-collision-after-.patch strongswan-6.0.1/debian/patches/0026-ikev2-Prevent-use-after-free-during-collision-after-.patch --- strongswan-6.0.1/debian/patches/0026-ikev2-Prevent-use-after-free-during-collision-after-.patch 1970-01-01 00:00:00.000000000 +0000 +++ strongswan-6.0.1/debian/patches/0026-ikev2-Prevent-use-after-free-during-collision-after-.patch 2026-09-01 11:29:28.000000000 +0000 @@ -0,0 +1,614 @@ +From: Tobias Brunner +Date: Fri, 5 Jun 2026 08:15:46 +0200 +Subject: ikev2: Prevent use-after-free during collision after passive + multi-KE rekeying failed + +During a multi-KE rekey collision, where the initial response to the +active rekeying is delayed (or withheld), the active task already keeps +track of the passive task to eventually resolve the collision (it can +only do so once all nonces are known). + +If the passive task then fails, e.g. due to a missing or invalid KE +payload, and completes with SUCCESS, `collide()` previously recognized +that the passive task is not yet complete returned FALSE, which caused +the task manager to destroy the task. However, the reference in the +active task would remain. So once the active rekeying progresses and +the collision is resolved, that dangling pointer would get dereferenced +for an indirect method call. This happens via the `get_lower_nonce` +function pointer of the `child_create_t` instance in the private task +struct. So besides having to be authenticated, an attacker has to get +two indirections right to exploit this flaw for a potential RCE. +Otherwise, the effects are a crash or basically undefined behavior +triggered by the method call. + +By passing whether the passive task is done (and would get destroyed), +the active tasks can properly clear the held reference. + +Note that this patch includes another fix for a state change during +Child SA rekeying that's included in 6.1.0 (4611f41b1e14 ("child-rekey: +Only reset state of SAs not actively rekeyed if passive rekeying +fails")). + +Fixes: d2b2e1b3fae8 ("ikev2: Make CHILD_SAs properly trackable during rekey collisions") +Fixes: ca3e6d2d144e ("ike-rekey: Support IKE_SA rekeying with multiple key exchanges") +Fixes: CVE-2026-78133 +--- + src/libcharon/sa/ikev2/task_manager_v2.c | 13 +-- + src/libcharon/sa/ikev2/tasks/child_rekey.c | 47 ++++++-- + src/libcharon/sa/ikev2/tasks/child_rekey.h | 3 +- + src/libcharon/sa/ikev2/tasks/ike_rekey.c | 40 +++++-- + src/libcharon/sa/ikev2/tasks/ike_rekey.h | 3 +- + src/libcharon/tests/suites/test_child_rekey.c | 136 ++++++++++++++++++++++++ + src/libcharon/tests/suites/test_ike_rekey.c | 147 ++++++++++++++++++++++++++ + 7 files changed, 361 insertions(+), 28 deletions(-) + +diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c +index 86f9f8b..85aaa24 100644 +--- a/src/libcharon/sa/ikev2/task_manager_v2.c ++++ b/src/libcharon/sa/ikev2/task_manager_v2.c +@@ -927,7 +927,8 @@ static status_t process_response(private_task_manager_t *this, + * Handle exchange collisions, returns TRUE if the given passive task was + * adopted by the active task and the task manager lost control over it. + */ +-static bool handle_collisions(private_task_manager_t *this, task_t *task) ++static bool handle_collisions(private_task_manager_t *this, task_t *task, ++ bool done) + { + enumerator_t *enumerator; + task_t *active; +@@ -951,7 +952,7 @@ static bool handle_collisions(private_task_manager_t *this, task_t *task) + if (type == TASK_IKE_REKEY || type == TASK_IKE_DELETE) + { + ike_rekey_t *rekey = (ike_rekey_t*)active; +- adopted = rekey->collide(rekey, task); ++ adopted = rekey->collide(rekey, task, done); + break; + } + continue; +@@ -959,7 +960,7 @@ static bool handle_collisions(private_task_manager_t *this, task_t *task) + if (type == TASK_CHILD_REKEY) + { + child_rekey_t *rekey = (child_rekey_t*)active; +- adopted = rekey->collide(rekey, task); ++ adopted = rekey->collide(rekey, task, done); + break; + } + continue; +@@ -1011,14 +1012,14 @@ static status_t build_response(private_task_manager_t *this, message_t *request) + case SUCCESS: + /* task completed, remove it */ + array_remove_at(this->passive_tasks, enumerator); +- if (!handle_collisions(this, task)) ++ if (!handle_collisions(this, task, TRUE)) + { + task->destroy(task); + } + break; + case NEED_MORE: + /* processed, but task needs another exchange */ +- if (handle_collisions(this, task)) ++ if (handle_collisions(this, task, FALSE)) + { + array_remove_at(this->passive_tasks, enumerator); + } +@@ -1029,7 +1030,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request) + /* FALL */ + case DESTROY_ME: + /* destroy IKE_SA, but SEND response first */ +- if (handle_collisions(this, task)) ++ if (handle_collisions(this, task, FALSE)) + { + array_remove_at(this->passive_tasks, enumerator); + } +diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c +index 6c73d06..51edfa1 100644 +--- a/src/libcharon/sa/ikev2/tasks/child_rekey.c ++++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c +@@ -406,7 +406,7 @@ METHOD(task_t, build_r, status_t, + child_sa_t *child_sa; + child_sa_state_t state = CHILD_INSTALLED; + uint32_t reqid; +- bool followup_sent = FALSE; ++ bool active, followup_sent = FALSE; + + if (!this->child_sa) + { +@@ -426,7 +426,8 @@ METHOD(task_t, build_r, status_t, + message->add_notify(message, TRUE, TEMPORARY_FAILURE, chunk_empty); + return SUCCESS; + } +- if (actively_rekeying(this, &followup_sent) && followup_sent) ++ active = actively_rekeying(this, &followup_sent); ++ if (active && followup_sent) + { + DBG1(DBG_IKE, "peer initiated rekeying, but we did too and already " + "sent IKE_FOLLOWUP_KE"); +@@ -475,8 +476,9 @@ METHOD(task_t, build_r, status_t, + /* like installing the outbound SA, we only trigger the child-rekey + * event once the old SA is deleted */ + } +- else if (this->child_sa->get_state(this->child_sa) == CHILD_REKEYING) +- { /* rekeying failed, reuse old child */ ++ else if (!active && ++ this->child_sa->get_state(this->child_sa) == CHILD_REKEYING) ++ { /* rekeying failed, reuse old child, unless we are actively rekeying */ + this->child_sa->set_state(this->child_sa, state); + } + return SUCCESS; +@@ -1119,8 +1121,22 @@ METHOD(child_rekey_t, handle_delete, child_rekey_collision_t, + return CHILD_REKEY_COLLISION_NONE; + } + ++/** ++ * Clear the colliding passive task if it did not complete successfully. ++ */ ++static void clear_collision(private_child_rekey_t *this, task_t *other) ++{ ++ if (this->collision == other) ++ { ++ DBG1(DBG_IKE, "colliding passive rekeying for CHILD_SA %s{%u} " ++ "failed", this->child_sa->get_name(this->child_sa), ++ this->child_sa->get_unique_id(this->child_sa)); ++ this->collision = NULL; ++ } ++} ++ + METHOD(child_rekey_t, collide, bool, +- private_child_rekey_t *this, task_t *other) ++ private_child_rekey_t *this, task_t *other, bool done) + { + private_child_rekey_t *rekey = (private_child_rekey_t*)other; + child_sa_t *other_child; +@@ -1134,16 +1150,25 @@ METHOD(child_rekey_t, collide, bool, + other_child = rekey->child_create->get_child(rekey->child_create); + if (!other_child) + { +- /* ignore passive tasks that did not successfully create a CHILD_SA */ ++ /* ignore passive tasks that did not successfully create a CHILD_SA, ++ * if we are already tracking it in the multi-KE case, clear it */ ++ clear_collision(this, other); + return FALSE; + } + if (other_child->get_state(other_child) != CHILD_INSTALLED) + { +- DBG1(DBG_IKE, "colliding passive rekeying for CHILD_SA %s{%u} is not " +- "yet complete", this->child_sa->get_name(this->child_sa), +- this->child_sa->get_unique_id(this->child_sa)); +- /* we do reference the task to check its state later */ +- this->collision = other; ++ if (done) ++ { /* passive task failed, clear it if necessary */ ++ clear_collision(this, other); ++ } ++ else ++ { ++ DBG1(DBG_IKE, "colliding passive rekeying for CHILD_SA %s{%u} is " ++ "not yet complete", this->child_sa->get_name(this->child_sa), ++ this->child_sa->get_unique_id(this->child_sa)); ++ /* we do reference the task to check its state later */ ++ this->collision = other; ++ } + return FALSE; + } + if (this->collision && this->collision != other) +diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.h b/src/libcharon/sa/ikev2/tasks/child_rekey.h +index a8daed7..fef0bba 100644 +--- a/src/libcharon/sa/ikev2/tasks/child_rekey.h ++++ b/src/libcharon/sa/ikev2/tasks/child_rekey.h +@@ -79,10 +79,11 @@ struct child_rekey_t { + * are going on and notifies the active task by passing the passive. + * + * @param other passive task ++ * @param done passive task is done and gets destroyed if not adopted + * @return whether the task was adopted and should be removed from + * the task manager's control + */ +- bool (*collide)(child_rekey_t* this, task_t *other); ++ bool (*collide)(child_rekey_t* this, task_t *other, bool done); + }; + + /** +diff --git a/src/libcharon/sa/ikev2/tasks/ike_rekey.c b/src/libcharon/sa/ikev2/tasks/ike_rekey.c +index f624464..cb45bda 100644 +--- a/src/libcharon/sa/ikev2/tasks/ike_rekey.c ++++ b/src/libcharon/sa/ikev2/tasks/ike_rekey.c +@@ -743,8 +743,23 @@ METHOD(ike_rekey_t, did_collide, bool, + return this->collision != NULL; + } + ++/** ++ * Clear the colliding passive task if it did not complete successfully. ++ */ ++static bool clear_collision(private_ike_rekey_t *this, ++ private_ike_rekey_t *other) ++{ ++ if (this->collision == other) ++ { ++ DBG1(DBG_IKE, "colliding passive rekeying failed, ignore"); ++ this->collision = NULL; ++ return TRUE; ++ } ++ return FALSE; ++} ++ + METHOD(ike_rekey_t, collide, bool, +- private_ike_rekey_t* this, task_t *other) ++ private_ike_rekey_t* this, task_t *other, bool done) + { + DBG1(DBG_IKE, "detected %N collision with %N", task_type_names, + TASK_IKE_REKEY, task_type_names, other->get_type(other)); +@@ -760,23 +775,30 @@ METHOD(ike_rekey_t, collide, bool, + + if (!rekey->ike_init) + { +- DBG1(DBG_IKE, "colliding exchange did not result in an IKE_SA, " +- "ignore"); +- if (this->collision == rekey) ++ if (!clear_collision(this, rekey)) + { +- this->collision = NULL; ++ DBG1(DBG_IKE, "colliding exchange did not result in an " ++ "IKE_SA, ignore"); + } + break; + } +- /* we keep track of the passive exchange in any case, if not +- * complete yet, this method might be called again later */ +- this->collision = rekey; ++ /* we keep track of the passive exchange, if not complete yet, this ++ * method might be called again later */ + if (rekey->flags & IKE_REKEY_DONE) + { ++ this->collision = rekey; + this->flags |= IKE_REKEY_ADOPTED_PASSIVE; + return TRUE; + } +- DBG1(DBG_IKE, "colliding passive exchange is not yet complete"); ++ else if (done) ++ { /* passive task failed, clear it if necessary */ ++ clear_collision(this, rekey); ++ } ++ else ++ { ++ DBG1(DBG_IKE, "colliding passive exchange is not yet complete"); ++ this->collision = rekey; ++ } + break; + } + default: +diff --git a/src/libcharon/sa/ikev2/tasks/ike_rekey.h b/src/libcharon/sa/ikev2/tasks/ike_rekey.h +index 5fab349..e68fa62 100644 +--- a/src/libcharon/sa/ikev2/tasks/ike_rekey.h ++++ b/src/libcharon/sa/ikev2/tasks/ike_rekey.h +@@ -54,10 +54,11 @@ struct ike_rekey_t { + * are going on and notifies the active task by passing the passive. + * + * @param other passive task ++ * @param done passive task is done and gets destroyed if not adopted + * @return whether the task was adopted and should be removed from + * the task manager's control + */ +- bool (*collide)(ike_rekey_t* this, task_t *other); ++ bool (*collide)(ike_rekey_t* this, task_t *other, bool done); + }; + + /** +diff --git a/src/libcharon/tests/suites/test_child_rekey.c b/src/libcharon/tests/suites/test_child_rekey.c +index b61f31c..ed92849 100644 +--- a/src/libcharon/tests/suites/test_child_rekey.c ++++ b/src/libcharon/tests/suites/test_child_rekey.c +@@ -2488,6 +2488,141 @@ START_TEST(test_collision_delayed_response_multi_ke) + } + END_TEST + ++/** ++ * Remove the KE payload from the IKE_FOLLOWUP_KE request ++ */ ++static bool remove_ke(listener_t *listener, ike_sa_t *ike_sa, ++ message_t *message, bool incoming, bool plain) ++{ ++ if (plain && incoming && ++ message->get_exchange_type(message) == IKE_FOLLOWUP_KE && ++ message->get_request(message)) ++ { ++ enumerator_t *enumerator = message->create_payload_enumerator(message); ++ payload_t *pld; ++ ++ while (enumerator->enumerate(enumerator, &pld)) ++ { ++ if (pld->get_type(pld) == PLV2_KEY_EXCHANGE) ++ { ++ message->remove_payload_at(message, enumerator); ++ pld->destroy(pld); ++ break; ++ } ++ } ++ enumerator->destroy(enumerator); ++ free(listener); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++#define remove_ke_from_ike_followup_ke() ({ \ ++ listener_t *_ke_listener; \ ++ INIT(_ke_listener, \ ++ .message = remove_ke, \ ++ ); \ ++ exchange_test_helper->add_listener(exchange_test_helper, _ke_listener); \ ++}) ++ ++/** ++ * This simulates an incorrect behavior by the peer. It triggers a collision by ++ * not responding to the initial CREATE_CHILD_SA and then sends an invalid ++ * IKE_FOLLOWUP_KE (in this case the KE payload is missing). The initiator ++ * has to correctly track and then untrack the passive rekey task. ++ * ++ * Peer A Peer B ++ * rekey ----\ /---- rekey ++ * \-----/----> detect collision and withhold response ++ * detect collision <---------/ ++ * ----------------> ++ * handle failure <---------------- send invalid additional KE ++ * handle rekey <---------------- send withheld response ++ */ ++START_TEST(test_collision_delayed_response_multi_ke_failure) ++{ ++ ike_sa_t *a, *b; ++ message_t *msg; ++ ++ assert_track_sas_start(); ++ ++ exchange_test_helper->establish_sa(exchange_test_helper, ++ &a, &b, &multi_ke_conf); ++ ++ /* make sure the responder wins the collision so it continues */ ++ exchange_test_helper->nonce_first_byte = 0x00; ++ initiate_rekey(a, 1); ++ assert_ipsec_sas_installed(a, 1, 2); ++ exchange_test_helper->nonce_first_byte = 0xff; ++ initiate_rekey(b, 2); ++ assert_ipsec_sas_installed(b, 1, 2); ++ ++ /* these should not get called as no SA goes down or gets rekeyed */ ++ assert_hook_not_called(child_updown); ++ assert_hook_not_called(child_rekey); ++ ++ /* CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } --> */ ++ exchange_test_helper->nonce_first_byte = 0xff; ++ exchange_test_helper->process_message(exchange_test_helper, b, NULL); ++ assert_child_sa_state(b, 2, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED); ++ assert_ipsec_sas_installed(b, 1, 2); ++ ++ /* <-- CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } */ ++ exchange_test_helper->nonce_first_byte = 0xff; ++ exchange_test_helper->process_message(exchange_test_helper, a, NULL); ++ assert_child_sa_state(a, 1, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED); ++ assert_ipsec_sas_installed(a, 1, 2); ++ ++ /* the responder is not responding */ ++ msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender); ++ ++ /* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */ ++ exchange_test_helper->process_message(exchange_test_helper, b, NULL); ++ assert_num_tasks(b, 0, TASK_QUEUE_PASSIVE); ++ assert_num_tasks(b, 1, TASK_QUEUE_ACTIVE); ++ assert_child_sa_state(b, 2, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED); ++ assert_ipsec_sas_installed(b, 1, 2); ++ ++ /* remove the KE payload in the IKE_FOLLOWUP_KE request */ ++ remove_ke_from_ike_followup_ke(); ++ ++ /* <-- IKE_FOLLOWUP_KE { N(ADD_KE) } */ ++ assert_no_payload(IN, PLV2_KEY_EXCHANGE); ++ assert_single_notify(OUT, INVALID_SYNTAX); ++ exchange_test_helper->process_message(exchange_test_helper, a, NULL); ++ assert_child_sa_state(a, 1, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED); ++ assert_ipsec_sas_installed(a, 1, 2); ++ assert_num_tasks(a, 0, TASK_QUEUE_PASSIVE); ++ ++ /* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } (delayed) */ ++ exchange_test_helper->process_message(exchange_test_helper, a, msg); ++ assert_num_tasks(a, 0, TASK_QUEUE_PASSIVE); ++ assert_num_tasks(a, 1, TASK_QUEUE_ACTIVE); ++ assert_child_sa_state(a, 1, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED); ++ assert_ipsec_sas_installed(a, 1, 2); ++ ++ /* drop the STATE_NOT_FOUND error message from the initiator */ ++ msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender); ++ msg->destroy(msg); ++ ++ /* since we explicitly forced the responder to win, it already removed ++ * the passive task it won't accept the request */ ++ ++ /* IKE_FOLLOWUP_KE { KEi, N(ADD_KE) } --> */ ++ assert_payload(IN, PLV2_KEY_EXCHANGE); ++ assert_notify(IN, ADDITIONAL_KEY_EXCHANGE); ++ exchange_test_helper->process_message(exchange_test_helper, b, NULL); ++ ++ /* child_rekey/child_updown */ ++ assert_hook(); ++ assert_hook(); ++ assert_track_sas(2, 2); ++ ++ call_ikesa(a, destroy); ++ call_ikesa(b, destroy); ++} ++END_TEST ++ + /** + * In this scenario one of the peers does not notice that there is a + * rekey collision: +@@ -4377,6 +4512,7 @@ Suite *child_rekey_suite_create() + tcase_add_loop_test(tc, test_collision_delayed_response, 0, 4); + tcase_add_loop_test(tc, test_collision_delayed_response_delete, 0, 4); + tcase_add_loop_test(tc, test_collision_delayed_response_multi_ke, 0, 4); ++ tcase_add_test(tc, test_collision_delayed_response_multi_ke_failure); + tcase_add_loop_test(tc, test_collision_delayed_request, 0, 6); + tcase_add_loop_test(tc, test_collision_delayed_request_more, 0, 3); + tcase_add_loop_test(tc, test_collision_delayed_request_more_delete, 0, 3); +diff --git a/src/libcharon/tests/suites/test_ike_rekey.c b/src/libcharon/tests/suites/test_ike_rekey.c +index c6691ac..2c41022 100644 +--- a/src/libcharon/tests/suites/test_ike_rekey.c ++++ b/src/libcharon/tests/suites/test_ike_rekey.c +@@ -1784,6 +1784,152 @@ START_TEST(test_collision_delayed_response_multi_ke) + } + END_TEST + ++/** ++ * Remove the ADDITIONAL_KEY_EXCHANGE notify payload from the IKE_FOLLOWUP_KE ++ * request ++ */ ++static bool remove_notify(listener_t *listener, ike_sa_t *ike_sa, ++ message_t *message, bool incoming, bool plain) ++{ ++ if (plain && incoming && ++ message->get_exchange_type(message) == IKE_FOLLOWUP_KE && ++ message->get_request(message)) ++ { ++ enumerator_t *enumerator = message->create_payload_enumerator(message); ++ payload_t *pld; ++ ++ while (enumerator->enumerate(enumerator, &pld)) ++ { /* we only expect one notify, so just remove the first */ ++ if (pld->get_type(pld) == PLV2_NOTIFY) ++ { ++ message->remove_payload_at(message, enumerator); ++ pld->destroy(pld); ++ break; ++ } ++ } ++ enumerator->destroy(enumerator); ++ free(listener); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++#define remove_notify_from_ike_followup_ke() ({ \ ++ listener_t *_ke_listener; \ ++ INIT(_ke_listener, \ ++ .message = remove_notify, \ ++ ); \ ++ exchange_test_helper->add_listener(exchange_test_helper, _ke_listener); \ ++}) ++ ++/** ++ * This simulates an incorrect behavior by the peer. It triggers a collision by ++ * not responding to the initial CREATE_CHILD_SA and then sends an invalid ++ * IKE_FOLLOWUP_KE (in this case by removing the ADDITIONAL_KEY_EXCHANGE ++ * notify). The initiator has to correctly track and then untrack the passive ++ * rekey task. ++ * ++ * Peer A Peer B ++ * rekey ----\ /---- rekey ++ * \-----/----> detect collision and withhold response ++ * detect collision <---------/ ++ * ----------------> ++ * handle failure <---------------- send invalid additional KE ++ * handle rekey <---------------- send withheld response ++ */ ++START_TEST(test_collision_delayed_response_multi_ke_failure) ++{ ++ ike_sa_t *a, *b; ++ message_t *msg; ++ ++ assert_track_sas_start(); ++ ++ exchange_test_helper->establish_sa(exchange_test_helper, ++ &a, &b, &multi_ke_conf); ++ ++ /* these should not get called as no SA goes down or gets rekeyed */ ++ assert_hook_not_called(ike_updown); ++ assert_hook_not_called(ike_rekey); ++ assert_hook_not_called(child_updown); ++ ++ /* make sure the responder wins the collision so it continues */ ++ exchange_test_helper->nonce_first_byte = 0x00; ++ initiate_rekey(a); ++ exchange_test_helper->nonce_first_byte = 0xff; ++ initiate_rekey(b); ++ ++ /* CREATE_CHILD_SA { SA, Ni, KEi } --> */ ++ exchange_test_helper->nonce_first_byte = 0xff; ++ exchange_test_helper->process_message(exchange_test_helper, b, NULL); ++ assert_ike_sa_state(b, IKE_REKEYING); ++ assert_child_sa_count(b, 1); ++ assert_ike_sa_count(0); ++ ++ /* <-- CREATE_CHILD_SA { SA, Ni, KEi } */ ++ exchange_test_helper->nonce_first_byte = 0xff; ++ exchange_test_helper->process_message(exchange_test_helper, a, NULL); ++ assert_ike_sa_state(a, IKE_REKEYING); ++ assert_child_sa_count(a, 1); ++ assert_ike_sa_count(0); ++ ++ /* the responder is not responding */ ++ msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender); ++ ++ /* simplify next steps by checking in original IKE_SAs */ ++ charon->ike_sa_manager->checkin(charon->ike_sa_manager, a); ++ charon->ike_sa_manager->checkin(charon->ike_sa_manager, b); ++ assert_ike_sa_count(2); ++ ++ /* CREATE_CHILD_SA { SA, Nr, KEr, N(ADD_KE) } --> */ ++ assert_notify(IN, ADDITIONAL_KEY_EXCHANGE); ++ exchange_test_helper->process_message(exchange_test_helper, b, NULL); ++ assert_num_tasks(b, 0, TASK_QUEUE_PASSIVE); ++ assert_num_tasks(b, 1, TASK_QUEUE_ACTIVE); ++ assert_ike_sa_state(b, IKE_REKEYING); ++ assert_ike_sa_count(2); ++ ++ /* remove the ADD_KE notify from the IKE_FOLLOWUP_KE request */ ++ remove_notify_from_ike_followup_ke(); ++ ++ /* <-- IKE_FOLLOWUP_KE { KEi } */ ++ assert_payload(IN, PLV2_KEY_EXCHANGE); ++ assert_no_notify(IN, ADDITIONAL_KEY_EXCHANGE); ++ assert_single_notify(OUT, STATE_NOT_FOUND); ++ exchange_test_helper->process_message(exchange_test_helper, a, NULL); ++ assert_ike_sa_state(a, IKE_REKEYING); ++ assert_child_sa_count(a, 1); ++ assert_ike_sa_count(2); ++ ++ /* <-- CREATE_CHILD_SA { SA, Nr, KEr } (delayed) */ ++ exchange_test_helper->process_message(exchange_test_helper, a, msg); ++ assert_num_tasks(a, 0, TASK_QUEUE_PASSIVE); ++ assert_num_tasks(a, 1, TASK_QUEUE_ACTIVE); ++ assert_ike_sa_state(a, IKE_REKEYING); ++ assert_child_sa_count(a, 1); ++ assert_ike_sa_count(2); ++ ++ /* drop the STATE_NOT_FOUND error message from the initiator */ ++ msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender); ++ msg->destroy(msg); ++ ++ /* since we explicitly forced the responder to win, it already removed ++ * the passive task it won't accept the request */ ++ ++ /* IKE_FOLLOWUP_KE { KEi, N(ADD_KE) } --> */ ++ assert_payload(IN, PLV2_KEY_EXCHANGE); ++ assert_notify(IN, ADDITIONAL_KEY_EXCHANGE); ++ exchange_test_helper->process_message(exchange_test_helper, b, NULL); ++ ++ /* ike_updown/rekey/child_updown */ ++ assert_hook(); ++ assert_hook(); ++ assert_hook(); ++ assert_track_sas(2, 2); ++ ++ charon->ike_sa_manager->flush(charon->ike_sa_manager); ++} ++END_TEST ++ + /** + * In this scenario one of the peers does not notice that there is a rekey + * collision because the other request is dropped: +@@ -2590,6 +2736,7 @@ Suite *ike_rekey_suite_create() + tcase_add_loop_test(tc, test_collision_ke_invalid_delayed_retry, 0, 3); + tcase_add_loop_test(tc, test_collision_delayed_response, 0, 4); + tcase_add_loop_test(tc, test_collision_delayed_response_multi_ke, 0, 4); ++ tcase_add_test(tc, test_collision_delayed_response_multi_ke_failure); + tcase_add_loop_test(tc, test_collision_dropped_request, 0, 3); + tcase_add_loop_test(tc, test_collision_delayed_request, 0, 3); + tcase_add_loop_test(tc, test_collision_delayed_request_and_delete, 0, 3); diff -Nru strongswan-6.0.1/debian/patches/0027-eap-ttls-peap-Return-auth-cfg-with-details-on-TLS-an.patch strongswan-6.0.1/debian/patches/0027-eap-ttls-peap-Return-auth-cfg-with-details-on-TLS-an.patch --- strongswan-6.0.1/debian/patches/0027-eap-ttls-peap-Return-auth-cfg-with-details-on-TLS-an.patch 1970-01-01 00:00:00.000000000 +0000 +++ strongswan-6.0.1/debian/patches/0027-eap-ttls-peap-Return-auth-cfg-with-details-on-TLS-an.patch 2026-09-01 11:29:28.000000000 +0000 @@ -0,0 +1,703 @@ +From: Tobias Brunner +Date: Mon, 27 Jul 2026 15:05:45 +0200 +Subject: 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 +++++++++++++- + src/libcharon/plugins/eap_peap/eap_peap_peer.c | 20 ++++++ + src/libcharon/plugins/eap_peap/eap_peap_peer.h | 7 ++ + src/libcharon/plugins/eap_peap/eap_peap_server.c | 81 +++++++++++++++++++++--- + src/libcharon/plugins/eap_peap/eap_peap_server.h | 7 ++ + src/libcharon/plugins/eap_ttls/eap_ttls.c | 43 ++++++++++++- + src/libcharon/plugins/eap_ttls/eap_ttls_peer.c | 19 ++++++ + src/libcharon/plugins/eap_ttls/eap_ttls_peer.h | 7 ++ + src/libcharon/plugins/eap_ttls/eap_ttls_server.c | 56 ++++++++++++++-- + src/libcharon/plugins/eap_ttls/eap_ttls_server.h | 7 ++ + 10 files changed, 278 insertions(+), 18 deletions(-) + +diff --git a/src/libcharon/plugins/eap_peap/eap_peap.c b/src/libcharon/plugins/eap_peap/eap_peap.c +index 3573cba..cd942f1 100644 +--- 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_create_empty(void) + .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_create_empty(void) + /** + * 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(private_eap_peap_t * this, + 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)) +diff --git a/src/libcharon/plugins/eap_peap/eap_peap_peer.c b/src/libcharon/plugins/eap_peap/eap_peap_peer.c +index 95213a3..f6c087a 100644 +--- a/src/libcharon/plugins/eap_peap/eap_peap_peer.c ++++ b/src/libcharon/plugins/eap_peap/eap_peap_peer.c +@@ -52,6 +52,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 + */ +@@ -166,6 +171,12 @@ METHOD(tls_application_t, process, status_t, + 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_t, + 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(identification_t *server, + .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), + ); + +diff --git a/src/libcharon/plugins/eap_peap/eap_peap_peer.h b/src/libcharon/plugins/eap_peap/eap_peap_peer.h +index 53c25cd..7d16957 100644 +--- 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); + }; + + /** +diff --git a/src/libcharon/plugins/eap_peap/eap_peap_server.c b/src/libcharon/plugins/eap_peap/eap_peap_server.c +index 29ab9b4..388c3c6 100644 +--- 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 + #include + ++#include ++ + typedef struct private_eap_peap_server_t private_eap_peap_server_t; + + /** +@@ -77,6 +79,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 + */ +@@ -132,8 +144,11 @@ static status_t start_phase2_auth(private_eap_peap_server_t *this) + /** + * 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)) + { +@@ -145,6 +160,8 @@ static status_t start_phase2_tnc(private_eap_peap_server_t *this) + 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 */ +@@ -218,9 +235,13 @@ METHOD(tls_application_t, process, status_t, + 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) +@@ -245,6 +266,10 @@ METHOD(tls_application_t, process, status_t, + 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) + { +@@ -271,9 +296,22 @@ METHOD(tls_application_t, process, status_t, + + 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); +@@ -281,10 +319,9 @@ METHOD(tls_application_t, process, status_t, + 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 + { +@@ -305,11 +342,26 @@ METHOD(tls_application_t, process, status_t, + 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; +@@ -407,11 +459,18 @@ METHOD(eap_peap_server_t, set_tls, void, + this->tls = tls; + } + ++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); +@@ -435,10 +494,12 @@ eap_peap_server_t *eap_peap_server_create(identification_t *server, + .destroy = _destroy, + }, + .set_tls = _set_tls, ++ .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, +diff --git a/src/libcharon/plugins/eap_peap/eap_peap_server.h b/src/libcharon/plugins/eap_peap/eap_peap_server.h +index 3abe88b..8080e9f 100644 +--- a/src/libcharon/plugins/eap_peap/eap_peap_server.h ++++ b/src/libcharon/plugins/eap_peap/eap_peap_server.h +@@ -47,6 +47,13 @@ struct eap_peap_server_t { + * @param tls TLS connection + */ + void (*set_tls)(eap_peap_server_t *this, tls_t *tls); ++ ++ /** ++ * 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); + }; + + /** +diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls.c b/src/libcharon/plugins/eap_ttls/eap_ttls.c +index d8ad781..3df78bb 100644 +--- 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(identification_t *server, + .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, +diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c +index 63126a5..f8229f5 100644 +--- a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c ++++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c +@@ -54,6 +54,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 + */ +@@ -215,6 +220,11 @@ METHOD(tls_application_t, process, status_t, + 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 */ +@@ -275,11 +285,18 @@ METHOD(tls_application_t, build, status_t, + 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); +@@ -301,10 +318,12 @@ eap_ttls_peer_t *eap_ttls_peer_create(identification_t *server, + .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(), + ); + +diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.h b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.h +index 0c3d90a..69a8435 100644 +--- 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); + }; + + /** +diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c +index fc97f81..e1de1bf 100644 +--- a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c ++++ b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c +@@ -60,6 +60,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 + */ +@@ -220,6 +225,10 @@ METHOD(tls_application_t, process, status_t, + 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, status_t, + + 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, status_t, + 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, status_t, + 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_t, + 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_create(identification_t *server, + .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(), + ); + +diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_server.h b/src/libcharon/plugins/eap_ttls/eap_ttls_server.h +index 1e13f55..3348706 100644 +--- 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-6.0.1/debian/patches/0028-ikev2-Properly-reject-CREATE_CHILD_SA-requests-on-un.patch strongswan-6.0.1/debian/patches/0028-ikev2-Properly-reject-CREATE_CHILD_SA-requests-on-un.patch --- strongswan-6.0.1/debian/patches/0028-ikev2-Properly-reject-CREATE_CHILD_SA-requests-on-un.patch 1970-01-01 00:00:00.000000000 +0000 +++ strongswan-6.0.1/debian/patches/0028-ikev2-Properly-reject-CREATE_CHILD_SA-requests-on-un.patch 2026-09-01 11:29:28.000000000 +0000 @@ -0,0 +1,66 @@ +From: Tobias Brunner +Date: Mon, 27 Jul 2026 08:53:50 +0200 +Subject: 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(-) + +diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c +index 85aaa24..845fb9f 100644 +--- a/src/libcharon/sa/ikev2/task_manager_v2.c ++++ b/src/libcharon/sa/ikev2/task_manager_v2.c +@@ -1134,9 +1134,18 @@ static status_t process_request(private_task_manager_t *this, + 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: +@@ -1177,14 +1186,6 @@ static status_t process_request(private_task_manager_t *this, + { /* 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-6.0.1/debian/patches/series strongswan-6.0.1/debian/patches/series --- strongswan-6.0.1/debian/patches/series 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/patches/series 2026-09-01 11:29:28.000000000 +0000 @@ -15,3 +15,14 @@ 0015-constraints-Case-insensitive-matching-and-reject-exc.patch 0016-gmp-Avoid-crash-and-timing-leaks-in-PKCS-1-v1.5-decr.patch 0017-identification-Fix-double-free-when-cloning-empty-ID.patch +0018-openssl-Fix-undefined-memory-access-when-verifying-P.patch +0019-openssl-Fix-memory-leaks-after-enumerating-certifica.patch +0020-eap-aka-Only-accept-AKA-Synchronization-Failure-if-e.patch +0021-message-Avoid-memory-leak-if-string-buffer-for-messa.patch +0022-pkcs5-Validate-parsed-parameters-to-avoid-DoS-attack.patch +0023-x509-Avoid-NULL-pointer-dereference-if-issuerName-is.patch +0024-x509-Fix-memory-leaks-when-parsing-attribute-certifi.patch +0025-x509-Prevent-infinite-loop-when-parsing-ietfAttrSynt.patch +0026-ikev2-Prevent-use-after-free-during-collision-after-.patch +0027-eap-ttls-peap-Return-auth-cfg-with-details-on-TLS-an.patch +0028-ikev2-Properly-reject-CREATE_CHILD_SA-requests-on-un.patch diff -Nru strongswan-6.0.1/debian/po/ca.po strongswan-6.0.1/debian/po/ca.po --- strongswan-6.0.1/debian/po/ca.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/ca.po 2026-09-01 11:29:28.000000000 +0000 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: strongswan\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2025-01-30 07:33+0100\n" "Last-Translator: poc senderi \n" "Language-Team: Catalan \n" diff -Nru strongswan-6.0.1/debian/po/cs.po strongswan-6.0.1/debian/po/cs.po --- strongswan-6.0.1/debian/po/cs.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/cs.po 2026-09-01 11:29:28.000000000 +0000 @@ -13,7 +13,7 @@ msgstr "" "Project-Id-Version: strongswan\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2013-10-28 14:42+0100\n" "Last-Translator: Miroslav Kure \n" "Language-Team: Czech \n" diff -Nru strongswan-6.0.1/debian/po/da.po strongswan-6.0.1/debian/po/da.po --- strongswan-6.0.1/debian/po/da.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/da.po 2026-09-01 11:29:28.000000000 +0000 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: strongswan\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2013-10-06 12:42+0000\n" "Last-Translator: Joe Hansen \n" "Language-Team: Danish \n" diff -Nru strongswan-6.0.1/debian/po/de.po strongswan-6.0.1/debian/po/de.po --- strongswan-6.0.1/debian/po/de.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/de.po 2026-09-01 11:29:28.000000000 +0000 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: strongswan 4.4.0-1\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2013-11-02 15:40+0100\n" "Last-Translator: Helge Kreutzmann \n" "Language-Team: German \n" diff -Nru strongswan-6.0.1/debian/po/es.po strongswan-6.0.1/debian/po/es.po --- strongswan-6.0.1/debian/po/es.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/es.po 2026-09-01 11:29:28.000000000 +0000 @@ -31,7 +31,7 @@ msgstr "" "Project-Id-Version: strongswan 4.4.1-5\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2013-12-17 17:19-0300\n" "Last-Translator: Matías Bellone \n" "Language-Team: Debian l10n Spanish \n" diff -Nru strongswan-6.0.1/debian/po/eu.po strongswan-6.0.1/debian/po/eu.po --- strongswan-6.0.1/debian/po/eu.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/eu.po 2026-09-01 11:29:28.000000000 +0000 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: strongswan_4.4.1-5.1_eu\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2013-10-15 21:41+0200\n" "Last-Translator: Iñaki Larrañaga Murgoitio \n" "Language-Team: Basque \n" diff -Nru strongswan-6.0.1/debian/po/fi.po strongswan-6.0.1/debian/po/fi.po --- strongswan-6.0.1/debian/po/fi.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/fi.po 2026-09-01 11:29:28.000000000 +0000 @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: strongswan\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2009-05-25 14:49+0100\n" "Last-Translator: Esko Arajärvi \n" "Language-Team: Finnish \n" diff -Nru strongswan-6.0.1/debian/po/fr.po strongswan-6.0.1/debian/po/fr.po --- strongswan-6.0.1/debian/po/fr.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/fr.po 2026-09-01 11:29:28.000000000 +0000 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: strongswan\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2010-06-24 22:17+0200\n" "Last-Translator: Christian Perrier \n" "Language-Team: French \n" diff -Nru strongswan-6.0.1/debian/po/gl.po strongswan-6.0.1/debian/po/gl.po --- strongswan-6.0.1/debian/po/gl.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/gl.po 2026-09-01 11:29:28.000000000 +0000 @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: templates_[kI6655]\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2009-05-25 14:50+0100\n" "Last-Translator: marce villarino \n" "Language-Team: Galician \n" diff -Nru strongswan-6.0.1/debian/po/it.po strongswan-6.0.1/debian/po/it.po --- strongswan-6.0.1/debian/po/it.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/it.po 2026-09-01 11:29:28.000000000 +0000 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: strongswan\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2013-11-09 13:41+0200\n" "Last-Translator: Beatrice Torracca \n" "Language-Team: Italian \n" diff -Nru strongswan-6.0.1/debian/po/ja.po strongswan-6.0.1/debian/po/ja.po --- strongswan-6.0.1/debian/po/ja.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/ja.po 2026-09-01 11:29:28.000000000 +0000 @@ -16,7 +16,7 @@ msgstr "" "Project-Id-Version: strongswan 4.4.1-4\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2013-02-07 21:28+0900\n" "Last-Translator: Hideki Yamane \n" "Language-Team: Japanese \n" diff -Nru strongswan-6.0.1/debian/po/nb.po strongswan-6.0.1/debian/po/nb.po --- strongswan-6.0.1/debian/po/nb.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/nb.po 2026-09-01 11:29:28.000000000 +0000 @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: nb\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2013-10-06 17:37+0200\n" "Last-Translator: Bjørn Steensrud \n" "Language-Team: Norwegian Bokmål \n" diff -Nru strongswan-6.0.1/debian/po/nl.po strongswan-6.0.1/debian/po/nl.po --- strongswan-6.0.1/debian/po/nl.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/nl.po 2026-09-01 11:29:28.000000000 +0000 @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: strongswan 4.5.0-1\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2014-09-24 18:39+0200\n" "Last-Translator: Frans Spiesschaert \n" "Language-Team: Debian Dutch l10n Team \n" diff -Nru strongswan-6.0.1/debian/po/pl.po strongswan-6.0.1/debian/po/pl.po --- strongswan-6.0.1/debian/po/pl.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/pl.po 2026-09-01 11:29:28.000000000 +0000 @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2012-01-31 15:36+0100\n" "Last-Translator: Michał Kułach \n" "Language-Team: Polish \n" diff -Nru strongswan-6.0.1/debian/po/pt.po strongswan-6.0.1/debian/po/pt.po --- strongswan-6.0.1/debian/po/pt.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/pt.po 2026-09-01 11:29:28.000000000 +0000 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: strongswan 5.1.0-3\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2013-11-18 00:33+0000\n" "Last-Translator: Américo Monteiro \n" "Language-Team: Portuguese \n" diff -Nru strongswan-6.0.1/debian/po/pt_BR.po strongswan-6.0.1/debian/po/pt_BR.po --- strongswan-6.0.1/debian/po/pt_BR.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/pt_BR.po 2026-09-01 11:29:28.000000000 +0000 @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: strongswan 5.1.3-4\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2014-06-25 18:13-0300\n" "Last-Translator: Adriano Rafael Gomes \n" "Language-Team: Brazilian Portuguese \n" "Language-Team: Russian \n" diff -Nru strongswan-6.0.1/debian/po/sv.po strongswan-6.0.1/debian/po/sv.po --- strongswan-6.0.1/debian/po/sv.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/sv.po 2026-09-01 11:29:28.000000000 +0000 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: strongswan_sv\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2013-10-07 09:05+0100\n" "Last-Translator: Martin Bagge / brother \n" "Language-Team: Swedish \n" diff -Nru strongswan-6.0.1/debian/po/templates.pot strongswan-6.0.1/debian/po/templates.pot --- strongswan-6.0.1/debian/po/templates.pot 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/templates.pot 2026-09-01 11:29:28.000000000 +0000 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: strongswan\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff -Nru strongswan-6.0.1/debian/po/tr.po strongswan-6.0.1/debian/po/tr.po --- strongswan-6.0.1/debian/po/tr.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/tr.po 2026-09-01 11:29:28.000000000 +0000 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: strongswan\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2013-10-24 11:17+0200\n" "Last-Translator: Atila KOÇ \n" "Language-Team: Türkçe \n" diff -Nru strongswan-6.0.1/debian/po/vi.po strongswan-6.0.1/debian/po/vi.po --- strongswan-6.0.1/debian/po/vi.po 2026-05-27 06:40:18.000000000 +0000 +++ strongswan-6.0.1/debian/po/vi.po 2026-09-01 11:29:28.000000000 +0000 @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: strongswan 4.4.0-1\n" "Report-Msgid-Bugs-To: strongswan@packages.debian.org\n" -"POT-Creation-Date: 2026-05-27 08:41+0200\n" +"POT-Creation-Date: 2026-09-01 13:29+0200\n" "PO-Revision-Date: 2010-10-03 19:22+1030\n" "Last-Translator: Clytie Siddall \n" "Language-Team: Vietnamese \n"