javasslcertificatecertificate-store

which cacert is in use?


I have an example command-line java application from a vendor; it depends on SSL authentication. I have the vendor's certificate(s), I can see them in my java 7 cacerts file (windows, c:\program files\java\jdk1.7.0_07\jre\lib\security\cacerts). If I open the java 8 cacerts file, they are not there (c:\program files\java\jre1.8.0_66\lib\security\cacerts)

If I set a path so that java 8 is first, the program works. If I change the path so that java 7 is first, the program fails with a certification error:

C:\project\tryCerts\Demo2>path=c:\program files\java\jdk1.7.0_07\bin;c:\program files\java\jre1.8.0_66\bin


C:\project\tryCerts\Demo2>java -jar vendorCmd.jar user1 password2 environment3
Dec 22, 2015 11:11:35 AM [com.sun.xml.ws.policy.jaxws.PolicyConfigParser]  parse
INFO: WSP5018: Loaded WSIT configuration from file: jar:file:/C:/project/tryCerts/Demo2/vendorCmd/dist/vendorCmd.jar!/META-INF/wsit-client.xml.
Unable to log in: com.sun.xml.ws.client.ClientTransportException: HTTP transport error: javax.net.ssl.SSLHandshakeException: sun.security.validator.Va
lidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to re
quested target

C:\project\tryCerts\Demo2>path=c:\program files\java\jre1.8.0_66\bin;c:\program files\java\jdk1.7.0_07\bin

C:\project\tryCerts\Demo2>java -jar vendorCmd.jar acc03\acc03_ws_user accwbS3rv!ceS acc03_p_production
Dec 22, 2015 11:21:34 AM [com.sun.xml.ws.policy.jaxws.PolicyConfigParser]  parse
INFO: WSP5018: Loaded WSIT configuration from file: jar:file:/C:/project/tryCerts/Demo2/vendorCmd/dist/vendorCmd.jar!/META-INF/wsit-client.xml.
logged in
Dec 22, 2015 11:21:35 AM [com.sun.xml.ws.policy.jaxws.PolicyConfigParser]  parse
INFO: WSP5018: Loaded WSIT configuration from file: jar:file:/C:/project/tryCerts/Demo2/vendorCmd/dist/vendorCmd.jar!/META-INF/wsit-client.xml.
Signed Info:org.jcp.xml.dsig.internal.dom.DOMSignedInfo@3f071328
AccountNumber: 279105/ Firstname: null/ LastName: null
AccountNumber: 1005118/ Firstname: null/ LastName: COMPANY1
AccountNumber: 2102765/ Firstname: null/ LastName: COMPANY2
AccountNumber: 2101373/ Firstname: null/ LastName: COMPANY3
AccountNumber: 2119664/ Firstname: null/ LastName: COMPANY4
AccountNumber: 2119668/ Firstname: null/ LastName: ET CETERA

C:\project\tryCerts\Demo2>dir/s cacerts
 Volume in drive C is OS
 Volume Serial Number is 9896-211D
File Not Found

C:\project\tryCerts\Demo2>

This is exactly opposite from what I was expecting -- it is the cacerts file in the java 7 folders that has the vendor certificate chain, and java 8 that does not have it. Yet running the program on Java 7 fails with a certification error, and running it with 8 succeeds.

Can anyone tell me what I should look for to explain this?


Solution

  • To determine the trust store that's being used, without having to resort to tools like strace (linux) and process explorer (windows), you can pass the debug flag -Djavax.net.debug=trustmanager to the java command line, which dumps all the ssl related debug information (I mentioned all in the original comment, but that adds even more noise to the output):

    java -Djavax.net.debug=trustmanager -jar vendorCmd.jar user1 password2 environment3
    

    In the first few lines of the debug output, will be a line:

    trustStore is: <path to>cacerts
    

    this indicates the trust store that's being used.

    Adding the ssl option (trustmanager,ssl) , it also dumps all the trusted certs that are being added to the list of certs that are considered trusted by the JVM. This can be used to verify that the certs you think are in the trust store are actually in the trust store - in this case you should be able to see the vendor's certs in the list.

    A full list of the debug options for javax.net.debug are detailed in the JSSE reference guide. You can use =help to get a relatively short usage message for the flags

    Sample code & test run:

    import java.net.URL;
    import java.io.BufferedInputStream;
    
    public class pull_url {
        public static void main(String args[]) throws Exception {
            for (String arg : args) {
                downloadUsingUrl(arg);
            }
        }
    
        public static void downloadUsingUrl(String stringurl) throws Exception {
            URL url = new URL(stringurl);
            BufferedInputStream bis = new BufferedInputStream(url.openStream());
            bis.close();
        }
    }
    

    Output from a run:

    $ java -Djavax.net.debug=trustmanager pull_url https://google.com/
    javax.net.ssl|DEBUG|10|main|2023-05-06 13:40:20.584 IST|TrustStoreManager.java:162|Inaccessible trust store: /Users/anysh/Library/Java/JavaVirtualMachines/jdk-19.0.1.jdk/Contents/Home/lib/security/jssecacerts
    javax.net.ssl|DEBUG|10|main|2023-05-06 13:40:20.595 IST|TrustStoreManager.java:113|trustStore is: /Users/anysh/Library/Java/JavaVirtualMachines/jdk-19.0.1.jdk/Contents/Home/lib/security/cacerts
    trustStore type is: pkcs12
    trustStore provider is:
    the last modified time is: Wed Sep 14 17:16:16 IST 2022
    javax.net.ssl|DEBUG|10|main|2023-05-06 13:40:20.595 IST|TrustStoreManager.java:334|Reload the trust store
    javax.net.ssl|DEBUG|10|main|2023-05-06 13:40:20.620 IST|TrustStoreManager.java:342|Reload trust certs
    javax.net.ssl|DEBUG|10|main|2023-05-06 13:40:20.620 IST|TrustStoreManager.java:347|Reloaded 89 trust certs
    

    In this case, the second line indicates the cacerts file that's being used.