1

I know the reason why browsers and java7 are not affected is because they send Server Name Indication-SNI as part of the SSL information. So, apache knows what virtual host to use before starting SSL handshake and returns the proper certificate. Java 6 doesn't support SNI. So My question is, how do I verify and allow certificate to be accepted in java 6.

I made a spring client to consume webservice, Here is my code

public class classname1 {

    static {
        System.setProperty("javax.net.ssl.trustStore", "E://Workspace//keystore");
        System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
        System.setProperty("https.protocols", "SSLv3");
        System.setProperty("https.protocols", "TLSv1");

    }
    static {

                HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
                    {
                        public boolean verify(String hostname, SSLSession session)
                        {
                            if (hostname.equals("192.168.10.22"))
                                return true;
                            return false;
                        }
                    });
            }

    private static void main(String[] args) {
        try {
            SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
            SOAPConnection soapConnection = soapConnectionFactory.createConnection();

            String url = "https://192.168.10.22/getInformationSearch.asmx?wsdl";
            SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);
            printSOAPResponse(soapResponse);
            soapConnection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static SOAPMessage createSOAPRequest() throws Exception {
        // ... Code for request, which will be hitted to url
    }

    private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception {
        // ... Code for response, which will fetch information from webservice
        // URL
    }

}

As you can see code, I made two methods, 1. for Request createSOAPRequest() 2. for Response printSOAPResponse(). (Url name is changed in above snippet)

In main() method, below line will generate request and send that request to given url SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url); after that it goes to static block as shown above HttpsURLConnection.setDefaultHostnameVerifier() method.

At that time,debugger says: ssl handshake failed and SSL peer shut down incorrectly. It happens only in JAVA 6 but these code working proper with java 7/8.

Instead of that static block, I have tried below code in java 6

 HostnameVerifier hv = new HostnameVerifier() {
                public boolean verify(String urlHostName,
                        SSLSession session) {
                    return true;
                }
            };

But it won't work anyhow!!!

I am using following jars xercesImpl.jar,saaj-api.jar,saaj-impl.jar,spring-ws-core-1.5.6.jar,spring-ws-security-1.5.6.jar and Certificate for this SSL domain has been imported into keystore and It works in java7/8, So there is no issue in truststore right? (I made 2 certificate using keytool of java 6 and 7 as well, both works fine in java7/8 but not in 6)

I followed this thread but it wont work. So is there any alternative way to verify certificate and get response in java 6 environment, or should I change any JAR ?

Community
  • 1
  • 1

2 Answers2

2

As you already mentioned Java 6 does not support SNI. But, the problem of missing SNI is not only with verifying the certificate (because the server sends the wrong certificate) but also that depending on the servers configuration the server will cause a handshake error if the SNI extension is not present and does not point to a hostname available at the server. And this is obviously the case here:

... ssl handshake failed and SSL peer shut down incorrectly. It happens only in JAVA 6 but these code working proper with java 7/8.

Trying to change the validation of the certificate as you've tried will not help at all in this case because the error occurs before the client even has a certificate to verify. This means that there is no way around it: you need to support SNI in your client if you want to communicate with this specific server.

Steffen Ullrich
  • 90,680
  • 7
  • 99
  • 140
2

You can't if the server isn't configured to allow you to connect without SNI.

Without SNI, the server cannot tell which virtual host you want until after the SSL connection has been established.

To see the difference, if you have OpenSSL, you can use the s_client option to extract the different certificates presented, or perhaps note a failure to connect when you don't use SNI:

SNI:

echo | openssl s_client -servername www.virtualhost.com -connect 192.168.1.55:443 | openssl x509 -text

Replace 192.168.1.55 with the actual IP address of the server, and www.virtualhost.com with the host name of the virtual host you want to connect to. The echo command prepended to the pipeline prevents openssl from hanging in a wait for input.

Without SNI:

echo | openssl s_client -connect 192.168.1.55:443 | openssl x509 -text

Without SNI, you may see a completely different certificate, or you may get a connection error.

Andrew Henle
  • 27,654
  • 3
  • 23
  • 49