diff --git a/.tomcat.metadata b/.tomcat.metadata
index 3f0cce6..0f4bcad 100644
--- a/.tomcat.metadata
+++ b/.tomcat.metadata
@@ -1 +1 @@
-df0facd5b89243fbda74c91861c29c4039b9cd7d SOURCES/apache-tomcat-7.0.40-src.tar.gz
+3f1061428dc6274e5b6159ed06462702e0550bd1 SOURCES/apache-tomcat-7.0.42-src.tar.gz
diff --git a/SOURCES/tomcat-7.0.42-CVE-2013-4286.patch b/SOURCES/tomcat-7.0.42-CVE-2013-4286.patch
new file mode 100644
index 0000000..5555cfb
--- /dev/null
+++ b/SOURCES/tomcat-7.0.42-CVE-2013-4286.patch
@@ -0,0 +1,196 @@
+--- java/org/apache/coyote/ajp/AbstractAjpProcessor.java.orig 2014-03-14 17:13:46.228345000 -0400
++++ java/org/apache/coyote/ajp/AbstractAjpProcessor.java 2014-03-18 13:54:13.570758000 -0400
+@@ -25,6 +25,8 @@
+ import java.security.cert.X509Certificate;
+ import java.util.concurrent.atomic.AtomicBoolean;
+
++import javax.servlet.http.HttpServletResponse;
++
+ import org.apache.coyote.AbstractProcessor;
+ import org.apache.coyote.ActionCode;
+ import org.apache.coyote.AsyncContextCallback;
+@@ -651,7 +653,7 @@
+
+ // Set this every time in case limit has been changed via JMX
+ headers.setLimit(endpoint.getMaxHeaderCount());
+-
++ boolean contentLengthSet = false;
+ int hCount = requestHeaderMessage.getInt();
+ for(int i = 0 ; i < hCount ; i++) {
+ String hName = null;
+@@ -686,10 +688,15 @@
+
+ if (hId == Constants.SC_REQ_CONTENT_LENGTH ||
+ (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) {
+- // just read the content-length header, so set it
+ long cl = vMB.getLong();
+- if(cl < Integer.MAX_VALUE)
+- request.setContentLength( (int)cl );
++ if (contentLengthSet) {
++ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
++ error = true;
++ } else {
++ contentLengthSet = true;
++ // Set the content-length header for the request
++ request.setContentLength((int)cl);
++ }
+ } else if (hId == Constants.SC_REQ_CONTENT_TYPE ||
+ (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) {
+ // just read the content-type header, so set it
+--- java/org/apache/coyote/http11/AbstractHttp11Processor.java.orig 2014-03-14 17:13:46.514347000 -0400
++++ java/org/apache/coyote/http11/AbstractHttp11Processor.java 2014-03-14 17:13:46.353345000 -0400
+@@ -1277,10 +1277,20 @@
+
+ // Parse content-length header
+ long contentLength = request.getContentLengthLong();
+- if (contentLength >= 0 && !contentDelimitation) {
+- getInputBuffer().addActiveFilter
+- (inputFilters[Constants.IDENTITY_FILTER]);
+- contentDelimitation = true;
++ if (contentLength >= 0) {
++ if (contentDelimitation) {
++ // contentDelimitation being true at this point indicates that
++ // chunked encoding is being used but chunked encoding should
++ // not be used with a content length. RFC 2616, section 4.4,
++ // bullet 3 states Content-Length must be ignored in this case -
++ // so remove it.
++ headers.removeHeader("content-length");
++ request.setContentLength(-1);
++ } else {
++ getInputBuffer().addActiveFilter
++ (inputFilters[Constants.IDENTITY_FILTER]);
++ contentDelimitation = true;
++ }
+ }
+
+ MessageBytes valueMB = headers.getValue("host");
+--- test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java.orig 2014-03-14 17:13:52.878367000 -0400
++++ test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java 2014-03-14 17:21:43.278956000 -0400
+@@ -90,6 +90,61 @@
+ ajpClient.disconnect();
+ }
+
++ @Test
++ public void testPost() throws Exception {
++ doTestPost(false, HttpServletResponse.SC_OK);
++ }
++
++ public void testPostMultipleContentLength() throws Exception {
++ // Multiple content lengths
++ doTestPost(true, HttpServletResponse.SC_BAD_REQUEST);
++ }
++
++
++ public void doTestPost(boolean multipleCL, int expectedStatus)
++ throws Exception {
++ Tomcat tomcat = getTomcatInstance();
++ // Use the normal Tomcat ROOT context
++ File root = new File("test/webapp-3.0");
++ tomcat.addWebapp("", root.getAbsolutePath());
++ tomcat.start();
++ SimpleAjpClient ajpClient = new SimpleAjpClient();
++ ajpClient.setPort(getPort());
++ ajpClient.connect();
++
++ validateCpong(ajpClient.cping());
++
++ TesterAjpMessage forwardMessage =
++ ajpClient.createForwardMessage("/echo-params.jsp", 4);
++ forwardMessage.addHeader(0xA008, "9");
++ if (multipleCL) {
++ forwardMessage.addHeader(0xA008, "99");
++ }
++ forwardMessage.addHeader(0xA007, "application/x-www-form-urlencoded");
++ forwardMessage.end();
++ TesterAjpMessage bodyMessage =
++ ajpClient.createBodyMessage("test=data".getBytes());
++
++ TesterAjpMessage responseHeaders =
++ ajpClient.sendMessage(forwardMessage, bodyMessage);
++
++ validateResponseHeaders(responseHeaders, expectedStatus);
++ if (expectedStatus == HttpServletResponse.SC_OK) {
++ // Expect 3 messages: headers, body, end for a valid request
++ TesterAjpMessage responseBody = ajpClient.readMessage();
++ validateResponseBody(responseBody, "test - data");
++ validateResponseEnd(ajpClient.readMessage(), true);
++ // Double check the connection is still open
++ validateCpong(ajpClient.cping());
++ } else {
++ // Expect 2 messages: headers, end for an invalid request
++ validateResponseEnd(ajpClient.readMessage(), false);
++ }
++
++ ajpClient.disconnect();
++ }
++
++
+ /**
+ * Process response header packet and checks the status. Any other data is
+ * ignored.
+--- test/org/apache/coyote/http11/TestAbstractHttp11Processor.java.orig 2014-03-14 17:13:52.946367000 -0400
++++ test/org/apache/coyote/http11/TestAbstractHttp11Processor.java 2014-03-14 17:13:52.925368000 -0400
+@@ -87,7 +87,7 @@
+ "Transfer-encoding: buffered" + SimpleHttpClient.CRLF +
+ "Content-Length: 9" + SimpleHttpClient.CRLF +
+ "Content-Type: application/x-www-form-urlencoded" +
+- SimpleHttpClient.CRLF +
++ SimpleHttpClient.CRLF +
+ SimpleHttpClient.CRLF +
+ "test=data";
+
+@@ -99,6 +99,54 @@
+ assertTrue(client.isResponse501());
+ }
+
++ @Test
++ public void testWithTEChunked() throws Exception {
++ doTestWithTEChunked(false);
++ }
++
++ @Test
++ public void testWithTEChunkedWithCL() throws Exception {
++ // Should be ignored
++ doTestWithTEChunked(true);
++ }
++
++ private void doTestWithTEChunked(boolean withCL)
++ throws Exception {
++
++ Tomcat tomcat = getTomcatInstance();
++
++ // Use the normal Tomcat ROOT context
++ File root = new File("test/webapp-3.0");
++ tomcat.addWebapp("", root.getAbsolutePath());
++
++ tomcat.start();
++
++ String request =
++ "POST /echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
++ "Host: any" + SimpleHttpClient.CRLF +
++ (withCL ? "Content-length: 1" + SimpleHttpClient.CRLF : "") +
++ "Transfer-encoding: chunked" + SimpleHttpClient.CRLF +
++ "Content-Type: application/x-www-form-urlencoded" +
++ SimpleHttpClient.CRLF +
++ "Connection: close" + SimpleHttpClient.CRLF +
++ SimpleHttpClient.CRLF +
++ "9" + SimpleHttpClient.CRLF +
++ "test=data" + SimpleHttpClient.CRLF +
++ "0" + SimpleHttpClient.CRLF +
++ SimpleHttpClient.CRLF;
++
++ Client client = new Client(tomcat.getConnector().getLocalPort());
++ client.setRequest(new String[] {request});
++
++ client.connect();
++ client.processRequest();
++ assertTrue(client.isResponse200());
++ assertTrue(client.getResponseBody().contains("test - data"));
++ }
++
++
++
++
+
+ @Test
+ public void testWithTEIdentity() throws Exception {
diff --git a/SOURCES/tomcat-7.0.42-CVE-2013-4322.patch b/SOURCES/tomcat-7.0.42-CVE-2013-4322.patch
new file mode 100644
index 0000000..d814c39
--- /dev/null
+++ b/SOURCES/tomcat-7.0.42-CVE-2013-4322.patch
@@ -0,0 +1,365 @@
+--- java/org/apache/coyote/http11/AbstractHttp11Processor.java.orig 2014-03-17 16:00:40.592415000 -0400
++++ java/org/apache/coyote/http11/AbstractHttp11Processor.java 2014-03-18 13:39:06.789696000 -0400
+@@ -684,13 +684,14 @@
+ /**
+ * Initialize standard input and output filters.
+ */
+- protected void initializeFilters(int maxTrailerSize) {
++ protected void initializeFilters(int maxTrailerSize, int maxExtensionSize) {
+ // Create and add the identity filters.
+ getInputBuffer().addFilter(new IdentityInputFilter());
+ getOutputBuffer().addFilter(new IdentityOutputFilter());
+
+ // Create and add the chunked filters.
+- getInputBuffer().addFilter(new ChunkedInputFilter(maxTrailerSize));
++ getInputBuffer().addFilter(
++ new ChunkedInputFilter(maxTrailerSize, maxExtensionSize));
+ getOutputBuffer().addFilter(new ChunkedOutputFilter());
+
+ // Create and add the void filters.
+--- java/org/apache/coyote/http11/AbstractHttp11Protocol.java.orig 2014-03-17 16:00:57.458467000 -0400
++++ java/org/apache/coyote/http11/AbstractHttp11Protocol.java 2014-03-17 16:40:11.035409000 -0400
+@@ -151,7 +151,15 @@
+ this.maxTrailerSize = maxTrailerSize;
+ }
+
+-
++ /**
++ * Maximum size of extension information in chunked encoding
++ */
++ private int maxExtensionSize = 8192;
++ public int getMaxExtensionSize() { return maxExtensionSize; }
++ public void setMaxExtensionSize(int maxExtensionSize) {
++ this.maxExtensionSize = maxExtensionSize;
++ }
++
+ /**
+ * This field indicates if the protocol is treated as if it is secure. This
+ * normally means https is being used but can be used to fake https e.g
+--- java/org/apache/coyote/http11/Http11AprProcessor.java.orig 2014-03-17 16:01:22.889559000 -0400
++++ java/org/apache/coyote/http11/Http11AprProcessor.java 2014-03-17 16:43:14.716027000 -0400
+@@ -58,7 +58,7 @@
+
+
+ public Http11AprProcessor(int headerBufferSize, AprEndpoint endpoint,
+- int maxTrailerSize) {
++ int maxTrailerSize, int maxExtensionSize) {
+
+ super(endpoint);
+
+@@ -68,7 +68,7 @@
+ outputBuffer = new InternalAprOutputBuffer(response, headerBufferSize);
+ response.setOutputBuffer(outputBuffer);
+
+- initializeFilters(maxTrailerSize);
++ initializeFilters(maxTrailerSize, maxExtensionSize);
+ }
+
+
+--- java/org/apache/coyote/http11/Http11AprProtocol.java.orig 2014-03-17 16:10:16.268358000 -0400
++++ java/org/apache/coyote/http11/Http11AprProtocol.java 2014-03-17 16:50:17.428466000 -0400
+@@ -294,7 +294,7 @@
+ protected Http11AprProcessor createProcessor() {
+ Http11AprProcessor processor = new Http11AprProcessor(
+ proto.getMaxHttpHeaderSize(), (AprEndpoint)proto.endpoint,
+- proto.getMaxTrailerSize());
++ proto.getMaxTrailerSize(), proto.getMaxExtensionSize());
+ processor.setAdapter(proto.adapter);
+ processor.setMaxKeepAliveRequests(proto.getMaxKeepAliveRequests());
+ processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());
+--- java/org/apache/coyote/http11/Http11NioProcessor.java.orig 2014-03-17 16:02:20.016748000 -0400
++++ java/org/apache/coyote/http11/Http11NioProcessor.java 2014-03-17 16:51:55.623782000 -0400
+@@ -63,7 +63,7 @@
+
+
+ public Http11NioProcessor(int maxHttpHeaderSize, NioEndpoint endpoint,
+- int maxTrailerSize) {
++ int maxTrailerSize, int maxExtensionSize) {
+
+ super(endpoint);
+
+@@ -73,7 +73,7 @@
+ outputBuffer = new InternalNioOutputBuffer(response, maxHttpHeaderSize);
+ response.setOutputBuffer(outputBuffer);
+
+- initializeFilters(maxTrailerSize);
++ initializeFilters(maxTrailerSize, maxExtensionSize);
+ }
+
+
+--- java/org/apache/coyote/http11/Http11NioProtocol.java.orig 2014-03-17 16:07:26.027787000 -0400
++++ java/org/apache/coyote/http11/Http11NioProtocol.java 2014-03-17 16:53:09.198025000 -0400
+@@ -260,7 +260,7 @@
+ public Http11NioProcessor createProcessor() {
+ Http11NioProcessor processor = new Http11NioProcessor(
+ proto.getMaxHttpHeaderSize(), (NioEndpoint)proto.endpoint,
+- proto.getMaxTrailerSize());
++ proto.getMaxTrailerSize(), proto.getMaxExtensionSize());
+ processor.setAdapter(proto.adapter);
+ processor.setMaxKeepAliveRequests(proto.getMaxKeepAliveRequests());
+ processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());
+--- java/org/apache/coyote/http11/Http11Processor.java.orig 2014-03-17 16:07:45.099837000 -0400
++++ java/org/apache/coyote/http11/Http11Processor.java 2014-03-18 12:42:34.018260000 -0400
+@@ -50,7 +50,7 @@
+
+
+ public Http11Processor(int headerBufferSize, JIoEndpoint endpoint,
+- int maxTrailerSize) {
++ int maxTrailerSize, int maxExtensionSize) {
+
+ super(endpoint);
+
+@@ -60,7 +60,7 @@
+ outputBuffer = new InternalOutputBuffer(response, headerBufferSize);
+ response.setOutputBuffer(outputBuffer);
+
+- initializeFilters(maxTrailerSize);
++ initializeFilters(maxTrailerSize, maxExtensionSize);
+ }
+
+
+--- java/org/apache/coyote/http11/Http11Protocol.java.orig 2014-03-17 16:08:00.058113000 -0400
++++ java/org/apache/coyote/http11/Http11Protocol.java 2014-03-17 16:56:04.194609000 -0400
+@@ -164,7 +164,7 @@
+ protected Http11Processor createProcessor() {
+ Http11Processor processor = new Http11Processor(
+ proto.getMaxHttpHeaderSize(), (JIoEndpoint)proto.endpoint,
+- proto.getMaxTrailerSize());
++ proto.getMaxTrailerSize(), proto.getMaxExtensionSize());
+ processor.setAdapter(proto.adapter);
+ processor.setMaxKeepAliveRequests(proto.getMaxKeepAliveRequests());
+ processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());
+--- java/org/apache/coyote/http11/filters/ChunkedInputFilter.java.orig 2014-03-17 16:08:12.213985000 -0400
++++ java/org/apache/coyote/http11/filters/ChunkedInputFilter.java 2014-03-18 13:13:49.468583000 -0400
+@@ -118,9 +118,29 @@
+ */
+ private Request request;
+
++
++ /**
++ * Limit for extension size.
++ */
++ private final long maxExtensionSize;
++
++
++ /**
++ * Limit for trailer size.
++ */
++ private int maxTrailerSize;
++
++
++ /**
++ * Size of extensions processed for this request.
++ */
++ private long extensionSize;
++
+ // ----------------------------------------------------------- Constructors
+- public ChunkedInputFilter(int maxTrailerSize) {
++ public ChunkedInputFilter(int maxTrailerSize, int maxExtensionSize) {
+ this.trailingHeaders.setLimit(maxTrailerSize);
++ this.maxTrailerSize = maxTrailerSize;
++ this.maxExtensionSize = maxExtensionSize;
+ }
+
+ // ---------------------------------------------------- InputBuffer Methods
+@@ -250,6 +270,8 @@
+ endChunk = false;
+ needCRLFParse = false;
+ trailingHeaders.recycle();
++ trailingHeaders.setLimit(maxTrailerSize);
++ extensionSize = 0;
+ }
+
+
+@@ -299,7 +321,7 @@
+ int result = 0;
+ boolean eol = false;
+ boolean readDigit = false;
+- boolean trailer = false;
++ boolean extension = false;
+
+ while (!eol) {
+
+@@ -311,9 +333,13 @@
+ if (buf[pos] == Constants.CR || buf[pos] == Constants.LF) {
+ parseCRLF(false);
+ eol = true;
+- } else if (buf[pos] == Constants.SEMI_COLON) {
+- trailer = true;
+- } else if (!trailer) {
++ } else if (buf[pos] == Constants.SEMI_COLON && !extension) {
++ // First semi-colon marks the start of the extension. Further
++ // semi-colons may appear to separate multiple chunk-extensions.
++ // These need to be processed as part of parsing the extensions.
++ extension = true;
++ extensionSize++;
++ } else if (!extension) {
+ //don't read data after the trailer
+ int charValue = HexUtils.getDec(buf[pos]);
+ if (charValue != -1) {
+@@ -325,13 +351,20 @@
+ //in the chunked header
+ return false;
+ }
+- }
+-
+- // Parsing the CRLF increments pos
+- if (!eol) {
+- pos++;
+- }
++ } else {
++ // Extension 'parsing'
++ // Note that the chunk-extension is neither parsed nor
++ // validated. Currently it is simply ignored.
++ extensionSize++;
++ if (maxExtensionSize > -1 && extensionSize > maxExtensionSize) {
++ throw new IOException("maxExtensionSize exceeded");
++ }
++ }
++ }
+
++ // Parsing the CRLF increments pos
++ if (!eol) {
++ pos++;
+ }
+
+ if (!readDigit)
+@@ -489,12 +522,17 @@
+ chr = buf[pos];
+ if ((chr == Constants.SP) || (chr == Constants.HT)) {
+ pos++;
++ // If we swallow whitespace, make sure it counts towards the
++ // limit placed on trailing header size
++ int newlimit = trailingHeaders.getLimit() -1;
++ if (trailingHeaders.getEnd() > newlimit) {
++ throw new IOException("Exceeded maxTrailerSize");
++ }
++ trailingHeaders.setLimit(newlimit);
+ } else {
+ space = false;
+ }
+-
+ }
+-
+ // Reading bytes until the end of the line
+ while (!eol) {
+
+--- test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java.orig 2014-03-17 16:08:33.031999000 -0400
++++ test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java 2014-03-17 17:40:23.853592000 -0400
+@@ -41,6 +41,7 @@
+ public class TestChunkedInputFilter extends TomcatBaseTest {
+
+ private static final String LF = "\n";
++ private static final int EXT_SIZE_LIMIT = 10;
+
+ @Test
+ public void testChunkHeaderCRLF() throws Exception {
+@@ -202,6 +203,79 @@
+ assertTrue(client.isResponse500());
+ }
+
++
++ @Test
++ public void testExtensionSizeLimitOneBelow() throws Exception {
++ doTestExtensionSizeLimit(EXT_SIZE_LIMIT - 1, true);
++ }
++
++
++ @Test
++ public void testExtensionSizeLimitExact() throws Exception {
++ doTestExtensionSizeLimit(EXT_SIZE_LIMIT, true);
++ }
++
++
++ @Test
++ public void testExtensionSizeLimitOneOver() throws Exception {
++ doTestExtensionSizeLimit(EXT_SIZE_LIMIT + 1, false);
++ }
++
++ private void doTestExtensionSizeLimit(int len, boolean ok)
++ throws Exception {
++ // Setup Tomcat instance
++ Tomcat tomcat = getTomcatInstance();
++
++ tomcat.getConnector().setProperty(
++ "maxExtensionSize", Integer.toString(EXT_SIZE_LIMIT));
++
++ // Must have a real docBase - just use temp
++ Context ctx =
++ tomcat.addContext("", System.getProperty("java.io.tmpdir"));
++
++ Tomcat.addServlet(ctx, "servlet", new EchoHeaderServlet());
++ ctx.addServletMapping("/", "servlet");
++
++ tomcat.start();
++
++ String extName = ";foo=";
++ StringBuilder extValue = new StringBuilder(len);
++ for (int i = 0; i < (len - extName.length()); i++) {
++ extValue.append("x");
++ }
++
++ String[] request = new String[]{
++ "POST /echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
++ "Host: any" + SimpleHttpClient.CRLF +
++ "Transfer-encoding: chunked" + SimpleHttpClient.CRLF +
++ "Content-Type: application/x-www-form-urlencoded" +
++ SimpleHttpClient.CRLF +
++ "Connection: close" + SimpleHttpClient.CRLF +
++ SimpleHttpClient.CRLF +
++ "3" + extName + extValue.toString() + SimpleHttpClient.CRLF +
++ "a=0" + SimpleHttpClient.CRLF +
++ "4" + SimpleHttpClient.CRLF +
++ "&b=1" + SimpleHttpClient.CRLF +
++ "0" + SimpleHttpClient.CRLF +
++ SimpleHttpClient.CRLF };
++
++ TrailerClient client =
++ new TrailerClient(tomcat.getConnector().getLocalPort());
++ client.setRequest(request);
++
++ client.connect();
++ client.processRequest();
++
++ if (ok) {
++ assertTrue(client.isResponse200());
++ } else {
++ assertTrue(client.isResponse500());
++ }
++ }
++
++
++
++
+ @Test
+ public void testNoTrailingHeaders() throws Exception {
+ // Setup Tomcat instance
+--- webapps/docs/changelog.xml.orig 2014-03-17 16:08:46.095050000 -0400
++++ webapps/docs/changelog.xml 2014-03-17 17:44:14.163385000 -0400
+@@ -394,6 +394,11 @@
+
Limits the total length of chunk extensions in chunked HTTP requests.
++ If the value is -1
, no limit will be imposed. If not
++ specified, the default value of 8192
will be used.
The maximum size of the request and response HTTP header, specified + in bytes. If not specified, this attribute is set to 8192 (8 KB).
diff --git a/SOURCES/tomcat-7.0.42-CVE-2014-0050.patch b/SOURCES/tomcat-7.0.42-CVE-2014-0050.patch new file mode 100644 index 0000000..8ce8a51 --- /dev/null +++ b/SOURCES/tomcat-7.0.42-CVE-2014-0050.patch @@ -0,0 +1,107 @@ +--- java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java.orig 2014-03-17 18:30:01.467636000 -0400 ++++ java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java 2014-03-17 18:37:43.992207000 -0400 +@@ -805,7 +805,7 @@ + || (!contentType.toLowerCase(Locale.ENGLISH).startsWith(MULTIPART))) { + throw new InvalidContentTypeException(String.format( + "the request doesn't contain a %s or %s stream, content type header is %s", +- MULTIPART_FORM_DATA, MULTIPART_FORM_DATA, contentType)); ++ MULTIPART_FORM_DATA, MULTIPART_MIXED, contentType)); + } + + InputStream input = ctx.getInputStream(); +@@ -816,8 +816,7 @@ + if (requestSize != -1 && requestSize > sizeMax) { + throw new SizeLimitExceededException(String.format( + "the request was rejected because its size (%s) exceeds the configured maximum (%s)", +- Long.valueOf(requestSize), +- Long.valueOf(sizeMax)), ++ Long.valueOf(requestSize), Long.valueOf(sizeMax)), + requestSize, sizeMax); + } + input = new LimitedInputStream(input, sizeMax) { +@@ -844,7 +843,14 @@ + } + + notifier = new MultipartStream.ProgressNotifier(listener, requestSize); +- multi = new MultipartStream(input, boundary, notifier); ++ try { ++ multi = new MultipartStream(input, boundary, notifier); ++ } catch (IllegalArgumentException iae) { ++ throw new InvalidContentTypeException(String.format( ++ "The boundary specified in the %s header is too long", ++ CONTENT_TYPE), iae); ++ } ++ + multi.setHeaderEncoding(charEncoding); + + skipPreamble = true; +@@ -1022,7 +1028,7 @@ + * detail message. + */ + public InvalidContentTypeException() { +- // Nothing to do. ++ super(); + } + + /** +@@ -1035,6 +1041,10 @@ + super(message); + } + ++ public InvalidContentTypeException(String msg, Throwable cause) { ++ super(msg, cause); ++ } ++ + } + + /** +--- java/org/apache/tomcat/util/http/fileupload/MultipartStream.java.orig 2014-03-17 18:30:01.512626000 -0400 ++++ java/org/apache/tomcat/util/http/fileupload/MultipartStream.java 2014-03-17 18:41:15.868033000 -0400 +@@ -278,8 +278,7 @@ + * @param pNotifier The notifier, which is used for calling the + * progress listener, if any. + * +- * @see #MultipartStream(InputStream, byte[], +- * MultipartStream.ProgressNotifier) ++ * @throws IllegalArgumentException If the buffer size is too small + */ + MultipartStream(InputStream input, + byte[] boundary, +@@ -292,8 +291,12 @@ + + // We prepend CR/LF to the boundary to chop trailing CR/LF from + // body-data tokens. +- this.boundary = new byte[boundary.length + BOUNDARY_PREFIX.length]; + this.boundaryLength = boundary.length + BOUNDARY_PREFIX.length; ++ if (bufSize < this.boundaryLength + 1) { ++ throw new IllegalArgumentException( ++ "The buffer size specified for the MultipartStream is too small"); ++ } ++ this.boundary = new byte[this.boundaryLength]; + this.keepRegion = this.boundary.length; + System.arraycopy(BOUNDARY_PREFIX, 0, this.boundary, 0, + BOUNDARY_PREFIX.length); +@@ -313,8 +316,7 @@ + * @param pNotifier An object for calling the progress listener, if any. + * + * +- * @see #MultipartStream(InputStream, byte[], int, +- * MultipartStream.ProgressNotifier) ++ * @see #MultipartStream(InputStream, byte[], int, ProgressNotifier) + */ + MultipartStream(InputStream input, + byte[] boundary, +--- webapps/docs/changelog.xml.orig 2014-03-17 18:30:01.569656000 -0400 ++++ webapps/docs/changelog.xml 2014-03-17 18:44:11.967500000 -0400 +@@ -59,6 +59,11 @@ +ServletContextListener
s defined in one of the
diff --git a/SOURCES/tomcat-7.0.init b/SOURCES/tomcat-7.0.init
deleted file mode 100644
index f5269f5..0000000
--- a/SOURCES/tomcat-7.0.init
+++ /dev/null
@@ -1,319 +0,0 @@
-#!/bin/bash
-#
-# tomcat This shell script takes care of starting and stopping Tomcat
-#
-# chkconfig: - 80 20
-#
-### BEGIN INIT INFO
-# Provides: tomcat
-# Required-Start: $network $syslog
-# Required-Stop: $network $syslog
-# Default-Start:
-# Default-Stop:
-# Description: Release implementation for Servlet 3.0 and JSP 2.2
-# Short-Description: start and stop tomcat
-### END INIT INFO
-#
-# - originally written by Henri Gomez, Keith Irwin, and Nicolas Mailhot
-# - heavily rewritten by Deepak Bhole and Jason Corley
-#
-
-## Source function library.
-#. /etc/rc.d/init.d/functions
-# Source LSB function library.
-if [ -r /lib/lsb/init-functions ]; then
- . /lib/lsb/init-functions
-else
- exit 1
-fi
-
-DISTRIB_ID=`lsb_release -i -s 2>/dev/null`
-
-NAME="$(basename $0)"
-unset ISBOOT
-if [ "${NAME:0:1}" = "S" -o "${NAME:0:1}" = "K" ]; then
- NAME="${NAME:3}"
- ISBOOT="1"
-fi
-
-# For SELinux we need to use 'runuser' not 'su'
-if [ -x "/sbin/runuser" ]; then
- SU="/sbin/runuser -s /bin/sh"
-else
- SU="/bin/su -s /bin/sh"
-fi
-
-# Get the tomcat config (use this for environment specific settings)
-TOMCAT_CFG="/etc/tomcat/tomcat.conf"
-if [ -r "$TOMCAT_CFG" ]; then
- . $TOMCAT_CFG
-fi
-
-# Get instance specific config file
-if [ -r "/etc/sysconfig/${NAME}" ]; then
- . /etc/sysconfig/${NAME}
-fi
-
-# Define which connector port to use
-CONNECTOR_PORT="${CONNECTOR_PORT:-8080}"
-
-# Path to the tomcat launch script
-TOMCAT_SCRIPT="/usr/sbin/tomcat"
-
-# Tomcat program name
-TOMCAT_PROG="${NAME}"
-
-# Define the tomcat username
-TOMCAT_USER="${TOMCAT_USER:-tomcat}"
-
-# Define the tomcat log file
-TOMCAT_LOG="${TOMCAT_LOG:-${CATALINA_HOME}/logs/${NAME}-initd.log}"
-
-
-RETVAL="0"
-
-# Look for open ports, as the function name might imply
-function findFreePorts() {
- local isSet1="false"
- local isSet2="false"
- local isSet3="false"
- local lower="8000"
- randomPort1="0"
- randomPort2="0"
- randomPort3="0"
- local -a listeners="( $(
- netstat -ntl | \
- awk '/^tcp/ {gsub("(.)*:", "", $4); print $4}'
- ) )"
- while [ "$isSet1" = "false" ] || \
- [ "$isSet2" = "false" ] || \
- [ "$isSet3" = "false" ]; do
- let port="${lower}+${RANDOM:0:4}"
- if [ -z `expr " ${listeners[*]} " : ".*\( $port \).*"` ]; then
- if [ "$isSet1" = "false" ]; then
- export randomPort1="$port"
- isSet1="true"
- elif [ "$isSet2" = "false" ]; then
- export randomPort2="$port"
- isSet2="true"
- elif [ "$isSet3" = "false" ]; then
- export randomPort3="$port"
- isSet3="true"
- fi
- fi
- done
-}
-
-function makeHomeDir() {
- if [ ! -d "$CATALINA_HOME" ]; then
- echo "$CATALINA_HOME does not exist, creating"
- if [ ! -d "/usr/share/${NAME}" ]; then
- mkdir /usr/share/${NAME}
- cp -pLR /usr/share/tomcat/* /usr/share/${NAME}
- fi
- mkdir -p /var/log/${NAME} \
- /var/cache/${NAME} \
- /var/tmp/${NAME}
- ln -fs /var/cache/${NAME} ${CATALINA_HOME}/work
- ln -fs /var/tmp/${NAME} ${CATALINA_HOME}/temp
- cp -pLR /usr/share/${NAME}/bin $CATALINA_HOME
- cp -pLR /usr/share/${NAME}/conf $CATALINA_HOME
- ln -fs /usr/share/java/tomcat ${CATALINA_HOME}/lib
- ln -fs /usr/share/tomcat/webapps ${CATALINA_HOME}/webapps
- chown ${TOMCAT_USER}:${TOMCAT_USER} /var/log/${NAME}
- fi
-}
-
-function parseOptions() {
- options=""
- options="$options $(
- awk '!/^#/ && !/^$/ { ORS=" "; print "export ", $0, ";" }' \
- $TOMCAT_CFG
- )"
- if [ -r "/etc/sysconfig/${NAME}" ]; then
- options="$options $(
- awk '!/^#/ && !/^$/ { ORS=" ";
- print "export ", $0, ";" }' \
- /etc/sysconfig/${NAME}
- )"
- fi
- TOMCAT_SCRIPT="$options ${TOMCAT_SCRIPT}"
-}
-
-# See how we were called.
-function start() {
-
- echo -n "Starting ${TOMCAT_PROG}: "
- if [ "$RETVAL" != "0" ]; then
- log_failure_msg
- return
- fi
- if [ -f "/var/lock/subsys/${NAME}" ]; then
- if [ -s "/var/run/${NAME}.pid" ]; then
- read kpid < /var/run/${NAME}.pid
-# if checkpid $kpid 2>&1; then
- if [ -d "/proc/${kpid}" ]; then
- log_success_msg
- if [ "$DISTRIB_ID" = "MandrivaLinux" ]; then
- echo
- fi
- return 0
- fi
- fi
- fi
- # fix permissions on the log and pid files
- export CATALINA_PID="/var/run/${NAME}.pid"
- touch $CATALINA_PID 2>&1 || RETVAL="4"
- if [ "$RETVAL" -eq "0" -a "$?" -eq "0" ]; then
- chown ${TOMCAT_USER}:${TOMCAT_USER} $CATALINA_PID
- fi
- [ "$RETVAL" -eq "0" ] && touch $TOMCAT_LOG 2>&1 || RETVAL="4"
- if [ "$RETVAL" -eq "0" -a "$?" -eq "0" ]; then
- chown ${TOMCAT_USER}:${TOMCAT_USER} $TOMCAT_LOG
- fi
- if [ "$CATALINA_HOME" != "/usr/share/tomcat" -a "$RETVAL" -eq "0" ]; then
- # Create a tomcat directory if it doesn't exist
- makeHomeDir
- # If CATALINA_HOME doesn't exist modify port number so that
- # multiple instances don't interfere with each other
- findFreePorts
- sed -i -e "s/8005/${randomPort1}/g" -e "s/8080/${CONNECTOR_PORT}/g" \
- -e "s/8009/${randomPort2}/g" -e "s/8443/${randomPort3}/g" \
- ${CATALINA_HOME}/conf/server.xml
- fi
- parseOptions
- if [ "$RETVAL" -eq "0" -a "$SECURITY_MANAGER" = "true" ]; then
- $SU - $TOMCAT_USER -c "${TOMCAT_SCRIPT} start-security" \
- >> ${TOMCAT_LOG} 2>&1 || RETVAL="4"
- else
-
- [ "$RETVAL" -eq "0" ] && $SU - $TOMCAT_USER -c "${TOMCAT_SCRIPT} start" >> ${TOMCAT_LOG} 2>&1 || RETVAL="4"
- fi
- if [ "$RETVAL" -eq "0" ]; then
- log_success_msg
- touch /var/lock/subsys/${NAME}
- else
- log_failure_msg "Error code ${RETVAL}"
- fi
- if [ "$DISTRIB_ID" = "MandrivaLinux" ]; then
- echo
- fi
-}
-
-function stop() {
- echo -n "Stopping ${TOMCAT_PROG}: "
- if [ -f "/var/lock/subsys/${NAME}" ]; then
- parseOptions
- if [ "$RETVAL" -eq "0" ]; then
- touch /var/lock/subsys/${NAME} 2>&1 || RETVAL="4"
- [ "$RETVAL" -eq "0" ] && $SU - $TOMCAT_USER -c "${TOMCAT_SCRIPT} stop" >> ${TOMCAT_LOG} 2>&1 || RETVAL="4"
- fi
- if [ "$RETVAL" -eq "0" ]; then
- count="0"
- if [ -s "/var/run/${NAME}.pid" ]; then
- read kpid < /var/run/${NAME}.pid
- until [ "$(ps --pid $kpid | grep -c $kpid)" -eq "0" ] || \
- [ "$count" -gt "$SHUTDOWN_WAIT" ]; do
- if [ "$SHUTDOWN_VERBOSE" = "true" ]; then
- echo "waiting for processes $kpid to exit"
- fi
- sleep 1
- let count="${count}+1"
- done
- if [ "$count" -gt "$SHUTDOWN_WAIT" ]; then
- if [ "$SHUTDOWN_VERBOSE" = "true" ]; then
- log_warning_msg "killing processes which did not stop after ${SHUTDOWN_WAIT} seconds"
- fi
- kill -9 $kpid
- fi
- log_success_msg
- fi
- rm -f /var/lock/subsys/${NAME} /var/run/${NAME}.pid
- else
- log_failure_msg
- RETVAL="4"
- fi
- else
- log_success_msg
- RETVAL="0"
- fi
- if [ "$DISTRIB_ID" = "MandrivaLinux" ]; then
- echo
- fi
-}
-
-function usage()
-{
- echo "Usage: $0 {start|stop|restart|condrestart|try-restart|reload|force-reload|status|version}"
- RETVAL="2"
-}
-
-# See how we were called.
-RETVAL="0"
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- restart)
- stop
- start
- ;;
- condrestart|try-restart)
- if [ -s "/var/run/${NAME}.pid" ]; then
- stop
- start
- fi
- ;;
- reload)
- RETVAL="3"
- ;;
- force-reload)
- if [ -s "/var/run/${NAME}.pid" ]; then
- stop
- start
- fi
- ;;
- status)
- if [ -s "/var/run/${NAME}.pid" ]; then
- read kpid < /var/run/${NAME}.pid
- if [ -d "/proc/${kpid}" ]; then
- log_success_msg "${NAME} (pid ${kpid}) is running..."
- RETVAL="0"
- else
-# The pid file exists but the process is not running
- log_warning_msg "PID file exists, but process is not running"
- RETVAL="1"
- fi
- else
- pid="$(/usr/bin/pgrep -d , -u ${TOMCAT_USER} -G ${TOMCAT_USER} java)"
- if [ -z "$pid" ]; then
-# status ${NAME}
-# RETVAL="$?"
- log_success_msg "${NAME} is stopped"
- RETVAL="3"
- else
- log_success_msg "${NAME} (pid $pid) is running..."
- RETVAL="0"
- fi
- fi
- if [ -f /var/lock/subsys/${NAME} ]; then
- pid="$(/usr/bin/pgrep -d , -u ${TOMCAT_USER} -G ${TOMCAT_USER} java)"
-# The lockfile exists but the process is not running
- if [ -z "$pid" ]; then
- log_failure_msg "${NAME} lockfile exists but process is not running"
- RETVAL="2"
- fi
- fi
- ;;
- version)
- ${TOMCAT_SCRIPT} version
- ;;
- *)
- usage
- ;;
-esac
-
-exit $RETVAL
diff --git a/SPECS/tomcat.spec b/SPECS/tomcat.spec
index ddb2cab..18db988 100644
--- a/SPECS/tomcat.spec
+++ b/SPECS/tomcat.spec
@@ -31,7 +31,7 @@
%global jspspec 2.2
%global major_version 7
%global minor_version 0
-%global micro_version 40
+%global micro_version 42
%global packdname apache-tomcat-%{version}-src
%global servletspec 3.0
%global elspec 2.2
@@ -54,7 +54,7 @@
Name: tomcat
Epoch: 0
Version: %{major_version}.%{minor_version}.%{micro_version}
-Release: 2%{?dist}
+Release: 4%{?dist}
Summary: Apache Servlet/JSP Engine, RI for Servlet %{servletspec}/JSP %{jspspec} API
Group: System Environment/Daemons
@@ -62,7 +62,7 @@ License: ASL 2.0
URL: http://tomcat.apache.org/
Source0: http://www.apache.org/dist/tomcat/tomcat-%{major_version}/v%{version}/src/%{packdname}.tar.gz
Source1: %{name}-%{major_version}.%{minor_version}.conf
-Source2: %{name}-%{major_version}.%{minor_version}.init
+#Source2: %{name}-%{major_version}.%{minor_version}.init
Source3: %{name}-%{major_version}.%{minor_version}.sysconfig
Source4: %{name}-%{major_version}.%{minor_version}.wrapper
Source5: %{name}-%{major_version}.%{minor_version}.logrotate
@@ -83,13 +83,16 @@ Source19: %{name}-%{major_version}.%{minor_version}-jsvc.wrapper
Source20: %{name}-%{major_version}.%{minor_version}-jsvc.service
-Patch0: %{name}-%{major_version}.%{minor_version}-bootstrap-MANIFEST.MF.patch
-Patch1: %{name}-%{major_version}.%{minor_version}-tomcat-users-webapp.patch
+Patch0: %{name}-%{major_version}.%{minor_version}-bootstrap-MANIFEST.MF.patch
+Patch1: %{name}-%{major_version}.%{minor_version}-tomcat-users-webapp.patch
+Patch2: %{name}-%{version}-CVE-2013-4286.patch
+Patch3: %{name}-%{version}-CVE-2013-4322.patch
+Patch4: %{name}-%{version}-CVE-2014-0050.patch
BuildArch: noarch
BuildRequires: ant
-BuildRequires: ant-nodeps
+#BuildRequires: ant-nodeps
BuildRequires: ecj >= 1:4.2.1
BuildRequires: findutils
BuildRequires: apache-commons-collections
@@ -153,15 +156,15 @@ Requires: jpackage-utils
%description javadoc
Javadoc generated documentation for Apache Tomcat.
-%package systemv
-Group: System Environment/Daemons
-Summary: Systemv scripts for Apache Tomcat
-Requires: %{name} = %{epoch}:%{version}-%{release}
-Requires(post): chkconfig
-Requires(postun): chkconfig
+#%package systemv
+#Group: System Environment/Daemons
+#Summary: Systemv scripts for Apache Tomcat
+#Requires: %{name} = %{epoch}:%{version}-%{release}
+#Requires(post): chkconfig
+#Requires(postun): chkconfig
-%description systemv
-SystemV scripts to start and stop tomcat service
+#%description systemv
+#SystemV scripts to start and stop tomcat service
%package jsvc
Group: System Environment/Daemons
@@ -242,11 +245,16 @@ find . -type f \( -name "*.bat" -o -name "*.class" -o -name Thumbs.db -o -name "
%patch0 -p0
%patch1 -p0
+%patch2 -p0
+%patch3 -p0
+%patch4 -p0
+
%{__ln_s} $(build-classpath jakarta-taglibs-core) webapps/examples/WEB-INF/lib/jstl.jar
%{__ln_s} $(build-classpath jakarta-taglibs-standard) webapps/examples/WEB-INF/lib/standard.jar
%build
export OPT_JAR_LIST="xalan-j2-serializer"
+
# 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
@@ -358,8 +366,8 @@ popd
-e "s|\@\@\@TCTEMP\@\@\@|%{tempdir}|g" \
-e "s|\@\@\@LIBDIR\@\@\@|%{_libdir}|g" %{SOURCE3} \
> ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/%{name}
-%{__install} -m 0644 %{SOURCE2} \
- ${RPM_BUILD_ROOT}%{_initrddir}/%{name}
+#%{__install} -m 0644 %{SOURCE2} \
+# ${RPM_BUILD_ROOT}%{_initrddir}/%{name}
%{__install} -m 0644 %{SOURCE4} \
${RPM_BUILD_ROOT}%{_sbindir}/%{name}
%{__install} -m 0644 %{SOURCE11} \
@@ -372,7 +380,7 @@ popd
${RPM_BUILD_ROOT}%{_unitdir}/%{name}-jsvc.service
%{__install} -m 0644 %{SOURCE18} \
${RPM_BUILD_ROOT}%{_sbindir}/%{name}-jsvc-sysd
-%{__ln_s} %{name} ${RPM_BUILD_ROOT}%{_sbindir}/d%{name}
+# %{__ln_s} %{name} ${RPM_BUILD_ROOT}%{_sbindir}/d%{name}
%{__sed} -e "s|\@\@\@TCLOG\@\@\@|%{logdir}|g" %{SOURCE5} \
> ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}
%{__sed} -e "s|\@\@\@TCHOME\@\@\@|%{homedir}|g" \
@@ -503,15 +511,15 @@ EOF
# add the tomcat user and group
%{_sbindir}/groupadd -g %{tcuid} -r tomcat 2>/dev/null || :
%{_sbindir}/useradd -c "Apache Tomcat" -u %{tcuid} -g tomcat \
- -s /bin/nologin -r -d %{homedir} tomcat 2>/dev/null || :
+ -s /sbin/nologin -r -d %{homedir} tomcat 2>/dev/null || :
%post
# install but don't activate
%systemd_post %{name}.service
-%post systemv
+#%post systemv
# install but don't activate
-/sbin/chkconfig --add %{name}
+#/sbin/chkconfig --add %{name}
%post jsp-%{jspspec}-api
%{_sbindir}/update-alternatives --install %{_javadir}/jsp.jar jsp \
@@ -525,9 +533,11 @@ EOF
%{_sbindir}/update-alternatives --install %{_javadir}/elspec.jar elspec \
%{_javadir}/%{name}-el-%{elspec}-api.jar 20300
-%preun systemv
- %{_initrddir}/%{name} stop >/dev/null 2>&1
- /sbin/chkconfig --del %{name}
+#%preun systemv
+#if [ "$1" = "0" ]; then
+# %{_initrddir}/%{name} stop >/dev/null 2>&1
+# /sbin/chkconfig --del %{name}
+#fi
%preun
# clean tempdir and workdir on removal or upgrade
@@ -665,10 +675,10 @@ fi
%{appdir}/examples
%{appdir}/sample
-%files systemv
-%defattr(755,root,root,0755)
-%{_sbindir}/d%{name}
-%{_initrddir}/%{name}
+#%files systemv
+#%defattr(755,root,root,0755)
+#%{_sbindir}/d%{name}
+#%{_initrddir}/%{name}
%files jsvc
%defattr(755,root,root,0755)
@@ -676,7 +686,36 @@ fi
%{_sbindir}/%{name}-jsvc-sysd
%attr(0644,root,root) %{_unitdir}/%{name}-jsvc.service
+
%changelog
+* Thu Mar 20 2014 David Knox