Java SSL Exception, protocol_version when trying to use HttpClient to log into a website
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.
Admin
Updated on October 01, 2020Comments
-
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