2
votes

I have a strange problem (it's 100% server configuration problem,) for example I want to download something from Dropbox:

Resolving dl.dropboxusercontent.com... 23.23.160.146, 50.17.227.107, 54.221.248.69, ... Connecting to dl.dropboxusercontent.com|23.23.160.146|:443... connected. ERROR: cannot verify dl.dropboxusercontent.com’s certificate, issued by “/C=US/ST=CA/O=SonicWALL Inc./CN=SonicWALL Firewall DPI-SSL”:
Self-signed certificate encountered. To connect to dl.dropboxusercontent.com insecurely, use ‘--no-check-certificate’.

Yes, I know that I can use --non-check-certificate but when I want to use SSL connection in Java app I have something like this:

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

This app works great in other servers or in local machines, any ideas what is wrong here?

2

2 Answers

3
votes

/C=US/ST=CA/O=SonicWALL Inc./CN=SonicWALL Firewall DPI-SSL

Your traffic is visibly intercepted by a deep packet inspection firewall that acts as a MITM proxy to monitor your traffic.

This can generally be thought of as "legitimate" MITM attacker. (However legitimate this may be depends on a number of legal and ethical aspects.) Your local network administrator should be able to tell you a little bit about this. If this is part of a company network, this company is monitoring your traffic, including the contents of your HTTPS connection (so it's no longer secure from end-to-end). It the firewall does its job properly, it should still secure the connection from the firewall to the server (It's probably hard to know whether it check certificates properly.)

In general, such a firewall or proxy acts as its own Certification Authority, effectively forging each certificate as requested.

Most clients on the corporate network would trust certificates it issues (like the one you're facing) because system administrators would also install the CA certificate as a trusted certificate into each machine within that network. You probably have it the OS trusted root certificates.

However, it is likely that network administrators did not install this CA certificate into your JRE installation (which uses its own set of trust anchors by default).

Try to export that CA certificate (see the name above) from a reference machine and import it into the truststore you're using (either your JRE's default truststore: cacerts or a new truststore you build and pass to your application via the javax.net.trustStore properties).

Typically, you can use something like this (assuming you've exported the Firewall's CA as "firewallca.pem"):

keytool -import -file firewallca.pem -alias firewallca -keystore truststore.jks

If the truststore.jks file doesn't exist, it will be created. Otherwise, you can take a copy of the cacerts file in the lib/security directory of your JRE. You can also do this directly on the cacerts file (using -keystore /path/to/truststore.jks, provided you have write access to it).

If you choose not to do it on the default truststore (that cacerts file) but use a local truststore like truststore.jks, you'll can use it by using this system property when running your application: -Djavax.net.trustStore=/path/to/truststore.jks

For other ways of configuring your truststore, check this answer.


Another way to fix this is to tell Java to use your OS's truststore. I'll assume you're using Windows here. Using these system properties should work:

-Djavax.net.trustStore=NONE -Djavax.net.trustStoreType=WINDOWS-ROOT

(Try with WINDOWS-MY instead of WINDOWS-ROOT if this doesn't work.)

The WINDOWS-MY/WINDOWS-ROOT is a bit buggy in that it will miss some of the certificates in the Windows store: it uses the certificate "friendly name" (non unique) as the keystore alias (unique), so a certificate with a given friendly name will hide the others with the same name. (This effectively reduces the number of CA certificates that are trusted unfortunately.)

Since you're in an environment where presumably all the traffic goes through your DPI firewall, you'll probably only ever have to use one CA certificate at most. As long is it doesn't share its "friendly name" in the Windows list with any other cert, you should be fine.

1
votes

You need to add the server's SSL certificate in your client's Java keystore. Take a look at this SO post:

Resolving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error?

TIP: This is because your client's JVM does not 'trust' the server's SSL cert. So you need to add the cert in your keystore.