3

!Note. This is not for production environment and I fully understand that.

Currently we use org.apache.httpcomponents HttpClient where we have this possibility for "easier" modification. We modify like so:

    // Remove certificate validation
    TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;

    SSLContext sslContext = SSLContexts.custom()
            .loadTrustMaterial(null, acceptingTrustStrategy).build();

    HttpClientBuilder builder = HttpClients.custom();
    builder.setSSLHostnameVerifier(new NoopHostnameVerifier()); // Remove Host validation
    builder.setSSLContext(sslContext);

    CloseableHttpClient httpClient = builder.build();

However, I would like to move to standard Java 11 HttpClient. I have read Java Secure Socket Extension (JSSE) Reference Guide but it is still unclear for me how to modify SSLContext. So far I have:

    // Remove certificate validation
    SSLContext sslContext = null;

    TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                @Override
                public void checkClientTrusted(
                        java.security.cert.X509Certificate[] certs, String authType) {
                }

                @Override
                public void checkServerTrusted(
                        java.security.cert.X509Certificate[] certs, String authType) {
                }
            }
    };

    try {
        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustAllCerts, new SecureRandom());
    } catch (NoSuchAlgorithmException | KeyManagementException e) {
        e.printStackTrace();
    }

I think this essentially solves my first problem - trusting all certificates. However, how can I turn off hostname verification? Looking deeper into apache source code, I can only modify hostname verifier in SSLConnectionSocketFactory which is part of SSLContext. Does that mean I should create new SSLConnectionSocketFactory and assign HostnameVerifier like so:

        final String[] supportedProtocols = System.getProperty("https.protocols").split(",");
        final String[] supportedCipherSuites = System.getProperty("https.cipherSuites").split(",");
        var sslSocketFactoryCopy = new SSLConnectionSocketFactory(
                sslContext, supportedProtocols, supportedCipherSuites, new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });

But how do I assign it to SSLContext? For any part of the code, if you have better suggestions - please don't hesistate.

Edit. To modify HttpClient sslContext:

HttpClient.newBuilder()
            .sslContext(sslcontext)
            .build();
Mr.Robot
  • 397
  • 8
  • 21
  • 2
    Looks like the only way to disable hostname verification is [to set a (seemingly internal) system property](https://stackoverflow.com/a/52995420/6395627). – Slaw Oct 23 '19 at 15:45

0 Answers0