0

There is a ton of examples on how to ignore SSL certificates using Apache HTTPClient; I created a client along the lines of this SO answer. So far so good. Problem is, when a certificate is invalid, the client blindly accepts it, just like I told it too. But I don't want to quietly accept it; I'd like to log a warning of some sort letting me know that an invalid certificate was accepted.

Is there any way to do this?

P.S.: This is for internal tooling, not prod code. I understand and accept the risks of ignoring the certs so, please, don't start a "holier than thou" lecture.

Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219

1 Answers1

0

It is just a simple matter of decorating X509TrustManager instances passed to the SSLContext#init method

static class TrustManagerDelegate implements X509TrustManager {

    private final X509TrustManager trustManager;

    TrustManagerDelegate(final X509TrustManager trustManager) {
        super();
        this.trustManager = trustManager;
    }

    @Override
    public void checkClientTrusted(
            final X509Certificate[] chain, final String authType) throws CertificateException {
        trustManager.checkClientTrusted(chain, authType);
    }

    @Override
    public void checkServerTrusted(
            final X509Certificate[] chain, final String authType) {
        try {
            trustManager.checkServerTrusted(chain, authType);
        } catch (CertificateException ex) {
            // Implement proper logging;
            System.out.println(chain[0]);
            ex.printStackTrace(System.out);
        }
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return trustManager.getAcceptedIssuers();
    }

}

...

TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmfactory.init((KeyStore) null);
final TrustManager[] tms = tmfactory.getTrustManagers();
if (tms != null) {
    for (int i = 0; i < tms.length; i++) {
        final TrustManager tm = tms[i];
        if (tm instanceof X509TrustManager) {
            tms[i] = new TrustManagerDelegate((X509TrustManager) tm);
        }
    }
}
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tms, null);

CloseableHttpClient client = HttpClientBuilder.create()
        .setSSLContext(sslContext)
        .build();
ok2c
  • 26,450
  • 5
  • 63
  • 71
  • Turns out the `CertificateException` is pretty useless in telling me the domain name that failed. I ended up doing [this](https://stackoverflow.com/a/45091939/839733) – Abhijit Sarkar Jul 13 '17 at 22:38