diff --git a/9.0.10.tar.gz b/9.0.10.tar.gz deleted file mode 100644 index 157288e..0000000 Binary files a/9.0.10.tar.gz and /dev/null differ diff --git a/CVE-2018-11784.patch b/CVE-2018-11784.patch deleted file mode 100644 index 4bf1bb2..0000000 --- a/CVE-2018-11784.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- a/webapps/docs/changelog.xml 2018-06-20 13:35:40.000000000 -0400 -+++ b/webapps/docs/changelog_1.xml 2019-06-24 08:35:44.801000000 -0400 -@@ -164,6 +164,10 @@ - the authenticated Subject to include at least one Principal of a type - specified by userClassNames. (markt) - -+ -+ When generating a redirect to a directory in the Default Servlet, avoid -+ generating a protocol relative redirect. (markt) -+ - - - ---- a/java/org/apache/catalina/servlets/DefaultServlet.java 2018-06-20 13:35:34.000000000 -0400 -+++ b/java/org/apache/catalina/servlets/DefaultServlet_1.java 2019-06-24 08:40:08.699000000 -0400 -@@ -1324,6 +1324,10 @@ public class DefaultServlet extends Http - location.append('?'); - location.append(request.getQueryString()); - } -+ // Avoid protocol relative redirects -+ while (location.length() > 1 && location.charAt(1) == '/') { -+ location.deleteCharAt(0); -+ } - response.sendRedirect(response.encodeRedirectURL(location.toString())); - } - - diff --git a/CVE-2019-0199-1.patch b/CVE-2019-0199-1.patch deleted file mode 100644 index d05be52..0000000 --- a/CVE-2019-0199-1.patch +++ /dev/null @@ -1,75 +0,0 @@ ---- tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:17:08 1852697 -+++ tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:01 1852698 -@@ -42,8 +42,10 @@ - public class Http2Protocol implements UpgradeProtocol { - - static final long DEFAULT_READ_TIMEOUT = 10000; -- static final long DEFAULT_KEEP_ALIVE_TIMEOUT = -1; - static final long DEFAULT_WRITE_TIMEOUT = 10000; -+ static final long DEFAULT_KEEP_ALIVE_TIMEOUT = -1; -+ static final long DEFAULT_STREAM_READ_TIMEOUT = 20000; -+ static final long DEFAULT_STREAM_WRITE_TIMEOUT = 20000; - // The HTTP/2 specification recommends a minimum default of 100 - static final long DEFAULT_MAX_CONCURRENT_STREAMS = 200; - // Maximum amount of streams which can be concurrently executed over -@@ -57,9 +59,14 @@ - private static final byte[] ALPN_IDENTIFIER = ALPN_NAME.getBytes(StandardCharsets.UTF_8); - - // All timeouts in milliseconds -+ // These are the socket level timeouts - private long readTimeout = DEFAULT_READ_TIMEOUT; -- private long keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT; - private long writeTimeout = DEFAULT_WRITE_TIMEOUT; -+ private long keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT; -+ // These are the stream level timeouts -+ private long streamReadTimeout = DEFAULT_STREAM_READ_TIMEOUT; -+ private long streamWriteTimeout = DEFAULT_STREAM_WRITE_TIMEOUT; -+ - private long maxConcurrentStreams = DEFAULT_MAX_CONCURRENT_STREAMS; - private int maxConcurrentStreamExecution = DEFAULT_MAX_CONCURRENT_STREAM_EXECUTION; - // If a lower initial value is required, set it here but DO NOT change the -@@ -145,6 +152,16 @@ - } - - -+ public long getWriteTimeout() { -+ return writeTimeout; -+ } -+ -+ -+ public void setWriteTimeout(long writeTimeout) { -+ this.writeTimeout = writeTimeout; -+ } -+ -+ - public long getKeepAliveTimeout() { - return keepAliveTimeout; - } -@@ -155,13 +172,23 @@ - } - - -- public long getWriteTimeout() { -- return writeTimeout; -+ public long getStreamReadTimeout() { -+ return streamReadTimeout; - } - - -- public void setWriteTimeout(long writeTimeout) { -- this.writeTimeout = writeTimeout; -+ public void setStreamReadTimeout(long streamReadTimeout) { -+ this.streamReadTimeout = streamReadTimeout; -+ } -+ -+ -+ public long getStreamWriteTimeout() { -+ return streamWriteTimeout; -+ } -+ -+ -+ public void setStreamWriteTimeout(long streamWriteTimeout) { -+ this.streamWriteTimeout = streamWriteTimeout; - } - - diff --git a/CVE-2019-0199-10.patch b/CVE-2019-0199-10.patch deleted file mode 100644 index fef53b2..0000000 --- a/CVE-2019-0199-10.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java ---- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java 2019-06-09 21:03:54.790000000 -0400 -+++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java 2019-06-09 21:05:12.133000000 -0400 -@@ -905,7 +905,7 @@ class Stream extends AbstractStream impl - throw new IOException(sm.getString("stream.inputBuffer.reset")); - } - -- if (inBuffer.position() == 0) { -+ if (inBuffer.position() == 0 && isActive() && !isInputFinished()) { - String msg = sm.getString("stream.inputBuffer.readTimeout"); - StreamException se = new StreamException( - msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt()); - diff --git a/CVE-2019-0199-11.patch b/CVE-2019-0199-11.patch deleted file mode 100644 index 33e7526..0000000 --- a/CVE-2019-0199-11.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/java/org/apache/coyote/http2/Stream.java 2019-06-11 21:24:19.998000000 -0400 -+++ b/java/org/apache/coyote/http2/Stream_1.java 2019-06-11 21:26:18.329000000 -0400 -@@ -221,7 +221,7 @@ class Stream extends AbstractStream impl - if (windowSize == 0) { - String msg = sm.getString("stream.writeTimeout"); - StreamException se = new StreamException( -- msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt()); -+ msg, Http2Error.ENHANCE_YOUR_CALM, getIdentifier().intValue()); - // Prevent the application making further writes - streamOutputBuffer.closed = true; - // Prevent Tomcat's error handling trying to write -@@ -908,7 +908,7 @@ class Stream extends AbstractStream impl - if (inBuffer.position() == 0 && isActive() && !isInputFinished()) { - String msg = sm.getString("stream.inputBuffer.readTimeout"); - StreamException se = new StreamException( -- msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt()); -+ msg, Http2Error.ENHANCE_YOUR_CALM, getIdentifier().intValue()); - // Trigger a reset once control returns to Tomcat - coyoteResponse.setError(); - streamOutputBuffer.reset = se; - diff --git a/CVE-2019-0199-2.patch b/CVE-2019-0199-2.patch deleted file mode 100644 index c1c1fda..0000000 --- a/CVE-2019-0199-2.patch +++ /dev/null @@ -1,246 +0,0 @@ -diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/catalina/connector/OutputBuffer.java apache-tomcat-9.0.10-src-bak/java/org/apache/catalina/connector/OutputBuffer.java ---- apache-tomcat-9.0.10-src/java/org/apache/catalina/connector/OutputBuffer.java 2018-06-20 13:35:33.000000000 -0400 -+++ apache-tomcat-9.0.10-src-bak/java/org/apache/catalina/connector/OutputBuffer.java 2019-06-09 20:28:02.836000000 -0400 -@@ -33,6 +33,7 @@ import javax.servlet.http.HttpServletRes - - import org.apache.catalina.Globals; - import org.apache.coyote.ActionCode; -+import org.apache.coyote.CloseNowException; - import org.apache.coyote.Response; - import org.apache.tomcat.util.buf.C2BConverter; - import org.apache.tomcat.util.res.StringManager; -@@ -326,6 +327,13 @@ public class OutputBuffer extends Writer - // real write to the adapter - try { - coyoteResponse.doWrite(buf); -+ } catch (CloseNowException e) { -+ // Catch this sub-class as it requires specific handling. -+ // Examples where this exception is thrown: -+ // - HTTP/2 stream timeout -+ // Prevent further output for this response -+ closed = true; -+ throw e; - } catch (IOException e) { - // An IOException on a write is almost always due to - // the remote client aborting the request. Wrap this -diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/catalina/core/StandardWrapperValve.java apache-tomcat-9.0.10-src-bak/java/org/apache/catalina/core/StandardWrapperValve.java ---- apache-tomcat-9.0.10-src/java/org/apache/catalina/core/StandardWrapperValve.java 2018-06-20 13:35:34.000000000 -0400 -+++ apache-tomcat-9.0.10-src-bak/java/org/apache/catalina/core/StandardWrapperValve.java 2019-06-09 20:33:27.596000000 -0400 -@@ -36,6 +36,7 @@ import org.apache.catalina.connector.Cli - import org.apache.catalina.connector.Request; - import org.apache.catalina.connector.Response; - import org.apache.catalina.valves.ValveBase; -+import org.apache.coyote.CloseNowException; - import org.apache.tomcat.util.ExceptionUtils; - import org.apache.tomcat.util.buf.MessageBytes; - import org.apache.tomcat.util.log.SystemLogHandler; -@@ -201,7 +202,7 @@ final class StandardWrapperValve - } - - } -- } catch (ClientAbortException e) { -+ } catch (ClientAbortException | CloseNowException e) { - throwable = e; - exception(request, response, e); - } catch (IOException e) { -diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/LocalStrings.properties apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/LocalStrings.properties ---- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/LocalStrings.properties 2018-06-20 13:35:35.000000000 -0400 -+++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/LocalStrings.properties 2019-06-09 20:34:32.307000000 -0400 -@@ -93,6 +93,7 @@ stream.reset.fail=Connection [{0}], Stre - stream.reset.receive=Connection [{0}], Stream [{1}], Reset received due to [{2}] - stream.reset.send=Connection [{0}], Stream [{1}], Reset sent due to [{2}] - stream.trailerHeader.noEndOfStream=Connection [{0}], Stream [{1}], The trailer headers did not include the end of stream flag -+stream.writeTimeout=Timeout waiting for client to increase flow control window to permit stream data to be written - - stream.inputBuffer.copy=Copying [{0}] bytes from inBuffer to outBuffer - stream.inputBuffer.dispatch=Data added to inBuffer when read interest is registered. Triggering a read dispatch -@@ -149,4 +150,4 @@ upgradeHandler.writeHeaders=Connection [ - upgradeHandler.writePushHeaders=Connection [{0}], Stream [{1}], Pushed stream [{2}], EndOfStream [{3}] - - writeStateMachine.endWrite.ise=It is illegal to specify [{0}] for the new state once a write has completed --writeStateMachine.ise=It is illegal to call [{0}()] in state [{1}] -\ No newline at end of file -+writeStateMachine.ise=It is illegal to call [{0}()] in state [{1}] -diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java ---- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java 2018-06-20 13:35:35.000000000 -0400 -+++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java 2019-06-09 20:38:30.109000000 -0400 -@@ -211,7 +211,21 @@ class Stream extends AbstractStream impl - } - try { - if (block) { -- wait(); -+ wait(handler.getProtocol().getStreamWriteTimeout()); -+ windowSize = getWindowSize(); -+ if (windowSize == 0) { -+ String msg = sm.getString("stream.writeTimeout"); -+ StreamException se = new StreamException( -+ msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt()); -+ // Prevent the application making further writes -+ streamOutputBuffer.closed = true; -+ // Prevent Tomcat's error handling trying to write -+ coyoteResponse.setError(); -+ coyoteResponse.setErrorReported(); -+ // Trigger a reset once control returns to Tomcat -+ streamOutputBuffer.reset = se; -+ throw new CloseNowException(msg, se); -+ } - } else { - return 0; - } -@@ -221,7 +235,6 @@ class Stream extends AbstractStream impl - // Stream. - throw new IOException(e); - } -- windowSize = getWindowSize(); - } - int allocation; - if (windowSize < reservation) { -@@ -660,6 +673,9 @@ class Stream extends AbstractStream impl - return !streamOutputBuffer.endOfStreamSent; - } - -+ StreamException getResetException() { -+ return streamOutputBuffer.reset; -+ } - - private static void push(final Http2UpgradeHandler handler, final Request request, - final Stream stream) throws IOException { -@@ -707,6 +723,7 @@ class Stream extends AbstractStream impl - private final ByteBuffer buffer = ByteBuffer.allocate(8 * 1024); - private volatile long written = 0; - private volatile boolean closed = false; -+ private volatile StreamException reset = null; - private volatile boolean endOfStreamSent = false; - - /* The write methods are synchronized to ensure that only one thread at -@@ -800,9 +817,14 @@ class Stream extends AbstractStream impl - - @Override - public final void end() throws IOException { -- closed = true; -- flush(true); -- writeTrailers(); -+ if (reset != null) { -+ throw new CloseNowException(reset); -+ } -+ if (!closed) { -+ closed = true; -+ flush(true); -+ writeTrailers(); -+ } - } - - /** -diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/StreamProcessor.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/StreamProcessor.java ---- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/StreamProcessor.java 2018-06-20 13:35:35.000000000 -0400 -+++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/StreamProcessor.java 2019-06-09 20:40:08.789000000 -0400 -@@ -78,10 +78,13 @@ class StreamProcessor extends AbstractPr - stream.getIdentifier()), Http2Error.INTERNAL_ERROR); - stream.close(ce); - } else if (!getErrorState().isIoAllowed()) { -- StreamException se = new StreamException(sm.getString( -- "streamProcessor.error.stream", stream.getConnectionId(), -- stream.getIdentifier()), Http2Error.INTERNAL_ERROR, -- stream.getIdentifier().intValue()); -+ StreamException se = stream.getResetException(); -+ if (se == null) { -+ se = new StreamException(sm.getString( -+ "streamProcessor.error.stream", stream.getConnectionId(), -+ stream.getIdentifier()), Http2Error.INTERNAL_ERROR, -+ stream.getIdentifier().intValue()); -+ } - stream.close(se); - } - } -diff -Nurp apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/Http2TestBase.java apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/Http2TestBase.java ---- apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/Http2TestBase.java 2018-06-20 13:35:38.000000000 -0400 -+++ apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/Http2TestBase.java 2019-06-09 20:41:45.113000000 -0400 -@@ -486,8 +486,10 @@ public abstract class Http2TestBase exte - Http2Protocol http2Protocol = new Http2Protocol(); - // Short timeouts for now. May need to increase these for CI systems. - http2Protocol.setReadTimeout(2000); -- http2Protocol.setKeepAliveTimeout(5000); - http2Protocol.setWriteTimeout(2000); -+ http2Protocol.setKeepAliveTimeout(5000); -+ http2Protocol.setStreamReadTimeout(1000); -+ http2Protocol.setStreamWriteTimeout(1000); - http2Protocol.setMaxConcurrentStreams(maxConcurrentStreams); - connector.addUpgradeProtocol(http2Protocol); - } -diff -Nurp apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/TestHttp2Timeouts.java apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/TestHttp2Timeouts.java ---- apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/TestHttp2Timeouts.java 1969-12-31 19:00:00.000000000 -0500 -+++ apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/TestHttp2Timeouts.java 2019-06-09 20:42:38.095000000 -0400 -@@ -0,0 +1,73 @@ -+/* -+ * 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.coyote.http2; -+ -+import org.junit.Assert; -+import org.junit.Before; -+import org.junit.Test; -+ -+public class TestHttp2Timeouts extends Http2TestBase { -+ -+ @Override -+ @Before -+ public void http2Connect() throws Exception { -+ super.http2Connect(); -+ sendSettings(0, false, new SettingValue(Setting.INITIAL_WINDOW_SIZE.getId(), 0)); -+ } -+ -+ -+ /* -+ * Simple request won't fill buffer so timeout will occur in Tomcat internal -+ * code during response completion. -+ */ -+ @Test -+ public void testClientWithEmptyWindow() throws Exception { -+ sendSimpleGetRequest(3); -+ -+ // Settings -+ parser.readFrame(false); -+ // Headers -+ parser.readFrame(false); -+ -+ output.clearTrace(); -+ -+ parser.readFrame(false); -+ Assert.assertEquals("3-RST-[11]\n", output.getTrace()); -+ } -+ -+ -+ /* -+ * Large request will fill buffer so timeout will occur in application code -+ * during response write (when Tomcat commits the response and flushes the -+ * buffer as a result of the buffer filling). -+ */ -+ @Test -+ public void testClientWithEmptyWindowLargeResponse() throws Exception { -+ sendLargeGetRequest(3); -+ -+ // Settings -+ parser.readFrame(false); -+ // Headers -+ parser.readFrame(false); -+ -+ output.clearTrace(); -+ -+ parser.readFrame(false); -+ Assert.assertEquals("3-RST-[11]\n", output.getTrace()); -+ } -+ -+} diff --git a/CVE-2019-0199-3.patch b/CVE-2019-0199-3.patch deleted file mode 100644 index 0494f3b..0000000 --- a/CVE-2019-0199-3.patch +++ /dev/null @@ -1,202 +0,0 @@ -diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/LocalStrings.properties apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/LocalStrings.properties ---- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/LocalStrings.properties 2019-06-09 20:45:15.320000000 -0400 -+++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/LocalStrings.properties 2019-06-09 20:46:36.793000000 -0400 -@@ -98,6 +98,7 @@ stream.writeTimeout=Timeout waiting for - stream.inputBuffer.copy=Copying [{0}] bytes from inBuffer to outBuffer - stream.inputBuffer.dispatch=Data added to inBuffer when read interest is registered. Triggering a read dispatch - stream.inputBuffer.empty=The Stream input buffer is empty. Waiting for more data -+stream.inputBuffer.readTimeout=Timeout waiting to read data from client - stream.inputBuffer.reset=Stream reset - stream.inputBuffer.signal=Data added to inBuffer when read thread is waiting. Signalling that thread to continue - -diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java ---- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java 2019-06-09 20:45:15.321000000 -0400 -+++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java 2019-06-09 20:48:21.509000000 -0400 -@@ -888,10 +888,22 @@ class Stream extends AbstractStream impl - if (log.isDebugEnabled()) { - log.debug(sm.getString("stream.inputBuffer.empty")); - } -- inBuffer.wait(); -+ -+ inBuffer.wait(handler.getProtocol().getStreamReadTimeout()); -+ - if (reset) { - throw new IOException(sm.getString("stream.inputBuffer.reset")); - } -+ -+ if (inBuffer.position() == 0) { -+ String msg = sm.getString("stream.inputBuffer.readTimeout"); -+ StreamException se = new StreamException( -+ msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt()); -+ // Trigger a reset once control returns to Tomcat -+ coyoteResponse.setError(); -+ streamOutputBuffer.reset = se; -+ throw new CloseNowException(msg, se); -+ } - } catch (InterruptedException e) { - // Possible shutdown / rst or similar. Use an - // IOException to signal to the client that further I/O -diff -Nurp apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/Http2TestBase.java apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/Http2TestBase.java ---- apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/Http2TestBase.java 2019-06-09 20:45:15.323000000 -0400 -+++ apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/Http2TestBase.java 2019-06-09 20:53:54.809000000 -0400 -@@ -28,6 +28,7 @@ import java.nio.charset.StandardCharsets - import java.util.ArrayList; - import java.util.List; - import java.util.Locale; -+import java.util.Map; - import java.util.Random; - - import javax.net.SocketFactory; -@@ -300,6 +301,22 @@ public abstract class Http2TestBase exte - } - } - -+ protected void sendParameterPostRequest(int streamId, byte[] padding, String body, -+ long contentLength, boolean useExpectation) throws IOException { -+ byte[] headersFrameHeader = new byte[9]; -+ ByteBuffer headersPayload = ByteBuffer.allocate(128); -+ byte[] dataFrameHeader = new byte[9]; -+ ByteBuffer dataPayload = ByteBuffer.allocate(128); -+ -+ buildPostRequest(headersFrameHeader, headersPayload, useExpectation, -+ "application/x-www-form-urlencoded", contentLength, "/parameter", dataFrameHeader, -+ dataPayload, padding, null, null, streamId); -+ writeFrame(headersFrameHeader, headersPayload); -+ if (body != null) { -+ dataPayload.put(body.getBytes(StandardCharsets.ISO_8859_1)); -+ writeFrame(dataFrameHeader, dataPayload); -+ } -+ } - - protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer headersPayload, - boolean useExpectation, byte[] dataFrameHeader, ByteBuffer dataPayload, byte[] padding, -@@ -311,14 +328,29 @@ public abstract class Http2TestBase exte - protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer headersPayload, - boolean useExpectation, byte[] dataFrameHeader, ByteBuffer dataPayload, byte[] padding, - byte[] trailersFrameHeader, ByteBuffer trailersPayload, int streamId) { -+ buildPostRequest(headersFrameHeader, headersPayload, useExpectation, null, -1, "/simple", -+ dataFrameHeader, dataPayload, padding, trailersFrameHeader, trailersPayload, streamId); -+ } -+ -+ protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer headersPayload, -+ boolean useExpectation, String contentType, long contentLength, String path, -+ byte[] dataFrameHeader, ByteBuffer dataPayload, byte[] padding, -+ byte[] trailersFrameHeader, ByteBuffer trailersPayload, int streamId) { -+ - MimeHeaders headers = new MimeHeaders(); - headers.addValue(":method").setString("POST"); - headers.addValue(":scheme").setString("http"); -- headers.addValue(":path").setString("/simple"); -+ headers.addValue(":path").setString(path); - headers.addValue(":authority").setString("localhost:" + getPort()); - if (useExpectation) { - headers.addValue("expect").setString("100-continue"); - } -+ if (contentType != null) { -+ headers.addValue("content-type").setString(contentType); -+ } -+ if (contentLength > -1) { -+ headers.addValue("content-length").setLong(contentLength); -+ } - hpackEncoder.encode(headers, headersPayload); - - headersPayload.flip(); -@@ -507,6 +539,8 @@ public abstract class Http2TestBase exte - ctxt.addServletMappingDecoded("/large", "large"); - Tomcat.addServlet(ctxt, "cookie", new CookieServlet()); - ctxt.addServletMappingDecoded("/cookie", "cookie"); -+ Tomcat.addServlet(ctxt, "parameter", new ParameterServlet()); -+ ctxt.addServletMappingDecoded("/parameter", "parameter"); - - tomcat.start(); - } -@@ -1205,6 +1239,24 @@ public abstract class Http2TestBase exte - } - } - -+ -+ static class ParameterServlet extends HttpServlet { -+ -+ private static final long serialVersionUID = 1L; -+ -+ @Override -+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) -+ throws ServletException, IOException { -+ -+ Map params = req.getParameterMap(); -+ -+ resp.setContentType("text/plain"); -+ resp.setCharacterEncoding("UTF-8"); -+ -+ resp.getWriter().print(params.size()); -+ } -+ } -+ - - static class SettingValue { - private final int setting; -diff -Nurp apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/TestHttp2Timeouts.java apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/TestHttp2Timeouts.java ---- apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/TestHttp2Timeouts.java 2019-06-09 20:45:15.323000000 -0400 -+++ apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/TestHttp2Timeouts.java 2019-06-09 20:57:22.652000000 -0400 -@@ -26,7 +26,6 @@ public class TestHttp2Timeouts extends H - @Before - public void http2Connect() throws Exception { - super.http2Connect(); -- sendSettings(0, false, new SettingValue(Setting.INITIAL_WINDOW_SIZE.getId(), 0)); - } - - -@@ -36,7 +35,7 @@ public class TestHttp2Timeouts extends H - */ - @Test - public void testClientWithEmptyWindow() throws Exception { -- sendSimpleGetRequest(3); -+ sendSettings(0, false, new SettingValue(Setting.INITIAL_WINDOW_SIZE.getId(), 0)); - - // Settings - parser.readFrame(false); -@@ -57,6 +56,7 @@ public class TestHttp2Timeouts extends H - */ - @Test - public void testClientWithEmptyWindowLargeResponse() throws Exception { -+ sendSettings(0, false, new SettingValue(Setting.INITIAL_WINDOW_SIZE.getId(), 0)); - sendLargeGetRequest(3); - - // Settings -@@ -70,4 +70,36 @@ public class TestHttp2Timeouts extends H - Assert.assertEquals("3-RST-[11]\n", output.getTrace()); - } - -+ /* -+ * Timeout with app reading request body directly. -+ */ -+ @Test -+ public void testClientPostsNoBody() throws Exception { -+ sendSimplePostRequest(3, null, false); -+ -+ // Headers -+ parser.readFrame(false); -+ output.clearTrace(); -+ -+ parser.readFrame(false); -+ -+ Assert.assertEquals("3-RST-[11]\n", output.getTrace()); -+ } -+ -+ -+ /* -+ * Timeout with app processing parameters. -+ */ -+ @Test -+ public void testClientPostsNoParameters() throws Exception { -+ sendParameterPostRequest(3, null, null, 10, false); -+ -+ // Headers -+ parser.readFrame(false); -+ output.clearTrace(); -+ -+ parser.readFrame(false); -+ -+ Assert.assertEquals("3-RST-[11]\n", output.getTrace()); -+ } - } diff --git a/CVE-2019-0199-4.patch b/CVE-2019-0199-4.patch deleted file mode 100644 index 78e7858..0000000 --- a/CVE-2019-0199-4.patch +++ /dev/null @@ -1,38 +0,0 @@ ---- tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:14 1852700 -+++ tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:18 1852701 -@@ -41,9 +41,9 @@ - - public class Http2Protocol implements UpgradeProtocol { - -- static final long DEFAULT_READ_TIMEOUT = 10000; -- static final long DEFAULT_WRITE_TIMEOUT = 10000; -- static final long DEFAULT_KEEP_ALIVE_TIMEOUT = -1; -+ static final long DEFAULT_READ_TIMEOUT = 5000; -+ static final long DEFAULT_WRITE_TIMEOUT = 5000; -+ static final long DEFAULT_KEEP_ALIVE_TIMEOUT = 20000; - static final long DEFAULT_STREAM_READ_TIMEOUT = 20000; - static final long DEFAULT_STREAM_WRITE_TIMEOUT = 20000; - // The HTTP/2 specification recommends a minimum default of 100 ---- tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:14 1852700 -+++ tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:18 1852701 -@@ -329,9 +329,16 @@ - } - } - } -- // No more frames to read so switch to the keep-alive -- // timeout. -- socketWrapper.setReadTimeout(protocol.getKeepAliveTimeout()); -+ -+ if (activeRemoteStreamCount.get() == 0) { -+ // No streams currently active. Use the keep-alive -+ // timeout for the connection. -+ socketWrapper.setReadTimeout(protocol.getKeepAliveTimeout()); -+ } else { -+ // Streams currently active. Individual streams have -+ // timeouts so keep the connection open. -+ socketWrapper.setReadTimeout(-1); -+ } - } catch (Http2Exception ce) { - // Really ConnectionException - if (log.isDebugEnabled()) { - diff --git a/CVE-2019-0199-5.patch b/CVE-2019-0199-5.patch deleted file mode 100644 index a21d1a3..0000000 --- a/CVE-2019-0199-5.patch +++ /dev/null @@ -1,143 +0,0 @@ ---- tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:18 1852701 -+++ tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:22 1852702 -@@ -54,6 +54,8 @@ - // This default is defined by the HTTP/2 specification - static final int DEFAULT_INITIAL_WINDOW_SIZE = (1 << 16) - 1; - -+ static final int DEFAULT_OVERHEAD_COUNT_FACTOR = 1; -+ - private static final String HTTP_UPGRADE_NAME = "h2c"; - private static final String ALPN_NAME = "h2"; - private static final byte[] ALPN_IDENTIFIER = ALPN_NAME.getBytes(StandardCharsets.UTF_8); -@@ -79,6 +81,8 @@ - private int maxHeaderSize = Constants.DEFAULT_MAX_HEADER_SIZE; - private int maxTrailerCount = Constants.DEFAULT_MAX_TRAILER_COUNT; - private int maxTrailerSize = Constants.DEFAULT_MAX_TRAILER_SIZE; -+ private int overheadCountFactor = DEFAULT_OVERHEAD_COUNT_FACTOR; -+ - private boolean initiatePingDisabled = false; - private boolean useSendfile = true; - // Compression -@@ -306,6 +310,16 @@ - } - - -+ public int getOverheadCountFactor() { -+ return overheadCountFactor; -+ } -+ -+ -+ public void setOverheadCountFactor(int overheadCountFactor) { -+ this.overheadCountFactor = overheadCountFactor; -+ } -+ -+ - public void setInitiatePingDisabled(boolean initiatePingDisabled) { - this.initiatePingDisabled = initiatePingDisabled; - } ---- tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:18 1852701 -+++ tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:22 1852702 -@@ -30,6 +30,7 @@ - import java.util.concurrent.ConcurrentHashMap; - import java.util.concurrent.ConcurrentLinkedQueue; - import java.util.concurrent.atomic.AtomicInteger; -+import java.util.concurrent.atomic.AtomicLong; - import java.util.concurrent.atomic.AtomicReference; - - import javax.servlet.http.WebConnection; -@@ -139,6 +140,9 @@ - private AtomicInteger streamConcurrency = null; - private Queue queuedRunnable = null; - -+ // Track 'overhead' frames vs 'request/response' frames -+ private final AtomicLong overheadCount = new AtomicLong(-10); -+ - - Http2UpgradeHandler(Http2Protocol protocol, Adapter adapter, Request coyoteRequest) { - super (STREAM_ID_ZERO); -@@ -330,6 +334,10 @@ - } - } - -+ if (overheadCount.get() > 0) { -+ throw new ConnectionException("Too much overhead", Http2Error.ENHANCE_YOUR_CALM); -+ } -+ - if (activeRemoteStreamCount.get() == 0) { - // No streams currently active. Use the keep-alive - // timeout for the connection. -@@ -638,6 +646,9 @@ - log.debug(sm.getString("upgradeHandler.writeBody", connectionId, stream.getIdentifier(), - Integer.toString(len))); - } -+ -+ reduceOverheadCount(); -+ - // Need to check this now since sending end of stream will change this. - boolean writeable = stream.canWrite(); - byte[] header = new byte[9]; -@@ -1193,6 +1204,16 @@ - } - - -+ private void reduceOverheadCount() { -+ overheadCount.decrementAndGet(); -+ } -+ -+ -+ private void increaseOverheadCount() { -+ overheadCount.addAndGet(getProtocol().getOverheadCountFactor()); -+ } -+ -+ - // ----------------------------------------------- Http2Parser.Input methods - - @Override -@@ -1247,6 +1268,7 @@ - - @Override - public ByteBuffer startRequestBodyFrame(int streamId, int payloadSize) throws Http2Exception { -+ reduceOverheadCount(); - Stream stream = getStream(streamId, true); - stream.checkState(FrameType.DATA); - stream.receivedData(payloadSize); -@@ -1291,6 +1313,8 @@ - // determines if a new stream is created or if this stream is ignored. - checkPauseState(); - -+ reduceOverheadCount(); -+ - if (connectionState.get().isNewStreamAllowed()) { - Stream stream = getStream(streamId, false); - if (stream == null) { -@@ -1340,6 +1364,9 @@ - throw new ConnectionException(sm.getString("upgradeHandler.dependency.invalid", - getConnectionId(), Integer.valueOf(streamId)), Http2Error.PROTOCOL_ERROR); - } -+ -+ increaseOverheadCount(); -+ - Stream stream = getStream(streamId, false); - if (stream == null) { - stream = createRemoteStream(streamId); -@@ -1384,6 +1411,9 @@ - - @Override - public void setting(Setting setting, long value) throws ConnectionException { -+ -+ increaseOverheadCount(); -+ - // Special handling required - if (setting == Setting.INITIAL_WINDOW_SIZE) { - long oldValue = remoteSettings.getInitialWindowSize(); -@@ -1425,6 +1455,9 @@ - - @Override - public void pingReceive(byte[] payload, boolean ack) throws IOException { -+ if (!ack) { -+ increaseOverheadCount(); -+ } - pingManager.receivePing(payload, ack); - } - - diff --git a/CVE-2019-0199-6.patch b/CVE-2019-0199-6.patch deleted file mode 100644 index ef1ed8d..0000000 --- a/CVE-2019-0199-6.patch +++ /dev/null @@ -1,51 +0,0 @@ ---- tomcat/webapps/docs/config/http2.xml 2019/02/01 10:28:22 1852702 -+++ tomcat/webapps/docs/config/http2.xml 2019/02/01 10:28:26 1852703 -@@ -125,9 +125,9 @@ - - -

The time, in milliseconds, that Tomcat will wait between HTTP/2 frames -- before closing the connection. Negative values will be treated as an -- infinite timeout. If not specified, a default value of -1 -- will be used.

-+ when there is no active Stream before closing the connection. Negative -+ values will be treated as an infinite timeout. If not specified, a default -+ value of 20000 will be used.

-
- - -@@ -192,7 +192,24 @@ -

The time, in milliseconds, that Tomcat will wait for additional data - when a partial HTTP/2 frame has been received. Negative values will be - treated as an infinite timeout. If not specified, a default value of -- 10000 will be used.

-+ 5000 will be used.

-+
-+ -+ -+

The time, in milliseconds, that Tomcat will wait for additional data -+ frames to arrive for the stream when an application is performing a -+ blocking I/O read and additional data is required. Negative values will be -+ treated as an infinite timeout. If not specified, a default value of -+ 20000 will be used.

-+
-+ -+ -+

The time, in milliseconds, that Tomcat will wait for additional window -+ update frames to arrive for the stream and/or conenction when an -+ application is performing a blocking I/O write and the stream and/or -+ connection flow control window is too small for the write to complete. -+ Negative values will be treated as an infinite timeout. If not specified, -+ a default value of 20000 will be used.

-
- - -@@ -204,7 +221,7 @@ -

The time, in milliseconds, that Tomcat will wait to write additional - data when an HTTP/2 frame has been partially written. Negative values will - be treated as an infinite timeout. If not specified, a default value of -- 10000 will be used.

-+ 5000 will be used.

-
- - - diff --git a/CVE-2019-0199-7.patch b/CVE-2019-0199-7.patch deleted file mode 100644 index 0369108..0000000 --- a/CVE-2019-0199-7.patch +++ /dev/null @@ -1,32 +0,0 @@ -diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java ---- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java 2019-06-09 20:59:53.027000000 -0400 -+++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java 2019-06-09 21:02:31.878000000 -0400 -@@ -211,7 +211,12 @@ class Stream extends AbstractStream impl - } - try { - if (block) { -- wait(handler.getProtocol().getStreamWriteTimeout()); -+ long writeTimeout = handler.getProtocol().getStreamWriteTimeout(); -+ if (writeTimeout < 0) { -+ wait(); -+ } else { -+ wait(writeTimeout); -+ } - windowSize = getWindowSize(); - if (windowSize == 0) { - String msg = sm.getString("stream.writeTimeout"); -@@ -889,7 +894,12 @@ class Stream extends AbstractStream impl - log.debug(sm.getString("stream.inputBuffer.empty")); - } - -- inBuffer.wait(handler.getProtocol().getStreamReadTimeout()); -+ long readTimeout = handler.getProtocol().getStreamReadTimeout(); -+ if (readTimeout < 0) { -+ inBuffer.wait(); -+ } else { -+ inBuffer.wait(readTimeout); -+ } - - if (reset) { - throw new IOException(sm.getString("stream.inputBuffer.reset")); - diff --git a/CVE-2019-0199-8.patch b/CVE-2019-0199-8.patch deleted file mode 100644 index f921ed2..0000000 --- a/CVE-2019-0199-8.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:30 1852704 -+++ tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:34 1852705 -@@ -335,7 +335,9 @@ - } - - if (overheadCount.get() > 0) { -- throw new ConnectionException("Too much overhead", Http2Error.ENHANCE_YOUR_CALM); -+ throw new ConnectionException( -+ sm.getString("upgradeHandler.tooMuchOverhead", connectionId), -+ Http2Error.ENHANCE_YOUR_CALM); - } - - if (activeRemoteStreamCount.get() == 0) { ---- tomcat/java/org/apache/coyote/http2/LocalStrings.properties 2019/02/01 10:28:30 1852704 -+++ tomcat/java/org/apache/coyote/http2/LocalStrings.properties 2019/02/01 10:28:34 1852705 -@@ -141,6 +141,7 @@ - upgradeHandler.stream.notWritable=Connection [{0}], Stream [{1}], This stream is not writable - upgradeHandler.stream.old=A new remote stream ID of [{0}] was requested but the most recent stream was [{1}] - upgradeHandler.tooManyRemoteStreams=The client attempted to use more than [{0}] active streams -+upgradeHandler.tooMuchOverhead=Connection [{0}], Too much overhead so the connection will be closed - upgradeHandler.unexpectedAck=Connection [{0}], Stream [{1}], A settings acknowledgement was received when not expected - upgradeHandler.unexpectedEos=Unexpected end of stream - upgradeHandler.upgrade=Connection [{0}], HTTP/1.1 upgrade to stream [1] - diff --git a/CVE-2019-0199-9.patch b/CVE-2019-0199-9.patch deleted file mode 100644 index 78c22a1..0000000 --- a/CVE-2019-0199-9.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- tomcat/webapps/docs/config/http2.xml 2019/02/01 10:28:34 1852705 -+++ tomcat/webapps/docs/config/http2.xml 2019/02/01 10:28:38 1852706 -@@ -188,6 +188,20 @@ - The default value is an empty String (regexp matching disabled).

- - -+ -+

The factor to apply when counting overhead frames to determine if a -+ connection has too high an overhead and should be closed. The overhead -+ count starts at -10. The count is decreased for each -+ data frame sent or received and each headers frame received. The count is -+ increased by the overheadCountFactorfor each setting -+ received, priority frame received and ping received. If the overhead count -+ exceeds zero, the connection is closed. A value of less than -+ 1 disables this protection. In normal usage a value of -+ 3 or more will close the connection before any streams can -+ complete. If not specified, a default value of 1 will be -+ used.

-+
-+ - -

The time, in milliseconds, that Tomcat will wait for additional data - when a partial HTTP/2 frame has been received. Negative values will be - diff --git a/CVE-2019-0221.patch b/CVE-2019-0221.patch deleted file mode 100644 index cc2c366..0000000 --- a/CVE-2019-0221.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 15fcd166ea2c1bb79e8541b8e1a43da9c452ceea Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Mon, 11 Mar 2019 11:33:03 +0000 -Subject: [PATCH] Escape debug output to aid readability - -reason: Escape debug output to aid readability, fix CVE CVE-2019-0221 -https://github.com/apache/tomcat/commit/15fcd16 - ---- - java/org/apache/catalina/ssi/SSIPrintenv.java | 3 +-- - webapps/docs/changelog.xml | 3 +++ - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/java/org/apache/catalina/ssi/SSIPrintenv.java b/java/org/apache/catalina/ssi/SSIPrintenv.java -index 97470b2..092542f 100644 ---- a/java/org/apache/catalina/ssi/SSIPrintenv.java -+++ b/java/org/apache/catalina/ssi/SSIPrintenv.java -@@ -41,8 +41,7 @@ public class SSIPrintenv implements SSICommand { - } else { - Collection variableNames = ssiMediator.getVariableNames(); - for (String variableName : variableNames) { -- String variableValue = ssiMediator -- .getVariableValue(variableName); -+ String variableValue = ssiMediator.getVariableValue(variableName, "entity"); - //This shouldn't happen, since all the variable names must - // have values - if (variableValue == null) { -diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml -index 697cf07..cbd3961 100644 ---- a/webapps/docs/changelog.xml -+++ b/webapps/docs/changelog.xml -@@ -52,6 +52,9 @@ - Expires header as required by HTTP specification - (RFC 7231, 7234). (kkolinko) - -+ -+ Encode the output of the SSI printenv command. (markt) -+ - - - --- -1.8.3.1 - diff --git a/CVE-2019-10072-1.patch b/CVE-2019-10072-1.patch deleted file mode 100644 index 93ea148..0000000 --- a/CVE-2019-10072-1.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 7f748eb6bfaba5207c89dbd7d5adf50fae847145 Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Tue, 30 Apr 2019 22:18:12 +0100 -Subject: [PATCH] Expand HTTP/2 timeout handling to connection window - exhaustion on write. - -https://github.com/apache/tomcat/commit/7f748eb ---- - .../coyote/http2/Http2UpgradeHandler.java | 32 +++++++++++++++++-- - java/org/apache/coyote/http2/Stream.java | 27 +++++++++------- - webapps/docs/changelog.xml | 4 +++ - 3 files changed, 50 insertions(+), 13 deletions(-) - -diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -index 1d8770a..ab0369a 100644 ---- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java -+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -@@ -794,7 +794,26 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - } - if (allocation == 0) { - try { -- stream.wait(); -+ // Connection level window is empty. Although this -+ // request is for a stream, use the connection -+ // timeout -+ long writeTimeout = protocol.getWriteTimeout(); -+ if (writeTimeout < 0) { -+ stream.wait(); -+ } else { -+ stream.wait(writeTimeout); -+ } -+ // Has this stream been granted an allocation -+ int[] value = backLogStreams.get(stream); -+ if (value[1] == 0) { -+ // No allocation -+ // Close the connection. Do this first since -+ // closing the stream will raise an exception -+ close(); -+ // Close the stream (in app code so need to -+ // signal to app stream is closing) -+ stream.doWriteTimeout(); -+ } - } catch (InterruptedException e) { - throw new IOException(sm.getString( - "upgradeHandler.windowSizeReservationInterrupted", connectionId, -@@ -985,11 +1004,20 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - - - private void close() { -- connectionState.set(ConnectionState.CLOSED); -+ ConnectionState previous = connectionState.getAndSet(ConnectionState.CLOSED); -+ if (previous == ConnectionState.CLOSED) { -+ // Already closed -+ return; -+ } -+ - for (Stream stream : streams.values()) { - // The connection is closing. Close the associated streams as no - // longer required. - stream.receiveReset(Http2Error.CANCEL.getCode()); -+ // Release any streams waiting for an allocation -+ synchronized (stream) { -+ stream.notifyAll(); -+ } - } - try { - socketWrapper.close(); -diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java -index 2c4f67e..8b87b12 100644 ---- a/java/org/apache/coyote/http2/Stream.java -+++ b/java/org/apache/coyote/http2/Stream.java -@@ -219,17 +219,7 @@ class Stream extends AbstractStream implements HeaderEmitter { - } - windowSize = getWindowSize(); - if (windowSize == 0) { -- String msg = sm.getString("stream.writeTimeout"); -- StreamException se = new StreamException( -- msg, Http2Error.ENHANCE_YOUR_CALM, getIdentifier().intValue()); -- // Prevent the application making further writes -- streamOutputBuffer.closed = true; -- // Prevent Tomcat's error handling trying to write -- coyoteResponse.setError(); -- coyoteResponse.setErrorReported(); -- // Trigger a reset once control returns to Tomcat -- streamOutputBuffer.reset = se; -- throw new CloseNowException(msg, se); -+ doWriteTimeout(); - } - } else { - return 0; -@@ -252,6 +242,21 @@ class Stream extends AbstractStream implements HeaderEmitter { - } - - -+ void doWriteTimeout() throws CloseNowException { -+ String msg = sm.getString("stream.writeTimeout"); -+ StreamException se = new StreamException( -+ msg, Http2Error.ENHANCE_YOUR_CALM, getIdentifier().intValue()); -+ // Prevent the application making further writes -+ streamOutputBuffer.closed = true; -+ // Prevent Tomcat's error handling trying to write -+ coyoteResponse.setError(); -+ coyoteResponse.setErrorReported(); -+ // Trigger a reset once control returns to Tomcat -+ streamOutputBuffer.reset = se; -+ throw new CloseNowException(msg, se); -+ } -+ -+ - @Override - public final void emitHeader(String name, String value) throws HpackException { - if (log.isDebugEnabled()) { -diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml -index a8abf2d..5665df4 100644 ---- a/webapps/docs/changelog.xml -+++ b/webapps/docs/changelog.xml -@@ -362,6 +362,10 @@ - - Update the internal fork of Commons DBCP 2 to 2.4.0. (markt) - -+ -+ Expand HTTP/2 timeout handling to include connection window exhaustion -+ on write. (markt) -+ - - - --- -2.19.1 diff --git a/CVE-2019-10072-2.patch b/CVE-2019-10072-2.patch deleted file mode 100644 index 4619c59..0000000 --- a/CVE-2019-10072-2.patch +++ /dev/null @@ -1,28 +0,0 @@ -From ada725a50a60867af3422c8e612aecaeea856a9a Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Fri, 3 May 2019 21:52:41 +0100 -Subject: [PATCH] Fix test failures. Handle full allocation case. - -https://github.com/apache/tomcat/commit/ada725a ---- - java/org/apache/coyote/http2/Http2UpgradeHandler.java | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -index ab0369a..cadae44 100644 ---- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java -+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -@@ -804,8 +804,10 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - stream.wait(writeTimeout); - } - // Has this stream been granted an allocation -+ // Note: If the stream in not in this Map then the -+ // requested write has been fully allocated - int[] value = backLogStreams.get(stream); -- if (value[1] == 0) { -+ if (value != null && value[1] == 0) { - // No allocation - // Close the connection. Do this first since - // closing the stream will raise an exception --- -2.19.1 diff --git a/CVE-2019-12418.patch b/CVE-2019-12418.patch deleted file mode 100644 index c373c43..0000000 --- a/CVE-2019-12418.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 1fc9f589dbdd8295cf313b2667ab041c425f99c3 Mon Sep 17 00:00:00 2001 -From: remm -Date: Thu, 14 Nov 2019 13:39:31 +0100 -Subject: [PATCH] Refactor JMX remote RMI registry creation - ---- - .../mbeans/JmxRemoteLifecycleListener.java | 65 ++++++++++++++----- - 1 file changed, 49 insertions(+), 16 deletions(-) - -diff --git a/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java b/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java -index ae04294..e832935 100644 ---- a/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java -+++ b/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java -@@ -25,10 +25,11 @@ import java.net.MalformedURLException; - import java.net.ServerSocket; - import java.net.Socket; - import java.net.UnknownHostException; -+import java.rmi.AccessException; - import java.rmi.AlreadyBoundException; -+import java.rmi.NotBoundException; -+import java.rmi.Remote; - import java.rmi.RemoteException; --import java.rmi.registry.LocateRegistry; --import java.rmi.registry.Registry; - import java.rmi.server.RMIClientSocketFactory; - import java.rmi.server.RMIServerSocketFactory; - import java.security.NoSuchAlgorithmException; -@@ -301,18 +302,6 @@ public class JmxRemoteLifecycleListener implements LifecycleListener { - RMIClientSocketFactory registryCsf, RMIServerSocketFactory registrySsf, - RMIClientSocketFactory serverCsf, RMIServerSocketFactory serverSsf) { - -- // Create the RMI registry -- Registry registry; -- try { -- registry = LocateRegistry.createRegistry( -- theRmiRegistryPort, registryCsf, registrySsf); -- } catch (RemoteException e) { -- log.error(sm.getString( -- "jmxRemoteLifecycleListener.createRegistryFailed", -- serverName, Integer.toString(theRmiRegistryPort)), e); -- return null; -- } -- - if (bindAddress == null) { - bindAddress = "localhost"; - } -@@ -333,11 +322,20 @@ public class JmxRemoteLifecycleListener implements LifecycleListener { - cs = new RMIConnectorServer(serviceUrl, theEnv, server, - ManagementFactory.getPlatformMBeanServer()); - cs.start(); -- registry.bind("jmxrmi", server.toStub()); -+ Remote jmxServer = server.toStub(); -+ // Create the RMI registry -+ try { -+ new JmxRegistry(theRmiRegistryPort, registryCsf, registrySsf, "jmxrmi", jmxServer); -+ } catch (RemoteException e) { -+ log.error(sm.getString( -+ "jmxRemoteLifecycleListener.createRegistryFailed", -+ serverName, Integer.toString(theRmiRegistryPort)), e); -+ return null; -+ } - log.info(sm.getString("jmxRemoteLifecycleListener.start", - Integer.toString(theRmiRegistryPort), - Integer.toString(theRmiServerPort), serverName)); -- } catch (IOException | AlreadyBoundException e) { -+ } catch (IOException e) { - log.error(sm.getString( - "jmxRemoteLifecycleListener.createServerFailed", - serverName), e); -@@ -493,4 +491,39 @@ public class JmxRemoteLifecycleListener implements LifecycleListener { - return true; - } - } -+ -+ -+ private static class JmxRegistry extends sun.rmi.registry.RegistryImpl { -+ private static final long serialVersionUID = -3772054804656428217L; -+ private final String jmxName; -+ private final Remote jmxServer; -+ public JmxRegistry(int port, RMIClientSocketFactory csf, -+ RMIServerSocketFactory ssf, String jmxName, Remote jmxServer) throws RemoteException { -+ super(port, csf, ssf); -+ this.jmxName = jmxName; -+ this.jmxServer = jmxServer; -+ } -+ @Override -+ public Remote lookup(String name) -+ throws RemoteException, NotBoundException { -+ return (jmxName.equals(name)) ? jmxServer : null; -+ } -+ @Override -+ public void bind(String name, Remote obj) -+ throws RemoteException, AlreadyBoundException, AccessException { -+ } -+ @Override -+ public void unbind(String name) -+ throws RemoteException, NotBoundException, AccessException { -+ } -+ @Override -+ public void rebind(String name, Remote obj) -+ throws RemoteException, AccessException { -+ } -+ @Override -+ public String[] list() throws RemoteException { -+ return new String[] { jmxName }; -+ } -+ } -+ - } --- -2.23.0 - diff --git a/CVE-2019-17563.patch b/CVE-2019-17563.patch deleted file mode 100644 index 97f569d..0000000 --- a/CVE-2019-17563.patch +++ /dev/null @@ -1,137 +0,0 @@ -From fabfa49abf917e126dbcf299fed40a1ab96d6f7a Mon Sep 17 00:00:00 2001 -From: wang_yue111 -Date: Fri, 15 May 2020 17:17:57 +0800 -Subject: [PATCH] 2 - ---- - .../authenticator/AuthenticatorBase.java | 7 ++-- - .../catalina/authenticator/Constants.java | 3 ++ - .../authenticator/FormAuthenticator.java | 36 +++++-------------- - 3 files changed, 16 insertions(+), 30 deletions(-) - -diff --git a/java/org/apache/catalina/authenticator/AuthenticatorBase.java b/java/org/apache/catalina/authenticator/AuthenticatorBase.java -index 880ebde..47d562b 100644 ---- a/java/org/apache/catalina/authenticator/AuthenticatorBase.java -+++ b/java/org/apache/catalina/authenticator/AuthenticatorBase.java -@@ -1021,10 +1021,11 @@ public abstract class AuthenticatorBase extends ValveBase - } - - // Cache the authentication information in our session, if any -- if (cache) { -- if (session != null) { -+ if (session != null) { -+ if (cache) { - session.setAuthType(authType); - session.setPrincipal(principal); -+ } else { - if (username != null) { - session.setNote(Constants.SESS_USERNAME_NOTE, username); - } else { -diff --git a/java/org/apache/catalina/authenticator/Constants.java b/java/org/apache/catalina/authenticator/Constants.java -index 452a4f0..c9580d6 100644 ---- a/java/org/apache/catalina/authenticator/Constants.java -+++ b/java/org/apache/catalina/authenticator/Constants.java -@@ -93,7 +93,10 @@ public class Constants { - - /** - * The previously authenticated principal (if caching is disabled). -+ * -+ * @deprecated Unused. Will be removed in Tomcat 10. - */ -+ @Deprecated - public static final String FORM_PRINCIPAL_NOTE = - "org.apache.catalina.authenticator.PRINCIPAL"; - -diff --git a/java/org/apache/catalina/authenticator/FormAuthenticator.java b/java/org/apache/catalina/authenticator/FormAuthenticator.java -index 1b54ddd..44c783e 100644 ---- a/java/org/apache/catalina/authenticator/FormAuthenticator.java -+++ b/java/org/apache/catalina/authenticator/FormAuthenticator.java -@@ -133,10 +133,6 @@ public class FormAuthenticator - protected boolean doAuthenticate(Request request, HttpServletResponse response) - throws IOException { - -- if (checkForCachedAuthentication(request, response, true)) { -- return true; -- } -- - // References to objects we will need later - Session session = null; - Principal principal = null; -@@ -158,11 +154,8 @@ public class FormAuthenticator - principal = - context.getRealm().authenticate(username, password); - if (principal != null) { -- session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal); -+ register(request, response, principal, HttpServletRequest.FORM_AUTH, username, password); - if (!matchRequest(request)) { -- register(request, response, principal, -- HttpServletRequest.FORM_AUTH, -- username, password); - return true; - } - } -@@ -181,17 +174,6 @@ public class FormAuthenticator - + session.getIdInternal() - + "'"); - } -- principal = (Principal) -- session.getNote(Constants.FORM_PRINCIPAL_NOTE); -- register(request, response, principal, HttpServletRequest.FORM_AUTH, -- (String) session.getNote(Constants.SESS_USERNAME_NOTE), -- (String) session.getNote(Constants.SESS_PASSWORD_NOTE)); -- // If we're caching principals we no longer need the username -- // and password in the session, so remove them -- if (cache) { -- session.removeNote(Constants.SESS_USERNAME_NOTE); -- session.removeNote(Constants.SESS_PASSWORD_NOTE); -- } - if (restoreRequest(request, session)) { - if (log.isDebugEnabled()) { - log.debug("Proceed to restored request"); -@@ -206,6 +188,12 @@ public class FormAuthenticator - } - } - -+ // This check has to be after the previous check for a matching request -+ // because that matching request may also include a cached Principal. -+ if (checkForCachedAuthentication(request, response, true)) { -+ return true; -+ } -+ - // Acquire references to objects we will need to evaluate - String contextPath = request.getContextPath(); - String requestURI = request.getDecodedRequestURI(); -@@ -297,12 +285,7 @@ public class FormAuthenticator - return false; - } - -- // Save the authenticated Principal in our session -- session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal); -- -- // Save the username and password as well -- session.setNote(Constants.SESS_USERNAME_NOTE, username); -- session.setNote(Constants.SESS_PASSWORD_NOTE, password); -+ register(request, response, principal, HttpServletRequest.FORM_AUTH, username, password); - - // Redirect the user to the original request URI (which will cause - // the original request to be restored) -@@ -510,7 +493,7 @@ public class FormAuthenticator - } - - // Is there a saved principal? -- if (session.getNote(Constants.FORM_PRINCIPAL_NOTE) == null) { -+ if (cache && session.getPrincipal() == null || !cache && request.getPrincipal() == null) { - return false; - } - -@@ -541,7 +524,6 @@ public class FormAuthenticator - SavedRequest saved = (SavedRequest) - session.getNote(Constants.FORM_REQUEST_NOTE); - session.removeNote(Constants.FORM_REQUEST_NOTE); -- session.removeNote(Constants.FORM_PRINCIPAL_NOTE); - if (saved == null) { - return false; - } --- -2.23.0 - diff --git a/CVE-2020-11996.patch b/CVE-2020-11996.patch deleted file mode 100644 index 62ce447..0000000 --- a/CVE-2020-11996.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 9a0231683a77e2957cea0fdee88b193b30b0c976 Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Fri, 22 May 2020 11:27:49 +0100 -Subject: [PATCH] Fix BZ 64467. Improve performance of closing idle streams - ---- - .../coyote/http2/Http2UpgradeHandler.java | 10 +++--- - .../coyote/http2/TestHttp2Section_5_1.java | 31 ++++++++++++++++--- - webapps/docs/changelog.xml | 4 +++ - 3 files changed, 36 insertions(+), 9 deletions(-) - -diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -index bd836940fb..f0d5f27bda 100644 ---- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java -+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -@@ -1343,11 +1343,11 @@ public HeaderEmitter headersStart(int streamId, boolean headersEndStream) - } - - -- private void closeIdleStreams(int newMaxActiveRemoteStreamId) throws Http2Exception { -- for (int i = maxActiveRemoteStreamId + 2; i < newMaxActiveRemoteStreamId; i += 2) { -- Stream stream = getStream(i, false); -- if (stream != null) { -- stream.closeIfIdle(); -+ private void closeIdleStreams(int newMaxActiveRemoteStreamId) { -+ for (Entry entry : streams.entrySet()) { -+ if (entry.getKey().intValue() > maxActiveRemoteStreamId && -+ entry.getKey().intValue() < newMaxActiveRemoteStreamId) { -+ entry.getValue().closeIfIdle(); - } - } - maxActiveRemoteStreamId = newMaxActiveRemoteStreamId; -diff --git a/test/org/apache/coyote/http2/TestHttp2Section_5_1.java b/test/org/apache/coyote/http2/TestHttp2Section_5_1.java -index 2a466814e1..f878653ecf 100644 ---- a/test/org/apache/coyote/http2/TestHttp2Section_5_1.java -+++ b/test/org/apache/coyote/http2/TestHttp2Section_5_1.java -@@ -147,21 +147,44 @@ public void testClientSendOldStream() throws Exception { - - @Test - public void testImplicitClose() throws Exception { -+ doTestImplicitClose(5); -+ } -+ -+ -+ // https://bz.apache.org/bugzilla/show_bug.cgi?id=64467 -+ @Test -+ public void testImplicitCloseLargeId() throws Exception { -+ doTestImplicitClose(Integer.MAX_VALUE - 8); -+ } -+ -+ -+ private void doTestImplicitClose(int lastStreamId) throws Exception { -+ -+ long startFirst = System.nanoTime(); - http2Connect(); -+ long durationFirst = System.nanoTime() - startFirst; - - sendPriority(3, 0, 16); -- sendPriority(5, 0, 16); -+ sendPriority(lastStreamId, 0, 16); - -- sendSimpleGetRequest(5); -+ long startSecond = System.nanoTime(); -+ sendSimpleGetRequest(lastStreamId); - readSimpleGetResponse(); -- Assert.assertEquals(getSimpleResponseTrace(5), output.getTrace()); -+ long durationSecond = System.nanoTime() - startSecond; -+ -+ Assert.assertEquals(getSimpleResponseTrace(lastStreamId), output.getTrace()); - output.clearTrace(); - -+ // Allow second request to take up to 5 times first request or up to 1 second - whichever is the larger - mainly -+ // to allow for CI systems under load that can exhibit significant timing variation. -+ Assert.assertTrue("First request took [" + durationFirst/1000000 + "ms], second request took [" + -+ durationSecond/1000000 + "ms]", durationSecond < 1000000000 || durationSecond < durationFirst * 3); -+ - // Should trigger an error since stream 3 should have been implicitly - // closed. - sendSimpleGetRequest(3); - -- handleGoAwayResponse(5); -+ handleGoAwayResponse(lastStreamId); - } - - -diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml -index 5665df4..7b81937 100644 ---- a/webapps/docs/changelog.xml -+++ b/webapps/docs/changelog.xml -@@ -1803,6 +1803,10 @@ - HTTP 205 responses. Additional fix to r1795278. Based on a patch - provided by Alexandr Saperov. (violetagg) - -+ -+ 64467: Improve performance of closing idle HTTP/2 streams. -+ (markt) -+ - - 61345: Add a server listener that can be used to do system - property replacement from the property source configured in the diff --git a/CVE-2020-13934.patch b/CVE-2020-13934.patch deleted file mode 100644 index 96ada00..0000000 --- a/CVE-2020-13934.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 172977f04a5215128f1e278a688983dcd230f399 Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Fri, 26 Jun 2020 12:49:50 +0100 -Subject: [PATCH] Ensure HTTP/1.1 processor is recycled after a direct h2c - connection - ---- - java/org/apache/coyote/AbstractProtocol.java | 9 ++++++--- - webapps/docs/changelog.xml | 4 ++++ - 2 files changed, 10 insertions(+), 3 deletions(-) - -diff --git a/java/org/apache/coyote/AbstractProtocol.java b/java/org/apache/coyote/AbstractProtocol.java -index cb326dc12e..5bc2212549 100644 ---- a/java/org/apache/coyote/AbstractProtocol.java -+++ b/java/org/apache/coyote/AbstractProtocol.java -@@ -772,8 +772,10 @@ public SocketState process(SocketWrapperBase wrapper, SocketEvent status) { - // Assume direct HTTP/2 connection - UpgradeProtocol upgradeProtocol = getProtocol().getUpgradeProtocol("h2c"); - if (upgradeProtocol != null) { -- processor = upgradeProtocol.getProcessor( -- wrapper, getProtocol().getAdapter()); -+ // Release the Http11 processor to be re-used -+ release(processor); -+ // Create the upgrade processor -+ processor = upgradeProtocol.getProcessor(wrapper, getProtocol().getAdapter()); - wrapper.unRead(leftOverInput); - // Associate with the processor with the connection - connections.put(socket, processor); -@@ -785,7 +785,8 @@ public SocketState process(SocketWrapperBase wrapper, SocketEvent status) { - "abstractConnectionHandler.negotiatedProcessor.fail", - "h2c")); - } -- return SocketState.CLOSED; -+ // Exit loop and trigger appropriate clean-up -+ state = SocketState.CLOSED; - } - } else { - HttpUpgradeHandler httpUpgradeHandler = upgradeToken.getHttpUpgradeHandler(); -diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml -index 5665df4..60cd317 100644 ---- a/webapps/docs/changelog.xml -+++ b/webapps/docs/changelog.xml -@@ -232,6 +236,10 @@ - - Avoid unnecessary processing of async timeouts. (markt) - -+ -+ Ensure that the HTTP/1.1 processor is correctly recycled when a direct -+ connection to h2c is made. (markt) -+ - - - diff --git a/CVE-2020-13935.patch b/CVE-2020-13935.patch deleted file mode 100644 index d8ccc08..0000000 --- a/CVE-2020-13935.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 40fa74c74822711ab878079d0a69f7357926723d Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Mon, 29 Jun 2020 14:02:59 +0100 -Subject: [PATCH] Fix BZ 64563 - additional payload length validation - -https://bz.apache.org/bugzilla/show_bug.cgi?id=64563 ---- - java/org/apache/tomcat/websocket/LocalStrings.properties | 1 + - java/org/apache/tomcat/websocket/WsFrameBase.java | 7 +++++++ - webapps/docs/changelog.xml | 8 ++++++++ - 3 files changed, 16 insertions(+) - -diff --git a/java/org/apache/tomcat/websocket/LocalStrings.properties b/java/org/apache/tomcat/websocket/LocalStrings.properties -index 9412ffeb61..929822d94c 100644 ---- a/java/org/apache/tomcat/websocket/LocalStrings.properties -+++ b/java/org/apache/tomcat/websocket/LocalStrings.properties -@@ -70,6 +70,7 @@ wsFrame.noContinuation=A new message was started when a continuation frame was e - wsFrame.notMasked=The client frame was not masked but all client frames must be masked - wsFrame.oneByteCloseCode=The client sent a close frame with a single byte payload which is not valid - wsFrame.partialHeaderComplete=WebSocket frame received. fin [{0}], rsv [{1}], OpCode [{2}], payload length [{3}] -+wsFrame.payloadMsbInvalid=An invalid WebSocket frame was received - the most significant bit of a 64-bit payload was illegally set - wsFrame.sessionClosed=The client data cannot be processed because the session has already been closed - wsFrame.suspendRequested=Suspend of the message receiving has already been requested. - wsFrame.textMessageTooBig=The decoded text message was too big for the output buffer and the endpoint does not support partial messages -diff --git a/java/org/apache/tomcat/websocket/WsFrameBase.java b/java/org/apache/tomcat/websocket/WsFrameBase.java -index 28cdc30036..4afad67534 100644 ---- a/java/org/apache/tomcat/websocket/WsFrameBase.java -+++ b/java/org/apache/tomcat/websocket/WsFrameBase.java -@@ -261,6 +261,13 @@ private boolean processRemainingHeader() throws IOException { - } else if (payloadLength == 127) { - payloadLength = byteArrayToLong(inputBuffer.array(), - inputBuffer.arrayOffset() + inputBuffer.position(), 8); -+ // The most significant bit of those 8 bytes is required to be zero -+ // (see RFC 6455, section 5.2). If the most significant bit is set, -+ // the resulting payload length will be negative so test for that. -+ if (payloadLength < 0) { -+ throw new WsIOException( -+ new CloseReason(CloseCodes.PROTOCOL_ERROR, sm.getString("wsFrame.payloadMsbInvalid"))); -+ } - inputBuffer.position(inputBuffer.position() + 8); - } - if (Util.isControl(opCode)) { -diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml -index e75f367171..1d1a735c7e 100644 ---- a/webapps/docs/changelog.xml -+++ b/webapps/docs/changelog.xml -@@ -127,6 +127,14 @@ - - - -+ -+ -+ -+ 64563: Add additional validation of payload length for -+ WebSocket messages. (markt) -+ -+ -+ - - - diff --git a/CVE-2020-13943-1.patch b/CVE-2020-13943-1.patch deleted file mode 100644 index e2aa440..0000000 --- a/CVE-2020-13943-1.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 863b18e34f12085820ad02e86ca0ef7e961bb471 Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Wed, 7 Aug 2019 18:59:07 +0100 -Subject: [PATCH 1/5] Extend the timeout functionality to internal upgrade - processors - ---- - .../coyote/http11/upgrade/InternalHttpUpgradeHandler.java | 2 ++ - .../coyote/http11/upgrade/UpgradeProcessorInternal.java | 6 ++++++ - java/org/apache/coyote/http2/Http2UpgradeHandler.java | 6 ++++++ - .../tomcat/websocket/server/WsHttpUpgradeHandler.java | 6 ++++++ - .../coyote/http11/upgrade/TestUpgradeInternalHandler.java | 5 +++++ - 5 files changed, 25 insertions(+) - -diff --git a/java/org/apache/coyote/http11/upgrade/InternalHttpUpgradeHandler.java b/java/org/apache/coyote/http11/upgrade/InternalHttpUpgradeHandler.java -index 936784e20c..426b1bdb89 100644 ---- a/java/org/apache/coyote/http11/upgrade/InternalHttpUpgradeHandler.java -+++ b/java/org/apache/coyote/http11/upgrade/InternalHttpUpgradeHandler.java -@@ -32,6 +32,8 @@ public interface InternalHttpUpgradeHandler extends HttpUpgradeHandler { - - SocketState upgradeDispatch(SocketEvent status); - -+ void timeoutAsync(long now); -+ - void setSocketWrapper(SocketWrapperBase wrapper); - - void setSslSupport(SSLSupport sslSupport); -diff --git a/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java b/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java -index 6397a72a53..f0f546072d 100644 ---- a/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java -+++ b/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java -@@ -73,6 +73,12 @@ public class UpgradeProcessorInternal extends UpgradeProcessorBase { - } - - -+ @Override -+ public void timeoutAsync(long now) { -+ internalHttpUpgradeHandler.timeoutAsync(now); -+ } -+ -+ - // --------------------------------------------------- AutoCloseable methods - - @Override -diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -index 6206f5f5f2..da724652aa 100644 ---- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java -+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -@@ -388,6 +388,12 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - } - - -+ @Override -+ public void timeoutAsync(long now) { -+ // TODO: Implement improved connection timeouts -+ } -+ -+ - ConnectionSettingsRemote getRemoteSettings() { - return remoteSettings; - } -diff --git a/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java b/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java -index 0cde0e3672..5dd1c5a68c 100644 ---- a/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java -+++ b/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java -@@ -189,6 +189,12 @@ public class WsHttpUpgradeHandler implements InternalHttpUpgradeHandler { - } - - -+ @Override -+ public void timeoutAsync(long now) { -+ // NO-OP -+ } -+ -+ - @Override - public void pause() { - // NO-OP -diff --git a/test/org/apache/coyote/http11/upgrade/TestUpgradeInternalHandler.java b/test/org/apache/coyote/http11/upgrade/TestUpgradeInternalHandler.java -index 367f06f5b3..183a8dac7f 100644 ---- a/test/org/apache/coyote/http11/upgrade/TestUpgradeInternalHandler.java -+++ b/test/org/apache/coyote/http11/upgrade/TestUpgradeInternalHandler.java -@@ -256,6 +256,11 @@ public class TestUpgradeInternalHandler extends TomcatBaseTest { - return SocketState.UPGRADED; - } - -+ @Override -+ public void timeoutAsync(long now) { -+ // NO-OP -+ } -+ - @Override - public void setSocketWrapper(SocketWrapperBase wrapper) { - this.wrapper = wrapper; --- -2.23.0 - diff --git a/CVE-2020-13943-2.patch b/CVE-2020-13943-2.patch deleted file mode 100644 index d29bf38..0000000 --- a/CVE-2020-13943-2.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 38ef1f624aaf045458b6fe055742fa680a96a9e1 Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Thu, 7 Mar 2019 10:50:05 +0000 -Subject: [PATCH 2/5] Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63223 - ---- - java/org/apache/coyote/http2/Http2UpgradeHandler.java | 8 ++++++++ - java/org/apache/coyote/http2/Stream.java | 5 +++++ - java/org/apache/coyote/http2/StreamStateMachine.java | 8 +++++++- - 3 files changed, 20 insertions(+), 1 deletion(-) - -diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -index da724652aa..2330d12e09 100644 ---- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java -+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -@@ -555,6 +555,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - synchronized (socketWrapper) { - doWriteHeaders(stream, pushedStreamId, mimeHeaders, endOfStream, payloadSize); - } -+ stream.sentHeaders(); - if (endOfStream) { - stream.sentEndOfStream(); - } -@@ -1178,6 +1179,13 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - - - void push(Request request, Stream associatedStream) throws IOException { -+ if (localSettings.getMaxConcurrentStreams() < activeRemoteStreamCount.incrementAndGet()) { -+ // If there are too many open streams, simply ignore the push -+ // request. -+ activeRemoteStreamCount.decrementAndGet(); -+ return; -+ } -+ - Stream pushStream; - - // Synchronized since PUSH_PROMISE frames have to be sent in order. Once -diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java -index 43aee9d656..629d0210b4 100644 ---- a/java/org/apache/coyote/http2/Stream.java -+++ b/java/org/apache/coyote/http2/Stream.java -@@ -561,6 +561,11 @@ class Stream extends AbstractStream implements HeaderEmitter { - } - - -+ final void sentHeaders() { -+ state.sentHeaders(); -+ } -+ -+ - final void sentEndOfStream() { - streamOutputBuffer.endOfStreamSent = true; - state.sentEndOfStream(); -diff --git a/java/org/apache/coyote/http2/StreamStateMachine.java b/java/org/apache/coyote/http2/StreamStateMachine.java -index 3b67f865d3..d19bb0a255 100644 ---- a/java/org/apache/coyote/http2/StreamStateMachine.java -+++ b/java/org/apache/coyote/http2/StreamStateMachine.java -@@ -53,6 +53,12 @@ class StreamStateMachine { - } - - -+ final synchronized void sentHeaders() { -+ // No change if currently OPEN -+ stateChange(State.RESERVED_LOCAL, State.HALF_CLOSED_REMOTE); -+ } -+ -+ - final synchronized void receivedStartOfHeaders() { - stateChange(State.IDLE, State.OPEN); - stateChange(State.RESERVED_REMOTE, State.HALF_CLOSED_LOCAL); -@@ -170,7 +176,7 @@ class StreamStateMachine { - Http2Error.PROTOCOL_ERROR, FrameType.PRIORITY, - FrameType.RST, - FrameType.WINDOW_UPDATE), -- RESERVED_REMOTE (false, false, true, true, -+ RESERVED_REMOTE (false, true, true, true, - Http2Error.PROTOCOL_ERROR, FrameType.HEADERS, - FrameType.PRIORITY, - FrameType.RST), --- -2.23.0 - diff --git a/CVE-2020-13943-3.patch b/CVE-2020-13943-3.patch deleted file mode 100644 index a52ab3c..0000000 --- a/CVE-2020-13943-3.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 5d7f2eac857cc75757cfc58d003fbf17a23c2720 Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Wed, 7 Aug 2019 17:02:37 +0100 -Subject: [PATCH 3/5] Improve HTTP/2 connection timeout handling - ---- - .../http2/Http2AsyncUpgradeHandler.java | 6 +- - .../coyote/http2/Http2UpgradeHandler.java | 93 ++++++++++++++----- - 2 files changed, 73 insertions(+), 26 deletions(-) - -diff --git a/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java b/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java -index ba49986b5b..107d4bedd2 100644 ---- a/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java -+++ b/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java -@@ -191,7 +191,7 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { - header[4] = FLAG_END_OF_STREAM; - stream.sentEndOfStream(); - if (!stream.isActive()) { -- activeRemoteStreamCount.decrementAndGet(); -+ setConnectionTimeoutForStreamCount(activeRemoteStreamCount.decrementAndGet()); - } - } - if (writeable) { -@@ -297,7 +297,7 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { - header[4] = FLAG_END_OF_STREAM; - sendfile.stream.sentEndOfStream(); - if (!sendfile.stream.isActive()) { -- activeRemoteStreamCount.decrementAndGet(); -+ setConnectionTimeoutForStreamCount(activeRemoteStreamCount.decrementAndGet()); - } - } - if (writeable) { -@@ -358,7 +358,7 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { - header[4] = FLAG_END_OF_STREAM; - sendfile.stream.sentEndOfStream(); - if (!sendfile.stream.isActive()) { -- activeRemoteStreamCount.decrementAndGet(); -+ setConnectionTimeoutForStreamCount(activeRemoteStreamCount.decrementAndGet()); - } - } - if (writeable) { -diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -index 2330d12e09..9c18bf0ca8 100644 ---- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java -+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -@@ -133,6 +133,9 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - // Tracking for when the connection is blocked (windowSize < 1) - private final Map backLogStreams = new ConcurrentHashMap<>(); - private long backLogSize = 0; -+ // The time at which the connection will timeout unless data arrives before -+ // then. -1 means no timeout. -+ private volatile long connectionTimeout = -1; - - // Stream concurrency control - private AtomicInteger streamConcurrency = null; -@@ -313,8 +316,10 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - case OPEN_READ: - try { - // There is data to read so use the read timeout while -- // reading frames. -+ // reading frames ... - socketWrapper.setReadTimeout(protocol.getReadTimeout()); -+ // ... and disable the connection timeout -+ setConnectionTimeout(-1); - while (true) { - try { - if (!parser.readFrame(false)) { -@@ -330,23 +335,22 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - stream.close(se); - } - } -+ if (overheadCount.get() > 0) { -+ throw new ConnectionException( -+ sm.getString("upgradeHandler.tooMuchOverhead", connectionId), -+ Http2Error.ENHANCE_YOUR_CALM); -+ } - } - -- if (overheadCount.get() > 0) { -- throw new ConnectionException( -- sm.getString("upgradeHandler.tooMuchOverhead", connectionId), -- Http2Error.ENHANCE_YOUR_CALM); -- } -+ // Need to know the correct timeout before starting the read -+ // but that may not be known at this time if one or more -+ // requests are currently being processed so don't set a -+ // timeout for the socket... -+ socketWrapper.setReadTimeout(-1); -+ -+ // ...set a timeout on the connection -+ setConnectionTimeoutForStreamCount(activeRemoteStreamCount.get()); - -- if (activeRemoteStreamCount.get() == 0) { -- // No streams currently active. Use the keep-alive -- // timeout for the connection. -- socketWrapper.setReadTimeout(protocol.getKeepAliveTimeout()); -- } else { -- // Streams currently active. Individual streams have -- // timeouts so keep the connection open. -- socketWrapper.setReadTimeout(-1); -- } - } catch (Http2Exception ce) { - // Really ConnectionException - if (log.isDebugEnabled()) { -@@ -367,9 +371,12 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - result = SocketState.UPGRADED; - break; - -+ case TIMEOUT: -+ closeConnection(null); -+ break; -+ - case DISCONNECT: - case ERROR: -- case TIMEOUT: - case STOP: - close(); - break; -@@ -388,9 +395,41 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - } - - -+ /* -+ * Sets the connection timeout based on the current number of active -+ * streams. -+ */ -+ protected void setConnectionTimeoutForStreamCount(int streamCount) { -+ if (streamCount == 0) { -+ // No streams currently active. Use the keep-alive -+ // timeout for the connection. -+ long keepAliveTimeout = protocol.getKeepAliveTimeout(); -+ if (keepAliveTimeout == -1) { -+ setConnectionTimeout(-1); -+ } else { -+ setConnectionTimeout(System.currentTimeMillis() + keepAliveTimeout); -+ } -+ } else { -+ // Streams currently active. Individual streams have -+ // timeouts so keep the connection open. -+ setConnectionTimeout(-1); -+ } -+ } -+ -+ -+ private void setConnectionTimeout(long connectionTimeout) { -+ this.connectionTimeout = connectionTimeout; -+ } -+ -+ - @Override - public void timeoutAsync(long now) { -- // TODO: Implement improved connection timeouts -+ long connectionTimeout = this.connectionTimeout; -+ if (now == -1 || connectionTimeout > -1 && now > connectionTimeout) { -+ // Have to dispatch as this will be executed from a non-container -+ // thread. -+ socketWrapper.processSocket(SocketEvent.TIMEOUT, true); -+ } - } - - -@@ -499,9 +538,17 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - - - void closeConnection(Http2Exception ce) { -+ long code; -+ byte[] msg; -+ if (ce == null) { -+ code = Http2Error.NO_ERROR.getCode(); -+ msg = null; -+ } else { -+ code = ce.getError().getCode(); -+ msg = ce.getMessage().getBytes(StandardCharsets.UTF_8); -+ } - try { -- writeGoAwayFrame(maxProcessedStreamId, ce.getError().getCode(), -- ce.getMessage().getBytes(StandardCharsets.UTF_8)); -+ writeGoAwayFrame(maxProcessedStreamId, code, msg); - } catch (IOException ioe) { - // Ignore. GOAWAY is sent on a best efforts basis and the original - // error has already been logged. -@@ -665,7 +712,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - header[4] = FLAG_END_OF_STREAM; - stream.sentEndOfStream(); - if (!stream.isActive()) { -- activeRemoteStreamCount.decrementAndGet(); -+ setConnectionTimeoutForStreamCount(activeRemoteStreamCount.decrementAndGet()); - } - } - if (writeable) { -@@ -1182,7 +1229,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - if (localSettings.getMaxConcurrentStreams() < activeRemoteStreamCount.incrementAndGet()) { - // If there are too many open streams, simply ignore the push - // request. -- activeRemoteStreamCount.decrementAndGet(); -+ setConnectionTimeoutForStreamCount(activeRemoteStreamCount.decrementAndGet()); - return; - } - -@@ -1301,7 +1348,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - if (stream != null) { - stream.receivedEndOfStream(); - if (!stream.isActive()) { -- activeRemoteStreamCount.decrementAndGet(); -+ setConnectionTimeoutForStreamCount(activeRemoteStreamCount.decrementAndGet()); - } - } - } -@@ -1340,7 +1387,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - stream.receivedStartOfHeaders(headersEndStream); - closeIdleStreams(streamId); - if (localSettings.getMaxConcurrentStreams() < activeRemoteStreamCount.incrementAndGet()) { -- activeRemoteStreamCount.decrementAndGet(); -+ setConnectionTimeoutForStreamCount(activeRemoteStreamCount.decrementAndGet()); - throw new StreamException(sm.getString("upgradeHandler.tooManyRemoteStreams", - Long.toString(localSettings.getMaxConcurrentStreams())), - Http2Error.REFUSED_STREAM, streamId); --- -2.23.0 - diff --git a/CVE-2020-13943-4.patch b/CVE-2020-13943-4.patch deleted file mode 100644 index b10cb40..0000000 --- a/CVE-2020-13943-4.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 902356dc34097b50eb6ca3a74443be466e991a77 Mon Sep 17 00:00:00 2001 -From: wangxiao65 <287608437@qq.com> -Date: Wed, 2 Dec 2020 11:07:21 +0800 -Subject: [PATCH] CVE-2020-13943 - ---- - java/org/apache/coyote/http2/Http2Parser.java | 2 +- - .../coyote/http2/Http2UpgradeHandler.java | 20 ++++++++++++------- - .../coyote/http2/TestHttp2Section_5_1.java | 20 ++++++++++++------- - 3 files changed, 27 insertions(+), 15 deletions(-) - -diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java -index f5e19865b2..6ec659d1e0 100644 ---- a/java/org/apache/coyote/http2/Http2Parser.java -+++ b/java/org/apache/coyote/http2/Http2Parser.java -@@ -721,7 +721,7 @@ class Http2Parser { - // Header frames - HeaderEmitter headersStart(int streamId, boolean headersEndStream) - throws Http2Exception, IOException; -- void headersEnd(int streamId) throws ConnectionException; -+ void headersEnd(int streamId) throws Http2Exception; - - // Priority frames (also headers) - void reprioritise(int streamId, int parentStreamId, boolean exclusive, int weight) -diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -index 9c18bf0ca8..af10cd0838 100644 ---- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java -+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java -@@ -1386,12 +1386,6 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - stream.checkState(FrameType.HEADERS); - stream.receivedStartOfHeaders(headersEndStream); - closeIdleStreams(streamId); -- if (localSettings.getMaxConcurrentStreams() < activeRemoteStreamCount.incrementAndGet()) { -- setConnectionTimeoutForStreamCount(activeRemoteStreamCount.decrementAndGet()); -- throw new StreamException(sm.getString("upgradeHandler.tooManyRemoteStreams", -- Long.toString(localSettings.getMaxConcurrentStreams())), -- Http2Error.REFUSED_STREAM, streamId); -- } - return stream; - } else { - if (log.isDebugEnabled()) { -@@ -1439,12 +1433,24 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH - - - @Override -- public void headersEnd(int streamId) throws ConnectionException { -+ public void headersEnd(int streamId) throws Http2Exception { - Stream stream = getStream(streamId, connectionState.get().isNewStreamAllowed()); - if (stream != null) { - setMaxProcessedStream(streamId); - if (stream.isActive()) { - if (stream.receivedEndOfHeaders()) { -+ -+ if (localSettings.getMaxConcurrentStreams() < activeRemoteStreamCount.incrementAndGet()) { -+ setConnectionTimeoutForStreamCount(activeRemoteStreamCount.decrementAndGet()); -+ // Ignoring maxConcurrentStreams increases the overhead count -+ increaseOverheadCount(); -+ throw new StreamException(sm.getString("upgradeHandler.tooManyRemoteStreams", -+ Long.toString(localSettings.getMaxConcurrentStreams())), -+ Http2Error.REFUSED_STREAM, streamId); -+ } -+ // Valid new stream reduces the overhead count -+ reduceOverheadCount(); -+ - processStreamOnContainerThread(stream); - } - } -diff --git a/test/org/apache/coyote/http2/TestHttp2Section_5_1.java b/test/org/apache/coyote/http2/TestHttp2Section_5_1.java -index f878653ecf..0b937a9fb9 100644 ---- a/test/org/apache/coyote/http2/TestHttp2Section_5_1.java -+++ b/test/org/apache/coyote/http2/TestHttp2Section_5_1.java -@@ -222,11 +222,11 @@ public class TestHttp2Section_5_1 extends Http2TestBase { - // Expecting - // 1 * headers - // 56k-1 of body (7 * ~8k) -- // 1 * error (could be in any order) -- for (int i = 0; i < 8; i++) { -+ // 1 * error -+ // for a total of 9 frames (could be in any order) -+ for (int i = 0; i < 9; i++) { - parser.readFrame(true); - } -- parser.readFrame(true); - - Assert.assertTrue(output.getTrace(), - output.getTrace().contains("5-RST-[" + -@@ -238,14 +238,20 @@ public class TestHttp2Section_5_1 extends Http2TestBase { - - // Release the remaining body - sendWindowUpdate(0, (1 << 31) - 2); -- // Allow for the 8k still in the stream window -+ // Allow for the ~8k still in the stream window - sendWindowUpdate(3, (1 << 31) - 8193); - -- // 192k of body (24 * 8k) -- // 1 * error (could be in any order) -- for (int i = 0; i < 24; i++) { -+ // Read until the end of stream 3 -+ while (!output.getTrace().contains("3-EndOfStream")) { - parser.readFrame(true); - } -+ output.clearTrace(); -+ -+ // Confirm another request can be sent once concurrency falls back below limit -+ sendSimpleGetRequest(7); -+ parser.readFrame(true); -+ parser.readFrame(true); -+ Assert.assertEquals(getSimpleResponseTrace(7), output.getTrace()); - } - - --- -2.23.0 - diff --git a/CVE-2020-17527.patch b/CVE-2020-17527.patch deleted file mode 100644 index f1fafa3..0000000 --- a/CVE-2020-17527.patch +++ /dev/null @@ -1,47 +0,0 @@ -From d56293f816d6dc9e2b47107f208fa9e95db58c65 Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Mon, 9 Nov 2020 19:23:12 +0000 -Subject: [PATCH] Fix BZ 64830 - concurrency issue in HPACK decoder - -https://bz.apache.org/bugzilla/show_bug.cgi?id=64830 ---- - java/org/apache/coyote/http2/HpackDecoder.java | 12 ++++-------- - 1 files changed, 4 insertions(+), 8 deletions(-) - -diff --git a/java/org/apache/coyote/http2/HpackDecoder.java b/java/org/apache/coyote/http2/HpackDecoder.java -index 551101b33a..517dc0b4ae 100644 ---- a/java/org/apache/coyote/http2/HpackDecoder.java -+++ b/java/org/apache/coyote/http2/HpackDecoder.java -@@ -72,8 +72,6 @@ - private volatile boolean countedCookie; - private volatile int headerSize = 0; - -- private final StringBuilder stringBuilder = new StringBuilder(); -- - HpackDecoder(int maxMemorySize) { - this.maxMemorySizeHard = maxMemorySize; - this.maxMemorySizeSoft = maxMemorySize; -@@ -222,19 +220,17 @@ private String readHpackString(ByteBuffer buffer) throws HpackException { - if (huffman) { - return readHuffmanString(length, buffer); - } -+ StringBuilder stringBuilder = new StringBuilder(length); - for (int i = 0; i < length; ++i) { - stringBuilder.append((char) buffer.get()); - } -- String ret = stringBuilder.toString(); -- stringBuilder.setLength(0); -- return ret; -+ return stringBuilder.toString(); - } - - private String readHuffmanString(int length, ByteBuffer buffer) throws HpackException { -+ StringBuilder stringBuilder = new StringBuilder(length); - HPackHuffman.decode(buffer, length, stringBuilder); -- String ret = stringBuilder.toString(); -- stringBuilder.setLength(0); -- return ret; -+ return stringBuilder.toString(); - } - - private String handleIndexedHeaderName(int index) throws HpackException { diff --git a/CVE-2020-1935.patch b/CVE-2020-1935.patch deleted file mode 100644 index 033c655..0000000 --- a/CVE-2020-1935.patch +++ /dev/null @@ -1,443 +0,0 @@ -From 8bfb0ff7f25fe7555a5eb2f7984f73546c11aa26 Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Mon, 6 Jan 2020 20:53:25 +0000 -Subject: [PATCH] Stricter header value parsing - ---- - .../coyote/http11/AbstractHttp11Protocol.java | 51 ++++++++++--- - .../coyote/http11/Http11InputBuffer.java | 51 +++++++++---- - .../apache/coyote/http11/Http11Processor.java | 2 +- - .../apache/tomcat/util/http/MimeHeaders.java | 2 +- - .../tomcat/util/http/parser/HttpParser.java | 11 +++ - .../coyote/http11/TestHttp11InputBuffer.java | 74 +++++++++++++++---- - webapps/docs/config/http.xml | 11 ++- - 8 files changed, 164 insertions(+), 43 deletions(-) - -diff --git a/java/org/apache/coyote/http11/AbstractHttp11Protocol.java b/java/org/apache/coyote/http11/AbstractHttp11Protocol.java -index e5ab885..9d10cbf 100644 ---- a/java/org/apache/coyote/http11/AbstractHttp11Protocol.java -+++ b/java/org/apache/coyote/http11/AbstractHttp11Protocol.java -@@ -136,27 +136,56 @@ public abstract class AbstractHttp11Protocol extends AbstractProtocol { - } - - -- private boolean rejectIllegalHeaderName = true; -+ private boolean rejectIllegalHeader = true; - /** -- * If an HTTP request is received that contains an illegal header name (i.e. -- * the header name is not a token) will the request be rejected (with a 400 -- * response) or will the illegal header be ignored. -+ * If an HTTP request is received that contains an illegal header name or -+ * value (e.g. the header name is not a token) will the request be rejected -+ * (with a 400 response) or will the illegal header be ignored? - * - * @return {@code true} if the request will be rejected or {@code false} if - * the header will be ignored - */ -- public boolean getRejectIllegalHeaderName() { return rejectIllegalHeaderName; } -+ public boolean getRejectIllegalHeader() { return rejectIllegalHeader; } - /** -- * If an HTTP request is received that contains an illegal header name (i.e. -- * the header name is not a token) should the request be rejected (with a -- * 400 response) or should the illegal header be ignored. -+ * If an HTTP request is received that contains an illegal header name or -+ * value (e.g. the header name is not a token) should the request be -+ * rejected (with a 400 response) or should the illegal header be ignored? -+ * -+ * @param rejectIllegalHeader {@code true} to reject requests with illegal -+ * header names or values, {@code false} to -+ * ignore the header -+ */ -+ public void setRejectIllegalHeader(boolean rejectIllegalHeader) { -+ this.rejectIllegalHeader = rejectIllegalHeader; -+ } -+ /** -+ * If an HTTP request is received that contains an illegal header name or -+ * value (e.g. the header name is not a token) will the request be rejected -+ * (with a 400 response) or will the illegal header be ignored? -+ * -+ * @return {@code true} if the request will be rejected or {@code false} if -+ * the header will be ignored -+ * -+ * @deprecated Now an alias for {@link #getRejectIllegalHeader()}. Will be -+ * removed in Tomcat 10 onwards. -+ */ -+ @Deprecated -+ public boolean getRejectIllegalHeaderName() { return rejectIllegalHeader; } -+ /** -+ * If an HTTP request is received that contains an illegal header name or -+ * value (e.g. the header name is not a token) should the request be -+ * rejected (with a 400 response) or should the illegal header be ignored? - * - * @param rejectIllegalHeaderName {@code true} to reject requests with -- * illegal header names, {@code false} to -- * ignore the header -+ * illegal header names or values, -+ * {@code false} to ignore the header -+ * -+ * @deprecated Now an alias for {@link #setRejectIllegalHeader(boolean)}. -+ * Will be removed in Tomcat 10 onwards. - */ -+ @Deprecated - public void setRejectIllegalHeaderName(boolean rejectIllegalHeaderName) { -- this.rejectIllegalHeaderName = rejectIllegalHeaderName; -+ this.rejectIllegalHeader = rejectIllegalHeaderName; - } - - -diff --git a/java/org/apache/coyote/http11/Http11InputBuffer.java b/java/org/apache/coyote/http11/Http11InputBuffer.java -index 2dc7c17..57c670e 100644 ---- a/java/org/apache/coyote/http11/Http11InputBuffer.java -+++ b/java/org/apache/coyote/http11/Http11InputBuffer.java -@@ -64,7 +64,7 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler - private final MimeHeaders headers; - - -- private final boolean rejectIllegalHeaderName; -+ private final boolean rejectIllegalHeader; - - /** - * State. -@@ -150,13 +150,13 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler - // ----------------------------------------------------------- Constructors - - public Http11InputBuffer(Request request, int headerBufferSize, -- boolean rejectIllegalHeaderName, HttpParser httpParser) { -+ boolean rejectIllegalHeader, HttpParser httpParser) { - - this.request = request; - headers = request.getMimeHeaders(); - - this.headerBufferSize = headerBufferSize; -- this.rejectIllegalHeaderName = rejectIllegalHeaderName; -+ this.rejectIllegalHeader = rejectIllegalHeader; - this.httpParser = httpParser; - - filterLibrary = new InputFilter[0]; -@@ -752,6 +752,8 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler - // - - byte chr = 0; -+ byte prevChr = 0; -+ - while (headerParsePos == HeaderParsePosition.HEADER_START) { - - // Read new bytes if needed -@@ -762,17 +764,23 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler - } - } - -+ prevChr = chr; - chr = byteBuffer.get(); - -- if (chr == Constants.CR) { -- // Skip -- } else if (chr == Constants.LF) { -+ if (chr == Constants.CR && prevChr != Constants.CR) { -+ // Possible start of CRLF - process the next byte. -+ } else if (prevChr == Constants.CR && chr == Constants.LF) { - return HeaderParseStatus.DONE; - } else { -- byteBuffer.position(byteBuffer.position() - 1); -+ if (prevChr == 0) { -+ // Must have only read one byte -+ byteBuffer.position(byteBuffer.position() - 1); -+ } else { -+ // Must have read two bytes (first was CR, second was not LF) -+ byteBuffer.position(byteBuffer.position() - 2); -+ } - break; - } -- - } - - if (headerParsePos == HeaderParsePosition.HEADER_START) { -@@ -868,11 +876,22 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler - } - } - -+ prevChr = chr; - chr = byteBuffer.get(); - if (chr == Constants.CR) { -- // Skip -- } else if (chr == Constants.LF) { -+ // Possible start of CRLF - process the next byte. -+ } else if (prevChr == Constants.CR && chr == Constants.LF) { - eol = true; -+ } else if (prevChr == Constants.CR) { -+ // Invalid value -+ // Delete the header (it will be the most recent one) -+ headers.removeHeader(headers.size() - 1); -+ return skipLine(); -+ } else if (chr != Constants.HT && HttpParser.isControl(chr)) { -+ // Invalid value -+ // Delete the header (it will be the most recent one) -+ headers.removeHeader(headers.size() - 1); -+ return skipLine(); - } else if (chr == Constants.SP || chr == Constants.HT) { - byteBuffer.put(headerData.realPos, chr); - headerData.realPos++; -@@ -924,6 +943,9 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler - headerParsePos = HeaderParsePosition.HEADER_SKIPLINE; - boolean eol = false; - -+ byte chr = 0; -+ byte prevChr = 0; -+ - // Reading bytes until the end of the line - while (!eol) { - -@@ -935,21 +957,22 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler - } - - int pos = byteBuffer.position(); -- byte chr = byteBuffer.get(); -+ prevChr = chr; -+ chr = byteBuffer.get(); - if (chr == Constants.CR) { - // Skip -- } else if (chr == Constants.LF) { -+ } else if (prevChr == Constants.CR && chr == Constants.LF) { - eol = true; - } else { - headerData.lastSignificantChar = pos; - } - } -- if (rejectIllegalHeaderName || log.isDebugEnabled()) { -+ if (rejectIllegalHeader || log.isDebugEnabled()) { - String message = sm.getString("iib.invalidheader", - new String(byteBuffer.array(), headerData.start, - headerData.lastSignificantChar - headerData.start + 1, - StandardCharsets.ISO_8859_1)); -- if (rejectIllegalHeaderName) { -+ if (rejectIllegalHeader) { - throw new IllegalArgumentException(message); - } - log.debug(message); -diff --git a/java/org/apache/coyote/http11/Http11Processor.java b/java/org/apache/coyote/http11/Http11Processor.java -index df002e0..86556ec 100644 ---- a/java/org/apache/coyote/http11/Http11Processor.java -+++ b/java/org/apache/coyote/http11/Http11Processor.java -@@ -153,7 +153,7 @@ public class Http11Processor extends AbstractProcessor { - protocol.getRelaxedQueryChars()); - - inputBuffer = new Http11InputBuffer(request, protocol.getMaxHttpHeaderSize(), -- protocol.getRejectIllegalHeaderName(), httpParser); -+ protocol.getRejectIllegalHeader(), httpParser); - request.setInputBuffer(inputBuffer); - - outputBuffer = new Http11OutputBuffer(response, protocol.getMaxHttpHeaderSize()); -diff --git a/java/org/apache/tomcat/util/http/MimeHeaders.java b/java/org/apache/tomcat/util/http/MimeHeaders.java -index 59504ee..b76b274 100644 ---- a/java/org/apache/tomcat/util/http/MimeHeaders.java -+++ b/java/org/apache/tomcat/util/http/MimeHeaders.java -@@ -396,7 +396,7 @@ public class MimeHeaders { - * reset and swap with last header - * @param idx the index of the header to remove. - */ -- private void removeHeader(int idx) { -+ public void removeHeader(int idx) { - MimeHeaderField mh = headers[idx]; - - mh.recycle(); -diff --git a/java/org/apache/tomcat/util/http/parser/HttpParser.java b/java/org/apache/tomcat/util/http/parser/HttpParser.java -index 827f2c5..644b1d1 100644 ---- a/java/org/apache/tomcat/util/http/parser/HttpParser.java -+++ b/java/org/apache/tomcat/util/http/parser/HttpParser.java -@@ -317,6 +317,17 @@ public class HttpParser { - } - - -+ public static boolean isControl(int c) { -+ // Fast for valid control characters, slower for some incorrect -+ // ones -+ try { -+ return IS_CONTROL[c]; -+ } catch (ArrayIndexOutOfBoundsException ex) { -+ return false; -+ } -+ } -+ -+ - // Skip any LWS and position to read the next character. The next character - // is returned as being able to 'peek()' it allows a small optimisation in - // some cases. -diff --git a/test/org/apache/coyote/http11/TestHttp11InputBuffer.java b/test/org/apache/coyote/http11/TestHttp11InputBuffer.java -index 131fa21..e60a474 100644 ---- a/test/org/apache/coyote/http11/TestHttp11InputBuffer.java -+++ b/test/org/apache/coyote/http11/TestHttp11InputBuffer.java -@@ -163,13 +163,13 @@ public class TestHttp11InputBuffer extends TomcatBaseTest { - - - @Test -- public void testBug51557Separators() throws Exception { -+ public void testBug51557SeparatorsInName() throws Exception { - char httpSeparators[] = new char[] { - '\t', ' ', '\"', '(', ')', ',', '/', ':', ';', '<', - '=', '>', '?', '@', '[', '\\', ']', '{', '}' }; - - for (char s : httpSeparators) { -- doTestBug51557Char(s); -+ doTestBug51557CharInName(s); - tearDown(); - setUp(); - } -@@ -177,13 +177,38 @@ public class TestHttp11InputBuffer extends TomcatBaseTest { - - - @Test -- public void testBug51557Ctl() throws Exception { -+ public void testBug51557CtlInName() throws Exception { - for (int i = 0; i < 31; i++) { -- doTestBug51557Char((char) i); -+ doTestBug51557CharInName((char) i); -+ tearDown(); -+ setUp(); -+ } -+ doTestBug51557CharInName((char) 127); -+ } -+ -+ -+ @Test -+ public void testBug51557CtlInValue() throws Exception { -+ for (int i = 0; i < 31; i++) { -+ if (i == '\t') { -+ // TAB is allowed -+ continue; -+ } -+ doTestBug51557InvalidCharInValue((char) i); -+ tearDown(); -+ setUp(); -+ } -+ doTestBug51557InvalidCharInValue((char) 127); -+ } -+ -+ -+ @Test -+ public void testBug51557ObsTextInValue() throws Exception { -+ for (int i = 128; i < 255; i++) { -+ doTestBug51557ValidCharInValue((char) i); - tearDown(); - setUp(); - } -- doTestBug51557Char((char) 127); - } - - -@@ -226,7 +251,7 @@ public class TestHttp11InputBuffer extends TomcatBaseTest { - } - - -- private void doTestBug51557Char(char s) { -+ private void doTestBug51557CharInName(char s) { - Bug51557Client client = - new Bug51557Client("X-Bug" + s + "51557", "invalid"); - -@@ -236,6 +261,29 @@ public class TestHttp11InputBuffer extends TomcatBaseTest { - Assert.assertTrue(client.isResponseBodyOK()); - } - -+ -+ private void doTestBug51557InvalidCharInValue(char s) { -+ Bug51557Client client = -+ new Bug51557Client("X-Bug51557-Invalid", "invalid" + s + "invalid"); -+ -+ client.doRequest(); -+ Assert.assertTrue("Testing [" + (int) s + "]", client.isResponse200()); -+ Assert.assertEquals("Testing [" + (int) s + "]", "abcd", client.getResponseBody()); -+ Assert.assertTrue(client.isResponseBodyOK()); -+ } -+ -+ -+ private void doTestBug51557ValidCharInValue(char s) { -+ Bug51557Client client = -+ new Bug51557Client("X-Bug51557-Valid", "valid" + s + "valid"); -+ -+ client.doRequest(); -+ Assert.assertTrue("Testing [" + (int) s + "]", client.isResponse200()); -+ Assert.assertEquals("Testing [" + (int) s + "]", "valid" + s + "validabcd", client.getResponseBody()); -+ Assert.assertTrue(client.isResponseBodyOK()); -+ } -+ -+ - /** - * Bug 51557 test client. - */ -@@ -243,12 +291,12 @@ public class TestHttp11InputBuffer extends TomcatBaseTest { - - private final String headerName; - private final String headerLine; -- private final boolean rejectIllegalHeaderName; -+ private final boolean rejectIllegalHeader; - - public Bug51557Client(String headerName) { - this.headerName = headerName; - this.headerLine = headerName; -- this.rejectIllegalHeaderName = false; -+ this.rejectIllegalHeader = false; - } - - public Bug51557Client(String headerName, String headerValue) { -@@ -256,10 +304,10 @@ public class TestHttp11InputBuffer extends TomcatBaseTest { - } - - public Bug51557Client(String headerName, String headerValue, -- boolean rejectIllegalHeaderName) { -+ boolean rejectIllegalHeader) { - this.headerName = headerName; - this.headerLine = headerName + ": " + headerValue; -- this.rejectIllegalHeaderName = rejectIllegalHeaderName; -+ this.rejectIllegalHeader = rejectIllegalHeader; - } - - private Exception doRequest() { -@@ -273,8 +321,8 @@ public class TestHttp11InputBuffer extends TomcatBaseTest { - - try { - Connector connector = tomcat.getConnector(); -- connector.setProperty("rejectIllegalHeaderName", -- Boolean.toString(rejectIllegalHeaderName)); -+ connector.setProperty("rejectIllegalHeader", -+ Boolean.toString(rejectIllegalHeader)); - tomcat.start(); - setPort(connector.getLocalPort()); - -@@ -548,7 +596,7 @@ public class TestHttp11InputBuffer extends TomcatBaseTest { - - try { - Connector connector = tomcat.getConnector(); -- connector.setProperty("rejectIllegalHeaderName", "false"); -+ connector.setProperty("rejectIllegalHeader", "false"); - tomcat.start(); - setPort(connector.getLocalPort()); - -diff --git a/webapps/docs/config/http.xml b/webapps/docs/config/http.xml -index ebb277d..3902c9a 100644 ---- a/webapps/docs/config/http.xml -+++ b/webapps/docs/config/http.xml -@@ -551,14 +551,19 @@ - expected concurrent requests (synchronous and asynchronous).

-
- -- --

If an HTTP request is received that contains an illegal header name -- (i.e. the header name is not a token) this setting determines if the -+ -+

If an HTTP request is received that contains an illegal header name or -+ value (e.g. the header name is not a token) this setting determines if the - request will be rejected with a 400 response (true) or if the - illegal header be ignored (false). The default value is - true which will cause the request to be rejected.

-
- -+ -+

This attribute is deprecated. It will be removed in Tomcat 10 onwards. -+ It is now an alias for rejectIllegalHeader.

-+
-+ - -

The HTTP/1.1 - specification requires that certain characters are %nn encoded when --- -2.23.0 - diff --git a/CVE-2020-1938-1.patch b/CVE-2020-1938-1.patch deleted file mode 100644 index c2feb27..0000000 --- a/CVE-2020-1938-1.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0e8a50f0a5958744bea1fd6768c862e04d3b7e75 Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Tue, 21 Jan 2020 13:02:13 +0000 -Subject: [PATCH] Change the default bind address for AJP to the loopback - address - ---- - java/org/apache/coyote/ajp/AbstractAjpProtocol.java | 4 ++++ - webapps/docs/changelog.xml | 4 ++++ - webapps/docs/config/ajp.xml | 5 +---- - 3 files changed, 9 insertions(+), 4 deletions(-) - -diff --git a/java/org/apache/coyote/ajp/AbstractAjpProtocol.java b/java/org/apache/coyote/ajp/AbstractAjpProtocol.java -index 2500abd7ad..8e0593b771 100644 ---- a/java/org/apache/coyote/ajp/AbstractAjpProtocol.java -+++ b/java/org/apache/coyote/ajp/AbstractAjpProtocol.java -@@ -16,6 +16,8 @@ - */ - package org.apache.coyote.ajp; - -+import java.net.InetAddress; -+ - import org.apache.coyote.AbstractProtocol; - import org.apache.coyote.Processor; - import org.apache.coyote.UpgradeProtocol; -@@ -46,6 +48,8 @@ public AbstractAjpProtocol(AbstractEndpoint endpoint) { - setConnectionTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT); - // AJP does not use Send File - getEndpoint().setUseSendfile(false); -+ // AJP listens on loopback by default -+ getEndpoint().setAddress(InetAddress.getLoopbackAddress()); - ConnectionHandler cHandler = new ConnectionHandler<>(this); - setHandler(cHandler); - getEndpoint().setHandler(cHandler); -diff --git a/webapps/docs/config/ajp.xml b/webapps/docs/config/ajp.xml -index c70af91eae..5535a062e7 100644 ---- a/webapps/docs/config/ajp.xml -+++ b/webapps/docs/config/ajp.xml -@@ -308,10 +308,7 @@ - -

For servers with more than one IP address, this attribute - specifies which address will be used for listening on the specified -- port. By default, this port will be used on all IP addresses -- associated with the server. A value of 127.0.0.1 -- indicates that the Connector will only listen on the loopback -- interface.

-+ port. By default, the loopback address will be used.

-
- - diff --git a/CVE-2020-1938-2.patch b/CVE-2020-1938-2.patch deleted file mode 100644 index cb57232..0000000 --- a/CVE-2020-1938-2.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 9ac90532e9a7d239f90952edb229b07c80a9a3eb Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Tue, 21 Jan 2020 14:24:33 +0000 -Subject: [PATCH] Rename requiredSecret to secret and add secretRequired - -AJP Connector will not start if secretRequired="true" and secret is set -to null or zero length String. ---- - .../coyote/ajp/AbstractAjpProtocol.java | 49 +++++++++++++++++-- - java/org/apache/coyote/ajp/AjpProcessor.java | 12 ++--- - .../apache/coyote/ajp/LocalStrings.properties | 1 + - webapps/docs/config/ajp.xml | 12 ++++- - 5 files changed, 72 insertions(+), 10 deletions(-) - -diff --git a/java/org/apache/coyote/ajp/AbstractAjpProtocol.java b/java/org/apache/coyote/ajp/AbstractAjpProtocol.java -index 8e0593b771..81da7da6d1 100644 ---- a/java/org/apache/coyote/ajp/AbstractAjpProtocol.java -+++ b/java/org/apache/coyote/ajp/AbstractAjpProtocol.java -@@ -143,17 +143,48 @@ public void setTomcatAuthorization(boolean tomcatAuthorization) { - } - - -- private String requiredSecret = null; -+ private String secret = null; -+ /** -+ * Set the secret that must be included with every request. -+ * -+ * @param secret The required secret -+ */ -+ public void setSecret(String secret) { -+ this.secret = secret; -+ } -+ protected String getSecret() { -+ return secret; -+ } - /** - * Set the required secret that must be included with every request. - * - * @param requiredSecret The required secret -+ * -+ * @deprecated Replaced by {@link #setSecret(String)}. -+ * Will be removed in Tomcat 11 onwards - */ -+ @Deprecated - public void setRequiredSecret(String requiredSecret) { -- this.requiredSecret = requiredSecret; -+ setSecret(requiredSecret); - } -+ /** -+ * @return The current secret -+ * -+ * @deprecated Replaced by {@link #getSecret()}. -+ * Will be removed in Tomcat 11 onwards -+ */ -+ @Deprecated - protected String getRequiredSecret() { -- return requiredSecret; -+ return getSecret(); -+ } -+ -+ -+ private boolean secretRequired = true; -+ public void setSecretRequired(boolean secretRequired) { -+ this.secretRequired = secretRequired; -+ } -+ public boolean getSecretRequired() { -+ return secretRequired; - } - - -@@ -210,4 +241,16 @@ protected Processor createUpgradeProcessor(SocketWrapperBase socket, - throw new IllegalStateException(sm.getString("ajpprotocol.noUpgradeHandler", - upgradeToken.getHttpUpgradeHandler().getClass().getName())); - } -+ -+ -+ @Override -+ public void init() throws Exception { -+ if (getSecretRequired()) { -+ String secret = getSecret(); -+ if (secret == null || secret.length() == 0) { -+ throw new IllegalArgumentException(sm.getString("ajpprotocol.nosecret")); -+ } -+ } -+ super.init(); -+ } - } -diff --git a/java/org/apache/coyote/ajp/AjpProcessor.java b/java/org/apache/coyote/ajp/AjpProcessor.java -index a3e628d2eb..d466de2c09 100644 ---- a/java/org/apache/coyote/ajp/AjpProcessor.java -+++ b/java/org/apache/coyote/ajp/AjpProcessor.java -@@ -698,8 +698,8 @@ private void prepareRequest() { - } - - // Decode extra attributes -- String requiredSecret = protocol.getRequiredSecret(); -- boolean secret = false; -+ String secret = protocol.getSecret(); -+ boolean secretPresentInRequest = false; - byte attributeCode; - while ((attributeCode = requestHeaderMessage.getByte()) - != Constants.SC_A_ARE_DONE) { -@@ -801,9 +801,9 @@ private void prepareRequest() { - - case Constants.SC_A_SECRET: - requestHeaderMessage.getBytes(tmpMB); -- if (requiredSecret != null) { -- secret = true; -- if (!tmpMB.equals(requiredSecret)) { -+ if (secret != null) { -+ secretPresentInRequest = true; -+ if (!tmpMB.equals(secret)) { - response.setStatus(403); - setErrorState(ErrorState.CLOSE_CLEAN, null); - } -@@ -819,7 +819,7 @@ private void prepareRequest() { - } - - // Check if secret was submitted if required -- if ((requiredSecret != null) && !secret) { -+ if ((secret != null) && !secretPresentInRequest) { - response.setStatus(403); - setErrorState(ErrorState.CLOSE_CLEAN, null); - } -diff --git a/java/org/apache/coyote/ajp/LocalStrings.properties b/java/org/apache/coyote/ajp/LocalStrings.properties -index 9b569bbc6e..01de92a424 100644 ---- a/java/org/apache/coyote/ajp/LocalStrings.properties -+++ b/java/org/apache/coyote/ajp/LocalStrings.properties -@@ -28,6 +28,7 @@ ajpprocessor.request.prepare=Error preparing request - # limitations under the License. - - ajpprotocol.noSSL=SSL is not supported with AJP. The SSL host configuration for [{0}] was ignored -+ajpprotocol.nosecret=The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid. - ajpprotocol.noUpgrade=Upgrade is not supported with AJP. The UpgradeProtocol configuration for [{0}] was ignored - ajpprotocol.noUpgradeHandler=Upgrade is not supported with AJP. The HttpUpgradeHandler [{0}] can not be processed - -diff --git a/webapps/docs/config/ajp.xml b/webapps/docs/config/ajp.xml -index 5535a062e7..3999a13e66 100644 ---- a/webapps/docs/config/ajp.xml -+++ b/webapps/docs/config/ajp.xml -@@ -428,8 +428,18 @@ - expected concurrent requests (synchronous and asynchronous).

-
- -- -+ -

Only requests from workers with this secret keyword will be accepted. -+ The default value is null. This attrbute must be specified -+ with a non-null, non-zero length value unless -+ secretRequired is explicitly configured to be -+ false.

-+
-+ -+ -+

If this attribute is true, the AJP Connector will only -+ start if the secret attribute is configured with a -+ non-null, non-zero length value. The default value is true. -

-
- diff --git a/CVE-2020-1938-3.patch b/CVE-2020-1938-3.patch deleted file mode 100644 index dc152a7..0000000 --- a/CVE-2020-1938-3.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 64fa5b99442589ef0bf2a7fcd71ad2bc68b35fad Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Tue, 21 Jan 2020 15:04:12 +0000 -Subject: [PATCH] Add new AJP attribute allowedArbitraryRequestAttributes - -Requests with unrecognised attributes will be blocked with a 403 ---- - .../coyote/ajp/AbstractAjpProtocol.java | 13 +++++++ - java/org/apache/coyote/ajp/AjpProcessor.java | 36 ++++++++++++++++++- - webapps/docs/config/ajp.xml | 19 ++++++++++ - 4 files changed, 72 insertions(+), 1 deletion(-) - -diff --git a/java/org/apache/coyote/ajp/AbstractAjpProtocol.java b/java/org/apache/coyote/ajp/AbstractAjpProtocol.java -index 81da7da6d1..a2f5e2844a 100644 ---- a/java/org/apache/coyote/ajp/AbstractAjpProtocol.java -+++ b/java/org/apache/coyote/ajp/AbstractAjpProtocol.java -@@ -17,6 +17,7 @@ - package org.apache.coyote.ajp; - - import java.net.InetAddress; -+import java.util.regex.Pattern; - - import org.apache.coyote.AbstractProtocol; - import org.apache.coyote.Processor; -@@ -188,6 +189,18 @@ public boolean getSecretRequired() { - } - - -+ private Pattern allowedArbitraryRequestAttributesPattern; -+ public void setAllowedArbitraryRequestAttributes(String allowedArbitraryRequestAttributes) { -+ this.allowedArbitraryRequestAttributesPattern = Pattern.compile(allowedArbitraryRequestAttributes); -+ } -+ public String getAllowedArbitraryRequestAttributes() { -+ return allowedArbitraryRequestAttributesPattern.pattern(); -+ } -+ protected Pattern getAllowedArbitraryRequestAttributesPattern() { -+ return allowedArbitraryRequestAttributesPattern; -+ } -+ -+ - /** - * AJP packet size. - */ -diff --git a/java/org/apache/coyote/ajp/AjpProcessor.java b/java/org/apache/coyote/ajp/AjpProcessor.java -index d466de2c09..f3d783f546 100644 ---- a/java/org/apache/coyote/ajp/AjpProcessor.java -+++ b/java/org/apache/coyote/ajp/AjpProcessor.java -@@ -25,6 +25,11 @@ - import java.security.NoSuchProviderException; - import java.security.cert.CertificateFactory; - import java.security.cert.X509Certificate; -+import java.util.Collections; -+import java.util.HashSet; -+import java.util.Set; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; - - import javax.servlet.http.HttpServletResponse; - -@@ -78,6 +83,9 @@ - private static final byte[] pongMessageArray; - - -+ private static final Set javaxAttributes; -+ -+ - static { - // Allocate the end message array - AjpMessage endMessage = new AjpMessage(16); -@@ -118,6 +126,14 @@ - pongMessageArray = new byte[pongMessage.getLen()]; - System.arraycopy(pongMessage.getBuffer(), 0, pongMessageArray, - 0, pongMessage.getLen()); -+ -+ // Build the Set of javax attributes -+ Set s = new HashSet<>(); -+ s.add("javax.servlet.request.cipher_suite"); -+ s.add("javax.servlet.request.key_size"); -+ s.add("javax.servlet.request.ssl_session"); -+ s.add("javax.servlet.request.X509Certificate"); -+ javaxAttributes= Collections.unmodifiableSet(s); - } - - -@@ -728,8 +744,26 @@ private void prepareRequest() { - } - } else if(n.equals(Constants.SC_A_SSL_PROTOCOL)) { - request.setAttribute(SSLSupport.PROTOCOL_VERSION_KEY, v); -+ } else if (n.equals("JK_LB_ACTIVATION")) { -+ request.setAttribute(n, v); -+ } else if (javaxAttributes.contains(n)) { -+ request.setAttribute(n, v); - } else { -- request.setAttribute(n, v ); -+ // All 'known' attributes will be processed by the previous -+ // blocks. Any remaining attribute is an 'arbitrary' one. -+ Pattern pattern = protocol.getAllowedArbitraryRequestAttributesPattern(); -+ if (pattern == null) { -+ response.setStatus(403); -+ setErrorState(ErrorState.CLOSE_CLEAN, null); -+ } else { -+ Matcher m = pattern.matcher(n); -+ if (m.matches()) { -+ request.setAttribute(n, v); -+ } else { -+ response.setStatus(403); -+ setErrorState(ErrorState.CLOSE_CLEAN, null); -+ } -+ } - } - break; - -diff --git a/webapps/docs/config/ajp.xml b/webapps/docs/config/ajp.xml -index 3999a13e66..69348a18e2 100644 ---- a/webapps/docs/config/ajp.xml -+++ b/webapps/docs/config/ajp.xml -@@ -311,6 +311,25 @@ - port. By default, the loopback address will be used.

-
- -+ -+

The AJP protocol passes some information from the reverse proxy to the -+ AJP connector using request attributes. These attributes are:

-+
    -+
  • javax.servlet.request.cipher_suite
  • -+
  • javax.servlet.request.key_size
  • -+
  • javax.servlet.request.ssl_session
  • -+
  • javax.servlet.request.X509Certificate
  • -+
  • AJP_LOCAL_ADDR
  • -+
  • AJP_REMOTE_PORT
  • -+
  • AJP_SSL_PROTOCOL
  • -+
  • JK_LB_ACTIVATION
  • -+
-+

The AJP protocol supports the passing of arbitrary request attributes. -+ Requests containing arbitrary request attributes will be rejected with a -+ 403 response unless the entire attribute name matches this regular -+ expression. If not specified, the default value is null.

-+
-+ - -

Controls when the socket used by the connector is bound. By default it - is bound when the connector is initiated and unbound when the connector is diff --git a/CVE-2020-1938-4.patch b/CVE-2020-1938-4.patch deleted file mode 100644 index e5e6108..0000000 --- a/CVE-2020-1938-4.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 5716044b61cb5b638d8f0de848ac64df03184bc7 Mon Sep 17 00:00:00 2001 -From: wang_yue111 -Date: Mon, 18 May 2020 15:23:19 +0800 -Subject: [PATCH] 3 - ---- - conf/server.xml | 5 ++++- - .../apache/coyote/ajp/AbstractAjpProtocol.java | 18 +++++++++--------- - java/org/apache/coyote/ajp/AjpProcessor.java | 2 +- - webapps/docs/config/ajp.xml | 2 +- - 4 files changed, 15 insertions(+), 12 deletions(-) - -diff --git a/conf/server.xml b/conf/server.xml -index fce8922..81a4e16 100644 ---- a/conf/server.xml -+++ b/conf/server.xml -@@ -113,7 +113,10 @@ - --> - - -- -+ - - - -+ -+ -+ -+ Update the internal fork of Apache Commons FileUpload to 34eb241 -+ (2023-01-03, 2.0-SNAPSHOT). (markt) -+ -+ -+ -

- - -diff --git a/webapps/docs/config/ajp.xml b/webapps/docs/config/ajp.xml -index 622e7ca..38c5269 100644 ---- a/webapps/docs/config/ajp.xml -+++ b/webapps/docs/config/ajp.xml -@@ -114,12 +114,15 @@ - - - --

The maximum number of parameter and value pairs (GET plus POST) which -- will be automatically parsed by the container. Parameter and value pairs -- beyond this limit will be ignored. A value of less than 0 means no limit. -- If not specified, a default of 10000 is used. Note that -- FailedRequestFilter filter can be -- used to reject requests that hit the limit.

-+

The maximum total number of request parameters (including uploaded -+ files) obtained from the query string and, for POST requests, the request -+ body if the content type is -+ application/x-www-form-urlencoded or -+ multipart/form-data. Request parameters beyond this limit -+ will be ignored. A value of less than 0 means no limit. If not specified, -+ a default of 10000 is used. Note that FailedRequestFilter -+ filter can be used to reject requests that -+ exceed the limit.

-
- - -diff --git a/webapps/docs/config/http.xml b/webapps/docs/config/http.xml -index 3902c9a..52ad063 100644 ---- a/webapps/docs/config/http.xml -+++ b/webapps/docs/config/http.xml -@@ -111,12 +111,15 @@ - - - --

The maximum number of parameter and value pairs (GET plus POST) which -- will be automatically parsed by the container. Parameter and value pairs -- beyond this limit will be ignored. A value of less than 0 means no limit. -- If not specified, a default of 10000 is used. Note that -- FailedRequestFilter filter can be -- used to reject requests that hit the limit.

-+

The maximum total number of request parameters (including uploaded -+ files) obtained from the query string and, for POST requests, the request -+ body if the content type is -+ application/x-www-form-urlencoded or -+ multipart/form-data. Request parameters beyond this limit -+ will be ignored. A value of less than 0 means no limit. If not specified, -+ a default of 10000 is used. Note that FailedRequestFilter -+ filter can be used to reject requests that -+ exceed the limit.

-
- - --- -2.33.0 diff --git a/CVE-2023-28708-pre.patch b/CVE-2023-28708-pre.patch deleted file mode 100644 index 01ed17b..0000000 --- a/CVE-2023-28708-pre.patch +++ /dev/null @@ -1,238 +0,0 @@ -From 09e214c09c78a48ea96b0137555b3c2a98a1bfab Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Tue, 31 Mar 2020 14:03:17 +0100 -Subject: [PATCH] Make the HTTP/2 connection ID and stream Id available to - applications -Origin: https://github.com/apache/tomcat/commit/09e214c09c78a48ea96b0137555b3c2a98a1bfab - ---- - java/org/apache/catalina/Globals.java | 16 ++++++++ - .../apache/catalina/connector/Request.java | 27 +++++++++++++ - java/org/apache/coyote/AbstractProcessor.java | 39 +++++++++++++++++++ - java/org/apache/coyote/ActionCode.java | 14 ++++++- - .../apache/coyote/http2/StreamProcessor.java | 12 ++++++ - webapps/docs/changelog.xml | 5 +++ - webapps/docs/config/http2.xml | 9 +++++ - 7 files changed, 121 insertions(+), 1 deletion(-) - -diff --git a/java/org/apache/catalina/Globals.java b/java/org/apache/catalina/Globals.java -index 994902b..c19d69c 100644 ---- a/java/org/apache/catalina/Globals.java -+++ b/java/org/apache/catalina/Globals.java -@@ -112,6 +112,22 @@ public final class Globals { - "org.apache.catalina.NAMED"; - - -+ /** -+ * The request attribute used to expose the current connection ID associated -+ * with the request, if any. Used with multiplexing protocols such as -+ * HTTTP/2. -+ */ -+ public static final String CONNECTION_ID = "org.apache.coyote.connectionID"; -+ -+ -+ /** -+ * The request attribute used to expose the current stream ID associated -+ * with the request, if any. Used with multiplexing protocols such as -+ * HTTTP/2. -+ */ -+ public static final String STREAM_ID = "org.apache.coyote.streamID"; -+ -+ - /** - * The servlet context attribute under which we store a flag used - * to mark this request as having been processed by the SSIServlet. -diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java -index c4cc26a..94065ef 100644 ---- a/java/org/apache/catalina/connector/Request.java -+++ b/java/org/apache/catalina/connector/Request.java -@@ -40,6 +40,7 @@ import java.util.TimeZone; - import java.util.TreeMap; - import java.util.concurrent.ConcurrentHashMap; - import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.concurrent.atomic.AtomicReference; - - import javax.naming.NamingException; - import javax.security.auth.Subject; -@@ -3487,6 +3488,32 @@ public class Request implements HttpServletRequest { - // NO-OP - } - }); -+ specialAttributes.put(Globals.CONNECTION_ID, -+ new SpecialAttributeAdapter() { -+ @Override -+ public Object get(Request request, String name) { -+ AtomicReference result = new AtomicReference<>(); -+ request.getCoyoteRequest().action(ActionCode.CONNECTION_ID, result); -+ return result.get(); -+ } -+ @Override -+ public void set(Request request, String name, Object value) { -+ // NO-OP -+ } -+ }); -+ specialAttributes.put(Globals.STREAM_ID, -+ new SpecialAttributeAdapter() { -+ @Override -+ public Object get(Request request, String name) { -+ AtomicReference result = new AtomicReference<>(); -+ request.getCoyoteRequest().action(ActionCode.STREAM_ID, result); -+ return result.get(); -+ } -+ @Override -+ public void set(Request request, String name, Object value) { -+ // NO-OP -+ } -+ }); - - for (SimpleDateFormat sdf : formatsTemplate) { - sdf.setTimeZone(GMT_ZONE); -diff --git a/java/org/apache/coyote/AbstractProcessor.java b/java/org/apache/coyote/AbstractProcessor.java -index 5be2cb8..b351cb7 100644 ---- a/java/org/apache/coyote/AbstractProcessor.java -+++ b/java/org/apache/coyote/AbstractProcessor.java -@@ -22,6 +22,7 @@ import java.nio.ByteBuffer; - import java.util.Iterator; - import java.util.concurrent.RejectedExecutionException; - import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.concurrent.atomic.AtomicReference; - - import javax.servlet.RequestDispatcher; - -@@ -589,6 +590,20 @@ public abstract class AbstractProcessor extends AbstractProcessorLight implement - result.set(isTrailerFieldsSupported()); - break; - } -+ -+ // Identifiers associated with multiplexing protocols like HTTP/2 -+ case CONNECTION_ID: { -+ @SuppressWarnings("unchecked") -+ AtomicReference result = (AtomicReference) param; -+ result.set(getConnectionID()); -+ break; -+ } -+ case STREAM_ID: { -+ @SuppressWarnings("unchecked") -+ AtomicReference result = (AtomicReference) param; -+ result.set(getStreamID()); -+ break; -+ } - } - } - -@@ -889,6 +904,30 @@ public abstract class AbstractProcessor extends AbstractProcessorLight implement - } - - -+ /** -+ * Protocols that support multiplexing (e.g. HTTP/2) should override this -+ * method and return the appropriate ID. -+ * -+ * @return The stream ID associated with this request or {@code null} if a -+ * multiplexing protocol is not being used -+ */ -+ protected Object getConnectionID() { -+ return null; -+ } -+ -+ -+ /** -+ * Protocols that support multiplexing (e.g. HTTP/2) should override this -+ * method and return the appropriate ID. -+ * -+ * @return The stream ID associated with this request or {@code null} if a -+ * multiplexing protocol is not being used -+ */ -+ protected Object getStreamID() { -+ return null; -+ } -+ -+ - /** - * Flush any pending writes. Used during non-blocking writes to flush any - * remaining data from a previous incomplete write. -diff --git a/java/org/apache/coyote/ActionCode.java b/java/org/apache/coyote/ActionCode.java -index 3ff4c21..5c5af4f 100644 ---- a/java/org/apache/coyote/ActionCode.java -+++ b/java/org/apache/coyote/ActionCode.java -@@ -265,5 +265,17 @@ public enum ActionCode { - * once an HTTP/1.1 response has been committed, it will no longer support - * trailer fields. - */ -- IS_TRAILER_FIELDS_SUPPORTED -+ IS_TRAILER_FIELDS_SUPPORTED, -+ -+ /** -+ * Obtain the connection identifier for the request. Used with multiplexing -+ * protocols such as HTTP/2. -+ */ -+ CONNECTION_ID, -+ -+ /** -+ * Obtain the stream identifier for the request. Used with multiplexing -+ * protocols such as HTTP/2. -+ */ -+ STREAM_ID - } -diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java -index d9c1c82..fd833ec 100644 ---- a/java/org/apache/coyote/http2/StreamProcessor.java -+++ b/java/org/apache/coyote/http2/StreamProcessor.java -@@ -300,6 +300,18 @@ class StreamProcessor extends AbstractProcessor { - } - - -+ @Override -+ protected Object getConnectionID() { -+ return stream.getConnectionId(); -+ } -+ -+ -+ @Override -+ protected Object getStreamID() { -+ return stream.getIdentifier().toString(); -+ } -+ -+ - @Override - public final void recycle() { - // StreamProcessor instances are not re-used. -diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml -index a97e15d..8837628 100644 ---- a/webapps/docs/changelog.xml -+++ b/webapps/docs/changelog.xml -@@ -247,6 +247,11 @@ - Ensure that the HTTP/1.1 processor is correctly recycled when a direct - connection to h2c is made. (markt) - -+ -+ Expose the HTTP/2 connection ID and stream ID to applications via the -+ request attributes org.apache.coyote.connectionID and -+ org.apache.coyote.streamID respectively. (markt) -+ - - - -diff --git a/webapps/docs/config/http2.xml b/webapps/docs/config/http2.xml -index 83b8acd..145a184 100644 ---- a/webapps/docs/config/http2.xml -+++ b/webapps/docs/config/http2.xml -@@ -44,6 +44,15 @@ - the Servlet API is fundamentally blocking, each HTTP/2 stream requires a - dedicated container thread for the duration of that stream.

- -+

Requests processed using HTTP/2 will have the following additional request -+ attributes available:

-+
    -+
  • org.apache.coyote.connectionID will return the HTTP/2 -+ connection ID
  • -+
  • org.apache.coyote.streamID will return the HTTP/2 stream -+ ID
  • -+
-+ - - - --- -2.33.0 - diff --git a/CVE-2023-28708.patch b/CVE-2023-28708.patch deleted file mode 100644 index 1d03fc7..0000000 --- a/CVE-2023-28708.patch +++ /dev/null @@ -1,232 +0,0 @@ -From 3b51230764da595bb19e8d0962dd8c69ab40dfab Mon Sep 17 00:00:00 2001 -From: lihan -Date: Fri, 10 Feb 2023 10:01:27 +0800 -Subject: [PATCH] Fix BZ 66471 - JSessionId secure attribute missing with - RemoteIpFilter and X-Forwarded-Proto set to https - -https://bz.apache.org/bugzilla/show_bug.cgi?id=66471 - -Origin: https://github.com/apache/tomcat/commit/3b51230764da595bb19e8d0962dd8c69ab40dfab ---- - java/org/apache/catalina/Globals.java | 8 ++ - .../apache/catalina/connector/Request.java | 14 +++ - .../catalina/filters/RemoteIpFilter.java | 7 +- - .../catalina/filters/TestRemoteIpFilter.java | 96 ++++++++++++++----- - webapps/docs/changelog.xml | 5 + - 5 files changed, 101 insertions(+), 29 deletions(-) - -diff --git a/java/org/apache/catalina/Globals.java b/java/org/apache/catalina/Globals.java -index c19d69c..2e9a377 100644 ---- a/java/org/apache/catalina/Globals.java -+++ b/java/org/apache/catalina/Globals.java -@@ -160,6 +160,14 @@ public final class Globals { - org.apache.coyote.Constants.SENDFILE_SUPPORTED_ATTR; - - -+ /** -+ * The request attribute that is set to the value of {@code Boolean.TRUE} -+ * if {@link org.apache.catalina.filters.RemoteIpFilter} determines -+ * that this request was submitted via a secure channel. -+ */ -+ public static final String REMOTE_IP_FILTER_SECURE = "org.apache.catalina.filters.RemoteIpFilter.secure"; -+ -+ - /** - * The request attribute that can be used by a servlet to pass - * to the connector the name of the file that is to be served -diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java -index 94065ef..889d5e7 100644 ---- a/java/org/apache/catalina/connector/Request.java -+++ b/java/org/apache/catalina/connector/Request.java -@@ -3501,6 +3501,20 @@ public class Request implements HttpServletRequest { - // NO-OP - } - }); -+ specialAttributes.put(Globals.REMOTE_IP_FILTER_SECURE, -+ new SpecialAttributeAdapter() { -+ @Override -+ public Object get(Request request, String name) { -+ return Boolean.valueOf(request.isSecure()); -+ } -+ -+ @Override -+ public void set(Request request, String name, Object value) { -+ if (value instanceof Boolean) { -+ request.setSecure(((Boolean) value).booleanValue()); -+ } -+ } -+ }); - specialAttributes.put(Globals.STREAM_ID, - new SpecialAttributeAdapter() { - @Override -diff --git a/java/org/apache/catalina/filters/RemoteIpFilter.java b/java/org/apache/catalina/filters/RemoteIpFilter.java -index b9f6655..e978cfb 100644 ---- a/java/org/apache/catalina/filters/RemoteIpFilter.java -+++ b/java/org/apache/catalina/filters/RemoteIpFilter.java -@@ -577,11 +577,6 @@ public class RemoteIpFilter extends GenericFilter { - return serverPort; - } - -- @Override -- public boolean isSecure() { -- return secure; -- } -- - public void removeHeader(String name) { - Map.Entry> header = getHeaderEntry(name); - if (header != null) { -@@ -617,7 +612,7 @@ public class RemoteIpFilter extends GenericFilter { - } - - public void setSecure(boolean secure) { -- this.secure = secure; -+ super.getRequest().setAttribute(Globals.REMOTE_IP_FILTER_SECURE, Boolean.valueOf(secure)); - } - - public void setServerPort(int serverPort) { -diff --git a/test/org/apache/catalina/filters/TestRemoteIpFilter.java b/test/org/apache/catalina/filters/TestRemoteIpFilter.java -index f7f2093..109fdd2 100644 ---- a/test/org/apache/catalina/filters/TestRemoteIpFilter.java -+++ b/test/org/apache/catalina/filters/TestRemoteIpFilter.java -@@ -81,15 +81,21 @@ public class TestRemoteIpFilter extends TomcatBaseTest { - - private static final long serialVersionUID = 1L; - -- private transient HttpServletRequest request; -- -- public HttpServletRequest getRequest() { -- return request; -- } -+ public String remoteAddr; -+ public String remoteHost; -+ public String scheme; -+ public String serverName; -+ public int serverPort; -+ public boolean isSecure; - - @Override - public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { -- this.request = request; -+ this.isSecure = request.isSecure(); -+ this.remoteAddr = request.getRemoteAddr(); -+ this.remoteHost = request.getRemoteHost(); -+ this.scheme = request.getScheme(); -+ this.serverName = request.getServerName(); -+ this.serverPort = request.getServerPort(); - PrintWriter writer = response.getWriter(); - - writer.println("request.remoteAddr=" + request.getRemoteAddr()); -@@ -127,16 +133,6 @@ public class TestRemoteIpFilter extends TomcatBaseTest { - getCoyoteRequest().scheme().setString(scheme); - } - -- @Override -- public void setAttribute(String name, Object value) { -- getCoyoteRequest().getAttributes().put(name, value); -- } -- -- @Override -- public Object getAttribute(String name) { -- return getCoyoteRequest().getAttributes().get(name); -- } -- - @Override - public String getServerName() { - return "localhost"; -@@ -667,16 +663,70 @@ public class TestRemoteIpFilter extends TomcatBaseTest { - - // VALIDATE - Assert.assertEquals(HttpURLConnection.HTTP_OK, httpURLConnection.getResponseCode()); -- HttpServletRequest request = mockServlet.getRequest(); -- Assert.assertNotNull(request); - - // VALIDATE X-FORWARDED-FOR -- Assert.assertEquals(expectedRemoteAddr, request.getRemoteAddr()); -- Assert.assertEquals(expectedRemoteAddr, request.getRemoteHost()); -+ Assert.assertEquals(expectedRemoteAddr, mockServlet.remoteAddr); -+ Assert.assertEquals(expectedRemoteAddr, mockServlet.remoteHost); - - // VALIDATE X-FORWARDED-PROTO -- Assert.assertTrue(request.isSecure()); -- Assert.assertEquals("https", request.getScheme()); -- Assert.assertEquals(443, request.getServerPort()); -+ Assert.assertTrue(mockServlet.isSecure); -+ Assert.assertEquals("https", mockServlet.scheme); -+ Assert.assertEquals(443, mockServlet.serverPort); -+ } -+ -+ @Test -+ public void testJSessionIdSecureAttributeMissing() throws Exception { -+ -+ // mostly default configuration : enable "x-forwarded-proto" -+ Map remoteIpFilterParameter = new HashMap<>(); -+ remoteIpFilterParameter.put("protocolHeader", "x-forwarded-proto"); -+ -+ // SETUP -+ Tomcat tomcat = getTomcatInstance(); -+ Context root = tomcat.addContext("", TEMP_DIR); -+ -+ FilterDef filterDef = new FilterDef(); -+ filterDef.getParameterMap().putAll(remoteIpFilterParameter); -+ filterDef.setFilterClass(RemoteIpFilter.class.getName()); -+ filterDef.setFilterName(RemoteIpFilter.class.getName()); -+ -+ root.addFilterDef(filterDef); -+ -+ FilterMap filterMap = new FilterMap(); -+ filterMap.setFilterName(RemoteIpFilter.class.getName()); -+ filterMap.addURLPatternDecoded("*"); -+ root.addFilterMap(filterMap); -+ -+ Bug66471Servlet bug66471Servlet = new Bug66471Servlet(); -+ -+ Tomcat.addServlet(root, bug66471Servlet.getClass().getName(), bug66471Servlet); -+ root.addServletMappingDecoded("/test", bug66471Servlet.getClass().getName()); -+ -+ getTomcatInstance().start(); -+ -+ Map> resHeaders = new HashMap<>(); -+ Map> reqHeaders = new HashMap<>(); -+ String expectedRemoteAddr = "my-remote-addr"; -+ List forwardedFor = new ArrayList<>(1); -+ forwardedFor.add(expectedRemoteAddr); -+ List forwardedProto = new ArrayList<>(1); -+ forwardedProto.add("https"); -+ reqHeaders.put("x-forwarded-for", forwardedFor); -+ reqHeaders.put("x-forwarded-proto", forwardedProto); -+ -+ getUrl("http://localhost:" + tomcat.getConnector().getLocalPort() + -+ "/test", null, reqHeaders, resHeaders); -+ String setCookie = resHeaders.get("Set-Cookie").get(0); -+ Assert.assertTrue(setCookie.contains("Secure")); -+ Assert.assertTrue(bug66471Servlet.isSecure.booleanValue()); -+ } -+ public static class Bug66471Servlet extends HttpServlet { -+ private static final long serialVersionUID = 1L; -+ public Boolean isSecure; -+ @Override -+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { -+ req.getSession(); -+ isSecure = (Boolean) req.getAttribute(Globals.REMOTE_IP_FILTER_SECURE); -+ } - } - } -diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml -index 8837628..15be3ed 100644 ---- a/webapps/docs/changelog.xml -+++ b/webapps/docs/changelog.xml -@@ -478,6 +478,11 @@ - Improve handling of overflow in the UTF-8 decoder with supplementary - characters. (markt) - -+ -+ 66471: Fix JSessionId secure attribute missing When -+ RemoteIpFilter determines that this request was submitted -+ via a secure channel. (lihan) -+ - -
- --- -2.33.0 - diff --git a/CVE-2023-28709.patch b/CVE-2023-28709.patch deleted file mode 100644 index 5768c20..0000000 --- a/CVE-2023-28709.patch +++ /dev/null @@ -1,35 +0,0 @@ -From fbd81421629afe8b8a3922d59020cde81caea861 Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Tue, 11 Apr 2023 16:41:44 +0100 -Subject: [PATCH] Fix parameter counting logic - -Origin: https://github.com/apache/tomcat/commit/fbd81421629afe8b8a3922d59020cde81caea861 - ---- - java/org/apache/tomcat/util/http/Parameters.java | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/java/org/apache/tomcat/util/http/Parameters.java b/java/org/apache/tomcat/util/http/Parameters.java -index 08c6ffd..a19453d 100644 ---- a/java/org/apache/tomcat/util/http/Parameters.java -+++ b/java/org/apache/tomcat/util/http/Parameters.java -@@ -205,14 +205,14 @@ public final class Parameters { - return; - } - -- parameterCount ++; -- if (limit > -1 && parameterCount > limit) { -+ if (limit > -1 && parameterCount >= limit) { - // Processing this parameter will push us over the limit. ISE is - // what Request.parseParts() uses for requests that are too big - setParseFailedReason(FailReason.TOO_MANY_PARAMETERS); - throw new IllegalStateException(sm.getString( - "parameters.maxCountFail", Integer.valueOf(limit))); - } -+ parameterCount ++; - - ArrayList values = paramHashValues.get(key); - if (values == null) { --- -2.33.0 - diff --git a/CVE-2023-41080.patch b/CVE-2023-41080.patch deleted file mode 100644 index 6b7ab80..0000000 --- a/CVE-2023-41080.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 77c0ce2d169efa248b64b992e547aad549ec906b Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Tue, 22 Aug 2023 11:31:23 -0700 -Subject: [PATCH] Avoid protocol relative redirects - -Origin: https://github.com/apache/tomcat/commit/77c0ce2d169efa248b64b992e547aad549ec906b - ---- - .../apache/catalina/authenticator/FormAuthenticator.java | 6 ++++++ - webapps/docs/changelog.xml | 3 +++ - 2 files changed, 9 insertions(+) - -diff --git a/java/org/apache/catalina/authenticator/FormAuthenticator.java b/java/org/apache/catalina/authenticator/FormAuthenticator.java -index a57db51776b..d54cc62182e 100644 ---- a/java/org/apache/catalina/authenticator/FormAuthenticator.java -+++ b/java/org/apache/catalina/authenticator/FormAuthenticator.java -@@ -747,6 +747,12 @@ protected String savedRequestURL(Session session) { - sb.append('?'); - sb.append(saved.getQueryString()); - } -+ -+ // Avoid protocol relative redirects -+ while (sb.length() > 1 && sb.charAt(1) == '/') { -+ sb.deleteCharAt(0); -+ } -+ - return sb.toString(); - } - } diff --git a/CVE-2023-42795.patch b/CVE-2023-42795.patch deleted file mode 100644 index 2ac136b..0000000 --- a/CVE-2023-42795.patch +++ /dev/null @@ -1,251 +0,0 @@ -From 44d05d75d696ca10ce251e4e370511e38f20ae75 Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Thu, 5 Oct 2023 20:52:46 +0100 -Subject: [PATCH] Improve handling of failures during recycle() methods - -Origin: https://github.com/apache/tomcat/commit/44d05d75d696ca10ce251e4e370511e38f20ae75 - ---- - .../catalina/connector/LocalStrings.properties | 1 + - java/org/apache/catalina/connector/Request.java | 7 ++++--- - .../catalina/core/ApplicationHttpRequest.java | 16 ++++++++++++---- - .../apache/catalina/core/LocalStrings.properties | 1 + - .../catalina/core/LocalStrings_es.properties | 2 ++ - .../catalina/core/LocalStrings_fr.properties | 1 + - .../catalina/core/LocalStrings_ja.properties | 1 + - .../org/apache/tomcat/util/buf/B2CConverter.java | 11 ++++++++++- - .../org/apache/tomcat/util/buf/C2BConverter.java | 15 ++++++++++++++- - .../tomcat/util/buf/LocalStrings.properties | 3 +++ - 10 files changed, 49 insertions(+), 9 deletions(-) - -diff --git a/java/org/apache/catalina/connector/LocalStrings.properties b/java/org/apache/catalina/connector/LocalStrings.properties -index 86c6487..596805b 100644 ---- a/java/org/apache/catalina/connector/LocalStrings.properties -+++ b/java/org/apache/catalina/connector/LocalStrings.properties -@@ -47,6 +47,7 @@ coyoteRequest.setAttribute.namenull=Cannot call setAttribute with a null name - coyoteRequest.attributeEvent=Exception thrown by attributes event listener - coyoteRequest.parseParameters=Exception thrown whilst processing POSTed parameters - coyoteRequest.postTooLarge=Parameters were not parsed because the size of the posted data was too big. Use the maxPostSize attribute of the connector to resolve this if the application should accept large POSTs. -+coyoteRequest.deletePartFailed=Failed to deleted temporary file used for part [{0}] - coyoteRequest.chunkedPostTooLarge=Parameters were not parsed because the size of the posted data was too big. Because this request was a chunked request, it could not be processed further. Use the maxPostSize attribute of the connector to resolve this if the application should accept large POSTs. - coyoteRequest.alreadyAuthenticated=This request has already been authenticated - coyoteRequest.authenticate.ise=Cannot call authenticate() after the response has been committed -diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java -index 889d5e7..de53769 100644 ---- a/java/org/apache/catalina/connector/Request.java -+++ b/java/org/apache/catalina/connector/Request.java -@@ -465,8 +465,9 @@ public class Request implements HttpServletRequest { - for (Part part: parts) { - try { - part.delete(); -- } catch (IOException ignored) { -- // ApplicationPart.delete() never throws an IOEx -+ } catch (Throwable t) { -+ ExceptionUtils.handleThrowable(t); -+ log.warn(sm.getString("coyoteRequest.deletePartFailed", part.getName()), t); - } - } - parts = null; -@@ -518,8 +519,8 @@ public class Request implements HttpServletRequest { - asyncSupported = null; - if (asyncContext!=null) { - asyncContext.recycle(); -+ asyncContext = null; - } -- asyncContext = null; - } - - -diff --git a/java/org/apache/catalina/core/ApplicationHttpRequest.java b/java/org/apache/catalina/core/ApplicationHttpRequest.java -index fc3a1d6..0b5b4f5 100644 ---- a/java/org/apache/catalina/core/ApplicationHttpRequest.java -+++ b/java/org/apache/catalina/core/ApplicationHttpRequest.java -@@ -29,6 +29,8 @@ import java.util.Enumeration; - import java.util.List; - import java.util.Map; - import java.util.NoSuchElementException; -+import java.util.Arrays; -+import java.util.HashMap; - - import javax.servlet.DispatcherType; - import javax.servlet.RequestDispatcher; -@@ -48,9 +50,12 @@ import org.apache.catalina.Session; - import org.apache.catalina.connector.RequestFacade; - import org.apache.catalina.util.ParameterMap; - import org.apache.catalina.util.RequestUtil; -+import org.apache.catalina.util.URLEncoder; -+import org.apache.tomcat.util.ExceptionUtils; - import org.apache.tomcat.util.buf.B2CConverter; - import org.apache.tomcat.util.buf.MessageBytes; - import org.apache.tomcat.util.http.Parameters; -+import org.apache.tomcat.util.res.StringManager; - - - /** -@@ -70,9 +75,7 @@ import org.apache.tomcat.util.http.Parameters; - */ - class ApplicationHttpRequest extends HttpServletRequestWrapper { - -- -- // ------------------------------------------------------- Static Variables -- -+ private static final StringManager sm = StringManager.getManager(ApplicationHttpRequest.class); - - /** - * The set of attribute names that are special for request dispatchers. -@@ -626,7 +629,12 @@ class ApplicationHttpRequest extends HttpServletRequestWrapper { - */ - public void recycle() { - if (session != null) { -- session.endAccess(); -+ try { -+ session.endAccess(); -+ } catch (Throwable t) { -+ ExceptionUtils.handleThrowable(t); -+ context.getLogger().warn(sm.getString("applicationHttpRequest.sessionEndAccessFail"), t); -+ } - } - } - -diff --git a/java/org/apache/catalina/core/LocalStrings.properties b/java/org/apache/catalina/core/LocalStrings.properties -index c5b55b1..0e17e3c 100644 ---- a/java/org/apache/catalina/core/LocalStrings.properties -+++ b/java/org/apache/catalina/core/LocalStrings.properties -@@ -55,6 +55,7 @@ applicationFilterConfig.release=Failed to destroy the filter named [{0}] of type - applicationFilterRegistration.nullInitParam=Unable to set initialisation parameter for filter due to null name and/or value. Name [{0}], Value [{1}] - applicationFilterRegistration.nullInitParams=Unable to set initialisation parameters for filter due to null name and/or value. Name [{0}], Value [{1}] - -+applicationHttpRequest.sessionEndAccessFail=Exception triggered ending access to session while recycling request - applicationPushBuilder.methodInvalid=The HTTP method for a push request must be both cacheable and safe but [{0}] is not - applicationPushBuilder.methodNotToken=HTTP methods must be tokens but [{0}] contains a non-token character - applicationPushBuilder.noCoyoteRequest=Unable to find the underlying Coyote request object (which is required to create a push request) from the request of type [{0}] -diff --git a/java/org/apache/catalina/core/LocalStrings_es.properties b/java/org/apache/catalina/core/LocalStrings_es.properties -index f138d17..e6a9ab2 100644 ---- a/java/org/apache/catalina/core/LocalStrings_es.properties -+++ b/java/org/apache/catalina/core/LocalStrings_es.properties -@@ -43,6 +43,8 @@ applicationFilterConfig.jmxUnregister = Se ha completado el desregistro JMX para - applicationFilterConfig.jmxUnregisterFail = Ha fallado el desregistro JMX para el filtro del tipo [{0}] y nombre [{1}] - applicationFilterRegistration.nullInitParam = No puedo poner el par\u00E1metro de inicializaci\u00F3n para el filtro debido a un nombre nulo y/o valor. Nombre [{0}], Valor [{1}] - applicationFilterRegistration.nullInitParams = No puedo poner los par\u00E1metros de inicializaci\u00F3n para el filtro debido a un nombre nulo y/o valor. Nombre [{0}], Valor [{1}] -+applicationHttpRequest.sessionEndAccessFail=Excepción disparada acabando acceso a sesión mientras se reciclaba el requerimiento -+ - applicationServletRegistration.setServletSecurity.iae = Se ha especificado restricci\u00F3n Null para el servlet [{0}] desplegado en el contexto con el nombre [{1}] - applicationServletRegistration.setServletSecurity.ise = No se pueden a\u00F1adir restricciones de seguridad al servlet [{0}] desplegado en el contexto con el nombre [{1}] ya que el contexto ya ha sido inicializado. - aprListener.aprInit = La biblioteca nativa de Apache Tomcat basada en ARP que permite un rendimiento \u00F3ptimo en entornos de desarrollo no ha sido hallada en java.library.path: [{0}] -diff --git a/java/org/apache/catalina/core/LocalStrings_fr.properties b/java/org/apache/catalina/core/LocalStrings_fr.properties -index dfc1cf7..91ead47 100644 ---- a/java/org/apache/catalina/core/LocalStrings_fr.properties -+++ b/java/org/apache/catalina/core/LocalStrings_fr.properties -@@ -59,6 +59,7 @@ standardContext.startFailed=Erreur de d\u00e9marrage du contexte [{0}] suite aux - standardContext.startingContext=Exception lors du d\u00e9marrage du contexte [{0}] - standardContext.stoppingContext=Exception \u00e0 l''arr\u00eat du Context [{0}] - standardContext.resourcesStart=Erreur lors du d\u00e9marrage des ressources statiques -+applicationHttpRequest.sessionEndAccessFail=Exception lancée durant l'arrêt de l'accès à la session durant le recyclage de la requête - standardContext.urlPattern.patternWarning=ATTENTION: Le mod\u00e8le (pattern) URL [{0}] doit commencer par un ''/'' dans l''API Servlet 2.4 - standardEngine.noHost=Aucune h\u00f4te (host) ne correspond au nom de serveur [{0}] - standardEngine.notHost=Le fils d''un moteur (child of an Engine) doit \u00eatre un h\u00f4te -diff --git a/java/org/apache/catalina/core/LocalStrings_ja.properties b/java/org/apache/catalina/core/LocalStrings_ja.properties -index d34d598..ae85dd4 100644 ---- a/java/org/apache/catalina/core/LocalStrings_ja.properties -+++ b/java/org/apache/catalina/core/LocalStrings_ja.properties -@@ -66,6 +66,7 @@ standardEngine.notParent=\u30a8\u30f3\u30b8\u30f3\u306f\u89aa\u306e\u30b3\u30f3\ - standardHost.clientAbort=\u30ea\u30e2\u30fc\u30c8\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u4e2d\u6b62\u3057\u307e\u3057\u305f, IOException: [{0}] - standardHost.invalidErrorReportValveClass=\u6307\u5b9a\u3055\u308c\u305f\u30a8\u30e9\u30fc\u30ea\u30dd\u30fc\u30c8\u30d0\u30eb\u30d6\u30af\u30e9\u30b9\u3092\u30ed\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093: [{0}] - standardHost.noContext=\u3053\u306e\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u51e6\u7406\u3059\u308b\u305f\u3081\u306b\u8a2d\u5b9a\u3055\u308c\u305f\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u304c\u3042\u308a\u307e\u305b\u3093 -+applicationHttpRequest.sessionEndAccessFail=リクエストの再利用中に行ったセッションへのアクセス終了処理で例外が送出されました。 - standardHost.notContext=\u30db\u30b9\u30c8\u306e\u5b50\u4f9b\u306f\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093 - standardHost.nullName=\u30db\u30b9\u30c8\u540d\u304c\u5fc5\u8981\u3067\u3059 - standardService.start.name=\u30b5\u30fc\u30d3\u30b9 [{0}] \u3092\u8d77\u52d5\u3057\u307e\u3059 -diff --git a/java/org/apache/tomcat/util/buf/B2CConverter.java b/java/org/apache/tomcat/util/buf/B2CConverter.java -index f046ad7..1e3e1f4 100644 ---- a/java/org/apache/tomcat/util/buf/B2CConverter.java -+++ b/java/org/apache/tomcat/util/buf/B2CConverter.java -@@ -27,6 +27,9 @@ import java.nio.charset.CodingErrorAction; - import java.nio.charset.StandardCharsets; - import java.util.HashMap; - import java.util.Locale; -+import org.apache.juli.logging.Log; -+import org.apache.juli.logging.LogFactory; -+import org.apache.tomcat.util.ExceptionUtils; - import java.util.Map; - - import org.apache.tomcat.util.res.StringManager; -@@ -35,6 +38,7 @@ import org.apache.tomcat.util.res.StringManager; - * NIO based character decoder. - */ - public class B2CConverter { -+ private static final Log log = LogFactory.getLog(B2CConverter.class); - - private static final StringManager sm = StringManager.getManager(B2CConverter.class); - -@@ -120,7 +124,12 @@ public class B2CConverter { - * Reset the decoder state. - */ - public void recycle() { -- decoder.reset(); -+ try { -+ decoder.reset(); -+ } catch (Throwable t) { -+ ExceptionUtils.handleThrowable(t); -+ log.warn(sm.getString("b2cConverter.decoderResetFail", decoder.charset()), t); -+ } - leftovers.position(0); - } - -diff --git a/java/org/apache/tomcat/util/buf/C2BConverter.java b/java/org/apache/tomcat/util/buf/C2BConverter.java -index e5062de..f3b4dd7 100644 ---- a/java/org/apache/tomcat/util/buf/C2BConverter.java -+++ b/java/org/apache/tomcat/util/buf/C2BConverter.java -@@ -24,11 +24,19 @@ import java.nio.charset.CharsetEncoder; - import java.nio.charset.CoderResult; - import java.nio.charset.CodingErrorAction; - -+import org.apache.juli.logging.Log; -+import org.apache.juli.logging.LogFactory; -+import org.apache.tomcat.util.ExceptionUtils; -+import org.apache.tomcat.util.res.StringManager; -+ - /** - * NIO based character encoder. - */ - public final class C2BConverter { - -+ private static final Log log = LogFactory.getLog(C2BConverter.class); -+ private static final StringManager sm = StringManager.getManager(C2BConverter.class); -+ - private final CharsetEncoder encoder; - private ByteBuffer bb = null; - private CharBuffer cb = null; -@@ -50,7 +58,12 @@ public final class C2BConverter { - * Reset the encoder state. - */ - public void recycle() { -- encoder.reset(); -+ try { -+ encoder.reset(); -+ } catch (Throwable t) { -+ ExceptionUtils.handleThrowable(t); -+ log.warn(sm.getString("c2bConverter.decoderResetFail", encoder.charset()), t); -+ } - leftovers.position(0); - } - -diff --git a/java/org/apache/tomcat/util/buf/LocalStrings.properties b/java/org/apache/tomcat/util/buf/LocalStrings.properties -index c8a8d3b..574f6c2 100644 ---- a/java/org/apache/tomcat/util/buf/LocalStrings.properties -+++ b/java/org/apache/tomcat/util/buf/LocalStrings.properties -@@ -13,9 +13,12 @@ - # See the License for the specific language governing permissions and - # limitations under the License. - -+b2cConverter.decoderResetFail=Failed to reset instance of decoder for character set [{0}] - b2cConverter.unknownEncoding=The character encoding [{0}] is not supported - c2bConverter.recycleFailed=Failed to recycle the C2B Converter. Creating new BufferedWriter, WriteConvertor and IntermediateOutputStream. - -+c2bConverter.encoderResetFail=Failed to reset instance of encoder for character set [{0}] -+ - hexUtils.fromHex.oddDigits=The input must consist of an even number of hex digits - hexUtils.fromHex.nonHex=The input must consist only of hex digits - --- -2.33.0 diff --git a/CVE-2023-45648.patch b/CVE-2023-45648.patch deleted file mode 100644 index 58c6e25..0000000 --- a/CVE-2023-45648.patch +++ /dev/null @@ -1,89 +0,0 @@ -Description: Align processing of trailer headers with standard processing -Origin: upstream, https://github.com/apache/tomcat/commit/59583245639d8c42ae0009f4a4a70464d3ea70a0 ---- a/java/org/apache/coyote/http11/Http11InputBuffer.java -+++ b/java/org/apache/coyote/http11/Http11InputBuffer.java -@@ -818,6 +818,12 @@ - */ - private HeaderParseStatus parseHeader() throws IOException { - -+ /* -+ * Implementation note: Any changes to this method probably need to be echoed in -+ * ChunkedInputFilter.parseHeader(). Why not use a common implementation? In short, this code uses non-blocking -+ * reads whereas ChunkedInputFilter using blocking reads. The code is just different enough that a common -+ * implementation wasn't viewed as practical. -+ */ - // - // Check for blank line - // - - byte chr = 0; - byte prevChr = 0; - - while (headerParsePos == HeaderParsePosition.HEADER_START) { - - // Read new bytes if needed -@@ -950,7 +956,7 @@ - } else if (prevChr == Constants.CR) { - // Invalid value - also need to delete header - return skipLine(true); -- } else if (chr != Constants.HT && HttpParser.isControl(chr)) { -+ } else if (HttpParser.isControl(chr) && chr != Constants.HT) { - // Invalid value - also need to delete header - return skipLine(true); - } else if (chr == Constants.SP || chr == Constants.HT) { ---- a/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java -+++ b/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java -@@ -30,6 +30,7 @@ - import org.apache.coyote.http11.InputFilter; - import org.apache.tomcat.util.buf.ByteChunk; - import org.apache.tomcat.util.buf.HexUtils; -+import org.apache.tomcat.util.http.parser.HttpParser; - import org.apache.tomcat.util.net.ApplicationBufferHandler; - import org.apache.tomcat.util.res.StringManager; - -@@ -443,6 +444,13 @@ - - private boolean parseHeader() throws IOException { - -+ /* -+ * Implementation note: Any changes to this method probably need to be echoed in -+ * Http11InputBuffer.parseHeader(). Why not use a common implementation? In short, this code uses blocking -+ * reads whereas Http11InputBuffer using non-blocking reads. The code is just different enough that a common -+ * implementation wasn't viewed as practical. -+ */ -+ - Map headers = request.getTrailerFields(); - - byte chr = 0; -@@ -489,6 +497,9 @@ - - if (chr == Constants.COLON) { - colon = true; -+ } else if (!HttpParser.isToken(chr)) { -+ // Non-token characters are illegal in header names -+ throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderName")); - } else { - trailingHeaders.append(chr); - } -@@ -550,7 +561,9 @@ - if (chr == Constants.CR || chr == Constants.LF) { - parseCRLF(true); - eol = true; -- } else if (chr == Constants.SP) { -+ } else if (HttpParser.isControl(chr) && chr != Constants.HT) { -+ throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderValue")); -+ } else if (chr == Constants.SP || chr == Constants.HT) { - trailingHeaders.append(chr); - } else { - trailingHeaders.append(chr); ---- a/java/org/apache/coyote/http11/filters/LocalStrings.properties -+++ b/java/org/apache/coyote/http11/filters/LocalStrings.properties -@@ -21,6 +21,8 @@ - chunkedInputFilter.invalidCrlfNoCR=Invalid end of line sequence (No CR before LF) - chunkedInputFilter.invalidCrlfNoData=Invalid end of line sequence (no data available to read) - chunkedInputFilter.invalidHeader=Invalid chunk header -+chunkedInputFilter.invalidTrailerHeaderName=Invalid trailer header name (non-token character in name) -+chunkedInputFilter.invalidTrailerHeaderValue=Invalid trailer header value (control character in value) - chunkedInputFilter.maxExtension=maxExtensionSize exceeded - chunkedInputFilter.maxTrailer=maxTrailerSize exceeded - diff --git a/CVE-2024-21733.patch b/CVE-2024-21733.patch deleted file mode 100644 index d43417c..0000000 --- a/CVE-2024-21733.patch +++ /dev/null @@ -1,579 +0,0 @@ -From ce4b154e7b48f66bd98858626347747cd2514311 Mon Sep 17 00:00:00 2001 -From: Mark Thomas -Date: Thu, 18 Feb 2021 16:41:57 +0000 -Subject: [PATCH] Ensure ReadListener.onError() is fired if client drops the - connection - -Origin: -https://github.com/apache/tomcat/commit/659b28c00d94e2a9049e0a8ac1e02bd4d36dd005 -https://github.com/apache/tomcat/commit/f562edd3302866f34c0ca9fa97f6ff414450f1ae -https://github.com/apache/tomcat/commit/918146f9d04af67d904b47c440acaab14380521b -https://github.com/apache/tomcat/commit/504445cd2c618fb1edbfeda62e07e1c29b4d285c -https://github.com/apache/tomcat/commit/ce4b154e7b48f66bd98858626347747cd2514311 - ---- - .../catalina/core/StandardWrapperValve.java | 2 + - .../coyote/http11/Http11InputBuffer.java | 43 +++- - .../coyote/http11/Http11OutputBuffer.java | 15 +- - .../catalina/core/TestAsyncContextImpl.java | 172 +++++++++++++++- - .../nonblocking/TestNonBlockingAPI.java | 192 ++++++++++++++++++ - 5 files changed, 412 insertions(+), 12 deletions(-) - -diff --git a/java/org/apache/catalina/core/StandardWrapperValve.java b/java/org/apache/catalina/core/StandardWrapperValve.java -index 27f136a..89f5915 100644 ---- a/java/org/apache/catalina/core/StandardWrapperValve.java -+++ b/java/org/apache/catalina/core/StandardWrapperValve.java -@@ -29,6 +29,7 @@ import javax.servlet.ServletException; - import javax.servlet.UnavailableException; - import javax.servlet.http.HttpServletResponse; - -+import org.apache.catalina.Container; - import org.apache.catalina.Context; - import org.apache.catalina.Globals; - import org.apache.catalina.LifecycleException; -@@ -174,6 +175,7 @@ final class StandardWrapperValve - - // Call the filter chain for this request - // NOTE: This also calls the servlet's service() method -+ Container container = this.container; - try { - if ((servlet != null) && (filterChain != null)) { - // Swallow output if needed -diff --git a/java/org/apache/coyote/http11/Http11InputBuffer.java b/java/org/apache/coyote/http11/Http11InputBuffer.java -index 27392d4..db596b4 100644 ---- a/java/org/apache/coyote/http11/Http11InputBuffer.java -+++ b/java/org/apache/coyote/http11/Http11InputBuffer.java -@@ -22,6 +22,7 @@ import java.nio.ByteBuffer; - import java.nio.charset.StandardCharsets; - import java.util.Arrays; - -+import org.apache.coyote.CloseNowException; - import org.apache.coyote.InputBuffer; - import org.apache.coyote.Request; - import org.apache.juli.logging.Log; -@@ -382,10 +383,6 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler - - parsingRequestLineStart = byteBuffer.position(); - parsingRequestLinePhase = 2; -- if (log.isDebugEnabled()) { -- log.debug("Received [" -- + new String(byteBuffer.array(), byteBuffer.position(), byteBuffer.remaining(), StandardCharsets.ISO_8859_1) + "]"); -- } - } - if (parsingRequestLinePhase == 2) { - // -@@ -709,6 +706,16 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler - */ - private boolean fill(boolean block) throws IOException { - -+ if (log.isDebugEnabled()) { -+ log.debug("Before fill(): parsingHeader: [" + parsingHeader + -+ "], parsingRequestLine: [" + parsingRequestLine + -+ "], parsingRequestLinePhase: [" + parsingRequestLinePhase + -+ "], parsingRequestLineStart: [" + parsingRequestLineStart + -+ "], byteBuffer.position(): [" + byteBuffer.position() + -+ "], byteBuffer.limit(): [" + byteBuffer.limit() + -+ "], end: [" + end + "]"); -+ } -+ - if (parsingHeader) { - if (byteBuffer.limit() >= headerBufferSize) { - if (parsingRequestLine) { -@@ -721,13 +728,31 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler - byteBuffer.limit(end).position(end); - } - -+ int nRead = -1; - byteBuffer.mark(); -- if (byteBuffer.position() < byteBuffer.limit()) { -- byteBuffer.position(byteBuffer.limit()); -+ try { -+ if (byteBuffer.position() < byteBuffer.limit()) { -+ byteBuffer.position(byteBuffer.limit()); -+ } -+ byteBuffer.limit(byteBuffer.capacity()); -+ SocketWrapperBase socketWrapper = this.wrapper; -+ if (socketWrapper != null) { -+ nRead = socketWrapper.read(block, byteBuffer); -+ } else { -+ throw new CloseNowException(sm.getString("iib.eof.error")); -+ } -+ } finally { -+ // Ensure that the buffer limit and position are returned to a -+ // consistent "ready for read" state if an error occurs during in -+ // the above code block. -+ byteBuffer.limit(byteBuffer.position()).reset(); - } -- byteBuffer.limit(byteBuffer.capacity()); -- int nRead = wrapper.read(block, byteBuffer); -- byteBuffer.limit(byteBuffer.position()).reset(); -+ -+ if (log.isDebugEnabled()) { -+ log.debug("Received [" -+ + new String(byteBuffer.array(), byteBuffer.position(), byteBuffer.remaining(), StandardCharsets.ISO_8859_1) + "]"); -+ } -+ - if (nRead > 0) { - return true; - } else if (nRead == -1) { -diff --git a/java/org/apache/coyote/http11/Http11OutputBuffer.java b/java/org/apache/coyote/http11/Http11OutputBuffer.java -index aa5ad48..c369837 100644 ---- a/java/org/apache/coyote/http11/Http11OutputBuffer.java -+++ b/java/org/apache/coyote/http11/Http11OutputBuffer.java -@@ -21,6 +21,7 @@ import java.nio.ByteBuffer; - import java.util.Arrays; - - import org.apache.coyote.ActionCode; -+import org.apache.coyote.CloseNowException; - import org.apache.coyote.Response; - import org.apache.tomcat.util.buf.ByteChunk; - import org.apache.tomcat.util.buf.MessageBytes; -@@ -303,7 +304,12 @@ public class Http11OutputBuffer implements HttpOutputBuffer { - // Sending the response header buffer - headerBuffer.flip(); - try { -- socketWrapper.write(isBlocking(), headerBuffer); -+ SocketWrapperBase socketWrapper = this.socketWrapper; -+ if (socketWrapper != null) { -+ socketWrapper.write(isBlocking(), headerBuffer); -+ } else { -+ throw new CloseNowException(sm.getString("iob.failedwrite")); -+ } - } finally { - headerBuffer.position(0).limit(headerBuffer.capacity()); - } -@@ -527,7 +533,12 @@ public class Http11OutputBuffer implements HttpOutputBuffer { - public int doWrite(ByteBuffer chunk) throws IOException { - try { - int len = chunk.remaining(); -- socketWrapper.write(isBlocking(), chunk); -+ SocketWrapperBase socketWrapper = Http11OutputBuffer.this.socketWrapper; -+ if (socketWrapper != null) { -+ socketWrapper.write(isBlocking(), chunk); -+ } else { -+ throw new CloseNowException(sm.getString("iob.failedwrite")); -+ } - len -= chunk.remaining(); - byteCount += len; - return len; -diff --git a/test/org/apache/catalina/core/TestAsyncContextImpl.java b/test/org/apache/catalina/core/TestAsyncContextImpl.java -index 3f6524b..4023a74 100644 ---- a/test/org/apache/catalina/core/TestAsyncContextImpl.java -+++ b/test/org/apache/catalina/core/TestAsyncContextImpl.java -@@ -17,6 +17,7 @@ - package org.apache.catalina.core; - - import java.io.IOException; -+import java.io.InputStream; - import java.io.PrintWriter; - import java.net.URI; - import java.net.URISyntaxException; -@@ -819,7 +820,7 @@ public class TestAsyncContextImpl extends TomcatBaseTest { - } - } - -- private static class TrackingListener implements AsyncListener { -+ public static class TrackingListener implements AsyncListener { - - private final boolean completeOnError; - private final boolean completeOnTimeout; -@@ -2653,4 +2654,173 @@ public class TestAsyncContextImpl extends TomcatBaseTest { - } - - } -+ -+ -+ -+ /* -+ * Tests an error on an async thread when the client closes the connection -+ * before fully writing the request body. -+ * -+ * Required sequence is: -+ * - enter Servlet's service() method -+ * - startAsync() -+ * - start async thread -+ * - read partial body -+ * - close client connection -+ * - read on async thread -> I/O error -+ * - exit Servlet's service() method -+ * -+ * This test makes extensive use of instance fields in the Servlet that -+ * would normally be considered very poor practice. It is only safe in this -+ * test as the Servlet only processes a single request. -+ */ -+ @Test -+ public void testCanceledPost() throws Exception { -+ CountDownLatch partialReadLatch = new CountDownLatch(1); -+ CountDownLatch clientCloseLatch = new CountDownLatch(1); -+ CountDownLatch threadCompleteLatch = new CountDownLatch(1); -+ -+ AtomicBoolean testFailed = new AtomicBoolean(true); -+ -+ // Setup Tomcat instance -+ Tomcat tomcat = getTomcatInstance(); -+ -+ // No file system docBase required -+ Context ctx = tomcat.addContext("", null); -+ -+ PostServlet postServlet = new PostServlet(partialReadLatch, clientCloseLatch, threadCompleteLatch, testFailed); -+ Wrapper wrapper = Tomcat.addServlet(ctx, "postServlet", postServlet); -+ wrapper.setAsyncSupported(true); -+ ctx.addServletMappingDecoded("/*", "postServlet"); -+ -+ tomcat.start(); -+ -+ PostClient client = new PostClient(); -+ client.setPort(getPort()); -+ client.setRequest(new String[] { "POST / HTTP/1.1" + SimpleHttpClient.CRLF + -+ "Host: localhost:" + SimpleHttpClient.CRLF + -+ "Content-Length: 100" + SimpleHttpClient.CRLF + -+ SimpleHttpClient.CRLF + -+ "This is 16 bytes" -+ }); -+ client.connect(); -+ client.sendRequest(); -+ -+ // Wait server to read partial request body -+ partialReadLatch.await(); -+ -+ client.disconnect(); -+ -+ clientCloseLatch.countDown(); -+ -+ threadCompleteLatch.await(); -+ -+ Assert.assertFalse(testFailed.get()); -+ } -+ -+ -+ private static final class PostClient extends SimpleHttpClient { -+ -+ @Override -+ public boolean isResponseBodyOK() { -+ return true; -+ } -+ } -+ -+ -+ private static final class PostServlet extends HttpServlet { -+ -+ private static final long serialVersionUID = 1L; -+ -+ private final transient CountDownLatch partialReadLatch; -+ private final transient CountDownLatch clientCloseLatch; -+ private final transient CountDownLatch threadCompleteLatch; -+ private final AtomicBoolean testFailed; -+ -+ public PostServlet(CountDownLatch doPostLatch, CountDownLatch clientCloseLatch, -+ CountDownLatch threadCompleteLatch, AtomicBoolean testFailed) { -+ this.partialReadLatch = doPostLatch; -+ this.clientCloseLatch = clientCloseLatch; -+ this.threadCompleteLatch = threadCompleteLatch; -+ this.testFailed = testFailed; -+ } -+ -+ @Override -+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) -+ throws ServletException, IOException { -+ -+ AsyncContext ac = req.startAsync(); -+ Thread t = new PostServletThread(ac, partialReadLatch, clientCloseLatch, threadCompleteLatch, testFailed); -+ t.start(); -+ -+ try { -+ threadCompleteLatch.await(); -+ } catch (InterruptedException e) { -+ // Ignore -+ } -+ } -+ } -+ -+ -+ private static final class PostServletThread extends Thread { -+ -+ private final AsyncContext ac; -+ private final CountDownLatch partialReadLatch; -+ private final CountDownLatch clientCloseLatch; -+ private final CountDownLatch threadCompleteLatch; -+ private final AtomicBoolean testFailed; -+ -+ public PostServletThread(AsyncContext ac, CountDownLatch partialReadLatch, CountDownLatch clientCloseLatch, -+ CountDownLatch threadCompleteLatch, AtomicBoolean testFailed) { -+ this.ac = ac; -+ this.partialReadLatch = partialReadLatch; -+ this.clientCloseLatch = clientCloseLatch; -+ this.threadCompleteLatch = threadCompleteLatch; -+ this.testFailed = testFailed; -+ } -+ -+ @Override -+ public void run() { -+ try { -+ int bytesRead = 0; -+ byte[] buffer = new byte[32]; -+ InputStream is = null; -+ -+ try { -+ is = ac.getRequest().getInputStream(); -+ -+ // Read the partial request body -+ while (bytesRead < 16) { -+ int read = is.read(buffer); -+ if (read == -1) { -+ // Error condition -+ return; -+ } -+ bytesRead += read; -+ } -+ } catch (IOException ioe) { -+ // Error condition -+ return; -+ } finally { -+ partialReadLatch.countDown(); -+ } -+ -+ // Wait for client to close connection -+ clientCloseLatch.await(); -+ -+ // Read again -+ try { -+ is.read(); -+ } catch (IOException e) { -+ e.printStackTrace(); -+ // Required. Clear the error marker. -+ testFailed.set(false); -+ } -+ } catch (InterruptedException e) { -+ // Ignore -+ } finally { -+ threadCompleteLatch.countDown(); -+ } -+ } -+ } - } -diff --git a/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java b/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java -index 7130b11..6868375 100644 ---- a/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java -+++ b/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java -@@ -32,6 +32,9 @@ import java.util.Map; - import java.util.Set; - import java.util.concurrent.CountDownLatch; - import java.util.concurrent.TimeUnit; -+import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.logging.Level; -+import java.util.logging.LogManager; - - import javax.net.SocketFactory; - import javax.servlet.AsyncContext; -@@ -44,6 +47,7 @@ import javax.servlet.ServletInputStream; - import javax.servlet.ServletOutputStream; - import javax.servlet.WriteListener; - import javax.servlet.annotation.WebServlet; -+import javax.servlet.http.HttpServlet; - import javax.servlet.http.HttpServletRequest; - import javax.servlet.http.HttpServletResponse; - -@@ -52,7 +56,9 @@ import org.junit.Ignore; - import org.junit.Test; - - import org.apache.catalina.Context; -+import org.apache.catalina.Wrapper; - import org.apache.catalina.startup.BytesStreamer; -+import org.apache.catalina.startup.SimpleHttpClient; - import org.apache.catalina.startup.TesterServlet; - import org.apache.catalina.startup.Tomcat; - import org.apache.catalina.startup.TomcatBaseTest; -@@ -997,4 +1003,190 @@ public class TestNonBlockingAPI extends TomcatBaseTest { - - } - } -+ -+ -+ /* -+ * Tests an error on an non-blocking read when the client closes the -+ * connection before fully writing the request body. -+ * -+ * Required sequence is: -+ * - enter Servlet's service() method -+ * - startAsync() -+ * - configure non-blocking read -+ * - read partial body -+ * - close client connection -+ * - error is triggered -+ * - exit Servlet's service() method -+ * -+ * This test makes extensive use of instance fields in the Servlet that -+ * would normally be considered very poor practice. It is only safe in this -+ * test as the Servlet only processes a single request. -+ */ -+ @Test -+ public void testCanceledPost() throws Exception { -+ -+ LogManager.getLogManager().getLogger("org.apache.coyote").setLevel(Level.ALL); -+ LogManager.getLogManager().getLogger("org.apache.tomcat.util.net").setLevel(Level.ALL); -+ -+ CountDownLatch partialReadLatch = new CountDownLatch(1); -+ CountDownLatch completeLatch = new CountDownLatch(1); -+ -+ AtomicBoolean testFailed = new AtomicBoolean(true); -+ -+ // Setup Tomcat instance -+ Tomcat tomcat = getTomcatInstance(); -+ -+ // No file system docBase required -+ Context ctx = tomcat.addContext("", null); -+ -+ PostServlet postServlet = new PostServlet(partialReadLatch, completeLatch, testFailed); -+ Wrapper wrapper = Tomcat.addServlet(ctx, "postServlet", postServlet); -+ wrapper.setAsyncSupported(true); -+ ctx.addServletMappingDecoded("/*", "postServlet"); -+ -+ tomcat.start(); -+ -+ PostClient client = new PostClient(); -+ client.setPort(getPort()); -+ client.setRequest(new String[] { "POST / HTTP/1.1" + SimpleHttpClient.CRLF + -+ "Host: localhost:" + SimpleHttpClient.CRLF + -+ "Content-Length: 100" + SimpleHttpClient.CRLF + -+ SimpleHttpClient.CRLF + -+ "This is 16 bytes" -+ }); -+ client.connect(); -+ client.sendRequest(); -+ -+ // Wait server to read partial request body -+ partialReadLatch.await(); -+ -+ client.disconnect(); -+ -+ completeLatch.await(); -+ -+ Assert.assertFalse(testFailed.get()); -+ } -+ -+ -+ private static final class PostClient extends SimpleHttpClient { -+ -+ @Override -+ public boolean isResponseBodyOK() { -+ return true; -+ } -+ } -+ -+ -+ private static final class PostServlet extends HttpServlet { -+ -+ private static final long serialVersionUID = 1L; -+ -+ private final transient CountDownLatch partialReadLatch; -+ private final transient CountDownLatch completeLatch; -+ private final AtomicBoolean testFailed; -+ -+ public PostServlet(CountDownLatch doPostLatch, CountDownLatch completeLatch, AtomicBoolean testFailed) { -+ this.partialReadLatch = doPostLatch; -+ this.completeLatch = completeLatch; -+ this.testFailed = testFailed; -+ } -+ -+ @Override -+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) -+ throws ServletException, IOException { -+ -+ AsyncContext ac = req.startAsync(); -+ ac.setTimeout(-1); -+ CanceledPostAsyncListener asyncListener = new CanceledPostAsyncListener(completeLatch); -+ ac.addListener(asyncListener); -+ -+ CanceledPostReadListener readListener = new CanceledPostReadListener(ac, partialReadLatch, testFailed); -+ req.getInputStream().setReadListener(readListener); -+ } -+ } -+ -+ -+ private static final class CanceledPostAsyncListener implements AsyncListener { -+ -+ private final transient CountDownLatch completeLatch; -+ -+ public CanceledPostAsyncListener(CountDownLatch completeLatch) { -+ this.completeLatch = completeLatch; -+ } -+ -+ @Override -+ public void onComplete(AsyncEvent event) throws IOException { -+ System.out.println("complete"); -+ completeLatch.countDown(); -+ } -+ -+ @Override -+ public void onTimeout(AsyncEvent event) throws IOException { -+ System.out.println("onTimeout"); -+ } -+ -+ @Override -+ public void onError(AsyncEvent event) throws IOException { -+ System.out.println("onError-async"); -+ } -+ -+ @Override -+ public void onStartAsync(AsyncEvent event) throws IOException { -+ System.out.println("onStartAsync"); -+ } -+ } -+ -+ private static final class CanceledPostReadListener implements ReadListener { -+ -+ private final AsyncContext ac; -+ private final CountDownLatch partialReadLatch; -+ private final AtomicBoolean testFailed; -+ private int totalRead = 0; -+ -+ public CanceledPostReadListener(AsyncContext ac, CountDownLatch partialReadLatch, AtomicBoolean testFailed) { -+ this.ac = ac; -+ this.partialReadLatch = partialReadLatch; -+ this.testFailed = testFailed; -+ } -+ -+ @Override -+ public void onDataAvailable() throws IOException { -+ ServletInputStream sis = ac.getRequest().getInputStream(); -+ boolean isReady; -+ -+ byte[] buffer = new byte[32]; -+ do { -+ if (partialReadLatch.getCount() == 0) { -+ System.out.println("debug"); -+ } -+ int bytesRead = sis.read(buffer); -+ -+ if (bytesRead == -1) { -+ return; -+ } -+ totalRead += bytesRead; -+ isReady = sis.isReady(); -+ System.out.println("Read [" + bytesRead + -+ "], buffer [" + new String(buffer, 0, bytesRead, StandardCharsets.UTF_8) + -+ "], total read [" + totalRead + -+ "], isReady [" + isReady + "]"); -+ } while (isReady); -+ if (totalRead == 16) { -+ partialReadLatch.countDown(); -+ } -+ } -+ -+ @Override -+ public void onAllDataRead() throws IOException { -+ ac.complete(); -+ } -+ -+ @Override -+ public void onError(Throwable throwable) { -+ throwable.printStackTrace(); -+ // This is the expected behaviour so clear the failed flag. -+ testFailed.set(false); -+ ac.complete(); -+ } -+ } - } --- -2.33.0 - diff --git a/apache-tomcat-9.0.96-src.tar.gz b/apache-tomcat-9.0.96-src.tar.gz new file mode 100644 index 0000000..2fcd495 Binary files /dev/null and b/apache-tomcat-9.0.96-src.tar.gz differ diff --git a/build-with-jdk-1.8.patch b/build-with-jdk-1.8.patch new file mode 100644 index 0000000..a6f6050 --- /dev/null +++ b/build-with-jdk-1.8.patch @@ -0,0 +1,88 @@ +diff --git a/build.xml b/build.xml +index 5c09831..9efcd81 100644 +--- a/build.xml ++++ b/build.xml +@@ -108,8 +108,8 @@ + + + +- +- ++ ++ + + + +@@ -1497,8 +1497,6 @@ + + +- +- + + + +diff --git a/java/org/apache/jasper/compiler/JDTCompiler.java b/java/org/apache/jasper/compiler/JDTCompiler.java +index 1ed4ef4..8339eff 100644 +--- a/java/org/apache/jasper/compiler/JDTCompiler.java ++++ b/java/org/apache/jasper/compiler/JDTCompiler.java +@@ -297,17 +297,17 @@ public class JDTCompiler extends org.apache.jasper.compiler.Compiler { + } else if(opt.equals("10")) { + settings.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_10); + } else if(opt.equals("11")) { +- settings.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_11); ++ settings.put(CompilerOptions.OPTION_Source, "11"); + } else if(opt.equals("12")) { +- settings.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_12); ++ settings.put(CompilerOptions.OPTION_Source, "12"); + } else if(opt.equals("13")) { +- settings.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_13); ++ settings.put(CompilerOptions.OPTION_Source, "13"); + } else if(opt.equals("14")) { +- settings.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_14); ++ settings.put(CompilerOptions.OPTION_Source, "14"); + } else if(opt.equals("15")) { +- settings.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_15); ++ settings.put(CompilerOptions.OPTION_Source, "15"); + } else if(opt.equals("16")) { +- settings.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_16); ++ settings.put(CompilerOptions.OPTION_Source, "16"); + } else if(opt.equals("17")) { + // Constant not available in latest ECJ version that runs on + // Java 8. +@@ -389,23 +389,23 @@ public class JDTCompiler extends org.apache.jasper.compiler.Compiler { + settings.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_10); + settings.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_10); + } else if(opt.equals("11")) { +- settings.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_11); +- settings.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_11); ++ settings.put(CompilerOptions.OPTION_TargetPlatform, "11"); ++ settings.put(CompilerOptions.OPTION_Compliance, "11"); + } else if(opt.equals("12")) { +- settings.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_12); +- settings.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_12); ++ settings.put(CompilerOptions.OPTION_TargetPlatform, "12"); ++ settings.put(CompilerOptions.OPTION_Compliance, "12"); + } else if(opt.equals("13")) { +- settings.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_13); +- settings.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_13); ++ settings.put(CompilerOptions.OPTION_TargetPlatform, "13"); ++ settings.put(CompilerOptions.OPTION_Compliance, "13"); + } else if(opt.equals("14")) { +- settings.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_14); +- settings.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_14); ++ settings.put(CompilerOptions.OPTION_TargetPlatform, "14"); ++ settings.put(CompilerOptions.OPTION_Compliance, "14"); + } else if(opt.equals("15")) { +- settings.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_15); +- settings.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_15); ++ settings.put(CompilerOptions.OPTION_TargetPlatform, "15"); ++ settings.put(CompilerOptions.OPTION_Compliance, "15"); + } else if(opt.equals("16")) { +- settings.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_16); +- settings.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_16); ++ settings.put(CompilerOptions.OPTION_TargetPlatform, "16"); ++ settings.put(CompilerOptions.OPTION_Compliance, "16"); + } else if(opt.equals("17")) { + // Constant not available in latest ECJ version that runs on + // Java 8. diff --git a/disableJavadocFailOnWarning.patch b/disableJavadocFailOnWarning.patch deleted file mode 100644 index b37a535..0000000 --- a/disableJavadocFailOnWarning.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- tomcat/build.xml.orig 2018-03-15 13:49:03.366863009 -0400 -+++ tomcat/build.xml 2018-03-15 13:49:29.690870139 -0400 -@@ -1777,7 +1777,7 @@ Apache Tomcat ${version} native binaries - additionalparam="-breakiterator -notimestamp" - maxmemory="512m" - failonerror="true" -- failonwarning="true"> -+ failonwarning="false"> - - - -@@ -1798,7 +1798,7 @@ Apache Tomcat ${version} native binaries - additionalparam="-breakiterator -notimestamp" - maxmemory="512m" - failonerror="true" -- failonwarning="true"> -+ failonwarning="false"> - - - -@@ -1819,7 +1819,7 @@ Apache Tomcat ${version} native binaries - additionalparam="-breakiterator -notimestamp" - maxmemory="512m" - failonerror="true" -- failonwarning="true"> -+ failonwarning="false"> - - - -@@ -1840,7 +1840,7 @@ Apache Tomcat ${version} native binaries - additionalparam="-breakiterator -notimestamp" - maxmemory="512m" - failonerror="true" -- failonwarning="true"> -+ failonwarning="false"> - - - -@@ -1860,7 +1860,7 @@ Apache Tomcat ${version} native binaries - additionalparam="-breakiterator -notimestamp ${java9.add.modules}" - maxmemory="512m" - failonerror="true" -- failonwarning="true"> -+ failonwarning="false"> - - - diff --git a/el-api-OSGi-MANIFEST.MF b/el-api-OSGi-MANIFEST.MF deleted file mode 100644 index 69b797f..0000000 --- a/el-api-OSGi-MANIFEST.MF +++ /dev/null @@ -1,13 +0,0 @@ -Manifest-Version: 1.0 -Export-Package: javax.el;version="2.2.0" -Bundle-Vendor: %bundleProvider -Bundle-ClassPath: . -Bundle-Version: 2.2.0 -Bundle-Name: %bundleName -Bundle-Localization: plugin -Bundle-ManifestVersion: 2 -Bundle-SymbolicName: javax.el -DynamicImport-Package: org.apache.el -Bundle-RequiredExecutionEnvironment: J2SE-1.4,CDC-1.0/Foundation-1.0,J - 2SE-1.3 - diff --git a/jasper-OSGi-MANIFEST.MF b/jasper-OSGi-MANIFEST.MF deleted file mode 100644 index ad34978..0000000 --- a/jasper-OSGi-MANIFEST.MF +++ /dev/null @@ -1,40 +0,0 @@ -Manifest-Version: 1.0 -Export-Package: org.apache.jasper;version="8.0.26",org.apache.jasper.c - ompiler;version="8.0.26",org.apache.jasper.compiler.tagplugin;version - ="8.0.26",org.apache.jasper.resources;version="8.0.26",org.apache.jas - per.runtime;version="8.0.26",org.apache.jasper.security;version="7.0. - 19",org.apache.jasper.servlet;version="8.0.26",org.apache.jasper.tagp - lugins.jstl;version="8.0.26",org.apache.jasper.tagplugins.jstl.core;v - ersion="8.0.26",org.apache.jasper.util;version="8.0.26",org.apache.ja - sper.xmlparser;version="8.0.26" -Bundle-Vendor: %bundleProvider -Bundle-ClassPath: . -Bundle-Version: 8.0.26 -Bundle-Localization: plugin -Bundle-Name: %bundleName -Bundle-ManifestVersion: 2 -Bundle-SymbolicName: org.apache.jasper -Import-Package: javax.servlet;version="[2.4.0, 3.0.0]",javax.servlet.h - ttp;version="[2.4.0, 3.0.0]",javax.servlet.jsp;version="[2.0.0, 2.2.0 - ]",javax.servlet.jsp.el;version="[2.0.0, 2.2.0]",javax.servlet.jsp.re - sources;version="[2.0.0, 2.2.0]",javax.servlet.jsp.tagext;version="[2 - .0.0, 2.2.0]",javax.servlet.resources;version="[2.4.0, 3.0.0]",javax. - xml.parsers,org.apache.commons.el;version="[1.0.0,2.0.0)",org.apache. - commons.logging;version="[1.0.0,2.0.0)",org.apache.tools.ant;resoluti - on:=optional,org.apache.tools.ant.taskdefs;resolution:=optional,org.a - pache.tools.ant.types;resolution:=optional,org.apache.tools.ant.util; - resolution:=optional,org.w3c.dom,org.xml.sax,org.xml.sax.ext,org.xml. - sax.helpers,org.apache.tomcat;version="8.0.26",org.apache.juli.loggin - g;version="8.0.26",javax.el;version="2.2.0",org.eclipse.jdt.internal. - compiler,org.eclipse.jdt.internal.compiler.parser,org.eclipse.jdt.int - ernal.compiler.parser.diagnose,org.eclipse.jdt.internal.compiler.flow - ,org.eclipse.jdt.internal.compiler.util,org.eclipse.jdt.internal.comp - iler.impl,org.eclipse.jdt.internal.compiler.lookup,org.eclipse.jdt.in - ternal.compiler.codegen,org.eclipse.jdt.internal.compiler.batch,org.e - clipse.jdt.internal.compiler.classfmt,org.eclipse.jdt.internal.compil - er.ast,org.eclipse.jdt.internal.compiler.problem,org.eclipse.jdt.inte - rnal.compiler.env,org.eclipse.jdt.internal.core.util,org.eclipse.jdt. - core.compiler -Bundle-RequiredExecutionEnvironment: J2SE-1.4,CDC-1.0/Foundation-1.0,J - 2SE-1.3 - diff --git a/jasper-el-OSGi-MANIFEST.MF b/jasper-el-OSGi-MANIFEST.MF deleted file mode 100644 index 14e4282..0000000 --- a/jasper-el-OSGi-MANIFEST.MF +++ /dev/null @@ -1,13 +0,0 @@ -Manifest-Version: 1.0 -Export-Package: org.apache.el;version="7.0.21" -Bundle-Vendor: %bundleProvider -Bundle-ClassPath: . -Bundle-Version: 8.0.26 -Bundle-Name: %bundleName -Bundle-Localization: plugin -Bundle-ManifestVersion: 2 -Import-Package: javax.el;version="2.2" -Bundle-SymbolicName: org.apache.el -Bundle-RequiredExecutionEnvironment: J2SE-1.4,CDC-1.0/Foundation-1.0,J - 2SE-1.3 - diff --git a/java-9-start-up-parameters.conf b/java-9-start-up-parameters.conf new file mode 100644 index 0000000..341e077 --- /dev/null +++ b/java-9-start-up-parameters.conf @@ -0,0 +1,7 @@ +# Add the JAVA 9 specific start-up parameters required by Tomcat +JDK_JAVA_OPTIONS="$JDK_JAVA_OPTIONS --add-opens=java.base/java.lang=ALL-UNNAMED" +JDK_JAVA_OPTIONS="$JDK_JAVA_OPTIONS --add-opens=java.base/java.io=ALL-UNNAMED" +JDK_JAVA_OPTIONS="$JDK_JAVA_OPTIONS --add-opens=java.base/java.util=ALL-UNNAMED" +JDK_JAVA_OPTIONS="$JDK_JAVA_OPTIONS --add-opens=java.base/java.util.concurrent=ALL-UNNAMED" +JDK_JAVA_OPTIONS="$JDK_JAVA_OPTIONS --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED" +export JDK_JAVA_OPTIONS diff --git a/jsp-api-OSGi-MANIFEST.MF b/jsp-api-OSGi-MANIFEST.MF deleted file mode 100644 index 62bc00d..0000000 --- a/jsp-api-OSGi-MANIFEST.MF +++ /dev/null @@ -1,13 +0,0 @@ -Manifest-Version: 1.0 -Bundle-Vendor: %bundleProvider -Bundle-Localization: plugin -Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,J2SE-1.3 -Bundle-Name: %bundleName -Bundle-SymbolicName: javax.servlet.jsp -Export-Package: javax.servlet.jsp; version=2.2,javax.servlet.jsp.el; v - ersion=2.2,javax.servlet.jsp.resources; version=2.2,javax.servlet.jsp - .tagext; version=2.2 -Bundle-Version: 2.2.0.v200806031607 -Bundle-ManifestVersion: 2 -Import-Package: javax.servlet; version=3.0,javax.servlet.http; version - =3.0,javax.servlet.resources; version=3.0,javax.el;version="2.2.0" diff --git a/remove-bnd-annotation.patch b/remove-bnd-annotation.patch new file mode 100644 index 0000000..7aed665 --- /dev/null +++ b/remove-bnd-annotation.patch @@ -0,0 +1,74 @@ +diff --git a/build.xml b/build.xml +index 1a4b255..ea50aeb 100644 +--- a/build.xml ++++ b/build.xml +@@ -3296,7 +3296,7 @@ asf.ldap.username=${release.asfusername} + + ++ > + + + +diff --git a/java/org/apache/el/ExpressionFactoryImpl.java b/java/org/apache/el/ExpressionFactoryImpl.java +index 3a6690a..03a2afe 100644 +--- a/java/org/apache/el/ExpressionFactoryImpl.java ++++ b/java/org/apache/el/ExpressionFactoryImpl.java +@@ -34,7 +34,7 @@ import org.apache.el.util.MessageFactory; + * + * @author Jacob Hookom [jacob@hookom.net] + */ +-@aQute.bnd.annotation.spi.ServiceProvider(value = ExpressionFactory.class) ++//@aQute.bnd.annotation.spi.ServiceProvider(value = ExpressionFactory.class) + public class ExpressionFactoryImpl extends ExpressionFactory { + + static { +diff --git a/java/org/apache/juli/logging/LogFactory.java b/java/org/apache/juli/logging/LogFactory.java +index bfc4238..acf989a 100644 +--- a/java/org/apache/juli/logging/LogFactory.java ++++ b/java/org/apache/juli/logging/LogFactory.java +@@ -21,7 +21,7 @@ import java.nio.file.FileSystems; + import java.util.ServiceLoader; + import java.util.logging.LogManager; + +-import aQute.bnd.annotation.spi.ServiceConsumer; ++//import aQute.bnd.annotation.spi.ServiceConsumer; + + /** + * This is a modified LogFactory that uses a simple {@link ServiceLoader} based +@@ -63,7 +63,7 @@ import aQute.bnd.annotation.spi.ServiceConsumer; + * @author Costin Manolache + * @author Richard A. Sitze + */ +-@ServiceConsumer(value=Log.class) ++//@ServiceConsumer(value=Log.class) + public class LogFactory { + + private static final LogFactory singleton = new LogFactory(); +diff --git a/java/org/apache/tomcat/websocket/WsContainerProvider.java b/java/org/apache/tomcat/websocket/WsContainerProvider.java +index 4b0577c..e383290 100644 +--- a/java/org/apache/tomcat/websocket/WsContainerProvider.java ++++ b/java/org/apache/tomcat/websocket/WsContainerProvider.java +@@ -19,7 +19,7 @@ package org.apache.tomcat.websocket; + import javax.websocket.ContainerProvider; + import javax.websocket.WebSocketContainer; + +-@aQute.bnd.annotation.spi.ServiceProvider(value = ContainerProvider.class) ++//@aQute.bnd.annotation.spi.ServiceProvider(value = ContainerProvider.class) + public class WsContainerProvider extends ContainerProvider { + + @Override +diff --git a/java/org/apache/tomcat/websocket/server/DefaultServerEndpointConfigurator.java b/java/org/apache/tomcat/websocket/server/DefaultServerEndpointConfigurator.java +index 00f492e..fe5c34d 100644 +--- a/java/org/apache/tomcat/websocket/server/DefaultServerEndpointConfigurator.java ++++ b/java/org/apache/tomcat/websocket/server/DefaultServerEndpointConfigurator.java +@@ -26,7 +26,7 @@ import javax.websocket.HandshakeResponse; + import javax.websocket.server.HandshakeRequest; + import javax.websocket.server.ServerEndpointConfig; + +-@aQute.bnd.annotation.spi.ServiceProvider(value = ServerEndpointConfig.Configurator.class) ++//@aQute.bnd.annotation.spi.ServiceProvider(value = ServerEndpointConfig.Configurator.class) + public class DefaultServerEndpointConfigurator extends ServerEndpointConfig.Configurator { + + @Override diff --git a/rhbz-1857043.patch b/rhbz-1857043.patch new file mode 100644 index 0000000..6fb739c --- /dev/null +++ b/rhbz-1857043.patch @@ -0,0 +1,208 @@ +diff -up a/build.xml.orig b/build.xml +--- a/build.xml.orig 2021-07-07 10:53:55.493742841 +0800 ++++ b/build.xml 2021-07-07 11:09:43.107968515 +0800 +@@ -1020,7 +1020,7 @@ + filesDir="${tomcat.classes}" + filesId="files.annotations-api" + manifest="${tomcat.manifests}/annotations-api.jar.manifest" +- addOSGi="true" /> ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + ++ addOSGi="false" /> + + + --> diff --git a/tomcat-9.0.conf b/tomcat-9.0.conf index 3f43006..e5fa60a 100644 --- a/tomcat-9.0.conf +++ b/tomcat-9.0.conf @@ -43,9 +43,8 @@ JAVA_OPTS="-Djavax.sql.DataSource.Factory=org.apache.commons.dbcp.BasicDataSourc # Run tomcat under the Java Security Manager SECURITY_MANAGER="false" -# Time to wait in seconds, before killing process -# TODO(stingray): does nothing, fix. -# SHUTDOWN_WAIT="30" +# SHUTDOWN_WAIT has been deprecated. To change the shutdown wait time, set +# TimeoutStopSec in tomcat.service. # If you wish to further customize your tomcat environment, # put your own definitions here diff --git a/tomcat-9.0.logrotate b/tomcat-9.0.logrotate index a87b4c0..082092a 100644 --- a/tomcat-9.0.logrotate +++ b/tomcat-9.0.logrotate @@ -1,4 +1,7 @@ -@@@TCLOG@@@/catalina.out { +# This is an example config only and is disabled by default +# If you wish to use it, you'll need to update /etc/tomcat/logging.properties +# to prevent catalina*.log from being rotated by Tomcat +@@@TCLOG@@@/catalina*.log { copytruncate weekly rotate 52 diff --git a/tomcat-9.0.service b/tomcat-9.0.service index 2b20aa0..832e7c6 100644 --- a/tomcat-9.0.service +++ b/tomcat-9.0.service @@ -15,8 +15,6 @@ EnvironmentFile=-/etc/sysconfig/tomcat ExecStart=/usr/libexec/tomcat/server start SuccessExitStatus=143 User=tomcat -Group=tomcat - [Install] WantedBy=multi-user.target diff --git a/tomcat-api-OSGi-MANIFEST.MF b/tomcat-api-OSGi-MANIFEST.MF deleted file mode 100644 index 85b12b8..0000000 --- a/tomcat-api-OSGi-MANIFEST.MF +++ /dev/null @@ -1,12 +0,0 @@ -Manifest-Version: 1.0 -Export-Package: org.apache.tomcat;version="8.0.26" -Bundle-Vendor: %bundleProvider -Bundle-ClassPath: . -Bundle-Version: 8.0.26 -Bundle-Name: %bundleName -Bundle-Localization: plugin -Bundle-ManifestVersion: 2 -Bundle-SymbolicName: org.apache.tomcat -Bundle-RequiredExecutionEnvironment: J2SE-1.4,CDC-1.0/Foundation-1.0,J - 2SE-1.3 - diff --git a/tomcat-build.patch b/tomcat-build.patch index cf39361..8aa9d0e 100644 --- a/tomcat-build.patch +++ b/tomcat-build.patch @@ -1,12 +1,11 @@ ---- tomcat/build.xml.orig 2018-08-07 10:32:04.994403913 -0400 -+++ tomcat/build.xml 2018-08-07 10:32:30.874319588 -0400 -@@ -2989,6 +2989,9 @@ Read the Building page on the Apache Tom - - - -+ -+ -+ - +--- tomcat/res/bnd/build-defaults.bnd.orig 2024-05-01 11:07:38.804582327 +0300 ++++ tomcat/res/bnd/build-defaults.bnd 2024-05-01 11:17:08.857295279 +0300 +@@ -13,7 +13,7 @@ + # See the License for the specific language governing permissions and + # limitations under the License. - +-Bundle-Version: ${version_cleanup;${version}} ++Bundle-Version: ${version} + Bundle-License: https://www.apache.org/licenses/LICENSE-2.0.txt + + Specification-Title: Apache Tomcat diff --git a/tomcat-juli-OSGi-MANIFEST.MF b/tomcat-juli-OSGi-MANIFEST.MF deleted file mode 100644 index b856d9f..0000000 --- a/tomcat-juli-OSGi-MANIFEST.MF +++ /dev/null @@ -1,13 +0,0 @@ -Manifest-Version: 1.0 -Export-Package: org.apache.juli;version="8.0.26",org.apache.juli.loggi - ng;version="8.0.26" -Bundle-Vendor: %bundleProvider -Bundle-ClassPath: . -Bundle-Version: 8.0.26 -Bundle-Name: %bundleName -Bundle-Localization: plugin -Bundle-ManifestVersion: 2 -Bundle-SymbolicName: org.apache.juli -Bundle-RequiredExecutionEnvironment: J2SE-1.4,CDC-1.0/Foundation-1.0,J - 2SE-1.3 - diff --git a/tomcat-named.service b/tomcat-named.service index 9bbcb17..b6cd8bd 100644 --- a/tomcat-named.service +++ b/tomcat-named.service @@ -13,14 +13,12 @@ After=syslog.target network.target [Service] Type=simple EnvironmentFile=/etc/tomcat/tomcat.conf -Environment="NAME=%I" -EnvironmentFile=-/etc/sysconfig/tomcat@%I +Environment="NAME=%i" +EnvironmentFile=-/etc/sysconfig/tomcat@%i ExecStart=/usr/libexec/tomcat/server start ExecStop=/usr/libexec/tomcat/server stop SuccessExitStatus=143 User=tomcat -Group=tomcat [Install] WantedBy=multi-user.target - diff --git a/tomcat.spec b/tomcat.spec index 529e9d2..c5d4914 100644 --- a/tomcat.spec +++ b/tomcat.spec @@ -1,133 +1,74 @@ %global jspspec 2.3 %global major_version 9 %global minor_version 0 -%global micro_version 10 +%global micro_version 96 %global packdname apache-tomcat-%{version}-src %global servletspec 4.0 %global elspec 3.0 -%global tcuid 91 +%global tcuid 53 -%{!?_mavendepmapfragdir: %global _mavendepmapfragdir /usr/share/maven-metadata} -%{?fc24: %global _mavendepmapfragdir /usr/share/maven-metadata} +# FHS 2.3 compliant tree structure - http://www.pathname.com/fhs/2.3/ +%global basedir %{_var}/lib/%{name} +%global appdir %{basedir}/webapps +%global homedir %{_datadir}/%{name} +%global bindir %{homedir}/bin +%global confdir %{_sysconfdir}/%{name} +%global libdir %{_javadir}/%{name} +%global logdir %{_var}/log/%{name} +%global cachedir %{_var}/cache/%{name} +%global tempdir %{cachedir}/temp +%global workdir %{cachedir}/work +%global _systemddir /lib/systemd/system Name: tomcat Epoch: 1 Version: %{major_version}.%{minor_version}.%{micro_version} -Release: 33 -Summary: Implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies -License: ASL 2.0 -URL: http://tomcat.apache.org/ +Release: 1 +Summary: Apache Servlet/JSP Engine, RI for Servlet %{servletspec}/JSP %{jspspec} API -Source0: https://github.com/apache/tomcat/archive/%{version}.tar.gz +License: Apache-2.0 +URL: http://tomcat.apache.org/ +Source0: https://archive.apache.org/dist/tomcat/tomcat-%{major_version}/v%{version}/src/%{packdname}.tar.gz Source1: %{name}-%{major_version}.%{minor_version}.conf Source3: %{name}-%{major_version}.%{minor_version}.sysconfig Source4: %{name}-%{major_version}.%{minor_version}.wrapper Source5: %{name}-%{major_version}.%{minor_version}.logrotate Source6: %{name}-%{major_version}.%{minor_version}-digest.script Source7: %{name}-%{major_version}.%{minor_version}-tool-wrapper.script -Source8: servlet-api-OSGi-MANIFEST.MF -Source9: jsp-api-OSGi-MANIFEST.MF Source11: %{name}-%{major_version}.%{minor_version}.service -Source12: el-api-OSGi-MANIFEST.MF -Source13: jasper-el-OSGi-MANIFEST.MF -Source14: jasper-OSGi-MANIFEST.MF -Source15: tomcat-api-OSGi-MANIFEST.MF -Source16: tomcat-juli-OSGi-MANIFEST.MF Source20: %{name}-%{major_version}.%{minor_version}-jsvc.service Source21: tomcat-functions Source30: tomcat-preamble Source31: tomcat-server Source32: tomcat-named.service +Source33: java-9-start-up-parameters.conf Patch0: %{name}-%{major_version}.%{minor_version}-bootstrap-MANIFEST.MF.patch Patch1: %{name}-%{major_version}.%{minor_version}-tomcat-users-webapp.patch Patch2: %{name}-build.patch -Patch3: disableJavadocFailOnWarning.patch -Patch6001: CVE-2019-0199-1.patch -Patch6002: CVE-2019-0199-2.patch -Patch6003: CVE-2019-0199-3.patch -Patch6004: CVE-2019-0199-4.patch -Patch6005: CVE-2019-0199-5.patch -Patch6006: CVE-2019-0199-6.patch -Patch6007: CVE-2019-0199-7.patch -Patch6008: CVE-2019-0199-8.patch -Patch6009: CVE-2019-0199-9.patch -Patch6010: CVE-2019-0199-10.patch -Patch6011: CVE-2019-0199-11.patch -Patch6012: CVE-2018-11784.patch -Patch6013: CVE-2019-0221.patch -Patch6014: CVE-2019-10072-1.patch -Patch6015: CVE-2019-10072-2.patch -Patch6016: CVE-2019-17563.patch -Patch6017: CVE-2019-12418.patch -Patch6018: CVE-2020-1938-1.patch -Patch6019: CVE-2020-1938-2.patch -Patch6020: CVE-2020-1938-3.patch -Patch6021: CVE-2020-1938-4.patch -Patch6022: CVE-2020-1938-5.patch -Patch6023: CVE-2020-1935.patch -Patch6024: CVE-2020-9484.patch -Patch6025: CVE-2020-11996.patch -Patch6026: CVE-2020-13934.patch -Patch6027: CVE-2020-13935.patch -Patch6028: CVE-2020-13943-1.patch -Patch6029: CVE-2020-13943-2.patch -Patch6030: CVE-2020-13943-3.patch -Patch6031: CVE-2020-13943-4.patch -Patch6032: CVE-2020-17527.patch -Patch6033: CVE-2021-24122.patch -Patch6035: CVE-2021-25122-pre.patch -Patch6036: CVE-2021-25122.patch -Patch6037: CVE-2021-25329-pre1.patch -Patch6038: CVE-2021-25329-pre2.patch -Patch6039: CVE-2021-25329-pre3.patch -Patch6040: CVE-2021-25329.patch -Patch6041: CVE-2021-33037-1.patch -Patch6042: CVE-2021-33037-2.patch -Patch6043: CVE-2021-33037-3.patch -Patch6044: CVE-2021-30640-pre1.patch -Patch6045: CVE-2021-30640-pre2.patch -Patch6046: CVE-2021-30640-pre3.patch -Patch6047: CVE-2021-30640-pre4.patch -Patch6048: CVE-2021-30640-pre5.patch -Patch6049: CVE-2021-30640-1.patch -Patch6050: CVE-2021-30640-2.patch -Patch6051: CVE-2021-30640-3.patch -Patch6052: CVE-2021-30640-4.patch -Patch6053: CVE-2021-30640-5.patch -Patch6054: CVE-2021-30640-6.patch -Patch6055: CVE-2021-30640-7.patch -Patch6056: CVE-2021-30640-8.patch -Patch6057: CVE-2021-41079.patch -Patch6058: CVE-2021-42340.patch -Patch6069: CVE-2022-23181.patch -Patch6070: CVE-2022-42252.patch -Patch6071: CVE-2023-28708-pre.patch -Patch6072: CVE-2023-28708.patch -Patch6073: CVE-2023-41080.patch -Patch6074: CVE-2023-45648.patch -Patch6075: CVE-2024-21733.patch -Patch6076: CVE-2023-24998.patch -Patch6077: CVE-2023-28709.patch -Patch6078: CVE-2023-42795.patch +Patch3: %{name}-%{major_version}.%{minor_version}-catalina-policy.patch +Patch4: rhbz-1857043.patch +# remove bnd dependency which version is too low on rhel8 +Patch6: remove-bnd-annotation.patch +Patch7: build-with-jdk-1.8.patch -BuildRequires: ecj >= 1:4.6.1 findutils apache-commons-collections apache-commons-daemon -BuildRequires: apache-commons-dbcp apache-commons-pool tomcat-taglibs-standard ant -BuildRequires: jpackage-utils >= 0:1.7.0 java-devel >= 1:1.8.0 junit javapackages-local -BuildRequires: geronimo-saaj aqute-bndlib aqute-bnd systemd-units wsdl4j geronimo-jaxrpc +BuildArch: noarch -Requires: procps jpackage-utils java-headless >= 1:1.8.0 apache-commons-daemon -Requires: tomcat-taglibs-standard >= 0:1.1 ecj libtcnative-1-0 >= 1.2.14 -Requires: apache-commons-dbcp apache-commons-pool apache-commons-collections +BuildRequires: ant +BuildRequires: ecj +BuildRequires: findutils +BuildRequires: javapackages-local +BuildRequires: aqute-bnd +BuildRequires: aqute-bndlib +BuildRequires: systemd +Requires: (java-headless >= 1:1.8 or java-1.8.0-headless or java-11-headless or java-17-headless or java >= 1:1.8) +Requires: javapackages-tools +Requires: %{name}-lib = %{epoch}:%{version}-%{release} Requires(pre): shadow-utils -Requires(post): chkconfig -Requires(preun): chkconfig -Requires(postun): chkconfig - -Requires(post): systemd-units -Requires(preun): systemd-units -Requires(postun): systemd-units +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd Provides: %{name}-log4j = %{epoch}:%{version}-%{release} Provides: servlet = %{servletspec} servlet6 servlet3 el_api = %{elspec} jsp = %{jspspec} @@ -147,13 +88,16 @@ Obsoletes: %{name}-jsp-%{jspspec}-api < %{epoch}:%{version}-%{release} Obsoletes: %{name}-webapps < %{epoch}:%{version}-%{release} Obsoletes: %{name}-admin-webapps < %{epoch}:%{version}-%{release} -BuildArch: noarch - %description -The Apache Tomcat software is developed in an open and participatory environment -and released under the Apache License version 2. The Apache Tomcat project is -intended to be a collaboration of the best-of-breed developers from around the -world. We invite you to participate in this open development project +Tomcat is the servlet container that is used in the official Reference +Implementation for the Java Servlet and JavaServer Pages technologies. +The Java Servlet and JavaServer Pages specifications are developed by +Sun under the Java Community Process. + +Tomcat is developed in an open and participatory environment and +released under the Apache Software License version 2.0. Tomcat is intended +to be a collaboration of the best-of-breed developers from around the world. + %package jsvc Summary: Apache jsvc wrapper for Apache Tomcat as separate service @@ -179,124 +123,105 @@ Obsoletes: %{name}-javadoc < %{epoch}:%{version}-%{release} Man pages and other related documents for %{name}. %prep +%autosetup -p1 -n %{packdname} +# remove pre-built binaries and windows files find . -type f \( -name "*.bat" -o -name "*.class" -o -name Thumbs.db -o -name "*.gz" -o \ -name "*.jar" -o -name "*.war" -o -name "*.zip" \) -delete -%autosetup -p1 -n %{name}-%{version} +# Remove webservices naming resources as it's generally unused +%{__rm} -rf java/org/apache/naming/factory/webservices + +# Configure maven files +%mvn_package ":tomcat-el-api" tomcat-el-api +%mvn_alias "org.apache.tomcat:tomcat-el-api" "org.eclipse.jetty.orbit:javax.el" +%mvn_file org.apache.tomcat:tomcat-jsp-api tomcat/jsp-api +%mvn_package ":tomcat-jsp-api" tomcat-jsp-api +%mvn_alias "org.apache.tomcat:tomcat-jsp-api" "org.eclipse.jetty.orbit:javax.servlet.jsp" +%mvn_package ":tomcat-servlet-api" tomcat-servlet-api -ln -s $(build-classpath tomcat-taglibs-standard/taglibs-standard-impl) webapps/examples/WEB-INF/lib/jstl.jar -ln -s $(build-classpath tomcat-taglibs-standard/taglibs-standard-compat) webapps/examples/WEB-INF/lib/standard.jar %build export OPT_JAR_LIST="xalan-j2-serializer" - touch HACK - %{ant} -Dbase.path="." \ - -Dbuild.compiler="modern" \ - -Dcommons-collections.jar="$(build-classpath apache-commons-collections)" \ - -Dcommons-daemon.jar="$(build-classpath apache-commons-daemon)" \ - -Dcommons-daemon.native.src.tgz="HACK" \ - -Djdt.jar="$(build-classpath ecj/ecj)" \ - -Dtomcat-native.tar.gz="HACK" \ - -Dtomcat-native.home="." \ - -Dcommons-daemon.native.win.mgr.exe="HACK" \ - -Dnsis.exe="HACK" \ - -Djaxrpc-lib.jar="$(build-classpath jaxrpc)" \ - -Dwsdl4j-lib.jar="$(build-classpath wsdl4j)" \ - -Dsaaj-api.jar="$(build-classpath geronimo-saaj)" \ - -Dbnd.jar="$(build-classpath aqute-bnd/biz.aQute.bnd)" \ - -Dbndlib.jar="$(build-classpath aqute-bnd/biz.aQute.bndlib)" \ - -Dbndlibg.jar="$(build-classpath aqute-bnd/aQute.libg)" \ - -Dbndannotation.jar="$(build-classpath aqute-bnd/biz.aQute.bnd.annotation)" \ - -Dslf4j-api.jar="$(build-classpath slf4j/slf4j-api)" \ - -Dno.build.dbcp=true \ - -Dversion="%{version}" \ - -Dversion.build="%{micro_version}" \ - -Djava.7.home=%{java_home} \ - -Dexecute.validate=false \ - deploy dist-prepare dist-source javadoc - rm output/build/bin/commons-daemon.jar output/build/lib/ecj.jar -pushd output/dist/src/webapps/docs/appdev/sample/src -mkdir -p ../web/WEB-INF/classes -%{javac} -cp ../../../../../../../../output/build/lib/servlet-api.jar -d ../web/WEB-INF/classes mypackage/Hello.java -pushd ../web -%{jar} cf ../../../../../../../../output/build/webapps/docs/appdev/sample/sample.war * -popd -popd +# we don't care about the tarballs and we're going to replace +# tomcat-dbcp.jar with apache-commons-{collections,dbcp,pool}-tomcat5.jar +# so just create a dummy file for later removal +touch HACK -mkdir -p META-INF -cp -p %{SOURCE8} META-INF/MANIFEST.MF -touch META-INF/MANIFEST.MF -zip output/build/lib/servlet-api.jar META-INF/MANIFEST.MF -cp -p %{SOURCE9} META-INF/MANIFEST.MF -touch META-INF/MANIFEST.MF -zip output/build/lib/jsp-api.jar META-INF/MANIFEST.MF -cp -p %{SOURCE12} META-INF/MANIFEST.MF -touch META-INF/MANIFEST.MF -zip output/build/lib/el-api.jar META-INF/MANIFEST.MF -cp -p %{SOURCE13} META-INF/MANIFEST.MF -touch META-INF/MANIFEST.MF -zip output/build/lib/jasper-el.jar META-INF/MANIFEST.MF -cp -p %{SOURCE14} META-INF/MANIFEST.MF -touch META-INF/MANIFEST.MF -zip output/build/lib/jasper.jar META-INF/MANIFEST.MF -cp -p %{SOURCE15} META-INF/MANIFEST.MF -touch META-INF/MANIFEST.MF -zip output/build/lib/tomcat-api.jar META-INF/MANIFEST.MF -cp -p %{SOURCE16} META-INF/MANIFEST.MF -touch META-INF/MANIFEST.MF -zip output/build/bin/tomcat-juli.jar META-INF/MANIFEST.MF +# who needs a build.properties file anyway +%{ant} -Dbase.path="." \ + -Dbuild.compiler="modern" \ + -Dcommons-daemon.jar="HACK" \ + -Dcommons-daemon.native.src.tgz="HACK" \ + -Djdt.jar="$(build-classpath ecj/ecj)" \ + -Dtomcat-native.tar.gz="HACK" \ + -Dtomcat-native.home="." \ + -Dcommons-daemon.native.win.mgr.exe="HACK" \ + -Dnsis.exe="HACK" \ + -Djaxrpc-lib.jar="HACK" \ + -Dwsdl4j-lib.jar="HACK" \ + -Dbnd.jar="HACK" \ + -Dversion="%{version}" \ + -Dversion.build="%{micro_version}" \ + deploy + +# remove some jars that we'll replace with symlinks later +%{__rm} output/build/lib/ecj.jar +# Remove the example webapps per Apache Tomcat Security Considerations +# see https://tomcat.apache.org/tomcat-9.0-doc/security-howto.html +%{__rm} -rf output/build/webapps/examples %install install -d -m 0755 %{buildroot}%{_bindir} install -d -m 0755 %{buildroot}%{_sbindir} -install -d -m 0755 %{buildroot}%{_javadocdir}/%{name} install -d -m 0755 %{buildroot}%{_sysconfdir}/init.d -install -d -m 0755 %{buildroot}/lib/systemd/system +install -d -m 0755 %{buildroot}%{_systemddir} install -d -m 0755 %{buildroot}%{_sysconfdir}/logrotate.d install -d -m 0755 %{buildroot}%{_sysconfdir}/sysconfig -install -d -m 0755 %{buildroot}%{_var}/lib/%{name}/webapps -install -d -m 0755 %{buildroot}%{_datadir}/%{name}/bin -install -d -m 0775 %{buildroot}%{_sysconfdir}/%{name} -install -d -m 0775 %{buildroot}%{_sysconfdir}/%{name}/Catalina/localhost -install -d -m 0775 %{buildroot}%{_sysconfdir}/%{name}/conf.d +install -d -m 0755 %{buildroot}%{appdir} +install -d -m 0755 %{buildroot}%{bindir} +install -d -m 0775 %{buildroot}%{confdir} +install -d -m 0775 %{buildroot}%{confdir}/Catalina/localhost +install -d -m 0775 %{buildroot}%{confdir}/conf.d /bin/echo "Place your custom *.conf files here. Shell expansion is supported." > %{buildroot}%{_sysconfdir}/%{name}/conf.d/README -install -d -m 0755 %{buildroot}%{_javadir}/%{name} -install -d -m 0775 %{buildroot}%{_var}/log/%{name} -/bin/touch %{buildroot}%{_var}/log/%{name}/catalina.out +install -d -m 0755 %{buildroot}%{libdir} +install -d -m 0775 %{buildroot}%{logdir} +/bin/touch %{buildroot}%{logdir}/catalina.out install -d -m 0775 %{buildroot}%{_localstatedir}/lib/tomcats -install -d -m 0775 %{buildroot}%{_datadir}/%{name} -install -d -m 0775 %{buildroot}%{_var}/cache/%{name}/temp -install -d -m 0775 %{buildroot}%{_var}/cache/%{name}/work +install -d -m 0775 %{buildroot}%{homedir} +install -d -m 0775 %{buildroot}%{tempdir} +install -d -m 0775 %{buildroot}%{workdir} install -d -m 0755 %{buildroot}%{_unitdir} install -d -m 0755 %{buildroot}%{_libexecdir}/%{name} pushd output/build - cp -a bin/*.{jar,xml} %{buildroot}%{_datadir}/%{name}/bin - cp -a conf/*.{policy,properties,xml,xsd} %{buildroot}%{_sysconfdir}/%{name} - cp -a lib/*.jar %{buildroot}%{_javadir}/%{name} - cp -a webapps/* %{buildroot}%{_var}/lib/%{name}/webapps + cp -a bin/*.{jar,xml} %{buildroot}%{bindir} + cp -a conf/*.{policy,properties,xml,xsd} %{buildroot}%{confdir} + cp -a lib/*.jar %{buildroot}%{libdir} + cp -a webapps/* %{buildroot}%{appdir} popd -cp -a output/dist/webapps/docs/api/* %{buildroot}%{_javadocdir}/%{name} - -sed -e "s|\@\@\@TCHOME\@\@\@|%{_datadir}/%{name}|g" \ - -e "s|\@\@\@TCTEMP\@\@\@|%{_var}/cache/%{name}/temp|g" \ +sed -e "s|\@\@\@TCHOME\@\@\@|%{homedir}|g" \ + -e "s|\@\@\@TCTEMP\@\@\@|%{tempdir}|g" \ -e "s|\@\@\@LIBDIR\@\@\@|%{_libdir}|g" %{SOURCE1} \ - > %{buildroot}%{_sysconfdir}/%{name}/%{name}.conf -sed -e "s|\@\@\@TCHOME\@\@\@|%{_datadir}/%{name}|g" \ - -e "s|\@\@\@TCTEMP\@\@\@|%{_var}/cache/%{name}/temp|g" \ + > %{buildroot}%{confdir}/%{name}.conf +sed -e "s|\@\@\@TCHOME\@\@\@|%{homedir}|g" \ + -e "s|\@\@\@TCTEMP\@\@\@|%{tempdir}|g" \ -e "s|\@\@\@LIBDIR\@\@\@|%{_libdir}|g" %{SOURCE3} \ > %{buildroot}%{_sysconfdir}/sysconfig/%{name} -install -m 0644 %{SOURCE4} %{buildroot}%{_sbindir}/%{name} -install -m 0644 %{SOURCE11} %{buildroot}%{_unitdir}/%{name}.service -install -m 0644 %{SOURCE20} %{buildroot}%{_unitdir}/%{name}-jsvc.service -sed -e "s|\@\@\@TCLOG\@\@\@|%{_var}/log/%{name}|g" %{SOURCE5} > %{buildroot}%{_sysconfdir}/logrotate.d/%{name} -sed -e "s|\@\@\@TCHOME\@\@\@|%{_datadir}/%{name}|g" \ - -e "s|\@\@\@TCTEMP\@\@\@|%{_var}/cache/%{name}/temp|g" \ +install -m 0644 %{SOURCE4} \ + %{buildroot}%{_sbindir}/%{name} +install -m 0644 %{SOURCE11} \ + %{buildroot}%{_unitdir}/%{name}.service +install -m 0644 %{SOURCE20} \ + %{buildroot}%{_unitdir}/%{name}-jsvc.service +sed -e "s|\@\@\@TCLOG\@\@\@|%{logdir}|g" %{SOURCE5} \ + > %{buildroot}%{_sysconfdir}/logrotate.d/%{name} +sed -e "s|\@\@\@TCHOME\@\@\@|%{homedir}|g" \ + -e "s|\@\@\@TCTEMP\@\@\@|%{tempdir}|g" \ -e "s|\@\@\@LIBDIR\@\@\@|%{_libdir}|g" %{SOURCE6} \ > %{buildroot}%{_bindir}/%{name}-digest -sed -e "s|\@\@\@TCHOME\@\@\@|%{_datadir}/%{name}|g" \ - -e "s|\@\@\@TCTEMP\@\@\@|%{_var}/cache/%{name}/temp|g" \ +sed -e "s|\@\@\@TCHOME\@\@\@|%{homedir}|g" \ + -e "s|\@\@\@TCTEMP\@\@\@|%{tempdir}|g" \ -e "s|\@\@\@LIBDIR\@\@\@|%{_libdir}|g" %{SOURCE7} \ > %{buildroot}%{_bindir}/%{name}-tool-wrapper @@ -304,6 +229,7 @@ install -m 0644 %{SOURCE21} %{buildroot}%{_libexecdir}/%{name}/functions install -m 0755 %{SOURCE30} %{buildroot}%{_libexecdir}/%{name}/preamble install -m 0755 %{SOURCE31} %{buildroot}%{_libexecdir}/%{name}/server install -m 0644 %{SOURCE32} %{buildroot}%{_unitdir}/%{name}@.service +install -m 0644 %{SOURCE33} %{buildroot}%{confdir}/conf.d/ sed -i \ "s,el-api.jar,%{name}-el-%{elspec}-api.jar,; @@ -321,52 +247,29 @@ pushd %{buildroot}%{_javadir} popd pushd output/build - %{_bindir}/build-jar-repository lib apache-commons-collections apache-commons-dbcp apache-commons-pool ecj 2>&1 - %{_bindir}/build-jar-repository -p webapps/examples/WEB-INF/lib \ - tomcat-taglibs-standard/taglibs-standard-impl.jar tomcat-taglibs-standard/taglibs-standard-compat.jar 2>&1 + %{_bindir}/build-jar-repository lib ecj 2>&1 popd -pushd %{buildroot}%{_javadir}/%{name} +pushd %{buildroot}%{libdir} ln -s ../../java/%{name}-jsp-%{jspspec}-api.jar . ln -s ../../java/%{name}-servlet-%{servletspec}-api.jar . ln -s ../../java/%{name}-el-%{elspec}-api.jar . - ln -s $(build-classpath apache-commons-collections) commons-collections.jar - ln -s $(build-classpath apache-commons-dbcp) commons-dbcp.jar - ln -s $(build-classpath apache-commons-pool) commons-pool.jar ln -s $(build-classpath ecj/ecj) jasper-jdt.jar cp -a %{buildroot}%{_datadir}/%{name}/bin/tomcat-juli.jar ./ popd -pushd %{buildroot}%{_datadir}/%{name} - ln -s %{_var}/lib/%{name}/webapps webapps - ln -s %{_sysconfdir}/%{name} conf - ln -s %{_javadir}/%{name} lib - ln -s %{_var}/log/%{name} logs - ln -s %{_var}/cache/%{name}/temp temp - ln -s %{_var}/cache/%{name}/work work -popd - -mkdir -p %{buildroot}%{_var}/lib/%{name}/webapps/sample -pushd %{buildroot}%{_var}/lib/%{name}/webapps/sample -%{jar} xf %{buildroot}%{_var}/lib/%{name}/webapps/docs/appdev/sample/sample.war -popd -rm %{buildroot}%{_var}/lib/%{name}/webapps/docs/appdev/sample/sample.war - -mkdir -p %{buildroot}%{_var}/lib/%{name}/webapps/examples/META-INF -pushd %{buildroot}%{_var}/lib/%{name}/webapps/examples/META-INF -echo '' > context.xml -echo '' >> context.xml -echo ' ' >> context.xml -echo '' >> context.xml -popd - -pushd %{buildroot}%{_var}/lib/%{name}/webapps/examples/WEB-INF/lib -ln -s -f $(build-classpath tomcat-taglibs-standard/taglibs-standard-impl) jstl.jar -ln -s -f $(build-classpath tomcat-taglibs-standard/taglibs-standard-compat) standard.jar +# symlink to the FHS locations where we've installed things +pushd %{buildroot}%{homedir} + ln -s %{appdir} webapps + ln -s %{confdir} conf + ln -s %{libdir} lib + ln -s %{logdir} logs + ln -s %{tempdir} temp + ln -s %{workdir} work popd install -d -m 0755 %{buildroot}%{_mavenpomdir} -pushd output/dist/src/res/maven +pushd res/maven for pom in *.pom; do sed -i 's/@MAVEN.DEPLOY.VERSION@/%{version}/g' $pom done @@ -407,17 +310,26 @@ cp -a tomcat-jaspic-api.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-jaspic-api.p %add_maven_depmap JPP.%{name}-jaspic-api.pom %{name}/jaspic-api.jar %pre -%{_sbindir}/groupadd -g %{tcuid} -r tomcat 2>/dev/null || : -%{_sbindir}/useradd -c "Apache Tomcat" -u %{tcuid} -g tomcat -s /sbin/nologin -r -d %{_datadir}/%{name} tomcat 2>/dev/null || : +# add the tomcat user and group +getent group tomcat >/dev/null || %{_sbindir}/groupadd -f -g %{tcuid} -r tomcat +if ! getent passwd tomcat >/dev/null ; then + if ! getent passwd %{tcuid} >/dev/null ; then + %{_sbindir}/useradd -r -u %{tcuid} -g tomcat -d %{homedir} -s /sbin/nologin -c "Apache Tomcat" tomcat + # Tomcat uses a reserved ID, so there should never be an else + fi +fi +exit 0 %post +# install but don't activate %systemd_post %{name}.service %{_sbindir}/update-alternatives --install %{_javadir}/servlet.jar servlet %{_javadir}/%{name}-servlet-%{servletspec}-api.jar 30000 %{_sbindir}/update-alternatives --install %{_javadir}/elspec.jar elspec %{_javadir}/%{name}-el-%{elspec}-api.jar 20300 %{_sbindir}/update-alternatives --install %{_javadir}/jsp.jar jsp %{_javadir}/%{name}-jsp-%{jspspec}-api.jar 20200 %preun -rm -rf %{_var}/cache/%{name}/work/* %{_var}/cache/%{name}/temp/* +# clean tempdir and workdir on removal or upgrade +%{__rm} -rf %{workdir}/* %{tempdir}/* %systemd_preun %{name}.service %postun @@ -428,23 +340,8 @@ if [ "$1" = "0" ]; then %{_sbindir}/update-alternatives --remove jsp %{_javadir}/%{name}-jsp-%{jspspec}-api.jar fi -%triggerun -- tomcat < 0:7.0.22-2 -/usr/bin/systemd-sysv-convert -- save tomcat > /dev/null 2>&1 || : -/sbin/chkconfig --del tomcat > /dev/null 2>&1 || : -/bin/systemctl try-restart tomcat.service > /dev/null 2>&1 || : %files -%doc LICENSE -%{_javadir}/%{name}-servlet-%{servletspec}*.jar -%dir %{_javadir}/%{name} -%{_javadir}/%{name}/*.jar -%{_javadir}/*.jar -%{_datadir}/%{name}/bin/tomcat-juli.jar -%{_mavenpomdir}/JPP*%{name}-*.pom -%{_datadir}/maven-metadata/*.xml -%{_javadir}/%{name}-el-%{elspec}-api.jar -%{_javadir}/%{name}/%{name}-el-%{elspec}-api.jar -%{_javadir}/%{name}-jsp-%{jspspec}*.jar %defattr(0664,root,tomcat,0755) %doc {LICENSE,NOTICE,RELEASE*} %attr(0755,root,root) %{_bindir}/%{name}-digest @@ -458,46 +355,57 @@ fi %attr(0755,root,root) %{_libexecdir}/%{name}/preamble %attr(0755,root,root) %{_libexecdir}/%{name}/server %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/sysconfig/%{name} -%attr(0755,root,tomcat) %dir %{_var}/lib/%{name} -%attr(0755,root,tomcat) %dir %{_sysconfdir}/%{name} +%attr(0755,root,tomcat) %dir %{basedir} +%attr(0755,root,tomcat) %dir %{confdir} + %defattr(0664,tomcat,root,0770) -%attr(0770,tomcat,root) %dir %{_var}/log/%{name} +%attr(0770,tomcat,root) %dir %{logdir} + %defattr(0664,root,tomcat,0770) -%attr(0770,root,tomcat) %dir %{_var}/cache/%{name} -%attr(0770,root,tomcat) %dir %{_var}/cache/%{name}/temp -%attr(0770,root,tomcat) %dir %{_var}/cache/%{name}/work +%attr(0770,root,tomcat) %dir %{cachedir} +%attr(0770,root,tomcat) %dir %{tempdir} +%attr(0770,root,tomcat) %dir %{workdir} + %defattr(0644,root,tomcat,0775) -%attr(0775,root,tomcat) %dir %{_var}/lib/%{name}/webapps -%attr(0775,root,tomcat) %dir %{_sysconfdir}/%{name}/Catalina -%attr(0775,root,tomcat) %dir %{_sysconfdir}/%{name}/Catalina/localhost -%attr(0755,root,tomcat) %dir %{_sysconfdir}/%{name}/conf.d -%{_sysconfdir}/%{name}/conf.d/README -%config(noreplace) %{_sysconfdir}/%{name}/%{name}.conf -%config(noreplace) %{_sysconfdir}/%{name}/*.policy -%config(noreplace) %{_sysconfdir}/%{name}/*.properties -%config(noreplace) %{_sysconfdir}/%{name}/context.xml -%config(noreplace) %{_sysconfdir}/%{name}/server.xml -%attr(0640,root,tomcat) %config(noreplace) %{_sysconfdir}/%{name}/tomcat-users.xml -%attr(0664,root,tomcat) %{_sysconfdir}/%{name}/tomcat-users.xsd -%attr(0664,root,tomcat) %config(noreplace) %{_sysconfdir}/%{name}/jaspic-providers.xml -%attr(0664,root,tomcat) %{_sysconfdir}/%{name}/jaspic-providers.xsd -%config(noreplace) %{_sysconfdir}/%{name}/web.xml -%dir %{_datadir}/%{name} -%{_datadir}/%{name}/bin/bootstrap.jar -%{_datadir}/%{name}/bin/catalina-tasks.xml -%{_datadir}/%{name}/lib -%{_datadir}/%{name}/temp -%{_datadir}/%{name}/webapps -%{_datadir}/%{name}/work -%{_datadir}/%{name}/logs -%{_datadir}/%{name}/conf +%attr(0775,root,tomcat) %dir %{appdir} +%attr(0775,root,tomcat) %dir %{confdir}/Catalina +%attr(0775,root,tomcat) %dir %{confdir}/Catalina/localhost +%attr(0755,root,tomcat) %dir %{confdir}/conf.d +%{confdir}/conf.d/README +%{confdir}/conf.d/java-9-start-up-parameters.conf +%config(noreplace) %{confdir}/%{name}.conf +%config(noreplace) %{confdir}/*.policy +%config(noreplace) %{confdir}/*.properties +%config(noreplace) %{confdir}/context.xml +%config(noreplace) %{confdir}/server.xml +%attr(0640,root,tomcat) %config(noreplace) %{confdir}/tomcat-users.xml +%attr(0664,root,tomcat) %{confdir}/tomcat-users.xsd +%attr(0664,root,tomcat) %config(noreplace) %{confdir}/jaspic-providers.xml +%attr(0664,root,tomcat) %{confdir}/jaspic-providers.xsd +%config(noreplace) %{confdir}/web.xml + +%dir %{homedir} +%{bindir}/catalina-tasks.xml +%{homedir}/lib +%{homedir}/temp +%{homedir}/webapps +%{homedir}/work +%{homedir}/logs +%{homedir}/conf + %defattr(0664,root,tomcat,0755) -%{_var}/lib/%{name}/webapps/host-manager -%{_var}/lib/%{name}/webapps/manager +%{appdir}/host-manager +%{appdir}/manager %defattr(0644,tomcat,tomcat,0755) -%{_var}/lib/%{name}/webapps/ROOT -%{_var}/lib/%{name}/webapps/examples -%{_var}/lib/%{name}/webapps/sample +%{appdir}/ROOT + +%dir %{libdir} +%{libdir}/*.jar +%{_javadir}/*.jar +%{bindir}/tomcat-juli.jar +%{bindir}/bootstrap.jar +%{_mavenpomdir}/JPP*%{name}-*.pom +%{_datadir}/maven-metadata/*.xml %files jsvc %defattr(755,root,root,0755) @@ -506,10 +414,14 @@ fi %attr(0660,tomcat,tomcat) %verify(not size md5 mtime) %{_var}/log/%{name}/catalina.out %files help -%{_var}/lib/%{name}/webapps/docs -%{_javadocdir}/%{name} +%{appdir}/docs %changelog +* Thu Nov 07 2024 chenyaqiang - 1:9.0.96-1 +- Update to 9.0.96 +- Fix CVE-2021-43980 CVE-2022-25762 CVE-2023-44487 CVE-2023-46589 + CVE-2024-23672 CVE-2024-24549 CVE-2024-34750 + * Tue Jan 23 2024 wangkai <13474090681@163.com> - 1:9.0.10-33 - Fix CVE-2024-21733,CVE-2023-24998,CVE-2023-28709,CVE-2023-42795