Java SSL handshake alert no_negotiation - java

This error happened while communicating with a webservice.
Client reported error:
javax.net.ssl.SSLException: Received fatal alert: unexpected_message
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:1991)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1098)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:903)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:102)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:687)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:633)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1324)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:468)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:2223)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:2192)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:2036)
and there was an error in server log
javax.net.ssl.SSLProtocolException: handshake_alert

It looked like server was not updated to RFC 5746.
I stumbled upon https://www.digicert.com/news/2011-06-03-ssl-renego.htm and foud
If the server does not respond in accordance with RFC 5746, the client MUST abort the renegotiation handshake.
Then I found http://www.oracle.com/technetwork/java/javase/overview/tlsreadme2-176330.html
sun.security.ssl.allowUnsafeRenegotiation - Introduced in Phase 1, this controls whether legacy (unsafe) renegotiations are permitted.
A temporary fix was to add System property
-Dsun.security.ssl.allowUnsafeRenegotiation=true
but that turned out not to be the real reason error happened. The real reason was that my client was using old SSL.
tlsClientParameters.setSecureSocketProtocol("SSL");
I commented that line, so the default value is used: "TLS" and after that the communication worked just fine.

Related

Java "Remote host closed connection during handshake" using Bittrex HTTP API

I've suddenly been getting these errors when making HTTP requests:
Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1002)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
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.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
at com.mashape.unirest.http.HttpClientHelper.request(HttpClientHelper.java:138)
... 24 more
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:505)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983)
... 41 more
It didn't always do this, it was working fine for awhile. I then used different libraries and even a different IntelliJ project for testing, still the same issues. Things I've tried:
Changing the endpoint I'm using
Setting the TLS version to TLSv1.2 (as I found when making a browser request)
I can load the endpoint fine with a browser and Postman. My code (using the Unirest library):
System.setProperty("https.protocols", "TLSv1.2");
System.out.println(Unirest.get("https://bittrex.com/api/v1.1/public/getmarketsummary?market=btc-ltc").asString().getBody());
I'm at a loss as to what could be causing this issue, and it's extremely frustrating. Any help would be appreciated.
EDIT: Updating to JDK10 fixed the issue. See the chosen answer and it's comment thread for more info.
First, turn on SSL debug: -Djavax.net.debug=all
Redirect your code's stdout to a file and check it for errors around handshaking.
If you examine the url you use with nmap or openssl:
nmap --script ssl-enum-ciphers -p <port> <host>
or
openssl s_client -connect <host>:<port>
(host: bittrex.com, port: 443)
you can see that is uses TLSv1.2 and ECDHE-ECDSA-AES128-GCM-SHA256 cypher:
New, TLSv1/SSLv3, Cipher is ECDHE-ECDSA-AES128-GCM-SHA256
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-ECDSA-AES128-GCM-SHA256
Depending on your JDK version, you may need to install JCE extension and/or specify this cypher.
To be sure, you should print out the current supported cyphers using this little java code. If ECDHE-ECDSA-AES128-GCM-SHA256 not listed, this is your problem.

SSL Handshake Error using Java

I am trying to connect a java client with a JMX server using SSL certificate.
But unfortunately this connection gives a SSL Handshake error. When I tried to debug this, using -Djavax.net.debug=all flag, I get the following error message on the java client.
2016-07-15T13:29:50.02-0700 [APP/0] OUT RMI RenewClean-[10.200.0.27:44445,javax.rmi.ssl.SslRMIClientSocketFactory#305a99f7], READ: TLSv1.2 Alert, length = 2
2016-07-15T13:29:50.02-0700 [APP/0] OUT RMI RenewClean-[10.200.0.27:44445,javax.rmi.ssl.SslRMIClientSocketFactory#305a99f7], RECV TLSv1 ALERT: fatal, handshake_failure
2016-07-15T13:29:50.02-0700 [APP/0] OUT RMI RenewClean-[10.200.0.27:44445,javax.rmi.ssl.SslRMIClientSocketFactory#305a99f7], called closeSocket()
2016-07-15T13:29:50.02-0700 [APP/0] OUT RMI RenewClean-[10.200.0.27:44445,javax.rmi.ssl.SslRMIClientSocketFactory#305a99f7], handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
When I change the client to something else, like a JConsole, the connection works fine using the same SSL certificate and the truststore, which indicates that there is nothing wrong with the SSL certificate or the domain its connecting to.
It seems that the handshake was failing due to incorrect TLS version types.
My client was running on Java7 which was using TLS version 1, while the server was running Java8 which was using TLS version 1.2.
Check this oracle blog, which mentions that Java8 will default use TLS version 1.2
So, when I upgraded my client to use Java8, the issue got resolved.
Hope, this helps someone else as well.

Getting "Received fatal alert: handshake_failure" in specific machine

I am running the same jar file in different machines. In one machine it is working fine, means while hitting different URL's able to get the proper response always.
But in another machine, at beginning all the URL's are working fine, after some period of time say 6 hours, it start throwing "handshake_failure" for few URL's (which are all working fine at beginning).
I understood that the "handshake_failure" may occurs due to SSL certificate issue or protocol issue (client and server has no common protocol)..
But here,
Same URL is working during the start of application. So it wont be
due to SSL certificate or protocol issue.
Same URL is working during the start of application, so it wont be
due to the URL blocking from the server , Like white-listing etc,,
Also same jar file is used in both the machines , so it wont be due
to code issue.
Also application working fine once we start the application (restart
the jar file).
Over all i suspect that there may be any chances of difference in any of configuration between the machines?
It would be great if any one can help me in this.
Exception:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) [na:1.6]
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136) [na:1.6]
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1720) [na:1.6]
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:954) [na:1.6]
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138) [na:1.6]
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:632) [na:1.6]
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59) [na:1.6]
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65) [na:1.6.0_26]
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123) [na:1.6.0_26]
at org.owasp.webscarab.model.Request.writeDirect(Request.java:234) [webscarab-selfcontained-20070504-1631.jar:na]
at org.owasp.webscarab.model.Request.writeDirect(Request.java:215) [webscarab-selfcontained-20070504-1631.jar:na]
at org.owasp.webscarab.httpclient.URLFetcher.fetchResponse(URLFetcher.java:267) [siteprofiler.jar:na]
at org.owasp.webscarab.plugin.proxy.ConnectionHandler.run(ConnectionHandler.java:346) [siteprofiler.jar:na]
at java.lang.Thread.run(Thread.java:662) [na:1.6.0_26]

SSL handshake unrecognized_name exception

We have a process use HttpClient to make https connection with different URLs. Our JDK version is 1.7. We found some URLs, if we use default JSSE SIN extension flag, which is turn on, we got the following exception:
javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name
If we set -Djsse.enableSNIExtension=false, some other URLs throw this exception:
javax.net.ssl.SSLException: Received fatal alert: unrecognized_name
Does anybody have idea about this?
The SNI extension will add the server_name(hostname) in the client hello message at the SSL handshake stage.
It may be needed by a server that serves requests for different hostnames or virtual hosts. It is used to resolve the Certificate for the hostname the client intend to communicate with. The server may be configured with a default certificate if the host name is not added or not found. The default certificate may be a multisigned certificate for all the hosts it serves.
The first warning you get may be a server responding with a default certificate but that also warns that the hostname is not recognized. The server probably does not recognize the hostname simply because it is not included in the configuration. Instead of ignoring the warning and use the default certificate, Java seems to throw an exception.
In the other case where you disabled SNI, you do not include the hostname anymore and the request is sent to a server that does not have a default certificate. It will respond with a fatal error because it cannot resolve any certificate for you.

Axis2 client is unable to initiate a second https call on Tomcat 7.0.42

I am trying to migrate an Java Axis2 client from Websphere6/JRE1.5.x to Tomcat 7.0.42/JRE1.6.x on Solaris. In the process, I have come across a issue where the client can communicate with a webservice through https the first time, but would fail from the second attempt onwards due to ssl errors.
Extracted from the log of the failed attempts showed -
%% Client cached [Session-1, SSL_RSA_WITH_RC4_128_MD5]
%% Try resuming [Session-1, SSL_RSA_WITH_RC4_128_MD5] from port 34092
** ClientHello, TLSv1
...
Thread-606, WRITE: TLSv1 Handshake, length = 179
Thread-606, READ: TLSv1 Alert, > length = 2
Thread-606, RECV TLSv1 ALERT: fatal, unexpected_message
and the actual exception was (I suspect it was due to no open socket)-
Caused by: javax.net.ssl.SSLException: Received fatal alert:
unexpected_message at
com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown
Source) at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown
Source) at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown
Source) at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(Unknown Source)
at java.io.BufferedOutputStream.flushBuffer(Unknown Source) at
java.io.BufferedOutputStream.write(Unknown Source) at
java.io.FilterOutputStream.write(Unknown Source) at
org.apache.commons.httpclient.WireLogOutputStream.write(WireLogOutputStream.java:86)
at
org.apache.axis2.transport.http.AxisRequestEntity.writeRequest(AxisRequestEntity.java:89)
Comparing this to the logs on the Websphere environment, I have found a couple of differences and hence my questions -
Is SSL configuration on the Tomcat going to affect the behaviour of a Axis2 client calling a different server? Or is my issue more at the OS level?
on the old environment, I have noticed more than one ssl sessions were cached. When resume failed on one session, it simply tried using a different session and continued with the call. On the new server, however, I have ever only seen one session created and was cached. When resuming, it kept trying to resume the same sessionn a different port but kept failing. As it was the only session, if couldn't try a different session nor creating a new session. My question is why is there only one session created and is it a configuration issue to enable caching of more than one sessions?
Any help/pointers are greatly appreciated.
Finally tracked down the fault. Thought I would share it here for anyone that may come across a similar issue.
As it turned out, it has to do with the Security Provider on the JRE itself. Here is a link on how to configure it -
http://pic.dhe.ibm.com/infocenter/ssp/v3r4/index.jsp?topic=%2Fcom.ibm.help.sspreleasenotes.doc%2FSSP_RN_RemovePKCS11SecurityProvider.html
It seemed the default security provider on Solaris was causing the weird behaviour I saw. Following the instruction in the link, and by using the Java default provider, resolved the ssl problem I saw.

Categories

Resources