0

I have a utility SSLSocketFactory class that essentially allows you to toggle if you want to trust all certificates and/or turn of Diffie-Hellman due to a JDK bug. I've recently added the option of providing your own SSLSocketFactory but seem to of forgotten something

Disabling Diffie-Hellman is easy enough to do on a factory by simply adding some code when you create the socket. However to trust all certificates I replace the factory with a different one

public UtilSSLSocketFactory trustAllCertificates() {
    if (trustingAllCertificates)
    //Already doing this, no need to do it again
        return this;
    trustingAllCertificates = true;
    try {
        TrustManager[] tm = new TrustManager[] {new TrustingX509TrustManager()};
        SSLContext context = SSLContext.getInstance("SSL");
        context.init(new KeyManager[0], tm, new SecureRandom());
        wrappedFactory = (SSLSocketFactory) context.getSocketFactory();
    } catch (Exception e) {
        throw new RuntimeException("Can't recreate socket factory that trusts all certificates", e);
    }
    return this;
}

Is there any way to tell an arbitrary SSLSocketFactory to trust all certificates without replacing it?

Bruno Rohée
  • 3,436
  • 27
  • 32
TheLQ
  • 14,830
  • 14
  • 69
  • 107
  • Why `new KeyManager[0]` and not `null`? (Which DH bug are you referring to, btw?) – Bruno May 23 '12 at 18:12
  • @Bruno To be honest, I copied this from somewhere, made sure it worked, and then was done with it. I've never been able to fully understand the underlying SSL Java code so I try not to deal with it when I can – TheLQ May 23 '12 at 18:16
  • 1
    If you don't fully understand the underlying SSL code, do you realise why it's a bad idea to trust all certificates? – Bruno May 23 '12 at 18:18
  • 1
    Due to *what* 'JDK bug'? Do you realize this is rsdically insecure? If you don't want it secure why are you using SSL at all? – user207421 May 23 '12 at 21:51
  • @Bruno I'm writing a framework. Some users want to connect to servers using SSL, so I provide support. For those who want to, they can disable checking certificates and diffie hellman. This is simply a utility class for them. And yes, there is a warning saying that this is insecure. Its simply for convenience – TheLQ May 23 '12 at 23:47
  • @EJP JDK bug #6521495. Java throws an Exception when prime sizes are above 1024 bits. See http://stackoverflow.com/questions/6851461/java-why-does-ssl-handshake-give-could-not-generate-dh-keypair-exception – TheLQ May 23 '12 at 23:49

3 Answers3

4

Besides the fact that trusting all certificates blindly is generally a bad idea (if you want SSL/TLS to be used to secure the communication), the pattern you're using seems quite odd.

SSLContext is a factory for SSLSocketFactory, which is in turn a factory for SSLSocket.

If needed, you can set the default SSLContext (from Java 6 onwards) with SSLContext.setDefault(...): this will affect the default SSLSocketFactory, but perhaps not more specific ones.

You can't change the SSLContext used by an existing SSLSocketFactory instance.

Unless your existing SSLSocketFactory differs from the default implementation with specific settings (e.g. something you would tweak on the created socket before returning it), what you're trying to do doesn't seem to fit the intended design patterns here.

Bruno
  • 119,590
  • 31
  • 270
  • 376
2

an arbitrary SSLSocketFactory to trust all certificates without replacing it

No. You have to set your own custom "Trust All Certificates" manager, otherwise the default one is being used which "consults" the java's default truststore which is cacerts in your JDK installation.

But from a security perspective if you are going to have no server authentication you might as well go with plain TCP and avoid the SSL overhead since you don't actually have any security at all the way you are following.

Cratylus
  • 52,998
  • 69
  • 209
  • 339
  • 1
    Hmm, I was afraid of that. I'll leave this question open to see if anyone else has another option, but if not I'll accept your answer – TheLQ May 23 '12 at 18:18
-1

Try this code....Its a working code, use this class in your code like this

HttpClient client = MySSLSocketFactory.getNewHttpClient();

Here is the code

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;

public class MySSLSocketFactory extends SSLSocketFactory {
    SSLContext sslContext = SSLContext.getInstance("TLS");

    public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
       super(truststore);

       TrustManager tm = new X509TrustManager() {
           public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
           }

           public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
           }

           public X509Certificate[] getAcceptedIssuers() {
               return null;
           }
       };

       sslContext.init(null, new TrustManager[] { tm }, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
       return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
       return sslContext.getSocketFactory().createSocket();
    }


public static HttpClient getNewHttpClient() {
    try {
       KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
       trustStore.load(null, null);

       SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
       sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

       HttpParams params = new BasicHttpParams();
       HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
       HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

       SchemeRegistry registry = new SchemeRegistry();
       registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
       registry.register(new Scheme("https", sf, 443));

       ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

       return new DefaultHttpClient(ccm, params);
    } catch (Exception e) {
       return new DefaultHttpClient();
    }
}

}
Kumar Vivek Mitra
  • 33,294
  • 6
  • 48
  • 75
  • 1
    Read the question again: I'm already replacing a SSLSocketFactory with my own, however I'm wanting to tell an existing factory to trust all certificates. I'm also not using any HTTP stuff, I'm using the raw socket – TheLQ May 23 '12 at 18:12
  • 6
    @EJP Trusting all certificates **is the point of this question**. Stop spamming the comments saying that its insecure, I know it is, and I'm working around it – TheLQ May 23 '12 at 23:51