2

I'm trying to use the SNI pattern in my current project where a client initiates an SSL connection to a server. I would like my server to know what host/server name the client is intending to connect to. This server name is supplied by the client. I have an ExtendedSSLSession object but since I'm using Java 7, I cannot use the getRequestedServerNames() method (which was introduced in Java 8) which achieves the exact functionality I'm looking for. My current situation does not allow me to upgrade my java version unfortunately.

I wanted to ask the community if there is a workaround to get the server names when using Java 7?

I would appreciate any guidance.

Thank you!

  • Also see [How to implement Server Name Indication (SNI)](http://stackoverflow.com/q/5113333), [Serving multiple domains in one box with SNI](http://stackoverflow.com/q/22373332) and [SSL_CTX_set_tlsext_servername_callback callback function not being called](http://stackoverflow.com/q/22607121). – jww Nov 23 '16 at 23:08
  • Sorry, could you please let me know how I can use this information? They seem to use SSL_get_servername which I think is what I'm hoping to find an implementation of in Java 7? Thanks! – Marko Yuvanska Nov 24 '16 at 23:34
  • They are OpenSSL calls. Why does the question have the OpenSSL tag? – jww Nov 25 '16 at 00:36

1 Answers1

0

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:

  1. accept the TCP connection yourself (either explicitly or in a replacement for SSLServerSocket)

  2. read the ClientHello and parse the piece(s) you want i.e the SNI extension

  3. 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

  4. create a server-side SSLSocket 'above' this wrapper-Socket and use it as usual

  5. 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.

dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70