Java SSL Exception, protocol_version when trying to use HttpClient to log into a website

23,238

Solution 1

*** 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 .

Solution 2

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();
        }

Solution 3

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.

Share:
23,238
Admin
Author by

Admin

Updated on October 01, 2020

Comments

  • Admin
    Admin over 3 years

    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