2

I need to ignore the PKIX path building exception

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderExc
ption: unable to find valid certification path to requested target

I know how to do this by writing my own class implementing X509TrustManager where I always return true from isServerTrusted.

But this is rather broad. My code is going to be a part of bigger project. I don't want everything else to be affected by my replacement of the trust manager.

I am always going to connect to a fixed domain name i.e. "www.myws.com". I want to only ignore the SSLHandshakeException only for connections to "www.myws.com".

Is something like this possible?

user93353
  • 13,733
  • 8
  • 60
  • 122
  • possible duplicate of [Implementing X509TrustManager - passing on part of the verification to existing verifier](http://stackoverflow.com/questions/19005318/implementing-x509trustmanager-passing-on-part-of-the-verification-to-existing) – Bruno Sep 25 '13 at 13:16
  • This is *very* similar to your other question, but seems to focus more on how to set the trust manager for a particular connection. Which libraries are you using? – Bruno Sep 25 '13 at 13:18
  • @Bruno It's similar to my other question. But surely not a duplicate. Approaching the same problem from 2 diff angles. SSL exception is thrown when the domain name doesn't match Subject in Cert. Here I am trying to filter based on Domain Name, there I am trying to filter based on Subject. There is little chance that the answers to 2 questions is going to be the same because I don't think the TrustMananger gets the domain name of the server at all. I would think the domain name comparison would happen before (or after) the TrustManager is asked to verify if the Cert is signed by a trusted CA. – user93353 Sep 25 '13 at 15:13
  • Fair enough. It's virtually impossible to answer your question without more details about how much control you have over that client code and which libraries are in use. – Bruno Sep 25 '13 at 15:49
  • 1
    To clarify, you can't 'ignore SSLHandshakeException'. It is fatal to the connection. But you can prevent it from happening. – user207421 Sep 25 '13 at 18:27

1 Answers1

1

There is little chance that the answers to 2 questions is going to be the same because I don't think the TrustMananger gets the domain name of the server at all.

Actually, the trust manager can get the name of the host name you were after. It depends on a number of factors though.

  • Let's just assume your clients are running on Java 7.

    If you follow the same method as in this other answer but use an X509ExtendedTrustManager (introduced in Java 7, as opposed to a plain X509TrustManager), you'll get additional overloaded methods that give you the current SSLSocket or SSLEngine as well.

    The SSLContext makes use of these methods when initialised with an X509ExtendedTrustManager instance, but not when it's a plain X509TrustManager, so it must be checking the type before making those calls (see quick test at the end of this answer, base on the code in that answer).

    I'm not sure where this behaviour is specified the API. There doesn't seem to be anything about this X509ExtendedTrustManager type-check in the JSSE Reference Guide. One way of making sure the extended methods are used would be to set an enpoint identification algorithm (like HTTPS) in your SSLParameters, but you'd need some degree of control of the client code and the libraries it uses. (This is also a feature introduced in Java 7.)

    From the SSLSocket or SSLEngine obtained there, you can get the SSLSession and the peer host, so you could perform checks there. (Note that the host name may not quite match what was intended if the library creating the SSLSocket or SSLEngine didn't use one of the method that passes that name as a String, but passed an InetAddress instead. You'll also lose SNI in this case.)

    You could then use such a trust manager in your default SSLContext (with setDefault(...)).

  • If you don't want to affect the default SSLContext (a sensible choice for these kind of tweaking), you'll need to figure out how your client library can use a different one per connection. This depends entirely on what's used.

    For a traditional URLConnection, cast it as an HttpsURLConnection and set is SSLSocketFactory as one build from your custom SSLContext.


Which methods are used will depend on whether you've instantiated an X509ExtendedTrustManager or a X509TrustManager:

X509TrustManager customTm = new X509ExtendedTrustManager() {
    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return finalTm.getAcceptedIssuers();
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain,
            String authType) throws CertificateException {
        System.out
                .println("Current method: checkServerTrusted(chain, authType)");
        finalTm.checkServerTrusted(chain, authType);
    }

    //@Override
    public void checkServerTrusted(X509Certificate[] chain,
            String authType, Socket socket) throws CertificateException {
        System.out
                .println("Current method: checkServerTrusted(chain, authType, socket)");
        finalTm.checkServerTrusted(chain, authType, socket);
    }

    //@Override
    public void checkServerTrusted(X509Certificate[] chain,
            String authType, SSLEngine engine)
            throws CertificateException {
        System.out
                .println("Current method: checkServerTrusted(chain, authType, engine)");
        finalTm.checkServerTrusted(chain, authType, engine);
    }

    // Same for client-related methods.
};
Community
  • 1
  • 1
Bruno
  • 119,590
  • 31
  • 270
  • 376