views:

677

answers:

2

It looks like a standard question, but I couldn't find clear directions anywhere.

I have java code trying to connect server with probably self-signed (or expired) certificate. It gives something like this

[HttpMethodDirector] I/O exception (javax.net.ssl.SSLHandshakeException) caught when processing request: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

As I understand, I have to play around with keytool and tell java that it's ok to allow this connection. But all comments I've found assume I'm fully proficient with keytool, like "generate private key for server and import it into keystore". And I'm not. Is there anybody who could post detailed instructions?
I'm running unix, so bash script would be best.

Not sure if it's important, but code executed in jboss.

Thanks a lot!

+4  A: 

You have basically two options here: add the self-signed certificate to your JVM truststore or configure your client to

Option 1

Export the certificate from your browser and import it in your JVM truststore (to establish a chain of trust):

<JAVA_HOME>\bin\keytool -import -v -trustcacerts
-alias server-alias -file server.cer
-keystore cacerts.jks -keypass changeit
-storepass changeit 

Option 2

Disable Certificate Validation (code from Example Depot):

// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { 
    new X509TrustManager() {     
        public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
            return null;
        } 
        public void checkClientTrusted( 
            java.security.cert.X509Certificate[] certs, String authType) {
            } 
        public void checkServerTrusted( 
            java.security.cert.X509Certificate[] certs, String authType) {
        }
    } 
}; 

// Install the all-trusting trust manager
try {
    SSLContext sc = SSLContext.getInstance("SSL"); 
    sc.init(null, trustAllCerts, new java.security.SecureRandom()); 
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
} 
// Now you can access an https URL without having the certificate in the truststore
try { 
    URL url = new URL("https://hostname/index.html"); 
} catch (MalformedURLException e) {
} 

Note that I do not recommend the Option #2 at all. Disabling the trust manager defeats some parts of SSL and makes you vulnerable to man in the middle attacks. Prefer Option #1 or, even better, have the server use a "real" certificate signed by a well known CA.

Pascal Thivent
I've tried 2 (for testing), but it doesn't seem to work. Maybe, because amazon ws client employs apache HttpClient and HttpMethod classes to make a call. I executed the code right before that call. Also, do you mean in the last sentence that our server having bad certificate can prevent connection? I thought it's only about checking target server's certificate. Thanks, and I'll see what I can do with keytool.
Nikita Rybak
Not just the MIM attack. It renders you vulnerable to connecting to the wrong site. It is completely insecure. See RFC 2246. I am opposed to posting this TrustManager at all times. It's not even correct w.r.t. its own specification.
EJP
@EJP I'm really not recommending the second option (I've updated my answer to make it clear). However, not posting it won't solve anything (this is public information) and doesn't IMHO deserve a downvote.
Pascal Thivent
It turns out, the problem was in our ssl certificate (which can't be valid because VM is used for testing). I didn't expect it: browsers don't require you to have certificate, so why do I need one in jboss? Anyway, playing around with keytool helped. I guess, I'll have to find time and really learn all this stuff :/
Nikita Rybak
Pascal, I disagree. If you're not recommending it don't post it. I tremble to think how many production systems this has been embedded in just because someone used it to 'get it working' and then moved on. The thing doesn't even confirm to its own specification let alone any conceivable security scenario, and it doesn't just 'defeat some parts of SSL', it defeats the point of using SSL at all.
EJP
@EJP It's by teaching people that you educate them, not by hiding things. So keeping things secret or in obscurity is not a solution at all. This code is public, the Java API is public, it's better to talk about it than to ignore it. But I can live with you not agreeing.
Pascal Thivent
A: 

If 'they' are using a self-signed certificate it is up to them to take the steps required to make their server usable. Specifically that means providing their certificate to you offline in a trustworthy way. So get them to do that. You then import that into your truststore using the keytool as described in the JSSE Reference Guide. Don't even think about the insecure TrustManager posted here.

EJP