ADDITIONAL SYSTEM INFORMATION :
Observed on 64-bit Linux with both Oracle and OpenJDk builds
openjdk version "11-ea" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11-ea+24)
OpenJDK 64-Bit Server VM 18.9 (build 11-ea+24, mixed mode)
java version "11-ea" 2018-09-25
Java(TM) SE Runtime Environment 18.9 (build 11-ea+24)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11-ea+24, mixed mode)
Linux study04 4.15.0-29-generic #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
Failure observed while running Apache Tomcat trunk test suite with Java 11 EA 24. Failure not observed with Java 10.0.2
Relevant configuration details:
- Server
- TLSv1, TLSv1.2, SSLv2Hello, TLSv1.1
- Want client authentication
- Client
- Default protocols (includes TLSv1.3)
- Will send client cert if requested
The test proceeds as follows:
- TLS connection established to server. No client cert auth since client does not send cert.
- Client makes HTTP request to endpoint that does not require authentication
- Server responds
- Client makes HTTP request to endpoint that DOES require authentication
- Server starts renegotiation
- Client fails to process the "request hello" message
The failure occurs in sun.security.ssl.SSLHandshake.getHandshakeConsumer()
The message is correctly identified as a 'hello request' and the consumer is set to SSLHandshake.HELLO_REQUEST at line 432 of HandshakeContext.
Execution proceeds to line 445 of HandshakeContext
Execution proceeds to line 388 of SSLHandshake
At line 405 of SSLHandshake hc.negotiatedProtocol is null so protocol version is updated to hc.maximumActiveProtocol which is now TLS13.
The for loops at lines 412-419 fail to find a matching consumer because SSLHandshake.HELLO_REQUEST only supports TLS12 and below.
A null SSLConsumer is returned and the connection fails due to the unrecognised message.
The full stack trace at the client is:
javax.net.ssl.SSLProtocolException: Unsupported handshake message: hello_request
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:126)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:325)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:268)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:447)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:422)
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:178)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:880)
at java.base/sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:852)
at java.base/sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:602)
at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:252)
at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:292)
at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:351)
at java.base/sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:746)
at java.base/sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:689)
at java.base/sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:717)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1604)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1509)
at java.base/java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:527)
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:329)
at org.apache.catalina.startup.TomcatBaseTest.methodUrl(TomcatBaseTest.java:690)
at org.apache.catalina.startup.TomcatBaseTest.methodUrl(TomcatBaseTest.java:663)
at org.apache.catalina.startup.TomcatBaseTest.getUrl(TomcatBaseTest.java:657)
at org.apache.catalina.startup.TomcatBaseTest.getUrl(TomcatBaseTest.java:651)
at org.apache.catalina.startup.TomcatBaseTest.getUrl(TomcatBaseTest.java:636)
at org.apache.catalina.startup.TomcatBaseTest.getUrl(TomcatBaseTest.java:630)
at org.apache.tomcat.util.net.TestClientCert.doTestClientCertGet(TestClientCert.java:84)
at org.apache.tomcat.util.net.TestClientCert.testClientCertGetWithoutPreemptive(TestClientCert.java:39)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: java.lang.UnsupportedOperationException: Unsupported handshake consumer: hello_request
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:445)
... 53 more
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Tomcat source code:
http://svn.apache.org/repos/asf/tomcat/trunk/
or
https://github.com/apache/tomcat
Run this test:
org.apache.tomcat.util.net.TestClientCert.testClientCertGetWithoutPreemptive
Adding the following properties to build.properties will limit the test suite to this single test:
test.entry=org.apache.tomcat.util.net.TestClientCert
test.entry.methods=testClientCertGetWithoutPreemptive
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The renegotiation succeeds and the test passes.
ACTUAL -
The renegotiation fails and the test fails.
---------- BEGIN SOURCE ----------
See steps to reproduce
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Disable TLSv1.3 support in the client. e.g. with:
System.setProperty("https.protocols", "TLSv1.1,TLSv1.2")
FREQUENCY : always