This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/10.1.x by this push:
     new 3344c17cef Add support for re-keying with TLS 1.3
3344c17cef is described below

commit 3344c17cef094da4bb616f4186ed32039627b543
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Jun 12 19:43:39 2024 +0100

    Add support for re-keying with TLS 1.3
---
 .../apache/tomcat/util/net/LocalStrings.properties |  2 ++
 .../apache/tomcat/util/net/SecureNio2Channel.java  | 26 ++++++++++++++++++++--
 .../apache/tomcat/util/net/SecureNioChannel.java   | 19 ++++++++++++++++
 webapps/docs/changelog.xml                         |  3 +++
 4 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/java/org/apache/tomcat/util/net/LocalStrings.properties 
b/java/org/apache/tomcat/util/net/LocalStrings.properties
index 35c9d890c2..de72354e30 100644
--- a/java/org/apache/tomcat/util/net/LocalStrings.properties
+++ b/java/org/apache/tomcat/util/net/LocalStrings.properties
@@ -26,6 +26,8 @@ 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.foundHttp=Found an plain text HTTP request on what should be 
an encrypted TLS connection
 channel.nio.ssl.handshakeError=Handshake error
+channel.nio.ssl.handshakeWrapPending=There is already handshake data waiting 
to be wrapped
+channel.nio.ssl.handshakeWrapQueueTooLong=The queue of handshake data to be 
wrapped has grown too long
 channel.nio.ssl.incompleteHandshake=Handshake incomplete, you must complete 
handshake before reading data.
 channel.nio.ssl.invalidCloseState=Invalid close state, will not send network 
data.
 channel.nio.ssl.invalidStatus=Unexpected status [{0}].
diff --git a/java/org/apache/tomcat/util/net/SecureNio2Channel.java 
b/java/org/apache/tomcat/util/net/SecureNio2Channel.java
index 076f336bb8..c2167f6683 100644
--- a/java/org/apache/tomcat/util/net/SecureNio2Channel.java
+++ b/java/org/apache/tomcat/util/net/SecureNio2Channel.java
@@ -53,10 +53,12 @@ public class SecureNio2Channel extends Nio2Channel  {
     private static final Log log = LogFactory.getLog(SecureNio2Channel.class);
     private static final StringManager sm = 
StringManager.getManager(SecureNio2Channel.class);
 
-    // Value determined by observation of what the SSL Engine requested in
-    // various scenarios
+    // Value determined by observation of what the SSL Engine requested in 
various scenarios
     private static final int DEFAULT_NET_BUFFER_SIZE = 16921;
 
+    // Much longer than it should ever need to be but short enough to trigger 
connection closure if something goes wrong
+    private static final int HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT = 100;
+
     protected final Nio2Endpoint endpoint;
 
     protected ByteBuffer netInBuffer;
@@ -67,6 +69,7 @@ public class SecureNio2Channel extends Nio2Channel  {
     protected volatile boolean sniComplete = false;
 
     private volatile boolean handshakeComplete = false;
+    private volatile int handshakeWrapQueueLength = 0;
     private volatile HandshakeStatus handshakeStatus; //gets set by handshake
 
     protected boolean closed;
@@ -762,6 +765,11 @@ public class SecureNio2Channel extends Nio2Channel  {
                     //perform any tasks if needed
                     if (unwrap.getHandshakeStatus() == 
HandshakeStatus.NEED_TASK) {
                         tasks();
+                    } else if (unwrap.getHandshakeStatus() == 
HandshakeStatus.NEED_WRAP) {
+                        if (++handshakeWrapQueueLength > 
HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT) {
+                            throw new ExecutionException(
+                                    new 
IOException(sm.getString("channel.nio.ssl.handshakeWrapQueueTooLong")));
+                        }
                     }
                     //if we need more network data, then bail out for now.
                     if (unwrap.getStatus() == Status.BUFFER_UNDERFLOW) {
@@ -892,6 +900,8 @@ public class SecureNio2Channel extends Nio2Channel  {
                 if (!netOutBuffer.hasRemaining()) {
                     netOutBuffer.clear();
                     SSLEngineResult result = sslEngine.wrap(src, netOutBuffer);
+                    // Call to wrap() will have included any required 
handshake data
+                    handshakeWrapQueueLength = 0;
                     written = result.bytesConsumed();
                     netOutBuffer.flip();
                     if (result.getStatus() == Status.OK) {
@@ -957,6 +967,11 @@ public class SecureNio2Channel extends Nio2Channel  {
                                 //perform any tasks if needed
                                 if (unwrap.getHandshakeStatus() == 
HandshakeStatus.NEED_TASK) {
                                     tasks();
+                                } else if (unwrap.getHandshakeStatus() == 
HandshakeStatus.NEED_WRAP) {
+                                    if (++handshakeWrapQueueLength > 
HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT) {
+                                        throw new ExecutionException(new 
IOException(
+                                                
sm.getString("channel.nio.ssl.handshakeWrapQueueTooLong")));
+                                    }
                                 }
                                 //if we need more network data, then bail out 
for now.
                                 if (unwrap.getStatus() == 
Status.BUFFER_UNDERFLOW) {
@@ -1070,6 +1085,11 @@ public class SecureNio2Channel extends Nio2Channel  {
                                 //perform any tasks if needed
                                 if (unwrap.getHandshakeStatus() == 
HandshakeStatus.NEED_TASK) {
                                     tasks();
+                                } else if (unwrap.getHandshakeStatus() == 
HandshakeStatus.NEED_WRAP) {
+                                    if (++handshakeWrapQueueLength > 
HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT) {
+                                        throw new ExecutionException(new 
IOException(
+                                                
sm.getString("channel.nio.ssl.handshakeWrapQueueTooLong")));
+                                    }
                                 }
                                 //if we need more network data, then bail out 
for now.
                                 if (unwrap.getStatus() == 
Status.BUFFER_UNDERFLOW) {
@@ -1179,6 +1199,8 @@ public class SecureNio2Channel extends Nio2Channel  {
             netOutBuffer.clear();
             // Wrap the source data into the internal buffer
             SSLEngineResult result = sslEngine.wrap(src, netOutBuffer);
+            // Call to wrap() will have included any required handshake data
+            handshakeWrapQueueLength = 0;
             final int written = result.bytesConsumed();
             netOutBuffer.flip();
             if (result.getStatus() == Status.OK) {
diff --git a/java/org/apache/tomcat/util/net/SecureNioChannel.java 
b/java/org/apache/tomcat/util/net/SecureNioChannel.java
index f3238f9c99..1ee7e4a50e 100644
--- a/java/org/apache/tomcat/util/net/SecureNioChannel.java
+++ b/java/org/apache/tomcat/util/net/SecureNioChannel.java
@@ -65,6 +65,7 @@ public class SecureNioChannel extends NioChannel {
     protected boolean sniComplete = false;
 
     protected boolean handshakeComplete = false;
+    protected boolean needHandshakeWrap = false;
     protected HandshakeStatus handshakeStatus; //gets set by handshake
 
     protected boolean closed = false;
@@ -622,6 +623,14 @@ public class SecureNioChannel extends NioChannel {
                 //perform any tasks if needed
                 if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
                     tasks();
+                } else if (unwrap.getHandshakeStatus() == 
HandshakeStatus.NEED_WRAP) {
+                    if (getOutboundRemaining() == 0) {
+                        handshakeWrap(true);
+                    } else if (needHandshakeWrap) {
+                        throw new 
IOException(sm.getString("channel.nio.ssl.handshakeWrapPending"));
+                    } else {
+                        needHandshakeWrap = true;
+                    }
                 }
                 //if we need more network data, then bail out for now.
                 if (unwrap.getStatus() == Status.BUFFER_UNDERFLOW) {
@@ -711,6 +720,14 @@ public class SecureNioChannel extends NioChannel {
                 //perform any tasks if needed
                 if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
                     tasks();
+                } else if (unwrap.getHandshakeStatus() == 
HandshakeStatus.NEED_WRAP) {
+                    if (getOutboundRemaining() == 0) {
+                        handshakeWrap(true);
+                    } else if (needHandshakeWrap) {
+                        throw new 
IOException(sm.getString("channel.nio.ssl.handshakeWrapPending"));
+                    } else {
+                        needHandshakeWrap = true;
+                    }
                 }
                 //if we need more network data, then bail out for now.
                 if (unwrap.getStatus() == Status.BUFFER_UNDERFLOW) {
@@ -809,6 +826,8 @@ public class SecureNioChannel extends NioChannel {
             netOutBuffer.clear();
 
             SSLEngineResult result = sslEngine.wrap(src, netOutBuffer);
+            // Call to wrap() will have included any required handshake data
+            needHandshakeWrap = false;
             // The number of bytes written
             int written = result.bytesConsumed();
             netOutBuffer.flip();
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 445c57059c..09da98d76c 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -165,6 +165,9 @@
         Make counting of active HTTP/2 streams per connection more robust.
         (markt)
       </fix>
+      <add>
+        Add support for TLS 1.3 client initiated re-keying. (markt)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Jasper">


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

Reply via email to