I am running embedded Jetty server with https/TLS enabled on it. It works perfectly with all modern browsers (TLSv1.2).
We have a legacy browser (.exe whose code cannot be changed/checked) which we are trying to connect to Jetty server over https, which is failing.
I debugged SSL on jetty side and came to know that this browser is connecting using TLSv1, so I did the following:
sslContextFactory.setIncludeProtocols( "TLSv1");
After this, I started getting error "no cipher suits in common" on server side. To pass this (I know this is dangeropus, but still for now), I did:
sslContextFactory.setExcludeCipherSuites();
After doing this, I don't see any error on server side, but still legacy browser is unable to connect. (It can connect to other https site though as facebook, google).
Server side logs after above change:
WRITE: TLSv1 Handshake, length = 48
called closeOutbound()
closeOutboundInternal()
SEND TLSv1 ALERT:
warning,
close_notify
WRITE: TLSv1 Alert, length = 32
Any idea what can be wrong here? I tried to do a lot of googling on it but cannot work it through. I also tried enabling SNI on server, but with no luck.
Any help would be very appreciated.
Thanks
edit1:
If I compare Jetty SSL logs with working request, I see below difference. Working request is sending application data also as below:
WRITE: TLSv1 Application Data, length = 1285
In non-working request, I see below additional line (TLS_RSA_WITH_AES_128_CBC_SHA is cipher suite name):
Cached server session: [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]
There is an issue with Jetty 9.4.*
https://github.com/eclipse/jetty.project/issues/3773
https://github.com/eclipse/jetty.project/issues/2807
which blindly excludes TLS1.0 and TLS1.1.
The fix
is (a) to call setExcludeCipherSuites() after SslContextFactory is contructed as mentioned above,
or (b) just override SslContextFactory.setExcludeCipherSuites(final String... cipherSuites) to do nothing, as below:
final SslContextFactory sslContextFactory = new SslContextFactory()
{
#Override
public void setExcludeCipherSuites(final String... cipherSuites)
{
// do nothing intentionally.
}
};
Related
There are 2 Websphere servers. First is Client and Second is Server (8.5.5.13).
An End-User makes a SOAP request to Client. Client receives the request, do some processing and then makes a REST request to the Server.
When the Server receives the request from Client it throws the below exception.
ERROR 22304 --- [ebContainer : 2]
c.i.w.s.c.impl.SSLHandshakeErrorTracker : SSLC0008E: Unable to
initialize SSL connection. Unauthorized access was denied or security
settings have expired. Exception is
javax.net.ssl.SSLHandshakeException: Client requested protocol TLSv1
not enabled or not supported
We have tested after enabling TLSv1.2 and then TLSv1 at the our Server level. We have exported the certificate from the Server and added in the Client trust store as well. But still we are not able to resolve the error.
Questions:
1. Do we need to keep the same TLS version at our Server which is present in the Client WebSphere?
2. We have deployed our application is java7. Is it due to Java version we are facing the issue?
3. Is it due to Certificate only, or something else?
When we disable the Global security at our Server then the request is processing correctly.
This error was due to the TLS version incompitability at Server. The client was sending the request using TLSv1 and server has TLSv1.2 enabled in it. For SSL handshake, the first thing is TLS compitability. The client and server should have same TLS versions.
After this if you are using one way SSL handshake, then the certificate from the server machine needs to extract and the same should be installed in the Client machine. This way SSL Handshake will happen.
I have enabled logs in my application using -Djavax.net.debug=all option. Code that have written is supposed to use SSLv3 protocol, but in logs when I am checking it is displaying as ::
*** ClientHello, TLSv1
*** ServerHello, TLSv1
As far as I understand from reading is, Client and Server using TLSv1 for handshake, but as I have used SSLv3 in my code while initiating socket, ideally it should print SSLv3 instead TLSv1.
Below is the code snippet I have used :
SSLContextBuilder builder = new SSLContextBuilder();
builder.useProtocol("SSLv3");
SSLContext sslContext = builder.build();
Can someone please clarify the reason for the same, or is there something else I have missed out. Just to add on I am on Java 7.
Most probably SSLv3 is just not supported by server (which is recommended configuration nowadays because of security), so the lib uses least supported TLS version.
UPD: seems that hello format says nothing about what protocol will be used in fact. There's something from Java docs:
Currently, the SSLv3, TLSv1, and TLSv1.1 protocols allow you to send SSLv3, TLSv1, and TLSv1.1 hellos encapsulated in an SSLv2 format hello. For more details on the reasons for allowing this compatibility in these protocols, see Appendix E in the appropriate RFCs (previously listed).
Note that some SSL/TLS servers do not support the v2 hello format and require that client hellos conform to the SSLv3 or TLSv1 client hello formats.
The SSLv2Hello option controls the SSLv2 encapsulation. If SSLv2Hello is disabled on the client, then all outgoing messages will conform to the SSLv3/TLSv1 client hello format. If SSLv2Hello is disabled on the server, then all incoming messages must conform to the SSLv3/TLSv1 client hello format.
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.
I have TLS client writen in JAVA. When i set
sslContext = TLS1.2
and enabled protocols to SSLv3 TLSv1 TLSv1.1 TLS1.2
it works fine with almost all servers. Client start handshake with TLSv1.2. If server can only TLSv1, connection downgrades to TLSv1 during handshake.
But! We use about 15 such TLSv1 services and 4 of them fails to downgrade. Servers are all different:
Microsoft-IIS/7.5, nginx, IBM_HTTP_SERVER, SQLAnywhere.
Errors like this:
SEND TLSv1 ALERT: fatal, description = unexpected_message X2
handling exception: javax.net.ssl.SSLException: Invalid Padding length: 139
javaException : Received fatal alert: unexpected_message
If i set enabled protocols to TLSv1, that servers works fine. But i want set sslContext and enabled protocols to be compatible with all services and preferably work with TLSv1.2
Any suggestions will be appreciated!
But i want set sslContext and enabled protocols to be compatible with all services and preferably work with TLSv1.2
First, there are enough servers out there which don't do TLS 1.2 but the best they can do is TLS 1.0 (and some even only SSL 3.0). A proper implementation of the TLS stack would in this case simply send a TLS 1.0 reply and thus enforcing the connection to be TLS 1.0 which is supported in your client. Forcing these servers to TLS 1.2 will not work because they don't implement it. All you could do is replace the servers with newer implementations.
And then there are several implementations out there which incorrectly implement the protocol. Some of these simply close the connection if you send a TLS 1.2 ClientHello or use some TLS extensions they never heard of. If you can not replace these servers you have to communicate with them in a way they will understand, like speaking only TLS 1.0 etc. Browsers already deal with this rotten servers by slowly downgrading the connection, i.e. if TLS 1.2 causes a handshake failure they will try again with TLS 1.0 etc. Often browsers even have hard coded a list of servers which are too rotten to even play nice after trying simple downgrads and which need to have special ciphers or something like this.
I have a CXF web services server running with embedded jetty.
A client connects and send several successful requests to the server.
After 5-10 seconds suddenly the client hangs.
The client / server reuse the same connection for all requests.
After running the server with -Djavax.net.debug=all I've noticed the following message before the connection hangs.
Keep-Alive-Timer, called close()
Keep-Alive-Timer, called closeInternal(true)
Keep-Alive-Timer, SEND TLSv1 ALERT: warning, description = close_notify
Keep-Alive-Timer, WRITE: TLSv1 Alert, length = 22
Any idea what should be fixed to disable this Keep-Alive-Timer to close the connection?
After upgrading to cxf 3.1.0 the problem disappeared.