We have an internal web service hosted on https with an authorized root CA. When I tried to call that service from Java Apache HttpClient, it gave me the cert error "PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target".
Using SSL tools, I found out that the web service is sending the cert chain without the intermediate cert and it contains only server cert. So the Java cert error made sense because, only the root CA is present in Java truststore and it is unable to verify the cert chain, hence the error.
But on the other hand, I can call the same web service using C# HttpClient (.Net 4.6.1) without any issues.
Is C# HttpClient ignoring the cert issues with the web service or is it downloading the missing cert? Can anyone please shed some light on this?
Figured this out with very helpful comments from Stephen and Mark. I set up the trace in app.config where I found that C# HttpClient could find the intermediate certificate.
"System.Net Information: 0 : [23580] SecureChannel#41622463 - Remote certificate was verified as valid by the user."
But I had already verified that the intermediate cert wasn't present in Windows cert store which had led to this confusion. I checked there again and turns out the cert was under My User Account and not Computer Account. It must have been installed there when our company desktops were set up.
Now I am not really sure about the difference between the usage of these two cert stores in Windows, but at least I understand how C# client found the cert.
Related
I have an Issue with the verification of a ssl certificate.
What I am trying to do, is sending some data from a java program to a server, which then stores that data.
The issue is, that the ssl certificate validation fails with the following exception:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed [...] unable to find valid certification path to...
I am able to resolve this issue, by adding the "end-user" certificate of the server to the truststore I am using.
The chain looks something like this:
Root Certificate 1
Intermediate Cert 11
Intermediate Certificate x
End-User Certificate
Something to note about this whole chain / process:
The communication is using the companies proxy, which replaces all the certificates, and creates its own chain.
So back to the issue:
By adding the end-user certificate everything runs fine. But only for a little while, before that certificate gets refreshed and the one I added is no longer valid. I have tried adding just the root certificate, just each intermediate certificate, adding all 3 certificates and also adding the certificate which would be used if the proxy does not replace the chain. But somehow the certificate cannot be validated.
Is there something I might be overlooking? Do I have to add something else to be able to validate the certificate?
Edit:
Maybe something to note:
I checked the chain, by using the browser and navigating to said server, and then checking the ssl certificates.
I have an Apache web server fronting a Tomcat 8 web server that is running my website, and I'm switching the top-level domain from my.website.ie to my.website.com. I have some code that runs in response to a particular request that generates a PDF. That code fetches an image (using a URL) which is served from the same web server e.g.
Image.getInstance(new URL("https://my.website.com/img/myimage.png"))
In addition to the domain change, I'm also changing my SSL certificate provider to LetsEncrypt (free SSL certs). My development website at the new .com domain is running and the certificate is valid and does not expire for a number of months.
I have another development server running on a separate machine that is still using the .ie domain. The Tomcat codebase running on both of these servers are identical right now. They are both trying to fetch the image at the URL shown above in that particular piece of code.
On the .ie server, the request that generates the PDF works correctly, without any problems fetching the image. On the .com server, the request fails with this error:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
My understanding of this error is that the certificate at the target URL is not trusted (e.g. self-signed), but that is not true in this case. Also, both of the servers are hitting the same URL for the image, so why is one server trusting the certificate and the other not?
I haven't made any additional configuration changes on the .ie server that I haven't made on the .com server (with respect to setting up the new certificate), so is there some other (mis)configuration that I haven't considered?
Not trusted means the used CA is not trusted by the software.
Self-signed certificates are never trusted.
Java has it's own trust store (only on Linux the system trust store is used AFAIR?). If the CA certificate is newer than the used Java version it may happen that Java does not trust the CA. Conclusion: Update your Java.
According to this Stackoverflow answer you need at least Java 8u101 for Let's Encrypt support:
Does Java support Let's Encrypt certificates?
The error says that the chain doesn't lead to a root certificate that is trusted. Trusted CA root certificates are stored in Java's root keystore where the root certificate issued by Let's Encrypt is obviously missing.
You can add the root certificate manually to the store or check if newer versions of Java already contain the certificate.
I need to consume some HTTPS web services. To use the certificate, I'm setting (javax.net.ssl) trustStore, trustStorePassword, keyStore and keyStorePassword properties through the System.setProperty.
If I do new URL([HTTPS...WSDL]).openStream(), it works. So, I'm sure that trust and keystore properties are ok (without setting those properties, my routine failed).
The problem is when I try to consume the service, I'm getting the famous
sun.security.provider.certpath.SunCertPathBuilderException: unable to
find valid certification path to requested target
exception.
Anyone have an idea of what I need to do?
Thanks a lot.
There are three possible failures:
You are using a self-signed certificate.
Your certificate has been signed by a common CA (Certificate Authority) using an intermediate certificate, but their intermediate certificate is not served by your web server.
Both the server certificate and the CA intermediate certificate are served by your web server, but the Java truststore does not contain the root certificate.
To solve the last step use:
Import CA root cert
I created a java agent that needs to connect to an API internaly. The protocol used is HTTPS. When the agent tries to connect to the API it throws the following error:
com.ibm.jsse2.util: no trusted certificate found. This all is running on a Domino 9.0.1fp3 server. The SSL certificate is a self signed certificate with a custom certificate authority.
I tried the following solution http://www-01.ibm.com/support/docview.wss?uid=swg21588966 but to no success. Even when we restarted the server it does not correctly pick up the certificate chain. As a last resort we created a little java class that ignores SSL certificates that are self signed. But ofcourse this is not a great solution.
I was wondering if someone also encountered this issue and knows how to solve it.
Apparently IBM forgot to mention that you actually need to restart the whole server for this to work....
I have a web service deployed on tomcat hosted on a remote server.
I have set it up such that it can be accessed only via HTTPS.
For this, I generated a Certificate Signing Request (CSR) and used it to get a temporary certificate from VeriSign.
My web service client is on my local machine. If I try to access the service it will throw a javax.net.ssl.SSLHandshakeException:unable to find valid certification path to requested target
If I install the certificate in to local Java's keystore, the issue will be resolved.
My question is if I install a valid SSL certificate from a CA in to my tomcat server,
will I get this client-side error even if I do not import the certificate to local key store?
No, you won't. JVM ships with root ca's by default. The older JVMs (1.5.xx version) don't have all root CA's, but if you have a certificate from Verisign it shouldn't be a problem.
Java has many root CA certificates already installed. As long as you use one of those popular CAs to get your certificate, the client will not receive an error.
While you should be fine, its a good idea to include not only the actual certificate for your site, but also the entire chain leading up to the root certificate. (Sometimes you'll bump into clients which are missing some intermediate certificates and this can cause annoying debugging problems.)