diff --git a/1001-libreswan-5.1-rereadsecrets.patch b/1001-libreswan-5.1-rereadsecrets.patch new file mode 100644 index 0000000000000000000000000000000000000000..2a19e2c01d9cbcb3357c71f4776461828e4feab7 --- /dev/null +++ b/1001-libreswan-5.1-rereadsecrets.patch @@ -0,0 +1,529 @@ +From 57184f415ee42774b2047f73e5bb0db54bcd4173 Mon Sep 17 00:00:00 2001 +From: mgb01105731 +Date: Tue, 11 Mar 2025 22:13:31 -0400 +Subject: [PATCH 1/1] libreswan 5.1 rereadsecrets + +--- + include/secrets.h | 6 ++- + lib/libswan/pubkey_ecdsa.c | 10 ++-- + lib/libswan/pubkey_rsa.c | 18 ++++---- + .../secret_pubkey_stuff_to_pubkey_der.c | 2 +- + lib/libswan/secrets.c | 46 ++++++++++++------- + programs/pluto/ikev2_auth_helper.c | 27 +++++++---- + programs/pluto/ikev2_eap.c | 2 +- + programs/pluto/keys.c | 6 +-- + programs/showhostkey/showhostkey.c | 32 +++++++------ + 9 files changed, 90 insertions(+), 59 deletions(-) + +diff --git a/include/secrets.h b/include/secrets.h +index 8f9f990..488d12e 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; + /* +@@ -88,7 +92,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 f8d0fe5..a4250d9 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 7862062..796748b 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 1b5de69..3f28cbd 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 01cf90e..ea071e8 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, +@@ -953,9 +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); ++ secret_pubkey_stuff_delref(&s->stuff.u.pubkey, HERE); + break; + default: + bad_case(s->stuff.kind); +@@ -1172,6 +1170,21 @@ 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) +@@ -1180,19 +1193,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 = 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); + 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_auth_helper.c b/programs/pluto/ikev2_auth_helper.c +index 4fe661b..4125824 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); + } +diff --git a/programs/pluto/ikev2_eap.c b/programs/pluto/ikev2_eap.c +index c43bd59..118c4c4 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 359ed87..e71fccb 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 aaef793..da4e40d 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); /* 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); ++ pfreeany(pks.u.pubkey); + + if (ret < 0) { + break; +-- +2.41.0 + diff --git a/0001-libreswan-anolis-rebrand-to-anolis.patch b/1001-libreswan-anolis-rebrand-to-anolis.patch similarity index 79% rename from 0001-libreswan-anolis-rebrand-to-anolis.patch rename to 1001-libreswan-anolis-rebrand-to-anolis.patch index 7feaa30405c3d749801264e5e1e967b6c16b6b2e..5a208a75c2964fb9755d5ae49efc80185a9960ca 100644 --- a/0001-libreswan-anolis-rebrand-to-anolis.patch +++ b/1001-libreswan-anolis-rebrand-to-anolis.patch @@ -6,16 +6,15 @@ Subject: [PATCH] libreswan anolis rebrand to anolis --- Makefile | 2 +- mk/defaults/linux.mk | 2 +- - programs/barf/barf.in | 2 +- testing/guestbin/docker-transmogrify | 8 +++++--- - 4 files changed, 8 insertions(+), 6 deletions(-) + 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile --- a/Makefile 2023-05-04 05:09:57.000000000 +0800 +++ b/Makefile 2023-05-30 10:27:11.589914728 +0800 @@ -27,7 +27,7 @@ MAIN_RPM_VERSION = $(shell make showversion | sed "s/-.*//") - MAIN_RPM_PREVER = $(shell make showversion | sed -e "s/^.[^-]*-\([^-]*\)-\(.*\)/rc\1_\2/" -e "s/-/_/g") + MAIN_RPM_PREVER = $(shell make showversion | sed -e "s/^.[^-]*-\([^-]*\)-\(.*\)/rc\1_\2/" -e "s/-/_/g" -e "s/\//_/g") MAIN_RPM_PREFIX = libreswan-$(MAIN_RPM_VERSION)$(MAIN_RPM_PREVER) -MAIN_RPM_RHEL_PKG = $(shell rpm -qf /etc/redhat-release) +MAIN_RPM_RHEL_PKG = $(shell rpm -qf /etc/anolis-release) @@ -34,18 +33,6 @@ diff --git a/mk/defaults/linux.mk b/mk/defaults/linux.mk # override for rhel/centos to use sysvinit INITSYSTEM=sysvinit else ifneq ($(wildcard /sbin/start),) -diff --git a/programs/barf/barf.in b/programs/barf/barf.in ---- a/programs/barf/barf.in 2023-05-04 05:09:57.000000000 +0800 -+++ b/programs/barf/barf.in 2023-05-30 10:27:11.590914728 +0800 -@@ -249,7 +249,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/anolis-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/testing/guestbin/docker-transmogrify b/testing/guestbin/docker-transmogrify --- a/testing/guestbin/docker-transmogrify 2023-05-04 05:09:57.000000000 +0800 +++ b/testing/guestbin/docker-transmogrify 2023-05-30 10:27:11.590914728 +0800 diff --git a/1001-Fix-the-error-that-the-variable-is-not-defined.patch b/1002-Fix-the-error-that-the-variable-is-not-defined.patch similarity index 100% rename from 1001-Fix-the-error-that-the-variable-is-not-defined.patch rename to 1002-Fix-the-error-that-the-variable-is-not-defined.patch diff --git a/libreswan-4.15-ipsec_import.patch b/libreswan-4.15-ipsec_import.patch new file mode 100644 index 0000000000000000000000000000000000000000..129fbfde23c6ebe6e6dd529296bd5da1cabc7b2e --- /dev/null +++ b/libreswan-4.15-ipsec_import.patch @@ -0,0 +1,20 @@ +diff --git a/programs/ipsec/ipsec.in b/programs/ipsec/ipsec.in +index 40ff9f4138..41813b5258 100755 +--- a/programs/ipsec/ipsec.in ++++ b/programs/ipsec/ipsec.in +@@ -758,7 +758,14 @@ ipsec_import() { + exit 1 + fi + +- pk12util -i "${pkcs12bundle}" -d "${IPSEC_NSSDIR_SQL}" ++ # First try blanc password to avoid uselessly prompting interactively ++ pk12util -i "${pkcs12bundle}" -d "${IPSEC_NSSDIR_SQL}" -W '' 2>/dev/null ++ # check for SEC_ERROR_BAD_PASSWORD ++ if [ $? -eq 18 ]; then ++ # Not the empty password ++ pk12util -i "${pkcs12bundle}" -d "${IPSEC_NSSDIR_SQL}" ++ fi ++ + # check and correct trust bits + set_nss_db_trusts + exit 0 diff --git a/libreswan-5.1-opt-protoport.patch b/libreswan-5.1-opt-protoport.patch new file mode 100644 index 0000000000000000000000000000000000000000..bb418bda6030e42980eae06f1a69d50d7ef26e07 --- /dev/null +++ b/libreswan-5.1-opt-protoport.patch @@ -0,0 +1,214 @@ +From b24a5b718303683420d37d0b88e7f52999195e48 Mon Sep 17 00:00:00 2001 +From: Ilya Maximets +Date: Thu, 2 Jan 2025 12:50:38 +0100 +Subject: [PATCH 1/2] ttoport: check numbers before the service name lookup + +getservbyname() is a very slow function. It seems to linearly scan all +the values in /etc/services (11473 lines on my system) and compare the +provided string to each and every one of them. One such lookup takes +around 1.8 milliseconds. Which is huge in CPU time. + +If the ipsec.conf contains a lot of connections, the time multiplies. +For example, a single 'addconn --checkconfig' with an ipsec.conf +containing 1000 connections takes 1.8 seconds. Most of that time is +just getservbyname() calls. + +Let's first check if the port string is a number before looking up the +service. This brings the total time of parsing a large config from +1.8 seconds down to 40-ish milliseconds in case the port is actually +just a number. + +Tested with an ipsec.conf containing 1000 connections with the left +protoport=udp and the right protoport=udp/6081 or udp/geneve. The +table below shows how much time it takes to execute the +'addconn --checkconfig'. + + protoport Before After SpeedUp + ------------------------------------------- + udp/6081 1.77 sec 0.04 sec 44x + udp/geneve 1.37 sec 1.37 sec -- + +Times for 'geneve' are very similar before and after, so the change +doesn't affect performance in cases where getservbyname() is needed. + +This change allows to save extra 8-10% on 'ipsec add ' calls as +well. Below are the times for 1000 consequent calls: + + protoport Before After SpeedUp + ------------------------------------------- + udp/6081 24.5 sec 22.5 sec 8.2% + udp/geneve 23.9 sec 23.9 sec -- + +Signed-off-by: Ilya Maximets +Signed-off-by: Andrew Cagney +--- + lib/libswan/ttoport.c | 45 ++++++++++++++++++++++--------------------- + 1 file changed, 23 insertions(+), 22 deletions(-) + +diff --git a/lib/libswan/ttoport.c b/lib/libswan/ttoport.c +index b1e38a4cd2..7a7083b5d2 100644 +--- a/lib/libswan/ttoport.c ++++ b/lib/libswan/ttoport.c +@@ -28,7 +28,27 @@ err_t ttoport(shunk_t service_name, ip_port *port) + *port = unset_port; + + /* +- * Extract port by trying to resolve it by name. ++ * Try converting it to a number; use SHUNK's variant of strtoul() ++ * as it is more strict around using the full string. ++ * ++ * Number conversion should be checked first, because the service ++ * name lookup is very expensive in comparision. ++ */ ++ uintmax_t l; ++ err_t e = shunk_to_uintmax(service_name, ++ NULL/*trailing-chars-not-allowed*/, ++ 0/*any-base*/, &l); ++ if (e == NULL) { ++ if (l > 0xffff) ++ return "must be between 0 and 65535"; ++ ++ /* success */ ++ *port = ip_hport(l); ++ return NULL; ++ } ++ ++ /* ++ * It's not a number, so trying to resolve it by name. + * + * XXX: the getservbyname() call requires a NUL terminated + * string but SERVICE_NAME, being a shunk_t may not include +@@ -43,25 +63,6 @@ err_t ttoport(shunk_t service_name, ip_port *port) + return NULL; + } + +- /* +- * Now try converting it to a number; use SHUNK's variant of +- * strtoul() as it is more strict around using the full +- * string. +- */ +- uintmax_t l; +- err_t e = shunk_to_uintmax(service_name, +- NULL/*trailing-chars-not-allowed*/, +- 0/*any-base*/, &l); +- if (e != NULL) { +- *port = unset_port; +- return e; +- } +- +- if (l > 0xffff) { +- *port = unset_port; +- return "must be between 0 and 65535"; +- } +- +- *port = ip_hport(l); +- return NULL; ++ /* 'e' still holds a number conversion error. */ ++ return e; + } +-- +2.48.1 + + +From 8a7043f497e8ea2fb8d066d04ac85a51c99e8056 Mon Sep 17 00:00:00 2001 +From: Ilya Maximets +Date: Wed, 15 Jan 2025 14:17:53 -0500 +Subject: [PATCH 2/2] ipsecconf: move protoport parsing to set_whack_end + +ttoprotoport() is using a very heavy getservbyname() underneath to +convert protocol names to port numbers. And this is done for every +connection being loaded. Move the logic down to set_whack_end(), so +the full validation is only done for connections we're about to add. +This significantly reduces the time required to load large config +files. For example, running 'addconn --cehckcinfig' on a file with +a 1000 connections with udp/geneve protoport takes 1.4 seconds without +this change and just 0.04 seconds with this change applied. + +The downside is that addconn --checkconfig will no longer fully +validate the protocols, but it's already not validating many other +things, and it seems to be a general direction for moving validation +to a single centralized place, which is pluto. + +Signed-off-by: Ilya Maximets +Signed-off-by: Andrew Cagney +--- + include/ipsecconf/confread.h | 1 - + lib/libipsecconf/confread.c | 10 ---------- + lib/libipsecconf/confwrite.c | 6 ++---- + lib/libipsecconf/starterwhack.c | 9 ++++++++- + 4 files changed, 10 insertions(+), 16 deletions(-) + +diff --git a/include/ipsecconf/confread.h b/include/ipsecconf/confread.h +index 6e4fcb6136..d290d847ab 100644 +--- a/include/ipsecconf/confread.h ++++ b/include/ipsecconf/confread.h +@@ -65,7 +65,6 @@ struct starter_end { + ip_address addr; + ip_address nexthop; + ip_cidr vti_ip; +- ip_protoport protoport; + + ksf strings; + knf options; +diff --git a/lib/libipsecconf/confread.c b/lib/libipsecconf/confread.c +index df8ca3d456..8e681fc2df 100644 +--- a/lib/libipsecconf/confread.c ++++ b/lib/libipsecconf/confread.c +@@ -383,16 +383,6 @@ static bool validate_end(struct starter_conn *conn_st, + } + } + +- /* copy certificate path name */ +- +- if (end->set[KSCF_PROTOPORT]) { +- char *value = end->strings[KSCF_PROTOPORT]; +- err_t ugh = ttoprotoport(value, &end->protoport); +- if (ugh != NULL) +- ERR_FOUND("bad %sprotoport=%s [%s]", leftright, value, +- ugh); +- } +- + return err; + # undef ERR_FOUND + } +diff --git a/lib/libipsecconf/confwrite.c b/lib/libipsecconf/confwrite.c +index 698091ac2e..354e318e77 100644 +--- a/lib/libipsecconf/confwrite.c ++++ b/lib/libipsecconf/confwrite.c +@@ -302,11 +302,9 @@ static void confwrite_side(FILE *out, struct starter_end *end) + str_cidr(&end->vti_ip, &as)); + } + +- if (end->protoport.is_set) { +- protoport_buf buf; ++ if (end->set[KSCF_PROTOPORT]) + fprintf(out, "\t%sprotoport=%s\n", side, +- str_protoport(&end->protoport, &buf)); +- } ++ end->strings[KSCF_PROTOPORT]); + + confwrite_int(out, side, + kv_conn | kv_leftright, +diff --git a/lib/libipsecconf/starterwhack.c b/lib/libipsecconf/starterwhack.c +index 3ec055bcb5..365494b7e8 100644 +--- a/lib/libipsecconf/starterwhack.c ++++ b/lib/libipsecconf/starterwhack.c +@@ -148,7 +148,14 @@ static bool set_whack_end(struct whack_end *w, + + w->subnets = l->strings[KSCF_SUBNETS]; + w->host_ikeport = l->options[KNCF_IKEPORT]; +- w->protoport = l->protoport; ++ ++ if (l->set[KSCF_PROTOPORT]) { ++ char *value = l->strings[KSCF_PROTOPORT]; ++ err_t ugh = ttoprotoport(value, &w->protoport); ++ if (ugh != NULL) ++ llog(RC_LOG, logger, "bad %sprotoport=%s [%s]", ++ lr, value, ugh); ++ } + + w->cert = l->strings[KSCF_CERT]; + w->ckaid = l->strings[KSCF_CKAID]; +-- +2.48.1 + diff --git a/libreswan-5.1-pexpect-negotiating-ike-sa.patch b/libreswan-5.1-pexpect-negotiating-ike-sa.patch new file mode 100644 index 0000000000000000000000000000000000000000..c991e8147b055554ff19f5cbffcc636da06b7d20 --- /dev/null +++ b/libreswan-5.1-pexpect-negotiating-ike-sa.patch @@ -0,0 +1,737 @@ +From d421aeb263d81bacb92e392c65910054f71f9843 Mon Sep 17 00:00:00 2001 +From: Andrew Cagney +Date: Thu, 16 Jan 2025 19:28:00 -0500 +Subject: [PATCH 1/4] revival: move state specific pexpects to + scheduled_{ike,child}_revival() + +--- + programs/pluto/revival.c | 101 +++++++++++++++++++-------------------- + programs/pluto/revival.h | 4 +- + programs/pluto/routing.c | 21 ++++++-- + 3 files changed, 66 insertions(+), 60 deletions(-) + +diff --git a/programs/pluto/revival.c b/programs/pluto/revival.c +index 0da0d7e4d2..8a2c779c18 100644 +--- a/programs/pluto/revival.c ++++ b/programs/pluto/revival.c +@@ -191,58 +191,9 @@ static void schedule_revival_event(struct connection *c, struct logger *logger, + (impair.revival ? "revival" : NULL), logger); + } + +-bool scheduled_revival(struct connection *c, struct state *st/*can be NULL*/, +- const char *subplot, struct logger *logger) ++static bool scheduled_revival(struct connection *c, struct state *st/*can be NULL*/, ++ const char *subplot, struct logger *logger) + { +- if (st != NULL) { +- /* +- * pexpect() ST is the owner. Routing should never +- * call when it isn't. +- */ +- if (IS_CHILD_SA(st)) { +- if (c->negotiating_child_sa != SOS_NOBODY && +- c->negotiating_child_sa != st->st_serialno) { +- /* +- * There's a newer SA playing with the routing. +- * Presumably this is an old Child SA that is in the +- * process of being rekeyed or replaced. +- */ +- llog_pexpect(st->logger, HERE, +- "revival: skipping, .negotiating_child_sa "PRI_SO" is not us", +- pri_so(c->negotiating_child_sa)); +- return false; +- } +- +- if (c->established_child_sa != SOS_NOBODY && +- c->established_child_sa != st->st_serialno) { +- /* should be covered by above */ +- llog_pexpect(st->logger, HERE, +- "revival: skipping, .established_child_sa "PRI_SO" is not us", +- pri_so(c->established_child_sa)); +- return false; +- } +- } +- +- if (IS_IKE_SA(st)) { +- if (c->negotiating_ike_sa != SOS_NOBODY && +- c->negotiating_ike_sa != st->st_serialno) { +- /* should be covered by above */ +- llog_pexpect(st->logger, HERE, +- "revival: skipping, .negotiating_ike_sa "PRI_SO" is is not us", +- pri_so(c->negotiating_ike_sa)); +- return false; +- } +- if (c->established_ike_sa != SOS_NOBODY && +- c->established_ike_sa != st->st_serialno) { +- /* should be covered by above */ +- llog_pexpect(st->logger, HERE, +- "revival: skipping, .established_ike_sa "PRI_SO" is is not us", +- pri_so(c->established_ike_sa)); +- return false; +- } +- } +- } +- + if (!revival_plausable(c, logger)) { + return false; + } +@@ -275,14 +226,58 @@ bool scheduled_revival(struct connection *c, struct state *st/*can be NULL*/, + + } + ++bool scheduled_connection_revival(struct connection *c, const char *subplot) ++{ ++ return scheduled_revival(c, NULL, subplot, c->logger); ++} ++ + bool scheduled_child_revival(struct child_sa *child, const char *subplot) + { +- return scheduled_revival(child->sa.st_connection, &child->sa, subplot, child->sa.logger); ++ struct connection *c = child->sa.st_connection; ++ if (c->negotiating_child_sa != SOS_NOBODY && ++ c->negotiating_child_sa != child->sa.st_serialno) { ++ /* ++ * There's a newer SA playing with the routing. ++ * Presumably this is an old Child SA that is in the ++ * process of being rekeyed or replaced. ++ */ ++ llog_pexpect(child->sa.logger, HERE, ++ "revival: skipping, .negotiating_child_sa "PRI_SO" is not us", ++ pri_so(c->negotiating_child_sa)); ++ return false; ++ } ++ ++ if (c->established_child_sa != SOS_NOBODY && ++ c->established_child_sa != child->sa.st_serialno) { ++ /* should be covered by above */ ++ llog_pexpect(child->sa.logger, HERE, ++ "revival: skipping, .established_child_sa "PRI_SO" is not us", ++ pri_so(c->established_child_sa)); ++ return false; ++ } ++ return scheduled_revival(c, &child->sa, subplot, child->sa.logger); + } + + bool scheduled_ike_revival(struct ike_sa *ike, const char *subplot) + { +- return scheduled_revival(ike->sa.st_connection, &ike->sa, subplot, ike->sa.logger); ++ struct connection *c = ike->sa.st_connection; ++ if (c->negotiating_ike_sa != SOS_NOBODY && ++ c->negotiating_ike_sa != ike->sa.st_serialno) { ++ /* should be covered by above */ ++ llog_pexpect(ike->sa.logger, HERE, ++ "revival: skipping, .negotiating_ike_sa "PRI_SO" is is not us", ++ pri_so(c->negotiating_ike_sa)); ++ return false; ++ } ++ if (c->established_ike_sa != SOS_NOBODY && ++ c->established_ike_sa != ike->sa.st_serialno) { ++ /* should be covered by above */ ++ llog_pexpect(ike->sa.logger, HERE, ++ "revival: skipping, .established_ike_sa "PRI_SO" is is not us", ++ pri_so(c->established_ike_sa)); ++ return false; ++ } ++ return scheduled_revival(c, &ike->sa, subplot, ike->sa.logger); + } + + void revive_connection(struct connection *c, const char *subplot, +diff --git a/programs/pluto/revival.h b/programs/pluto/revival.h +index dad6705301..13b00980dd 100644 +--- a/programs/pluto/revival.h ++++ b/programs/pluto/revival.h +@@ -25,14 +25,12 @@ struct timer_event; + void revive_connection(struct connection *c, const char *subplot, + const threadtime_t *inception); + +-bool scheduled_revival(struct connection *c, struct state *st, /*could-be-NULL*/ +- const char *subplot, struct logger *logger); +- + /* + * As in the SA's connection should be kept up so the call scheduled a + * revival. Caller should adjust routing accordingly. + */ + ++bool scheduled_connection_revival(struct connection *c, const char *subplot); + bool scheduled_child_revival(struct child_sa *child, const char *subplot); + bool scheduled_ike_revival(struct ike_sa *ike, const char *subplot); + +diff --git a/programs/pluto/routing.c b/programs/pluto/routing.c +index 91115ab081..dd9b39721c 100644 +--- a/programs/pluto/routing.c ++++ b/programs/pluto/routing.c +@@ -104,14 +104,27 @@ static bool connection_cannot_die(enum routing_event event, + struct logger *logger, + const struct routing_annex *e) + { +- struct state *st = (e->child != NULL && (*e->child) != NULL ? &(*e->child)->sa : +- e->ike != NULL && (*e->ike) != NULL ? &(*e->ike)->sa : +- NULL); + const char *subplot = (event == CONNECTION_TEARDOWN_IKE ? e->story : + event == CONNECTION_TEARDOWN_CHILD ? e->story : + event == CONNECTION_RESCHEDULE ? e->story : + "???"); +- return scheduled_revival(c, st, subplot, logger); ++ if (e->child != NULL) { ++ struct child_sa *child = (*e->child); ++ if (child != NULL) { ++ PEXPECT(logger, child->sa.st_connection == c); ++ return scheduled_child_revival(child, subplot); ++ } ++ } ++ ++ if (e->ike != NULL) { ++ struct ike_sa *ike = (*e->ike); ++ if (ike != NULL) { ++ PEXPECT(logger, ike->sa.st_connection == c); ++ return scheduled_ike_revival(ike, subplot); ++ } ++ } ++ ++ return scheduled_connection_revival(c, subplot); + } + + static void jam_sa(struct jambuf *buf, struct state *st, const char **sep) +-- +2.48.1 + + +From e474d36c43798898fa89d28ba302868399329f95 Mon Sep 17 00:00:00 2001 +From: Andrew Cagney +Date: Thu, 16 Jan 2025 20:20:24 -0500 +Subject: [PATCH 2/4] revival: don't expect the IKE SA have + .{established,negotiating}_ike_sa + +A crossing stream where this end initiated the connection's +IKE SA but is then crossed by the peer establishing the +connection's IKE SA only to connswitch to another +connection for the Child SA - leaves .negotiating_sa +but nothing else. + +see #1989 EXPECTATION FAILED: revival: skipping, .negotiating_ike_sa is not us +--- + programs/pluto/revival.c | 25 +++++++++++++++---------- + 1 file changed, 15 insertions(+), 10 deletions(-) + +diff --git a/programs/pluto/revival.c b/programs/pluto/revival.c +index 8a2c779c18..fe76d1039e 100644 +--- a/programs/pluto/revival.c ++++ b/programs/pluto/revival.c +@@ -261,21 +261,26 @@ bool scheduled_child_revival(struct child_sa *child, const char *subplot) + bool scheduled_ike_revival(struct ike_sa *ike, const char *subplot) + { + struct connection *c = ike->sa.st_connection; +- if (c->negotiating_ike_sa != SOS_NOBODY && +- c->negotiating_ike_sa != ike->sa.st_serialno) { +- /* should be covered by above */ ++ if (c->routing_sa != ike->sa.st_serialno) { + llog_pexpect(ike->sa.logger, HERE, +- "revival: skipping, .negotiating_ike_sa "PRI_SO" is is not us", +- pri_so(c->negotiating_ike_sa)); ++ "revival: skipping, .routing_sa "PRI_SO" is is not us", ++ pri_so(c->routing_sa)); + return false; + } ++ if (c->negotiating_ike_sa != SOS_NOBODY && ++ c->negotiating_ike_sa != ike->sa.st_serialno) { ++ /* ++ * For instance, crossing stream establishes IKE SA, ++ * but some other Child SA, leaving .routing_sa ++ * hanging. ++ */ ++ ldbg(ike->sa.logger, "revival: .negotiating_ike_sa "PRI_SO" is is not us", ++ pri_so(c->negotiating_ike_sa)); ++ } + if (c->established_ike_sa != SOS_NOBODY && + c->established_ike_sa != ike->sa.st_serialno) { +- /* should be covered by above */ +- llog_pexpect(ike->sa.logger, HERE, +- "revival: skipping, .established_ike_sa "PRI_SO" is is not us", +- pri_so(c->established_ike_sa)); +- return false; ++ ldbg(ike->sa.logger, "revival: .established_ike_sa "PRI_SO" is is not us", ++ pri_so(c->established_ike_sa)); + } + return scheduled_revival(c, &ike->sa, subplot, ike->sa.logger); + } +-- +2.48.1 + + +From c70b4bf00dee27d35a438bdac9ed78ea76127384 Mon Sep 17 00:00:00 2001 +From: Andrew Cagney +Date: Thu, 16 Jan 2025 17:22:09 -0500 +Subject: [PATCH 3/4] testing: add WIP + crossing-streams-23-conswitch-ike-sa-init-ikev2, see #1989 + +--- + testing/pluto/TESTLIST | 1 + + .../01-east-init.sh | 11 ++ + .../02-west-init.sh | 9 ++ + .../03-west-ike-sa-init.sh | 13 +++ + .../04-east-establish.sh | 6 ++ + .../05-west-crossing-stream.sh | 9 ++ + .../description.txt | 34 ++++++ + .../east.console.txt | 74 +++++++++++++ + .../final.sh | 6 ++ + .../ipsec.conf | 32 ++++++ + .../ipsec.secrets | 1 + + .../west.console.txt | 101 ++++++++++++++++++ + 12 files changed, 297 insertions(+) + create mode 100755 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/01-east-init.sh + create mode 100755 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/02-west-init.sh + create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/03-west-ike-sa-init.sh + create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/04-east-establish.sh + create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/05-west-crossing-stream.sh + create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/description.txt + create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/east.console.txt + create mode 100755 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/final.sh + create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.conf + create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.secrets + create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/west.console.txt + +diff --git a/testing/pluto/TESTLIST b/testing/pluto/TESTLIST +index 49d65fb534..24697f3786 100644 +--- a/testing/pluto/TESTLIST ++++ b/testing/pluto/TESTLIST +@@ -1562,6 +1562,7 @@ kvmplutotest crossing-streams-20-peer-restarts-ondemand-ike-auth good github/163 + + kvmplutotest crossing-streams-21-second-child-crypto-ikev2 good + kvmplutotest crossing-streams-22-ikev2-ipsec-interface wip github:557 ++kvmplutotest crossing-streams-23-conswitch-ike-sa-init-ikev2 wip github/1989 + + # uses the kernel-pfkeyv2.c code + +diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/01-east-init.sh b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/01-east-init.sh +new file mode 100755 +index 0000000000..5eac31179d +--- /dev/null ++++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/01-east-init.sh +@@ -0,0 +1,11 @@ ++/testing/guestbin/swan-prep --nokey ++ ++../../guestbin/ifconfig.sh eth0 add 192.0.20.254/24 ++ ++ipsec start ++../../guestbin/wait-until-pluto-started ++ ++ipsec whack --impair suppress_retransmits ++ ++ipsec add a ++ipsec add b +diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/02-west-init.sh b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/02-west-init.sh +new file mode 100755 +index 0000000000..3690498351 +--- /dev/null ++++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/02-west-init.sh +@@ -0,0 +1,9 @@ ++/testing/guestbin/swan-prep --nokey ++ipsec start ++../../guestbin/wait-until-pluto-started ++ ++ipsec whack --impair suppress_retransmits ++ ++# note order ++ipsec add a ++ipsec add b +diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/03-west-ike-sa-init.sh b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/03-west-ike-sa-init.sh +new file mode 100644 +index 0000000000..65837088f5 +--- /dev/null ++++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/03-west-ike-sa-init.sh +@@ -0,0 +1,13 @@ ++# Initiate "a" with all packets blocked. ++# ++# This will create the negotiating IKE SA #1, and then hang. ++ ++ipsec whack --impair block_outbound:yes ++ipsec up a --asynchronous ++../../guestbin/wait-for-pluto.sh --match '"a" #1: IMPAIR: blocking outbound message 1' ++../../guestbin/wait-for-pluto.sh --match '"a" #1: sent IKE_SA_INIT request' ++ ++# With connection "a"'s IKE SA #1 stuck, unblock so that the peer's ++# IKE SA #2, which will cross "a", can establish ++ ++ipsec whack --impair block_outbound:no +diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/04-east-establish.sh b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/04-east-establish.sh +new file mode 100644 +index 0000000000..668613881b +--- /dev/null ++++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/04-east-establish.sh +@@ -0,0 +1,6 @@ ++# Initiate "b" from EAST. ++# ++# On WEST this is will match and establish connection "a" with IKE SA ++# #2, and then switch to connection "b" for Child SA #3. ++ ++ipsec up b +diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/05-west-crossing-stream.sh b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/05-west-crossing-stream.sh +new file mode 100644 +index 0000000000..dc8387a82f +--- /dev/null ++++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/05-west-crossing-stream.sh +@@ -0,0 +1,9 @@ ++# confirm that the peer's IKE SA established "a", and then the peer's ++# Child SA needed to switch to "b" before establishing. ++ ++../../guestbin/wait-for-pluto.sh --match '"a" #2: responder established IKE SA' ++../../guestbin/wait-for-pluto.sh --match '"a" #3: switched to "b"' ++../../guestbin/wait-for-pluto.sh --match '"b" #3: responder established Child SA using #2' ++ ++# this is where pluto realises that the stream crossed ++../../guestbin/wait-for-pluto.sh --match '#1: dropping negotiation' +diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/description.txt b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/description.txt +new file mode 100644 +index 0000000000..52806b90d5 +--- /dev/null ++++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/description.txt +@@ -0,0 +1,34 @@ ++IKE exchange crosses, initiator conswitches peer's child leaving local ike hanging ++ ++each end has two connections that can share their IKE SA ++ ++- WEST sends "a":IKE_SA_INIT to EAST ++ - creates IKE SA #1 ++ - initiator sets "a".{routing,negotiating}_ike_sa to #1 ++ ++- EAST sends "b":IKE_SA_INIT to WEST ++ ++- WEST responds to EAST'S "b":IKE_SA_INIT ++ - creates IKE_SA #2 using connection "a" ++ - responder leaves "a".{routing,negotiating}_ike_sa et.al. untouched ++ ++- EAST sends "b":IKE_AUTH to WEST ++ ++- WEST responds to EAST's "b":IKE_AUTH ++ IKE ++ - establishes IKE SA #2 ++ - sets "a".{established,negotiating}_ike_sa #2 ++ - leaves "a".routing_sa set to #1 ++ Child: ++ - creates Child SA #3 ++ - connswitches Child SA #3 to "b" ++ - establishes Child SA #3 ++ - sets "b".{routing,negotiating,established}_child_sa to #3 ++ ++- WEST retransmits "a":IKE_SA_INIT #1 to EAST ++ - sees .established_ike_sa(?) is #2 stops negotiation ++ "tun-out-1" #1: suppressing retransmit because IKE SA was superseded #2; drop this negotiation ++ - tries to revive: ++ EXPECTATION FAILED: "a" #1: revival: skipping, .negotiating_ike_sa #2 is is not us ++ ++ref github #1989 +diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/east.console.txt b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/east.console.txt +new file mode 100644 +index 0000000000..d386cabf02 +--- /dev/null ++++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/east.console.txt +@@ -0,0 +1,74 @@ ++/testing/guestbin/swan-prep --nokey ++Creating empty NSS database ++east # ++ ../../guestbin/ifconfig.sh eth0 add 192.0.20.254/24 ++ inet 192.0.20.254/24 scope global eth0 ++east # ++ ipsec start ++Redirecting to: [initsystem] ++east # ++ ../../guestbin/wait-until-pluto-started ++east # ++ ipsec whack --impair suppress_retransmits ++east # ++ ipsec add a ++"a": added IKEv2 connection ++east # ++ ipsec add b ++"b": added IKEv2 connection ++east # ++ # Initiate "b" from EAST. ++east # ++ # ++east # ++ # On WEST this is will match and establish connection "a" with IKE SA ++east # ++ # #2, and then switch to connection "b" for Child SA #3. ++east # ++ ipsec up b ++"b" #1: initiating IKEv2 connection to 192.1.2.45 using UDP ++"b" #1: sent IKE_SA_INIT request to 192.1.2.45:UDP/500 ++"b" #1: processed IKE_SA_INIT response from 192.1.2.45:UDP/500 {cipher=AES_GCM_16_256 integ=n/a prf=HMAC_SHA2_512 group=DH19}, initiating IKE_AUTH ++"b" #1: sent IKE_AUTH request to 192.1.2.45:UDP/500 ++"b" #1: initiator established IKE SA; authenticated peer using authby=secret and ID_FQDN '@west' ++"b" #2: initiator established Child SA using #1; IPsec tunnel [192.0.20.0/24===192.0.3.0/24] {ESP/ESN=>0xESPESP <0xESPESP xfrm=AES_GCM_16_256-NONE DPD=passive} ++east # ++ # non-zero counts confirm encrypted traffic flowing ++east # ++ ipsec trafficstatus ++#2: "b", type=ESP, add_time=1234567890, inBytes=0, outBytes=0, maxBytes=2^63B, id='@west' ++east # ++ # do things line up? ++east # ++ ../../guestbin/ipsec-kernel-state.sh ++src 192.1.2.23 dst 192.1.2.45 ++ proto esp spi 0xSPISPI reqid REQID mode tunnel ++ replay-window 0 flag af-unspec esn ++ aead rfc4106(gcm(aes)) 0xENCAUTHKEY 128 ++ anti-replay esn context: ++ seq-hi 0x0, seq 0xXX, oseq-hi 0x0, oseq 0xXX ++ replay_window 0, bitmap-length 0 ++src 192.1.2.45 dst 192.1.2.23 ++ proto esp spi 0xSPISPI reqid REQID mode tunnel ++ replay-window 0 flag af-unspec esn ++ aead rfc4106(gcm(aes)) 0xENCAUTHKEY 128 ++ anti-replay esn context: ++ seq-hi 0x0, seq 0xXX, oseq-hi 0x0, oseq 0xXX ++ replay_window 128, bitmap-length 4 ++ 00000000 00000000 00000000 XXXXXXXX ++east # ++ ../../guestbin/ipsec-kernel-policy.sh ++src 192.0.3.0/24 dst 192.0.20.0/24 ++ dir fwd priority PRIORITY ptype main ++ tmpl src 192.1.2.45 dst 192.1.2.23 ++ proto esp reqid REQID mode tunnel ++src 192.0.3.0/24 dst 192.0.20.0/24 ++ dir in priority PRIORITY ptype main ++ tmpl src 192.1.2.45 dst 192.1.2.23 ++ proto esp reqid REQID mode tunnel ++src 192.0.20.0/24 dst 192.0.3.0/24 ++ dir out priority PRIORITY ptype main ++ tmpl src 192.1.2.23 dst 192.1.2.45 ++ proto esp reqid REQID mode tunnel ++east # ++ +diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/final.sh b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/final.sh +new file mode 100755 +index 0000000000..c84a482b6a +--- /dev/null ++++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/final.sh +@@ -0,0 +1,6 @@ ++# non-zero counts confirm encrypted traffic flowing ++ipsec trafficstatus ++ ++# do things line up? ++../../guestbin/ipsec-kernel-state.sh ++../../guestbin/ipsec-kernel-policy.sh +diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.conf b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.conf +new file mode 100644 +index 0000000000..cb3d584bc2 +--- /dev/null ++++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.conf +@@ -0,0 +1,32 @@ ++config setup ++ logfile=/tmp/pluto.log ++ logtime=no ++ logappend=no ++ dumpdir=/var/tmp ++ plutodebug=all ++ nhelpers=0 ++ ++conn base ++ keyexchange=ikev2 ++ auto=ignore ++ # host ++ left=192.1.2.45 ++ right=192.1.2.23 ++ # auth ++ leftid=@west ++ rightid=@east ++ authby=secret ++ leftsubnet=192.0.3.0/24 ++ retransmit-timeout=10s ++ ++conn a ++ also=base ++ # client ++ leftsourceip=192.0.3.253 ++ rightsubnet=192.0.2.0/24 ++ ++conn b ++ also=base ++ # client ++ leftsourceip=192.0.3.254 ++ rightsubnet=192.0.20.0/24 +diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.secrets b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.secrets +new file mode 100644 +index 0000000000..d3ed5698d0 +--- /dev/null ++++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.secrets +@@ -0,0 +1 @@ ++@west @east : PSK "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" +diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/west.console.txt b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/west.console.txt +new file mode 100644 +index 0000000000..00c98494e5 +--- /dev/null ++++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/west.console.txt +@@ -0,0 +1,101 @@ ++/testing/guestbin/swan-prep --nokey ++Creating empty NSS database ++west # ++ ipsec start ++Redirecting to: [initsystem] ++west # ++ ../../guestbin/wait-until-pluto-started ++west # ++ ipsec whack --impair suppress_retransmits ++west # ++ # note order ++west # ++ ipsec add a ++"a": added IKEv2 connection ++west # ++ ipsec add b ++"b": added IKEv2 connection ++west # ++ # Initiate "a" with all packets blocked. ++west # ++ # ++west # ++ # This will create the negotiating IKE SA #1, and then hang. ++west # ++ ipsec whack --impair block_outbound:yes ++IMPAIR: recording all outbound messages ++IMPAIR: block all outbound messages: no -> yes ++west # ++ ipsec up a --asynchronous ++"a" #1: initiating IKEv2 connection to 192.1.2.23 using UDP ++west # ++ ../../guestbin/wait-for-pluto.sh --match '"a" #1: IMPAIR: blocking outbound message 1' ++"a" #1: IMPAIR: blocking outbound message 1 ++west # ++ ../../guestbin/wait-for-pluto.sh --match '"a" #1: sent IKE_SA_INIT request' ++"a" #1: sent IKE_SA_INIT request to 192.1.2.23:UDP/500 ++west # ++ # With connection "a"'s IKE SA #1 stuck, unblock so that the peer's ++west # ++ # IKE SA #2, which will cross "a", can establish ++west # ++ ipsec whack --impair block_outbound:no ++IMPAIR: block all outbound messages: yes -> no ++west # ++ # confirm that the peer's IKE SA established "a", and then the peer's ++west # ++ # Child SA needed to switch to "b" before establishing. ++west # ++ ../../guestbin/wait-for-pluto.sh --match '"a" #2: responder established IKE SA' ++"a" #2: responder established IKE SA; authenticated peer using authby=secret and ID_FQDN '@east' ++west # ++ ../../guestbin/wait-for-pluto.sh --match '"a" #3: switched to "b"' ++"a" #3: switched to "b" ++west # ++ ../../guestbin/wait-for-pluto.sh --match '"b" #3: responder established Child SA using #2' ++"b" #3: responder established Child SA using #2; IPsec tunnel [192.0.3.0/24===192.0.20.0/24] {ESP/ESN=>0xESPESP <0xESPESP xfrm=AES_GCM_16_256-NONE DPD=passive} ++west # ++ # this is where pluto realises that the stream crossed ++west # ++ ../../guestbin/wait-for-pluto.sh --match '#1: dropping negotiation' ++"a" #1: dropping negotiation as superseeded by established IKE SA #2 ++west # ++ # non-zero counts confirm encrypted traffic flowing ++west # ++ ipsec trafficstatus ++#3: "b", type=ESP, add_time=1234567890, inBytes=0, outBytes=0, maxBytes=2^63B, id='@east' ++west # ++ # do things line up? ++west # ++ ../../guestbin/ipsec-kernel-state.sh ++src 192.1.2.45 dst 192.1.2.23 ++ proto esp spi 0xSPISPI reqid REQID mode tunnel ++ replay-window 0 flag af-unspec esn ++ aead rfc4106(gcm(aes)) 0xENCAUTHKEY 128 ++ anti-replay esn context: ++ seq-hi 0x0, seq 0xXX, oseq-hi 0x0, oseq 0xXX ++ replay_window 0, bitmap-length 0 ++src 192.1.2.23 dst 192.1.2.45 ++ proto esp spi 0xSPISPI reqid REQID mode tunnel ++ replay-window 0 flag af-unspec esn ++ aead rfc4106(gcm(aes)) 0xENCAUTHKEY 128 ++ anti-replay esn context: ++ seq-hi 0x0, seq 0xXX, oseq-hi 0x0, oseq 0xXX ++ replay_window 128, bitmap-length 4 ++ 00000000 00000000 00000000 XXXXXXXX ++west # ++ ../../guestbin/ipsec-kernel-policy.sh ++src 192.0.3.0/24 dst 192.0.20.0/24 ++ dir out priority PRIORITY ptype main ++ tmpl src 192.1.2.45 dst 192.1.2.23 ++ proto esp reqid REQID mode tunnel ++src 192.0.20.0/24 dst 192.0.3.0/24 ++ dir fwd priority PRIORITY ptype main ++ tmpl src 192.1.2.23 dst 192.1.2.45 ++ proto esp reqid REQID mode tunnel ++src 192.0.20.0/24 dst 192.0.3.0/24 ++ dir in priority PRIORITY ptype main ++ tmpl src 192.1.2.23 dst 192.1.2.45 ++ proto esp reqid REQID mode tunnel ++west # ++ +-- +2.48.1 + + +From ee7a62dc7f400f4b830e64e0385a6d16fda234b3 Mon Sep 17 00:00:00 2001 +From: Andrew Cagney +Date: Mon, 6 Jan 2025 15:38:03 -0500 +Subject: [PATCH 4/4] ikev2: in event_v2_retransmit() check .established_ike_sa + != SOS_NOBODY + +That is: + !IS_IKE_SA_ESTABLISHED(&ike->sa) && c->established_ike_sa != SOS_NOBODY +when the streams cross, the etablished IKE SA may be older. +--- + programs/pluto/ikev2_retransmit.c | 32 ++++++++++++++++++++----------- + 1 file changed, 21 insertions(+), 11 deletions(-) + +diff --git a/programs/pluto/ikev2_retransmit.c b/programs/pluto/ikev2_retransmit.c +index df6ab99e63..7b0197445c 100644 +--- a/programs/pluto/ikev2_retransmit.c ++++ b/programs/pluto/ikev2_retransmit.c +@@ -49,25 +49,35 @@ void event_v2_retransmit(struct state *ike_sa, monotime_t now UNUSED) + return; + } + +- /* if this connection has a newer Child SA than this state +- * this negotiation is not relevant any more. would this +- * cover if there are multiple CREATE_CHILD_SA pending on this +- * IKE negotiation ??? +- * ++ /* + * XXX: Suspect this is to handle a race where the other end + * brings up the connection first? For that case, shouldn't + * this state have been deleted? + * +- * NOTE: a larger serialno does not mean superseded. crossed ++ * NOTE: a larger serialno does not mean superseded. Crossed + * streams could mean the lower serial established later and +- * is the "newest". Should > be replaced with != ? ++ * is the "newest". Hence the equality check (and not >). + */ + + struct connection *c = ike->sa.st_connection; +- if (!IS_IKE_SA_ESTABLISHED(&ike->sa) && c->established_ike_sa > ike->sa.st_serialno) { +- llog_sa(RC_LOG, ike, +- "suppressing retransmit because IKE SA was superseded #%lu; drop this negotiation", +- c->established_ike_sa); ++ if (!IS_IKE_SA_ESTABLISHED(&ike->sa) && c->established_ike_sa != SOS_NOBODY) { ++ /* ++ * The connection is established, yet this IKE SA is ++ * not. Presumably this means that the peer also ++ * initiated and established an IKE SA leaving this ++ * IKE SA in limbo. ++ * ++ * Note: since it isn't established it can't be the ++ * connection's established IKE SA. ++ * ++ * Note: this may also leave the Child SA for the ++ * connection in limbo. Hopefully revival code will ++ * pick that up. ++ */ ++ PEXPECT(ike->sa.logger, c->established_ike_sa != ike->sa.st_serialno); ++ llog(RC_LOG, ike->sa.logger, ++ "suppressing retransmit because IKE SA was superseded by #%lu; drop this negotiation", ++ c->established_ike_sa); + pstat_sa_failed(&ike->sa, REASON_SUPERSEDED_BY_NEW_SA); + connection_delete_ike_family(&ike, HERE); + return; +-- +2.48.1 + diff --git a/libreswan-5.1-whack-ctlsocket.patch b/libreswan-5.1-whack-ctlsocket.patch new file mode 100644 index 0000000000000000000000000000000000000000..601930265385c3ac64f91dcced2f8c74c2479cdd --- /dev/null +++ b/libreswan-5.1-whack-ctlsocket.patch @@ -0,0 +1,26 @@ +From 43e5255728845f9314049a20644fc19a745cde81 Mon Sep 17 00:00:00 2001 +From: Tuomo Soini +Date: Fri, 11 Oct 2024 18:28:24 +0300 +Subject: [PATCH] ipsec: fix duplicate --ctlsocket option for whack + +github issue: whack error: duplicated flag ctlsocket #1840 +--- + programs/ipsec/ipsec.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/programs/ipsec/ipsec.in b/programs/ipsec/ipsec.in +index 1510d238d0..fbceac682b 100755 +--- a/programs/ipsec/ipsec.in ++++ b/programs/ipsec/ipsec.in +@@ -1203,7 +1203,7 @@ while [ ${#} -gt 0 ]; do + # We need to make sure we don't give it twice + shift + case " ${@} " in +- --ctlsocket) ++ *" --ctlsocket "*) + exec ${dry_run} "${IPSEC_EXECDIR}/whack" "${@}" + ;; + *) +-- +2.48.1 + diff --git a/v4.12.tar.gz b/libreswan-5.1.tar.gz similarity index 33% rename from v4.12.tar.gz rename to libreswan-5.1.tar.gz index 2b8b9778e297ee749f32652386251c9c15e3149e..cf3b0abc80582d752d01bfadad2b6c674c9deef8 100644 Binary files a/v4.12.tar.gz and b/libreswan-5.1.tar.gz differ diff --git a/libreswan.spec b/libreswan.spec index 867bf8982a68643467b38a55e0fc3a6e55fe09b4..c9bbb408f0139a31f975665e6abf0ea311b0dfb1 100644 --- a/libreswan.spec +++ b/libreswan.spec @@ -1,4 +1,4 @@ -%define anolis_release 2 +%define anolis_release 1 %global _hardened_build 1 # These are rpm macros and are 0 or 1 @@ -9,8 +9,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 \\\ PYTHON_BINARY=%{__python3} \\\ @@ -30,11 +30,11 @@ Name: libreswan Summary: Internet Key Exchange (IKEv1 and IKEv2) implementation for IPsec # version is generated in the release script -Version: 4.12 +Version: 5.1 Release: %{anolis_release}%{?dist} License: GPLv2 Url: https://libreswan.org/ -Source0: https://github.com/libreswan/libreswan/archive/refs/tags/v%{version}.tar.gz +Source0: https://github.com/libreswan/libreswan/releases/download/v%{version}/%{name}-%{version}.tar.gz %if 0%{with_cavstests} Source1: https://download.libreswan.org/cavs/ikev1_dsa.fax.bz2 @@ -42,8 +42,18 @@ Source2: https://download.libreswan.org/cavs/ikev1_psk.fax.bz2 Source3: https://download.libreswan.org/cavs/ikev2.fax.bz2 %endif -Patch1000: 0001-libreswan-anolis-rebrand-to-anolis.patch -Patch1001: 1001-Fix-the-error-that-the-variable-is-not-defined.patch +Patch1000: 1001-libreswan-anolis-rebrand-to-anolis.patch +Patch1001: 1002-Fix-the-error-that-the-variable-is-not-defined.patch + +Patch1: libreswan-4.15-ipsec_import.patch +# https://github.com/libreswan/libreswan/commit/6612afa2daaceceff066acf6b2d90d7f00ce8b98 +Patch2: 1001-libreswan-5.1-rereadsecrets.patch +# https://github.com/libreswan/libreswan/commit/f9af980132f585a7735e8cbe62d9691565a0f5b1 +Patch3: libreswan-5.1-opt-protoport.patch +# https://github.com/libreswan/libreswan/commit/596159df8abd9e118644de378366c68df63b9367 +Patch4: libreswan-5.1-pexpect-negotiating-ike-sa.patch +# https://github.com/libreswan/libreswan/commit/43e5255728845f9314049a20644fc19a745cde81 +Patch5: libreswan-5.1-whack-ctlsocket.patch BuildRequires: audit-libs-devel BuildRequires: bison @@ -200,6 +210,13 @@ certutil -N -d sql:$tmpdir --empty-password %doc docs/*.* %changelog +* Wed Feb 19 2025 mgb01105731 - 5.1-1 +- Update to 5.1 from 4.12 +- Add patches to first try blanc password to avoid uselessly prompting +- Add patches to refcnt struct secret_pubkey_stuff when passing to helper thread + [Patches cherry-picked from c10s. Original changelog: + - ipsec: fix duplicate --ctlsocket option for whack(5.1-6)] + * Fri Nov 10 2023 Funda Wang - 4.12-2 - Rebrand to anolis