From 60c36bc85859a5c7e8f286640c53d93234bff9cf Mon Sep 17 00:00:00 2001 From: eabdullin Date: Wed, 19 Mar 2025 14:44:46 +0300 Subject: [PATCH] import OL --- .gitignore | 2 +- .libreswan.metadata | 2 +- ...an-4.12-ikev1-compute-keymat-default.patch | 92 --- ...breswan-4.12-ikev2-auth-delete-state.patch | 54 -- SOURCES/libreswan-4.12-ipv6-san.patch | 198 ------ ...-4.15-create-child-sa-race-condition.patch | 57 ++ SOURCES/libreswan-4.15-netlink-extack.patch | 153 +++++ SOURCES/libreswan-4.15-ondemand-tcp.patch | 52 ++ SOURCES/libreswan-4.15-rereadsecrets.patch | 594 ++++++++++++++++++ SOURCES/libreswan-oracle.patch | 24 + SPECS/libreswan.spec | 40 +- 11 files changed, 916 insertions(+), 352 deletions(-) delete mode 100644 SOURCES/libreswan-4.12-ikev1-compute-keymat-default.patch delete mode 100644 SOURCES/libreswan-4.12-ikev2-auth-delete-state.patch delete mode 100644 SOURCES/libreswan-4.12-ipv6-san.patch create mode 100644 SOURCES/libreswan-4.15-create-child-sa-race-condition.patch create mode 100644 SOURCES/libreswan-4.15-netlink-extack.patch create mode 100644 SOURCES/libreswan-4.15-ondemand-tcp.patch create mode 100644 SOURCES/libreswan-4.15-rereadsecrets.patch create mode 100644 SOURCES/libreswan-oracle.patch diff --git a/.gitignore b/.gitignore index 13bd332..2b9b5b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ SOURCES/ikev1_dsa.fax.bz2 SOURCES/ikev1_psk.fax.bz2 SOURCES/ikev2.fax.bz2 -SOURCES/libreswan-4.12.tar.gz +SOURCES/libreswan-4.15.tar.gz diff --git a/.libreswan.metadata b/.libreswan.metadata index 0dc2bf4..199f4d2 100644 --- a/.libreswan.metadata +++ b/.libreswan.metadata @@ -1,4 +1,4 @@ b35cd50b8bc0a08b9c07713bf19c72d53bfe66bb SOURCES/ikev1_dsa.fax.bz2 861d97bf488f9e296cad8c43ab72f111a5b1a848 SOURCES/ikev1_psk.fax.bz2 fcaf77f3deae3d8e99cdb3b1f8abea63167a0633 SOURCES/ikev2.fax.bz2 -786c14a4755311ea3103683a3294e1536b1e44a6 SOURCES/libreswan-4.12.tar.gz +861eaeefff1c2f3862a8bfe0295b3e307f8e3055 SOURCES/libreswan-4.15.tar.gz diff --git a/SOURCES/libreswan-4.12-ikev1-compute-keymat-default.patch b/SOURCES/libreswan-4.12-ikev1-compute-keymat-default.patch deleted file mode 100644 index 7f283f0..0000000 --- a/SOURCES/libreswan-4.12-ikev1-compute-keymat-default.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 5101913b1e623121a9222f11eefa18f0a2708b00 Mon Sep 17 00:00:00 2001 -From: Andrew Cagney -Date: Wed, 27 Mar 2024 10:43:19 -0400 -Subject: [PATCH] ikev1: in compute_proto_keymat() only allow explicitly - handled ESP algorithms - ---- - programs/pluto/ikev1_quick.c | 41 ++++++++++++++---------------------- - 1 file changed, 16 insertions(+), 25 deletions(-) - -diff --git a/programs/pluto/ikev1_quick.c b/programs/pluto/ikev1_quick.c -index 81c522c148..22c346afb4 100644 ---- a/programs/pluto/ikev1_quick.c -+++ b/programs/pluto/ikev1_quick.c -@@ -203,7 +203,7 @@ static bool emit_subnet_id(enum perspective perspective, - * RFC 2409 "IKE" section 5.5 - * specifies how this is to be done. - */ --static void compute_proto_keymat(struct state *st, -+static bool compute_proto_keymat(struct state *st, - uint8_t protoid, - struct ipsec_proto_info *pi, - const char *satypename) -@@ -297,27 +297,13 @@ static void compute_proto_keymat(struct state *st, - } - break; - -- case ESP_CAST: -- case ESP_TWOFISH: -- case ESP_SERPENT: -- /* ESP_SEED is for IKEv1 only and not supported. Its number in IKEv2 has been re-used */ -- bad_case(pi->attrs.transattrs.ta_ikev1_encrypt); -- - default: -- /* bytes */ -- needed_len = encrypt_max_key_bit_length(pi->attrs.transattrs.ta_encrypt) / BITS_PER_BYTE; -- if (needed_len > 0) { -- /* XXX: check key_len coupling with kernel.c's */ -- if (pi->attrs.transattrs.enckeylen) { -- needed_len = -- pi->attrs.transattrs.enckeylen -- / BITS_PER_BYTE; -- dbg("compute_proto_keymat: key_len=%d from peer", -- (int)needed_len); -- } -- break; -- } -- bad_case(pi->attrs.transattrs.ta_ikev1_encrypt); -+ { -+ enum_buf eb; -+ llog(RC_LOG, st->st_logger, "rejecting request for keymat for %s", -+ str_enum(&esp_transformid_names, protoid, &eb)); -+ return false; -+ } - } - dbg("compute_proto_keymat: needed_len (after ESP enc)=%d", (int)needed_len); - needed_len += pi->attrs.transattrs.ta_integ->integ_keymat_size; -@@ -359,14 +345,17 @@ static void compute_proto_keymat(struct state *st, - DBG_dump_hunk(" inbound:", pi->inbound.keymat); - DBG_dump_hunk(" outbound:", pi->outbound.keymat); - } -+ -+ return true; - } - --static void compute_keymats(struct state *st) -+static bool compute_keymats(struct state *st) - { - if (st->st_ah.present) -- compute_proto_keymat(st, PROTO_IPSEC_AH, &st->st_ah, "AH"); -+ return compute_proto_keymat(st, PROTO_IPSEC_AH, &st->st_ah, "AH"); - if (st->st_esp.present) -- compute_proto_keymat(st, PROTO_IPSEC_ESP, &st->st_esp, "ESP"); -+ return compute_proto_keymat(st, PROTO_IPSEC_ESP, &st->st_esp, "ESP"); -+ return false; - } - - /* -@@ -1460,7 +1449,9 @@ static stf_status quick_inI1_outR1_continue12_tail(struct state *st, struct msg_ - fixup_v1_HASH(st, &hash_fixup, st->st_v1_msgid.id, rbody.cur); - - /* Derive new keying material */ -- compute_keymats(st); -+ if (!compute_keymats(st)) { -+ return STF_FATAL; -+ } - - /* Tell the kernel to establish the new inbound SA - * (unless the commit bit is set -- which we don't support). --- -2.45.0 - diff --git a/SOURCES/libreswan-4.12-ikev2-auth-delete-state.patch b/SOURCES/libreswan-4.12-ikev2-auth-delete-state.patch deleted file mode 100644 index c17b457..0000000 --- a/SOURCES/libreswan-4.12-ikev2-auth-delete-state.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 2ec448884a7467743699803f8a36ee28d237666c Mon Sep 17 00:00:00 2001 -From: Andrew Cagney -Date: Wed, 28 Feb 2024 08:29:53 -0500 -Subject: [PATCH] ikev2: return STF_FATAL when initiator fails to emit AUTH - packet - ---- - programs/pluto/ikev2_ike_auth.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/programs/pluto/ikev2_ike_auth.c b/programs/pluto/ikev2_ike_auth.c -index 192eb1b3b6..a54a109699 100644 ---- a/programs/pluto/ikev2_ike_auth.c -+++ b/programs/pluto/ikev2_ike_auth.c -@@ -1267,7 +1267,7 @@ static stf_status process_v2_IKE_AUTH_request_auth_signature_continue(struct ike - /* now send AUTH payload */ - - if (!emit_local_v2AUTH(ike, auth_sig, &ike->sa.st_v2_id_payload.mac, response.pbs)) { -- return STF_INTERNAL_ERROR; -+ return STF_FATAL; - } - ike->sa.st_v2_ike_intermediate.used = false; - --- -2.44.0 - -From 16272f2475d25baab58fbed2af7c67cfb459137f Mon Sep 17 00:00:00 2001 -From: Andrew Cagney -Date: Thu, 29 Feb 2024 12:19:20 -0500 -Subject: [PATCH] ikev2: always return STF_FATAL if emitting AUTH fails - -Fix: - ikev2: return STF_FATAL when initiator fails to emit AUTH packet -which really fixed the responder. ---- - programs/pluto/ikev2_ike_auth.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/programs/pluto/ikev2_ike_auth.c b/programs/pluto/ikev2_ike_auth.c -index a54a109699..491053fb10 100644 ---- a/programs/pluto/ikev2_ike_auth.c -+++ b/programs/pluto/ikev2_ike_auth.c -@@ -397,7 +397,7 @@ stf_status initiate_v2_IKE_AUTH_request_signature_continue(struct ike_sa *ike, - /* send out the AUTH payload */ - - if (!emit_local_v2AUTH(ike, auth_sig, &ike->sa.st_v2_id_payload.mac, request.pbs)) { -- return STF_INTERNAL_ERROR; -+ return STF_FATAL; - } - - if (LIN(POLICY_MOBIKE, ike->sa.st_connection->policy)) { --- -2.44.0 - diff --git a/SOURCES/libreswan-4.12-ipv6-san.patch b/SOURCES/libreswan-4.12-ipv6-san.patch deleted file mode 100644 index 6eb0b58..0000000 --- a/SOURCES/libreswan-4.12-ipv6-san.patch +++ /dev/null @@ -1,198 +0,0 @@ -From 474d75be074799efa9e38f346d3fdb76dec3eead Mon Sep 17 00:00:00 2001 -From: Andrew Cagney -Date: Tue, 5 Dec 2023 13:55:37 -0500 -Subject: [PATCH] x509: unpack IPv6 general names based on length - -fix #1321 ---- - programs/pluto/x509.c | 35 +++++++++++++++++++++++++++++------ - 1 file changed, 29 insertions(+), 6 deletions(-) - -diff --git a/programs/pluto/x509.c b/programs/pluto/x509.c -index fbbf5a553e..f7e97b9979 100644 ---- a/programs/pluto/x509.c -+++ b/programs/pluto/x509.c -@@ -336,7 +336,7 @@ generalName_t *collect_rw_ca_candidates(struct msg_digest *md) - */ - static void gntoid(struct id *id, const generalName_t *gn, struct logger *logger) - { -- *id = empty_id; -+ *id = empty_id; /* aka ID_NONE */ - - switch (gn->kind) { - case GN_DNS_NAME: /* ID type: ID_FQDN */ -@@ -345,18 +345,37 @@ static void gntoid(struct id *id, const generalName_t *gn, struct logger *logger - break; - case GN_IP_ADDRESS: /* ID type: ID_IPV4_ADDR */ - { -+ const struct ip_info *afi = NULL; -+ for (enum ip_index i = 0; i < IP_INDEX_ROOF; i++) { -+ if (ip_families[i].ip_size == gn->name.len) { -+ afi = &ip_families[i]; -+ break; -+ } -+ } -+ if (afi == NULL) { -+ llog(RC_LOG, logger, -+ "warning: invalid IP_ADDRESS general name: %zu byte length is not valid", -+ gn->name.len); -+ PEXPECT(logger, id->kind == ID_NONE); -+ return; -+ } -+ - /* - * XXX: why could this fail; and what happens when it - * is ignored? - */ -- const struct ip_info *afi = &ipv4_info; -- id->kind = afi->id_ip_addr; -- err_t ugh = hunk_to_address(gn->name, afi, &id->ip_addr); -+ ip_address addr; -+ err_t ugh = hunk_to_address(gn->name, afi, &addr); - if (ugh != NULL) { - llog(RC_LOG, logger, -- "warning: gntoid() failed to initaddr(): %s", -- ugh); -+ "warning: invalid IP_ADDRESS general name: %s", -+ ugh); -+ PEXPECT(logger, id->kind == ID_NONE); -+ return; - } -+ -+ id->kind = afi->id_ip_addr; -+ id->ip_addr = addr; - break; - } - case GN_RFC822_NAME: /* ID type: ID_USER_FQDN */ -@@ -464,14 +483,18 @@ bool add_pubkey_from_nss_cert(struct pubkey_list **pubkey_db, - return false; - } - -+ ldbg(logger, "adding cert using subject name"); - replace_public_key(pubkey_db, &pk); - passert(pk == NULL); /*stolen*/ - -+ ldbg(logger, "adding cert using general names"); - add_cert_san_pubkeys(pubkey_db, cert, logger); - - if (keyid != NULL && keyid->kind != ID_DER_ASN1_DN && - keyid->kind != ID_NONE && - keyid->kind != ID_FROMCERT) { -+ id_buf idb; -+ ldbg(logger, "adding cert using keyid %s", str_id(keyid, &idb)); - struct pubkey *pk2 = NULL; - diag_t d = create_pubkey_from_cert(keyid, cert, &pk2, logger); - if (d != NULL) { --- -2.44.0 - -From 1e27be95cd710a840681d1a51913e6a32ce75a2a Mon Sep 17 00:00:00 2001 -From: Andrew Cagney -Date: Mon, 11 Mar 2024 17:18:51 -0400 -Subject: [PATCH] building: back-port ip_families[] and ip_index - ---- - include/ip_index.h | 27 +++++++++++++++++++++++++++ - include/ip_info.h | 7 +++++-- - lib/libswan/ip_info.c | 9 ++++++--- - 3 files changed, 38 insertions(+), 5 deletions(-) - create mode 100644 include/ip_index.h - -diff --git a/include/ip_index.h b/include/ip_index.h -new file mode 100644 -index 0000000000..508589b05e ---- /dev/null -+++ b/include/ip_index.h -@@ -0,0 +1,27 @@ -+/* ip address type index, for libreswan -+ * -+ * Copyright (C) 2022 Andrew Cagney -+ * -+ * This library is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU Library General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This library is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -+ * License for more details. -+ * -+ */ -+ -+#ifndef IP_INDEX_H -+#define IP_INDEX_H -+ -+enum ip_index { -+ IPv4_INDEX, -+ IPv6_INDEX, -+}; -+ -+#define IP_INDEX_ROOF (IPv6_INDEX+1) -+ -+#endif -diff --git a/include/ip_info.h b/include/ip_info.h -index 40e99ef687..c1329a8569 100644 ---- a/include/ip_info.h -+++ b/include/ip_info.h -@@ -9,6 +9,7 @@ - #include "ip_subnet.h" - #include "ip_selector.h" - #include "ip_sockaddr.h" -+#include "ip_index.h" - - struct ip_info { - /* -@@ -113,8 +114,10 @@ struct ip_info { - - }; - --extern const struct ip_info ipv4_info; --extern const struct ip_info ipv6_info; -+extern const struct ip_info ip_families[IP_INDEX_ROOF]; -+ -+#define ipv4_info ip_families[IPv4_INDEX] -+#define ipv6_info ip_families[IPv6_INDEX] - - extern const struct ip_info *aftoinfo(int af); - -diff --git a/lib/libswan/ip_info.c b/lib/libswan/ip_info.c -index 70cd6a368f..97296d3a11 100644 ---- a/lib/libswan/ip_info.c -+++ b/lib/libswan/ip_info.c -@@ -158,7 +158,9 @@ static ip_port port_from_ipv6_sockaddr(const ip_sockaddr sa) - - #define IPv4_FF { { 255, 255, 255, 255, }, } - --const struct ip_info ipv4_info = { -+const struct ip_info ip_families[IP_INDEX_ROOF] = { -+ -+ [IPv4_INDEX] = { - - .ip_version = IPv4, - .ip_size = sizeof(struct in_addr), -@@ -210,11 +212,11 @@ const struct ip_info ipv4_info = { - .id_ip_addr = ID_IPV4_ADDR, - .id_ip_addr_subnet = ID_IPV4_ADDR_SUBNET, - .id_ip_addr_range = ID_IPV4_ADDR_RANGE, --}; -+ }, - - #define IPv6_FF { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, } - --const struct ip_info ipv6_info = { -+ [IPv6_INDEX] = { - - .ip_version = IPv6, - .ip_size = sizeof(struct in6_addr), -@@ -266,6 +268,7 @@ const struct ip_info ipv6_info = { - .id_ip_addr = ID_IPV6_ADDR, - .id_ip_addr_subnet = ID_IPV6_ADDR_SUBNET, - .id_ip_addr_range = ID_IPV6_ADDR_RANGE, -+ } - }; - - const struct ip_info *aftoinfo(int af) --- -2.44.0 - diff --git a/SOURCES/libreswan-4.15-create-child-sa-race-condition.patch b/SOURCES/libreswan-4.15-create-child-sa-race-condition.patch new file mode 100644 index 0000000..99f7e3e --- /dev/null +++ b/SOURCES/libreswan-4.15-create-child-sa-race-condition.patch @@ -0,0 +1,57 @@ +From d0a468bc4ca54b3aa941f522afd4ef8ed279e3cd Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Tue, 22 Oct 2024 07:53:20 +0900 +Subject: [PATCH] pluto: ignore CREATE_CHILD_SA request if crypto is in + progress + +Since commit 1f4cede653c865d84ea4dd045db05670d513d385, both initiator +and responder drive CREATE_CHILD_SA processing with the same shared +IKE SA, which may sometimes interleave. This adds a guard at the +entry to the responder code, to return STF_IGNORE in case any CRYPTO +continuation is already in place, so that the initiator could +retransmit after a timeout on their side. + +Signed-off-by: Daiki Ueno +--- + programs/pluto/ikev2_create_child_sa.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/programs/pluto/ikev2_create_child_sa.c b/programs/pluto/ikev2_create_child_sa.c +index 951485d063..504fc58a6b 100644 +--- a/programs/pluto/ikev2_create_child_sa.c ++++ b/programs/pluto/ikev2_create_child_sa.c +@@ -662,6 +662,15 @@ stf_status process_v2_CREATE_CHILD_SA_rekey_child_request(struct ike_sa *ike, + struct child_sa *larval_child, + struct msg_digest *md) + { ++ /* ++ * CRYPTO continuation is ongoing as the same IKE SA is shared ++ * between initiator and responder, ignore it for now and let ++ * the initiator retransmit. ++ */ ++ if (verbose_state_busy(&ike->sa)) { ++ return STF_IGNORE; ++ } ++ + struct child_sa *predecessor = NULL; + if (!find_v2N_REKEY_SA_child(ike, md, &predecessor)) { + record_v2N_response(ike->sa.st_logger, ike, md, v2N_INVALID_SYNTAX, +@@ -870,6 +879,15 @@ stf_status process_v2_CREATE_CHILD_SA_new_child_request(struct ike_sa *ike, + struct child_sa *larval_child, + struct msg_digest *md) + { ++ /* ++ * CRYPTO continuation is ongoing as the same IKE SA is shared ++ * between initiator and responder, ignore it for now and let ++ * the initiator retransmit. ++ */ ++ if (verbose_state_busy(&ike->sa)) { ++ return STF_IGNORE; ++ } ++ + pexpect(larval_child == NULL); + larval_child = new_v2_child_state(ike->sa.st_connection, + ike, IPSEC_SA, SA_RESPONDER, +-- +2.47.0 + diff --git a/SOURCES/libreswan-4.15-netlink-extack.patch b/SOURCES/libreswan-4.15-netlink-extack.patch new file mode 100644 index 0000000..92cf5e7 --- /dev/null +++ b/SOURCES/libreswan-4.15-netlink-extack.patch @@ -0,0 +1,153 @@ +From 4f2af7c8c3afaaa63e8e16467de3441622a5314d Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Tue, 21 May 2024 20:12:17 +0900 +Subject: [PATCH] kernel_xfrm: record extended ack from netlink response + +This enables pluto to log any error message reported through extended +ACK attributes[1] in a netlink response, to make diagnostic easier +when an error occurs. Suggested by Sabrina Dubroca. + +1. https://docs.kernel.org/userspace-api/netlink/intro.html#ext-ack + +Signed-off-by: Daiki Ueno +Signed-off-by: Andrew Cagney +--- + include/netlink_attrib.h | 4 +++ + lib/libswan/netlink_attrib.c | 29 +++++++++++++++++++++ + programs/pluto/kernel_xfrm.c | 49 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 82 insertions(+) + +diff --git a/include/netlink_attrib.h b/include/netlink_attrib.h +index 4c952ae3e9..fff35d83f1 100644 +--- a/include/netlink_attrib.h ++++ b/include/netlink_attrib.h +@@ -46,4 +46,8 @@ void nl_addattrstrz(struct nlmsghdr *n, int maxlen, int type, + const char *str); + void nl_addattr32(struct nlmsghdr *n, int maxlen, int type, const uint32_t data); + ++const struct nlattr *nl_getattr(const struct nlmsghdr *n, size_t *offset); ++const char *nl_getattrvalstrz(const struct nlmsghdr *n, ++ const struct nlattr *attr); ++ + #endif +diff --git a/lib/libswan/netlink_attrib.c b/lib/libswan/netlink_attrib.c +index 34bb4bec83..ccc08cba8f 100644 +--- a/lib/libswan/netlink_attrib.c ++++ b/lib/libswan/netlink_attrib.c +@@ -66,3 +66,32 @@ void nl_addattr32(struct nlmsghdr *n, int maxlen, int type, const uint32_t data) + { + nl_addattr_l(n, maxlen, type, &data, sizeof(uint32_t)); + } ++ ++const struct nlattr *nl_getattr(const struct nlmsghdr *n, size_t *offset) ++{ ++ struct nlattr *attr = (void *)n + NLMSG_HDRLEN + NLMSG_ALIGN(*offset); ++ struct nlattr *tail = (void *)n + NLMSG_ALIGN(n->nlmsg_len); ++ ++ if (attr == tail) { ++ return NULL; ++ } ++ ++ *offset += NLA_ALIGN(attr->nla_len); ++ return attr; ++} ++ ++const char *nl_getattrvalstrz(const struct nlmsghdr *n, ++ const struct nlattr *attr) ++{ ++ struct nlattr *tail = (void *)n + NLMSG_ALIGN(n->nlmsg_len); ++ ++ ptrdiff_t len = (void *)tail - (void *)attr; ++ if (len < (ptrdiff_t)sizeof(struct nlattr) || ++ attr->nla_len <= sizeof(struct nlattr) || ++ attr->nla_len > len || ++ !memchr(attr + NLA_HDRLEN, '\0', attr->nla_len - NLA_HDRLEN)) { ++ return NULL; ++ } ++ ++ return (void *)attr + NLA_HDRLEN; ++} +diff --git a/programs/pluto/kernel_xfrm.c b/programs/pluto/kernel_xfrm.c +index eed307f42b..25d1b16bc9 100644 +--- a/programs/pluto/kernel_xfrm.c ++++ b/programs/pluto/kernel_xfrm.c +@@ -260,6 +260,22 @@ static void init_netlink(struct logger *logger) + "socket() in init_netlink()"); + } + ++#ifdef SOL_NETLINK ++ const int on = true; ++ if (setsockopt(nl_send_fd, SOL_NETLINK, NETLINK_CAP_ACK, ++ (const void *)&on, sizeof(on)) < 0) { ++ llog_errno(RC_LOG, logger, errno, "xfrm: setsockopt(NETLINK_CAP_ACK) failed: "); ++ } else { ++ ldbg(logger, "xfrm: setsockopt(NETLINK_CAP_ACK) ok"); ++ } ++ if (setsockopt(nl_send_fd, SOL_NETLINK, NETLINK_EXT_ACK, ++ (const void *)&on, sizeof(on)) < 0) { ++ llog_errno(RC_LOG, logger, errno, "xfrm: setsockopt(NETLINK_EXT_ACK) failed: "); ++ } else { ++ ldbg(logger, "xfrm: setsockopt(NETLINK_EXT_ACK) ok"); ++ } ++#endif ++ + nl_xfrm_fd = cloexec_socket(AF_NETLINK, SOCK_DGRAM|SOCK_NONBLOCK, NETLINK_XFRM); + if (nl_xfrm_fd < 0) { + fatal_errno(PLUTO_EXIT_FAIL, logger, errno, +@@ -301,6 +317,37 @@ static void init_netlink(struct logger *logger) + } + } + ++static void llog_ext_ack(lset_t rc_flags, struct logger *logger, ++ const struct nlmsghdr *n) ++{ ++#ifdef SOL_NETLINK ++ if (n->nlmsg_type != NLMSG_ERROR || ++ !(n->nlmsg_flags & NLM_F_ACK_TLVS)) { ++ return; ++ } ++ ++ struct nlmsgerr *err = (void *)n + NLMSG_HDRLEN; ++ size_t offset = sizeof(*err); ++ if (!(n->nlmsg_flags & NLM_F_CAPPED)) { ++ offset += err->msg.nlmsg_len - NLMSG_HDRLEN; ++ } ++ ++ for (const struct nlattr *attr = nl_getattr(n, &offset); ++ attr != NULL; attr = nl_getattr(n, &offset)) { ++ if ((attr->nla_type & NLA_TYPE_MASK) == NLMSGERR_ATTR_MSG) { ++ const char *msg = nl_getattrvalstrz(n, attr); ++ if (msg) { ++ llog(rc_flags, logger, "netlink ext_ack: %s", ++ msg); ++ } ++ } ++ } ++#else ++ /* use the arguments */ ++ ldbg(logger, "ignoring "PRI_LSET" %p", rc_flags, n); ++#endif ++} ++ + /* + * sendrecv_xfrm_msg() + * +@@ -403,6 +450,7 @@ static bool sendrecv_xfrm_msg(struct nlmsghdr *hdr, + if (rsp.u.e.error != 0) { + llog_error(logger, -rsp.u.e.error, + "netlink response for %s %s", description, story); ++ llog_ext_ack(RC_LOG, logger, &rsp.n); + return false; + } + /* +@@ -413,6 +461,7 @@ static bool sendrecv_xfrm_msg(struct nlmsghdr *hdr, + */ + dbg("netlink response for %s %s included non-error error", + description, story); ++ llog_ext_ack(DEBUG_STREAM, logger, &rsp.n); + /* ignore */ + } + if (rbuf == NULL) { +-- +2.45.2 + diff --git a/SOURCES/libreswan-4.15-ondemand-tcp.patch b/SOURCES/libreswan-4.15-ondemand-tcp.patch new file mode 100644 index 0000000..11689a6 --- /dev/null +++ b/SOURCES/libreswan-4.15-ondemand-tcp.patch @@ -0,0 +1,52 @@ +From 0b91406427cf7292d61900991fd665f076b6d43f Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Tue, 2 Jul 2024 20:37:07 +0900 +Subject: [PATCH] tcp: call kernel_ops->poke_ipsec_policy_hole before connect + +This fixes ondemand initiation with TCP. Without the policy hole, a +TCP handshake will not complete, as it cannot receive SYN-ACK packet +in plaintext and thus connect blocks until timeout. + +Signed-off-by: Daiki Ueno +Signed-off-by: Andrew Cagney +--- + programs/pluto/iface_tcp.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/programs/pluto/iface_tcp.c b/programs/pluto/iface_tcp.c +index c63e8bfe4d..55fe639174 100644 +--- a/programs/pluto/iface_tcp.c ++++ b/programs/pluto/iface_tcp.c +@@ -473,6 +473,15 @@ struct iface_endpoint *connect_to_tcp_endpoint(struct iface_dev *local_dev, + return NULL; + } + ++ /* This needs to be called before connect, so TCP handshake ++ * (in plaintext) completes. */ ++ if (kernel_ops->poke_ipsec_policy_hole != NULL && ++ !kernel_ops->poke_ipsec_policy_hole(fd, afi, logger)) { ++ /* already logged */ ++ close(fd); ++ return NULL; ++ } ++ + /* + * Connect + * +@@ -551,13 +560,6 @@ struct iface_endpoint *connect_to_tcp_endpoint(struct iface_dev *local_dev, + } + } + +- if (kernel_ops->poke_ipsec_policy_hole != NULL && +- !kernel_ops->poke_ipsec_policy_hole(fd, afi, logger)) { +- /* already logged */ +- close(fd); +- return NULL; +- } +- + struct iface_endpoint *ifp = + alloc_iface_endpoint(fd, local_dev, &iketcp_iface_io, + /*esp_encapsulation_enabled*/true, +-- +2.45.2 + diff --git a/SOURCES/libreswan-4.15-rereadsecrets.patch b/SOURCES/libreswan-4.15-rereadsecrets.patch new file mode 100644 index 0000000..6808ad4 --- /dev/null +++ b/SOURCES/libreswan-4.15-rereadsecrets.patch @@ -0,0 +1,594 @@ +From 5d20ce318199d3d525c8503ffc3242a90117a944 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Sat, 23 Nov 2024 10:18:03 +0900 +Subject: [PATCH 1/2] secrets: allocate secret_pubkey_stuff separately from + heap + +Signed-off-by: Daiki Ueno +--- + include/secrets.h | 2 +- + lib/libswan/pubkey_ecdsa.c | 12 +++---- + lib/libswan/pubkey_rsa.c | 18 +++++------ + .../secret_pubkey_stuff_to_pubkey_der.c | 2 +- + lib/libswan/secrets.c | 32 ++++++++++--------- + programs/pluto/ikev2_eap.c | 2 +- + programs/pluto/keys.c | 6 ++-- + programs/showhostkey/showhostkey.c | 32 +++++++++++-------- + 8 files changed, 56 insertions(+), 50 deletions(-) + +diff --git a/include/secrets.h b/include/secrets.h +index 971f559da7..38906bf6ba 100644 +--- a/include/secrets.h ++++ b/include/secrets.h +@@ -88,7 +88,7 @@ struct secret_stuff { + int line; + union { + chunk_t preshared_secret; +- struct secret_pubkey_stuff pubkey; ++ struct secret_pubkey_stuff *pubkey; + } u; + + chunk_t ppk; +diff --git a/lib/libswan/pubkey_ecdsa.c b/lib/libswan/pubkey_ecdsa.c +index 29af07f380..17f39fbbc1 100644 +--- a/lib/libswan/pubkey_ecdsa.c ++++ b/lib/libswan/pubkey_ecdsa.c +@@ -287,7 +287,7 @@ static struct hash_signature ECDSA_raw_sign_hash(const struct secret_stuff *pks, + { + DBGF(DBG_CRYPT, "%s: started using NSS", __func__); + +- if (!pexpect(pks->u.pubkey.private_key != NULL)) { ++ if (!pexpect(pks->u.pubkey->private_key != NULL)) { + dbg("no private key!"); + return (struct hash_signature) { .len = 0, }; + } +@@ -304,14 +304,14 @@ static struct hash_signature ECDSA_raw_sign_hash(const struct secret_stuff *pks, + struct hash_signature signature = {0}; + SECItem raw_signature = { + .type = siBuffer, +- .len = PK11_SignatureLen(pks->u.pubkey.private_key), ++ .len = PK11_SignatureLen(pks->u.pubkey->private_key), + .data = signature.ptr/*array*/, + }; + passert(raw_signature.len <= sizeof(signature.ptr/*array*/)); + dbg("ECDSA signature.len %d", raw_signature.len); + + /* create the raw signature */ +- SECStatus s = PK11_Sign(pks->u.pubkey.private_key, &raw_signature, &hash_to_sign); ++ SECStatus s = PK11_Sign(pks->u.pubkey->private_key, &raw_signature, &hash_to_sign); + if (DBGP(DBG_CRYPT)) { + DBG_dump("PK11_Sign()", raw_signature.data, raw_signature.len); + } +@@ -407,7 +407,7 @@ static struct hash_signature ECDSA_digsig_sign_hash(const struct secret_stuff *p + struct logger *logger) + { + +- if (!pexpect(pks->u.pubkey.private_key != NULL)) { ++ if (!pexpect(pks->u.pubkey->private_key != NULL)) { + dbg("no private key!"); + return (struct hash_signature) { .len = 0, }; + } +@@ -425,14 +425,14 @@ static struct hash_signature ECDSA_digsig_sign_hash(const struct secret_stuff *p + uint8_t raw_signature_data[sizeof(struct hash_signature)]; + SECItem raw_signature = { + .type = siBuffer, +- .len = PK11_SignatureLen(pks->u.pubkey.private_key), ++ .len = PK11_SignatureLen(pks->u.pubkey->private_key), + .data = raw_signature_data, + }; + passert(raw_signature.len <= sizeof(raw_signature_data)); + dbg("ECDSA signature.len %d", raw_signature.len); + + /* create the raw signature */ +- SECStatus s = PK11_Sign(pks->u.pubkey.private_key, &raw_signature, &hash_to_sign); ++ SECStatus s = PK11_Sign(pks->u.pubkey->private_key, &raw_signature, &hash_to_sign); + if (DBGP(DBG_CRYPT)) { + DBG_dump("sig_from_nss", raw_signature.data, raw_signature.len); + } +diff --git a/lib/libswan/pubkey_rsa.c b/lib/libswan/pubkey_rsa.c +index 38b44ab61d..be8935c38c 100644 +--- a/lib/libswan/pubkey_rsa.c ++++ b/lib/libswan/pubkey_rsa.c +@@ -350,7 +350,7 @@ static struct hash_signature RSA_sign_hash_raw_rsa(const struct secret_stuff *pk + return (struct hash_signature) { .len = 0, }; + } + +- if (!pexpect(pks->u.pubkey.private_key != NULL)) { ++ if (!pexpect(pks->u.pubkey->private_key != NULL)) { + dbg("no private key!"); + return (struct hash_signature) { .len = 0, }; + } +@@ -361,7 +361,7 @@ static struct hash_signature RSA_sign_hash_raw_rsa(const struct secret_stuff *pk + .data = DISCARD_CONST(uint8_t *, hash_val), + }; + +- struct hash_signature sig = { .len = PK11_SignatureLen(pks->u.pubkey.private_key), }; ++ struct hash_signature sig = { .len = PK11_SignatureLen(pks->u.pubkey->private_key), }; + passert(sig.len <= sizeof(sig.ptr/*array*/)); + SECItem signature = { + .type = siBuffer, +@@ -369,7 +369,7 @@ static struct hash_signature RSA_sign_hash_raw_rsa(const struct secret_stuff *pk + .data = sig.ptr, + }; + +- SECStatus s = PK11_Sign(pks->u.pubkey.private_key, &signature, &data); ++ SECStatus s = PK11_Sign(pks->u.pubkey->private_key, &signature, &data); + if (s != SECSuccess) { + /* PR_GetError() returns the thread-local error */ + llog_nss_error(RC_LOG_SERIOUS, logger, +@@ -485,7 +485,7 @@ static struct hash_signature RSA_sign_hash_pkcs1_1_5_rsa(const struct secret_stu + { + dbg("%s: started using NSS", __func__); + +- if (!pexpect(pks->u.pubkey.private_key != NULL)) { ++ if (!pexpect(pks->u.pubkey->private_key != NULL)) { + dbg("no private key!"); + return (struct hash_signature) { .len = 0, }; + } +@@ -501,7 +501,7 @@ static struct hash_signature RSA_sign_hash_pkcs1_1_5_rsa(const struct secret_stu + * used to generate the signature. + */ + SECItem signature_result = {0}; +- SECStatus s = SGN_Digest(pks->u.pubkey.private_key, ++ SECStatus s = SGN_Digest(pks->u.pubkey->private_key, + hash_algo->nss.oid_tag, + &signature_result, &digest); + if (s != SECSuccess) { +@@ -516,7 +516,7 @@ static struct hash_signature RSA_sign_hash_pkcs1_1_5_rsa(const struct secret_stu + /* save the signature, free the returned pointer */ + + struct hash_signature signature = { +- .len = PK11_SignatureLen(pks->u.pubkey.private_key), ++ .len = PK11_SignatureLen(pks->u.pubkey->private_key), + }; + passert(signature.len <= sizeof(signature.ptr/*array*/)); + memcpy(signature.ptr, signature_result.data, signature.len); +@@ -629,7 +629,7 @@ static struct hash_signature RSA_sign_hash_rsassa_pss(const struct secret_stuff + { + dbg("%s: started using NSS", __func__); + +- if (!pexpect(pks->u.pubkey.private_key != NULL)) { ++ if (!pexpect(pks->u.pubkey->private_key != NULL)) { + dbg("no private key!"); + return (struct hash_signature) { .len = 0, }; + } +@@ -640,7 +640,7 @@ static struct hash_signature RSA_sign_hash_rsassa_pss(const struct secret_stuff + .data = DISCARD_CONST(uint8_t *, hash_val), + }; + +- struct hash_signature sig = { .len = PK11_SignatureLen(pks->u.pubkey.private_key), }; ++ struct hash_signature sig = { .len = PK11_SignatureLen(pks->u.pubkey->private_key), }; + passert(sig.len <= sizeof(sig.ptr/*array*/)); + SECItem signature = { + .type = siBuffer, +@@ -661,7 +661,7 @@ static struct hash_signature RSA_sign_hash_rsassa_pss(const struct secret_stuff + .data = (void*)mech, /* strip const */ + .len = sizeof(*mech), + }; +- SECStatus s = PK11_SignWithMechanism(pks->u.pubkey.private_key, CKM_RSA_PKCS_PSS, ++ SECStatus s = PK11_SignWithMechanism(pks->u.pubkey->private_key, CKM_RSA_PKCS_PSS, + &mech_item, &signature, &data); + if (s != SECSuccess) { + /* PR_GetError() returns the thread-local error */ +diff --git a/lib/libswan/secret_pubkey_stuff_to_pubkey_der.c b/lib/libswan/secret_pubkey_stuff_to_pubkey_der.c +index 1b5de6917e..3f28cbd765 100644 +--- a/lib/libswan/secret_pubkey_stuff_to_pubkey_der.c ++++ b/lib/libswan/secret_pubkey_stuff_to_pubkey_der.c +@@ -32,7 +32,7 @@ static diag_t seckey_pubkey_to_der(SECKEYPublicKey *seckey_pubkey, chunk_t *der) + + diag_t secret_pubkey_stuff_to_pubkey_der(struct secret_stuff *pks, chunk_t *der) + { +- SECKEYPublicKey *seckey_pubkey = SECKEY_ConvertToPublicKey(pks->u.pubkey.private_key); ++ SECKEYPublicKey *seckey_pubkey = SECKEY_ConvertToPublicKey(pks->u.pubkey->private_key); + if (seckey_pubkey == NULL) { + return diag_nss_error("extracting Public Key from Private Key"); + } +diff --git a/lib/libswan/secrets.c b/lib/libswan/secrets.c +index 44578efbe5..6becebe8e8 100644 +--- a/lib/libswan/secrets.c ++++ b/lib/libswan/secrets.c +@@ -185,7 +185,7 @@ const ckaid_t *secret_ckaid(const struct secret *secret) + case SECRET_RSA: + case SECRET_ECDSA: + /* some sort of PKI */ +- return &secret->stuff.u.pubkey.content.ckaid; ++ return &secret->stuff.u.pubkey->content.ckaid; + default: + return NULL; + } +@@ -197,7 +197,7 @@ const keyid_t *secret_keyid(const struct secret *secret) + case SECRET_RSA: + case SECRET_ECDSA: + /* some sort of PKI */ +- return &secret->stuff.u.pubkey.content.keyid; ++ return &secret->stuff.u.pubkey->content.keyid; + default: + return NULL; + } +@@ -239,12 +239,12 @@ static struct secret *find_secret_by_pubkey_ckaid_1(struct secret *secrets, + dbg(" not PKI"); + continue; + } +- if (type != NULL && pks->u.pubkey.content.type != type) { ++ if (type != NULL && pks->u.pubkey->content.type != type) { + /* need exact or wildcard */ + dbg(" not %s", type->name); + continue; + } +- if (!ckaid_eq_nss(&pks->u.pubkey.content.ckaid, pubkey_ckaid)) { ++ if (!ckaid_eq_nss(&pks->u.pubkey->content.ckaid, pubkey_ckaid)) { + dbg(" wrong ckaid"); + continue; + } +@@ -274,12 +274,12 @@ bool secret_pubkey_same(struct secret *lhs, struct secret *rhs) + return false; + } + +- if (lhs->stuff.u.pubkey.content.type != rhs->stuff.u.pubkey.content.type) { ++ if (lhs->stuff.u.pubkey->content.type != rhs->stuff.u.pubkey->content.type) { + return false; + } + +- return lhs->stuff.u.pubkey.content.type->pubkey_same(&lhs->stuff.u.pubkey.content, +- &rhs->stuff.u.pubkey.content); ++ return lhs->stuff.u.pubkey->content.type->pubkey_same(&lhs->stuff.u.pubkey->content, ++ &rhs->stuff.u.pubkey->content); + } + + struct secret *lsw_find_secret_by_id(struct secret *secrets, +@@ -965,8 +965,9 @@ void lsw_free_preshared_secrets(struct secret **psecrets, struct logger *logger) + case SECRET_RSA: + case SECRET_ECDSA: + /* Note: pub is all there is */ +- SECKEY_DestroyPrivateKey(s->stuff.u.pubkey.private_key); +- s->stuff.u.pubkey.content.type->free_pubkey_content(&s->stuff.u.pubkey.content); ++ SECKEY_DestroyPrivateKey(s->stuff.u.pubkey->private_key); ++ s->stuff.u.pubkey->content.type->free_pubkey_content(&s->stuff.u.pubkey->content); ++ pfree(s->stuff.u.pubkey); + break; + default: + bad_case(s->stuff.kind); +@@ -1193,19 +1194,20 @@ static err_t add_private_key(struct secret **secrets, const struct secret_stuff + s->stuff.kind = type->private_key_kind; + s->stuff.line = 0; + /* make an unpacked copy of the private key */ +- s->stuff.u.pubkey.private_key = copy_private_key(private_key); +- err_t err = type->extract_pubkey_content(&s->stuff.u.pubkey.content, ++ s->stuff.u.pubkey = alloc_thing(struct secret_pubkey_stuff, "secret_pubkey_stuff"); ++ s->stuff.u.pubkey->private_key = copy_private_key(private_key); ++ err_t err = type->extract_pubkey_content(&s->stuff.u.pubkey->content, + pubk, ckaid_nss); + if (err != NULL) { + /* extract should leave pubkey_content clean */ +- SECKEY_DestroyPrivateKey(s->stuff.u.pubkey.private_key); /* allocated above */ ++ SECKEY_DestroyPrivateKey(s->stuff.u.pubkey->private_key); /* allocated above */ + pfree(s); + return err; + } + +- passert(s->stuff.u.pubkey.content.type == type); +- pexpect(s->stuff.u.pubkey.content.ckaid.len > 0); +- pexpect(s->stuff.u.pubkey.content.keyid.keyid[0] != '\0'); ++ passert(s->stuff.u.pubkey->content.type == type); ++ pexpect(s->stuff.u.pubkey->content.ckaid.len > 0); ++ pexpect(s->stuff.u.pubkey->content.keyid.keyid[0] != '\0'); + + add_secret(secrets, s, "lsw_add_rsa_secret"); + *pks = &s->stuff; +diff --git a/programs/pluto/ikev2_eap.c b/programs/pluto/ikev2_eap.c +index d7f0b1d527..fe4c6e2e8c 100644 +--- a/programs/pluto/ikev2_eap.c ++++ b/programs/pluto/ikev2_eap.c +@@ -264,7 +264,7 @@ static bool start_eap(struct ike_sa *ike, struct pbs_out *pbs) + SSL_OptionSet(pr, SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess || + SSL_BadCertHook(pr, eaptls_bad_cert_cb, eap) != SECSuccess || + SSL_HandshakeCallback(pr, eaptls_handshake_cb, eap) != SECSuccess || +- SSL_ConfigServerCert(pr, mycert->nss_cert, pks->u.pubkey.private_key, 0, 0) != SECSuccess) { ++ SSL_ConfigServerCert(pr, mycert->nss_cert, pks->u.pubkey->private_key, 0, 0) != SECSuccess) { + llog_nss_error(RC_LOG, logger, "Failed to start configure TLS options"); + return false; + } +diff --git a/programs/pluto/keys.c b/programs/pluto/keys.c +index 81e506556a..37f2408ae3 100644 +--- a/programs/pluto/keys.c ++++ b/programs/pluto/keys.c +@@ -609,7 +609,7 @@ const struct secret_stuff *get_local_private_key(const struct connection *c, + * etc) then best will end up as NULL + */ + pexpect(pks->kind == type->private_key_kind); +- pexpect(pks->u.pubkey.content.type == type); ++ pexpect(pks->u.pubkey->content.type == type); + dbg("connection %s's %s private key found in NSS DB using cert", + c->name, type->name); + return pks; +@@ -657,7 +657,7 @@ const struct secret_stuff *get_local_private_key(const struct connection *c, + * etc) then best will end up as NULL + */ + pexpect(pks->kind == type->private_key_kind); +- pexpect(pks->u.pubkey.content.type == type); ++ pexpect(pks->u.pubkey->content.type == type); + dbg("connection %s's %s private key found in NSS DB using CKAID", + c->name, type->name); + return pks; +@@ -676,7 +676,7 @@ const struct secret_stuff *get_local_private_key(const struct connection *c, + passert(pks != NULL); + + pexpect(pks->kind == type->private_key_kind); +- pexpect(pks->u.pubkey.content.type == type); ++ pexpect(pks->u.pubkey->content.type == type); + dbg("connection %s's %s private key found", + c->name, type->name); + return pks; +diff --git a/programs/showhostkey/showhostkey.c b/programs/showhostkey/showhostkey.c +index 8f40b67a62..7b003365dd 100644 +--- a/programs/showhostkey/showhostkey.c ++++ b/programs/showhostkey/showhostkey.c +@@ -172,14 +172,14 @@ static void print(struct secret_stuff *pks, + case SECRET_RSA: + case SECRET_ECDSA: + { +- printf("%s", pks->u.pubkey.content.type->name); +- keyid_t keyid = pks->u.pubkey.content.keyid; ++ printf("%s", pks->u.pubkey->content.type->name); ++ keyid_t keyid = pks->u.pubkey->content.keyid; + printf(" keyid: %s", str_keyid(keyid)[0] ? str_keyid(keyid) : ""); + if (id) { + printf(" id: %s", idb); + } + ckaid_buf cb; +- const ckaid_t *ckaid = &pks->u.pubkey.content.ckaid; ++ const ckaid_t *ckaid = &pks->u.pubkey->content.ckaid; + printf(" ckaid: %s\n", str_ckaid(ckaid, &cb)); + break; + } +@@ -237,7 +237,7 @@ static int pick_by_rsaid(struct secret *secret UNUSED, + { + char *rsaid = (char *)uservoid; + +- if (pks->kind == SECRET_RSA && streq(pks->u.pubkey.content.keyid.keyid, rsaid)) { ++ if (pks->kind == SECRET_RSA && streq(pks->u.pubkey->content.keyid.keyid, rsaid)) { + /* stop */ + return 0; + } else { +@@ -254,7 +254,7 @@ static int pick_by_ckaid(struct secret *secret UNUSED, + switch (pks->kind) { + case SECRET_RSA: + case SECRET_ECDSA: +- if (ckaid_starts_with(&pks->u.pubkey.content.ckaid, start)) { ++ if (ckaid_starts_with(&pks->u.pubkey->content.ckaid, start)) { + /* stop */ + return 0; + } +@@ -283,7 +283,7 @@ static char *base64_ipseckey_rdata_from_pubkey_secret(struct secret_stuff *pks, + enum ipseckey_algorithm_type *ipseckey_algorithm) + { + chunk_t ipseckey_pubkey = empty_chunk; /* must free */ +- err_t e = pks->u.pubkey.content.type->pubkey_content_to_ipseckey_rdata(&pks->u.pubkey.content, ++ err_t e = pks->u.pubkey->content.type->pubkey_content_to_ipseckey_rdata(&pks->u.pubkey->content, + &ipseckey_pubkey, + ipseckey_algorithm); + if (e != NULL) { +@@ -390,7 +390,7 @@ static int show_leftright(struct secret_stuff *pks, + } + } + +- passert(pks->u.pubkey.content.type != NULL); ++ passert(pks->u.pubkey->content.type != NULL); + + char *base64 = NULL; + if (pubkey_flg) { +@@ -408,11 +408,11 @@ static int show_leftright(struct secret_stuff *pks, + } else { + switch (pks->kind) { + case SECRET_RSA: +- printf("\t# rsakey %s\n", pks->u.pubkey.content.keyid.keyid); ++ printf("\t# rsakey %s\n", pks->u.pubkey->content.keyid.keyid); + printf("\t%srsasigkey=0s", side); + break; + case SECRET_ECDSA: +- printf("\t# ecdsakey %s\n", pks->u.pubkey.content.keyid.keyid); ++ printf("\t# ecdsakey %s\n", pks->u.pubkey->content.keyid.keyid); + printf("\t%secdsakey=0s", side); + break; + default: +@@ -481,14 +481,17 @@ static struct secret_stuff *foreach_nss_private_key(secret_eval func, + continue; + } + ++ struct secret_pubkey_stuff pubkey = { ++ .private_key = SECKEY_CopyPrivateKey(private_key), /* add reference */ ++ }; ++ type->extract_pubkey_content(&pubkey.content, pubk, ckaid_nss); ++ + struct secret_stuff pks = { + .kind = type->private_key_kind, + .line = 0, +- .u.pubkey.private_key = SECKEY_CopyPrivateKey(private_key), /* add reference */ ++ .u.pubkey = clone_thing(pubkey, "pubkey"), + }; + +- type->extract_pubkey_content(&pks.u.pubkey.content, pubk, ckaid_nss); +- + /* + * Only count private keys that get processed. + */ +@@ -513,8 +516,9 @@ static struct secret_stuff *foreach_nss_private_key(secret_eval func, + break; + } + +- SECKEY_DestroyPrivateKey(pks.u.pubkey.private_key); /* destory reference */ +- type->free_pubkey_content(&pks.u.pubkey.content); ++ SECKEY_DestroyPrivateKey(pks.u.pubkey->private_key); /* destory reference */ ++ type->free_pubkey_content(&pks.u.pubkey->content); ++ pfreeany(pks.u.pubkey); + + if (ret < 0) { + break; +-- +2.47.1 + + +From b4102e2243a6513897502113dfbf90fc4ff36323 Mon Sep 17 00:00:00 2001 +From: Andrew Cagney +Date: Fri, 8 Nov 2024 17:45:53 -0500 +Subject: [PATCH 2/2] crypto: refcnt struct secret_pubkey_stuff when passing to + helper thread + +fix problem where a thread was trying to use a key when which +was being deleted by reloadsecrets. + +close #1894 Segmentation fault in PK11_SignatureLen (key=0xa5a5a5a5a5a5a5a5) + +Modified-by: Daiki Ueno +--- + include/secrets.h | 4 ++++ + lib/libswan/secrets.c | 26 +++++++++++++++++++++----- + programs/pluto/ikev2_auth_helper.c | 27 ++++++++++++++++++--------- + 3 files changed, 43 insertions(+), 14 deletions(-) + +diff --git a/include/secrets.h b/include/secrets.h +index 38906bf6ba..b64e9091ca 100644 +--- a/include/secrets.h ++++ b/include/secrets.h +@@ -74,10 +74,14 @@ enum secret_kind { + }; + + struct secret_pubkey_stuff { ++ struct refcnt refcnt; + SECKEYPrivateKey *private_key; + struct pubkey_content content; + }; + ++struct secret_pubkey_stuff *secret_pubkey_stuff_addref(struct secret_pubkey_stuff *, where_t where); ++void secret_pubkey_stuff_delref(struct secret_pubkey_stuff **, where_t where); ++ + struct secret_stuff { + enum secret_kind kind; + /* +diff --git a/lib/libswan/secrets.c b/lib/libswan/secrets.c +index 6becebe8e8..5c725c5734 100644 +--- a/lib/libswan/secrets.c ++++ b/lib/libswan/secrets.c +@@ -964,10 +964,7 @@ void lsw_free_preshared_secrets(struct secret **psecrets, struct logger *logger) + break; + case SECRET_RSA: + case SECRET_ECDSA: +- /* Note: pub is all there is */ +- SECKEY_DestroyPrivateKey(s->stuff.u.pubkey->private_key); +- s->stuff.u.pubkey->content.type->free_pubkey_content(&s->stuff.u.pubkey->content); +- pfree(s->stuff.u.pubkey); ++ secret_pubkey_stuff_delref(&s->stuff.u.pubkey, HERE); + break; + default: + bad_case(s->stuff.kind); +@@ -1186,6 +1183,25 @@ static const struct pubkey_type *private_key_type_nss(SECKEYPrivateKey *private_ + } + } + ++struct secret_pubkey_stuff *secret_pubkey_stuff_addref(struct secret_pubkey_stuff *pks, ++ where_t where) ++{ ++ return addref_where(pks, where); ++} ++ ++static void free_secret_pubkey_stuff(void *obj, where_t where UNUSED) ++{ ++ struct secret_pubkey_stuff *pks = obj; ++ SECKEY_DestroyPrivateKey(pks->private_key); ++ pks->content.type->free_pubkey_content(&pks->content); ++ pfree(pks); ++} ++ ++void secret_pubkey_stuff_delref(struct secret_pubkey_stuff **pks, where_t where) ++{ ++ delref_where(pks, where) ++} ++ + static err_t add_private_key(struct secret **secrets, const struct secret_stuff **pks, + SECKEYPublicKey *pubk, SECItem *ckaid_nss, + const struct pubkey_type *type, SECKEYPrivateKey *private_key) +@@ -1194,7 +1210,7 @@ static err_t add_private_key(struct secret **secrets, const struct secret_stuff + s->stuff.kind = type->private_key_kind; + s->stuff.line = 0; + /* make an unpacked copy of the private key */ +- s->stuff.u.pubkey = alloc_thing(struct secret_pubkey_stuff, "secret_pubkey_stuff"); ++ s->stuff.u.pubkey = refcnt_alloc(struct secret_pubkey_stuff, free_secret_pubkey_stuff, HERE); + s->stuff.u.pubkey->private_key = copy_private_key(private_key); + err_t err = type->extract_pubkey_content(&s->stuff.u.pubkey->content, + pubk, ckaid_nss); +diff --git a/programs/pluto/ikev2_auth_helper.c b/programs/pluto/ikev2_auth_helper.c +index 388f57c611..08edf412ee 100644 +--- a/programs/pluto/ikev2_auth_helper.c ++++ b/programs/pluto/ikev2_auth_helper.c +@@ -38,7 +38,7 @@ struct task { + const struct crypt_mac hash_to_sign; + const struct hash_desc *hash_algo; + v2_auth_signature_cb *cb; +- const struct secret_stuff *pks; ++ struct secret_pubkey_stuff *pks; + const struct pubkey_signer *signer; + /* out */ + struct hash_signature signature; +@@ -63,19 +63,21 @@ bool submit_v2_auth_signature(struct ike_sa *ike, + where_t where) + { + const struct connection *c = ike->sa.st_connection; ++ const struct secret_stuff *s = get_local_private_key(c, signer->type, ++ ike->sa.st_logger); ++ if (s == NULL) { ++ /* failure: no key to use */ ++ return false; ++ } ++ + struct task task = { + .cb = cb, + .hash_algo = hash_algo, + .hash_to_sign = *hash_to_sign, + .signer = signer, +- .pks = get_local_private_key(c, signer->type, +- ike->sa.st_logger), ++ .pks = secret_pubkey_stuff_addref(s->u.pubkey, HERE), + }; + +- if (task.pks == NULL) +- /* failure: no key to use */ +- return false; +- + submit_task(ike->sa.st_logger, &ike->sa /*state to resume*/, + clone_thing(task, "signature task"), + &v2_auth_signature_handler, where); +@@ -85,7 +87,7 @@ bool submit_v2_auth_signature(struct ike_sa *ike, + static struct hash_signature v2_auth_signature(struct logger *logger, + const struct crypt_mac *hash_to_sign, + const struct hash_desc *hash_algo, +- const struct secret_stuff *pks, ++ const struct secret_pubkey_stuff *pks, + const struct pubkey_signer *signer) + { + passert(hash_to_sign->len <= sizeof(hash_to_sign->ptr/*array*/)); /*hint to coverity*/ +@@ -95,8 +97,14 @@ static struct hash_signature v2_auth_signature(struct logger *logger, + DBG_dump_hunk("hash to sign", *hash_to_sign); + } + ++ struct secret_stuff s = { ++ .kind = pks->content.type->private_key_kind, ++ .line = 0, ++ .u.pubkey = (struct secret_pubkey_stuff *)pks, ++ }; ++ + logtime_t sign_time = logtime_start(logger); +- struct hash_signature sig = signer->sign_hash(pks, ++ struct hash_signature sig = signer->sign_hash(&s, + hash_to_sign->ptr, + hash_to_sign->len, + hash_algo, +@@ -124,5 +132,6 @@ static stf_status v2_auth_signature_completed(struct state *st, + + static void v2_auth_signature_cleanup(struct task **task) + { ++ secret_pubkey_stuff_delref(&(*task)->pks, HERE); + pfreeany(*task); + } +-- +2.47.1 + diff --git a/SOURCES/libreswan-oracle.patch b/SOURCES/libreswan-oracle.patch new file mode 100644 index 0000000..76293eb --- /dev/null +++ b/SOURCES/libreswan-oracle.patch @@ -0,0 +1,24 @@ +From d2b6309933caaee42804eadd687a3a1f2db9833f Mon Sep 17 00:00:00 2001 +From: Edward Leung +Date: Wed, 9 Jan 2019 15:55:37 -0800 +Subject: [PATCH] Add libreswan-oracle.patch to detect Oracle Linux distro + +Signed-off-by: David Sloboda +diff --git a/libreswan-oracle.patch b/libreswan-oracle.patch +new file mode 100644 +index 0000000..89a6e6f +--- /dev/null ++++ b/libreswan-oracle.patch +@@ -0,0 +1,12 @@ ++diff -Nur libreswan-3.27.orig/programs/barf/barf.in libreswan-3.27/programs/barf/barf.in ++--- libreswan-3.27.orig/programs/barf/barf.in 2013-10-31 06:46:36.000000000 +0400 +++++ libreswan-3.27/programs/barf/barf.in 2014-03-24 18:18:25.256273674 +0400 ++@@ -272,7 +272,7 @@ ++ cat /proc/config_built_with ++ fi ++ _________________________ distro-release ++-for distro in /etc/redhat-release /etc/debian-release /etc/SuSE-release /etc/mandrake-release /etc/mandriva-release /etc/gentoo-release +++for distro in /etc/redhat-release /etc/oracle-release /etc/debian-release /etc/SuSE-release /etc/mandrake-release /etc/mandriva-release /etc/gentoo-release ++ do ++ if [ -f ${distro} ]; then ++ cat ${distro} diff --git a/SPECS/libreswan.spec b/SPECS/libreswan.spec index adc4839..4a2937b 100644 --- a/SPECS/libreswan.spec +++ b/SPECS/libreswan.spec @@ -30,8 +30,8 @@ Name: libreswan Summary: Internet Key Exchange (IKEv1 and IKEv2) implementation for IPsec # version is generated in the release script -Version: 4.12 -Release: %{?prever:0.}2%{?prever:.%{prever}}%{?dist}.1 +Version: 4.15 +Release: %{?prever:0.}3%{?prever:.%{prever}}.0.1%{?dist}.3 License: GPLv2 Url: https://libreswan.org/ Source0: https://download.libreswan.org/%{?prever:development/}%{name}-%{version}%{?prever}.tar.gz @@ -41,9 +41,12 @@ Source2: https://download.libreswan.org/cavs/ikev1_psk.fax.bz2 Source3: https://download.libreswan.org/cavs/ikev2.fax.bz2 %endif Patch: libreswan-4.6-ikev1-policy-defaults-to-drop.patch -Patch: libreswan-4.12-ikev2-auth-delete-state.patch -Patch: libreswan-4.12-ipv6-san.patch -Patch: libreswan-4.12-ikev1-compute-keymat-default.patch +Patch: libreswan-4.15-ondemand-tcp.patch +Patch: libreswan-4.15-netlink-extack.patch +Patch: libreswan-4.15-create-child-sa-race-condition.patch +Patch: libreswan-4.15-rereadsecrets.patch + +Patch100: libreswan-oracle.patch BuildRequires: audit-libs-devel BuildRequires: bison @@ -199,7 +202,32 @@ certutil -N -d sql:$tmpdir --empty-password %doc %{_mandir}/*/* %changelog -* Wed Jun 5 2024 Daiki Ueno - 4.12-2.1 +* Tue Mar 18 2025 Craig Guiller - 4.15-3.0.1.3 +- Add libreswan-oracle.patch to detect Oracle Linux distro + +* Fri Jan 24 2025 Daiki Ueno - 4.15-3.3 +- showhostkey: fix regression after RHEL-68755 (RHEL-75967) + +* Fri Nov 22 2024 Daiki Ueno - 4.15-3.2 +- crypto: refcnt struct secret_pubkey_stuff when passing to helper thread (RHEL-68755) + +* Tue Nov 12 2024 Daiki Ueno - 4.15-3.1 +- pluto: ignore CREATE_CHILD_SA request if crypto is in progress (RHEL-71496) + +* Tue Aug 6 2024 Daiki Ueno - 4.15-3 +- Fix release number + +* Tue Aug 6 2024 Daiki Ueno - 4.15-2 +- Fix auto=ondemand connection initialization with TCP (RHEL-51879) +- Make use of Netlink extack for additional error reporting (RHEL-51881) + +* Tue Jul 30 2024 Daiki Ueno - 4.15-1 +- Update to 4.15 (RHEL-50006) + +* Thu Jul 11 2024 Daiki Ueno - 4.12-4 +- Bump release to synchronize with el9_5 package + +* Wed Jun 5 2024 Daiki Ueno - 4.12-3 - Fix CVE-2024-3652 (RHEL-32483) * Thu Apr 11 2024 Daiki Ueno - 4.12-2