You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2015/05/07 16:31:17 UTC

svn commit: r1678218 - in /tomcat/trunk: java/org/apache/coyote/http11/ java/org/apache/tomcat/util/net/ webapps/docs/config/

Author: markt
Date: Thu May  7 14:31:16 2015
New Revision: 1678218

URL: http://svn.apache.org/r1678218
Log:
Add a configurable limit to the size of client hello that Tomcat parses looking for SNI data.
Fallback to the default if the limit is not enough

Modified:
    tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11JsseProtocol.java
    tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties
    tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
    tomcat/trunk/webapps/docs/config/http.xml

Modified: tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11JsseProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11JsseProtocol.java?rev=1678218&r1=1678217&r2=1678218&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11JsseProtocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11JsseProtocol.java Thu May  7 14:31:16 2015
@@ -35,4 +35,10 @@ public abstract class AbstractHttp11Jsse
 
     public String getSslImplementationName() { return getEndpoint().getSslImplementationName(); }
     public void setSslImplementationName(String s) { getEndpoint().setSslImplementationName(s); }
+
+
+    public int getSniParseLimit() { return getEndpoint().getSniParseLimit(); }
+    public void setSniParseLimit(int sniParseLimit) {
+        getEndpoint().setSniParseLimit(sniParseLimit);
+    }
 }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java?rev=1678218&r1=1678217&r2=1678218&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java Thu May  7 14:31:16 2015
@@ -30,6 +30,7 @@ import org.apache.tomcat.util.net.jsse.N
 public abstract class AbstractJsseEndpoint<S> extends AbstractEndpoint<S> {
 
     private String sslImplementationName = null;
+    private int sniParseLimit = 64 * 1024;
 
     private SSLImplementation sslImplementation = null;
 
@@ -49,6 +50,16 @@ public abstract class AbstractJsseEndpoi
     }
 
 
+    public int getSniParseLimit() {
+        return sniParseLimit;
+    }
+
+
+    public void setSniParseLimit(int sniParseLimit) {
+        this.sniParseLimit = sniParseLimit;
+    }
+
+
     @Override
     protected Type getSslConfigType() {
         return SSLHostConfig.Type.JSSE;

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties?rev=1678218&r1=1678217&r2=1678218&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties Thu May  7 14:31:16 2015
@@ -99,6 +99,7 @@ channel.nio.ssl.closing=Channel is in cl
 channel.nio.ssl.invalidBuffer=You can only read using the application read buffer provided by the handler.
 channel.nio.ssl.expandNetInBuffer=Expanding network input buffer to [{0}] bytes
 channel.nio.ssl.expandNetOutBuffer=Expanding network output buffer to [{0}] bytes
+channel.nio.ssl.sniDefault=Unable to buffer enough data to determine requested SNI host name. Using default
 channel.nio.ssl.sniHostName=The SNI host name extracted for this connection was [{0}]
 
 sniExtractor.clientHelloTooBig=The ClientHello was not presented in a single TLS record so no SNI information could be extracted

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java?rev=1678218&r1=1678217&r2=1678218&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java Thu May  7 14:31:16 2015
@@ -299,13 +299,15 @@ public class SecureNio2Channel extends N
 
         SNIExtractor extractor = new SNIExtractor(netInBuffer);
 
-        while (extractor.getResult() == SNIResult.UNDERFLOW) {
+        while (extractor.getResult() == SNIResult.UNDERFLOW &&
+                netInBuffer.capacity() < endpoint.getSniParseLimit()) {
             // extractor needed more data to process but netInBuffer was full so
-            // double the size of the buffer and read some more data.
+            // expand the buffer and read some more data.
+            int newLimit = Math.min(netInBuffer.capacity() * 2, endpoint.getSniParseLimit());
             log.info(sm.getString("channel.nio.ssl.expandNetInBuffer",
-                    Integer.toString(netInBuffer.capacity() * 2)));
+                    Integer.toString(newLimit)));
 
-            netInBuffer = ByteBufferUtils.expand(netInBuffer);
+            netInBuffer = ByteBufferUtils.expand(netInBuffer, newLimit);
             sc.read(netInBuffer);
             extractor = new SNIExtractor(netInBuffer);
         }
@@ -322,7 +324,11 @@ public class SecureNio2Channel extends N
             sc.read(netInBuffer, socket, handshakeReadCompletionHandler);
             return 1;
         case UNDERFLOW:
-            // Can't happen. Buffer would have been expanded above.
+            // Unable to buffer enough data to read SNI extension data
+            if (log.isDebugEnabled()) {
+                log.debug(sm.getString("channel.nio.ssl.sniDefault"));
+            }
+            hostName = endpoint.getDefaultSSLHostConfigName();
             break;
         }
 

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java?rev=1678218&r1=1678217&r2=1678218&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java Thu May  7 14:31:16 2015
@@ -235,13 +235,15 @@ public class SecureNioChannel extends Ni
         sc.read(netInBuffer);
         SNIExtractor extractor = new SNIExtractor(netInBuffer);
 
-        while (extractor.getResult() == SNIResult.UNDERFLOW) {
+        while (extractor.getResult() == SNIResult.UNDERFLOW &&
+                netInBuffer.capacity() < endpoint.getSniParseLimit()) {
             // extractor needed more data to process but netInBuffer was full so
-            // double the size of the buffer and read some more data.
+            // expand the buffer and read some more data.
+            int newLimit = Math.min(netInBuffer.capacity() * 2, endpoint.getSniParseLimit());
             log.info(sm.getString("channel.nio.ssl.expandNetInBuffer",
-                    Integer.toString(netInBuffer.capacity() * 2)));
+                    Integer.toString(newLimit)));
 
-            netInBuffer = ByteBufferUtils.expand(netInBuffer);
+            netInBuffer = ByteBufferUtils.expand(netInBuffer, newLimit);
             sc.read(netInBuffer);
             extractor = new SNIExtractor(netInBuffer);
         }
@@ -257,7 +259,11 @@ public class SecureNioChannel extends Ni
         case NEED_READ:
             return SelectionKey.OP_READ;
         case UNDERFLOW:
-            // Can't happen. Buffer would have been expanded above.
+            // Unable to buffer enough data to read SNI extension data
+            if (log.isDebugEnabled()) {
+                log.debug(sm.getString("channel.nio.ssl.sniDefault"));
+            }
+            hostName = endpoint.getDefaultSSLHostConfigName();
             break;
         }
 

Modified: tomcat/trunk/webapps/docs/config/http.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/http.xml?rev=1678218&r1=1678217&r2=1678218&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/http.xml (original)
+++ tomcat/trunk/webapps/docs/config/http.xml Thu May  7 14:31:16 2015
@@ -1330,6 +1330,19 @@
 
   <attributes>
 
+    <attribute name="sniParseLimit" required="false">
+      <p>In order to implement SNI support, Tomcat has to parse the first TLS
+      message received on a new TLS connection (the client hello) to extract the
+      requested server name. The message needs to be buffered so it can then be
+      passed to the JSSE implementation for normal TLS processing. In theory,
+      this first message could be very large although in practise it is
+      typically a few hundered bytes. This attribute sets the maximum message
+      size that Tomcat will buffer. If a message exceeds this size, the
+      connection will be configured as if no server name was indicated by the
+      client. If not specified a default of <code>65536</code> (64k) will be
+      used.</p>
+    </attribute>
+
     <attribute name="sslImplementationName" required="false">
       <p>The class name of the SSL implementation to use. If not specified, the
       default of <code>org.apache.tomcat.util.net.jsse.JSSEImplementation</code>



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org