Subject: [xmpp] mutual auth for s2s

From: Peter Saint-Andre <[email-masked]>
Date: Wed, 17 Mar 2010 12:31:36 -0600

I plan to have a slide about this in Anaheim but I figured I'd raise the
issue on the list so that we can discuss it a bit...

RFC 3920 says that you MUST have one TCP connection in each direction
for s2s communication (thus 2 connections in total). This is a legacy of
server dialback because dialback "authenticates" a connection in only
one direction. However, TLS should enable us to perform mutual auth (if
both servers have acceptable certificates) and therefore use one TCP
connection instead of two. Mutual auth is not specified in rfc3920bis
but I think it would be valuable to add it. This seems fairly
straightforward (e.g., specify that the receiving entity shall include a
CertificateRequest message during TLS negotiation) but I admit that I
might be missing something...

Peter

-- 
Peter Saint-Andre
https://stpeter.im/

---

From: Peter Saint-Andre <[email-masked]>
Date: Wed, 17 Mar 2010 12:37:53 -0600

> might be missing something...

In fact we have minimal text about this under section 6.3.3.1 of rfc3920bis:

   3.  The receiving entity SHOULD send a certificate request to the
       initiating entity so that mutual authentication will be possible.

But that's all we say. Ideally we'd have some text about what to do if
mutual authentication fails (e.g., fall back to a unidirectional
connection) and perhaps some additional checking rules that I haven't
thought of yet.

Peter

-- 
Peter Saint-Andre
https://stpeter.im/

---

From: Dave Cridland <[email-masked]>
Date: Wed, 17 Mar 2010 18:50:41 +0000

> might be missing something...

Yup. :-)

The sending entity already includes a certificate anyway, since  
that's the only way it can authenticate.

The receiver includes a certificate, because, well, it has to.

So in fact, both ends are (or should be) authenticating the other  
already... The only thing we need to do is include some protocol to  
allow both ends to take advantage of this fact.

Dave.
-- 
Dave Cridland - mailto:[email-masked] - xmpp:[email-masked]
  - acap://acap.dave.cridland.net/byowner/user/dwd/bookmarks/
  - http://dave.cridland.net/
Infotrope Polymer - ACAP, IMAP, ESMTP, and Lemonade

---

From: Philipp Hancke <[email-masked]>
Date: Wed, 17 Mar 2010 22:36:32 +0100

> issue on the list so that we can discuss it a bit...

after some off-list discussion:

XEP 0178 almost solves this issue. However, there is no way for the 
receiving server to determine if the auth is mutual. This might be 
accomplished by the following change:

The receiving server (server2) will only offer EXTERNAL if it has been 
able to verify the identity of the originating server (server1) - S2S 
step 9 in XEP 0178.

The originating server (server1) might include a hint that it has been 
able to verify the identity of the receiving server(server2) in step 10:
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
mechanism='EXTERNAL' mutual='true'>
Y29uZmVyZW5jZS5leGFtcGxlLm9yZwo=</auth>
where mutual defaults to false.

By doing this, the originating server signals that it is ready to accept 
stanzas with a from/to as specified in stream headers.

Unfortunately, that only works for one domain pair per tcp connection...

---

From: Peter Saint-Andre <[email-masked]>
Date: Wed, 17 Mar 2010 15:40:09 -0600

> stanzas with a from/to as specified in stream headers.

Yes, I think that works.

> Unfortunately, that only works for one domain pair per tcp connection...

Let's solve one problem at a time...

Peter

-- 
Peter Saint-Andre
https://stpeter.im/

---

From: Justin Karneges <[email-masked]>
Date: Wed, 17 Mar 2010 19:12:26 -0700

> allow both ends to take advantage of this fact.

Indeed.  Mutual auth is necessary even for one-way stanza streams.  This was 
something I recall clarifying back when RFC 3920 was being written.  Using 
one TCP connection for both directions of the stream is not really a mutual 
auth issue so much as smart optimization.

-Justin

---

From: Dave Cridland <[email-masked]>
Date: Fri, 26 Mar 2010 11:32:27 +0000

On Wed Mar 17 21:36:32 2010, Philipp Hancke wrote:
> The originating server (server1) might include a hint that it has  
> been able to verify the identity of the receiving server(server2)  
> in step 10:

Does mutual being false actually indicate the following statement:

"I am willing to continue to initiate a stream even though I cannot  
authenticate you to my satisfaction."

Dave.

---

From: Philipp Hancke <[email-masked]>
Date: Fri, 26 Mar 2010 13:29:34 +0100

> authenticate you to my satisfaction."

Yes. If a server sends false it is ignoring the rules regarding 
certificate validation and expected identity.

---

From: Kurt Zeilenga <[email-masked]>
Date: Fri, 26 Mar 2010 06:46:50 -0700

It seems to me that we're missing something here.

In the mutual authentication, the TLS server should be performing the same checks it would as a TLS client in absence of mutual authentication.   That is, the TLS server should verify that the TLS client is the entity that it would have connected to if it was initiating the connection and verify that the subject of TLS client's certificate is that entity.  The former could be done by performing a DNS lookup (SRV and subsequent A/AAAA lookups) to determine if the connection came from one of IP addresses DNS offers for the entity.   And then the TLS server can perform server identity checks as if it were the TLS client initiating the connection.

-- Kurt

---

From: Peter Saint-Andre <[email-masked]>
Date: Fri, 26 Mar 2010 08:42:56 -0700

On 3/26/10 5:29 AM, Philipp Hancke wrote:
>>> been able to verify the identity of the receiving server(server2) in
>>> step 10:

What do you mean by "server" here? The initiating entity is the one that
sends <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
mechanism='EXTERNAL' mutual='true'> during SASL negotiation. I prefer to
differentiate between the TLS server (receiving entity) and TLS client
(initiating entity -- here we could call it a "peer").

Perhaps 'mutual' is a confusing name. I think the peer is communicating
that it is willing to allow the stream to be bidirectional. Its exact
reason for doing so is left up to interpretation. IMHO the text needs to
say that the peer should allow the s2s stream to be bidirectional only
if the initiating entity has authenticated the receiving entity, but I
suppose it might have other reasons (business level agreement to pursue
DNA-like piggybacking or whatever). If we can't envision other reasons,
perhaps it would be better to define authed="true" and authed="false";
if we can, perhaps bidi="true" and bidi="false". Here, a value of "true"
means "if SASL negotiation succeeds, you don't need to initiate a TCP
connection back to me but instead you can re-use the existing
stream/connection", whereas "false" means "even if SASL negotiation
succeeds, you will need to negotiate another TCP connection for
communication in the other direction and I'll close this stream with a
<not-authenticated/> error if you try to send data over this stream".

Peter

-- 
Peter Saint-Andre
https://stpeter.im/

---

From: Dave Cridland <[email-masked]>
Date: Fri, 26 Mar 2010 16:23:06 +0000

On Fri Mar 26 15:42:56 2010, Peter Saint-Andre wrote:
> I think the peer is communicating
> that it is willing to allow the stream to be bidirectional.

Right, that's all that's needed - it's just mechanics, not security.

The thing is, from a security standpoint, both initiator and the  
receiver must have authenticated the other party. Otherwise, why is  
the initiator still sending stanzas, and why is the receiver  
accepting them?

Basically I cannot see any case when the receiver is happy to accept  
stanzas from the initiator - and the intitiator is happy to send them  
- yet the reverse is not true.

So the way I'd do this is to have a stream feature:

  <bidi xmlns='urn:xmpp:bidi'/>

A top-level element to turn request it:

  <bidi xmlns='urn:xmpp:bidi'/>

And a response:

  <success xmlns='urn:xmpp:bidi'/>
  <failure xmlns='urn:xmpp:bidi'/>

I don't see the need for anything else - moreover, these could be  
pipelined easily, so don't actually represent a new round-trip.

Dave.

---

From: Philipp Hancke <[email-masked]>
Date: Fri, 26 Mar 2010 17:26:16 +0100

> (initiating entity -- here we could call it a "peer").

The TLS client - it would have been better to say that explicitly.

> if the initiating entity has authenticated the receiving entity, but I

Well... both 3920 and -bis already require that the TLS client should 
not continue to connect unless it can authenticate the TLS server.

So if a server (TLS client) sends 'false' here, it has already continued
to connect even though either the expected identity did not match or the 
certificate of the peer (TLS server) is not trusted.

If clients were compliant, we would only have to signal the ability of 
the client to accept a bidirectional stream. 'mutual' is confusing, 
'bidi' is better.

> <not-authenticated/> error if you try to send data over this stream".

Well... if the originating server does not trust the receiving server to 
send from the target domain, why is it sending messages there?
http://mail.jabber.org/pipermail/xmppwg/2004-February/002009.html

---

From: Philipp Hancke <[email-masked]>
Date: Fri, 26 Mar 2010 18:03:55 +0100

> Right, that's all that's needed - it's just mechanics, not security.

Exactly.

> receiver must have authenticated the other party. Otherwise, why is the 
> initiator still sending stanzas, and why is the receiver accepting them?
> 
> stanzas from the initiator - and the intitiator is happy to send them - 
> yet the reverse is not true.

http://mail.jabber.org/pipermail/xmppwg/2004-February/002026.html
(working archives are super)

> pipelined easily, so don't actually represent a new round-trip.

+1, especially since that applies to dialback as well - at least if you 
make sure that the verification requests (if you don't do DwD) are never 
sent over a bidi stream.

---

From: Kurt Zeilenga <[email-masked]>
Date: Fri, 26 Mar 2010 10:41:05 -0700

I'd like to see us support bidirectional S2S on one stream without TLS.  Just require do DNS checks instead of dialback to have reasonable assurance (as good as dialback) at the receiving entity that the connecting entity is who it would have dialbacked to if it gone that route.

Then if one wants to do TLS, this can be done with or without certificate verification/subject name verification.

-- Kurt

---

From: Kurt Zeilenga <[email-masked]>
Date: Fri, 26 Mar 2010 11:00:22 -0700

> I'd like to see us support bidirectional S2S on one stream without TLS.  Just require do DNS checks instead of dialback to have reasonable assurance (as good as dialback) at the receiving entity th…

Actually, just doing the DNS checks is NOT as good as dialback.

Consider one server is behind a NAT which has inbound rule that S2S connections go to a specific host/port behind the NAT.

If you just do DNS checks, you'd allow any host behind that NAT to masquerade as the server.  Connecting to that server and verifying it knows the dialback key prevents this.

However, it's not a case I'm particularly concerned about as those who operate NATs should take responsibility for the security considerations they introduce.

IMO, if we do allow bidirectional without TLS, we should simply note this as a security consideration.

-- Kurt

---

From: Philipp Hancke <[email-masked]>
Date: Fri, 26 Mar 2010 19:28:19 +0100

> Actually, just doing the DNS checks is NOT as good as dialback.

It has some nice additional features...
You can not open a connection to another domain if your server is not
configured to listen on a port and reachable from the outside.

> IMO, if we do allow bidirectional without TLS, we should simply note this as a security consideration.

Dialback also protects administrators who allow an evil user on the
server machine that can establish an outbound connection from the XMPP
servers IP address. Same problem, same solution ;-)

philipp

---

From: Philipp Hancke <[email-masked]>
Date: Sun, 28 Mar 2010 21:01:48 +0200

> So the way I'd do this is to have a stream feature:

I implemented it that way. Not fully done yet, but it looks promising 
and is straightforward to implement. Thank you!

>  <bidi xmlns='urn:xmpp:bidi'/>

The client should send that before doing SASL or dialback, but after 
doing STARTTLS (if that was offered).

Then, if a client requests dialback for a domain pair (sender domain, 
target domain), the server may (after validating the dialback key) also 
send for (target domain, sender domain).

The same applies to using SASL EXTERNAL, just with the sender domain and 
target domain as specified in the stream header.

>  <failure xmlns='urn:xmpp:bidi'/>

I don't think we need that. When implementing that on the client, I
could not figure out what needs to be done when receiving this and
removed the code.

If that fails the only result is that the client will never get any
stanzas.

And even a <success/> would not imply that there will ever be a
stanza sent from the server to the client - for example because the
server has an older connection to the client and all stanzas travel over
  that connection.

> pipelined easily, so don't actually represent a new round-trip.

+1

philipp

---

From: Peter Saint-Andre <[email-masked]>
Date: Tue, 30 Mar 2010 22:21:04 -0600

> pipelined easily, so don't actually represent a new round-trip.

So this sounds like an XMPP extension, not something that belongs in
rfc3920bis. Correct? If so, feel free to write up a proposal and submit
it to mailto:[email-masked]... :)

Peter

-- 
Peter Saint-Andre
https://stpeter.im/