2

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?

Lou
  • 2,200
  • 2
  • 33
  • 66

2 Answers2

3

/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.

Community
  • 1
  • 1
Bruno
  • 119,590
  • 31
  • 270
  • 376
  • "This can generally be thought of as 'legitimate' MITM attacker" - there's no such thing as a legitmate attack. Its like saying you can get half preganant. (1) Did Dropbox agree to be intercepted (likely not). (2) How do you teach programmers to differentiate between "good" bad guys" and "bad" bad guys (you can't)? – jww Jul 25 '14 at 05:04
  • 1
    @jww I don't disagree, but it can make sense for a company to inspect all its SSL traffic. It's not about Dropbox being intercepted, it's about the company monitoring its network. – Bruno Jul 25 '14 at 09:06
1

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.

Community
  • 1
  • 1
Pat
  • 2,223
  • 4
  • 19
  • 25
  • Is there any possible to "trust" every web ? – user3771297 Jul 24 '14 at 17:49
  • 1
    @user3771297 that would nullify the entire concept of the certs if you trust all certs :) but nevertheless, you may like to take a look at this http://stackoverflow.com/questions/2893819/telling-java-to-accept-self-signed-ssl-certificate I would suggest to rather use `--no-check-certificate` option that you mentioned instead. But again, are you sure about this? – Pat Jul 24 '14 at 18:06
  • @user3771297 There are ways to disable certificate verification, but they're a terrible idea 99.9999999% of the time. It *feels* like a quick way, but it leads to more trouble later on: you'll either have to remove that code before it goes into production, or you'll forget and leave a security hole in your application (remember that you're turning off an "alarm" without addressing the problem, it's likely not to get noticed before a release). Neither are good options. – Bruno Jul 24 '14 at 18:16
  • @user3771297: "Is there any possible to 'trust' every web ". As Pat and Bruno said, that's a very bad idea. But if you don't care about the certificate validation, then don't use a certificate. You do that by using one of to cipher suites: Anonymous Diffie-Hellman (ADH) or Anonymous Elliptic Curve Diffie-Hellman (AECDH). Servers don't send certificates when the cipher suite is ADH or AECDH. But if you are not going to use PKIX correctly, why bother using SSL/TLS at all? – jww Jul 25 '14 at 05:02
  • By the way, it's not to the *keystore* you'd need to add the server (or CA) cert, but to the [*truststore*](http://stackoverflow.com/a/6341566/372643). – Bruno Jul 25 '14 at 09:13