How do I specify which ciphers to use on my axis2 https sender?

4.6k views Asked by At

Our WSO2 ESB connects to an SSL server, which has recently been patched to remove weak/insecure SSL protocols and ciphers. I have been able to change which protocol the Axis2 https sender uses by adding the following parameter to the https sender element in the axis2_blocking_client.xml configuration file

<transportSender name="https"
                 class="org.apache.axis2.transport.http.CommonsHTTPTransportSender">
    <parameter name="PROTOCOL">HTTP/1.1</parameter>
    <parameter name="HttpsProtocols">TLSv1,TLSv1.1,TLSv1.2</parameter>
    <parameter name="Transfer-Encoding">chunked</parameter>
    <parameter name="cacheHttpClient">true</parameter>
    <parameter name="defaultMaxConnectionsPerHost">200</parameter>
</transportSender>

But the ESB still fails to connect to the server with an SSL handshake error. Looking at a packet capture at the server, we see that none of the ciphers offered by the ESB are in the list of accepted ciphers by the server.

So my question is, How do I specify which ciphers to use (or which ones not to use) in my axis2 https sender configuration?

P.S. Here's what the server is accepting

 RSA_WITH_RC4_128_SHA
 RSA_WITH_3DES_EDE_CBC_SHA
 RSA_WITH_AES_128_CBC_SHA
 RSA_WITH_AES_256_CBC_SHA
 RSA_WITH_AES_128_CBC_SHA256
 RSA_WITH_AES_256_CBC_SHA256
 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

And here's what the ESB is offering

 TLS_RSA_WITH_AES_128_CBC_SHA
 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
 TLS_RSA_WITH_RC4_128_SHA
 TLS_RSA_WITH_3DES_EDE_CBC_SHA
 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
 TLS_RSA_WITH_RC4_128_MD5

P.P.S. Here's a packet capture from the server's point of view:

New TCP connection #3: XXX.XXX.XXX.XXX(40922) <-> XXX.XXX.XXX.XXX(8006) 1 1 1435165035.7617 (0.0292) C>SV3.1(185) Handshake ClientHello

    Version 3.1
    random[32]=
      55 8a e1 6b f3 30 a8 68 42 dd f0 b4 96 c6 39 9d
      15 78 3d bd b2 77 2b 76 39 82 c4 2e 98 be 71 92

    cipher suites
    Unknown value 0xc009
    Unknown value 0xc013
    TLS_RSA_WITH_AES_128_CBC_SHA
    Unknown value 0xc004
    Unknown value 0xc00e
    TLS_DHE_RSA_WITH_AES_128_CBC_SHA
    TLS_DHE_DSS_WITH_AES_128_CBC_SHA
    Unknown value 0xc007
    Unknown value 0xc011
    TLS_RSA_WITH_RC4_128_SHA
    Unknown value 0xc002
    Unknown value 0xc00c
    Unknown value 0xc008
    Unknown value 0xc012
    TLS_RSA_WITH_3DES_EDE_CBC_SHA
    Unknown value 0xc003
    Unknown value 0xc00d
    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
    TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
    TLS_RSA_WITH_RC4_128_MD5
    Unknown value 0xff
    compression methods
              NULL

1 2 1435165035.7617 (0.0000) S>CV3.1(2) Alert level fatal value handshake_failure 1 1435165035.7618 (0.0000) S>C TCP FIN

1

There are 1 answers

1
Bruno On BEST ANSWER

I haven't checked recent versions of Axis 2, but you should be able to set the protocol and cipher suites using the same principle as what's described in this question.

Essentially, you'd need to register SecureProtocolFactory with Apache HTTP Client 3.x (if it's still in use Axis 2):

Protocol.registerProtocol("https", new Protocol("https",
   (ProtocolSocketFactory)secureProtocolSocketFactory, 443));

You can extend or delegate the default behaviour of the factory to the existing implementation. However, before returning the SSLSocket instance from the createSocket methods, call setEnabledCipherSuites(...) and setEnabledProtocols(...) with the settings you require.

That said, from the cipher suites list your client is sending, and based on the assumption it wouldn't have been configured at all (so it would be using the default settings), my guess is that you might be running an old version of the JRE (see cipher suite table in the SunJSSE provider documentation).

I'm not sure how Axis2 deviates from the default settings via code, but if you're able to use Java 8, it might be worth trying the new jdk.tls.client.protocols system property (although with Java 8, TLS 1.2 should be enabled by default). In that case, you might not need to change any code at all. If possible, using the JCE Unlimited Strength Jurisdiction Policy Files would also help for the AES 256 cipher suites.

Following your edit, it seems that your client is actually sending more cipher suites names than you thought it was. What you're using to dump the ClientHello can't work out what those unknown values are, but it contains more cipher suites than you've written down. 0xc0009 would be TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (see full list). In terms of naming, the TLS_ or SSL_ prefix is rather flexible depending on the tool you use. OpenSSL and Java names aren't exactly the same either.

While this answer should answer "How do I specify which ciphers to use on my axis2 https sender?", this might not help you fix your actual problem.