@@ -54,10 +54,12 @@ public class SecureNio2Channel extends Nio2Channel {
5454 private static final Log log = LogFactory .getLog (SecureNio2Channel .class );
5555 private static final StringManager sm = StringManager .getManager (SecureNio2Channel .class );
5656
57- // Value determined by observation of what the SSL Engine requested in
58- // various scenarios
57+ // Value determined by observation of what the SSL Engine requested in various scenarios
5958 private static final int DEFAULT_NET_BUFFER_SIZE = 16921 ;
6059
60+ // Much longer than it should ever need to be but short enough to trigger connection closure if something goes wrong
61+ private static final int HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT = 100 ;
62+
6163 protected final Nio2Endpoint endpoint ;
6264
6365 protected ByteBuffer netInBuffer ;
@@ -68,6 +70,7 @@ public class SecureNio2Channel extends Nio2Channel {
6870 protected volatile boolean sniComplete = false ;
6971
7072 private volatile boolean handshakeComplete = false ;
73+ private volatile int handshakeWrapQueueLength = 0 ;
7174 private volatile HandshakeStatus handshakeStatus ; //gets set by handshake
7275
7376 protected boolean closed ;
@@ -764,6 +767,11 @@ private Integer unwrap(int nRead, long timeout, TimeUnit unit) throws ExecutionE
764767 //perform any tasks if needed
765768 if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_TASK ) {
766769 tasks ();
770+ } else if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_WRAP ) {
771+ if (++handshakeWrapQueueLength > HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT ) {
772+ throw new ExecutionException (
773+ new IOException (sm .getString ("channel.nio.ssl.handshakeWrapQueueTooLong" )));
774+ }
767775 }
768776 //if we need more network data, then bail out for now.
769777 if (unwrap .getStatus () == Status .BUFFER_UNDERFLOW ) {
@@ -894,6 +902,8 @@ protected void wrap() {
894902 if (!netOutBuffer .hasRemaining ()) {
895903 netOutBuffer .clear ();
896904 SSLEngineResult result = sslEngine .wrap (src , netOutBuffer );
905+ // Call to wrap() will have included any required handshake data
906+ handshakeWrapQueueLength = 0 ;
897907 written = result .bytesConsumed ();
898908 netOutBuffer .flip ();
899909 if (result .getStatus () == Status .OK ) {
@@ -959,6 +969,11 @@ public void completed(Integer nBytes, A attach) {
959969 //perform any tasks if needed
960970 if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_TASK ) {
961971 tasks ();
972+ } else if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_WRAP ) {
973+ if (++handshakeWrapQueueLength > HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT ) {
974+ throw new ExecutionException (new IOException (
975+ sm .getString ("channel.nio.ssl.handshakeWrapQueueTooLong" )));
976+ }
962977 }
963978 //if we need more network data, then bail out for now.
964979 if (unwrap .getStatus () == Status .BUFFER_UNDERFLOW ) {
@@ -1072,6 +1087,11 @@ public void completed(Integer nBytes, A attach) {
10721087 //perform any tasks if needed
10731088 if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_TASK ) {
10741089 tasks ();
1090+ } else if (unwrap .getHandshakeStatus () == HandshakeStatus .NEED_WRAP ) {
1091+ if (++handshakeWrapQueueLength > HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT ) {
1092+ throw new ExecutionException (new IOException (
1093+ sm .getString ("channel.nio.ssl.handshakeWrapQueueTooLong" )));
1094+ }
10751095 }
10761096 //if we need more network data, then bail out for now.
10771097 if (unwrap .getStatus () == Status .BUFFER_UNDERFLOW ) {
@@ -1181,6 +1201,8 @@ public <A> void write(final ByteBuffer src, final long timeout, final TimeUnit u
11811201 netOutBuffer .clear ();
11821202 // Wrap the source data into the internal buffer
11831203 SSLEngineResult result = sslEngine .wrap (src , netOutBuffer );
1204+ // Call to wrap() will have included any required handshake data
1205+ handshakeWrapQueueLength = 0 ;
11841206 final int written = result .bytesConsumed ();
11851207 netOutBuffer .flip ();
11861208 if (result .getStatus () == Status .OK ) {
0 commit comments