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: [email protected]
For additional commands, e-mail: [email protected]