@@ -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 ;
@@ -762,6 +765,11 @@ private Integer unwrap(int nRead, long timeout, TimeUnit unit) throws ExecutionE
762765 //perform any tasks if needed
763766 if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_TASK ) {
764767 tasks ();
768+ } else if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_WRAP ) {
769+ if (++handshakeWrapQueueLength > HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT ) {
770+ throw new ExecutionException (
771+ new IOException (sm .getString ("channel.nio.ssl.handshakeWrapQueueTooLong" )));
772+ }
765773 }
766774 //if we need more network data, then bail out for now.
767775 if (unwrap .getStatus () == Status .BUFFER_UNDERFLOW ) {
@@ -892,6 +900,8 @@ protected void wrap() {
892900 if (!netOutBuffer .hasRemaining ()) {
893901 netOutBuffer .clear ();
894902 SSLEngineResult result = sslEngine .wrap (src , netOutBuffer );
903+ // Call to wrap() will have included any required handshake data
904+ handshakeWrapQueueLength = 0 ;
895905 written = result .bytesConsumed ();
896906 netOutBuffer .flip ();
897907 if (result .getStatus () == Status .OK ) {
@@ -957,6 +967,11 @@ public void completed(Integer nBytes, A attach) {
957967 //perform any tasks if needed
958968 if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_TASK ) {
959969 tasks ();
970+ } else if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_WRAP ) {
971+ if (++handshakeWrapQueueLength > HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT ) {
972+ throw new ExecutionException (new IOException (
973+ sm .getString ("channel.nio.ssl.handshakeWrapQueueTooLong" )));
974+ }
960975 }
961976 //if we need more network data, then bail out for now.
962977 if (unwrap .getStatus () == Status .BUFFER_UNDERFLOW ) {
@@ -1070,6 +1085,11 @@ public void completed(Integer nBytes, A attach) {
10701085 //perform any tasks if needed
10711086 if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_TASK ) {
10721087 tasks ();
1088+ } else if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_WRAP ) {
1089+ if (++handshakeWrapQueueLength > HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT ) {
1090+ throw new ExecutionException (new IOException (
1091+ sm .getString ("channel.nio.ssl.handshakeWrapQueueTooLong" )));
1092+ }
10731093 }
10741094 //if we need more network data, then bail out for now.
10751095 if (unwrap .getStatus () == Status .BUFFER_UNDERFLOW ) {
@@ -1179,6 +1199,8 @@ public <A> void write(final ByteBuffer src, final long timeout, final TimeUnit u
11791199 netOutBuffer .clear ();
11801200 // Wrap the source data into the internal buffer
11811201 SSLEngineResult result = sslEngine .wrap (src , netOutBuffer );
1202+ // Call to wrap() will have included any required handshake data
1203+ handshakeWrapQueueLength = 0 ;
11821204 final int written = result .bytesConsumed ();
11831205 netOutBuffer .flip ();
11841206 if (result .getStatus () == Status .OK ) {
0 commit comments