W3C home > Mailing lists > Public > public-xg-webid@w3.org > October 2011

Re: TLS session renegotiation in java

From: Henry Story <henry.story@bblfish.net>
Date: Tue, 11 Oct 2011 11:47:02 +0200
Cc: "WebID XG" <public-xg-webid@w3.org>, "Jérôme Louvel" <jerome.louvel@noelios.com>
Message-Id: <741C1D1D-7FFF-47EC-9458-D1F6D0C93066@bblfish.net>
To: ryan-webid@sleevi.com
Thanks Ryan for the detailed response, which is a good contribution to ISSUE-58: Login/Logout behavior

More below .

On 11 Oct 2011, at 01:40, Ryan Sleevi wrote:

>> just a note that I put together a mini server in the git repository 
>> 
>>   https://github.com/bblfish/TLS_test
>> 
>> that tests TLS session renegotiation, to see how browsers react to that.
>> I wanted to see:
>>  - if when renegotiating browsers ask their users for a new certificate
>> (they don't seem to - so this may be a bug in my code , the server, or a
>> bug in the browsers)
> 
> None of the above - it's a bug in your expectations.
> 
> TLS renegotiation is not strictly tied to renegotiating identity
> (certificates), it's tied to the overall process of renegotiating security
> parameters. Though this may include identity - and indeed, commonly does
> when using something like mod_ssl + vhosts + directory-specific
> certificate requests - that is not all that is renegotiated. Further,
> there is no requirement for the browser (or any other TLS implementation)
> to invalidate the previous identity selection - it's up to the server to
> reject it.
> 
> Speaking from first-hand experience with Chromium and second-hand with
> Firefox, both browsers cache identity selections to minimize the number of
> times the user is prompted. From the browser perspective, this is a "good"
> and "correct" thing, for a few reasons:
> 
> 1) There may be multiple TLS handshakes in-flight with the same endpoint.
> Prompting the user each time the endpoint sends a CertificateRequest
> message may result in many spurious prompts to the user (from 6 to upwards
> of 100).
> 2) As previously mentioned, frequently server implementations may request
> "spurious" renegotiations. Spurious in this sense because the list of
> acceptable parameters on the server end hasn't changed, but it performs
> renegotiation as a way to pass parameters between its internal
> implementation (again, mod_ssl comes to mind)

yes, makes sense.

> 
> Typically, these caches are not invalidated until a response is received
> from the server that is interpreted as if the identity was unacceptable. A
> renegotiation message is NOT such a response. Rather, they look for
> appropriate handshake errors. In addition to explicit errors, and again
> due to various legacy server implementations, the spontaneous disconnect
> of the channel is also interpreted as a "certificate unacceptable"
> response.
> 
> These responses will typically flush the browser-side cache and thus allow
> re-selection to happen. Of course, "re-selection" doesn't necessarily mean
> "re-prompting", since there may be other sources of certificate selection
> beyond direct user interaction (extensions, cached preferences,
> administrative policies).
> 
> As I've mentioned previously on this list, if you want to implement "Log
> Out" functionality, you need to both reject the TLS session cache (as
> browsers will attempt TLS session resumption, which implicitly includes
> client identity) and reject TLS connections that attempt to use the
> "existing" certificate.

This is what I do for 

   https://foafssl.org/srv/idp?rs=http%3A%2F%2Fbblfish.net%2F

The "change identity" button on that page there works in Firefox (and should work on Internet Explorer - nobody has yet confirmed this for me) by  using the javascript logout functionality found at https://foafssl.org/scripts/logout.js

For other browsers the link ends up being clicked, which calls the IdentityProvider.scala [1]
def logout(...) method (line 172) . This gets hold of the current session and calls the TrustManager (line 194)

   tlsTM.breakConnectionFor(s,subj)

tlsTM is an instance of our tweaked TrustManager - X509TrustManagerWrapperService.scala [2]. As opposed to the default TrustManager that comes with the JVM and that verifies that the certificate sent was signed by some known CA, this TrustManager does nothing. Well not quite: as you suggested previously on this list it refuses connections by throwing a TLS Exception for certificates on a timed list (line 100). The 

    def breakConnectionFor(session: SSLSession, subject: Subject) { ... }

on line 188 adds certificates to that list. 

So the IdentityProvider Servlet then closes the TCP connection. (line 215)

Anyway - it does not seem to work reliably for either Safari, Opera or Chrome. Or rather, those browsers just seem to send the same certificate again, without prompting the user.

> Because TLS is a transport protocol, and not really at the application
> layer, such "Log Out" is hardly reliable, and as I've mentioned before,
> prone to breakage for any number of reasons.

yes. that is my experience, though it could be that it is also due to bugs in my code.

LogOut with the JavaScript in Firefox is completely reliable though.

I suggested that this JavaScript functionality be added to Chrome in bug report 90676

   http://code.google.com/p/chromium/issues/detail?id=90676

but the bug report was closed because that functionality was not standard. I am not sure where
we should go to standardise it. The HTML5 Working Group?

> 
> That's why mechanisms such as TLS Origin Bound Certificates (
> http://tools.ietf.org/html/draft-balfanz-tls-obc-00 ) instead work to bind
> the certificate to the cookie (an application-layer construct), and let
> the cookie handle "Log Out".

Ok, that sounds interesting. Two remarks (one positive, one negive) 

 - As it is written now it would not be useful for what we need, as it is tied too closely to a specific type of certificate. In order to create a Social Web, we do want identifying information in the certificate - in the form of a WebID (see the second video on http://bblfish.net/ for such a use case), and we don't just want to use self signed certificates.
 + I like the idea of having a mechanism of tying a certificate to a cookie, and using the cookie mechanism to close a session

So perhaps they could reduce the scope of their RFC and deal just with the X509 session -> Cookie layer? 
This would then tie in with Bruno Harbulot's suggestion a few years ago 
   http://www6.ietf.org/mail-archive/web/tls/current/msg05589.html


> 
> I should further add that "spontaneous disconnect" only works before the
> handshake is completed. If you accept the handshake with the ("old")
> identity, but then display an error page and spontaneously disconnect at
> the end, that's certainly not going to flush any identity cache.

If you disconnect the http session, after breaking the session on your side,
and then refuse the first certificate sent if it is the same, should that give the
correct behaviour? We are not looking for perfection, just something that can get us
99% of the way there, so that we can then put together more proofs of concepts.

> 
>>   - to see how this can be done in java
>>   - to improve html users login experience, so that when they reach a site
>> they don't get asked immediately for a certificate but only once they
>> have been able to look around a bit
> 
> If you want this to even remotely work in browsers, you'll want to look at
> binding different host names between anonymous and secured access. If a
> CertificateRequest message comes in (whether or not the server "requires"
> a cert), the browser will prompt. Further, if the user declines to provide
> such a cert (thus causing an empty Certificate message to be sent back),
> and the server accepts it, the "null" or anonymous identity will be cached
> for that server. Meaning future requests will not prompt - it'll
> automatically send no certificate.
> 
> If you wish to flush that caching, see above, you'll need to flush it as
> if the user actually selected an identity.
> 
> The use of separate domains is recommended so that you can have one domain
> never request for the certificate (the "browse" site), and the other
> domain always request & require a certificate (the "login" site).

The problem is the "Require" part. If requiring a certificate means that not sending one leads to a broken connection, if one is not sent - and so to an ugly error message - then this is unacceptable from the users perspective.  One cannot have a site that asks the user for something and the fails horribly without explanation on error.


Having two sites  on the other hand is a well established  workaround, and is even mention in such a section of the the Java™ Secure Socket Extension (JSSE) Reference Guide [3]. But from what I read there, TLS renegotiation should have the same effect, and at least remove the need for another domain name, thereby reducing setup costs. 

But from all this it does seem to me that the only correct fix is for the end user to be in charge of when to send his identity, as we argued in "The WebID Protocol and Browsers" 

   http://www.w3.org/2011/identity-ws/papers/idbrowser2011_submission_22/webid.html

Is this something you agree with?


> 
>>   - which browsers support the TLS rengotiation fix
> 
> You may be interested in
> http://blog.ivanristic.com/Qualys_SSL_Labs-A_Study_of_Really_Breaks_SSL-HITB_Amsterdam_2011.pdf
> (particularly, Slide 24). As far as browser support goes, all of your
> "major" browser support it. IE just requires the proper security patch to
> Windows ( http://support.microsoft.com/kb/977377 )

Ok that mentions which servers support the secure renegotiation patch correctly - which is more a question of how many people have updated their servers.  But what is more important for us now - given that we want to do the right thing with the servers - is which browsers support it.

The absolute latest Safari - Version 5.1 (7534.48.3)  - does not. Or at least that is what running 
https://github.com/bblfish/TLS_test seems to indicate:

-----------------------8<------------------------------------------
11:18:28 - ~/Programming/FoafSSL/TLS_test/session_renegotiation
$ mvn -e clean compile exec:java
[INFO] Error stacktraces are turned on.
[INFO] Scanning for projects...
[INFO]                                                                         

         [snip]

Oct 11, 2011 11:19:08 AM org.restlet.engine.connector.ServerConnectionHelper start
INFO: Starting the internal [HTTPS/1.1] server on port 8443
javax.net.ssl.SSLHandshakeException: Insecure renegotiation is not allowed
	at sun.security.ssl.SSLEngineImpl.kickstartHandshake(SSLEngineImpl.java:663)
	at sun.security.ssl.SSLEngineImpl.beginHandshake(SSLEngineImpl.java:726)
	at net.bblfish.zz.test.HttpsRenegServerInboundWay.onReceived(HttpsRenegServerInboundWay.java:56)
	at org.restlet.engine.connector.ServerInboundWay.onReceived(ServerInboundWay.java:112)
	at org.restlet.engine.connector.InboundWay.onDrain(InboundWay.java:253)
-----------------------8<------------------------------------------

If I then run the same with legacy enabled I don't have that problem

$ export MAVEN_OPTS="$MAVEN_OPTS -Dsun.security.ssl.allowUnsafeRenegotiation=true"
$ mvn -e clean compile exec:java

But then again I am not sure about my code yet. The results vary a lot on different browsers.
Chrome and Chromium seem to block on either server setup, and  Opera never requests the client certificate.

It works with Firefox, but it seems to take one more connection before it show me my certificate.

So there is perhaps some little problem in my code still. It would be useful to be able to compare this with other servers.

I am using RESTlets there because it was the easiest to work out how one may go about getting renegotiation to work - but then I that may just have been an illusion. We need some team work here to help work out what the correct behaviour should be.

Henry


[1] version of IdentityProvider.scala on github that I am referring to  
https://github.com/bblfish/clerezza/blob/b9da0482b4526bdf317369bc0dd6ca4c64eebb51/parent/platform.security.foafssl/identity-provider/src/main/scala/org/apache/clerezza/foafssl/idp/IdentityProvider.scala

[2] version of X509TrustManagerWrapperService github  that I am referring to	
https://github.com/bblfish/clerezza/blob/db5836df79d37b93c35ed259413f19aca5d8f562/parent/platform.security.foafssl/core/src/main/scala/org/apache/clerezza/foafssl/ssl/X509TrustManagerWrapperService.scala

[3] "Java™ Secure Socket Extension (JSSE) Reference Guide" for java 7, workarounds section
http://download.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#workarounds

Social Web Architect
http://bblfish.net/
Received on Tuesday, 11 October 2011 09:47:43 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 19:39:47 UTC