Author: markt Date: Thu Oct 11 20:25:42 2018 New Revision: 1843601 URL: http://svn.apache.org/viewvc?rev=1843601&view=rev Log: Fix server initiated TLS renegotiation to obtain a client certificate when using NIO/NIO2 and the OpenSSL backed JSSE TLS implementation with TLSv1.3.
Modified: tomcat/trunk/java/org/apache/tomcat/jni/SSL.java tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/tomcat/jni/SSL.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/jni/SSL.java?rev=1843601&r1=1843600&r2=1843601&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/jni/SSL.java (original) +++ tomcat/trunk/java/org/apache/tomcat/jni/SSL.java Thu Oct 11 20:25:42 2018 @@ -564,6 +564,20 @@ public final class SSL { public static native int renegotiatePending(long ssl); /** + * SSL_verify_client_post_handshake + * @param ssl the SSL instance (SSL *) + * @return the operation status + */ + public static native int verifyClientPostHandshake(long ssl); + + /** + * Is post handshake authentication in progress on this connection? + * @param ssl the SSL instance (SSL *) + * @return the operation status + */ + public static native int getPostHandshakeAuthInProgress(long ssl); + + /** * SSL_in_init. * @param ssl the SSL instance (SSL *) * @return the status Modified: tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java?rev=1843601&r1=1843600&r2=1843601&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java Thu Oct 11 20:25:42 2018 @@ -908,7 +908,12 @@ public final class OpenSSLEngine extends private synchronized void renegotiate() throws SSLException { clearLastError(); - int code = SSL.renegotiate(ssl); + int code; + if (SSL.getVersion(ssl).equals(Constants.SSL_PROTO_TLSv1_3)) { + code = SSL.verifyClientPostHandshake(ssl); + } else { + code = SSL.renegotiate(ssl); + } if (code <= 0) { checkLastError(); } @@ -979,10 +984,42 @@ public final class OpenSSLEngine extends return SSLEngineResult.HandshakeStatus.NEED_WRAP; } + /* + * Tomcat Native stores a count of the completed handshakes in the + * SSL instance and increments it every time a handshake is + * completed. Comparing the handshake count when the handshake + * started to the current handshake count enables this code to + * detect when the handshake has completed. + * + * Obtaining client certificates after the connection has been + * established requires additional checks. We need to trigger + * additional reads until the certificates have been read but we + * don't know how many reads we will need as it depends on both + * client and network behaviour. + * + * The additional reads are triggered by returning NEED_UNWRAP + * rather than FINISHED. This allows the standard I/O code to be + * used. + * + * For TLSv1.2 and below, the handshake completes before the + * renegotiation. We therefore use SSL.renegotiatePending() to + * check on the current status of the renegotiation and return + * NEED_UNWRAP until it completes which means the client + * certificates will have been read from the client. + * + * For TLSv1.3, Tomcat Native sets a flag when post handshake + * authentication is started and updates it once the client + * certificate has been received. We therefore use + * SSL.getPostHandshakeAuthInProgress() to check the current status + * and return NEED_UNWRAP until that methods indicates that PHA is + * no longer in progress. + */ + // No pending data to be sent to the peer // Check to see if we have finished handshaking int handshakeCount = SSL.getHandshakeCount(ssl); - if (handshakeCount != currentHandshake && SSL.renegotiatePending(ssl) == 0) { + if (handshakeCount != currentHandshake && SSL.renegotiatePending(ssl) == 0 && + (SSL.getPostHandshakeAuthInProgress(ssl) == 0)) { if (alpn) { selectedProtocol = SSL.getAlpnSelected(ssl); if (selectedProtocol == null) { @@ -994,7 +1031,8 @@ public final class OpenSSLEngine extends return SSLEngineResult.HandshakeStatus.FINISHED; } - // No pending data and still handshaking / renegotiation pending + // No pending data + // Still handshaking / renegotiation / post-handshake auth pending // Must be waiting on the peer to send more data return SSLEngineResult.HandshakeStatus.NEED_UNWRAP; } Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1843601&r1=1843600&r2=1843601&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Thu Oct 11 20:25:42 2018 @@ -119,8 +119,9 @@ Orr. (markt) </fix> <add> - <bug>62748</bug>: Add TLS 1.3 support for the Tomcat Native connector. - (schultz/markt) + <bug>62748</bug>: Add TLS 1.3 support for the APR/Native connector and + the NIO/NIO2 connector when using the OpenSSL backed JSSE + implementation. (schultz/markt) </add> <fix> <bug>62791</bug>: Remove an unnecessary check in the NIO TLS --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org