Subject: Re: [kitten] SCRAM for GSS-API

From: Jeffrey Hutzelman <[email-masked]>
Date: Mon, 07 Feb 2011 18:20:06 -0500

--On Sunday, February 06, 2011 04:49:05 PM +0100 Gerd Stolpmann 
<[email-masked]> wrote:

> Hello,
>
> I'm implementing SCRAM (RFC 5802) for GSS-API. In my opinion, the text
> has a few imprecise statements, and I'd like to clarify on them.
>
> In particular, the question is how to interpret section 8, which reads
>
>   "The messages are the
>    same, but a) the GS2 header on the client's first message and channel
>    binding data is excluded when SCRAM is used as a GSS-API mechanism,
>    and b) the RFC2743 section 3.1 initial context token header is
>    prefixed to the client's first authentication message (context
>    token)."

It may help to work backwards.

SCRAM-as-SASL is exactly GS2 with SCRAM-as-GSSAPI as the GSS mech.
So, all the bits of SCRAM-as-SASL that come from GS2 are not present in 
SCRAM-as-GSSAPI.  The idea is that if I take your GSSAPI mechanism 
implementation and plug it into a generic GS2 implementation, what I get 
out is interoperable with a straight SCRAM-as-SASL.

> The exclusion (removal?) of the GS2 header probably means that the
> production for gs2-header should read
>
> 	gs2-header = epsilon
>
> which is also compatible with RFC 5801 (GS2).

There are two places where the ABNF for SCRAM-as-SASL refers to the 
gs2-header production.  Ths production provides bits that actually come 
from GS2, rather than from the SCRAM mechanism itself.  When you are 
implementing as a GSSAPI mechansim, the entire gs2-header production is 
omitted.

> However, the wording is
> not really precise. Another problem is the removal of the channel
> binding data (the sentence is quite strange English in this respect).
> This occurs in client-final-message-without-proof, which is defined as
>
>    client-final-message-without-proof =
>                      channel-binding "," nonce ["," extensions]
>
> So, how to remove channel binding data here? It needs to be removed,
> because it is essentially a copy of the channel binding that might be in
> gs2-header.

No, you don't remove the channel binding data.  You remove gs2-header from 
the CB data.  Of course, if you got channel bindings from the application 
(cbind-data), you still include that.

-- Jeffrey T. Hutzelman (N3NHS) <[email-masked]>
   Carnegie Mellon University - Pittsburgh, PA

---

From: Gerd Stolpmann <[email-masked]>
Date: Tue, 08 Feb 2011 15:18:32 +0100

> out is interoperable with a straight SCRAM-as-SASL.

Thanks for explaining this - it's not immediately obvious (although I
must admit one _can_ have this idea when reading the text).

> implementing as a GSSAPI mechansim, the entire gs2-header production is 

Ok, so this is the part I got right.

> (cbind-data), you still include that.

What still confuses me is the definition of cbind-input (and
channel-binding is just a base64 encoding of cbind-input):

cbind-input   = gs2-header [ cbind-data ]

So, given the above symmetry that SCRAM-as-SASL=GS2(SCRAM-as-GSSAPI), I
wonder how the GS2 implementation can ensure that the right gs2-header
is included at this place. It cannot just add it here, because this
would change the signatures (and it is also not described as such in RFC
5801). The conclusion is that even SCRAM-as-GSSAPI has to include the
gs2-header at this point of the protocol - which feels a bit strange,
and is probably the source of my confusion. Also, gs2-header may include
gs2-authzid which also looks weird (at this point of the protocol).

I see now that section 5.1 of RFC 5801 restricts the possible values for
the chan_bindings parameter of GSS-API. So the format of cbind-input
could be read as a consequence of this constraint on chan_bindings. In
my project, I do not plan to support channel bindings, so I guess the
client should just send "n" as gs2-header, and the server also tolerate
"y".

Do I come closer to the intended meaning?

Gerd
-- 
------------------------------------------------------------
Gerd Stolpmann, Bad Nauheimer Str.3, 64289 Darmstadt,Germany 
[email-masked]          http://www.gerd-stolpmann.de
Phone: +49-6151-153855                  Fax: +49-6151-997714
------------------------------------------------------------

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Tue, 08 Feb 2011 12:01:08 -0500

--On Tuesday, February 08, 2011 03:18:32 PM +0100 Gerd Stolpmann 
<[email-masked]> wrote:

>> > because it is essentially a copy of the channel binding that might be
>> > in gs2-header.
>>
>> No, you don't remove the channel binding data.  You remove gs2-header
>> from  the CB data.  Of course, if you got channel bindings from the
>> application  (cbind-data), you still include that.
>

GS2 takes the channel binding data passed to it by the application, 
prepends the GS2 header, and passes the result as channel binding data to 
the GSS-API mechanism.

> the chan_bindings parameter of GSS-API.

No; it restricts the format of the c= attribute in the SCRAM mechanism. 
The GSS-API channel bindings (and, for that matter, the channel bindings 
provided by a SASL application) can be ~anything.  gs2-header is part of 
the way GS2 wraps a GSS-API mechanism to form a SASL mechanism.

 So the format >of cbind-input
> client should just send "n" as gs2-header, and the server also tolerate

If you're a GSS-API mechanism, you don't send gs2-header at all.  The whole 
n/p/y thing is an artifact of how SASL does negotiation of channel bindings 
and is part of GS2.  In the GSS-API mechanism, there is no negotiation; the 
channel bindings data sent by the client (which may be empty) must agree 
with that sent by the server, or authentication fails.

Note that an implementation of SCRAM MUST support channel bindings, though 
an application doesn't have to use them.  If yours is a single-application 
mechanism, you can decide that cbind-input is always empty and not pass it 
around as a parameter in your API, but you'd still have to compute the 
messages properly.

---

From: Sam Hartman <[email-masked]>
Date: Tue, 08 Feb 2011 12:05:28 -0500

I don't think so.
I think the fact the the gs2 header is part of the scram channel binding
is simply because conceptually that is the channel binding data gs2
passes into the gss-api mechanism.
So in a non-sasl use case I would not expect either n or y to appear in
the channel binding for the GSS-API mechanism.

---

From: Gerd Stolpmann <[email-masked]>
Date: Tue, 08 Feb 2011 18:31:42 +0100

> the way GS2 wraps a GSS-API mechanism to form a SASL mechanism.

Right, this makes sense. I forgot that GS2 is also the caller of
GSS_Init_sec_context, so it can easily smuggle the gs2-header in at this
point.

> with that sent by the server, or authentication fails.

Ok
.
> around as a parameter in your API, but you'd still have to compute the 

Right.

What does "MUST" mean in this case? As far as channel binding data are
just opaque tokens, there is no problem, and SCRAM can just transport
them. However, at a certain point channel bindings need to be enforced.
I guess you'd say this is the task of the application?

Anyway, thanks for your patience. My confusion is gone.

Gerd

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Tue, 08 Feb 2011 12:43:33 -0500

> I guess you'd say this is the task of the application?

Yes.  The job of SASL or GSS-API is to insure that the channel bindings 
data provided by the client agrees with that provided by the server.  It is 
up to each of those, at the application level, to insure that the data they 
provide actually matches the channel in use.  Neither SASL nor GSS-API can 
do this, because all they do is generate and process tokens which are 
transported by the application in whatever way it wants.

-- Jeff