4
votes

what is wrong with this code, it is supposed to trust all hosts, but it doesn't..

It works fine with for example google.com but not with an API Gateway service running locally on my machine, why?

SSL DEBUG OUTPUT

trigger seeding of SecureRandom done seeding SecureRandom Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 ... Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 Allow unsafe renegotiation: false Allow legacy hello messages: true Is initial handshake: true Is secure renegotiation: false Thread-6, setSoTimeout(0) called %% No cached client session *** ClientHello, TLSv1 RandomCookie: GMT: 1434280256 bytes = { 216 ... 40 } Session ID: {} Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, .... SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV] Compression Methods: { 0 } Extension elliptic_curves, curve names: {secp256r1 .. secp256k1} Extension ec_point_formats, formats: [uncompressed]

Thread-6, WRITE: TLSv1 Handshake, length = 163 Thread-6, READ: TLSv1 Alert, length = 2 Thread-6, RECV TLSv1 ALERT: fatal, handshake_failure Thread-6, called closeSocket() Thread-6, handling exception: javax.net.ssl.SSLHandshakeException: **

Received fatal alert: handshake_failure


**

import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;

public class ConnectHttps {
  public static void main(String[] args) throws Exception {
    /*
     *  fix for
     *    Exception in thread "main" javax.net.ssl.SSLHandshakeException:
     *       sun.security.validator.ValidatorException:
     *           PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
     *               unable to find valid certification path to requested target
     */
    TrustManager[] trustAllCerts = [
        [ getAcceptedIssuers: { -> null },
          checkClientTrusted: { X509Certificate[] certs, String authType -> },
          checkServerTrusted: { X509Certificate[] certs, String authType -> } ] as X509TrustManager
    ]

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

    // Create all-trusting host name verifier
    HostnameVerifier allHostsValid = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
          return true;
        }
    };
    // Install the all-trusting host verifier
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    /*
     * end of the fix
     */

    //URL url = new URL("https://google.com"); //WORKS
    URL url = new URL("https://localhost:8090");   // DOES NOT WORK, WHY?
    URLConnection con = url.openConnection();
    Reader reader = new InputStreamReader(con.getInputStream());
    while (true) {
      int ch = reader.read();
      if (ch==-1) {
        break;
      }
      System.out.print((char)ch);
    }
  }
}

Running the code found here it shows that TLSv1.2 is not enabled on the client side:

Supported Protocols: 5
SSLv2Hello
SSLv3
TLSv1
TLSv1.1
TLSv1.2

Enabled Protocols: 2
SSLv3
TLSv1

1

1 Answers

6
votes

.. it is supposed to trust all hosts, but it doesn't..

.. RECV TLSv1 ALERT: fatal, handshake_failure Thread-6

A handshake failure alert from the server is unrelated to the validation of the servers certificate on the client and can thus not stopped by disabling certificate validation. Lots of things can cause such a failure, like no common ciphers, unsupported protocol version, missing SNI extension (only supported starting with JDK7). Since the error is issued by the server you might find more details about the problem in the servers log messages.

EDIT: from the server logs the cause of the problem is visible:

error handling connection: SSL protocol error error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher

This means that there is no common cipher between client and server.

A typical cause for this is a wrong setup of the certificates at the server. If you don't configure any certificates the server might require anonymous authentication with ADH ciphers, which are usually not enabled on the client side. I suggest that you check if you could connect with a browser.

Another common misconfiguration is disabling all SSLv3 ciphers at the server in the believe that this is necessary to disable the SSL3.0 protocol (it is not). This effectively disables all ciphers except some new ciphers introduced with TLS 1.2. Modern browsers will be still able to connect but older clients not. This misconfiguration can be seen in this case (from the comment):

From server log,, interface ciphers: FIPS:!SSLv3:!aNULL,,

!SSLv3 disables all ciphers available for version SSL3.0 and higher. This in effect leaves only the TLS1.2 ciphers because there are no new ciphers with TLS1.0 and TLS1.1. Since the client seems to be only support TLS1.0 there will be no shared ciphers:

...WRITE: TLSv1 Handshake

Use of !SSLv3 in the ciphers is usually caused by a lack of understanding of the difference between protocol version and ciphers. To disable SSLv3 you should only set the protocol accordingly but not the ciphers.