How to use custom truststore?
Hi, I've written a simple ssl client (basing on jakarta commons httpclient project) that connects to IIS with SSL and it works only i f I add ssl certificate from IIS to the jre cacerts (using keytool import). The cacerts are automatically readed somehow (don't know how)
I want to make the whole thing more elastic and be able to provide my client with a path to cacerts / truststore / keystore. Am I doing it OK? I Currently it works...
BUT the loops that print certificates and trustores to screen are empty - for example keystore.getCertificateChain(alias); always returns null....
But IIS cert is inside
C:\\Program Files\\Java\\jre1.5.0_09\\lib\\security\\cacertsbbb
PS. I would like to avoid setting System properties in my code like System.setTruststore etc.
PS. Should be without sockets. Just extension of what i got.
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import javax.net.SocketFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.log4j.Logger;
import junit.framework.TestCase;
publicclass SSLSocketClientextends TestCase{
private URL keystoreUrl =null;
private String mockKeystoreUrl ="C:\\Program Files\\Java\\jre1.5.0_09\\lib\\security\\cacertsbbb";
private String keystorePassword ="changeit";
private URL truststoreUrl =null;
private String mockTruststoreUrl ="C:\\Program Files\\Java\\jre1.5.0_09\\lib\\security\\cacertsbbb";
private String truststorePassword =null;
private SSLContext sslcontext =null;
//
publicvoid testSSLSocket(){
try{
SSLSocketClient client =new SSLSocketClient();
// client.createSocket("10.63.29.50", 443);
HttpConnectionParams params =new HttpConnectionParams();
InetAddress ia = InetAddress.getLocalHost();
// params.setParameter(arg0, arg1)
//client.createSocket("10.63.29.50", 443, ia, 444, params);
client.connect("10.63.29.50", 443,"/ssl2/index.html", params);
}catch (ConnectTimeoutException e){
// TODO Auto-generated catch block
e.printStackTrace();
}catch (UnknownHostException e){
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IOException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
privatestatic Logger log = Logger.getLogger(SSLSocketClient.class);
/*
* private static KeyStore createKeyStore(final URL url, final String
* password) throws KeyStoreException, NoSuchAlgorithmException,
* CertificateException, IOException { if (url == null) { throw new
* IllegalArgumentException("Keystore url may not be null"); }
*
* KeyStore keystore = KeyStore.getInstance("jks");
* keystore.load(url.openStream(), password != null ? password
* .toCharArray() : null); return keystore; }
*/
private KeyStore mockCreateKeyStore(final String url,final String password)
throws KeyStoreException, NoSuchAlgorithmException,
CertificateException, IOException{
if (url ==null){
thrownew IllegalArgumentException("Keystore url may not be null");
}
InputStream keystoreStream =new FileInputStream(url);
KeyStore keystore = KeyStore.getInstance("jks");
keystore.load(keystoreStream, password !=null ? password.toCharArray()
:null);
return keystore;
}
private KeyManager[] createKeyManagers(final KeyStore keystore,
final String password)throws KeyStoreException,
NoSuchAlgorithmException, UnrecoverableKeyException{
if (keystore ==null){
thrownew IllegalArgumentException("Keystore may not be null");
}
KeyManagerFactory kmfactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmfactory.init(keystore, password !=null ? password.toCharArray()
:null);
return kmfactory.getKeyManagers();
}
private TrustManager[] createTrustManagers(final KeyStore keystore)
throws KeyStoreException, NoSuchAlgorithmException{
if (keystore ==null){
thrownew IllegalArgumentException("Keystore may not be null");
}
TrustManagerFactory tmfactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmfactory.init(keystore);
TrustManager[] trustmanagers = tmfactory.getTrustManagers();
for (int i = 0; i < trustmanagers.length; i++){
if (trustmanagers[i]instanceof X509TrustManager){
trustmanagers[i] =new AuthSSLX509TrustManager(
(X509TrustManager) trustmanagers[i]);
}
}
return trustmanagers;
}
private SSLContext createSSLContext(){
try{
KeyManager[] keymanagers =null;
TrustManager[] trustmanagers =null;
if (this.mockKeystoreUrl !=null){
KeyStore keystore = mockCreateKeyStore(this.mockKeystoreUrl,
this.keystorePassword);
//if (log.isDebugEnabled()) {
Enumeration aliases = keystore.aliases();
while (aliases.hasMoreElements()){
String alias = (String) aliases.nextElement();
Certificate[] certs = keystore
.getCertificateChain(alias);
if (certs !=null){
log.info("Certificate chain '" + alias +"':");
for (int c = 0; c < certs.length; c++){
if (certs[c]instanceof X509Certificate){
X509Certificate cert = (X509Certificate) certs[c];
log.info(" Certificate " + (c + 1) +":");
log.info(" Subject DN: "
+ cert.getSubjectDN());
log.info(" Signature Algorithm: "
+ cert.getSigAlgName());
log.info(" Valid from: "
+ cert.getNotBefore());
log.info(" Valid until: "
+ cert.getNotAfter());
log
.info(" Issuer: "
+ cert.getIssuerDN());
}
}
}
}
//}
keymanagers = createKeyManagers(keystore, this.keystorePassword);
}
if (this.mockTruststoreUrl !=null){
KeyStore keystore = mockCreateKeyStore(this.mockKeystoreUrl,
this.truststorePassword);
//if (log.isDebugEnabled()) {
Enumeration aliases = keystore.aliases();
while (aliases.hasMoreElements()){
String alias = (String) aliases.nextElement();
log.debug("Trusted certificate '" + alias +"':");
Certificate trustedcert = keystore
.getCertificate(alias);
if (trustedcert !=null
&& trustedcertinstanceof X509Certificate){
X509Certificate cert = (X509Certificate) trustedcert;
log.info(" Subject DN: " + cert.getSubjectDN());
log.info(" Signature Algorithm: "
+ cert.getSigAlgName());
log.info(" Valid from: " + cert.getNotBefore());
log.info(" Valid until: " + cert.getNotAfter());
log.info(" Issuer: " + cert.getIssuerDN());
}
}
//}
trustmanagers = createTrustManagers(keystore);
}
SSLContext sslcontext = SSLContext.getInstance("SSL");
///sslcontext.
sslcontext.init(keymanagers, trustmanagers,null);
return sslcontext;
}catch (NoSuchAlgorithmException e){
log.error(e.getMessage(), e);
thrownew RuntimeException("Unsupported algorithm exception: "
+ e.getMessage());
// throw new AuthSSLInitializationError("Unsupported algorithm
// exception: " + e.getMessage());
}catch (KeyStoreException e){
log.error(e.getMessage(), e);
thrownew RuntimeException("Keystore exception: " + e.getMessage());
// throw new AuthSSLInitializationError("Keystore exception: " +
// e.getMessage());
}catch (GeneralSecurityException e){
log.error(e.getMessage(), e);
thrownew RuntimeException("Key management exception: "
+ e.getMessage());
// throw new AuthSSLInitializationError("Key management exception: "
// + e.getMessage());
}catch (IOException e){
log.error(e.getMessage(), e);
thrownew RuntimeException(
"I/O error reading keystore/truststore file: "
+ e.getMessage());
// throw new AuthSSLInitializationError("I/O error reading
// keystore/truststore file: " + e.getMessage());
}
}
private SSLContext getSSLContext(){
if (this.sslcontext ==null){
this.sslcontext = createSSLContext();
}
return this.sslcontext;
}
/**
* Attempts to get a new socket connection to the given host within the
* given time limit.
*
* To circumvent the limitations of older JREs that do not support connect
* timeout a controller thread is executed. The controller thread attempts
* to create a new socket within the given limit of time. If socket
* constructor does not return until the timeout expires, the controller
* terminates and throws an {@link ConnectTimeoutException}
*
*
* @param host
*the host name/IP
* @param port
*the port on the host
* @param clientHost
*the local host name/IP to bind the socket to
* @param clientPort
*the port on the local machine
* @param params
*{@link HttpConnectionParams Http connection parameters}
*
* @return Socket a new socket
* @throws IOException
* @throws IOException
* if an I/O error occurs while creating the socket
* @throws UnknownHostException
* if the IP address of the host cannot be determined
*/
publicvoid connect(final String host,finalint sport,final String query,
final HttpConnectionParams params)throws IOException{
HostnameVerifier hv =new HostnameVerifier(){
publicboolean verify(String arg0, SSLSession arg1){
System.out.println("Bartek: Hostname is not matched for cert.");
returntrue;
}
};
URL wlsUrl =null;
wlsUrl =new URL("https", host, Integer.valueOf(sport).intValue(),
query);
System.out
.println(" Trying a new HTTPS connection using WLS client classes - "
+ wlsUrl.toString());
HttpsURLConnection sconnection = (HttpsURLConnection) wlsUrl
.openConnection();
SocketFactory socketfactory = getSSLContext().getSocketFactory();
/*
* HttpsURLConnection sconnection = new HttpsURLConnection( wlsUrl);
*/
sconnection.setHostnameVerifier(hv);
//sconnection.setSSLSocketFactory((SSLSocketFactory) socketfactory);
sconnection.setSSLSocketFactory((SSLSocketFactory) socketfactory);
//sconnection.setHostnameVerifier(hv);
tryConnection(sconnection, System.out);
}
publicstaticvoid tryConnection(HttpsURLConnection connection,
OutputStream stream)throws IOException{
connection.connect();
String responseStr ="\t\t" + connection.getResponseCode() +" -- "
+ connection.getResponseMessage() +"\n\t\t"
+ connection.getContent().getClass().getName() +"\n";
connection.disconnect();
System.out.print(responseStr);
}
}
Message was edited by:
herbatniczek

