6

Note: this question has been asked numerous times for Java HTTPS clients; my question is about configuring a server.

I'm trying to use MockWebServer to test my OkHttpClient configuration. The real web server my code hits just dropped TLS v1.0 support, so I'm changing my code to use TLS v1.2 and use the server's preferred cipher suites. I'd like to test this change with an in-memory web server that mimics the real server, but I can't figure out how to configure a SSLContext in my test with a specific list of cipher suites. (All the methods I need to access are pretty well protected inside of SSLContextImpl and its inner classes.)

The best I've been able to figure out is completely wrapping a SSLServerSocketFactory, overriding the 4 createServerSocket() methods, and calling setEnabledCipherSuites() on the SSLServerSocket before returning it, similar to how this answer did with SSLSocketFactoryEx on the client: https://stackoverflow.com/a/23365536/278800

It's frustrating that using a specific TLS version is as simple as calling e.g. SSLContext.getInstance("TLSv1.2"), but there isn't a similarly easy way to configure the cipher suites.

Steve K
  • 2,044
  • 3
  • 24
  • 37

2 Answers2

3

The way I ended up doing it was to wrap the underlying SSLSocketFactory, and call sslSocket.setEnabledCipherSuites(..) on the SSLSocket before returning it, like so:

final class MySSLSocketFactory extends SSLSocketFactory {
    final SSLSocketFactory wrappedSSLSocketFactory;

    MySSLSocketFactory(SSLSocketFactory wrappedSSLSocketFactory) {
        this.wrappedSSLSocketFactory = wrappedSSLSocketFactory;
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return getMyCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return getMyCipherSuites();
    }

    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        final SSLSocket sslSocket = (SSLSocket) wrappedSSLSocketFactory.createSocket(s, host, port, autoClose);

        // change the supported cipher suites on the socket, *before* it's returned to the client
        sslSocket.setEnabledCipherSuites(getMyCipherSuites());

        return sslSocket;
    }

    // other overloaded createSocket() methods do the same

    private String[] getMyCipherSuites() {
        // TODO: change this to return whatever cipher suites you want the server to use, from CipherSuite
        return new String[] {...};
    }
}
Steve K
  • 2,044
  • 3
  • 24
  • 37
-3

There isn't a similarly easy way to configure the cipher suites that the server accepts.

Err, yes there is. SSLServerSocket.setEnabledCipherSuites(). Why you don't consider this 'easy' is a mystery.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    That’s only changing it for a single socket, not the whole server. How would you configure the cipher suites in something like OkHttp’s MockWebServer (or hell, even a WireMock server)? – Steve K Jul 11 '18 at 02:17
  • 1
    Wanna open a feature request for OkHttp? Seems like something we should do. – Jesse Wilson Jul 11 '18 at 03:53
  • @JesseWilson is that what's already going on here? https://github.com/square/okhttp/tree/master/okhttp-tls – Steve K Jul 11 '18 at 19:33