Author: kkolinko Date: Thu Jun 14 15:26:43 2012 New Revision: 1350295 URL: http://svn.apache.org/viewvc?rev=1350295&view=rev Log: Implement maxHeaderCount attribute on Connector. It is equivalent of LimitRequestFields directive of Apache HTTPD
Modified: tomcat/trunk/java/org/apache/catalina/connector/Connector.java tomcat/trunk/java/org/apache/catalina/connector/mbeans-descriptors.xml tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java tomcat/trunk/java/org/apache/coyote/spdy/SpdyProcessor.java tomcat/trunk/java/org/apache/tomcat/util/http/LocalStrings.properties tomcat/trunk/java/org/apache/tomcat/util/http/MimeHeaders.java tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java tomcat/trunk/webapps/docs/config/ajp.xml tomcat/trunk/webapps/docs/config/http.xml Modified: tomcat/trunk/java/org/apache/catalina/connector/Connector.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/Connector.java?rev=1350295&r1=1350294&r2=1350295&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/connector/Connector.java (original) +++ tomcat/trunk/java/org/apache/catalina/connector/Connector.java Thu Jun 14 15:26:43 2012 @@ -394,6 +394,24 @@ public class Connector extends Lifecycle /** + * Return the maximum number of headers that are allowed by the container. A + * value of less than 0 means no limit. + */ + public int getMaxHeaderCount() { + return ((Integer) getProperty("maxHeaderCount")).intValue(); + } + + /** + * Set the maximum number of headers in a request that are allowed by the + * container. A value of less than 0 means no limit. + * + * @param maxHeaderCount The new setting + */ + public void setMaxHeaderCount(int maxHeaderCount) { + setProperty("maxHeaderCount", String.valueOf(maxHeaderCount)); + } + + /** * Return the maximum number of parameters (GET plus POST) that will be * automatically parsed by the container. A value of less than 0 means no * limit. Modified: tomcat/trunk/java/org/apache/catalina/connector/mbeans-descriptors.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/mbeans-descriptors.xml?rev=1350295&r1=1350294&r2=1350295&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/connector/mbeans-descriptors.xml (original) +++ tomcat/trunk/java/org/apache/catalina/connector/mbeans-descriptors.xml Thu Jun 14 15:26:43 2012 @@ -77,6 +77,10 @@ description="The port number on which this connector is listening to requests. If the special value for port of zero is used then this method will report the actual port bound." type="int"/> + <attribute name="maxHeaderCount" + description="The maximum number of headers that are allowed by the container. 100 by default. A value of less than 0 means no limit." + type="int"/> + <attribute name="maxKeepAliveRequests" description="Maximum number of Keep-Alive requests to honor per connection" type="int"/> Modified: tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java?rev=1350295&r1=1350294&r2=1350295&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java (original) +++ tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java Thu Jun 14 15:26:43 2012 @@ -237,6 +237,12 @@ public abstract class AbstractProtocol i setConnectionTimeout(timeout); } + public int getMaxHeaderCount() { + return endpoint.getMaxHeaderCount(); + } + public void setMaxHeaderCount(int maxHeaderCount) { + endpoint.setMaxHeaderCount(maxHeaderCount); + } // ---------------------------------------------------------- Public methods Modified: tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java?rev=1350295&r1=1350294&r2=1350295&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java Thu Jun 14 15:26:43 2012 @@ -647,6 +647,9 @@ public abstract class AbstractAjpProcess // Decode headers MimeHeaders headers = request.getMimeHeaders(); + // Set this every time in case limit has been changed via JMX + headers.setLimit(endpoint.getMaxHeaderCount()); + int hCount = requestHeaderMessage.getInt(); for(int i = 0 ; i < hCount ; i++) { String hName = null; Modified: tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java?rev=1350295&r1=1350294&r2=1350295&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java Thu Jun 14 15:26:43 2012 @@ -932,6 +932,8 @@ public abstract class AbstractHttp11Proc } else { request.setStartTime(System.currentTimeMillis()); keptAlive = true; + // Set this every time in case limit has been changed via JMX + request.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount()); // Currently only NIO will ever return false here if (!getInputBuffer().parseHeaders()) { // We've read part of the request, don't recycle it Modified: tomcat/trunk/java/org/apache/coyote/spdy/SpdyProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/spdy/SpdyProcessor.java?rev=1350295&r1=1350294&r2=1350295&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/spdy/SpdyProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/spdy/SpdyProcessor.java Thu Jun 14 15:26:43 2012 @@ -519,6 +519,9 @@ public class SpdyProcessor extends Abstr // Request received. MimeHeaders mimeHeaders = request.getMimeHeaders(); + // Set this every time in case limit has been changed via JMX + mimeHeaders.setLimit(endpoint.getMaxHeaderCount()); + for (int i = 0; i < frame.nvCount; i++) { int nameLen = frame.read16(); if (nameLen > frame.remaining()) { Modified: tomcat/trunk/java/org/apache/tomcat/util/http/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/LocalStrings.properties?rev=1350295&r1=1350294&r2=1350295&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/http/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/util/http/LocalStrings.properties Thu Jun 14 15:26:43 2012 @@ -28,3 +28,5 @@ parameters.fallToDebug=\n Note: further cookies.invalidCookieToken=Cookies: Invalid cookie. Value not a token or quoted value cookies.invalidSpecial=Cookies: Unknown Special Cookie cookies.fallToDebug=\n Note: further occurrences of Cookie errors will be logged at DEBUG level. + +headers.maxCountFail=More than the maximum allowed number of headers ([{0}]) were detected. Modified: tomcat/trunk/java/org/apache/tomcat/util/http/MimeHeaders.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/MimeHeaders.java?rev=1350295&r1=1350294&r2=1350295&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/http/MimeHeaders.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/http/MimeHeaders.java Thu Jun 14 15:26:43 2012 @@ -21,6 +21,7 @@ import java.io.StringWriter; import java.util.Enumeration; import org.apache.tomcat.util.buf.MessageBytes; +import org.apache.tomcat.util.res.StringManager; /* XXX XXX XXX Need a major rewrite !!!! */ @@ -95,6 +96,9 @@ public class MimeHeaders { */ public static final int DEFAULT_HEADER_SIZE=8; + private static final StringManager sm = + StringManager.getManager("org.apache.tomcat.util.http"); + /** * The header fields. */ @@ -107,6 +111,11 @@ public class MimeHeaders { private int count; /** + * The limit on the number of header fields. + */ + private int limit = -1; + + /** * Creates a new MimeHeaders object using a default buffer size. */ public MimeHeaders() { @@ -114,6 +123,19 @@ public class MimeHeaders { } /** + * Set limit on the number of header fields. + */ + public void setLimit(int limit) { + this.limit = limit; + if (limit > 0 && headers.length > limit && count < limit) { + // shrink header list array + MimeHeaderField tmp[] = new MimeHeaderField[limit]; + System.arraycopy(headers, 0, tmp, 0, count); + headers = tmp; + } + } + + /** * Clears all header fields. */ // [seguin] added for consistency -- most other objects have recycle(). @@ -218,11 +240,19 @@ public class MimeHeaders { * field has not had its name or value initialized. */ private MimeHeaderField createHeader() { + if (limit > -1 && count >= limit) { + throw new IllegalStateException(sm.getString( + "headers.maxCountFail", Integer.valueOf(limit))); + } MimeHeaderField mh; int len = headers.length; if (count >= len) { // expand header list array - MimeHeaderField tmp[] = new MimeHeaderField[count * 2]; + int newLength = count * 2; + if (limit > 0 && newLength > limit) { + newLength = limit; + } + MimeHeaderField tmp[] = new MimeHeaderField[newLength]; System.arraycopy(headers, 0, tmp, 0, len); headers = tmp; } Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java?rev=1350295&r1=1350294&r2=1350295&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java Thu Jun 14 15:26:43 2012 @@ -349,6 +349,18 @@ public abstract class AbstractEndpoint { } /** + * The maximum number of headers in a request that are allowed. + * 100 by default. A value of less than 0 means no limit. + */ + private int maxHeaderCount = 100; // as in Apache HTTPD server + public int getMaxHeaderCount() { + return maxHeaderCount; + } + public void setMaxHeaderCount(int maxHeaderCount) { + this.maxHeaderCount = maxHeaderCount; + } + + /** * Name of the thread pool, which will be used for naming child threads. */ private String name = "TP"; Modified: tomcat/trunk/webapps/docs/config/ajp.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/ajp.xml?rev=1350295&r1=1350294&r2=1350295&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/ajp.xml (original) +++ tomcat/trunk/webapps/docs/config/ajp.xml Thu Jun 14 15:26:43 2012 @@ -95,6 +95,13 @@ By default, DNS lookups are disabled.</p> </attribute> + <attribute name="maxHeaderCount" required="false"> + <p>The maximum number of headers in a request that are allowed by the + container. A request that contains more headers than the specified limit + will be rejected. A value of less than 0 means no limit. + If not specified, a default of 100 is used.</p> + </attribute> + <attribute name="maxParameterCount" required="false"> <p>The maximum number of parameter and value pairs (GET plus POST) which will be automatically parsed by the container. Parameter and value pairs Modified: tomcat/trunk/webapps/docs/config/http.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/http.xml?rev=1350295&r1=1350294&r2=1350295&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/http.xml (original) +++ tomcat/trunk/webapps/docs/config/http.xml Thu Jun 14 15:26:43 2012 @@ -93,6 +93,13 @@ By default, DNS lookups are disabled.</p> </attribute> + <attribute name="maxHeaderCount" required="false"> + <p>The maximum number of headers in a request that are allowed by the + container. A request that contains more headers than the specified limit + will be rejected. A value of less than 0 means no limit. + If not specified, a default of 100 is used.</p> + </attribute> + <attribute name="maxParameterCount" required="false"> <p>The maximum number of parameter and value pairs (GET plus POST) which will be automatically parsed by the container. Parameter and value pairs --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org