I have an application embedding Jetty. I would like to use client cert authentication in SSL and when I enable that; I am getting the following exception at start of request. But the request is getting served properly after that. This exception comes only when accessed from IE or Chrome. It does not come when accessed from Firefox. We have our custom SSLConnector extending SslSocketConnector. I am trying to debug it; but wanted to know if there is any specific place/code where I can start checking.
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:808)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1112)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1139)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1123)
at org.mortbay.jetty.security.SslSocketConnector$SslConnection.run(SslSocketConnector.java:631)
at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:451)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:333)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:789)
Update:
I enabled SSL debug option and was getting this exception on a read immediately after the ServerHelloDone message. This is the message where server sends its cert along with request for client certificate i believe. I am not sure whats happening in first read. Any help is deeply appreciated.
*** ClientHello, TLSv1
****
%% Created: [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]
*** ServerHello, TLSv1
*** Certificate chain
***
*** CertificateRequest
Cert Types: RSA, DSS
Cert Authorities:
*** ServerHelloDone
WRITE: TLSv1 Handshake, length = 703
received EOFException: error
handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Update:
Updated JDK to latest, 23 and tried with the two properties enabled/disabled. Still gettting the same behavior.
More info:
TLSv1 and SSLv3 are enabled in all browsers. The communication is happening properly without client-auth enabled. With client auth, always we get exception on first handshake and the next is getting properly done and proceeding without exceptions. Using jetty version 6.1.14 at server side
I have seen issues like this with TLS/SSLv3 negotiation.
http://www.oracle.com/technetwork/java/javase/documentation/tlsreadme2-176330.html
In SSL/TLS, renegotiations can be initiated by either side. Like the Phase 1 fix, applications communicating with an un-upgraded peer in Interoperable mode and that attempt to initiate renegotiation (via SSLSocket.startHandshake()
or SSLEngine.beginHandshake()
) will receive a SSLHandshakeException
(IOException
) and the connection will be shutdown (handshake_failure
). Applications that receive a renegotiation request from a non-upgraded peer will respond according to the type of connection in place:
- TLSv1: A warning
Alert
message of type "no_renegotiation
(100)" will be sent to the peer and the connection will remain open. Older versions of SunJSSE will shutdown the connection when a "no_renegotiation
" Alert is received.
- SSLv3: The application will receive a
SSLHandshakeException
, and the connection will be closed (handshake_failure
). ("no_renegotiation
" is not defined in the SSLv3 spec.)
To set these modes, two system properties are used:
sun.security.ssl.allowUnsafeRenegotiation
- Introduced in Phase 1, this controls whether legacy (unsafe) renegotiations are permitted.
sun.security.ssl.allowLegacyHelloMessages
- Introduced in Phase 2, this allows the peer to handshake without requiring the proper RFC 5746 messages.
If that still doesn't help, you can try turning on SSL dedug, and taking a look at the handshaking.
-Djavax.net.debug=all
I got this when I accidentally put the non-ssl port in the URL but started the URL with https. Doh.
Sometimes the simplest solutions are the ones that we forget!
Try the newest jdk. They fixed an ssl handshake bug. http://www.java.net/blogs/kumarjayanti/
I still think this is a TLS/SSL negotiation issue.
After you posed the debug info, it shows you are doing a TLSv1 Handshake.
Are you sure you have TLSv1 enabled in your browsers?
Chrome:
In order to enable TLS 1.0 in chrome do the following:
- Click the wrench icon:
- Choose Options
- Select "Under the Hood" Tab
- Click Change proxy settings
- Select "Advanced" Tab
- Scoll down and check TLS 1.0
- Close and restart all open browsers.
IE:
- Click the Tools menu
- Click Internet Options
- Advanced tab
- Scroll to the Security section
- Enable TLS 1.0
Firefox:
- Click Tools
- Click Options
- Advanced tab
- Encryption tab
- Enable TLS 1.0
You then also mention that:
This is the message where server
sends its cert along with request for
client certificate i believe.
Have you installed the client certificate into each of the web browsers you are testing from?
Make sure you can get everything working without mutual/client authentication first, and then once its working, add it back in.