Closed Bug 696531 Opened 13 years ago Closed 13 years ago

SPDY - Disable IP Pooling with Client Certificate

Categories

(Core :: Networking: HTTP, defect)

10 Branch
defect
Not set
normal

Tracking

()

RESOLVED DUPLICATE of bug 528288

People

(Reporter: mcmanus, Assigned: mcmanus)

Details

(Whiteboard: [http-conn])

Attachments

(1 file)

in comment 63 of bug 528288 honza says:

 think we should not coalesce ssl sessions that clients have previously authenticated with client certificates on ; regardless this is not mentioned in the SPDY spec.  It might lead to privacy leaks/login attacks.

To explain: when the connection (conn) has sent a client certificate, don't allow use of this connection by other requests to the same IP even there would be a match by the cert name, rather use a new one and let client reauth again.

We currently don't track client certificate authentication status in ssl status object.  So it is hard to say if we have sent a client cert or not.  Needs a new API for that.

This probably can be done in a separate patch/bug.  Also we might want to communicate this to google people.
Depends on: SPDY
Attached patch patch 1Splinter Review
I'm just kind of exploring how this should be done - but this seems to work (I have a test that shows that the client cert is recorded by the time we need it, even though that test isn't spdy). Does it make sense to you?
Assignee: nobody → mcmanus
Attachment #568961 - Flags: review?(honzab.moz)
Comment on attachment 568961 [details] [diff] [review]
patch 1

Review of attachment 568961 [details] [diff] [review]:
-----------------------------------------------------------------

::: security/manager/ssl/public/nsISSLStatus.idl
@@ +66,5 @@
>       implement NPN.
>    */
>    readonly attribute ACString negotiatedNPN;
> +
> +  readonly attribute nsIX509Cert clientCert;

Add this to nsITransportSecurityInfo instead. Adding this to nsISSLStatus will change the serialization of nsNSSStatus objects, which changes the format of the cache. We should avoid doing that if we can.

::: security/manager/ssl/src/nsNSSIOLayer.cpp
@@ +3219,5 @@
> +      status = new nsSSLStatus();
> +     info->SetSSLStatus(status);
> +    }
> +    status->mClientCert = nsNSSCertificate::Create(cert);
> +  }

Just assert that info is not null and then stuff the client certificate in the nsNSSSocketInfo structure. Client cert stuff happens after server cert authentication, so AuthCertificateCallback and/or BadCertHandler will have already set the SSL status.

::: security/manager/ssl/src/nsSSLStatus.cpp
@@ +147,1 @@
>  nsSSLStatus::Read(nsIObjectInputStream* stream)

Do not change the serialization of nsSSLStatus or nsNSSSocketInfo objects. Otherwise, we need to bump the version number in nsNSSSocketInfo::Write() and nsNSSSocketInfo::Read() and we won't be able to share a profile (cache) with older versions of Firefox.
Attachment #568961 - Flags: review-
Blocks: SPDY
No longer depends on: SPDY
OS: Linux → All
Hardware: x86_64 → All
Because of a TLS feature called renegotiation, whether a client cert is in effect and which client cert is being used can change over the lifetime of the connection. In theory, renegotiation can happen even within the processing of a single HTTP request; in practice, renegotiation usually (but not always) happens immediately after the first handshake on a connection, and/or between the server receiving a particular HTTP request and it sending the response. For example, in order to encrypt the client certificate itself, Microsoft products (IIS) will first negotiate a no-client-cert connection, and then re-negotiate requesting the client certificate.

I suggest that, at least for now, we consider SPDY to be mutually-exclusive with client certificates and (in HandshakeCallback) cancel the connection if we've negotiated SPDY (via NPN) and send a client certificate.
s/and send a client certificate/and SENT a client certificate/
I don't think a single SPDY connection can be shared between host names (even if the TLS certificate would match) because SPDY has a bunch of interesting state (e.g., in the compression dictionary).  That means you need to establish a separate TLS connection for each host name anyway, so you might as well allow client certs (since there isn't a privacy problem sharing a cert within a single host name).
(In reply to Adam Barth from comment #5)
> I don't think a single SPDY connection can be shared between host names
> (even if the TLS certificate would match) because SPDY has a bunch of
> interesting state (e.g., in the compression dictionary).  That means you
> need to establish a separate TLS connection for each host name anyway, so
> you might as well allow client certs (since there isn't a privacy problem
> sharing a cert within a single host name).

Adam, have you talked to the Chromium people about how they are doing this [1]? It would be great to get your feedback on it. See also [2] (where you are referenced) and [3].

[1] https://groups.google.com/forum/#!searchin/spdy-dev/pool/spdy-dev/UW0_X2GaMSQ/6sx-_So4aikJ
[2] http://groups.google.com/group/spdy-dev/browse_thread/thread/07fba50a70634ae8/332e0f6b6dec29ac?lnk=raot
[3] http://groups.google.com/group/spdy-dev/browse_thread/thread/7fba50a70634ae8/7daa4d86e1ed4070?lnk=gst&q=compression+contexts+and+privacy+considerations#7daa4d86e1ed4070
This issue came up in one of the security reviews of the protocol.  From that thread, it looks like folks decided I was being overly paranoid (which might well be true).
(In reply to Adam Barth from comment #7)
> This issue came up in one of the security reviews of the protocol.  From
> that thread, it looks like folks decided I was being overly paranoid (which
> might well be true).

That thread is (besides?) about an issue with sharing a compression dynamic dictionary for different host in the same session (connection) and I have seen some suggestion how to solve that.


To go back to our issue, imagine an SSL server on IP 1.2.3.4 configured for client cert authentication.  There are DN records foo.com and bar.com pointing to 1.2.3.4.  User connects to foo.com, does a client authentication.  Is it OK to, when the client goes to bar.com, use the same existing authenticated ssl session so that bar.com sees the user's credentials previously negotiated with foo.com?

Other question is, whether the server would ask for a different client cert when connecting a different host.  Based on the fact that client cert selection is actually influenced only by what a server sends in the list of CAs a client cert must be signed by, then the only way to distinguish for the server what to send is SNI, that is IMO nonsensical (and not used?) while going SPDY regarding the original request of coalescing.

So, only one that can select a different client cert is the user him/her self.
(In reply to Honza Bambas (:mayhemer) from comment #8)
> Other question is, whether the server would ask for a different client cert
> when connecting a different host. 

I think we have to assume that they will. Some servers may even require different certificates for particular resources on the same host, (e.g. https://example.org/ might not require any client cert, https://example.org/legal/* might require a cert issued by the "Legal Department PKI", and https://example.org/marketing/* might require a cert issued by "Marketing Department PKI"). The same would apply to example.org vs legal.example.org vs. marketing.example.org.

> Based on the fact that client cert
> selection is actually influenced only by what a server sends in the list of
> CAs a client cert must be signed by, then the only way to distinguish for
> the server what to send is SNI, that is IMO nonsensical (and not used?)
> while going SPDY regarding the original request of coalescing.
>
> So, only one that can select a different client cert is the user him/her
> self.

Right. In the example above, it is likely that the server TLS terminator would include both "Legal Department PKI" and "Marketing Department PKI" in the list of valid CAs, and then the user would have to choose whether to use the Legal or Marketing certificate based on which part of the website he/she is trying to access.
(In reply to Brian Smith (:bsmith) from comment #3)
> I suggest that, at least for now, we consider SPDY to be mutually-exclusive
> with client certificates and (in HandshakeCallback) cancel the connection if
> we've negotiated SPDY (via NPN) and SENT a client certificate.

The Patrick's patch doesn't allow to send a client cert to a host that shares an IP with a host we have already an establish ssl session with and haven't sent a client cert (it was only requested by the server).  That is safe, but breaks user experience, however in very rare case.

Your suggestion doesn't fix that issue either.  It actually breaks more, but is 100% safe.

Maybe just disable coalescing when we have detected CertificateRequest from a server on an IP/port regardless we have sent a cert back?
Attachment #568961 - Flags: review?(honzab.moz)
(In reply to Honza Bambas (:mayhemer) from comment #10)
> Patrick's patch doesn't allow to send a client cert to a host that
> shares an IP with a host we have already an establish ssl session with and
> haven't sent a client cert (it was only requested by the server).  That is
> safe, but breaks user experience, however in very rare case.

I am not yet convinced that there aren't races between the connection coalescing logic and renegotiations. Regarding this specific issue, the case I worry about is renegotiations where in the original handshake a client cert wasn't used but in the subsequent handshake one is used, and we are trying to make a decision in between those handshakes or during the second one.

> Your suggestion doesn't fix that issue either.  It actually breaks more, but
> is 100% safe.

In both cases, it only breaks when SPDY is turned on. I would much rather go with the approach I suggested as it is more clearly safe. The fact is that there isn't a good story for SPDY+coalescing+client certs right now. Google is also aware of the issue as it is being discussed on spdy-dev. AFAICT, there are not yet any SPDY-enabled servers in the world that use SPDY and client certificates except maybe Google's, which may be using client certificates for the Origin-Bound Certificates extension. That usage of client certs doesn't apply to us because we don't support Origin-Bound Certificates. "Firefox does not support the use of client certificates with SPDY" in the relnotes and dev-docs is sufficient for the first pre-release (especially considering our backlog of client certificate bugs even for non-SPDY uses). 

> Maybe just disable coalescing when we have detected CertificateRequest from
> a server on an IP/port regardless we have sent a cert back?

I think this would still be subject to the kind of races I mention above--we might have done handshake without client certificates so that the connection looks OK for coalescing, but already we might be doing a new handshake with a client certificate, unbeknownst to the SPDY connection coalescing code.
(In reply to Brian Smith (:bsmith) from comment #11)

I agree it is better to be safe here with a simple solution also regarding it is not clear right bow what the consensus is going to be.  It also won't have much affect to testing SPDY (Patrick, please confirm).  We only drop the connection for the rare combination of NPN+sent client cert.
just do this as part of the pre-landing 528288 series
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → DUPLICATE
No longer blocks: SPDY
Whiteboard: [http-conn]
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: