diff --git a/.gitignore b/.gitignore index 2b9b5b9..bf4e63f 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.15.tar.gz +SOURCES/libreswan-5.1.tar.gz diff --git a/.libreswan.metadata b/.libreswan.metadata index 199f4d2..7b3063f 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 -861eaeefff1c2f3862a8bfe0295b3e307f8e3055 SOURCES/libreswan-4.15.tar.gz +12d2ddd7cad4aab849456e2175378f034eab27bb SOURCES/libreswan-5.1.tar.gz diff --git a/SOURCES/libreswan-4.15-netlink-extack.patch b/SOURCES/libreswan-4.15-netlink-extack.patch deleted file mode 100644 index 92cf5e7..0000000 --- a/SOURCES/libreswan-4.15-netlink-extack.patch +++ /dev/null @@ -1,153 +0,0 @@ -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 deleted file mode 100644 index 11689a6..0000000 --- a/SOURCES/libreswan-4.15-ondemand-tcp.patch +++ /dev/null @@ -1,52 +0,0 @@ -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.tar.gz.asc b/SOURCES/libreswan-4.15.tar.gz.asc deleted file mode 100644 index c7efe26..0000000 --- a/SOURCES/libreswan-4.15.tar.gz.asc +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQJHBAABCgAxFiEEkH55DyXB6OVhzXO1hf9LQ7MPxvkFAmYXR8ETHHRlYW1AbGli -cmVzd2FuLm9yZwAKCRCF/0tDsw/G+WmID/46LnJ04rvj7RBZDzZg1nUnZyquuWd+ -vqGSFG54Ku5p62/JqL3+8Eu6dQ2o8DI1SJwMJFdaSFIwxNHTvZSr1wOwaSa+NQrI -y/zTSAdZP04P0SqqJyOQxqYFMAEoRZhRE1gD4+1KGlQwPKzAtHi+2sHlfVryZEuF -ZRRpuEcYrsdRneWxzRHKguDLb58b159yvt/HIQNOe7/BGnlq1rkBMgT0rD98A8Qb -EOeZh6TcV9OnW2qm4QcJ5fm0ihvZpO/h3gih4KopwZQa7fUJYUPVRrS2AO40MVIM -peq9/V+wD/+gthVh2eqtNzghGWxxwpZgBDQCmAUTr60QdCYeR2XsB/MGG5BJBs4m -zFgXqsSHnEVJisUxnynNIFhUECo2A0CbVTAZnqBWgGkSO82VLu7506eaxJcJW84s -QpNM7shHVdmV3lroqbJU2zBMKEHvCldFTDO2YTvfOV0Twytyn5gmT1sVqGiwdGpR -XhfoRWILy+ViExhv6ZTubIYc1c8yo5wCG1tAq2iYfdLIcZVvqZIWB5LCv0rN2iPl -0OrKo7bOQEmf7C+AL/LoAKWPpQeS79CYzwSKDfYHzE559yks0KPiTE5nLu8VrWH9 -zDTJ+2Ket3Ve93cz7zdqWcD7+HfKN7CxBW/bfCrysldsEjDBmvMiUI46kwPI99Y2 -w08DOHUAwSUgDg== -=nCeA ------END PGP SIGNATURE----- diff --git a/SOURCES/libreswan-4.6-ikev1-policy-defaults-to-drop.patch b/SOURCES/libreswan-4.6-ikev1-policy-defaults-to-drop.patch deleted file mode 100644 index 40073d5..0000000 --- a/SOURCES/libreswan-4.6-ikev1-policy-defaults-to-drop.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 13720e0dedcab1eaf3334a73a42b68581acd9f3b Mon Sep 17 00:00:00 2001 -From: Daniel Kahn Gillmor -Date: Fri, 7 Jan 2022 18:36:47 -0500 -Subject: [PATCH] ikev1-policy defaults to drop - -IKEv2 has been available for 16 years (RFC 4306 was published December -2005). At some point, we should be discouraging IKEv1 adoption. - -To the extent that a user needs IKEv1, they can manually add -ikev1-policy=accept to /etc/ipsec.conf. ---- - configs/d.ipsec.conf/ikev1-policy.xml | 7 ++++--- - include/ipsecconf/keywords.h | 2 +- - lib/libipsecconf/confread.c | 1 + - programs/pluto/server.c | 5 ----- - 4 files changed, 6 insertions(+), 9 deletions(-) - -diff --git a/configs/d.ipsec.conf/ikev1-policy.xml b/configs/d.ipsec.conf/ikev1-policy.xml -index 17d1747e3b..3bd6702564 100644 ---- a/configs/d.ipsec.conf/ikev1-policy.xml -+++ b/configs/d.ipsec.conf/ikev1-policy.xml -@@ -3,9 +3,10 @@ - - - What to do with received IKEv1 packets. Valid options are --accept (default), reject which --will reply with an error, and drop which will silently drop --any received IKEv1 packet. If this option is set to drop or reject, an attempt to load an -+drop (default) which will silently drop -+any received IKEv1 packet, accept, and -+reject which will reply with an error. -+If this option is set to drop or reject, an attempt to load an - IKEv1 connection will fail, as these connections would never be able to receive a packet - for processing. - -diff --git a/include/ipsecconf/keywords.h b/include/ipsecconf/keywords.h -index 660847733c..31b519242a 100644 ---- a/include/ipsecconf/keywords.h -+++ b/include/ipsecconf/keywords.h -@@ -111,7 +111,7 @@ enum keyword_numeric_config_field { - - KBF_LISTEN_TCP, /* listen on TCP port 4500 - default no */ - KBF_LISTEN_UDP, /* listen on UDP port 500/4500 - default yes */ -- KBF_GLOBAL_IKEv1, /* global ikev1 policy - default accept */ -+ KBF_GLOBAL_IKEv1, /* global ikev1 policy - default drop */ - KBF_ROOF - }; - -diff --git a/lib/libipsecconf/confread.c b/lib/libipsecconf/confread.c -index 5b5aba723f..68fbccf442 100644 ---- a/lib/libipsecconf/confread.c -+++ b/lib/libipsecconf/confread.c -@@ -95,6 +95,7 @@ static void ipsecconf_default_values(struct starter_config *cfg) - /* Don't inflict BSI requirements on everyone */ - SOPT(KBF_SEEDBITS, 0); - SOPT(KBF_DROP_OPPO_NULL, false); -+ SOPT(KBF_GLOBAL_IKEv1, GLOBAL_IKEv1_DROP); - - #ifdef HAVE_LABELED_IPSEC - SOPT(KBF_SECCTX, SECCTX); --- -2.34.1 - diff --git a/SOURCES/libreswan-5.1-rereadsecrets.patch b/SOURCES/libreswan-5.1-rereadsecrets.patch new file mode 100644 index 0000000..be23585 --- /dev/null +++ b/SOURCES/libreswan-5.1-rereadsecrets.patch @@ -0,0 +1,582 @@ +From ddf4fcee5812e453f784e7b453f52d242baf060c 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 | 10 +++--- + 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 | 31 ++++++++++-------- + 8 files changed, 54 insertions(+), 49 deletions(-) + +diff --git a/include/secrets.h b/include/secrets.h +index 8f9f990c10..c9272d71e0 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 f8d0fe5dae..a4250d9356 100644 +--- a/lib/libswan/pubkey_ecdsa.c ++++ b/lib/libswan/pubkey_ecdsa.c +@@ -288,7 +288,7 @@ static struct hash_signature ECDSA_raw_sign_hash(const struct secret_stuff *pks, + { + ldbgf(DBG_CRYPT, logger, "%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,7 +304,7 @@ static struct hash_signature ECDSA_raw_sign_hash(const struct secret_stuff *pks, + /* point signature at the SIG_VAL buffer */ + struct hash_signature signature = {0}; + SECItem raw_signature; +- SECStatus s = SGN_Digest(pks->u.pubkey.private_key, ++ SECStatus s = SGN_Digest(pks->u.pubkey->private_key, + hash_alg->nss.oid_tag, + &raw_signature, &hash_to_sign); + if (s != SECSuccess) { +@@ -411,7 +411,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, }; + } +@@ -429,14 +429,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 78620620d6..796748bdaa 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, 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 01cf90e4f3..1088f914af 100644 +--- a/lib/libswan/secrets.c ++++ b/lib/libswan/secrets.c +@@ -186,7 +186,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; + } +@@ -198,7 +198,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; + } +@@ -241,12 +241,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; + } +@@ -276,12 +276,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, +@@ -954,8 +954,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); +@@ -1180,19 +1181,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 c43bd59b6d..118c4c484e 100644 +--- a/programs/pluto/ikev2_eap.c ++++ b/programs/pluto/ikev2_eap.c +@@ -282,7 +282,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 359ed87f75..e71fccb825 100644 +--- a/programs/pluto/keys.c ++++ b/programs/pluto/keys.c +@@ -697,7 +697,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; +@@ -745,7 +745,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; +@@ -764,7 +764,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 aaef793914..65b95ba596 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 = &pubkey, + }; + +- type->extract_pubkey_content(&pks.u.pubkey.content, pubk, ckaid_nss); +- + /* + * Only count private keys that get processed. + */ +@@ -513,8 +516,8 @@ static struct secret_stuff *foreach_nss_private_key(secret_eval func, + break; + } + +- SECKEY_DestroyPrivateKey(pks.u.pubkey.private_key); /* destroy reference */ +- type->free_pubkey_content(&pks.u.pubkey.content); ++ SECKEY_DestroyPrivateKey(pks.u.pubkey->private_key); /* destroy reference */ ++ type->free_pubkey_content(&pks.u.pubkey->content); + + if (ret < 0) { + break; +-- +2.47.0 + + +From 9e9bdbc27aedb035e769660b65a92e173ee9a5f9 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 | 23 ++++++++++++++++++----- + programs/pluto/ikev2_auth_helper.c | 27 ++++++++++++++++++--------- + 3 files changed, 40 insertions(+), 14 deletions(-) + +diff --git a/include/secrets.h b/include/secrets.h +index c9272d71e0..488d12e8c5 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 1088f914af..3fed6a55da 100644 +--- a/lib/libswan/secrets.c ++++ b/lib/libswan/secrets.c +@@ -953,10 +953,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); +@@ -1173,6 +1170,22 @@ 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); ++} ++ ++void secret_pubkey_stuff_delref(struct secret_pubkey_stuff **pks, where_t where) ++{ ++ struct secret_pubkey_stuff *last = delref_where(pks, &global_logger, where); ++ if (last != NULL) { ++ SECKEY_DestroyPrivateKey(last->private_key); ++ last->content.type->free_pubkey_content(&last->content); ++ pfree(last); ++ } ++} ++ + 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) +@@ -1181,7 +1194,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, 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 4fe661b559..2973569a90 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, struct msg_digest *md, + 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.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.logger), ++ .pks = secret_pubkey_stuff_addref(s->u.pubkey, HERE), + }; + +- if (task.pks == NULL) +- /* failure: no key to use */ +- return false; +- + submit_task(/*callback*/&ike->sa, /*task*/&ike->sa, md, + /*detach_whack*/false, + clone_thing(task, "signature task"), +@@ -86,7 +88,7 @@ bool submit_v2_auth_signature(struct ike_sa *ike, struct msg_digest *md, + 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*/ +@@ -96,8 +98,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, +@@ -125,5 +133,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.0 + diff --git a/SOURCES/libreswan-5.1.tar.gz.asc b/SOURCES/libreswan-5.1.tar.gz.asc new file mode 100644 index 0000000..53c900c --- /dev/null +++ b/SOURCES/libreswan-5.1.tar.gz.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJHBAABCgAxFiEEkH55DyXB6OVhzXO1hf9LQ7MPxvkFAmcFdvUTHHRlYW1AbGli +cmVzd2FuLm9yZwAKCRCF/0tDsw/G+aDLD/9SxgIFhOgqE+X7HT7JN2bDRyZuEUCP +0FK7q2bcBNDgA7AlEiSqYFiHVQcAzmZLrx39IqMfAIGNDoB5jSUUl+Ij4zT/qEfU +nMJ1pxt+GqUwOeVkz+89KOS6KkQ9N3W8Y0HZjlI3LB/rvL8+/eytXv9ckbrQZuwL +Anqv4pdgYO/ybVF/n8vz/8vgAhDM0Rhm3Xqft4w8sxyWrl3LU11/mmaOyD5eXdCD +QvLtvhQg10W+/MKNzrKHfbIgFjtzEeKo3CMSniNAgkHtNwXTVIR09RkACvfCtAhv +yO4gmsTl4ftGAtvUeq3pexJsbpyJTywwwCVNFn1ustrwxatbn0oDdo1aqd33Dt/w +gb1yt14smwahRyMCROK1Ozrk1KBYl7lQ3eek1SXKEJ33GzxDw6HB2PCy1Y+ni54W +NGuN9oJQNVGZiU/kD7mWWWGeHCNetTIZLNRaV7RoGxZFH1zn0n7jvhk5SezPsQNN +e4y5HSd8sEoUtmgYN2uf902Iq0Af5QErqieSPCz130F9lndGbGxMlAF64wVgaNfq +/jjH8whHkNqWyM3BRQE2tTtpM9AONF9GJ3RgeaAfSLZV2SMeGVs9YPNs4XFqs3xM +ToQMCE7OG6VgPQAvE/JnPoTGOk+GX2C+cXi2Vluvc+E3Sw52To+q2ZeQTjr+ejj6 +EULR5f5plo88uQ== +=ieXQ +-----END PGP SIGNATURE----- diff --git a/SPECS/libreswan.spec b/SPECS/libreswan.spec index bee5e01..3aee224 100644 --- a/SPECS/libreswan.spec +++ b/SPECS/libreswan.spec @@ -2,7 +2,7 @@ ## (rpmautospec version 0.6.5) ## RPMAUTOSPEC: autorelease, autochangelog %define autorelease(e:s:pb:n) %{?-p:0.}%{lua: - release_number = 7; + release_number = 2; base_release_number = tonumber(rpm.expand("%{?-b*}%{!?-b:1}")); print(release_number + base_release_number - 1); }%{?-e:.%{-e*}}%{?-s:.%{-s*}}%{!?-n:%{?dist}} @@ -17,8 +17,8 @@ %global unbound_version 1.6.6 # Libreswan config options %global libreswan_config \\\ - FINALLIBEXECDIR=%{_libexecdir}/ipsec \\\ - FINALMANDIR=%{_mandir} \\\ + LIBEXECDIR=%{_libexecdir}/ipsec \\\ + MANDIR=%{_mandir} \\\ PREFIX=%{_prefix} \\\ INITSYSTEM=systemd \\\ SHELL_BINARY=%{_bindir}/sh \\\ @@ -39,7 +39,7 @@ Name: libreswan Summary: Internet Key Exchange (IKEv1 and IKEv2) implementation for IPsec # version is generated in the release script -Version: 4.15 +Version: 5.1 Release: %autorelease # The code in lib/libswan/nss_copies.c is under MPL-2.0, while the # rest is under GPL-2.0-or-later @@ -55,9 +55,7 @@ Source5: https://download.libreswan.org/cavs/ikev2.fax.bz2 %endif Patch1: libreswan-4.15-ipsec_import.patch -Patch2: libreswan-4.6-ikev1-policy-defaults-to-drop.patch -Patch3: libreswan-4.15-ondemand-tcp.patch -Patch4: libreswan-4.15-netlink-extack.patch +Patch2: libreswan-5.1-rereadsecrets.patch BuildRequires: audit-libs-devel BuildRequires: bison @@ -230,6 +228,12 @@ certutil -N -d sql:$tmpdir --empty-password %changelog ## START: Generated by rpmautospec +* Fri Nov 29 2024 Daiki Ueno - 5.1-2 +- crypto: refcnt struct secret_pubkey_stuff when passing to helper thread + +* Fri Nov 29 2024 Paul Wouters - 5.1-1 +- Update to libreswan 5.1 + * Tue Oct 29 2024 Troy Dawson - 4.15-7 - Bump release for October 2024 mass rebuild: