diff --git a/CVE-2018-11784.patch b/CVE-2018-11784.patch new file mode 100644 index 0000000..4bf1bb2 --- /dev/null +++ b/CVE-2018-11784.patch @@ -0,0 +1,27 @@ +--- 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 new file mode 100644 index 0000000..d05be52 --- /dev/null +++ b/CVE-2019-0199-1.patch @@ -0,0 +1,75 @@ +--- 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 new file mode 100644 index 0000000..fef53b2 --- /dev/null +++ b/CVE-2019-0199-10.patch @@ -0,0 +1,13 @@ +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 new file mode 100644 index 0000000..33e7526 --- /dev/null +++ b/CVE-2019-0199-11.patch @@ -0,0 +1,21 @@ +--- 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 new file mode 100644 index 0000000..c1c1fda --- /dev/null +++ b/CVE-2019-0199-2.patch @@ -0,0 +1,246 @@ +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 new file mode 100644 index 0000000..0494f3b --- /dev/null +++ b/CVE-2019-0199-3.patch @@ -0,0 +1,202 @@ +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 new file mode 100644 index 0000000..78e7858 --- /dev/null +++ b/CVE-2019-0199-4.patch @@ -0,0 +1,38 @@ +--- 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 new file mode 100644 index 0000000..a21d1a3 --- /dev/null +++ b/CVE-2019-0199-5.patch @@ -0,0 +1,143 @@ +--- 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 new file mode 100644 index 0000000..ef1ed8d --- /dev/null +++ b/CVE-2019-0199-6.patch @@ -0,0 +1,51 @@ +--- 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 new file mode 100644 index 0000000..0369108 --- /dev/null +++ b/CVE-2019-0199-7.patch @@ -0,0 +1,32 @@ +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 new file mode 100644 index 0000000..f921ed2 --- /dev/null +++ b/CVE-2019-0199-8.patch @@ -0,0 +1,24 @@ +--- 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 new file mode 100644 index 0000000..78c22a1 --- /dev/null +++ b/CVE-2019-0199-9.patch @@ -0,0 +1,24 @@ +--- 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 new file mode 100644 index 0000000..cc2c366 --- /dev/null +++ b/CVE-2019-0221.patch @@ -0,0 +1,44 @@ +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 new file mode 100644 index 0000000..93ea148 --- /dev/null +++ b/CVE-2019-10072-1.patch @@ -0,0 +1,129 @@ +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 new file mode 100644 index 0000000..4619c59 --- /dev/null +++ b/CVE-2019-10072-2.patch @@ -0,0 +1,28 @@ +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/apache-tomcat-9.0.10-src.tar.gz b/apache-tomcat-9.0.10-src.tar.gz new file mode 100644 index 0000000..017333d Binary files /dev/null and b/apache-tomcat-9.0.10-src.tar.gz differ diff --git a/el-api-OSGi-MANIFEST.MF b/el-api-OSGi-MANIFEST.MF new file mode 100644 index 0000000..69b797f --- /dev/null +++ b/el-api-OSGi-MANIFEST.MF @@ -0,0 +1,13 @@ +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 new file mode 100644 index 0000000..ad34978 --- /dev/null +++ b/jasper-OSGi-MANIFEST.MF @@ -0,0 +1,40 @@ +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 new file mode 100644 index 0000000..14e4282 --- /dev/null +++ b/jasper-el-OSGi-MANIFEST.MF @@ -0,0 +1,13 @@ +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/jsp-api-OSGi-MANIFEST.MF b/jsp-api-OSGi-MANIFEST.MF new file mode 100644 index 0000000..62bc00d --- /dev/null +++ b/jsp-api-OSGi-MANIFEST.MF @@ -0,0 +1,13 @@ +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/servlet-api-OSGi-MANIFEST.MF b/servlet-api-OSGi-MANIFEST.MF new file mode 100644 index 0000000..3938935 --- /dev/null +++ b/servlet-api-OSGi-MANIFEST.MF @@ -0,0 +1,17 @@ +Manifest-Version: 1.0 +Bundle-RequiredExecutionEnvironment: CDC-1.1/Foundation-1.1,J2SE-1.4 +Bundle-SymbolicName: javax.servlet +Bundle-ManifestVersion: 2 +Bundle-Name: %bundleName +Bundle-Localization: plugin +Bundle-Version: 3.0.0 +Bundle-Vendor: %bundleProvider +Export-Package: javax.servlet;version="3.0", + javax.servlet;version="2.6", + javax.servlet.http;version="3.0", + javax.servlet.http;version="2.6", + javax.servlet.annotation;version="2.6", + javax.servlet.descriptor;version="3.0", + javax.servlet.descriptor;version="2.6", + javax.servlet.resources;version="3.0", + javax.servlet.resources;version="2.6" diff --git a/tomcat-9.0-bootstrap-MANIFEST.MF.patch b/tomcat-9.0-bootstrap-MANIFEST.MF.patch new file mode 100644 index 0000000..81ee283 --- /dev/null +++ b/tomcat-9.0-bootstrap-MANIFEST.MF.patch @@ -0,0 +1,9 @@ +--- tomcat/res/META-INF/bootstrap.jar.manifest.orig 2010-04-06 10:11:09.000000000 -0600 ++++ tomcat/res/META-INF/bootstrap.jar.manifest 2010-04-06 10:45:56.000000000 -0600 +@@ -1,6 +1,5 @@ + Manifest-Version: 1.0 + Main-Class: org.apache.catalina.startup.Bootstrap +-Class-Path: commons-daemon.jar + Specification-Title: Apache Tomcat Bootstrap + Specification-Version: @VERSION_MAJOR_MINOR@ + Specification-Vendor: Apache Software Foundation diff --git a/tomcat-9.0-digest.script b/tomcat-9.0-digest.script new file mode 100644 index 0000000..ce4aa0f --- /dev/null +++ b/tomcat-9.0-digest.script @@ -0,0 +1,45 @@ +#!/bin/sh +# +# tomcat-digest script +# JPackage Project + +# Source functions library +if [ -f /usr/share/java-utils/java-functions ] ; then + . /usr/share/java-utils/java-functions +else + echo "Can't find functions library, aborting" + exit 1 +fi + +# Get the tomcat config (use this for environment specific settings) +if [ -z "${TOMCAT_CFG}" ]; then + TOMCAT_CFG="/etc/tomcat/tomcat.conf" +fi + +if [ -r "$TOMCAT_CFG" ]; then + . $TOMCAT_CFG +fi + +set_javacmd + +# CLASSPATH munging +if [ -n "$JSSE_HOME" ]; then + CLASSPATH="${CLASSPATH}:$(build-classpath jcert jnet jsse 2>/dev/null)" +fi +CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/bin/bootstrap.jar" +CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/bin/tomcat-juli.jar" +export CLASSPATH + +# Configuration +MAIN_CLASS="org.apache.catalina.startup.Tool" +BASE_FLAGS="-Dcatalina.home=\"$CATALINA_HOME\"" +BASE_OPTIONS="" +BASE_JARS="commons-daemon tomcat/catalina servlet tomcat/tomcat-util tomcat/tomcat-coyote tomcat/tomcat-api tomcat/tomcat-util-scan" + +# Set parameters +set_classpath $BASE_JARS +set_flags $BASE_FLAGS +set_options $BASE_OPTIONS + +# Let's start +run -server org.apache.catalina.realm.RealmBase "$@" diff --git a/tomcat-9.0-jsvc.service b/tomcat-9.0-jsvc.service new file mode 100644 index 0000000..f480324 --- /dev/null +++ b/tomcat-9.0-jsvc.service @@ -0,0 +1,22 @@ +# Systemd unit file for tomcat +# +# To create clones of this service: +# 1) By default SERVICE_NAME=tomcat. When cloned, the value must be defined +# before tomcat-sysd is called. +# 2) Create /etc/sysconfig/${SERVICE_NAME} from /etc/sysconfig/tomcat +# to override tomcat defaults + +[Unit] +Description=Apache Tomcat Web Application Container JSVC wrapper +After=syslog.target network.target + +[Service] +Type=simple +EnvironmentFile=/etc/tomcat/tomcat.conf +Environment="NAME=" "USE_JSVC=true" +EnvironmentFile=-/etc/sysconfig/tomcat +ExecStart=/usr/libexec/tomcat/server start +ExecStop=/usr/libexec/tomcat/server stop + +[Install] +WantedBy=multi-user.target diff --git a/tomcat-9.0-tomcat-users-webapp.patch b/tomcat-9.0-tomcat-users-webapp.patch new file mode 100644 index 0000000..107040e --- /dev/null +++ b/tomcat-9.0-tomcat-users-webapp.patch @@ -0,0 +1,17 @@ +--- tomcat/conf/tomcat-users.xml~ 2008-01-28 17:41:06.000000000 -0500 ++++ tomcat/conf/tomcat-users.xml 2008-03-07 19:40:07.000000000 -0500 +@@ -23,4 +23,14 @@ + + + --> ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + diff --git a/tomcat-9.0-tool-wrapper.script b/tomcat-9.0-tool-wrapper.script new file mode 100644 index 0000000..949d46d --- /dev/null +++ b/tomcat-9.0-tool-wrapper.script @@ -0,0 +1,45 @@ +#!/bin/sh +# +# tomcat-digest script +# JPackage Project + +# Source functions library +if [ -f /usr/share/java-utils/java-functions ] ; then + . /usr/share/java-utils/java-functions +else + echo "Can't find functions library, aborting" + exit 1 +fi + +# Get the tomcat config (use this for environment specific settings) +if [ -z "${TOMCAT_CFG}" ]; then + TOMCAT_CFG="/etc/tomcat/tomcat.conf" +fi + +if [ -r "$TOMCAT_CFG" ]; then + . $TOMCAT_CFG +fi + +set_javacmd + +# CLASSPATH munging +if [ -n "$JSSE_HOME" ]; then + CLASSPATH="${CLASSPATH}:$(build-classpath jcert jnet jsse 2>/dev/null)" +fi +CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/bin/bootstrap.jar" +CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/bin/tomcat-juli.jar" +export CLASSPATH + +# Configuration +MAIN_CLASS="org.apache.catalina.startup.Tool" +BASE_OPTIONS="" +BASE_FLAGS="-Dcatalina.home=\"$CATALINA_HOME\"" +BASE_JARS="commons-daemon tomcat/catalina servlet tomcat/tomcat-util tomcat/tomcat-coyote tomcat/tomcat-api tomcat/tomcat-util-scan" + +# Set parameters +set_classpath $BASE_JARS +set_flags $BASE_FLAGS +set_options $BASE_OPTIONS + +# Let's start +run "$@" diff --git a/tomcat-9.0.conf b/tomcat-9.0.conf new file mode 100644 index 0000000..3f43006 --- /dev/null +++ b/tomcat-9.0.conf @@ -0,0 +1,52 @@ +# System-wide configuration file for tomcat services +# This will be loaded by systemd as an environment file, +# so please keep the syntax. For shell expansion support +# place your custom files as /etc/tomcat/conf.d/*.conf +# +# There are 2 "classes" of startup behavior in this package. +# The old one, the default service named tomcat.service. +# The new named instances are called tomcat@instance.service. +# +# Use this file to change default values for all services. +# Change the service specific ones to affect only one service. +# For tomcat.service it's /etc/sysconfig/tomcat, for +# tomcat@instance it's /etc/sysconfig/tomcat@instance. + +# This variable is used to figure out if config is loaded or not. +TOMCAT_CFG_LOADED="1" + +# In new-style instances, if CATALINA_BASE isn't specified, it will +# be constructed by joining TOMCATS_BASE and NAME. +TOMCATS_BASE="/var/lib/tomcats/" + +# Where your java installation lives +JAVA_HOME="/usr/lib/jvm/jre" + +# Where your tomcat installation lives +CATALINA_HOME="@@@TCHOME@@@" + +# System-wide tmp +CATALINA_TMPDIR="/var/cache/tomcat/temp" + +# You can pass some parameters to java here if you wish to +#JAVA_OPTS="-Xminf0.1 -Xmaxf0.3" + +# Use JAVA_OPTS to set java.library.path for libtcnative.so +#JAVA_OPTS="-Djava.library.path=/usr/lib" + +# Set default javax.sql.DataSource factory to apache commons one. See rhbz#1214381 +JAVA_OPTS="-Djavax.sql.DataSource.Factory=org.apache.commons.dbcp.BasicDataSourceFactory" + +# You can change your tomcat locale here +#LANG="en_US" + +# 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" + +# If you wish to further customize your tomcat environment, +# put your own definitions here +# (i.e. LD_LIBRARY_PATH for some jdbc drivers) diff --git a/tomcat-9.0.logrotate b/tomcat-9.0.logrotate new file mode 100644 index 0000000..a87b4c0 --- /dev/null +++ b/tomcat-9.0.logrotate @@ -0,0 +1,8 @@ +@@@TCLOG@@@/catalina.out { + copytruncate + weekly + rotate 52 + compress + missingok + create 0644 tomcat tomcat +} diff --git a/tomcat-9.0.service b/tomcat-9.0.service new file mode 100644 index 0000000..2b20aa0 --- /dev/null +++ b/tomcat-9.0.service @@ -0,0 +1,22 @@ +# Systemd unit file for default tomcat +# +# To create clones of this service: +# DO NOTHING, use tomcat@.service instead. + +[Unit] +Description=Apache Tomcat Web Application Container +After=syslog.target network.target + +[Service] +Type=simple +EnvironmentFile=/etc/tomcat/tomcat.conf +Environment="NAME=" +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-9.0.sysconfig b/tomcat-9.0.sysconfig new file mode 100644 index 0000000..3117bf7 --- /dev/null +++ b/tomcat-9.0.sysconfig @@ -0,0 +1,11 @@ +# Service-specific configuration file for tomcat. This will be sourced by +# systemd for the default service (tomcat.service) +# If you want to customize named instance, make a similar file +# and name it tomcat@instancename. + +# You will not need to set this, usually. For default service it equals +# CATALINA_HOME. For named service, it equals ${TOMCATS_BASE}${NAME} +#CATALINA_BASE="@@@TCHOME@@@" + +# Please take a look at /etc/tomcat/tomcat.conf to have an idea what you +# can override. diff --git a/tomcat-9.0.wrapper b/tomcat-9.0.wrapper new file mode 100644 index 0000000..c97cb85 --- /dev/null +++ b/tomcat-9.0.wrapper @@ -0,0 +1,24 @@ +#!/bin/bash + +if [ "$1" = "version" ]; then + . /usr/libexec/tomcat/preamble + exec ${JAVACMD} -classpath ${CATALINA_HOME}/lib/catalina.jar \ + org.apache.catalina.util.ServerInfo +fi + +SRV="tomcat" +if [ -n "$2" ]; then + SRV="tomcat@$2" +fi + +if [ "$1" = "start" ]; then + systemctl start ${SRV}.service +elif [ "$1" = "stop" ]; then + systemctl stop ${SRV}.service +elif [ "$1" = "version" ]; then + ${JAVACMD} -classpath ${CATALINA_HOME}/lib/catalina.jar \ + org.apache.catalina.util.ServerInfo +else + echo "Usage: $0 {start|stop|version} [server-id]" + exit 1 +fi diff --git a/tomcat-api-OSGi-MANIFEST.MF b/tomcat-api-OSGi-MANIFEST.MF new file mode 100644 index 0000000..85b12b8 --- /dev/null +++ b/tomcat-api-OSGi-MANIFEST.MF @@ -0,0 +1,12 @@ +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 new file mode 100644 index 0000000..cf39361 --- /dev/null +++ b/tomcat-build.patch @@ -0,0 +1,12 @@ +--- 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 + + + ++ ++ ++ + + + diff --git a/tomcat-functions b/tomcat-functions new file mode 100644 index 0000000..ab08fa2 --- /dev/null +++ b/tomcat-functions @@ -0,0 +1,42 @@ +#!/bin/bash + +if [ -r /usr/share/java-utils/java-functions ]; then + . /usr/share/java-utils/java-functions +else + echo "Can't read Java functions library, aborting" + exit 1 +fi + +_save_function() { + local ORIG_FUNC=$(declare -f $1) + local NEWNAME_FUNC="$2${ORIG_FUNC#$1}" + eval "$NEWNAME_FUNC" +} + +run_jsvc(){ + if [ -x /usr/bin/jsvc ]; then + TOMCAT_USER="${TOMCAT_USER:-tomcat}" + JSVC="/usr/bin/jsvc" + + JSVC_OPTS="-nodetach -pidfile /var/run/jsvc-tomcat${NAME}.pid -user ${TOMCAT_USER} -outfile ${CATALINA_BASE}/logs/catalina.out -errfile ${CATALINA_BASE}/logs/catalina.out" + if [ "$1" = "stop" ]; then + JSVC_OPTS="${JSVC_OPTS} -stop" + fi + + exec "${JSVC}" ${JSVC_OPTS} ${FLAGS} -classpath "${CLASSPATH}" ${OPTIONS} "${MAIN_CLASS}" "${@}" + else + echo "Can't find /usr/bin/jsvc executable" + fi + +} + +_save_function run run_java + +run() { + if [ "${USE_JSVC}" = "true" ] ; then + run_jsvc $@ + else + run_java $@ + fi +} + diff --git a/tomcat-juli-OSGi-MANIFEST.MF b/tomcat-juli-OSGi-MANIFEST.MF new file mode 100644 index 0000000..b856d9f --- /dev/null +++ b/tomcat-juli-OSGi-MANIFEST.MF @@ -0,0 +1,13 @@ +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 new file mode 100644 index 0000000..9bbcb17 --- /dev/null +++ b/tomcat-named.service @@ -0,0 +1,26 @@ +# Systemd unit file for tomcat instances. +# +# To create clones of this service: +# 0. systemctl enable tomcat@name.service +# 1. create catalina.base directory structure in +# /var/lib/tomcats/name +# 2. profit. + +[Unit] +Description=Apache Tomcat Web Application Container +After=syslog.target network.target + +[Service] +Type=simple +EnvironmentFile=/etc/tomcat/tomcat.conf +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-preamble b/tomcat-preamble new file mode 100644 index 0000000..1271dca --- /dev/null +++ b/tomcat-preamble @@ -0,0 +1,52 @@ +#!/bin/bash + +. /usr/libexec/tomcat/functions + +# Get the tomcat config (use this for environment specific settings) + +if [ -z "${TOMCAT_CFG_LOADED}" ]; then + if [ -z "${TOMCAT_CFG}" ]; then + TOMCAT_CFG="/etc/tomcat/tomcat.conf" + fi + . $TOMCAT_CFG +fi + +if [ -d "${TOMCAT_CONFD=/etc/tomcat/conf.d}" ]; then + for file in ${TOMCAT_CONFD}/*.conf ; do + if [ -f "$file" ] ; then + . "$file" + fi + done +fi + +if [ -z "$CATALINA_BASE" ]; then + if [ -n "$NAME" ]; then + if [ -z "$TOMCATS_BASE" ]; then + TOMCATS_BASE="/var/lib/tomcats/" + fi + CATALINA_BASE="${TOMCATS_BASE}${NAME}" + else + CATALINA_BASE="${CATALINA_HOME}" + fi +fi +VERBOSE=1 +set_javacmd +cd ${CATALINA_HOME} +# CLASSPATH munging +if [ ! -z "$CLASSPATH" ] ; then + CLASSPATH="$CLASSPATH": +fi + +if [ -n "$JSSE_HOME" ]; then + CLASSPATH="${CLASSPATH}$(build-classpath jcert jnet jsse 2>/dev/null):" +fi +CLASSPATH="${CLASSPATH}${CATALINA_HOME}/bin/bootstrap.jar" +CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/bin/tomcat-juli.jar" +CLASSPATH="${CLASSPATH}:$(build-classpath commons-daemon 2>/dev/null)" + +if [ -z "$LOGGING_PROPERTIES" ] ; then + LOGGING_PROPERTIES="${CATALINA_BASE}/conf/logging.properties" + if [ ! -f "${LOGGING_PROPERTIES}" ] ; then + LOGGING_PROPERTIES="${CATALINA_HOME}/conf/logging.properties" + fi +fi diff --git a/tomcat-server b/tomcat-server new file mode 100644 index 0000000..17ae385 --- /dev/null +++ b/tomcat-server @@ -0,0 +1,25 @@ +#!/bin/bash + +. /usr/libexec/tomcat/preamble + +MAIN_CLASS=org.apache.catalina.startup.Bootstrap + +FLAGS="$JAVA_OPTS" +OPTIONS="-Dcatalina.base=$CATALINA_BASE \ +-Dcatalina.home=$CATALINA_HOME \ +-Djava.endorsed.dirs=$JAVA_ENDORSED_DIRS \ +-Djava.io.tmpdir=$CATALINA_TMPDIR \ +-Djava.util.logging.config.file=${LOGGING_PROPERTIES} \ +-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" + +if [ "$1" = "start" ] ; then + FLAGS="${FLAGS} $CATALINA_OPTS" + if [ "${SECURITY_MANAGER}" = "true" ] ; then + OPTIONS="${OPTIONS} \ + -Djava.security.manager \ + -Djava.security.policy==${CATALINA_BASE}/conf/catalina.policy" + fi + run start +elif [ "$1" = "stop" ] ; then + run stop +fi diff --git a/tomcat.spec b/tomcat.spec new file mode 100644 index 0000000..bd0b3c9 --- /dev/null +++ b/tomcat.spec @@ -0,0 +1,463 @@ +%global jspspec 2.3 +%global major_version 9 +%global minor_version 0 +%global micro_version 10 +%global packdname apache-tomcat-%{version}-src +%global servletspec 4.0 +%global elspec 3.0 +%global tcuid 91 + +%{!?_mavendepmapfragdir: %global _mavendepmapfragdir /usr/share/maven-metadata} +%{?fc24: %global _mavendepmapfragdir /usr/share/maven-metadata} + +Name: tomcat +Epoch: 1 +Version: %{major_version}.%{minor_version}.%{micro_version} +Release: 11 +Summary: Implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies +License: ASL 2.0 +URL: http://tomcat.apache.org/ + +Source0: https://github.com/apache/tomcat/archive/%{version}.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 + +Patch0: %{name}-%{major_version}.%{minor_version}-bootstrap-MANIFEST.MF.patch +Patch1: %{name}-%{major_version}.%{minor_version}-tomcat-users-webapp.patch +Patch2: %{name}-build.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 + +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 + +Requires: procps jpackage-utils java-headless >= 1:1.8.0 apache-commons-daemon +Requires: tomcat-taglibs-standard >= 0:1.1 + +Recommends: tomcat-native >= 1.2.14 + +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 + +Provides: %{name}-log4j = %{epoch}:%{version}-%{release} +Provides: servlet = %{servletspec} servlet6 servlet3 el_api = %{elspec} jsp = %{jspspec} +Obsoletes: %{name}-el-2.2-api %{name}-servlet-3.1-api %{name}-jsp-2.2-api + +Provides: %{name}-lib = %{epoch}:%{version}-%{release} +Provides: %{name}-servlet-%{servletspec}-api = %{epoch}:%{version}-%{release} +Provides: %{name}-el-%{elspec}-api = %{epoch}:%{version}-%{release} +Provides: %{name}-jsp-%{jspspec}-api = %{epoch}:%{version}-%{release} +Provides: %{name}-webapps = %{epoch}:%{version}-%{release} +Provides: %{name}-admin-webapps = %{epoch}:%{version}-%{release} + +Obsoletes: %{name}-lib < %{epoch}:%{version}-%{release} +Obsoletes: %{name}-servlet-%{servletspec}-api < %{epoch}:%{version}-%{release} +Obsoletes: %{name}-el-%{elspec}-api < %{epoch}:%{version}-%{release} +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 + +%package jsvc +Summary: Apache jsvc wrapper for Apache Tomcat as separate service +Requires: %{name} = %{epoch}:%{version}-%{release} +Requires: apache-commons-daemon-jsvc + +%description jsvc +Systemd service to start tomcat with jsvc, +which allows tomcat to perform some privileged operations +(e.g. bind to a port < 1024) and then switch identity to a non-privileged user. + +%package help +Summary: Documents for %{name} +Buildarch: noarch +Requires: man info jpackage-utils +Requires: %{name} = %{epoch}:%{version}-%{release} +Provides: %{name}-docs-webapp = %{epoch}:%{version}-%{release} +Provides: %{name}-javadoc = %{epoch}:%{version}-%{release} +Obsoletes: %{name}-docs-webapp < %{epoch}:%{version}-%{release} +Obsoletes: %{name}-javadoc < %{epoch}:%{version}-%{release} + +%description help +Man pages and other related documents for %{name}. + +%prep +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 %{packdname} + +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)" \ + -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 + +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 + +%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}%{_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 +/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 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 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 +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" \ + -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" \ + -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" \ + -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" \ + -e "s|\@\@\@LIBDIR\@\@\@|%{_libdir}|g" %{SOURCE7} \ + > %{buildroot}%{_bindir}/%{name}-tool-wrapper + +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 + +sed -i \ + "s,el-api.jar,%{name}-el-%{elspec}-api.jar,; + s,servlet-api.jar,%{name}-servlet-%{servletspec}-api.jar,; + s,jsp-api.jar,%{name}-jsp-%{jspspec}-api.jar,;" \ + %{buildroot}%{_datadir}/%{name}/bin/catalina-tasks.xml + +pushd %{buildroot}%{_javadir} + mv %{name}/jsp-api.jar %{name}-jsp-%{jspspec}-api.jar + ln -s %{name}-jsp-%{jspspec}-api.jar %{name}-jsp-api.jar + mv %{name}/servlet-api.jar %{name}-servlet-%{servletspec}-api.jar + ln -s %{name}-servlet-%{servletspec}-api.jar %{name}-servlet-api.jar + mv %{name}/el-api.jar %{name}-el-%{elspec}-api.jar + ln -s %{name}-el-%{elspec}-api.jar %{name}-el-api.jar +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 +popd + +pushd %{buildroot}%{_javadir}/%{name} + 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) 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 +popd + +install -d -m 0755 %{buildroot}%{_mavenpomdir} +pushd output/dist/src/res/maven +for pom in *.pom; do + sed -i 's/@MAVEN.DEPLOY.VERSION@/%{version}/g' $pom +done + +for libname in annotations-api catalina jasper-el jasper catalina-ha; do + cp -a %{name}-$libname.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-$libname.pom + %add_maven_depmap JPP.%{name}-$libname.pom %{name}/$libname.jar -f "tomcat-lib" +done + +cp -a %{name}-util-scan.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-util-scan.pom +%add_maven_depmap JPP.%{name}-util-scan.pom %{name}/%{name}-util-scan.jar -f "tomcat-lib" +cp -a %{name}-jni.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-jni.pom +%add_maven_depmap JPP.%{name}-jni.pom %{name}/%{name}-jni.jar -f "tomcat-lib" +cp -a tomcat-jsp-api.pom %{buildroot}%{_mavenpomdir}/JPP-tomcat-jsp-api.pom +%add_maven_depmap JPP-tomcat-jsp-api.pom tomcat-jsp-api.jar -f "tomcat-jsp-api" -a "org.eclipse.jetty.orbit:javax.servlet.jsp" +cp -a tomcat-el-api.pom %{buildroot}%{_mavenpomdir}/JPP-tomcat-el-api.pom +%add_maven_depmap JPP-tomcat-el-api.pom tomcat-el-api.jar -f "tomcat-el-api" -a "org.eclipse.jetty.orbit:javax.el" +cp -a tomcat-servlet-api.pom %{buildroot}%{_mavenpomdir}/JPP-tomcat-servlet-api.pom +%add_maven_depmap JPP-tomcat-servlet-api.pom tomcat-servlet-api.jar -f "tomcat-servlet-api" +ln -s -f $(abs2rel %{_datadir}/%{name}/bin/tomcat-juli.jar %{_javadir}/%{name}) %{buildroot}%{_javadir}/%{name}/ +cp -a tomcat-tribes.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-catalina-tribes.pom +%add_maven_depmap JPP.%{name}-catalina-tribes.pom %{name}/catalina-tribes.jar +cp -a tomcat-coyote.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-tomcat-coyote.pom +%add_maven_depmap JPP.%{name}-tomcat-coyote.pom %{name}/tomcat-coyote.jar +cp -a tomcat-juli.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-tomcat-juli.pom +%add_maven_depmap JPP.%{name}-tomcat-juli.pom %{name}/tomcat-juli.jar +cp -a tomcat-api.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-tomcat-api.pom +%add_maven_depmap JPP.%{name}-tomcat-api.pom %{name}/tomcat-api.jar +cp -a tomcat-util.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-tomcat-util.pom +%add_maven_depmap JPP.%{name}-tomcat-util.pom %{name}/tomcat-util.jar +cp -a tomcat-jdbc.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-tomcat-jdbc.pom +%add_maven_depmap JPP.%{name}-tomcat-jdbc.pom %{name}/tomcat-jdbc.jar +cp -a tomcat-websocket-api.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-websocket-api.pom +%add_maven_depmap JPP.%{name}-websocket-api.pom %{name}/websocket-api.jar +cp -a tomcat-websocket.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-tomcat-websocket.pom +%add_maven_depmap JPP.%{name}-tomcat-websocket.pom %{name}/tomcat-websocket.jar +cp -a tomcat-jaspic-api.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-jaspic-api.pom +%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 || : + +%post +%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/* +%systemd_preun %{name}.service + +%postun +%systemd_postun_with_restart %{name}.service +if [ "$1" = "0" ]; then + %{_sbindir}/update-alternatives --remove servlet %{_javadir}/%{name}-servlet-%{servletspec}-api.jar + %{_sbindir}/update-alternatives --remove elspec %{_javadir}/%{name}-el-%{elspec}-api.jar + %{_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 +%attr(0755,root,root) %{_bindir}/%{name}-tool-wrapper +%attr(0755,root,root) %{_sbindir}/%{name} +%attr(0644,root,root) %{_unitdir}/%{name}.service +%attr(0644,root,root) %{_unitdir}/%{name}@.service +%attr(0755,root,root) %dir %{_libexecdir}/%{name} +%attr(0755,root,root) %dir %{_localstatedir}/lib/tomcats +%attr(0644,root,root) %{_libexecdir}/%{name}/functions +%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} +%defattr(0664,tomcat,root,0770) +%attr(0770,tomcat,root) %dir %{_var}/log/%{name} +%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 +%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 +%defattr(0664,root,tomcat,0755) +%{_var}/lib/%{name}/webapps/host-manager +%{_var}/lib/%{name}/webapps/manager +%defattr(0644,tomcat,tomcat,0755) +%{_var}/lib/%{name}/webapps/ROOT +%{_var}/lib/%{name}/webapps/examples +%{_var}/lib/%{name}/webapps/sample + +%files jsvc +%defattr(755,root,root,0755) +%attr(0644,root,root) %{_unitdir}/%{name}-jsvc.service +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/logrotate.d/%{name} +%attr(0660,tomcat,tomcat) %verify(not size md5 mtime) %{_var}/log/%{name}/catalina.out + +%files help +%{_var}/lib/%{name}/webapps/docs +%{_javadocdir}/%{name} + +%changelog +* Fri Feb 28 2020 Senlin Xia - 1:9.0.10-11 +- Package init +