Author: remm Date: Tue Feb 2 17:46:17 2016 New Revision: 1728162 URL: http://svn.apache.org/viewvc?rev=1728162&view=rev Log: Port Mark's patch to NIO2 in places where it can be useful, also add a separate log message for the resize failure.
Modified: 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/changelog.xml 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=1728162&r1=1728161&r2=1728162&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties Tue Feb 2 17:46:17 2016 @@ -97,6 +97,7 @@ channel.nio.ssl.remainingDataDuringClose channel.nio.ssl.pendingWriteDuringClose=Pending write, so remaining data in the network buffer, can't send SSL close message, force a close with close(true) instead channel.nio.ssl.invalidCloseState=Invalid close state, will not send network data. channel.nio.ssl.unwrapFail=Unable to unwrap data, invalid status [{0}] +channel.nio.ssl.unwrapFailResize=Unable to unwrap data because buffer is too small, invalid status [{0}] channel.nio.ssl.wrapException=Handshake failed during wrap channel.nio.ssl.wrapFail=Unable to wrap data, invalid status [{0}] channel.nio.ssl.incompleteHandshake=Handshake incomplete, you must complete handshake before reading data. 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=1728162&r1=1728161&r2=1728162&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java Tue Feb 2 17:46:17 2016 @@ -573,7 +573,7 @@ public class SecureNio2Channel extends N } private class FutureRead implements Future<Integer> { - private final ByteBuffer dst; + private ByteBuffer dst; private Future<Integer> integer; private FutureRead(ByteBuffer dst) { this.dst = dst; @@ -652,17 +652,31 @@ public class SecureNio2Channel extends N break; } } - } else if (unwrap.getStatus() == Status.BUFFER_OVERFLOW && read > 0) { - //buffer overflow can happen, if we have read data, then - //empty out the dst buffer before we do another read - break; + } else if (unwrap.getStatus() == Status.BUFFER_OVERFLOW) { + if (read > 0) { + // Buffer overflow can happen if we have read data. Return + // so the destination buffer can be emptied before another + // read is attempted + break; + } else { + // The SSL session has increased the required buffer size + // since the buffer was created. + if (dst == socket.getSocketBufferHandler().getReadBuffer()) { + // This is the normal case for this code + socket.getSocketBufferHandler().expand( + sslEngine.getSession().getApplicationBufferSize()); + dst = socket.getSocketBufferHandler().getReadBuffer(); + } else { + // Can't expand the buffer as there is no way to signal + // to the caller that the buffer has been replaced. + throw new ExecutionException(new IOException(sm.getString("channel.nio.ssl.unwrapFailResize", unwrap.getStatus()))); + } + } } else { - //here we should trap BUFFER_OVERFLOW and call expand on the buffer - //for now, throw an exception, as we initialized the buffers - //in the constructor + // Something else went wrong throw new ExecutionException(new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus()))); } - } while ((netInBuffer.position() != 0)); //continue to unwrapping as long as the input buffer has stuff + } while (netInBuffer.position() != 0); //continue to unwrapping as long as the input buffer has stuff if (!dst.hasRemaining()) { unwrapBeforeRead = true; } else { @@ -796,6 +810,7 @@ public class SecureNio2Channel extends N failed(new EOFException(), attach); } else { try { + ByteBuffer dst2 = dst; //the data read int read = 0; //the SSL engine result @@ -804,7 +819,7 @@ public class SecureNio2Channel extends N //prepare the buffer netInBuffer.flip(); //unwrap the data - unwrap = sslEngine.unwrap(netInBuffer, dst); + unwrap = sslEngine.unwrap(netInBuffer, dst2); //compact the buffer netInBuffer.compact(); if (unwrap.getStatus() == Status.OK || unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { @@ -822,19 +837,34 @@ public class SecureNio2Channel extends N break; } } - } else if (unwrap.getStatus() == Status.BUFFER_OVERFLOW && read > 0) { - //buffer overflow can happen, if we have read data, then - //empty out the dst buffer before we do another read - break; + } else if (unwrap.getStatus() == Status.BUFFER_OVERFLOW) { + if (read > 0) { + // Buffer overflow can happen if we have read data. Return + // so the destination buffer can be emptied before another + // read is attempted + break; + } else { + // The SSL session has increased the required buffer size + // since the buffer was created. + if (dst2 == socket.getSocketBufferHandler().getReadBuffer()) { + // This is the normal case for this code + socket.getSocketBufferHandler().expand( + sslEngine.getSession().getApplicationBufferSize()); + dst2 = socket.getSocketBufferHandler().getReadBuffer(); + } else { + // Can't expand the buffer as there is no way to signal + // to the caller that the buffer has been replaced. + throw new IOException( + sm.getString("channel.nio.ssl.unwrapFailResize", unwrap.getStatus())); + } + } } else { - //here we should trap BUFFER_OVERFLOW and call expand on the buffer - //for now, throw an exception, as we initialized the buffers - //in the constructor + // Something else went wrong throw new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus())); } // continue to unwrap as long as the input buffer has stuff } while (netInBuffer.position() != 0); - if (!dst.hasRemaining()) { + if (!dst2.hasRemaining()) { unwrapBeforeRead = true; } else { unwrapBeforeRead = false; @@ -915,7 +945,7 @@ public class SecureNio2Channel extends N //in the constructor throw new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus())); } - } while ((netInBuffer.position() != 0)); //continue to unwrapping as long as the input buffer has stuff + } while (netInBuffer.position() != 0); //continue to unwrapping as long as the input buffer has stuff int capacity = 0; final int endOffset = offset + length; for (int i = offset; i < endOffset; i++) { 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=1728162&r1=1728161&r2=1728162&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java Tue Feb 2 17:46:17 2016 @@ -576,7 +576,7 @@ public class SecureNioChannel extends Ni // Can't expand the buffer as there is no way to signal // to the caller that the buffer has been replaced. throw new IOException( - sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus())); + sm.getString("channel.nio.ssl.unwrapFailResize", unwrap.getStatus())); } } } else { Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1728162&r1=1728161&r2=1728162&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Tue Feb 2 17:46:17 2016 @@ -45,6 +45,14 @@ issues do not "pop up" wrt. others). --> <section name="Tomcat 9.0.0.M4" rtext="In development"> + <subsection name="Coyote"> + <changelog> + <fix> + Handle the case in the NIO2 connector where the required TLS buffer + sizes increase after the connection has been initiated. (markt/remm) + </fix> + </changelog> + </subsection> <subsection name="WebSocket"> <changelog> <fix> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org