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


Reply via email to