Subject: domain-based service names redux

From: Peter Saint-Andre <[email-masked]>
Date: Mon, 11 Jun 2007 16:42:02 -0600

Warning: I am far from a Kerberos or SASL expert, and this email mostly 
channels feedback from several XMPP developers (cc'd on this message, 
also cc'ing [email-masked]). My apologies for any inaccuracies.

That said...

I'm working to understand if draft-ietf-kitten-gssapi-domain-based-names 
and draft-ietf-kitten-krb5-gssapi-domain-based-names solve a problem 
we're having in the XMPP community. As you may know, XMPP (RFC 3920) 
essentially streams XML over a long-lived TCP connection. Large XMPP 
deployments tend to require tens of thousands of TCP connections (or 
more) from clients to a server, with the result that they are often 
architected with multiple connection managers (perhaps one CM per 10k 
clients) hooked into a core router. Client connections to the connection 
managers are often managed through a front-end load balancer. We can 
visualize as follows (where "CM" is a connection manager and "C" is a 
client):

             XMPP ROUTER
            /     |    \
          CM     CM     CM
            \     |    /
            LOAD BALANCER
            /     |    \
           C      C     C

(Such a solution *could* be managed via SRV, but in practice that is not 
feasible for some large XMPP deployments.)

The problem is that a client doesn't know which CM it has connected to 
(e.g., cm6.example.com), since that information is hidden by the load 
balancer in the middle (all clients appear to be connected to the IP 
address of the load balancer). For non-Kerberos deployments that doesn't 
matter, but it does matter for Kerberos deployments since a client needs 
to know the address of its service.

My understanding of draft-ietf-kitten-gssapi-domain-based-names is that 
it should be possible to name a CM in such a deployment as a 
GSS_C_NT_DOMAINBASED_SERVICE name like so:

   [email-masked]@cm6.example.com

Where the form is "service@domain@hostname".

In the context of the Kerberos 5 GSS-API mechanism, that would result in 
a principal name of:

   xmpp/cm6.example.com/example.com

Based on my reading of RFC 4752, I assume that in a SASL exchange using 
the GSSAPI mechanism, the client can replace GSS_C_NT_HOSTBASED_SERVICE 
with GSS_C_NT_DOMAINBASED_SERVICE in the following operation (Section 
3.1 of RFC 4752):

    The client calls GSS_Init_sec_context, passing in
    input_context_handle of 0 (initially), mech_type of the Kerberos V5
    GSS-API mechanism [KRB5GSS], chan_binding of NULL, and targ_name
    equal to output_name from GSS_Import_Name called with input_name_type
    of GSS_C_NT_HOSTBASED_SERVICE (*) and input_name_string of
    "service@hostname" where "service" is the service name specified in
    the protocol's profile, and "hostname" is the fully qualified host
    name of the server.

Where the asterisk refers to the following note:

    (*) Clients MAY use name types other than GSS_C_NT_HOSTBASED_SERVICE
    to import servers' acceptor names, but only when they have a priori
    knowledge that the servers support alternate name types.  Otherwise
    clients MUST use GSS_C_NT_HOSTBASED_SERVICE for importing acceptor
    names.

It is less clear to me how this service name should be communicated to 
the XMPP client. Currently in some XMPP implementations the Service 
Principal Name of the connection manager is returned to the client from 
the CM after the TCP connection is made (typically after TLS has been 
negotiated):

http://mail.jabber.org/pipermail/xmppwg/2006-April/002379.html

This is a mere assertion, but no one in the XMPP community has yet 
figured out a better method for communicating the CM's name to the 
client (at least in a way that is deployable in existing organizational 
environments).

Would the use of the GSS_C_NT_DOMAINBASED_SERVICE name provide 
information that is stronger than a mere assertion by the CM? My reading 
of draft-ietf-kitten-gssapi-domain-based-names indicates that the 
"hostname" portion of the GSS_C_NT_DOMAINBASED_SERVICE name may be 
obtained via insecure service discovery mechanisms (DNS SRV is 
mentioned) as long as the service and domain are obtained in a secure 
fashion. Would communication of the GSS_C_NT_DOMAINBASED_SERVICE name 
after TLS negotiation with the service is complete qualify as obtaining 
the service and domain in a secure fashion? It seems to me that before 
TLS is negotiated, communication of the GSS_C_NT_DOMAINBASED_SERVICE 
name from the CM to the client would indeed be a mere assertion, but 
that after TLS is negotiated between the XMPP client and server, the 
client has securely verified the identity of the XMPP server (e.g., the 
combination of service name "xmpp" and domain name "example.com") and 
therefore can accept the hostname asserted by the connection manager. 
(Naturally, that hostname might also be discoverable via SRV through 
resolution of "_xmpp-client._tcp.example.com.".)

If that is right, then the CM could legitimately communicate something 
like the following to the client after they complete the TLS negotiation 
(line breaks included for readability only):

   <stream:features>
     <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
       <mechanism
       GSS_C_NT_DOMAINBASED_SERVICE=[email-masked]@cm6.example.com'>
         GSSAPI
       </mechanism>
       <mechanism>DIGEST-MD5</mechanism>
       <mechanism>PLAIN</mechanism>
     </mechanisms>
   </stream:features>

I freely admit that I may be mistaken, so suggestions from folks in the 
KITTEN and SASL WGs would be most welcome.

Thanks!

Peter

-- 
Peter Saint-Andre
XMPP Standards Foundation
http://www.xmpp.org/xsf/people/stpeter.shtml

_______________________________________________
Kitten mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/kitten

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Tue, 12 Jun 2007 16:02:13 -0400

On Monday, June 11, 2007 04:42:02 PM -0600 Peter Saint-Andre 
<[email-masked]> wrote:

> figured out a better method for communicating the CM's name to the client
> (at least in a way that is deployable in existing organizational
> environments).

So, the model we had in mind was that you'd do a SRV record or reverse DNS 
lookup and use the result of that for the "hostname" part of the 
domain-based service name, with the "domain" part being whatever domain the 
client was configured to talk to.  Of course, that doesn't work when you 
use a "transparent" load balancer; as you noted, you need some other way of 
discovering the hostname.

> My reading
> obtained via insecure service discovery mechanisms (DNS SRV is mentioned)
> as long as the service and domain are obtained in a secure fashion. Would
> communication of the GSS_C_NT_DOMAINBASED_SERVICE name after TLS
> negotiation with the service is complete qualify as obtaining the service
> and domain in a secure fashion?

No.  It is not good enough for the service and domain to be obtained via a 
secure channel; they also have to come from a trusted source, and the 
server that is trying to prove its identity to you doesn't qualify.

The service is actually easy - it's a constant specified by the application 
protocol, at both the GSS and SASL layers.  The domain is trickier, but 
only a little - this is the string the user provided (perhaps as part of a 
URI) that says what domain he wants to talk to.  For XMPP, that is probably 
the name you used for the SRV record lookup.

> It seems to me that before TLS is
> negotiated, communication of the GSS_C_NT_DOMAINBASED_SERVICE name from
> the CM to the client would indeed be a mere assertion, but that after TLS
> is negotiated between the XMPP client and server, the client has securely
> verified the identity of the XMPP server (e.g., the combination of
> service name "xmpp" and domain name "example.com") and therefore can
> accept the hostname asserted by the connection manager. (Naturally, that
> hostname might also be discoverable via SRV through resolution of
> "_xmpp-client._tcp.example.com.".)

That seems fishy.  I think if you do that, you need to verify that the name 
the server is asserting matches its certificate.  And, of course, that the 
cert matches what the user asked for.

-- Jeff

---

From: Martin Rex <[email-masked]>
Date: Tue, 12 Jun 2007 23:03:11 +0200 (MEST)

> to know the address of its service.

I never liked hostbased service names ;-)

For "old-fashioned" 2-token Kerberos authentication (which is the
authentication exchange currently covered by the official Kerberos 5
gssapi mechanisms (rfc-1964 and rfc-4121), the sharing of the
server credentials is a problem.  (session replay to servers sharing
credentials but not sharing the replay cache).

If Kerberos user2user authentication is used (exclusively), such a
vulnerability from sharing the server credentials does not exist.
Microsoft has implemented the 3-token user2user authentication exchange
in addition to the 2-token authentication exchange of the IETF-defined
Kerberos 5 gssapi mechanism, it has already been available in Windows 2000.

The correct approach of using the 2-token exchange in a distributed
environment was implemented by DCE many many years ago, but requires
a secure directory, something not available in traditional Kerberos.

The most sensible and infrastructure-independent approach (i.e. independent
of how load-balancing is done within the backend and where within
the backend the secure communication is terminated) for traditional
Kerberos authentication would be to standardize the user2user
authentication exchange and use that (no use of _hostbased_
service names).

Today, this option is only available if you go proprietary
(or implementation-specific).

-Martin

---

From: Peter Saint-Andre <[email-masked]>
Date: Thu, 14 Jun 2007 12:33:45 -0600

> (or implementation-specific).

Not an option. XMPP implementations use the open standards developed by 
the IETF. That's why I'm asking in this venue. :)

It's not clear to me how the session replay attack you mention is 
specific to the architecture I described. Couldn't an attacker send an 
earlier ticket even if there is only one service involved (i.e., in my 
description, only one connection manager)?

My understanding of potential objections to the method I described in my 
previous email is that there is no way for the XMPP client to trust that 
the connection manager (asserted as cm6.example.com) is associated with 
the domain (example.com) to which the initiator connected in the first 
place. But if the client and connection manager have successfully 
upgraded the XMPP stream to TLS (see Section 5 of RFC 3920), then 
presumably the connection manager has provided appropriate credentials 
(e.g., X.509 certificate) that it is indeed so associated. And if the 
connection manager asserts its GSS_C_NT_DOMAINBASED_SERVICE name only 
after TLS has been negotiated, then I think the risk is mitigated. What 
is the attack at that point?

Peter

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Thu, 14 Jun 2007 15:05:57 -0400

> description, only one connection manager)?

The basic Kerberos protocol provides only a limited amount of reply 
protection for applications, by requiring that clients include in their 
request a timestamp which must be "close enough" to the server's clock. 
The idea is that you get full replay protection by combining this with a 
cache which stores all messages received within the "close enough" period 
-- messages that are too old are rejected outright; more recent messages 
are rejected if they appear in the replay cache.  This only works if 
servers which share the same service key also share the same replay cache.

(BTW, the details of Kerberos are getting just a bit far afield for the 
Kitten list; at the GSS-API layer you're not supposed to care much what 
mechanism is being used, and at the SASL layer you should care even less).

Depending on the application involved, this may not be an issue.  For 
example, some application protocols are designed such that the application 
messages themselves are protected from replays, or require some sort of 
initial exchange that makes a replay impossible.

Similarly, you have to see a message to replay it, so if you are always 
using TLS _and checking the server's certificate_, then you need not worry 
about your credentials being replayed to a server.  Of course, servers do 
not have the luxury of assuming that clients will behave in this way.

> place.

Right.  This is why the domain indicated by the initiator is one of the 
parts of a domain-based service name; the presumption is that 
authentication with such a name will succeed only if that server is valid 
for that domain.

> But if the client and connection manager have successfully
> (e.g., X.509 certificate) that it is indeed so associated.

If that were true, then you wouldn't need a domain-based service name at 
all.  You could potentially just assume that whatever service name the 
service gives you is valid.  However, that's dangerous, as it could allow a 
"legitimate" but evil server to trick you into carrying out a negotiation 
to authenticate yourself to some other, unrelated service, and then cut you 
off and do anything it wants to the other service as you.

Also, "the connection manager has provided appropriate credentials" is 
unfortunately not a very good presumption.  Between users ignoring warning 
dialogs, software that ships with who-knows-what trust anchors, and 
software that just plain doesn't bother to validate server credentials, it 
is often the case that a TLS connection is established without the server 
actually proving its identity.  While this may be the best you can do for 
some authentication methods, I would not count on it for the security of 
Kerberos authentication, where it clearly is not necessary.

-- Jeff

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Thu, 14 Jun 2007 16:24:34 -0400 (EDT)

On Thu, 14 Jun 2007, Joe Hildebrand wrote:

> I'm not tracking what you meant by "not necessary".  Are you saying
> it's OK for the the CM to send it's service principal name to the
> client through an insecure channel?

No; I'm saying that it is not necessary to make the security of
sasl-gss-krb5 dependent on the security of the TLS tunnel over which it is
run, and that therefore it would be a poor design choice to introduce such
a dependency by specifying a means for obtaining the service principal
name that depends on the security of that tunnel.

That said, if you are using domain-based service names and doing so
correctly, it _is_ OK for the CM to send the hostname part to the client
through an insecure channel, as long as the service and domain parts are
obtained securely -- for example, from the protocol spec and the user,
respectively.

That is, if the user wants to talk to the XMPP service at example.com,
then the only acceptable value for the service part is "xmpp" (per the
spec), and the only acceptable value for the domain part is "example.com"
(from the user).  The hostname can be obtained from the CM by any means
you want.

-- Jeff

---

From: Joe Hildebrand <[email-masked]>
Date: Thu, 14 Jun 2007 14:05:25 -0600

On Jun 14, 2007, at 1:05 PM, Jeffrey Hutzelman wrote:

> Also, "the connection manager has provided appropriate credentials"  
> is unfortunately not a very good presumption.  Between users  
> ignoring warning dialogs, software that ships with who-knows-what  
> trust anchors, and software that just plain doesn't bother to  
> validate server credentials, it is often the case that a TLS  
> connection is established without the server actually proving its  
> identity.  While this may be the best you can do for some  
> authentication methods, I would not count on it for the security of  

-- 
Joe Hildebrand

---

From: Peter Saint-Andre <[email-masked]>
Date: Thu, 14 Jun 2007 14:51:15 -0600

> (from the user).  The hostname can be obtained from the CM by any means

Aha, OK. In our case it is indeed true that (1) the only acceptable 
value for the service part is "xmpp" and (2) the domain part will be 
provided by the user. It also happens to be true that in a typical 
high-security deployment the hostname of the CM will be communicated 
from the CM to the user over a TLS-encrypted XML stream; however, at an 
implementation level TLS is not yet required in XMPP so it possible that 
the hostname of the CM may be communicated over an XML stream that is 
not TLS-encrypted -- but you are saying that doesn't matter anyway.

BTW this issue will probably not be addressed in rfc3920bis because it 
is a bit of an edge case that is useful only for certain deployments, 
but we will probably define an XMPP extension for this functionality in 
a spec produced by the XMPP Standards Foundation.

Peter

---

From: Nicolas Williams <[email-masked]>
Date: Fri, 15 Jun 2007 14:46:13 -0500

> I never liked hostbased service names ;-)

Well, we undoubtably need principal names for hosts.  The service part
seems... less necessary.

That said, the service name component does simplify privilege separation
of different applications running on the same host because each can
manage its own keys without impacting the others.  Without service names
one has to ensure that there is a local facility for handling keys that
does not expose them to the apps, at least where said keys can be used
by one app against the other (typically that would be symmetric keys in
a protocol like Kerberos V).

Nico
--

---

From: Nicolas Williams <[email-masked]>
Date: Fri, 15 Jun 2007 14:56:00 -0500

> authentication exchange and use that (no use of _hostbased_

Well, no.  The ideal thing to do (as opposed to the *pragmatic* thing to
do) is to add a new krb5 mech or extension to the existing mech that
uses three tokens, with an option for user-to-user[*], so as to get rid
of the need for a replay cache.

That has nothing to do with also deprecating the user of hostbased
service names.  Apps will still need a way to name non-human entities
running on specific hosts.  And whether we drop the _service_ part of
hostbased service names is also an other story.

[*]  With RFC4120 as it is it is not quite possible to do a three-token
     user-2-user mechanism; four tokens are required.  That's because
     the initiator has to be the one sending the AP-REQ, but it can't
     make an AP-REQ until it has obtained the acceptor's Ticket (which
     has got to be sent no earlier than in the second token since in the
     GSS-API the initiator always sends the first token).

     A user-2-user three-token mechanism is possible however, but the
     spec for it would have to update RFC4120.

Nico
--

---

From: Michael B Allen <[email-masked]>
Date: Fri, 15 Jun 2007 17:40:14 -0400

On Fri, 15 Jun 2007 14:46:13 -0500

> a protocol like Kerberos V).

Hi Nico,

I haven't really been following this thread carefully but I have a
thought that may or may not be relevant.

When authenticating HTTP clients using Kerberos / GSSPI it's very nice
to be able to call gss_accept_sec_context with GSS_C_NO_CREDENTIAL so
that the server can choose a key in the keytab suitable for the target
principal requested.

As I'm sure you're aware HTTP clients do different things to come up
with the target SPN. Some just use the hostname in the URL. Some do
some canonicalization. If you're doing virtual hosting browsers will
send different SPNs.

However, rumor has it that if GSS_C_NO_CREDENTIAL is used I think clients
can authenticate with services using an SPN that is different from the
SPN the ticket was acquired with. Meaning, depending on how accounts
are setup, someone might be able to use their FTP ticket to authenticate
with HTTP.

Anyway I'm thinking about how that might interact with using service
name components to implement "privilege separation".

Mike

-- 
Michael B Allen
PHP Active Directory Kerberos SSO
http://www.ioplex.com/

---

From: Nicolas Williams <[email-masked]>
Date: Fri, 15 Jun 2007 17:26:51 -0500

> that the server can choose a key in the keytab suitable for the target

No, that's _always_ nice to be able to do :)

> are setup, someone might be able to use their FTP ticket to authenticate

Right.  Two things:

1) Different services using different acceptor principals shouldn't
   share acceptor credentials.  If they don't share those credentials
   then this can't happen.

2) Acceptors that use GSS_C_NO_CREDENTIAL should check the target name
   used by the initiator (see GSS_Inquire_sec_context() and
   GSS_Display_name()).

Unfortunately GSS_Display_name() typically returns a mechanism-specific
version of the MN used by the initiator, which means that (2) results in
less than generic (vis-a-vis mechanisms) code.

We have talked in the past about acceptor credential sets, but, frankly,
the GSS-API is complicated enough as it is that (1) is the best way
forward here, and an improved version of GSS_Display_name() (which we
intend to pursue) would help implementors pursuing (2).

> name components to implement "privilege separation".

See (1).

Nico
--

---

From: Nicolas Williams <[email-masked]>
Date: Fri, 15 Jun 2007 17:36:59 -0500

To clarify, (1) means "run each service with a separate keytab (and
rcache) with entries only for the principals that you want the service
to be able to accept as."

---

From: Martin Rex <[email-masked]>
Date: Sat, 16 Jun 2007 01:54:32 +0200 (MEST)

> Well, we undoubtably need principal names for hosts.  The service part

Depends on what you do.

In many situations hostbased service names are not only unnecessary,
they acutually create significant pain and problem.

On which particular "host" a service runs today, and on which
it runs tomorrow should be left up to the sysadmin, in many
situations a causal user need not and ought not to care about this.

None of the X.509-based gssapi mechanims I've seen so far did
support hostbased service names.  Probably all of our customers
that use an X.509-based gssapi mechanism for single sign-on
do *NOT* put hostnames into their server's certificates, but
instead the name of the distributed system,  because
it is so much easier if you can share the credentials for
all servers in your backend server farm.  You also don't have
to mess with the ACLs used by backend servers to authenticate
each other when you add or change/replace servers.

When using domain-based service names, the "service name" should
probably not name a protocol, but rather a particular incarnation
of a service.  Otherwise, one would need a seperate "domain"
(DNS-domain, Kerberos Realm) for each independently-managed
incarnation of a service talking a particular protocol.

A single (independently managed) Web-Server per domain looks like
a pretty strong limitation to me, and requiring a seperate domain
(or worse, a seperate kerberos realm) per Web-Server is a fairly
expensive solution (e.g. when each kerberos realm is equal
to a seperate Windows PDC).

But if _not_ using the protocol for the service part of the name,
the client software has little chance to guess it (or to supply
it automatically), it needs to get that information from the user.

-Martin