Reputation: 1260
I'm working on a SSL web server using NIO and the SSLEngine. I am able to successfully process handshakes and send/receive application data. However, I'm having difficulty understanding how to maintain SSL Session state.
I am using Firefox 10 to test my web server. On the initial page load, everything works great. Handshaking is completed successfully. The server processes the client request and sends back a response. The response comes across cleanly and the browser loads the application data (html, images, etc). Here's a snapshot of the messages sent from the client to the server.
Page Request #1
===============================================
== Message 1
===============================================
Client Request:
handshake (22)
- client_hello (1)
Server Response:
handshake (22)
- server_hello (2)
- certificate (11)
- server_key_exchange (12)
- certificate_request (13)
- server_hello_done (14)
===============================================
== Message 2
===============================================
Client Request:
handshake (22)
- certificate (11)
- client_key_exchange (16)
change_cipher_spec (20)
- client_hello (1)
handshake (22)
*** Encrypted Message ****
===============================================
== Message 3
===============================================
Client Request:
application_data (23)
*** Encrypted Message ****
application_data (23)
*** Encrypted Message ****
Server Response:
application_data (23)
*** Encrypted Message ****
Again, on the initial page load, everything works great. However, if I refresh the browser or go to another "page", Firefox sends an application record instead of a client hello.
Page Request #2
===============================================
== Application Data
===============================================
Client Request:
application_data (23)
*** Encrypted Message ****
In this case, the SSLEngine throws an exception when it tries to unwrap the application data.
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
I believe this is because I am instantiating a new SSLEngine with each page request. If I instantiate the SSLEngine only one time and make it a global/static variable, it successfully unwraps the application record and I can send a response back to the client. I can refresh the page, visit other pages, etc. without any issues. Page loads are super fast because we are skipping the entire ssl handshaking process.
Unfortunately, if I hit the web server from a different browser while all this is going on (e.g. IE or Safari), the session state inside the SSLEngine gets hosed and my web server can't respond to any new SSL requests. So instantiating the SSLEngine once and making it a globally accessible static variable does not appear to be a viable option. So...
How on earth should I respond to the second page request (Page Request #2)? Is there some way to tie the second page request (Page Request #2) to the initial handshake request (Page Request #1) other than an IP address? Is there an SSL Session ID buried inside the application data in the second page request (Page Request #2)?
Thanks in Advance!
Upvotes: 1
Views: 1458
Reputation: 310909
You must instantiate a new SSLEngine
per SocketChannel
, not per request, or per page, or per application. The SSLEngine
only knows about the state of one SSL connection at a time.
Upvotes: 3