dev@grizzly.java.net

SSL re-negotiation in Grizzly

From: Bruno Harbulot <Bruno.Harbulot_at_manchester.ac.uk>
Date: Sun, 18 Jan 2009 19:58:39 +0000

Hello,

I've been trying a few Servlet containers to check their support for SSL
re-negotiation to request a client-certificate when one hadn't initially
been requested during the first handshake.

First, to give a bit of background, here are a few traces obtained with
Wireshark.

1. When the server requests a client certificate in the initial handshake.
This is the case where the listening connector is configured to want
client authentication. For example, using <Connector clientAuth="want"
.../> in Tomcat, or by setting client-auth-enabled="true" in Glassfish v2.

(The following transmission has been deciphered using the server's
private key. Otherwise, only the first 4 messages are in clear.)

No. Time Source Src port Destination
  Dst port Protocol Info
       5 0.000442 127.0.0.1 50027 127.0.0.1
   8181 SSLv3 Client Hello
       7 4.102430 127.0.0.1 8181 127.0.0.1
   50027 SSLv3 Server Hello, Certificate, Certificate Request,
Server Hello Done
       9 4.136647 127.0.0.1 50027 127.0.0.1
   8181 SSLv3 Certificate, Client Key Exchange, Certificate
Verify, Change Cipher Spec, Finished
      11 4.175050 127.0.0.1 8181 127.0.0.1
   50027 SSLv3 Change Cipher Spec
      13 4.175223 127.0.0.1 8181 127.0.0.1
   50027 SSLv3 Finished
      15 4.176477 127.0.0.1 50027 127.0.0.1
   8181 HTTP GET /test/ HTTP/1.1
      17 4.258078 127.0.0.1 8181 127.0.0.1
   50027 HTTP HTTP/1.1 200 OK (text/html)


Here, the server sends a 'Certificate Request' with the initial 'Server
Hello' and the client responds accordingly with a 'Certificate'.



2. When the server hasn't been configured to request or require a
certificate in the initial handshake (client-auth-enabled="false"), but
access to the resource requires one (using
"<auth-method>CLIENT-CERT</auth-method>" in web.xml).


(The following transmission has been deciphered using the server's
private key. Otherwise, only the first 4 messages are in clear.)

No. Time Source Src port Destination
  Dst port Protocol Info
       5 0.000368 127.0.0.1 49632 127.0.0.1
   8181 SSLv3 Client Hello
       7 0.330026 127.0.0.1 8181 127.0.0.1
   49632 SSLv3 Server Hello, Certificate, Server Hello Done
       9 0.333000 127.0.0.1 49632 127.0.0.1
   8181 SSLv3 Client Key Exchange, Change Cipher Spec, Finished
      11 0.360068 127.0.0.1 8181 127.0.0.1
   49632 SSLv3 Change Cipher Spec
      13 0.360235 127.0.0.1 8181 127.0.0.1
   49632 SSLv3 Finished
      15 0.363124 127.0.0.1 49632 127.0.0.1
   8181 HTTP GET /test/ HTTP/1.1
      17 0.444374 127.0.0.1 8181 127.0.0.1
   49632 SSLv3 Hello Request
      19 0.444638 127.0.0.1 49632 127.0.0.1
   8181 SSLv3 Client Hello
      21 0.446479 127.0.0.1 8181 127.0.0.1
   49632 SSLv3 Server Hello, Certificate, Certificate Request,
Server Hello Done
      23 0.481312 127.0.0.1 49632 127.0.0.1
   8181 SSLv3 Certificate, Client Key Exchange, Certificate
Verify, Change Cipher Spec, Finished
      25 0.508715 127.0.0.1 8181 127.0.0.1
   49632 SSLv3 Change Cipher Spec
      27 0.508783 127.0.0.1 8181 127.0.0.1
   49632 SSLv3 Finished
      29 0.521032 127.0.0.1 8181 127.0.0.1
   49632 HTTP HTTP/1.1 200 OK (text/html)


Here a client certificate isn't initially presented, but just after the
client sends the GET request that targets a protected resource, the
servers triggers a new handshake by sending an 'Hello Request'. In the
second handshake, the server sends a 'Certificate Request' and the
client sends a 'Certificate' in response.

This is what Tomcat and Glassfish v2 UR2 (using the Coyote connector)
do. (This is also the same pattern as what happens when using
SSLVerifyClient at the directory level in Apache Httpd.)


3. Glassfish v2 and Grizzly.
If I use '<property name="cometSupport" value="true"/>' in the SSL
http-listener (still with "client-auth-enabled"=false), here is what
happens:


No. Time Source Src port Destination
  Dst port Protocol Info
       5 0.000403 127.0.0.1 56261 127.0.0.1
   8181 SSLv3 Client Hello
       7 0.401544 127.0.0.1 8181 127.0.0.1
   56261 SSLv3 Server Hello, Certificate, Server Hello Done
       9 0.421862 127.0.0.1 56261 127.0.0.1
   8181 SSLv3 Client Key Exchange, Change Cipher Spec, Finished
      11 0.452881 127.0.0.1 8181 127.0.0.1
   56261 SSLv3 Change Cipher Spec
      13 0.452970 127.0.0.1 8181 127.0.0.1
   56261 SSLv3 Finished
      15 0.456227 127.0.0.1 56261 127.0.0.1
   8181 HTTP GET /test/ HTTP/1.1
      17 0.600029 127.0.0.1 8181 127.0.0.1
   56261 SSLv3 Hello Request
      19 0.600308 127.0.0.1 56261 127.0.0.1
   8181 SSLv3 Client Hello
      21 0.600807 127.0.0.1 8181 127.0.0.1
   56261 HTTP HTTP/1.1 400 Bad Request (text/html)
      23 0.601116 127.0.0.1 56261 127.0.0.1
   8181 SSLv3 Alert (Level: Warning, Description: Close Notify)


In this case, it seems that the server sends the 'Hello Request'
message, as expected. However, it doesn't seem to process the subsequent
'Client Hello'.

I suppose there's a least a minor bug because, even if this feature
isn't supported, it should probably not return a 400 response in this case.

More generally, is SSL re-negotiation supposed to work with Grizzly (any
version, with or without Glassfish)?
I must admit I don't know Grizzly very well. I've mostly used it via
Restlet.


Best wishes,

Bruno.