[Pkg-nagios-devel] Bug#1106714: unblock: icinga2/2.14.6-1

Bas Couwenberg sebastic at xs4all.nl
Wed May 28 12:04:00 BST 2025


Package: release.debian.org
Severity: normal
X-Debbugs-Cc: icinga2 at packages.debian.org
Control: affects -1 + src:icinga2
User: release.debian.org at packages.debian.org
Usertags: unblock

Please unblock package icinga2

[ Reason ]
Fixes CVE-2025-48057.

[ Impact ]
Unfixed security issue.

[ Tests ]
Upstream test suite.

[ Risks ]
Low, we're not building with OpenSSL < 1.1.0.

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing

[ Other info ]
N/A

unblock icinga2/2.14.6-1


Kind Regards,

Bas
-------------- next part --------------
diff -Nru icinga2-2.14.5/CHANGELOG.md icinga2-2.14.6/CHANGELOG.md
--- icinga2-2.14.5/CHANGELOG.md	2025-02-05 15:12:30.000000000 +0100
+++ icinga2-2.14.6/CHANGELOG.md	2025-05-21 12:31:48.000000000 +0200
@@ -7,6 +7,19 @@
 
 Released closed milestones can be found on [GitHub](https://github.com/Icinga/icinga2/milestones?state=closed).
 
+## 2.14.6 (2025-05-27)
+
+This security release fixes a critical issue in the certificate renewal logic in Icinga 2, which
+might incorrectly renew an invalid certificate. However, only nodes with access to the Icinga CA
+private key running with OpenSSL older than version 1.1.0 (released in 2016) are vulnerable. So this
+typically affects Icinga 2 masters running on operating systems like RHEL 7 and Amazon Linux 2.
+
+* CVE-2025-48057: Prevent invalid certificates from being renewed with OpenSSL older than v1.1.0.
+* Fix use-after-free in VerifyCertificate(): Additionally, a use-after-free was found in the same
+  function which is fixed as well, but in case it is triggered, typically only a wrong error code
+  may be shown in a log message.
+* Windows: Update OpenSSL shipped on Windows to v3.0.16.
+
 ## 2.14.5 (2025-02-06)
 
 This release fixes a regression introduced in 2.14.4 that caused the `icinga2 node setup`,
diff -Nru icinga2-2.14.5/debian/changelog icinga2-2.14.6/debian/changelog
--- icinga2-2.14.5/debian/changelog	2025-02-06 05:45:24.000000000 +0100
+++ icinga2-2.14.6/debian/changelog	2025-05-28 12:47:15.000000000 +0200
@@ -1,3 +1,12 @@
+icinga2 (2.14.6-1) unstable; urgency=high
+
+  * Team upload.
+  * New upstream release.
+    Fixes CVE-2025-48057.
+  * Bump Standards-Version to 4.7.2, no changes.
+
+ -- Bas Couwenberg <sebastic at debian.org>  Wed, 28 May 2025 12:47:15 +0200
+
 icinga2 (2.14.5-1) unstable; urgency=medium
 
   * Team upload.
diff -Nru icinga2-2.14.5/debian/control icinga2-2.14.6/debian/control
--- icinga2-2.14.5/debian/control	2024-11-15 17:29:56.000000000 +0100
+++ icinga2-2.14.6/debian/control	2025-03-20 12:04:25.000000000 +0100
@@ -31,7 +31,7 @@
                pkgconf,
                po-debconf,
                tzdata
-Standards-Version: 4.7.0
+Standards-Version: 4.7.2
 Vcs-Browser: https://salsa.debian.org/nagios-team/icinga2
 Vcs-Git: https://salsa.debian.org/nagios-team/icinga2.git
 Homepage: https://icinga.com
diff -Nru icinga2-2.14.5/doc/win-dev.ps1 icinga2-2.14.6/doc/win-dev.ps1
--- icinga2-2.14.5/doc/win-dev.ps1	2025-02-05 15:12:30.000000000 +0100
+++ icinga2-2.14.6/doc/win-dev.ps1	2025-05-21 12:31:48.000000000 +0200
@@ -14,7 +14,7 @@
 $VsVersion = 2019
 $MsvcVersion = '14.2'
 $BoostVersion = @(1, 86, 0)
-$OpensslVersion = '3_0_15'
+$OpensslVersion = '3_0_16'
 
 switch ($Env:BITS) {
 	32 { }
diff -Nru icinga2-2.14.5/.github/workflows/linux.bash icinga2-2.14.6/.github/workflows/linux.bash
--- icinga2-2.14.5/.github/workflows/linux.bash	2025-02-05 15:12:30.000000000 +0100
+++ icinga2-2.14.6/.github/workflows/linux.bash	2025-05-21 12:31:48.000000000 +0200
@@ -30,7 +30,7 @@
 
   amazonlinux:20*)
     dnf install -y bison cmake flex gcc-c++ ninja-build \
-      {boost,libedit,mariadb1\*,ncurses,openssl,postgresql,systemd}-devel
+      {boost,libedit,mariadb-connector-c,ncurses,openssl,postgresql,systemd}-devel
     ;;
 
   debian:*|ubuntu:*)
diff -Nru icinga2-2.14.5/ICINGA2_VERSION icinga2-2.14.6/ICINGA2_VERSION
--- icinga2-2.14.5/ICINGA2_VERSION	2025-02-05 15:12:30.000000000 +0100
+++ icinga2-2.14.6/ICINGA2_VERSION	2025-05-21 12:31:48.000000000 +0200
@@ -1,2 +1,2 @@
-Version: 2.14.5
+Version: 2.14.6
 Revision: 1
diff -Nru icinga2-2.14.5/lib/base/tlsutility.cpp icinga2-2.14.6/lib/base/tlsutility.cpp
--- icinga2-2.14.5/lib/base/tlsutility.cpp	2025-02-05 15:12:30.000000000 +0100
+++ icinga2-2.14.6/lib/base/tlsutility.cpp	2025-05-21 12:31:48.000000000 +0200
@@ -983,27 +983,47 @@
 
 bool VerifyCertificate(const std::shared_ptr<X509> &caCertificate, const std::shared_ptr<X509> &certificate, const String& crlFile)
 {
-	X509_STORE *store = X509_STORE_new();
+	return VerifyCertificate(caCertificate.get(), certificate.get(), crlFile);
+}
+
+bool VerifyCertificate(X509* caCertificate, X509* certificate, const String& crlFile)
+{
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+	/*
+	 * OpenSSL older than version 1.1.0 stored a valid flag in the struct behind X509* which leads to certain validation
+	 * steps to be skipped on subsequent verification operations. If a certificate is verified multiple times with a
+	 * different configuration, for example with different trust anchors, this can result in the certificate
+	 * incorrectly being treated as valid.
+	 *
+	 * This issue is worked around by serializing and deserializing the certificate which creates a new struct instance
+	 * with the valid flag cleared, hence performing the full validation.
+	 *
+	 * The flag in question was removed in OpenSSL 1.1.0, so this extra step isn't necessary for more recent versions:
+	 * https://github.com/openssl/openssl/commit/0e76014e584ba78ef1d6ecb4572391ef61c4fb51
+	 */
+	std::shared_ptr<X509> copy = StringToCertificate(CertificateToString(certificate));
+	VERIFY(copy.get() != certificate);
+	certificate = copy.get();
+#endif
+
+	std::unique_ptr<X509_STORE, decltype(&X509_STORE_free)> store{X509_STORE_new(), &X509_STORE_free};
 
 	if (!store)
 		return false;
 
-	X509_STORE_add_cert(store, caCertificate.get());
+	X509_STORE_add_cert(store.get(), caCertificate);
 
 	if (!crlFile.IsEmpty()) {
-		AddCRLToSSLContext(store, crlFile);
+		AddCRLToSSLContext(store.get(), crlFile);
 	}
 
-	X509_STORE_CTX *csc = X509_STORE_CTX_new();
-	X509_STORE_CTX_init(csc, store, certificate.get(), nullptr);
-
-	int rc = X509_verify_cert(csc);
+	std::unique_ptr<X509_STORE_CTX, decltype(&X509_STORE_CTX_free)> csc{X509_STORE_CTX_new(), &X509_STORE_CTX_free};
+	X509_STORE_CTX_init(csc.get(), store.get(), certificate, nullptr);
 
-	X509_STORE_CTX_free(csc);
-	X509_STORE_free(store);
+	int rc = X509_verify_cert(csc.get());
 
 	if (rc == 0) {
-		int err = X509_STORE_CTX_get_error(csc);
+		int err = X509_STORE_CTX_get_error(csc.get());
 
 		BOOST_THROW_EXCEPTION(openssl_error()
 			<< boost::errinfo_api_function("X509_verify_cert")
diff -Nru icinga2-2.14.5/lib/base/tlsutility.hpp icinga2-2.14.6/lib/base/tlsutility.hpp
--- icinga2-2.14.5/lib/base/tlsutility.hpp	2025-02-05 15:12:30.000000000 +0100
+++ icinga2-2.14.6/lib/base/tlsutility.hpp	2025-05-21 12:31:48.000000000 +0200
@@ -79,6 +79,7 @@
 String BinaryToHex(const unsigned char* data, size_t length);
 
 bool VerifyCertificate(const std::shared_ptr<X509>& caCertificate, const std::shared_ptr<X509>& certificate, const String& crlFile);
+bool VerifyCertificate(X509* caCertificate, X509* certificate, const String& crlFile);
 bool IsCa(const std::shared_ptr<X509>& cacert);
 int GetCertificateVersion(const std::shared_ptr<X509>& cert);
 String GetSignatureAlgorithm(const std::shared_ptr<X509>& cert);
diff -Nru icinga2-2.14.5/test/base-tlsutility.cpp icinga2-2.14.6/test/base-tlsutility.cpp
--- icinga2-2.14.5/test/base-tlsutility.cpp	2025-02-05 15:12:30.000000000 +0100
+++ icinga2-2.14.6/test/base-tlsutility.cpp	2025-05-21 12:31:48.000000000 +0200
@@ -132,4 +132,24 @@
 	})));
 }
 
+BOOST_AUTO_TEST_CASE(VerifyCertificate_revalidate)
+{
+	X509_NAME *caSubject = X509_NAME_new();
+	X509_NAME_add_entry_by_txt(caSubject, "CN", MBSTRING_ASC, (const unsigned char*)"Icinga CA", -1, -1, 0);
+
+	auto signingCaKey = GenKeypair();
+	auto signingCaCert = CreateCert(signingCaKey, caSubject, caSubject, signingCaKey, true);
+
+	X509_NAME *leafSubject = X509_NAME_new();
+	X509_NAME_add_entry_by_txt(leafSubject, "CN", MBSTRING_ASC, (const unsigned char*)"Leaf Certificate", -1, -1, 0);
+	auto leafKey = GenKeypair();
+	auto leafCert = CreateCert(leafKey, leafSubject, caSubject, signingCaKey, false);
+	BOOST_CHECK(VerifyCertificate(signingCaCert, leafCert, ""));
+
+	// Create a second CA with a different key, the leaf certificate is supposed to fail validation against that CA.
+	auto otherCaKey = GenKeypair();
+	auto otherCaCert = CreateCert(otherCaKey, caSubject, caSubject, otherCaKey, true);
+	BOOST_CHECK_THROW(VerifyCertificate(otherCaCert, leafCert, ""), openssl_error);
+}
+
 BOOST_AUTO_TEST_SUITE_END()
diff -Nru icinga2-2.14.5/test/CMakeLists.txt icinga2-2.14.6/test/CMakeLists.txt
--- icinga2-2.14.5/test/CMakeLists.txt	2025-02-05 15:12:30.000000000 +0100
+++ icinga2-2.14.6/test/CMakeLists.txt	2025-05-21 12:31:48.000000000 +0200
@@ -123,6 +123,7 @@
     base_tlsutility/iscertuptodate_ok
     base_tlsutility/iscertuptodate_expiring
     base_tlsutility/iscertuptodate_old
+    base_tlsutility/VerifyCertificate_revalidate
     base_type/gettype
     base_type/assign
     base_type/byname
diff -Nru icinga2-2.14.5/tools/win32/configure.ps1 icinga2-2.14.6/tools/win32/configure.ps1
--- icinga2-2.14.5/tools/win32/configure.ps1	2025-02-05 15:12:30.000000000 +0100
+++ icinga2-2.14.6/tools/win32/configure.ps1	2025-05-21 12:31:48.000000000 +0200
@@ -33,7 +33,7 @@
   $env:CMAKE_ARGS = '[]'
 }
 if (-not (Test-Path env:OPENSSL_ROOT_DIR)) {
-  $env:OPENSSL_ROOT_DIR = "c:\local\OpenSSL_3_0_15-Win${env:BITS}"
+  $env:OPENSSL_ROOT_DIR = "c:\local\OpenSSL_3_0_16-Win${env:BITS}"
 }
 if (-not (Test-Path env:BOOST_ROOT)) {
   $env:BOOST_ROOT = "c:\local\boost_1_86_0-Win${env:BITS}"


More information about the Pkg-nagios-devel mailing list