@@ -53,10 +53,12 @@ public class SecureNio2Channel extends Nio2Channel {
5353 private static final Log log = LogFactory .getLog (SecureNio2Channel .class );
5454 private static final StringManager sm = StringManager .getManager (SecureNio2Channel .class );
5555
56- // Value determined by observation of what the SSL Engine requested in
57- // various scenarios
56+ // Value determined by observation of what the SSL Engine requested in various scenarios
5857 private static final int DEFAULT_NET_BUFFER_SIZE = 16921 ;
5958
59+ // Much longer than it should ever need to be but short enough to trigger connection closure if something goes wrong
60+ private static final int HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT = 100 ;
61+
6062 protected final Nio2Endpoint endpoint ;
6163
6264 protected ByteBuffer netInBuffer ;
@@ -67,6 +69,7 @@ public class SecureNio2Channel extends Nio2Channel {
6769 protected volatile boolean sniComplete = false ;
6870
6971 private volatile boolean handshakeComplete = false ;
72+ private volatile int handshakeWrapQueueLength = 0 ;
7073 private volatile HandshakeStatus handshakeStatus ; //gets set by handshake
7174
7275 protected boolean closed ;
@@ -767,6 +770,11 @@ private Integer unwrap(int nRead, long timeout, TimeUnit unit) throws ExecutionE
767770 //perform any tasks if needed
768771 if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_TASK ) {
769772 tasks ();
773+ } else if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_WRAP ) {
774+ if (++handshakeWrapQueueLength > HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT ) {
775+ throw new ExecutionException (
776+ new IOException (sm .getString ("channel.nio.ssl.handshakeWrapQueueTooLong" )));
777+ }
770778 }
771779 //if we need more network data, then bail out for now.
772780 if (unwrap .getStatus () == Status .BUFFER_UNDERFLOW ) {
@@ -897,6 +905,8 @@ protected void wrap() {
897905 if (!netOutBuffer .hasRemaining ()) {
898906 netOutBuffer .clear ();
899907 SSLEngineResult result = sslEngine .wrap (src , netOutBuffer );
908+ // Call to wrap() will have included any required handshake data
909+ handshakeWrapQueueLength = 0 ;
900910 written = result .bytesConsumed ();
901911 netOutBuffer .flip ();
902912 if (result .getStatus () == Status .OK ) {
@@ -962,6 +972,11 @@ public void completed(Integer nBytes, A attach) {
962972 //perform any tasks if needed
963973 if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_TASK ) {
964974 tasks ();
975+ } else if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_WRAP ) {
976+ if (++handshakeWrapQueueLength > HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT ) {
977+ throw new ExecutionException (new IOException (
978+ sm .getString ("channel.nio.ssl.handshakeWrapQueueTooLong" )));
979+ }
965980 }
966981 //if we need more network data, then bail out for now.
967982 if (unwrap .getStatus () == Status .BUFFER_UNDERFLOW ) {
@@ -1075,6 +1090,11 @@ public void completed(Integer nBytes, A attach) {
10751090 //perform any tasks if needed
10761091 if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_TASK ) {
10771092 tasks ();
1093+ } else if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_WRAP ) {
1094+ if (++handshakeWrapQueueLength > HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT ) {
1095+ throw new ExecutionException (new IOException (
1096+ sm .getString ("channel.nio.ssl.handshakeWrapQueueTooLong" )));
1097+ }
10781098 }
10791099 //if we need more network data, then bail out for now.
10801100 if (unwrap .getStatus () == Status .BUFFER_UNDERFLOW ) {
@@ -1184,6 +1204,8 @@ public <A> void write(final ByteBuffer src, final long timeout, final TimeUnit u
11841204 netOutBuffer .clear ();
11851205 // Wrap the source data into the internal buffer
11861206 SSLEngineResult result = sslEngine .wrap (src , netOutBuffer );
1207+ // Call to wrap() will have included any required handshake data
1208+ handshakeWrapQueueLength = 0 ;
11871209 final int written = result .bytesConsumed ();
11881210 netOutBuffer .flip ();
11891211 if (result .getStatus () == Status .OK ) {
0 commit comments