If you want to import certificate dynamically, you may need to use a custom x509TrustManager
. This is done when configuring the SSLContext
, which is itself used to create the SSLSocketFactory
or SSLEngine
.
jSSLutils is a library that lets you wrap existing trust managers and customize certain settings. You don't need it, but it may help.
This would go along these lines:
PKIXSSLContextFactory sslContextFactory = new PKIXSSLContextFactory();
sslContextFactory.setTrustManagerWrapper(new X509TrustManagerWrapper() {
@Override
public X509TrustManager wrapTrustManager(final X509TrustManager origManager) {
return new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return origManager.getAcceptedIssuers();
}
@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
try {
// This will call the default trust manager
// which will throw an exception if it doesn't know the certificate
origManager.checkServerTrusted(chain, authType);
} catch (CertificateException e) {
// If it throws an exception, check what this exception is
// the server certificate is in chain[0], you could
// implement a callback to the user to accept/refuse
}
}
@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
origManager.checkClientTrusted(chain, authType);
}
};
}
});
SSLContext sslContext = sslContextFactory.buildSSLContext();
(The (PKIX)SSLContextFactory
and X509TrustManagerWrapper
come from jSSLutils, but the rest is available with the J2SE/J2EE.)
There are a few CertificateException
s that you may want to catch (see subclasses).
If you make a callback to the user, it's possible that the SSL/TLS connection will fail the first time because of a time-out on the SSL/TLS handshake (if the callback takes too long to be replied to.)
You could then use this SSLContext
as your default using SSLContext.setSSLContext(...)
(from Java 6), but that's not necessarily a good idea. If you can, pass the SSLContext
to the library that makes the SSL/TLS connection. How this is done varies, but Apache HTTP Client 4.x, for example, has multiple options to configure its SSL settings, one of them being by passing KeyStore
s, another one being by passing an SSLContext
.
You could also to something per thread instead of per object that's going to connect (library dependent), by checking the current thread within the X509TrustManager
: this would probably make things a bit more complex in terms of synchronization and thread management/"awareness" by the trust manager.
javax.net.ssl.trustStore
will affect all connections (except those that have their specificSSLContext
). In addition, there's no point settingjavax.net.ssl.keyStore*
at all in this case (andjssecacerts
shouldn't contain any private key, so will be useless as a "keystore" anyway). – Facetiae