Compare commits

..

1 Commits

Author SHA1 Message Date
AlmaLinux RelEng Bot
e91f8e8452 import CS tomcat9-9.0.110-2.el10 2026-04-14 05:59:35 -04:00
10 changed files with 56 additions and 429 deletions

View File

@ -1 +0,0 @@
1

10
.gitignore vendored
View File

@ -1,9 +1 @@
results_tomcat9
*.rpm
/tomcat-9.0.87.redhat-*-src.zip
/apache-tomcat-9*-src.tar.gz
apache-tomcat-*-src
/tomcat9.iml
/.idea/.gitignore
/.idea/modules.xml
/.idea/vcs.xml
apache-tomcat-9.0.110-src.tar.gz

1
ci.fmf
View File

@ -1 +0,0 @@
resultsdb-testcase: separate

View File

@ -1,6 +0,0 @@
--- !Policy
product_versions:
- rhel-10
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: osci.brew-build./plans/tier1-internal.functional}

View File

@ -1,9 +0,0 @@
summary: Basic smoke test
prepare:
- name: packages
how: install
package:
- tomcat9
execute:
how: tmt
script: which tomcat

View File

@ -1,11 +0,0 @@
summary: Internal Tier1 beakerlib tests.
discover:
- name: rhel
how: fmf
url: git://pkgs.devel.redhat.com/tests/tomcat9
filter: 'tier: 1'
execute:
how: tmt
adjust:
enabled: false
when: distro == centos-stream-10

46
rhel-158962.patch Normal file
View File

@ -0,0 +1,46 @@
From 93fc51176bbcf643a46cc271b85ff49cbb01f1a6 Mon Sep 17 00:00:00 2001
From: remm <remm@apache.org>
Date: Wed, 3 Dec 2025 21:22:54 +0100
Subject: [PATCH] Avoid possible NPEs when using a TLS enabled custom connector
---
.../org/apache/tomcat/util/net/AbstractJsseEndpoint.java | 9 +++++++++
webapps/docs/changelog.xml | 7 +++++++
2 files changed, 16 insertions(+)
diff --git a/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java b/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java
index 1d639176eb17..9a4b8fa37fb5 100644
--- a/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java
+++ b/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java
@@ -127,8 +127,17 @@ protected void createSSLContext(SSLHostConfig sslHostConfig) throws IllegalArgum
protected SSLEngine createSSLEngine(String sniHostName, List<Cipher> clientRequestedCiphers,
List<String> clientRequestedApplicationProtocols) {
List<String> clientRequestedProtocols = clientRequestedProtocolsThreadLocal.get();
+ if (clientRequestedProtocols == null) {
+ clientRequestedProtocols = new ArrayList<String>();
+ }
List<Group> clientSupportedGroups = clientSupportedGroupsThreadLocal.get();
+ if (clientSupportedGroups == null) {
+ clientSupportedGroups = new ArrayList<Group>();
+ }
List<SignatureScheme> clientSignatureSchemes = clientSignatureSchemesThreadLocal.get();
+ if (clientSignatureSchemes == null) {
+ clientSignatureSchemes = new ArrayList<SignatureScheme>();
+ }
SSLHostConfig sslHostConfig = getSSLHostConfig(sniHostName);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 9ef3d9b04912..03be8d1358ae 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -155,6 +155,9 @@
Store HTTP request headers using the original case for the header name
rather than forcing it to lower case. (markt)
</fix>
+ <fix>
+ Avoid possible NPEs when using a TLS enabled custom connector. (remm)
+ </fix>
</changelog>
</subsection>
<subsection name="Cluster">

View File

@ -1,346 +0,0 @@
diff --git a/java/org/apache/catalina/storeconfig/LocalStrings.properties b/java/org/apache/catalina/storeconfig/LocalStrings.properties
index d3e8585df5..4c2aa53bee 100644
--- a/java/org/apache/catalina/storeconfig/LocalStrings.properties
+++ b/java/org/apache/catalina/storeconfig/LocalStrings.properties
@@ -28,8 +28,11 @@ factory.storeTag=store tag [{0}] ( Object: [{1}] )
globalNamingResourcesSF.noFactory=Cannot find NamingResources store factory
globalNamingResourcesSF.wrongElement=Wrong element [{0}]
+registry.interfacesLoaded=Loaded [{0}] interface classes for registry
registry.loadClassFailed=Failed to load class [{0}]
registry.noDescriptor=Can't find descriptor for key [{0}]
+registry.optionalClassLoaded=Loaded optional class [{0}]
+registry.optionalClassNotFound=Optional class [{0}] not found, skipping
standardContextSF.cannotWriteFile=Cannot write file at [{0}]
standardContextSF.canonicalPathError=Failed to obtain the canonical path of the configuration file [{0}]
diff --git a/java/org/apache/catalina/storeconfig/StandardEngineSF.java b/java/org/apache/catalina/storeconfig/StandardEngineSF.java
index 0f600ee5c1..b6bd5d7168 100644
--- a/java/org/apache/catalina/storeconfig/StandardEngineSF.java
+++ b/java/org/apache/catalina/storeconfig/StandardEngineSF.java
@@ -26,13 +26,23 @@ import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Realm;
import org.apache.catalina.Valve;
import org.apache.catalina.core.StandardEngine;
-import org.apache.catalina.ha.ClusterValve;
/**
* Store server.xml Element Engine
*/
public class StandardEngineSF extends StoreFactoryBase {
+ private static final Class<?> clusterValveClass;
+ static {
+ Class<?> clazz = null;
+ try {
+ clazz = Class.forName("org.apache.catalina.ha.ClusterValve");
+ } catch (ClassNotFoundException e) {
+ // Expected when clustering JARs are not present
+ }
+ clusterValveClass = clazz;
+ }
+
/**
* Store the specified Engine properties.
* <p>
@@ -64,7 +74,7 @@ public class StandardEngineSF extends StoreFactoryBase {
if (valves != null && valves.length > 0) {
List<Valve> engineValves = new ArrayList<>();
for (Valve valve : valves) {
- if (!(valve instanceof ClusterValve)) {
+ if (clusterValveClass == null || !clusterValveClass.isInstance(valve)) {
engineValves.add(valve);
}
}
diff --git a/java/org/apache/catalina/storeconfig/StandardHostSF.java b/java/org/apache/catalina/storeconfig/StandardHostSF.java
index 60d473982b..1e8f2d3a58 100644
--- a/java/org/apache/catalina/storeconfig/StandardHostSF.java
+++ b/java/org/apache/catalina/storeconfig/StandardHostSF.java
@@ -26,13 +26,23 @@ import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Realm;
import org.apache.catalina.Valve;
import org.apache.catalina.core.StandardHost;
-import org.apache.catalina.ha.ClusterValve;
/**
* Store server.xml Element Host
*/
public class StandardHostSF extends StoreFactoryBase {
+ private static final Class<?> clusterValveClass;
+ static {
+ Class<?> clazz = null;
+ try {
+ clazz = Class.forName("org.apache.catalina.ha.ClusterValve");
+ } catch (ClassNotFoundException e) {
+ // Expected when clustering JARs are not present
+ }
+ clusterValveClass = clazz;
+ }
+
/**
* Store the specified Host properties and children (Listener,Alias,Realm,Valve,Cluster, Context)
* <p>
@@ -68,7 +78,7 @@ public class StandardHostSF extends StoreFactoryBase {
if (valves != null && valves.length > 0) {
List<Valve> hostValves = new ArrayList<>();
for (Valve valve : valves) {
- if (!(valve instanceof ClusterValve)) {
+ if (clusterValveClass == null || !clusterValveClass.isInstance(valve)) {
hostValves.add(valve);
}
}
diff --git a/java/org/apache/catalina/storeconfig/StoreRegistry.java b/java/org/apache/catalina/storeconfig/StoreRegistry.java
index c17dd3817e..ee803abe36 100644
--- a/java/org/apache/catalina/storeconfig/StoreRegistry.java
+++ b/java/org/apache/catalina/storeconfig/StoreRegistry.java
@@ -16,7 +16,9 @@
*/
package org.apache.catalina.storeconfig;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import javax.naming.directory.DirContext;
@@ -28,17 +30,6 @@ import org.apache.catalina.Realm;
import org.apache.catalina.Valve;
import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.WebResourceSet;
-import org.apache.catalina.ha.CatalinaCluster;
-import org.apache.catalina.ha.ClusterDeployer;
-import org.apache.catalina.ha.ClusterListener;
-import org.apache.catalina.tribes.Channel;
-import org.apache.catalina.tribes.ChannelInterceptor;
-import org.apache.catalina.tribes.ChannelReceiver;
-import org.apache.catalina.tribes.ChannelSender;
-import org.apache.catalina.tribes.Member;
-import org.apache.catalina.tribes.MembershipService;
-import org.apache.catalina.tribes.MessageListener;
-import org.apache.catalina.tribes.transport.DataSender;
import org.apache.coyote.UpgradeProtocol;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
@@ -61,11 +52,74 @@ public class StoreRegistry {
private String version;
// Access Information
- private static final Class<?>[] interfaces = { CatalinaCluster.class, ChannelSender.class, ChannelReceiver.class,
- Channel.class, MembershipService.class, ClusterDeployer.class, Realm.class, Manager.class, DirContext.class,
- LifecycleListener.class, Valve.class, ClusterListener.class, MessageListener.class, DataSender.class,
- ChannelInterceptor.class, Member.class, WebResourceRoot.class, WebResourceSet.class,
- CredentialHandler.class, UpgradeProtocol.class, CookieProcessor.class };
+ // Lazily initialized to gracefully handle optional features like clustering
+ private static volatile Class<?>[] interfaces = null;
+
+ /**
+ * Initialize the interfaces array with all available classes.
+ * Uses dynamic loading for optional classes (e.g., clustering) to avoid
+ * ClassNotFoundException when those JARs are not present. This approach
+ * is consistent with how Catalina.addClusterRuleSet() handles clustering.
+ */
+ private static Class<?>[] getInterfaces() {
+ if (interfaces == null) {
+ synchronized (StoreRegistry.class) {
+ if (interfaces == null) {
+ // Required interfaces - always present
+ List<Class<?>> list = new ArrayList<>();
+ list.add(Realm.class);
+ list.add(Manager.class);
+ list.add(DirContext.class);
+ list.add(LifecycleListener.class);
+ list.add(Valve.class);
+ list.add(WebResourceRoot.class);
+ list.add(WebResourceSet.class);
+ list.add(CredentialHandler.class);
+ list.add(UpgradeProtocol.class);
+ list.add(CookieProcessor.class);
+
+ // Optional clustering interfaces - load dynamically to support
+ // deployments where clustering JARs may not be present
+ tryAddClass(list, "org.apache.catalina.ha.CatalinaCluster");
+ tryAddClass(list, "org.apache.catalina.tribes.ChannelSender");
+ tryAddClass(list, "org.apache.catalina.tribes.ChannelReceiver");
+ tryAddClass(list, "org.apache.catalina.tribes.Channel");
+ tryAddClass(list, "org.apache.catalina.tribes.MembershipService");
+ tryAddClass(list, "org.apache.catalina.ha.ClusterDeployer");
+ tryAddClass(list, "org.apache.catalina.ha.ClusterListener");
+ tryAddClass(list, "org.apache.catalina.tribes.MessageListener");
+ tryAddClass(list, "org.apache.catalina.tribes.transport.DataSender");
+ tryAddClass(list, "org.apache.catalina.tribes.ChannelInterceptor");
+ tryAddClass(list, "org.apache.catalina.tribes.Member");
+
+ interfaces = list.toArray(new Class<?>[0]);
+
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("registry.interfacesLoaded", Integer.valueOf(interfaces.length)));
+ }
+ }
+ }
+ }
+ return interfaces;
+ }
+
+ /**
+ * Try to load a class by name and add it to the list if successful.
+ * Logs at TRACE level if the class is not available.
+ */
+ private static void tryAddClass(List<Class<?>> list, String className) {
+ try {
+ Class<?> clazz = Class.forName(className, false, StoreRegistry.class.getClassLoader());
+ list.add(clazz);
+ if (log.isTraceEnabled()) {
+ log.trace(sm.getString("registry.optionalClassLoaded", className));
+ }
+ } catch (ClassNotFoundException | NoClassDefFoundError e) {
+ if (log.isTraceEnabled()) {
+ log.trace(sm.getString("registry.optionalClassNotFound", className));
+ }
+ }
+ }
/**
* @return the name
@@ -116,9 +170,10 @@ public class StoreRegistry {
}
if (aClass != null) {
desc = descriptors.get(aClass.getName());
- for (int i = 0; desc == null && i < interfaces.length; i++) {
- if (interfaces[i].isAssignableFrom(aClass)) {
- desc = descriptors.get(interfaces[i].getName());
+ Class<?>[] availableInterfaces = getInterfaces();
+ for (int i = 0; desc == null && i < availableInterfaces.length; i++) {
+ if (availableInterfaces[i].isAssignableFrom(aClass)) {
+ desc = descriptors.get(availableInterfaces[i].getName());
}
}
}
diff --git a/test/org/apache/catalina/storeconfig/TestStoreRegistry.java b/test/org/apache/catalina/storeconfig/TestStoreRegistry.java
new file mode 100644
index 0000000000..e6869d3642
--- /dev/null
+++ b/test/org/apache/catalina/storeconfig/TestStoreRegistry.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.storeconfig;
+
+import java.lang.reflect.Method;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.catalina.Manager;
+import org.apache.catalina.Realm;
+import org.apache.catalina.Valve;
+
+/**
+ * Test StoreRegistry behavior, particularly dynamic loading of optional classes like clustering.
+ *
+ * Verifies StoreRegistry uses the same dynamic loading pattern.
+ */
+public class TestStoreRegistry {
+
+ /**
+ * Test that clustering classes are dynamically loaded like other Tomcat components.
+ *
+ * StoreRegistry should initialize successfully whether clustering is available or not.
+ * This matches the pattern used in Catalina.addClusterRuleSet().
+ */
+ @Test
+ public void testClusteringClassesOptional() throws Exception {
+ // Verify StoreRegistry initializes successfully with dynamic class loading
+ StoreRegistry registry = new StoreRegistry();
+ Assert.assertNotNull("Registry should initialize with dynamic loading", registry);
+
+ // Trigger lazy loading of interfaces array
+ Method getInterfacesMethod = StoreRegistry.class.getDeclaredMethod("getInterfaces");
+ getInterfacesMethod.setAccessible(true);
+
+ Class<?>[] interfaces = (Class<?>[]) getInterfacesMethod.invoke(null);
+ Assert.assertNotNull("Interfaces should load dynamically", interfaces);
+
+ // Test passes if we get here without ClassNotFoundException.
+ // The actual number of interfaces loaded depends on whether clustering is available,
+ // but we should always have at least the core 10 interfaces.
+ Assert.assertTrue("Should have at least 10 core interfaces",
+ interfaces.length >= 10);
+
+ // Verify required core interfaces are always present
+ boolean hasRealm = false;
+ boolean hasManager = false;
+ boolean hasValve = false;
+
+ for (Class<?> iface : interfaces) {
+ if (iface.equals(Realm.class)) {
+ hasRealm = true;
+ }
+ if (iface.equals(Manager.class)) {
+ hasManager = true;
+ }
+ if (iface.equals(Valve.class)) {
+ hasValve = true;
+ }
+ }
+
+ Assert.assertTrue("Should contain Realm interface", hasRealm);
+ Assert.assertTrue("Should contain Manager interface", hasManager);
+ Assert.assertTrue("Should contain Valve interface", hasValve);
+ }
+
+ /**
+ * Test that findDescription works with interface inheritance and
+ * dynamically loaded interfaces.
+ */
+ @Test
+ public void testFindDescriptionWithDynamicInterfaces() throws Exception {
+ StoreRegistry registry = new StoreRegistry();
+
+ // Register a description for the Valve interface
+ StoreDescription valveDesc = new StoreDescription();
+ valveDesc.setId(Valve.class.getName());
+ valveDesc.setTag("Valve");
+ valveDesc.setTagClass(Valve.class.getName());
+ registry.registerDescription(valveDesc);
+
+ // AccessLogValve implements Valve interface - should find via dynamic interface matching
+ String accessLogValveClass = "org.apache.catalina.valves.AccessLogValve";
+ StoreDescription foundDesc = registry.findDescription(accessLogValveClass);
+
+ Assert.assertNotNull("Should find description via interface matching", foundDesc);
+ Assert.assertEquals("Should match Valve descriptor", "Valve", foundDesc.getTag());
+ }
+}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 808165f044..792dad2fa4 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -113,6 +113,13 @@
in RFC 9110 that hash functions used to generate strong ETags should be
collision resistant. (markt)
</update>
+ <fix>
+ Update <code>StoreRegistry</code> to dynamically load optional clustering
+ classes rather than statically referencing them. This matches the pattern
+ used in <code>Catalina.addClusterRuleSet()</code> and prevents
+ <code>NoClassDefFoundError</code> when <code>StoreConfigLifecycleListener</code>
+ is configured but clustering classes are not available. (csutherl)
+ </fix>
<fix>
Correct a regression in the fix for <bug>69781</bug> that broke
<code>FileStore</code>. (markt)

View File

@ -1 +1 @@
SHA512 (apache-tomcat-9.0.117-src.tar.gz) = f40854a6ed1f208ccdd3da82527fc806eb9231aebaee86d6987e9699d1d31bb548765241424368708b89bdce01d4558a638532a35932f686d3edabd26951041d
SHA512 (apache-tomcat-9.0.110-src.tar.gz) = a8fe2c59a801d6fb16ea74019c6fc58c34543d4d25a16d64e929e67c7736f6e16d08ec2061b37f1783ebfa0b1dacfff991e46ed5d24d89300a140cb94449f570

View File

@ -31,7 +31,7 @@
%global jspspec 2.3
%global major_version 9
%global minor_version 0
%global micro_version 117
%global micro_version 110
%global packdname apache-tomcat-%{major_version}.%{minor_version}.%{micro_version}-src
%global servletspec 4.0
%global elspec 3.0
@ -78,7 +78,7 @@ Patch3: tomcat-%{major_version}.%{minor_version}-catalina-policy.patch
Patch4: rhbz-1857043.patch
Patch6: tomcat-%{major_version}.%{minor_version}-bnd-annotation.patch
Patch7: build-with-java-25.patch
Patch8: rhel-168577.patch
Patch8: rhel-158962.patch
BuildArch: noarch
@ -223,9 +223,6 @@ find . -type f \( -name "*.bat" -o -name "*.class" -o -name Thumbs.db -o -name "
%mvn_alias "org.apache.tomcat:tomcat-jsp-api" "org.eclipse.jetty.orbit:javax.servlet.jsp"
%mvn_package ":tomcat-servlet-api" tomcat-servlet-api
%pom_remove_dep org.apache.tomcat:tomcat-tribes res/maven/tomcat-storeconfig.pom
%pom_remove_dep org.apache.tomcat:tomcat-catalina-ha res/maven/tomcat-storeconfig.pom
%build
export OPT_JAR_LIST="xalan-j2-serializer"
@ -297,10 +294,6 @@ pushd output/build
%{__cp} -a webapps/* ${RPM_BUILD_ROOT}%{appdir}
popd
# Clustering is unsupported in RHEL
rm -f ${RPM_BUILD_ROOT}%{libdir}/catalina-ha.jar
rm -f ${RPM_BUILD_ROOT}%{libdir}/catalina-tribes.jar
%{__sed} -e "s|\@\@\@TCHOME\@\@\@|%{homedir}|g" \
-e "s|\@\@\@TCTEMP\@\@\@|%{tempdir}|g" \
-e "s|\@\@\@LIBDIR\@\@\@|%{_libdir}|g" %{SOURCE1} \
@ -403,6 +396,9 @@ popd
%mvn_file org.apache.tomcat:tomcat-catalina-ant tomcat/catalina-ant
%mvn_artifact res/maven/tomcat-catalina-ant.pom ${RPM_BUILD_ROOT}%{libdir}/catalina-ant.jar
%mvn_file org.apache.tomcat:tomcat-catalina-ha tomcat/catalina-ha
%mvn_artifact res/maven/tomcat-catalina-ha.pom ${RPM_BUILD_ROOT}%{libdir}/catalina-ha.jar
%mvn_file org.apache.tomcat:tomcat-catalina tomcat/catalina
%mvn_artifact res/maven/tomcat-catalina.pom ${RPM_BUILD_ROOT}%{libdir}/catalina.jar
@ -466,6 +462,9 @@ popd
%mvn_file org.apache.tomcat:tomcat-storeconfig tomcat/catalina-storeconfig
%mvn_artifact res/maven/tomcat-storeconfig.pom ${RPM_BUILD_ROOT}%{libdir}/catalina-storeconfig.jar
%mvn_file org.apache.tomcat:tomcat-tribes tomcat/catalina-tribes
%mvn_artifact res/maven/tomcat-tribes.pom ${RPM_BUILD_ROOT}%{libdir}/catalina-tribes.jar
%mvn_file org.apache.tomcat:tomcat-util-scan tomcat/tomcat-util-scan
%mvn_artifact res/maven/tomcat-util-scan.pom ${RPM_BUILD_ROOT}%{libdir}/tomcat-util-scan.jar
@ -635,42 +634,6 @@ fi
%{appdir}/ROOT
%changelog
* Wed Jun 17 2026 Pietro Meloni <pmeloni@redhat.com> - 1:9.0.117-2
- Resolves: RHEL-185571 Remove tomcat clustering JAR from RPM builds
* Thu May 29 2026 Pietro Meloni <pmeloni@redhat.com> - 1:9.0.117-1
- Resolves: RHEL-150720
Tomcat: Certificate revocation bypass due to improper OCSP response validation (CVE-2026-24734)
- Resolves:
Tomcat: OCSP checks sometimes soft-fail with FFM even when soft-fail is disabled (CVE-2026-34500)
- Resolves:
Tomcat: Cloud membership for clustering component exposed the Kubernetes bearer token (CVE-2026-34487)
- Resolves:
Tomcat: The fix for CVE-2026-29146 allowed the bypass of the EncryptInterceptor (CVE-2026-34486)
- Resolves:
Tomcat: Incomplete escaping of JSON access logs (CVE-2026-34483)
- Resolves:
Tomcat: The fix for CVE-2025-66614 was incomplete (CVE-2026-32990)
- Resolves:
Tomcat: EncryptInterceptor vulnerable to padding oracle attack by default (CVE-2026-29146)
- Resolves:
Tomcat: OCSP checks sometimes soft-fail even when soft-fail is disabled (CVE-2026-29145)
- Resolves:
Tomcat: Configured TLS cipher preference order not preserved (CVE-2026-29129)
- Resolves:
Tomcat: Occasionally open redirect (CVE-2026-25854)
- Resolves:
Tomcat: Request smuggling via invalid chunk extension (CVE-2026-24880)
- Resolves:
Tomcat: Incomplete OCSP verification checks (CVE-2026-24734)
- Resolves:
Tomcat: Security constraint bypass (CVE-2026-24733)
- Resolves:
Tomcat: Client certificate verification bypass due to virtual host mapping (CVE-2025-66614)
* Tue Apr 14 2026 Coty Sutherland <csutherl@redhat.com> - 1:9.0.110-3
- Resolves: RHEL-168243 Fix copy/paste error in AJP connector that caused DELETE requests to be processed as OPTIONS requests (BZ#69848)
* Mon Mar 23 2026 Coty Sutherland <csutherl@redhat.com> - 1:9.0.110-2
- Resolves: RHEL-158962 NPE in tomcat9 when used with TLS enabled custom connector