Skip to content

Instantly share code, notes, and snippets.

@jroper
Created October 17, 2013 05:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jroper/7019715 to your computer and use it in GitHub Desktop.
Save jroper/7019715 to your computer and use it in GitHub Desktop.
Oracle JDK TLS renegotiation bug when want_auth is added and session caching is used

There is a bug in the Oracle JDK TLS implementation.

A server might have an existing SSL session that has no client authentication associated with it. For example, it might be a web server, and a client has accessed the index page. Authentication is not required for the index page, so the server hasn't requested it.

At some point in future, the user might attempt to access a secured area of the site. A typical use case might be that they click an authenticate button. If the server wants to use SSL client certificates to authenticate the user, then at this point the server can send a renegotiation request, asking for a client certificate.

Java SSL negotiation and renogotiation has two modes when it comes to requesting a client certificate, one is "want auth", and the other is "need auth". Want auth means that if the client doesn't provide a certificate, the session will continue, without any client certificates. Need auth means that if the client doesn't provide a certificate, the session will be terminated.

In the case of our web server, when a user doesn't supply a certificate, the most desirable way to respond from a usability perspective (remember that 99% of users in the world have no idea what an SSL certificate is) is to render a web page telling the user that they haven't supplied a certificate, and instructing them on what to do to get a certificate for this site. This means using the want auth mode, as it will allow the server to send an HTTP response with that message. If the server used need auth, then the SSL session would be closed before the server had a chance to render a friendly error message, and instead the browser will display a generic error message saying that the SSL session was closed, leaving the average user with no hint of what they should do to rectify the problem.

Another feature that Java SSL negotiation supports is session caching. If there exists a session in the cache that matches the attributes of the currently negotiatied session, then the client and server can use that, saving negotiation round trips.

The bug in the JDK comes when renegotiating a session in want auth mode, and caching is in use. Session caching caches the certificate that the client provided. It doesn't cache whether the session was negotiated in want or need auth mode. When it sees that the negotiation has requested want auth, and the cached session contains no certificate, it decides that that is an acceptable session to use, and so doesn't trigger the client certificate request.

The result is that, when session caching is used, renegotiating a session that previously had no client certificate, setting the mode to want auth, has no effect. In the use case mentioned earlier, it means that a client certificate is never requested from the user, and from the servers perspective, the user didn't provide one.

There are a number of possible solutions:

  • Always request a certificate if want auth is set for the renegotiation and the cached session doesn't contain one.
  • Store the want auth/need auth status of a session in the cache, and use that to verify whether a cached session matches the current request. This is probably the least desirable option, consider the use case where a user is unable to provide a certificate because they don't have one, but then they get one, and again they click "authenticate". Since the current session doesn't have a certificate and is want auth, they might not get asked for their certificate again.
  • Provide a mechanism to force renegotiation from application code, bypassing all caching mechanisms, eg a setForce method somewhere.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment