3

I have a Java program that I am trying to get to talk to a website that uses an HTTPS connection with TLSv1. (Checked with FireFox.)

The problem is that I still get a protocol_version exception. Here is the stack trace:

    javax.net.ssl.SSLException: Received fatal alert: protocol_version
2015-07-28 14:48:38 [INFO ] 
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:290)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:259)
    at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:125)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:319)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
    at org.openhab.binding.honeywellwifithermostat.handler.honeywellWifiThermostatHandler.getHoneywellWebsiteAuthCookie(honeywellWifiThermostatHandler.java:91)
    at org.openhab.binding.honeywellwifithermostat.handler.honeywellWifiThermostatHandler.initialize(honeywellWifiThermostatHandler.java:73)
    at org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory.registerHandler(BaseThingHandlerFactory.java:116)
    at org.eclipse.smarthome.core.thing.internal.ThingManager$6.call(ThingManager.java:480)
    at org.eclipse.smarthome.core.thing.internal.ThingManager$6.call(ThingManager.java:1)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Here is the relevant Java source:

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.SSLContext;

import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.eclipse.smarthome.config.core.Configuration;
import org.eclipse.smarthome.core.thing.ChannelUID;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandler;
import org.eclipse.smarthome.core.types.Command;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The {@link honeywellWifiThermostatHandler} is responsible for handling commands, which are
 * sent to one of the channels.
 *
 * @author  - Initial contribution
 */
public class honeywellWifiThermostatHandler extends BaseThingHandler {

    private Logger logger = LoggerFactory.getLogger(honeywellWifiThermostatHandler.class);

    private String userName = null;
    private String passWord = null;

    public honeywellWifiThermostatHandler(Thing thing) {
        super(thing);
    }

    @Override
    public void handleCommand(ChannelUID channelUID, Command command) {
        if (channelUID.getId().equals(CHANNEL_1)) {
            // TODO: handle command
        }
    }

    @Override
    public void initialize() {
        // TODO Auto-generated method stub
        Configuration conf = this.getConfig();

        if (conf.get("userName") != null) {
            userName = String.valueOf(conf.get("userName"));
        }
        if (conf.get("passWord") != null) {
            passWord = String.valueOf(conf.get("passWord"));
        }

        logger.debug("Attempting to get auth cookie for Honeywell site.");
        getHoneywellWebsiteAuthCookie(userName, passWord);

        super.initialize();
    }

    public void getHoneywellWebsiteAuthCookie(String userName, String passWord) {

        CloseableHttpClient httpclient;
        try {
            SSLContext ctx = SSLContexts.custom().useProtocol("TLSv1").build();
            httpclient = HttpClientBuilder.create().setSslcontext(ctx).build();

            HttpPost httpPost = new HttpPost("https://www.mytotalconnectcomfort.com/portal/");
            List<NameValuePair> fields = new ArrayList<NameValuePair>();
            fields.add(new BasicNameValuePair("UserName", userName));
            fields.add(new BasicNameValuePair("Password", passWord));

            httpPost.setEntity(new UrlEncodedFormEntity(fields));
            CloseableHttpResponse resp = httpclient.execute(httpPost);

            logger.debug("Status line: {}", resp.getStatusLine());
        } catch (IOException | NoSuchAlgorithmException | KeyManagementException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

Any ideas out there? Even an idea of how I could trace this down?

UPDATE

I got the debug information from the Java VM. It gives a bunch of errors about unsupported cipher suites, then maybe tries to fallback to SSLv3? I'm not too strong with crypto stuff. Again, any help is much appreciated.

-------------------------  NET DEBUG CRAP ---------------------------
trustStore is: /usr/lib/jvm/java-8-openjdk/jre/lib/security/cacerts
trustStore type is : jks
trustStore provider is : 
init truststore

== REMOVED ADDING TRUSTED ROOT CERT MESSAGES ==

trigger seeding of SecureRandom
done seeding SecureRandom
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
%% No cached client session
*** ClientHello, TLSv1.2
RandomCookie:  GMT: 1421269547 bytes = { 179, 68, 198, 137, 7, 197, 13, 106, 3, 187, 99, 160, 117, 164, 48, 226, 113, 136, 166, 199, 101, 82, 195, 192, 46, 52, 140, 181 }
Session ID:  {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
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: [type=host_name (0), value=www.mytotalconnectcomfort.com]
***
[write] MD5 and SHA1 hashes:  len = 219
0000: 01 00 00 D7 03 03 55 B7   DA 2B B3 44 C6 89 07 C5  ......U..+.D....
0010: 0D 6A 03 BB 63 A0 75 A4   30 E2 71 88 A6 C7 65 52  .j..c.u.0.q...eR
0020: C3 C0 2E 34 8C B5 00 00   2C C0 0A C0 14 00 35 C0  ...4....,.....5.
0030: 05 C0 0F 00 39 00 38 C0   09 C0 13 00 2F C0 04 C0  ....9.8...../...
0040: 0E 00 33 00 32 C0 08 C0   12 00 0A C0 03 C0 0D 00  ..3.2...........
0050: 16 00 13 00 FF 01 00 00   82 00 0A 00 34 00 32 00  ............4.2.
0060: 17 00 01 00 03 00 13 00   15 00 06 00 07 00 09 00  ................
0070: 0A 00 18 00 0B 00 0C 00   19 00 0D 00 0E 00 0F 00  ................
0080: 10 00 11 00 02 00 12 00   04 00 05 00 14 00 08 00  ................
0090: 16 00 0B 00 02 01 00 00   0D 00 1A 00 18 06 03 06  ................
00A0: 01 05 03 05 01 04 03 04   01 03 03 03 01 02 03 02  ................
00B0: 01 02 02 01 01 00 00 00   22 00 20 00 00 1D 77 77  ........". ...ww
00C0: 77 2E 6D 79 74 6F 74 61   6C 63 6F 6E 6E 65 63 74  w.mytotalconnect
00D0: 63 6F 6D 66 6F 72 74 2E   63 6F 6D                 comfort.com
ESH-safeCall-2, WRITE: TLSv1.2 Handshake, length = 219
[Raw write]: length = 224
0000: 16 03 03 00 DB 01 00 00   D7 03 03 55 B7 DA 2B B3  ...........U..+.
0010: 44 C6 89 07 C5 0D 6A 03   BB 63 A0 75 A4 30 E2 71  D.....j..c.u.0.q
0020: 88 A6 C7 65 52 C3 C0 2E   34 8C B5 00 00 2C C0 0A  ...eR...4....,..
0030: C0 14 00 35 C0 05 C0 0F   00 39 00 38 C0 09 C0 13  ...5.....9.8....
0040: 00 2F C0 04 C0 0E 00 33   00 32 C0 08 C0 12 00 0A  ./.....3.2......
0050: C0 03 C0 0D 00 16 00 13   00 FF 01 00 00 82 00 0A  ................
0060: 00 34 00 32 00 17 00 01   00 03 00 13 00 15 00 06  .4.2............
0070: 00 07 00 09 00 0A 00 18   00 0B 00 0C 00 19 00 0D  ................
0080: 00 0E 00 0F 00 10 00 11   00 02 00 12 00 04 00 05  ................
0090: 00 14 00 08 00 16 00 0B   00 02 01 00 00 0D 00 1A  ................
00A0: 00 18 06 03 06 01 05 03   05 01 04 03 04 01 03 03  ................
00B0: 03 01 02 03 02 01 02 02   01 01 00 00 00 22 00 20  .............". 
00C0: 00 00 1D 77 77 77 2E 6D   79 74 6F 74 61 6C 63 6F  ...www.mytotalco
00D0: 6E 6E 65 63 74 63 6F 6D   66 6F 72 74 2E 63 6F 6D  nnectcomfort.com
[Raw read]: length = 5
0000: 15 03 00 00 02                                     .....
[Raw read]: length = 2
0000: 02 46                                              .F
ESH-safeCall-2, READ: SSLv3 Alert, length = 2
ESH-safeCall-2, RECV TLSv1.2 ALERT:  fatal, protocol_version
ESH-safeCall-2, called closeSocket()
ESH-safeCall-2, handling exception: javax.net.ssl.SSLException: Received fatal alert: protocol_version
3
  • Have you tried to enable ssl debugging via System.setProperty("javax.net.debug", "all");? Commented Jul 28, 2015 at 19:02
  • Is there a way to set that on the command line? I inserted that code into the initialize() function in the above code, but I do not see any output. I am developing on OpenHAB which is an OSGi application, using Eclipse. Commented Jul 28, 2015 at 19:35
  • Ha ha, nevermind that was a simple google search. Commented Jul 28, 2015 at 19:38

4 Answers 4

4

*** ClientHello, TLSv1.2

You are using TLS 1.2. But unfortunately the server does not understand TLS 1.2 at all and will cause a handshake failure. Tests with my analyze-ssl.pl show:

 * supported SSL versions with handshake used and preferred cipher(s):
  * handshake protocols ciphers
  * SSLv23    TLSv1     RC4-MD5
  * TLSv1_2   FAILED: SSL connect attempt failed error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
  * TLSv1_1   FAILED: SSL connect attempt failed error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
  * TLSv1     TLSv1     RC4-MD5
  * SSLv3     FAILED: SSL connect attempt failed because of handshake problems error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version

Thus the server simply fails on TLSv1_2 handshakes.

You are trying to set TLS 1.0 inside your code:

        SSLContext ctx = SSLContexts.custom().useProtocol("TLSv1").build();

Unfortunately the documentation states that 'TLSv1' is not only TLS 1.0 but

TLSv1   Supports RFC 2246: TLS version 1.0 ; may support other versions

Thus it tries with the best version it can (TLS1.2) and fails because the server is broken. BTW, Chrome and Firefox only succeed because they retry with a lower protocol version on such errors. I don't do Java myself but based on the various documentation I've found on the net you probably need to do something like:

   sslSocket.setEnabledProtocols(new String[] {"SSLv2Hello", "TLSv1" })

which should remove the support for TLS1.1 and TLS1.2 .

Sign up to request clarification or add additional context in comments.

Comments

4

Steffen,

That answer got me on the right track. For anyone else that has a future problem, here is some code that works to force an Apache HttpClient to use TLSv1:

CloseableHttpClient httpclient;
        try {

            SSLContext ctx = SSLContexts.createSystemDefault();

            SSLConnectionSocketFactory fac = new SSLConnectionSocketFactory(ctx, new String[] { "TLSv1" }, null,
                    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            httpclient = HttpClientBuilder.create().setSSLSocketFactory(fac).build();

            HttpPost httpPost = new HttpPost("https://mytotalconnectcomfort.com/portal/");
            List<NameValuePair> fields = new ArrayList<NameValuePair>();
            fields.add(new BasicNameValuePair("UserName", userName));
            fields.add(new BasicNameValuePair("Password", passWord));

            httpPost.setEntity(new UrlEncodedFormEntity(fields));
            CloseableHttpResponse resp = httpclient.execute(httpPost);

            logger.debug("Status line: {}", resp.getStatusLine());
            // } catch (IOException | NoSuchAlgorithmException | KeyManagementException e) {
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

Comments

1

Quick Solution(Java 8): -Djdk.tls.client.protocols=TLSv1

Details: I had the same problem as in my application. This is the client view using -Djavax.net.debug=ssl:handshake

myScheduler-1, WRITE: TLSv1.2 Handshake, length = 189 
myScheduler-1, READ: TLSv1 Alert, length = 2 
myScheduler-1, RECV TLSv1.2 ALERT: fatal, protocol_version 
myScheduler-1, called closeSocket()
myScheduler-1, handling exception: javax.net.ssl.SSLException: Received fatal alert: protocol_version

My WebLogic server (10.3.6) only supports TLSv1. After upgrading the client to Java 8, it would no longer authenticate using SSL(as seen above). The projects web client is an older version of the Apache http client(4.1.3). Java 8 adds the new system property jdk.tls.client.protocols that allows a user to set the available JSSE protocols. For details, see http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#InstallationAndCustomization After the Java 8 upgrade, the client would no longer accept the TLSv1 handshake that the server was responding with and would fail as shown. I added -Djdk.tls.client.protocols=TLSv1 to the client startup, restarted the client, and the problem was immediately resolved. Note that I did try the https.protocols system property per https://blogs.oracle.com/java-platform-group/entry/diagnosing_tls_ssl_and_https but it did not work for me. I am assuming it failed because I am using Apache and, as the page notes, it pertains to

https connections through use of the HttpsURLConnection class or via URL.openStream() operations

but I did not test it extensively.

Comments

0

I'm using apache-tomcat-7.0.70 with jdk1.7.0_45 and none of the solutions here and elsewhere on stackoverflow worked for me. Just sharing this solution as it hopefully might help someone as this is very high on Google's search

What worked is doing BOTH of these steps:

  1. Starting my tomcat with "export JAVA_OPTS="$JAVA_OPTS -Dhttps.protocols=TLSv1.2" by adding it to tomcat/bin/setenv.sh (Syntax slightly different on Windows)

  2. Manually building/forcing HttpClients or anything else you need with the TLS1.2 protocol:

    Context ctx = SSLContexts.custom().useProtocol("TLSv1.2").build();
    HttpClient httpClient = HttpClientBuilder.create().setSslcontext(ctx).build();
    HttpPost httppost = new HttpPost(scsTokenVerificationUrl);
    
    List<NameValuePair> paramsAccessToken = new ArrayList<NameValuePair>(2);
    paramsAccessToken.add(new BasicNameValuePair("token", token));
    paramsAccessToken.add(new BasicNameValuePair("client_id", scsClientId));
    paramsAccessToken.add(new BasicNameValuePair("secret", scsClientSecret));
    httppost.setEntity(new UrlEncodedFormEntity(paramsAccessToken, "utf-8"));
    
    //Execute and get the response.
    HttpResponse httpResponseAccessToken = httpClientAccessToken.execute(httppost);
    
    String responseJsonAccessToken = EntityUtils.toString(httpResponseAccessToken.getEntity());
    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.