My problem:
I want to connect to servers (not limited to the HTTPS protocol - maybe LDAP-over-SSL, maybe SMTPS, maybe IMAPS, etc.), which can use certificates that Java will not trust by default (because they are self-signed )
The desired workflow is to try to connect, get information about the certificate, present it to the user, and if he accepts it, add it to the trusted store so that he is trusted to go forward.
I'm stuck getting a certificate. I have a code (see the end of the post) that I cut from here and from sites that point to answers to questions about java SSL. The code simply creates SSLSocket, starts an SSL handshake, and requests an SSL session for Certificate[]. The code works fine when I connect to the server using an already trusted certificate. But when I connect to the server using a self-signed certificate, I get the usual:
Exception in thread "main" 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 sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
[etc]
If I start with -Djavax.net.debug=all, I see that the JVM is extracting a self-signed certificate, but it will break the connection to use an untrusted certificate before proceeding to the point where it will return the certificates.
, . , . , , . ?
, :
java SSLTest www.google.com 443
, Google.
java SSLTest my.imap.server 993
, .
:
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.*;
import javax.net.SocketFactory;
import javax.net.ssl.*;
public class SSLTest
{
public static void main(String[] args) throws Exception {
if (args.length != 2) {
System.err.println("Usage: SSLTest host port");
return;
}
String host = args[0];
int port = Integer.parseInt(args[1]);
SocketFactory factory = SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
socket.startHandshake();
Certificate[] certs = socket.getSession().getPeerCertificates();
System.out.println("Certs retrieved: " + certs.length);
for (Certificate cert : certs) {
System.out.println("Certificate is: " + cert);
if(cert instanceof X509Certificate) {
try {
( (X509Certificate) cert).checkValidity();
System.out.println("Certificate is active for current date");
} catch(CertificateExpiredException cee) {
System.out.println("Certificate is expired");
}
}
}
}
}