forked from pool/tomcat10
Accepting request 1139494 from home:mbussolotto:branches:Java:packages
- change server.xml during %post instead of %posttrans - add libxslt-tools requirement - Fixed CVEs: * CVE-2023-46589: Apache Tomcat: HTTP request smuggling due to incorrect headers parsing (bsc#1217649) - Added patches: * tomcat-10-CVE-2023-46589.patch OBS-URL: https://build.opensuse.org/request/show/1139494 OBS-URL: https://build.opensuse.org/package/show/Java:packages/tomcat10?expand=0&rev=20
This commit is contained in:
parent
940c0b2f6d
commit
e59c5cabf4
307
tomcat-10-CVE-2023-46589.patch
Normal file
307
tomcat-10-CVE-2023-46589.patch
Normal file
@ -0,0 +1,307 @@
|
||||
Index: apache-tomcat-10.1.14-src/java/org/apache/catalina/connector/BadRequestException.java
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ apache-tomcat-10.1.14-src/java/org/apache/catalina/connector/BadRequestException.java
|
||||
@@ -0,0 +1,68 @@
|
||||
+/*
|
||||
+ * 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.connector;
|
||||
+
|
||||
+import java.io.IOException;
|
||||
+
|
||||
+/**
|
||||
+ * Extend IOException to identify it as being caused by a bad request from a remote client.
|
||||
+ */
|
||||
+public class BadRequestException extends IOException {
|
||||
+
|
||||
+ private static final long serialVersionUID = 1L;
|
||||
+
|
||||
+
|
||||
+ // ------------------------------------------------------------ Constructors
|
||||
+
|
||||
+ /**
|
||||
+ * Construct a new BadRequestException with no other information.
|
||||
+ */
|
||||
+ public BadRequestException() {
|
||||
+ super();
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /**
|
||||
+ * Construct a new BadRequestException for the specified message.
|
||||
+ *
|
||||
+ * @param message Message describing this exception
|
||||
+ */
|
||||
+ public BadRequestException(String message) {
|
||||
+ super(message);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /**
|
||||
+ * Construct a new BadRequestException for the specified throwable.
|
||||
+ *
|
||||
+ * @param throwable Throwable that caused this exception
|
||||
+ */
|
||||
+ public BadRequestException(Throwable throwable) {
|
||||
+ super(throwable);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /**
|
||||
+ * Construct a new BadRequestException for the specified message and throwable.
|
||||
+ *
|
||||
+ * @param message Message describing this exception
|
||||
+ * @param throwable Throwable that caused this exception
|
||||
+ */
|
||||
+ public BadRequestException(String message, Throwable throwable) {
|
||||
+ super(message, throwable);
|
||||
+ }
|
||||
+}
|
||||
Index: apache-tomcat-10.1.14-src/java/org/apache/catalina/connector/ClientAbortException.java
|
||||
===================================================================
|
||||
--- apache-tomcat-10.1.14-src.orig/java/org/apache/catalina/connector/ClientAbortException.java
|
||||
+++ apache-tomcat-10.1.14-src/java/org/apache/catalina/connector/ClientAbortException.java
|
||||
@@ -16,14 +16,12 @@
|
||||
*/
|
||||
package org.apache.catalina.connector;
|
||||
|
||||
-import java.io.IOException;
|
||||
-
|
||||
/**
|
||||
* Extend IOException to identify it as being caused by an abort of a request by a remote client.
|
||||
*
|
||||
* @author Glenn L. Nielsen
|
||||
*/
|
||||
-public final class ClientAbortException extends IOException {
|
||||
+public final class ClientAbortException extends BadRequestException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
Index: apache-tomcat-10.1.14-src/java/org/apache/catalina/connector/InputBuffer.java
|
||||
===================================================================
|
||||
--- apache-tomcat-10.1.14-src.orig/java/org/apache/catalina/connector/InputBuffer.java
|
||||
+++ apache-tomcat-10.1.14-src/java/org/apache/catalina/connector/InputBuffer.java
|
||||
@@ -29,6 +29,7 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import jakarta.servlet.ReadListener;
|
||||
+import jakarta.servlet.RequestDispatcher;
|
||||
|
||||
import org.apache.catalina.security.SecurityUtil;
|
||||
import org.apache.coyote.ActionCode;
|
||||
@@ -307,10 +308,24 @@ public class InputBuffer extends Reader
|
||||
|
||||
try {
|
||||
return coyoteRequest.doRead(this);
|
||||
+ } catch (BadRequestException bre) {
|
||||
+ // Set flag used by asynchronous processing to detect errors on non-container threads
|
||||
+ coyoteRequest.setErrorException(bre);
|
||||
+ // In synchronous processing, this exception may be swallowed by the application so set error flags here.
|
||||
+ coyoteRequest.setAttribute(RequestDispatcher.ERROR_EXCEPTION, bre);
|
||||
+ coyoteRequest.getResponse().setStatus(400);
|
||||
+ coyoteRequest.getResponse().setError();
|
||||
+ // Make the exception visible to the application
|
||||
+ throw bre;
|
||||
} catch (IOException ioe) {
|
||||
+ // Set flag used by asynchronous processing to detect errors on non-container threads
|
||||
coyoteRequest.setErrorException(ioe);
|
||||
- // An IOException on a read is almost always due to
|
||||
- // the remote client aborting the request.
|
||||
+ // In synchronous processing, this exception may be swallowed by the application so set error flags here.
|
||||
+ coyoteRequest.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
|
||||
+ coyoteRequest.getResponse().setStatus(400);
|
||||
+ coyoteRequest.getResponse().setError();
|
||||
+ // Any other IOException on a read is almost always due to the remote client aborting the request.
|
||||
+ // Make the exception visible to the application
|
||||
throw new ClientAbortException(ioe);
|
||||
}
|
||||
}
|
||||
Index: apache-tomcat-10.1.14-src/java/org/apache/catalina/core/ApplicationDispatcher.java
|
||||
===================================================================
|
||||
--- apache-tomcat-10.1.14-src.orig/java/org/apache/catalina/core/ApplicationDispatcher.java
|
||||
+++ apache-tomcat-10.1.14-src/java/org/apache/catalina/core/ApplicationDispatcher.java
|
||||
@@ -41,7 +41,7 @@ import org.apache.catalina.AsyncDispatch
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.Globals;
|
||||
import org.apache.catalina.Wrapper;
|
||||
-import org.apache.catalina.connector.ClientAbortException;
|
||||
+import org.apache.catalina.connector.BadRequestException;
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.RequestFacade;
|
||||
import org.apache.catalina.connector.Response;
|
||||
@@ -642,7 +642,7 @@ final class ApplicationDispatcher implem
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
// Servlet Service Method is called by the FilterChain
|
||||
- } catch (ClientAbortException e) {
|
||||
+ } catch (BadRequestException e) {
|
||||
ioException = e;
|
||||
} catch (IOException e) {
|
||||
wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException", wrapper.getName()), e);
|
||||
@@ -653,7 +653,7 @@ final class ApplicationDispatcher implem
|
||||
wrapper.unavailable(e);
|
||||
} catch (ServletException e) {
|
||||
Throwable rootCause = StandardWrapper.getRootCause(e);
|
||||
- if (!(rootCause instanceof ClientAbortException)) {
|
||||
+ if (!(rootCause instanceof BadRequestException)) {
|
||||
wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException", wrapper.getName()),
|
||||
rootCause);
|
||||
}
|
||||
Index: apache-tomcat-10.1.14-src/java/org/apache/catalina/core/StandardWrapperValve.java
|
||||
===================================================================
|
||||
--- apache-tomcat-10.1.14-src.orig/java/org/apache/catalina/core/StandardWrapperValve.java
|
||||
+++ apache-tomcat-10.1.14-src/java/org/apache/catalina/core/StandardWrapperValve.java
|
||||
@@ -32,7 +32,7 @@ import org.apache.catalina.Container;
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.Globals;
|
||||
import org.apache.catalina.LifecycleException;
|
||||
-import org.apache.catalina.connector.ClientAbortException;
|
||||
+import org.apache.catalina.connector.BadRequestException;
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
import org.apache.catalina.valves.ValveBase;
|
||||
@@ -169,7 +169,7 @@ final class StandardWrapperValve extends
|
||||
}
|
||||
|
||||
}
|
||||
- } catch (ClientAbortException | CloseNowException e) {
|
||||
+ } catch (BadRequestException | CloseNowException e) {
|
||||
if (container.getLogger().isDebugEnabled()) {
|
||||
container.getLogger().debug(
|
||||
sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
|
||||
@@ -190,7 +190,7 @@ final class StandardWrapperValve extends
|
||||
// do not want to do exception(request, response, e) processing
|
||||
} catch (ServletException e) {
|
||||
Throwable rootCause = StandardWrapper.getRootCause(e);
|
||||
- if (!(rootCause instanceof ClientAbortException)) {
|
||||
+ if (!(rootCause instanceof BadRequestException)) {
|
||||
container.getLogger().error(sm.getString("standardWrapper.serviceExceptionRoot", wrapper.getName(),
|
||||
context.getName(), e.getMessage()), rootCause);
|
||||
}
|
||||
Index: apache-tomcat-10.1.14-src/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java
|
||||
===================================================================
|
||||
--- apache-tomcat-10.1.14-src.orig/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java
|
||||
+++ apache-tomcat-10.1.14-src/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java
|
||||
@@ -428,6 +428,83 @@ public class TestChunkedInputFilter exte
|
||||
}
|
||||
}
|
||||
|
||||
+
|
||||
+ @Test
|
||||
+ public void testTrailerHeaderNameNotTokenThrowException() throws Exception {
|
||||
+ doTestTrailerHeaderNameNotToken(false);
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testTrailerHeaderNameNotTokenSwallowException() throws Exception {
|
||||
+ doTestTrailerHeaderNameNotToken(true);
|
||||
+ }
|
||||
+
|
||||
+ private void doTestTrailerHeaderNameNotToken(boolean swallowException) throws Exception {
|
||||
+
|
||||
+ // Setup Tomcat instance
|
||||
+ Tomcat tomcat = getTomcatInstance();
|
||||
+
|
||||
+ // No file system docBase required
|
||||
+ Context ctx = tomcat.addContext("", null);
|
||||
+
|
||||
+ Tomcat.addServlet(ctx, "servlet", new SwallowBodyServlet(swallowException));
|
||||
+ ctx.addServletMappingDecoded("/", "servlet");
|
||||
+
|
||||
+ tomcat.start();
|
||||
+
|
||||
+ String[] request = new String[]{
|
||||
+ "POST / HTTP/1.1" + SimpleHttpClient.CRLF +
|
||||
+ "Host: localhost" + SimpleHttpClient.CRLF +
|
||||
+ "Transfer-encoding: chunked" + SimpleHttpClient.CRLF +
|
||||
+ "Content-Type: application/x-www-form-urlencoded" + SimpleHttpClient.CRLF +
|
||||
+ "Connection: close" + SimpleHttpClient.CRLF +
|
||||
+ SimpleHttpClient.CRLF +
|
||||
+ "3" + SimpleHttpClient.CRLF +
|
||||
+ "a=0" + SimpleHttpClient.CRLF +
|
||||
+ "4" + SimpleHttpClient.CRLF +
|
||||
+ "&b=1" + SimpleHttpClient.CRLF +
|
||||
+ "0" + SimpleHttpClient.CRLF +
|
||||
+ "x@trailer: Test" + SimpleHttpClient.CRLF +
|
||||
+ SimpleHttpClient.CRLF };
|
||||
+
|
||||
+ TrailerClient client = new TrailerClient(tomcat.getConnector().getLocalPort());
|
||||
+ client.setRequest(request);
|
||||
+
|
||||
+ client.connect();
|
||||
+ client.processRequest();
|
||||
+ // Expected to fail because of invalid trailer header name
|
||||
+ Assert.assertTrue(client.getResponseLine(), client.isResponse400());
|
||||
+ }
|
||||
+
|
||||
+ private static class SwallowBodyServlet extends HttpServlet {
|
||||
+ private static final long serialVersionUID = 1L;
|
||||
+
|
||||
+ private final boolean swallowException;
|
||||
+
|
||||
+ SwallowBodyServlet(boolean swallowException) {
|
||||
+ this.swallowException = swallowException;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||
+ throws ServletException, IOException {
|
||||
+ resp.setContentType("text/plain");
|
||||
+ PrintWriter pw = resp.getWriter();
|
||||
+
|
||||
+ // Read the body
|
||||
+ InputStream is = req.getInputStream();
|
||||
+ try {
|
||||
+ while (is.read() > -1) {
|
||||
+ }
|
||||
+ pw.write("OK");
|
||||
+ } catch (IOException ioe) {
|
||||
+ if (!swallowException) {
|
||||
+ throw ioe;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
private static class EchoHeaderServlet extends HttpServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
Index: apache-tomcat-10.1.14-src/webapps/docs/changelog.xml
|
||||
===================================================================
|
||||
--- apache-tomcat-10.1.14-src.orig/webapps/docs/changelog.xml
|
||||
+++ apache-tomcat-10.1.14-src/webapps/docs/changelog.xml
|
||||
@@ -129,6 +129,11 @@
|
||||
Improve handling of failures within <code>recycle()</code> methods.
|
||||
(markt)
|
||||
</add>
|
||||
+ <fix>
|
||||
+ Ensure that an <code>IOException</code> during the reading of the
|
||||
+ request triggers always error handling, regardless of whether the
|
||||
+ application swallows the exception. (markt)
|
||||
+ </fix>
|
||||
</changelog>
|
||||
</subsection>
|
||||
<subsection name="Coyote">
|
||||
@@ -170,7 +175,7 @@
|
||||
<fix>
|
||||
Improvements to HTTP/2 overhead protection. (markt)
|
||||
</fix>
|
||||
- </changelog>
|
||||
+d </changelog>
|
||||
</subsection>
|
||||
<subsection name="Jasper">
|
||||
<changelog>
|
@ -1,3 +1,18 @@
|
||||
-------------------------------------------------------------------
|
||||
Wed Jan 17 15:35:51 UTC 2024 - Michele Bussolotto <michele.bussolotto@suse.com>
|
||||
|
||||
- change server.xml during %post instead of %posttrans
|
||||
- add libxslt-tools requirement
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Jan 17 15:35:40 UTC 2024 - Michele Bussolotto <michele.bussolotto@suse.com>
|
||||
|
||||
- Fixed CVEs:
|
||||
* CVE-2023-46589: Apache Tomcat: HTTP request smuggling due to
|
||||
incorrect headers parsing (bsc#1217649)
|
||||
- Added patches:
|
||||
* tomcat-10-CVE-2023-46589.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Jan 16 09:05:32 UTC 2024 - Michele Bussolotto <michele.bussolotto@suse.com>
|
||||
|
||||
|
@ -71,6 +71,7 @@ Source21: %{app_name}-functions
|
||||
Source30: %{app_name}-preamble
|
||||
Source31: %{app_name}-server
|
||||
Source32: %{app_name}-named.service
|
||||
Source33: tomcat-10-CVE-2023-46589.patch
|
||||
Source100: valve.xslt
|
||||
Source101: allowLinking.xslt
|
||||
Source1000: %{app_name}-rpmlintrc
|
||||
@ -111,7 +112,6 @@ BuildRequires: jakarta-taglibs-standard >= 1.1
|
||||
BuildRequires: java-devel >= 11
|
||||
BuildRequires: javapackages-local
|
||||
BuildRequires: junit
|
||||
BuildRequires: libxslt-tools
|
||||
BuildRequires: osgi-annotation
|
||||
BuildRequires: osgi-compendium
|
||||
BuildRequires: osgi-core
|
||||
@ -132,6 +132,7 @@ Requires: apache-commons-pool2
|
||||
Requires: jakarta-servlet
|
||||
Requires: java >= %{java_version}
|
||||
Requires(post): %fillup_prereq
|
||||
Requires(post): libxslt-tools
|
||||
Requires(pre): shadow
|
||||
Requires: libtcnative-1-0 >= 1.2.38
|
||||
Requires: logrotate
|
||||
@ -150,6 +151,7 @@ ATTENTION: This tomcat is built with java %{java_version}.
|
||||
Summary: The host manager and manager web applications for Apache Tomcat
|
||||
Group: Productivity/Networking/Web/Servers
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
Requires(post): libxslt-tools
|
||||
Conflicts: %{app_name}-admin-webapps
|
||||
|
||||
%description admin-webapps
|
||||
@ -167,6 +169,7 @@ Embeddeding support (various libraries) for Apache Tomcat.
|
||||
Summary: The "docs" web application for Apache Tomcat
|
||||
Group: Productivity/Networking/Web/Servers
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
Requires(post): libxslt-tools
|
||||
Conflicts: %{app_name}-docs-webapp
|
||||
|
||||
%description docs-webapp
|
||||
@ -261,6 +264,7 @@ Summary: ROOT and examples web applications for Apache Tomcat
|
||||
Group: Productivity/Networking/Web/Servers
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
Requires: jakarta-taglibs-standard >= 1.1
|
||||
Requires(post): libxslt-tools
|
||||
Conflicts: %{app_name}-webapps
|
||||
|
||||
%description webapps
|
||||
@ -587,6 +591,7 @@ getent passwd tomcat >/dev/null || %{_sbindir}/useradd -c "Apache Tomcat" \
|
||||
%post
|
||||
%service_add_post %{app_name}.service
|
||||
%{fillup_only %{app_name}}
|
||||
xsltproc --output %{confdir}/server.xml %{confdir}/valve.xslt %{confdir}/server.xml
|
||||
|
||||
%preun
|
||||
%service_del_preun %{app_name}.service
|
||||
@ -696,9 +701,6 @@ if [ ! -e %{_datadir}/%{app_name}/webapps/docs ]; then
|
||||
ln -sf %{tomcatappdir}/docs %{_datadir}/%{app_name}/webapps/docs
|
||||
fi
|
||||
|
||||
%posttrans
|
||||
xsltproc --output %{confdir}/server.xml %{confdir}/valve.xslt %{confdir}/server.xml
|
||||
|
||||
%files
|
||||
%doc {LICENSE,NOTICE,RELEASE*}
|
||||
%attr(0755,root,root) %{_bindir}/%{app_name}-digest
|
||||
|
Loading…
x
Reference in New Issue
Block a user