Why does Java's SSLSocket send a version 2 client hello?
Asked Answered
Z

2

23

The SSLSocket.getEnabledProtocols() method returns the following: [SSLv2Hello, SSLv3, TLSv1]. And indeed, when I call connect() and I have SSL debugging turned on, I see that a v2 client hello is used:

main, WRITE: TLSv1 Handshake, length = 81
main, WRITE: SSLv2 client hello message, length = 110

But I have found two (admittedly old) references that say JSSE does not support SSL version 2:

From Fundamental Networking in Java:

'SSLv2Hello' is a pseudo-protocol which allows Java to initiate the handshake with an SSLv2 'hello message'. This does not cause use of the SSLv2 protocol, which is not supported by Java at all.

And from the JSSE Reference Guide:

The JSSE implementation in the J2SDK 1.4 and later implements SSL 3.0 and TLS 1.0. It does not implement SSL 2.0.

Now, my understanding is that version 2.0 client hello should only be sent when the client does support SSL version 2.0. From RFC 2246:

TLS 1.0 clients that support SSL Version 2.0 servers must send SSL Version 2.0 client hello messages [SSL2] ... Warning: The ability to send Version 2.0 client hello messages will be phased out with all due haste.

So why does Java use it?

Zelig answered 13/1, 2011 at 17:11 Comment(1)
The SSLv2Hello is turned on by default on JSSE of Sun/Oracle Java 6, but not Java 7 or later. It breaks for example opening connectins with www.howismyssl.com for Java 6.Imponderable
V
19

Sun's JSSE doesn't support SSLv2 but it supports the SSlv2ClientHello, to support some SSL servers that require it. You can turn it off by removing it from the enabled protocols.

IBM's JSSE does support SSLv2 entirely.

From the JSSE Reference Guide:

For example, some older server implementations speak only SSLv3 and do not understand TLS. Ideally, these implementations should negotiate to SSLv3, but some simply hangup. For backwards compatibility, some server implementations (such as SunJSSE) send SSLv3/TLS ClientHellos encapsulated in a SSLv2 ClientHello packet. Some servers do not accept this format, in these cases use setEnabledProtocols to disable the sending of encapsulated SSLv2 ClientHellos.

I imagine 'server implementations' should read 'SSL implementations' above.

EDIT: thanks for citing my book!

Vasily answered 14/1, 2011 at 0:33 Comment(4)
Thanks for your answer. Are you saying that these servers, given a V2 client hello, will respond by using v3?Zelig
Also, out of curiosity, do you have any idea which servers the guide is referring to? ;-)Zelig
@Matt Solnit: (a) yes (b) no.Vasily
Note that this answer is out of date as of Java 7, but then so is the question. Java ceased doing this at Java 7.Vasily
G
-1

I faced the same issue, we had this error on our RCP application, it was trying to access our nginx which only handle TLS protocols. but openjdk which we use has a bug with TLS which in some case will end in: javax.net.ssl.SSLException: Received fatal alert: bad_record_mac. So i was trying to find a way to use a different protocol to do the handshake like SSLv3. At first I though that SSLv2Hello is the handshake protocols! but it is not!

SSLv2 never implemented in sun jdk or openjdk, this SSLv2Hello is not the actual protocol for the handshake, it is there for backward compatibility(my guess is because of the probability of existence of some servers) and it will be used for negotiation on the available protocols that will be used for the actual handshake!

on this link search for the answer from Stoinov, he wrap the answer very well.

Gandzha answered 9/4, 2021 at 16:25 Comment(1)
You could always have read my answer above. It had been there for 10 years already.Vasily

© 2022 - 2024 — McMap. All rights reserved.