2

I am getting the well known PKIX path building failed exception, and to find the underlying cause i have to enable java.security.debug=certpath and look at the logs. In my case the cause is

certpath: SunCertPathBuilder.depthFirstSearchForward(): final verification failed: java.security.cert.CertPathValidatorException: Certificate does not specify OCSP responder

but my problem is that I cannot get to the above underlying cause programmatically because the exception thrown(see below) is in the sun.security.validator package which I cannot import and even if I could I am not sure it contains any references to the underlying cause (please correct me if I am wrong)

I am using Java 17

The relevant code is:

PKIXBuilderParameters params = new PKIXBuilderParameters(trustAnchors, null);
params.addCertStore(intermediateCAcertStore);
params.addCertPathChecker((PKIXCertPathChecker) CertPathValidator.getInstance("PKIX").getRevocationChecker());

TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
tmf.init(new CertPathTrustManagerParameters(params));
X509TrustManager tm = (X509TrustManager) tmf.getTrustManagers()[0];
tm.checkClientTrusted(new X509Certificate[]{ targetCert }), "RSA");

which throws:

Exception in thread "main" sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
  at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
  at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
  at java.base/sun.security.validator.Validator.validate(Validator.java:264)
  at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:242)
  at java.base/sun.security.ssl.X509TrustManagerImpl.checkClientTrusted(X509TrustManagerImpl.java:107)
  at com.example.TrustManagerTest.test1(TrustManagerTest.java:98)
  at com.example.TrustManagerTest.main(TrustManagerTest.java:54)
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
  at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
  at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
  at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
  at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
... 6 more

so no way for me to see that the real cause is the OCSP check, unless i enable security debugging and search in the logs. But I want to programmatically discover it and maybe handle it, or at least somehow get hold of the

java.security.cert.CertPathValidatorException: Certificate does not specify OCSP responder

message and display it.

Any suggestions?

Paralife
  • 6,116
  • 8
  • 38
  • 64

1 Answers1

0

sun.security.validator.ValidatorException exception does not provide direct access to the CertPathValidatorException or its message.

However, you can catch the ValidatorException and inspect its cause to see if it is a CertPathBuilderException. If it is, you can then catch its cause and check if it is a CertPathValidatorException. If it is, you can then access its message using the getMessage() method.

try {
    // your code that throws the ValidatorException
} catch (ValidatorException e) {
    Throwable cause = e.getCause();
    if (cause instanceof CertPathBuilderException) {
        CertPathBuilderException cpbe = (CertPathBuilderException) cause;
        Throwable cpbeCause = cpbe.getCause();
        if (cpbeCause instanceof CertPathValidatorException) {
            CertPathValidatorException cpve = (CertPathValidatorException) cpbeCause;
            String message = cpve.getMessage();
            // handle or display the message here
        }
    }
}

catching the exception and inspecting its cause may not be the most elegant solution, but it should allow you to access the underlying CertPathValidatorException message that you are interested

Pushpendra Kumar
  • 1,721
  • 1
  • 15
  • 21
  • 1
    This will not provide the ValidatorException that has internally been thrown because it is thrown by a path validator that is called by a path builder. the path builder does not throw while building, because it does a DFS to find a cert path and validates at the same time, so if something is wrong while searching, it is stored in the Vertexes, but never exposed, only shown in debug, because it may backtrack and find another path. If it threw all the way, the DFS would stop and would not be complete. At least this is my take from looking at the implementation – Paralife May 09 '23 at 20:08
  • I think the best way would be for the builder, if it didnt find a path, to expose the last path tried somehow. Also when the validation problem is on the root of the path,[that is the end entity cert, since if does forward building], it should also expose the validation exceptions, since the end entity cert is contained in every possible path. But all the above need custom implementation, and I am not up to it. I am starting to think, there is no clean solution... – Paralife May 09 '23 at 20:20