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
<<attachment: Daniel_Christensen.vcf>>
