Subject: Re: [sasl] Mechanism Negotiation and Channel Binding with SCRAM

From: Simon Josefsson <[email-masked]>
Date: Mon, 01 Mar 2010 14:18:16 +0100

Tobias Markmann <[email-masked]> writes:

> Hi,
>
> In http://www.ietf.org/id/draft-ietf-sasl-scram-11.txt , Section 6, Bullet Point No 2 it says:
>> If the client negotiates mechanisms then the client MUST select
>> SCRAM-<hash-function>-PLUS if offered by the server and the client
>> wants to select SCRAM with the given hash function. Otherwise...
>
>
> How are clients supposed to behave if they don't support channel
> binding? Selecting SCRAM-<hash function>-PLUS doesn't make a lot sense
> in that case. However if that is the intended behavior it would be
> nice to have it more explicit in the text; or is the whole 'Channel
> Binding' section to be ignored if channel binding isn't supported by
> the client when it comes to protocol assertions?

Good point.  I believe it should be allowed for clients that do not
support channel bindings to select the non-PLUS name directly.  This is
what the GNU SASL client does, by the way.

/Simon

---

From: Nicolas Williams <[email-masked]>
Date: Mon, 1 Mar 2010 11:30:17 -0600

> what the GNU SASL client does, by the way.

The -PLUS thing is primarily a method by which the server indicates that
it supports channel binding.  The choice of -PLUS or not on the
client-side is irrelevant since the gs2-cbind-flag is what matters in
terms of downgrade protection.

When a client uses a non-PLUS name for SCRAM and sets gs2-cbind-flag=p
or gs2-cbind-flag=n the server can't tell whether the client is one that
cannot negotiate or if a downgrade attack was attempted.

The first MUST in the fourht bullet is somewhat more restrictive still.
There's no reason that the client should not use the non-PLUS name and
set gs2-cbind-flag=p even if the client negotiates mechanisms and the
server did not advertise the -PLUS name.

Therefore Tobias is correct that the "MUST" he quoted is not strictly
necessary.  It isn't exactly harmful, and at this point I'm inclined to
leave it as is.  However, if we really must, _now_ is the time to make a
change here (since SCRAM is in AUTH48).  Care to propose text?  Note
that SCRAM and GS2 both would have to be updated to be in sync with
regards to this change.

Nico
--

---

From: Simon Josefsson <[email-masked]>
Date: Mon, 01 Mar 2010 23:23:51 +0100

> terms of downgrade protection.

I agree.

> cannot negotiate or if a downgrade attack was attempted.

I don't see that.

If 'p' is chosen, negotiation will proceed correctly, and it will use a
channel binding.  There is no degraded security here?

If 'n' is chosen, the client is telling the server that it doesn't
support channel binding.  A client that supported channel bindings, but
did not see the *-PLUS name, MUST have sent 'y' here.  A client that
does not support channel bindings will always send a 'n'.  No degraded
security?  The server can tell from the use of 'n' or 'y' whether the
client supported channel bindings or not.

So I don't see how a downgrade attack affects anything here?  Maybe I'm
missing something.

> server did not advertise the -PLUS name.

I agree.

> that SCRAM and GS2 both would have to be updated to be in sync with

I don't care strongly, but at least my implementation wouldn't be
compliant with the current letters as the document is written now.

Given how many SASL libraries work, I suspect it will be common for
non-cb-capable clients to always chose the non-PLUS name directly.  For
example, Alexey, does your Cyrus SASL implementation select the *-PLUS
name if the server advertises it?

More information from Tobias why he noticed this wording could be
relevant too.

Given our discussion so far that there is no technical problem with
chosing a non-PLUS name in the client, and my code is already shipping,
I'm not that inclined to change it (at least not without a better
rationale).

For GS2 a proposed change would be:

OLD:
   o  If the client negotiates mechanisms, then clients MUST select the
      PLUS-variant if offered by the server.  Otherwise (the client does
      not negotiate mechanisms),

NEW:
   o  If the client negotiates mechanisms and supports channel bindings,
      then clients MUST select the PLUS-variant if offered by the
      server.  Otherwise (the client does not negotiate mechanisms or do
      not support channel bindings),

OLD:
   o  If the client supports channel binding and the server does not
      appear to (i.e., the client did not see the -PLUS name), then the
      client MUST either fail authentication or it MUST chose the non-
      PLUS mechanism name and use a "y" gs2-cb-flag.

NEW:
   o  If the client supports channel binding and the server does not
      appear to (i.e., the client did not see the -PLUS name), then the
      client MUST either fail authentication or it MUST NOT chose the
      "n" gs2-cb-flag.

For SCRAM it would be:

OLD:
   o  If the client negotiates mechanisms then the client MUST select
      SCRAM-<hash-function>-PLUS if offered by the server and the client
      wants to select SCRAM with the given hash function.  Otherwise
      (the client does not negotiate mechanisms)

NEW:
   o  If the client negotiates mechanisms and supports channel bindings
      then the client MUST select SCRAM-<hash-function>-PLUS if offered
      by the server and the client wants to select SCRAM with the given
      hash function.  Otherwise (the client does not negotiate
      mechanisms or do not support channel bindings)

OLD:
   o  If the client supports channel binding but the server does not
      appear to (i.e., the client did not see SCRAM-<hash-function>-
      PLUS) then the client MUST either fail authentication or it MUST
      choose the non-PLUS mechanism and set the GS2 channel binding flag
      to "y" and MUST NOT include channel binding data for the external
      channel in the computation of the "c=" attribute (see
      Section 5.1).

NEW:
   o  If the client supports channel binding but the server does not
      appear to (i.e., the client did not see SCRAM-<hash-function>-
      PLUS) then the client MUST either fail authentication or it MUST
      NOT choose the "n" GS2 channel binding flag or include channel
      binding data for the external channel in the computation of the
      "c=" attribute (see Section 5.1).

English is not a good language to express this in... sigh.

/Simon

---

From: Nicolas Williams <[email-masked]>
Date: Mon, 1 Mar 2010 16:44:24 -0600

> channel binding.  There is no degraded security here?

The _mechanism_ negotiation.

> did not see the *-PLUS name, MUST have sent 'y' here.  A client that

If the client doesn't do mechanism negotiation then it can pick the
non-PLUS names and set gs2-cbind-flag=p.  The server will accept that if
it supports channel binding and everything will work -- the server can't
tell whether the client saw that the server supports -PLUS because,
regardless of whether the client listed the mechanisms available on the
server, in this example the client was presupposed to not support
mechanism negotiation.

> So I don't see how a downgrade attack affects anything here?  Maybe I'm

It doesn't -- I'm saying that the server can't tell whether one was
attempted.  But, then again, the channel binding will fail if there was
such an attack.

> I'm not that inclined to change it (at least not without a better

OK.

>       not support channel bindings),

I see no real change.  I think we want to s/MUST select/selects/ to go
from normative to declarative language.

>       client MUST either fail authentication or it MUST NOT chose the

That works.  I'd tighten that up a bit as follows:

NEW:
   o  If the client supports channel binding but does not support
      mechanism negotiation, then the client MUST use channel binding
      (and so set gs2-cb-flag=p) and the use or non-use of the -PLUS
      suffix is irrelevant.

   o  If the client supports channel binding then the client MUST NOT
      set gs2-cb-flag=n.

   o  Corollary: if the client supports channel binding and mechanism
      negotiation, and the server does not appear to support channel
      binding then the client either: a) MUST fail authentication
      without trying, b) MUST NOT use SCRAM, c) MUST go ahead and use
      SCRAM (with or without the -PLUS suffix) with gs2-cb-flag=p and
      use channel binding, or d) MUST go ahead and use SCRAM (with or
      without the -PLUS suffix) with gs2-cb-flag=y and no channel
      binding.

> For SCRAM it would be:

Same comments.

> English is not a good language to express this in... sigh.

I don't think that's the issue.  I think the issue is just that we
should to use declarative language instead of normative language when
some choices are irrelevant.

Nico
--

---

From: Simon Josefsson <[email-masked]>
Date: Tue, 02 Mar 2010 00:10:49 +0100

> attempted.  But, then again, the channel binding will fail if there was

Exactly.  Detecting whether a downgrade attack is attempted seems
pointless if the downgrade attack cannot succeed, which certainly will
be detected eventually.

> from normative to declarative language.

That seems simpler.

>       without the -PLUS suffix) with gs2-cb-flag=y and no channel

Seems good to me, although it needs to be adapted to GS2 as well.

The question remains if we want to make this change now or not.  Both
SCRAM and GS2 needs to be updated.  Your proposed change wouldn't be the
most minimal fix, but maybe clarity is better served by rewriting these
paragraphs.

/Simon

---

From: Nicolas Williams <[email-masked]>
Date: Mon, 1 Mar 2010 17:19:01 -0600

On Tue, Mar 02, 2010 at 12:10:49AM +0100, Simon Josefsson wrote:
> > [...]

Does anyone else have an opinion on this?  I'd be happy doing: a)
nothing, b) changing a couple of normative MUSTs into declaratives, c)
re-writing some of these as I proposed.

_Now_ is the time to ask.

Nico
--

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Mon, 01 Mar 2010 19:24:35 -0500

> _Now_ is the time to ask.

I'm inclined to leave it as-is, simply because quite a few people have 
thought rather carefully about how the negotiation process covers all the 
possible cases, and relaxing a requirement risks invalidating an assumption 
that someone made during that evaluation.

However, I don't feel terribly strongly about it.

---

From: Paul Aurich <[email-masked]>
Date: Mon, 01 Mar 2010 17:43:24 -0800

> More information from Tobias why he noticed this wording could be

It's not very interesting, I'm afraid.  Tobias was asking on my behalf
(I wasn't subscribed to the list) because I kept pestering him :).

I was re-reading the channel binding sections of the spec in preparation
for implementing it in Pidgin, couldn't see a technical reason for the
wording, and disagreed with Tobias about the intention of the text.

Adding further comments in other parts of the thread,
~Paul

---

From: Paul Aurich <[email-masked]>
Date: Mon, 01 Mar 2010 17:44:23 -0800

>       mechanisms or do not support channel bindings)

That doesn't quite flow with the rest of the bullet point (pertaining
specifically to a client that does not negotiate mechanisms).  Something
like the following fixes my nitpick:

      Otherwise, if the client does not negotiate mechanisms, if the
      client has no prior knowledge about mechanisms supported

~Paul

---

From: Paul Aurich <[email-masked]>
Date: Mon, 01 Mar 2010 17:45:12 -0800

>>       without the -PLUS suffix) with gs2-cb-flag=y and no channel

Maybe I'm picky, but I think the "(with or without the -PLUS suffix)"
should be removed, since the assumption is already that the server does
not appear to support channel binding.

> most minimal fix, but maybe clarity is better served by rewriting these

I'm in favor of changing (or at least clarifying) it, and prefer Nicolas
and Simon's text.  Another possible textual change would be to just
clarify my initial confusion:

OLD:

   o  If the client negotiates mechanisms then the client MUST select
      SCRAM-<hash-function>-PLUS if offered by the server

NEW:

   o  If the client negotiates mechanisms (whether or not it supports
      channel binding) then the client MUST select
      SCRAM-<hash-function>-PLUS if offered by the server

~Paul

---

From: Simon Josefsson <[email-masked]>
Date: Tue, 02 Mar 2010 11:57:01 +0100

> re-writing some of these as I proposed.

I kind of prefer b) and the main reason is to minimize the amount of
changes we do at this late time.

I believe that if we don't change this now, clients without channel
binding support will violate the first MUST in practice.  This will
likely cause problems when moving SCRAM from Proposed to Draft (if that
happens...).

/Simon

---

From: Alexey Melnikov <[email-masked]>
Date: Tue, 02 Mar 2010 12:27:42 +0000

>likely cause problems when moving SCRAM from Proposed to Draft (if that
I can be easily confused by declarative language, so I would prefer c). 
But I can live with b).

---

From: Nicolas Williams <[email-masked]>
Date: Tue, 2 Mar 2010 13:37:23 -0600

> I can be easily confused by declarative language, so I would prefer c). 

Ok.  For GS2 then I propose the following changes (if you agree I'll
make the same changes for SCRAM and post them):

-   o  If the client negotiates mechanisms, then clients MUST select the
-      PLUS-variant if offered by the server.  Otherwise (the client does
-      not negotiate mechanisms), if the client has no prior knowledge
-      about mechanisms supported by the server and wasn't explicitly
-      configured to use a particular variant of the GS2 mechanism, then
-      it MUST select only non-PLUS version of the GS2 mechanism.
+   o  Clients that support mechanism negotiation and channel binding
+      MUST use a "p" gs2-cb-flag when the server offers the PLUS-variant
+      of the desired GS2 mechanism.

+   o  Clients that do not support mechanism negotiation but do support
+      channel binding MUST use a "p" gs2-cb-flag and SHOULD use the non-
+      PLUS variant of the desired GS2 mechanism.
+   
    o  If the client does not support channel binding, then it MUST use a
       "n" gs2-cb-flag.

    o  If the client supports channel binding and the server does not
       appear to (i.e., the client did not see the -PLUS name), then the
-      client MUST either fail authentication or it MUST chose the non-
-      PLUS mechanism name and use a "y" gs2-cb-flag.
+      client SHOULD either fail authentication immediately or choose
+      the non-PLUS mechanism name and use a "y" gs2-cb-flag.

-   o  If the client supports channel binding and the server appears to
-      support it (i.e., the client see the -PLUS name), or if the client
-      wishes to use channel binding but the client does not negotiate
-      mechanisms, then the client MUST use a "p" gs2-cb-flag to indicate
-      the channel binding type it is using.
-   
    o  The client generates the chan_bindings input parameter for
       GSS_Init_sec_context as described below.

Nico
--

---

From: Alexey Melnikov <[email-masked]>
Date: Tue, 02 Mar 2010 21:42:34 +0000

[...]

>non-cb-capable clients to always chose the non-PLUS name directly.
>
Agreed.

>For example, Alexey, does your Cyrus SASL implementation select the *-PLUS
Well, I didn't implement SCRAM-SHA-1-PLUS support yet, as this will 
require some API changes in libsasl itself. So this will be move involved.

---

From: Simon Josefsson <[email-masked]>
Date: Tue, 02 Mar 2010 23:00:14 +0100

> require some API changes in libsasl itself. So this will be move

The problem is that the current SCRAM document says that your
non-channel binding capable client MUST chose the SCRAM-SHA-1-PLUS
mechanism name if the server advertises SCRAM-SHA-1-PLUS (and your
client negotiates mechanisms, which I believe Cyrus SASL does).

So if your SCRAM client selects SCRAM-SHA-1 when SCRAM-SHA-1-PLUS is
advertised by the server, your implementation (like mine) violates a
MUST in the document.

If I'm the only one making this mistake, we could live with that from a
specification protocol point of view, but I suspect most client
implementers will implement it the same way.  It is the most natural way
for things to behave, and there doesn't appear to be any reason for
disallowing that.

/Simon

---

From: Alexey Melnikov <[email-masked]>
Date: Tue, 02 Mar 2010 22:42:41 +0000

>       GSS_Init_sec_context as described below.
This looks good to me.

---

From: Simon Josefsson <[email-masked]>
Date: Wed, 03 Mar 2010 18:03:23 +0100

> +      of the desired GS2 mechanism.

Fine.

> +      PLUS variant of the desired GS2 mechanism.

This is an unrelated change, and I don't like it -- why should, for
example, clients that _requires_ channel bindings have to select the
non-PLUS name?

This change actually _introduce_ the same kind of problem that we wanted
to fix!  Now the problem is the reverse -- with the above text, clients
that ONLY support channel binding-enabled GS2/SCRAM will need logic to
deal with the non-PLUS name.  This is the reverse problem as Tobias
noticed: clients that DO NOT support channel bindings shouldn't have to
worry about the PLUS name.

> +      the non-PLUS mechanism name and use a "y" gs2-cb-flag.

Why SHOULD here?

/Simon

---

From: Alexey Melnikov <[email-masked]>
Date: Wed, 03 Mar 2010 17:08:11 +0000

[...]

>>+      the non-PLUS mechanism name and use a "y" gs2-cb-flag.
I was actually thinking about that as well, but decided that that allows 
for "fallback to other SASL" mechanisms, etc.

---

From: Nicolas Williams <[email-masked]>
Date: Wed, 3 Mar 2010 11:21:36 -0600

OK.

> > +      the non-PLUS mechanism name and use a "y" gs2-cb-flag.

Because the client could also continue and use a "p" gs2-cb-flag.  Ah!
What we must say is that the client MUST NOT use a "n" gs2-cb-flag --
the other options are all equally reasonable.

Nico
--