From: http://blogs.sun.com/andreas/entry/no_more_unable_to_find
Some of you may be familiar with the (not very user friendly) exception
message
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
when trying to open an SSL connection to a host using JSSE.
What this usually means is that the server is using a test certificate
(possibly generated using keytool) rather than a certificate from a well
known commercial Certification Authority such as
Verisign or
GoDaddy. Web browsers display
warning dialogs in this case, but since JSSE cannot assume an
interactive user is present it just throws an exception by default.
Certificate validation is a very important part of SSL security, but I
am not writing this entry to explain the details. If you are interested,
you can start by reading the
Wikipedia
blurb. I am writing this entry to show a simple way to talk to that
host with the test certificate, if you really want to.
Basically, you want to add the server's certificate to the KeyStore with
your trusted certificates. There are any number of ways to achieve
that, but a simple solution is to compile and run the
attached
program as
java InstallCert hostname
, for example
% java InstallCert ecc.fedora.redhat.com
Loading KeyStore /usr/jdk/instances/jdk1
.5.0
/jre/lib/security/cacerts
Opening connection to ecc.fedora.redhat.com:
443
Starting SSL handshake
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:
1476
)
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:
846
)
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:
815
)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:
1025
)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:
1038
)
at InstallCert.main(InstallCert.java:
63
)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:
221
)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:
145
)
at sun.security.validator.Validator.validate(Validator.java:
203
)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:
172
)
at InstallCert$SavingTrustManager.checkServerTrusted(InstallCert.java:
158
)
at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:
320
)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:
839
)
7
more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:
236
)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:
194
)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:
216
)
13
more
Server sent
2
certificate(s):
1
Subject CN
=
ecc.fedora.redhat.com
,
O
=
example.com
,
C
=
US
Issuer CN
=
Certificate Shack
,
O
=
example.com
,
C
=
US
sha1 2e 7f
76
9b
52
91
09
2e 5d 8f 6b
61
39
2d 5e
06
e4 d8 e9 c7
md5 dd d1 a8
03
d7 6c 4b
11
a7 3d
74
28
89
d0
67
54
2
Subject CN
=
Certificate Shack
,
O
=
example.com
,
C
=
US
Issuer CN
=
Certificate Shack
,
O
=
example.com
,
C
=
US
sha1 fb
58
a7
03
c4 4e 3b 0e e3 2c
40
2f
87
64
13
4d df e1 a1 a6
md5
72
a0
95
43
7e
41
88
18
ae 2f 6d
98
01
2c
89
68
Enter certificate to add to trusted keystore or 'q' to quit:
[
1
]
What happened was that the program opened a connection to the specified
host and started an SSL handshake. It printed the exception stack trace
of the error that occured and shows you the certificates used by the
server. Now it prompts you for the certificate you want to add to your
trusted KeyStore. You should only do this if you are sure that
this is the certificate of the trusted host you want to connect to.
You may want to check the MD5 and SHA1 certificate fingerprints against
a fingerprint generated on the server (e.g. using keytool) to make sure
it is the correct certificate.
If you've changed your mind, enter 'q'. If you really want to add the
certificate, enter '1'. (You could also add a CA certificate by entering
a different certificate, but you usually don't want to do that'). Once
you have made your choice, the program will print the following:
...
Added certificate to keystore 'jssecacerts' using alias 'ecc.fedora.redhat.com-1'
It displayed the complete certificate and then added it to a Java
KeyStore 'jssecacerts' in the current directory. To use it in your
program, either configure JSSE to use it as its trust store (as
explained in the
documentation)
or copy it into your $JAVA_HOME/jre/lib/security
directory. If you want all Java applications to recognize the
certificate as trusted and not just JSSE, you could also overwrite the cacerts
file in that directory.
After all that, JSSE will be able to complete a handshake with the host,
which you can verify by running the program again:
% java InstallCert ecc.fedora.redhat.com Loading KeyStore jssecacerts
Opening connection to ecc.fedora.redhat.com:443
Starting SSL handshake
No errors, certificate is already trusted Server sent 2 certificate(s): 1 []
Enter certificate to add to trusted keystore or 'q' to quit: [1] q KeyStore not changed