# Why do I need to add intermediate CA certificates to JVM's cacerts file?

My company uses its own PKI. The web browser which I use to access to code repository shows a certificate chain as follows:

Company Root CA
Company Issuing CA Intranet Server
Certificate to the code repository that I want to access


sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target


error.

Gradle uses JVM. I have exported the "Company Root CA" certificate and added it to the certificate store of the JVM with the following command:

"%JAVA_HOME%\bin\keytool.exe" -import -alias company_root_cacert -file "C:\path\to\company\root\cacert.cer" -keystore "%JAVA_HOME%\jre\lib\security\cacerts" -storepass changeit


However, this did not solve the issue. I additionally exported the "Company Issuing CA Intranet Server" certificate and added it to the certificate store of the JVM with the following command:

"%JAVA_HOME%\bin\keytool.exe" -import -alias company_intermediate_cacert -file "C:\path\to\company\intermediate\cacert.cer" -keystore "%JAVA_HOME%\jre\lib\security\cacerts" -storepass changeit


This has solved the issue.

My question is, why was the second step necessary? Since the "Company Issuing CA Intranet Server" is signed by "Company Root CA", and since I have "Company Root CA" in the list of certificates trusted by JVM, why did I need to additionally add the "Company Issuing CA Intranet Server" certificate to the certificate store of JVM?

The problem you describe happens usually if the server only sends its leaf certificate and does not add all the chain certificates needed to build the trust chain to the root CA. Unfortunately this is a common misconfiguration of servers.

Many desktop browser work around this problem if they already know the missing chain certificate from earlier visits or maybe download the missing certificate if the leaf certificate contains a URL for CA issuers in authority information access. But this behavior is usually restricted to desktop browsers and other tools simply fail because they cannot build the trust chain.

• The intermediate certificate was in Windows' certificate store. I have removed the intermediate certificate from Windows' certificate store and the browser was still able to access it. This means that the browser somehow "cached" the intermediate certificate. I have cleared all browser history of Internet Explorer but it was still able to access it. Does clearing the browser history clear any "cached" certificates as well? If yes, then this should mean that the server's configuration is correct right? (that is, the server sends intermediate certificates). – Utku Jun 23 '17 at 10:26
• @Utku: I don't think that clearing the history clears cached certificates. What is really be sent from the server can be seen by doing a packet capture or using openssl s_client. – Steffen Ullrich Jun 23 '17 at 10:32
• I ran the command. The output includes the following: verify error:num=20:unable to get local issuer certificate and verify error:num=21:unable to verify the first certificate. I guess that these mean that the server is indeed not sending the chain certificates. – Utku Jun 23 '17 at 11:05
• @Utku: it might be that IE works around the problem by Downloading the missing certificate based on the CA issuers information in the AIA part of the certificate (see my response) while Firefox does not. There is a lot of undocumented magic going on in the different TLS stacks and apps and checking with a desktop browser often works while it does not work with other TLS clients. – Steffen Ullrich Jun 23 '17 at 12:59
• @MikeOunsworth: doubt that AIA is done by any implementations which just use OpenSSL, GnuTLS, Botan, PolarSSL or similar "lower" level libraries. Not only would the AIA extension to be automatically extracted during certificate verification but there must be also some HTTP stack somewhere so that the actual request can be made. And, given that these libraries are often used in a non-blocking way this HTTP stack would need to be integrated with the applications event loop etc. I'm not aware of any interface existing in these TLS stacks for this. – Steffen Ullrich Aug 23 '17 at 14:26

Support for the caIssuers access method of the Authority Information Access extension is available. It is disabled by default for compatibility and can be enabled by setting the system property com.sun.security.enableAIAcaIssuers to the value true.
If set to true, Sun's PKIX implementation of CertPathBuilder uses the information in a certificate's AIA extension (in addition to CertStores that are specified) to find the issuing CA certificate, provided it is a URI of type ldap, http, or ftp.