Hi Daniel thanks for bringing this up, this sounds like
https://bugs.openjdk.java.net/browse/JDK-8212885. I'm very close to a
fix on this one, just working out a few issues in testing.
--Jamil
On 10/8/2018 2:34 PM, Daniel Christensen wrote:
I have a custom HostnameVerifier that attempts to examine the
certificate chain using SSLSession#getPeerCertificates(). After
upgrading to Java 11, where it seems that TLSv1.3 is used by default,
I am seeing that getPeerCertificates() throws an
SSLPeerUnverifiedException after an HTTP redirect has occurred. If I
force the protocol to TLSv1.2 this does not occur. If there is no
redirect, then this does not occur.
Is this a bug in Java or a change in behavior with TLSv1.3?
The code below demonstrates the problem when 'protocol' is either
'TLS' or 'TLSv1.3' and path is '/redirect'.
doTest("TLSv1.3", "/redirect"); // Fails with SSLPeerUnverifiedException
doTest("TLSv1.3", "/content"); // Succeeds
doTest("TLSv1.2", "/redirect"); // Succeeds
doTest("TLSv1.2", "/content"); // Succeeds
private void doTest(String protocol, String path) throws
IOException, NoSuchAlgorithmException, KeyManagementException
{
whenHttp(server)
.match(get("/redirect"))
.then(status(HttpStatus.MOVED_PERMANENTLY_301),
contentType("text/html"), header("Location", "/content"),
stringContent("redirected"));
whenHttp(server)
.match(get("/content"))
.then(ok(), contentType("text/html"),
stringContent("ok"));
URL url = new URL("https", "localhost", server.getPort(), path);
HttpsURLConnection conn =
(HttpsURLConnection)url.openConnection();
SSLContext ctx = SSLContext.getInstance(protocol);
TrustManager[] tms = {new X509TrustManager()
{
@Override public void checkClientTrusted(X509Certificate[]
chain, String authType){}
@Override public void checkServerTrusted(X509Certificate[]
chain, String authType){}
@Override public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0]; }
}};
ctx.init(null, tms, new SecureRandom());
conn.setSSLSocketFactory(ctx.getSocketFactory());
conn.setHostnameVerifier(new HostnameVerifier()
{
@Override
public boolean verify(String hostname, SSLSession session)
{
java.security.cert.Certificate[] chain = null;
try
{
chain = session.getPeerCertificates();
}
catch (SSLPeerUnverifiedException e)
{
throw new RuntimeException(e);
}
return true;
}
});
int status = conn.getResponseCode();
assertEquals(200, status);
}
Thanks,
Dan
Daniel L. Christensen
Distinguished Engineer
Micro Focus
http://www.microfocus.com