Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extended server_name (SNI Extension) not sent with jdk1.8.0 but send with jdk1.7.0

I have implemented a JAX-WS client by using ApacheCXF (v3.0.4) and everything works successfully but the problem comes when I want to use a secure connection (SSL/TLS) with java 8 (jdk1.8.0_25).

I see the following exception in log (-Djavax.net.debug=all):

main, handling exception: java.net.SocketException: Connection reset
main, SEND TLSv1.2 ALERT:  fatal, description =    unexpected_message
main, WRITE: TLSv1.2 Alert, length = 2
main, Exception sending alert: java.net.SocketException: Connection reset by peer: socket write error

After a depeer analysis I have observed the problem is caused because the with Java 8 the server_name (SNI) is not sent but with Java 7 it is sent and the web service invocation works successfully.

Java 8 log (-Djavax.net.debug=all): Missing "Extension server_name"

[...]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
***
[...]

Java 7 log (-Djavax.net.debug=all) (works): "Extension server_name" is set

[...]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
Extension server_name, server_name: [host_name: testeo.hostname.es]
***
[...]

It is observed that with Java 7 the Extension server_name, server_name: [host_name: testeo.hostname.es] is set and then the web service invocation works successfully.

Why didn't Java 8 set the server_name as Java 7 did? Is it a Java configuration issue?

like image 270
hints4dev Avatar asked Jun 13 '15 11:06

hints4dev


3 Answers

As mentioned, the cause is related to the JDK bug where using setHostnameVerifier() breaks SNI (Extension server_name). https://bugs.openjdk.java.net/browse/JDK-8144566

Our workaround: After testing we found that setting a connection's SSLSocketFactory to just about anything from the default seems to fix the issue.

This does not work: HttpsURLConnection.setSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault());

This does work: HttpsURLConnection.setSSLSocketFactory(new SSLSocketFactoryFacade());

So, to fix it for a JAX-WS client, you could do something like this: bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", new SSLSocketFactoryFacade());

Our SSLSocketFactory facade: (Note that it really doesn't do anything)

public class SSLSocketFactoryFacade extends SSLSocketFactory {

    SSLSocketFactory sslsf;

    public SSLSocketFactoryFacade() {
        sslsf = (SSLSocketFactory) SSLSocketFactory.getDefault();;
    }

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

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

    @Override
    public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException {
        return sslsf.createSocket(socket, s, i, b);
    }

    @Override
    public Socket createSocket(String s, int i) throws IOException, UnknownHostException {
        return sslsf.createSocket(s, i);
    }

    @Override
    public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException, UnknownHostException {
        return sslsf.createSocket(s, i, inetAddress, i1);
    }

    @Override
    public Socket createSocket(InetAddress inetAddress, int i) throws IOException {
        return createSocket(inetAddress, i);
    }

    @Override
    public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException {
        return createSocket(inetAddress, i, inetAddress1, i1);
    }
}
like image 125
Benjamin Parry Avatar answered Oct 20 '22 13:10

Benjamin Parry


Please use JDK version 8u141 and above where this issue has been fixed. Please review the JDK 8u141 Bugs Fixes page for more details

like image 10
Harish Kumar Avatar answered Oct 20 '22 12:10

Harish Kumar


You, or the underlying libs (the WS lib does it) might be using setHostnameVerifier(..)

There is a bug in java8, where if setHostnameVerifier(..) is used the SNI is not done from the client side.

https://bugs.openjdk.java.net/browse/JDK-8072464

like image 9
Patrik Beck Avatar answered Oct 20 '22 14:10

Patrik Beck