From c83a49c5eb5519aacdab89f28b42bbd19990c901 Mon Sep 17 00:00:00 2001 From: Cropi Date: Thu, 25 Jun 2026 10:43:45 +0200 Subject: [PATCH] omelasticsearch: backport PQC TLS parameters Backport three new action parameters from upstream commit a3463c693: - tls.tlsversion (maps to CURLOPT_SSLVERSION) - tls.ciphersuites (maps to CURLOPT_TLS13_CIPHERS, requires libcurl >= 7.61) - tls.keyexchangegroups (maps to CURLOPT_SSL_EC_CURVES, requires libcurl >= 7.73) Setting tls.keyexchangegroups to "X25519MLKEM768:X25519" enables hybrid PQC key exchange when libcurl is linked against OpenSSL 3.x with the OQS provider. The patch was regenerated against the 8.2604.0 tarball because the upstream branch tip had diverged enough to cause fuzz=2 on hunk #7 (the writeoperation handler block had a different coding style in the packaged source), which RPM's --fuzz=0 patch invocation would reject. Resolves: RHEL-193505 Signed-off-by: Cropi --- ...arch-apply-tls-opts-during-detection.patch | 128 +++++++++++++++ omelasticsearch-pqc-tls.patch | 153 ++++++++++++++++++ rsyslog.spec | 15 +- 3 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 omelasticsearch-apply-tls-opts-during-detection.patch create mode 100644 omelasticsearch-pqc-tls.patch diff --git a/omelasticsearch-apply-tls-opts-during-detection.patch b/omelasticsearch-apply-tls-opts-during-detection.patch new file mode 100644 index 0000000..d8a54ff --- /dev/null +++ b/omelasticsearch-apply-tls-opts-during-detection.patch @@ -0,0 +1,128 @@ +From 930c97270c08102551e1b1b1a265326253303857 Mon Sep 17 00:00:00 2001 +From: Rainer Gerhards +Date: Sun, 5 Jul 2026 11:14:20 +0200 +Subject: [PATCH] omelasticsearch: apply TLS options during detection + +Extract all TLS-related curl setopt calls into a shared +curlSetupTlsOptions() helper and call it from both curlSetupCommon() +(worker handles) and detectTargetPlatformAndVersion() (the startup +Elasticsearch version probe), so that startup probes honour the same +TLS policy as worker connections. + +Also add a LIBCURL_VERSION_NUM >= 0x072200 guard around the TLSv1.2 +entry in tlsVersionMap[] to be safe on very old build-time headers. + +Backport of upstream commit 930c97270c08102551e1b1b1a265326253303857 + +Signed-off-by: Attila Lakatos +--- + plugins/omelasticsearch/omelasticsearch.c | 56 ++++++++++++----------- + 1 file changed, 29 insertions(+), 27 deletions(-) + +--- a/plugins/omelasticsearch/omelasticsearch.c ++++ b/plugins/omelasticsearch/omelasticsearch.c +@@ -254,6 +254,7 @@ + static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; + + static rsRetVal ATTR_NONNULL() curlSetup(wrkrInstanceData_t *pWrkrData); ++static void ATTR_NONNULL() curlSetupTlsOptions(instanceData *const pData, CURL *const handle); + static rsRetVal ATTR_NONNULL() detectTargetPlatformAndVersion(instanceData *const pData); + static rsRetVal ATTR_NONNULL() applyVersionRequirements(instanceData *const pData); + +@@ -801,8 +802,7 @@ + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlVersionResult); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); +- if (pData->allowUnsignedCerts) curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); +- if (pData->skipVerifyHost) curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); ++ curlSetupTlsOptions(pData, curl); + if (pData->authBuf != NULL) { + curl_easy_setopt(curl, CURLOPT_USERPWD, pData->authBuf); + curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY); +@@ -815,10 +815,6 @@ + } + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + } +- if (pData->caCertFile) curl_easy_setopt(curl, CURLOPT_CAINFO, pData->caCertFile); +- if (pData->myCertFile) curl_easy_setopt(curl, CURLOPT_SSLCERT, pData->myCertFile); +- if (pData->myPrivKeyFile) curl_easy_setopt(curl, CURLOPT_SSLKEY, pData->myPrivKeyFile); +- + CURLcode code = curl_easy_perform(curl); + long status = 0; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status); +@@ -2104,31 +2100,25 @@ + static const struct { + const char *name; + long curlver; +-} tlsVersionMap[] = {{"TLSv1.2", CURL_SSLVERSION_TLSv1_2}, ++} tlsVersionMap[] = { ++#if LIBCURL_VERSION_NUM >= 0x072200 ++ {"TLSv1.2", CURL_SSLVERSION_TLSv1_2}, ++#endif + #if LIBCURL_VERSION_NUM >= 0x073400 +- {"TLSv1.3", CURL_SSLVERSION_TLSv1_3}, ++ {"TLSv1.3", CURL_SSLVERSION_TLSv1_3}, + #endif +- {NULL, 0}}; ++ {NULL, 0}}; + +-static void ATTR_NONNULL() curlSetupCommon(wrkrInstanceData_t *const pWrkrData, CURL *const handle) { +- PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES); +- curl_easy_setopt(handle, CURLOPT_HTTPHEADER, pWrkrData->curlHeader); +- curl_easy_setopt(handle, CURLOPT_NOSIGNAL, TRUE); +- curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curlResult); +- curl_easy_setopt(handle, CURLOPT_WRITEDATA, pWrkrData); +- if (pWrkrData->pData->allowUnsignedCerts) curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, FALSE); +- if (pWrkrData->pData->skipVerifyHost) curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, FALSE); +- if (pWrkrData->pData->authBuf != NULL) { +- curl_easy_setopt(handle, CURLOPT_USERPWD, pWrkrData->pData->authBuf); +- curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); +- } +- if (pWrkrData->pData->caCertFile) curl_easy_setopt(handle, CURLOPT_CAINFO, pWrkrData->pData->caCertFile); +- if (pWrkrData->pData->myCertFile) curl_easy_setopt(handle, CURLOPT_SSLCERT, pWrkrData->pData->myCertFile); +- if (pWrkrData->pData->myPrivKeyFile) curl_easy_setopt(handle, CURLOPT_SSLKEY, pWrkrData->pData->myPrivKeyFile); +- if (pWrkrData->pData->tlsVersion) { ++static void ATTR_NONNULL() curlSetupTlsOptions(instanceData *const pData, CURL *const handle) { ++ if (pData->allowUnsignedCerts) curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L); ++ if (pData->skipVerifyHost) curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0L); ++ if (pData->caCertFile) curl_easy_setopt(handle, CURLOPT_CAINFO, pData->caCertFile); ++ if (pData->myCertFile) curl_easy_setopt(handle, CURLOPT_SSLCERT, pData->myCertFile); ++ if (pData->myPrivKeyFile) curl_easy_setopt(handle, CURLOPT_SSLKEY, pData->myPrivKeyFile); ++ if (pData->tlsVersion) { + long ver = CURL_SSLVERSION_DEFAULT; + for (size_t i = 0; tlsVersionMap[i].name != NULL; i++) { +- if (!strcmp((char *)pWrkrData->pData->tlsVersion, tlsVersionMap[i].name)) { ++ if (!strcmp((char *)pData->tlsVersion, tlsVersionMap[i].name)) { + ver = tlsVersionMap[i].curlver; + break; + } +@@ -2136,13 +2126,25 @@ + curl_easy_setopt(handle, CURLOPT_SSLVERSION, ver); + } + #if LIBCURL_VERSION_NUM >= 0x073D00 +- if (pWrkrData->pData->tlsCipherSuites) +- curl_easy_setopt(handle, CURLOPT_TLS13_CIPHERS, (char *)pWrkrData->pData->tlsCipherSuites); ++ if (pData->tlsCipherSuites) curl_easy_setopt(handle, CURLOPT_TLS13_CIPHERS, (char *)pData->tlsCipherSuites); + #endif + #if LIBCURL_VERSION_NUM >= 0x074900 +- if (pWrkrData->pData->tlsKeyExchangeGroups) +- curl_easy_setopt(handle, CURLOPT_SSL_EC_CURVES, (char *)pWrkrData->pData->tlsKeyExchangeGroups); ++ if (pData->tlsKeyExchangeGroups) ++ curl_easy_setopt(handle, CURLOPT_SSL_EC_CURVES, (char *)pData->tlsKeyExchangeGroups); + #endif ++} ++ ++static void ATTR_NONNULL() curlSetupCommon(wrkrInstanceData_t *const pWrkrData, CURL *const handle) { ++ PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES); ++ curl_easy_setopt(handle, CURLOPT_HTTPHEADER, pWrkrData->curlHeader); ++ curl_easy_setopt(handle, CURLOPT_NOSIGNAL, TRUE); ++ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curlResult); ++ curl_easy_setopt(handle, CURLOPT_WRITEDATA, pWrkrData); ++ curlSetupTlsOptions(pWrkrData->pData, handle); ++ if (pWrkrData->pData->authBuf != NULL) { ++ curl_easy_setopt(handle, CURLOPT_USERPWD, pWrkrData->pData->authBuf); ++ curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); ++ } + /* uncomment for in-dept debuggung: + curl_easy_setopt(handle, CURLOPT_VERBOSE, TRUE); */ + } diff --git a/omelasticsearch-pqc-tls.patch b/omelasticsearch-pqc-tls.patch new file mode 100644 index 0000000..1a9a9a7 --- /dev/null +++ b/omelasticsearch-pqc-tls.patch @@ -0,0 +1,153 @@ +From a3463c693ed89039cfc06616084eea2e67aca3fb Mon Sep 17 00:00:00 2001 +From: Cropi +Date: Wed, 24 Jun 2026 12:22:14 +0200 +Subject: [PATCH] omelasticsearch: add tls.tlsversion, tls.ciphersuites, + tls.keyexchangegroups + +Exposes three libcurl TLS knobs so operators can restrict the TLS version +floor and specify the cipher suite and key-exchange group preference list. +Setting tls.keyexchangegroups to "X25519MLKEM768:X25519" enables hybrid +PQC key exchange when libcurl is linked against OpenSSL 3.x with the OQS +provider. + +The TLS version string is validated at configuration time against a lookup +table; an unknown value causes an immediate config load failure rather than +being silently ignored. tls.ciphersuites and tls.keyexchangegroups are +passed verbatim to libcurl, which delegates validation to OpenSSL. + +CURLOPT_SSL_EC_CURVES (>= 7.73) and CURLOPT_TLS13_CIPHERS (>= 7.61) are +guarded with LIBCURL_VERSION_NUM so the build succeeds on older systems; +a runtime warning is emitted when an option is configured but the +build-time libcurl predates support for it. + +When all three parameters are absent the behaviour is unchanged. + +Signed-off-by: Cropi +--- + plugins/omelasticsearch/omelasticsearch.c | 65 +++++++++++++++++++++- + 1 file changed, 64 insertions(+), 1 deletion(-) + +--- a/plugins/omelasticsearch/omelasticsearch.c ++++ b/plugins/omelasticsearch/omelasticsearch.c +@@ -163,6 +163,9 @@ + uchar *caCertFile; + uchar *myCertFile; + uchar *myPrivKeyFile; ++ uchar *tlsVersion; /* tls.tlsversion → CURLOPT_SSLVERSION */ ++ uchar *tlsCipherSuites; /* tls.ciphersuites → CURLOPT_TLS13_CIPHERS */ ++ uchar *tlsKeyExchangeGroups; /* tls.keyexchangegroups → CURLOPT_SSL_EC_CURVES */ + es_write_ops_t writeOperation; + sbool retryFailures; + int ratelimitInterval; +@@ -237,6 +240,9 @@ + {"tls.cacert", eCmdHdlrString, 0}, + {"tls.mycert", eCmdHdlrString, 0}, + {"tls.myprivkey", eCmdHdlrString, 0}, ++ {"tls.tlsversion", eCmdHdlrString, 0}, ++ {"tls.ciphersuites", eCmdHdlrString, 0}, ++ {"tls.keyexchangegroups", eCmdHdlrString, 0}, + {"writeoperation", eCmdHdlrGetWord, 0}, + {"retryfailures", eCmdHdlrBinary, 0}, + {"ratelimit.interval", eCmdHdlrInt, 0}, +@@ -350,6 +356,9 @@ + free(pData->caCertFile); + free(pData->myCertFile); + free(pData->myPrivKeyFile); ++ free(pData->tlsVersion); ++ free(pData->tlsCipherSuites); ++ free(pData->tlsKeyExchangeGroups); + free(pData->retryRulesetName); + free(pData->detectedVersionString); + if (pData->ratelimiter != NULL) ratelimitDestruct(pData->ratelimiter); +@@ -2092,6 +2101,15 @@ + RETiRet; + } + ++static const struct { ++ const char *name; ++ long curlver; ++} tlsVersionMap[] = {{"TLSv1.2", CURL_SSLVERSION_TLSv1_2}, ++#if LIBCURL_VERSION_NUM >= 0x073400 ++ {"TLSv1.3", CURL_SSLVERSION_TLSv1_3}, ++#endif ++ {NULL, 0}}; ++ + static void ATTR_NONNULL() curlSetupCommon(wrkrInstanceData_t *const pWrkrData, CURL *const handle) { + PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES); + curl_easy_setopt(handle, CURLOPT_HTTPHEADER, pWrkrData->curlHeader); +@@ -2107,6 +2125,24 @@ + if (pWrkrData->pData->caCertFile) curl_easy_setopt(handle, CURLOPT_CAINFO, pWrkrData->pData->caCertFile); + if (pWrkrData->pData->myCertFile) curl_easy_setopt(handle, CURLOPT_SSLCERT, pWrkrData->pData->myCertFile); + if (pWrkrData->pData->myPrivKeyFile) curl_easy_setopt(handle, CURLOPT_SSLKEY, pWrkrData->pData->myPrivKeyFile); ++ if (pWrkrData->pData->tlsVersion) { ++ long ver = CURL_SSLVERSION_DEFAULT; ++ for (size_t i = 0; tlsVersionMap[i].name != NULL; i++) { ++ if (!strcmp((char *)pWrkrData->pData->tlsVersion, tlsVersionMap[i].name)) { ++ ver = tlsVersionMap[i].curlver; ++ break; ++ } ++ } ++ curl_easy_setopt(handle, CURLOPT_SSLVERSION, ver); ++ } ++#if LIBCURL_VERSION_NUM >= 0x073D00 ++ if (pWrkrData->pData->tlsCipherSuites) ++ curl_easy_setopt(handle, CURLOPT_TLS13_CIPHERS, (char *)pWrkrData->pData->tlsCipherSuites); ++#endif ++#if LIBCURL_VERSION_NUM >= 0x074900 ++ if (pWrkrData->pData->tlsKeyExchangeGroups) ++ curl_easy_setopt(handle, CURLOPT_SSL_EC_CURVES, (char *)pWrkrData->pData->tlsKeyExchangeGroups); ++#endif + /* uncomment for in-dept debuggung: + curl_easy_setopt(handle, CURLOPT_VERBOSE, TRUE); */ + } +@@ -2190,6 +2226,9 @@ + pData->caCertFile = NULL; + pData->myCertFile = NULL; + pData->myPrivKeyFile = NULL; ++ pData->tlsVersion = NULL; ++ pData->tlsCipherSuites = NULL; ++ pData->tlsKeyExchangeGroups = NULL; + pData->writeOperation = ES_WRITE_INDEX; + pData->retryFailures = 0; + pData->ratelimitBurst = -1; +@@ -2307,6 +2346,38 @@ + } else { + fclose(fp); + } ++ } else if (!strcmp(actpblk.descr[i].name, "tls.tlsversion")) { ++ char *ver; ++ int known; ++ CHKmalloc(ver = es_str2cstr(pvals[i].val.d.estr, NULL)); ++ known = 0; ++ for (size_t j = 0; tlsVersionMap[j].name != NULL; j++) { ++ if (!strcmp(ver, tlsVersionMap[j].name)) { ++ known = 1; ++ break; ++ } ++ } ++ if (!known) { ++ LogError(0, RS_RET_PARAM_ERROR, ++ "omelasticsearch: unknown tls.tlsversion '%s'; accepted: TLSv1.2, TLSv1.3", ver); ++ free(ver); ++ ABORT_FINALIZE(RS_RET_PARAM_ERROR); ++ } ++ pData->tlsVersion = (uchar *)ver; ++ } else if (!strcmp(actpblk.descr[i].name, "tls.ciphersuites")) { ++ CHKmalloc(pData->tlsCipherSuites = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); ++#if LIBCURL_VERSION_NUM < 0x073D00 ++ LogMsg(0, RS_RET_OK, LOG_WARNING, ++ "omelasticsearch: tls.ciphersuites set but libcurl < 7.61 was used at build time; " ++ "option will be ignored"); ++#endif ++ } else if (!strcmp(actpblk.descr[i].name, "tls.keyexchangegroups")) { ++ CHKmalloc(pData->tlsKeyExchangeGroups = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); ++#if LIBCURL_VERSION_NUM < 0x074900 ++ LogMsg(0, RS_RET_OK, LOG_WARNING, ++ "omelasticsearch: tls.keyexchangegroups set but libcurl < 7.73 was used at build time; " ++ "option will be ignored"); ++#endif + } else if (!strcmp(actpblk.descr[i].name, "writeoperation")) { + char *writeop = es_str2cstr(pvals[i].val.d.estr, NULL); + if (writeop && !strcmp(writeop, "create")) { +-- +2.54.0 diff --git a/rsyslog.spec b/rsyslog.spec index 573f6a6..750b02a 100644 --- a/rsyslog.spec +++ b/rsyslog.spec @@ -39,7 +39,7 @@ Summary: Enhanced system logging and kernel message trapping daemon Name: rsyslog Version: 8.2604.0 -Release: 2%{?dist} +Release: 3%{?dist} License: GPL-3.0-or-later AND Apache-2.0 URL: http://www.rsyslog.com/ Source0: http://www.rsyslog.com/files/download/rsyslog/%{name}-%{version}.tar.gz @@ -53,6 +53,8 @@ Source5: https://archive.apache.org/dist/qpid/proton/%{qpid_proton_v}/qpid-proto Source7: rsyslog-tmpfiles.conf Patch0: imfile-inotify-fd-release-on-delete.patch +Patch1: omelasticsearch-pqc-tls.patch +Patch2: omelasticsearch-apply-tls-opts-during-detection.patch BuildRequires: make BuildRequires: gcc @@ -388,6 +390,8 @@ This module allows rsyslog to send messages to a RabbitMQ server. # set up rsyslog sources %setup -q -D %patch -P0 -p1 +%patch -P1 -p1 +%patch -P2 -p1 %if %{with omamqp1} @@ -783,6 +787,15 @@ done %changelog +* Thu Jul 09 2026 Attila Lakatos - 8.2604.0-3 +- Backport omelasticsearch PQC TLS parameters (tls.tlsversion, tls.ciphersuites, +<<<<<<< HEAD + tls.keyexchangegroups) +======= + tls.keyexchangegroups) and apply them during startup version detection +>>>>>>> dad7741 (omelasticsearch: apply TLS options during startup detection) + Resolves: RHEL-193505 + * Wed Apr 29 2026 Attila Lakatos - 8.2604.0-2 - Rebase to 8.2604.0 Resolves: RHEL-140910