2

I'm seeing handshake_failure with client running on JDK 1.6. How can I configure the JDK 1.6 to allow the client to connect?

I suspect the problem is either with SSLv2 client hello or an unsupported cipher but not 100% sure which.

Client debug output:

Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
Client, setSoTimeout(61000) called
%% No cached client session
*** ClientHello, TLSv1
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
***
Client, WRITE: TLSv1 Handshake, length = 75
Client, WRITE: SSLv2 client hello message, length = 101
Client, received EOFException: error
Client, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Client
, SEND TLSv1 ALERT:  
fatal, 
description = handshake_failure

I understand another approach (not ideal) is to allow SSLv2Hello pseudo protocol on the remote server. I'd hang my head in shame & ask the provider to allow SSLv2Hello but I'm not sure even that would allow the connection to succeed based on the available ciphers.

shnplr
  • 230
  • 3
  • 12
  • What is the value of `jdk.tls.disabledAlgorithms` in the `$JAVA_HOME/lib/security/java.security` file, assuming it exists? You may be able to disable SSLv2Hello and SSLv3 there. – Andrew Henle May 17 '16 at 11:36
  • 2
    You are exposed to break another running apps if you are sharing the same virtual machine, is not a good idea change the java.security default values. – vzamanillo May 17 '16 at 11:41
  • @vzamanillo Modifying a configuration file - which exists to be modified so configurations can change when needed - is a lot more reliable, faster, requires less labor, and is a lot cheaper than attempting to force-fit custom code into a legacy application where source code isn't available. "More code" is not the solution to every problem - in fact, "more code" is usually the least reliable and most expensive option. – Andrew Henle May 17 '16 at 12:06
  • I am not completly agree, but that is another discussion. – vzamanillo May 17 '16 at 12:16
  • For the record, adding jdk.tls.disabledAlgorithms=SSLv2Hello in java.security did not prevent the SSLv2 client hello message from being sent. – shnplr May 18 '16 at 03:38
  • @shnplr Is the connection being made an SSLv2, SSLv3, or TLS connection? – Andrew Henle May 18 '16 at 14:09

1 Answers1

2

SSLv2 and SSLv3 are deprecated protocols due to security issues (CVE-2014-3566 or Poodle, etc...) so is not a good idea force the server to accept it.

Nor is it necessary to upgrade the client's JVM up to 6 (as long as the server accepts TLSv1), you just have to disable the above protocols creating a custom socket factory (extending the default SSLSocketFactory), then remove it and set the enabled protocols when you create the socket

private Socket removeSSLv2v3(Socket socket) {

    if (!(socket instanceof SSLSocket)) {
        return socket;
    }

    SSLSocket sslSocket = (SSLSocket) socket;

    String[] protocols = sslSocket.getEnabledProtocols();
    Set<String> set = new HashSet<String>();
    for (String s : protocols) {
        if (s.equals("SSLv3") || s.equals("SSLv2Hello")) {
            continue;
        }
        set.add(s);
    }
    sslSocket.setEnabledProtocols(set.toArray(new String[0]));

    return sslSocket;
}

An example using Apache HttpComponents 4.4.1 (accepting Java 6 secure protocols only)

SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
sslContextBuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContextBuilder.build(), new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());

CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

Or you can set the enabled protocols via properties in command line while executing your client (for Java 6, it accepts TLSv1 only)

java -Dhttps.protocols="TLSv1" <MyClient>

or

java -Dhttps.protocols=TLSv1 <MyClient>
vzamanillo
  • 9,905
  • 1
  • 36
  • 56
  • Unfortunately the runtime framework is closed source, otherwise I'm sure I could make it work using the example provided. I tried setting -Dhttps.protocols system property in the startup command where I also set -Djavax.net.debug, but SSLv2Hello is still sent – shnplr May 17 '16 at 10:43
  • Then you can update your Java version up to 6 to run your client, Java 7 uses TLSv1 by default, Java 8 uses TLSv1.2 – vzamanillo May 17 '16 at 11:03
  • I'm not sure what you mean by "update your Java version up to 6 to run your client" - I'm already running 1.6. I tested successfully using JDK 1.7 and it selected TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - is this cipher supported in Java 6 - if they enable SSLv2Hello will it work from the 1.6 client? – shnplr May 17 '16 at 11:29
  • Sorry, language mistake, with "up to 6" I meant > 6. TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA is supported by Java 6, it will work if the server side accepts SSLv2Hello, but is a deprecated (and insecure) protocol so keeping Java 7 is the best choice. – vzamanillo May 17 '16 at 11:38
  • The server has now enabled SSLv2Hello and I can see from ssllabs report that SSL 2 handshake compatibility: Yes - however the handshake still fails with EOFException. The ssllabs report shows: Java 6u45 footnote: No SNI 2 Server closed connection where footnote 2 is: No support for virtual SSL hosting (SNI). Connects to the default site if the server uses SNI. Any ideas? – shnplr May 17 '16 at 23:39
  • It seems it might be possible to use the BC provider to get the necessary cipher enabled along with remote server to allow SSLv2 handshake compatibility. Thanks for the feedback it helped a lot. – shnplr May 18 '16 at 03:28