Well, JDK 7 and 8 are opensource, so in principle you could backport the necessary new code and build your own version (call it 7.5?) -- at least if your requirement is only to stay on the java7 API not the/an official java7 JRE. But if you are talking about any substantial number of runtime systems or apps, especially business-critical ones, this could be a hassle to support.
As a workaround I think -- but haven't worked out all the details -- you can sneak the equivalent of SSLSocketFactory.createSocket(Socket,InputStream,boolean), also new in java8 and for the same reason according to the doc, 'underneath'. Specifically if you are using the 'simple' SSLServerSocket
or SSLSocket(client=false)
interface:
accept the TCP connection yourself (either explicitly or in a replacement for SSLServerSocket)
read the ClientHello and parse the piece(s) you want i.e the SNI extension
create a wrapper for Socket
that remembers this data, and also has something like a byte[]
containing the ClientHello and when read
is called it first returns the already-read ClientHello and thereafter reads from the actual socket, while write
and other operations work as usual
create a server-side SSLSocket
'above' this wrapper-Socket and use it as usual
when you want to get SNI, for example in an X509KeyManager
callback, instead of looking at the ExtendedSSLSession
from the [SSL]Socket
, downcast the Socket
to your wrapper-Socket and look there. (You could make this conditional on socket instanceof MyWrapper
so it shuts itself off when you do get onto java8.)
If you are using the SSLEngine
interface, you're already managing the connections and I/O, so you only need to do 2, 3A, and 5: before feeding the first input (ClientHello) to the SSLEngine
parse it and remember it in a wrapper, and when you want to look at it use the wrapper.