Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
334 views
in Technique[技术] by (71.8m points)

java - The Webserver I talk to updated its SSL cert and now my app can't talk to it

The webserver updated its SSL cert to a new verisign signed cert and my java app can no longer connect.

I am using java 5 with a date on the cert file Nov 2006 in /usr/java/jre/lib/security

I get

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
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1518)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:848)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:818)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1030)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1057)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1041)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:402)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:170)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:133)

How do I install a new key supplied by the server?

From a different java instance I get

Certificate chain received from eservices3.bus.att.com - 135.38.253.93 was not trusted causing SSL handshake failure.

I assume that it is from the same root problem.

Update Before the remote server was updated this worked with our standard java install. I didn't have to install any certs to get this to work last time around.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Java tries to validate the certificate by following the chain of certificates presented by the server, until it finds one it trusts (i.e. one that's present in your cacerts file).

We can verify the chain manually using the OpenSSL command line tools:

simon@lucifer:~$ openssl s_client -connect eservices3.bus.att.com:443
<snipped>
---
Certificate chain
 0 s:/C=US/ST=Georgia/L=Alpharetta/O=ATT Services, Inc./OU=ATTIT/CN=eservices3.bus.att.com
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
---

Now, here's the problem: the issuer (line beginning i:) "VeriSign Class 3 Secure Server CA - G3" is an intermediate certificate, not a root. The AT&T server is misconfigured, and should be sending both its own certificate ("eservices3.bus.att.com") and the intermediate, so that Java can verify the chain all the way to the root.

To illustrate another way, the chain should look like this:

1) VeriSign Class 3 Public Primary Certification Authority - G5 (root)
                               ^
                               | signed by
                               |
2)          VeriSign Class 3 Secure Server CA - G3      (intermediate)
                               ^
                               | signed by
                               |
3)                 eservices3.bus.att.com                     (server)
  • the root (1) is in cacerts - ok
  • the server certificate (3) is presented during the SSL handshake - ok
  • but: Java has no knowledge of the intermediate (2) - so can't verify the chain end-to-end

To fix this, you can either:

  • ask AT&T to fix the server so it sends both the server and intermediate cert during the handshake, or
  • import the intermediate cert into Java's keystore

The first solution is preferable, since it helps everyone (not just you) and is slightly less risky (you might not notice if the intermediate cert became compromised).

If you want to import the cert as a temporary measure, grab it from VeriSign's support pages (it's "Secondary SSL Intermediate CA Certificate"), then:

simon@lucifer:~$ keytool -importcert -alias some_alias_of_your_choosing 
                    -file intermediate_cert_path.crt 
                    -keystore your_cacerts_path
Enter keystore password:  *****
Certificate was added to keystore

To remove the cert (once AT&T get their act together):

simon@lucifer:~$ keytool -delete -alias same_alias_as_before 
                    -keystore your_cacerts_path

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.9k users

...