I am trying to invoke a WS
over SSL
, from a tomee 1.6 server
, but I get a SSLHandshakeError
. The problem is that the certificate is self signed, and is not recognized by my JVM
. As it is only for test purpose, and not production, I have been asked to bypass the certificate control.
I read a lot of stuff about how to proceed, and I have written that code :
a class NaiveSSLContext :
package fr.csf.ssl;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
/**
* A factory class which creates an {@link SSLContext} that
* naively accepts all certificates without verification.
*/
public class NaiveSSLContext
{
private NaiveSSLContext()
{}
/**
* Get an SSLContext that implements the specified secure
* socket protocol and naively accepts all certificates
* without verification.
*/
public static SSLContext getInstance( String protocol) throws NoSuchAlgorithmException
{
SSLContext sslCtx = SSLContext.getInstance( protocol);
init( sslCtx);
return sslCtx;
}
/**
* Get an SSLContext that implements the specified secure
* socket protocol and naively accepts all certificates
* without verification.
*/
public static SSLContext getInstance( String protocol, Provider provider) throws NoSuchAlgorithmException
{
SSLContext sslCtx = SSLContext.getInstance( protocol, provider);
init( sslCtx);
return sslCtx;
}
/**
* Get an SSLContext that implements the specified secure
* socket protocol and naively accepts all certificates
* without verification.
*/
public static SSLContext getInstance( String protocol, String provider) throws NoSuchAlgorithmException, NoSuchProviderException
{
SSLContext sslCtx = SSLContext.getInstance( protocol, provider);
init( sslCtx);
return sslCtx;
}
/**
* Set NaiveTrustManager to the given context.
*/
private static void init( SSLContext context)
{
try
{
// Set NaiveTrustManager.
context.init( null, new TrustManager[] { new NaiveTrustManager() }, new java.security.SecureRandom());
System.out.println( "------------- Initialisation du NaiveSSLContext ---------------------");
}
catch( java.security.KeyManagementException e)
{
throw new RuntimeException( "Failed to initialize an SSLContext.", e);
}
}
/**
* A {@link TrustManager} which trusts all certificates naively.
*/
private static class NaiveTrustManager implements X509TrustManager
{
@Override
public X509Certificate[] getAcceptedIssuers()
{
System.out.println( "------------- NaiveTrustManager.getAcceptedIssuers() ---------------------");
return null;
}
@Override
public void checkClientTrusted( X509Certificate[] certs, String authType)
{
System.out.println( "------------- NaiveTrustManager.checkClientTrusted( " + certs.toString() + ", " + authType
+ ") ---------------------");
}
@Override
public void checkServerTrusted( X509Certificate[] certs, String authType)
{
System.out.println( "------------- NaiveTrustManager.checkServerTrusted( " + certs.toString() + ", " + authType
+ ") ---------------------");
}
}
}
and another class NaiveSSLSocketFactory :
package fr.csf.ssl;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.NoSuchAlgorithmException;
public class NaiveSSLSocketFactory extends javax.net.ssl.SSLSocketFactory
{
private javax.net.ssl.SSLSocketFactory factory;
public NaiveSSLSocketFactory() throws NoSuchAlgorithmException
{
javax.net.ssl.SSLContext sslCtx = NaiveSSLContext.getInstance( "SSL");
factory = sslCtx.getSocketFactory();
}
private final String[] enabledProtocols = new String[]
{ "SSLv3", "TLSv1" };
@Override
public Socket createSocket( Socket s, String host, int port, boolean autoClose) throws IOException
{
Socket socket = factory.createSocket( s, host, port, autoClose);
((javax.net.ssl.SSLSocket) socket).setEnabledProtocols( enabledProtocols);
return socket;
}
@Override
public Socket createSocket( String host, int port) throws IOException, UnknownHostException
{
Socket socket = factory.createSocket( host, port);
((javax.net.ssl.SSLSocket) socket).setEnabledProtocols( enabledProtocols);
return socket;
}
@Override
public Socket createSocket( InetAddress host, int port) throws IOException
{
Socket socket = factory.createSocket( host, port);
((javax.net.ssl.SSLSocket) socket).setEnabledProtocols( enabledProtocols);
return socket;
}
@Override
public Socket createSocket( String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException
{
Socket socket = factory.createSocket( host, port, localHost, localPort);
((javax.net.ssl.SSLSocket) socket).setEnabledProtocols( enabledProtocols);
return socket;
}
@Override
public Socket createSocket( InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException
{
Socket socket = factory.createSocket( address, port, localAddress, localPort);
((javax.net.ssl.SSLSocket) socket).setEnabledProtocols( enabledProtocols);
return socket;
}
@Override
public String[] getDefaultCipherSuites()
{
String[] cipherSuites = factory.getDefaultCipherSuites();
return cipherSuites;
}
@Override
public String[] getSupportedCipherSuites()
{
String[] cipherSuites = factory.getSupportedCipherSuites();
return cipherSuites;
}
}
The problem is that I can't find out how to make the JVM use my Naive* classes instead of the default ones. I have tried different methods, but neither of them work :
First try :
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory( new NaiveSSLSocketFactory());
My log traces in the checkClientTruted methods are never displayed. It seems that my NaiveSSLSocketFactory is never called.
2nd try :
java.security.Security.setProperty( "ssl.SocketFactory.provider", new NaiveSSLSocketFactory().getClass().getName());
I experienced a ClassNotFoundException due to a ClassLoader problem, but after this problem was fixed, the same problem remains.
I eventually found a blog where it was said that CXF client had to do a little more configuration stuff :
<http-conf:conduit name="*.http-conduit" >
<http-conf:tlsClientParameters
useHttpsURLConnectionDefaultSslSocketFactory="true"
/>
</http-conf:conduit>
As I use a Tomee1.6 server, my program is a CXF client. So that must be the solution. But where do I have to write this configuration properties ? I can't find any xml file in Tomee, related with CXF. There's only e cxf.properties file, which is nearly empty.