Current semantics for channel-bindings in GSSAPI

Simo Sorce simo at redhat.com
Mon Mar 2 12:30:19 EST 2020


On Mon, 2020-03-02 at 15:12 +0100, Isaac Boukris wrote:
> On Fri, Feb 28, 2020 at 6:00 PM Greg Hudson <ghudson at mit.edu> wrote:
> > On 2/27/20 8:27 PM, Isaac Boukris wrote:
> > > Following the discussion on  IRC, there is currently a difference in
> > > between Heimdal and MIT, when the client does not send bindings, and
> > > the server does pass bindings to accept(), in MIT it fails, in Heimdal
> > > it succeeds.
> > 
> > There are a few reasons why I think Heimdal's behavior is better:
> 
> Taking a closer look at MIT accept() code, it looks like there is a
> case where no checksum is provided at all, where MIT would skip
> channel-bindings even if the server provided ones. It sounds like
> Windows also supports this.
> 
> https://github.com/krb5/krb5/blob/2b1acc07a267782a7f4c9644da78587cc29b6f56/src/lib/gssapi/krb5/accept_sec_context.c#L659

Given this case it sounds like relaxing MITs code to accept when
clients do not send Channel Bindings to allow the context to be
established brings consistency not only across implementations but also
within the MIT code by simplifying away that condition.


Here I am going to try to summarize how I and Isaac think we should
change the semantics so that we can interoperate better.

Premise: Isaac was investigating on how to handle connecting to Windows
servers that implement a configuration flag called
LdapEnforceChannelBinding

This flag can be configured with 3 levels:

Level 0: CBs are completely disabled
Level 1: CBs are optional. Specifically clients that do not send
KERB_AP_OPTIONS_CBT can still connect with or withouth CBs, while
clients that send KERB_AP_OPTIONS_CBT are required to send matching
Channel Bindings.
Level 2: All clients must send Channel Bindings, without exceptions.

This applies only to the LDAP service as far as we know, but requires
us to try to allow these configurations in servers that are used to
emulate Windows AD (eg Samba).

With current MIT code we can only really implement
LdapEnforceChannelBinding levels 0 and 2. Level 0 when setting no CBs
in the acceptor, and level 2 when passing CBs, however as stated
multiple times over the years in previous conversations, this MIT krb5
behavior makes it hard to perform gradual conversions of the clients.

With current Heimdal, in contrast, it looks like we can only implement 
LdapEnforceChannelBinding levels 0 and 1. Level 0 when setting no CBs
in the acceptor, and level 1 when passing CBs, this means we do not
have a way to enforce CBs at all.

We'd like to propose that both MIT and Heimdal code converge in
behavior and agree in implementing the following behavior:

[ACCEPTOR SIDE]

1) When passing GSS_C_NO_CHANNEL_BINDINGS to gss_accept_sec_context()
then Channel Bindings are ignored (equivalent to level = 0)
2) When passing actual Channel Bindings to gss_accept_sec_context()
then Channel Bindings are checked only if the client sends non zero
CBs. (allows us to implement level = 1)
3) If the client sent CBs and we verified them set a new flag in
ret_flags that signify CBs were received and checked (this will allow
us to implement level = 2 behavior by failing the connection if the
flag is missing).

Optionally[A] support the presence of the KERB_AP_OPTIONS_CBT. If we do
this then the above point (2) above is split in two sub options:

2) When passing actual Channel Bindings to gss_accept_sec_context()
then:
2.1) Channel Bindings are checked only if the client sends non zero CBs
and KERB_AP_OPTIONS_CBT is not present.
2.2) Channel Bindings are enforced if the client provides the
KERB_AP_OPTIONS_CBT.

NOTE in 2.2 we propose that context establishment fails if CBs are not
provided, we do not rely on the application to check ret_flags in this
case.

Optionally[B] we add a krb5.conf flag like "require channel bindings"
that causes the gss_accept_sec_context() function to fail if CBs are
passed into it and the client does not send CBs (ie we do not rely on
the applications to check ret_flags, the context establishment fails
just like MIT code currently does).

Option B allows operators relying on current MIT behavior to retain it
by simply adding this option in krb5.conf and not having to worry to
change pre-existing applications in order to enforce CBs.


[INITIATOR SIDE]

Optionally [C] we add a krb5.conf flag like "require channel bindings"
that causes gss_init_sec_context() to emit the KERB_AP_OPTIONS_CBT.
The flag should always be emitted and will cause clients that have not
been updated to send CBs to fail against servers that have support for
interpreting KERB_AP_OPTIONS_CBT. This is useful for deployers to check
that all their client software has been properly updated before
switching the same flag on on the servers.


In closing,

Although Options B and C could use different config options we suggest
the exact same option to be used for both initiator and acceptor for
consistency of behavior and to reduce the number of knobs to dial for
admins. Applications that need special exceptions can always be
configured to point to a different custom krb5.conf file.

NOTE: "require channel bindings" defaults to False in our proposal.


We can say that Options A,B,C are in decreasing order of importance to
us, but I personally would like to see all three implemented at the
same time if at all possible.


HTH,
Simo.

-- 
Simo Sorce
RHEL Crypto Team
Red Hat, Inc






More information about the krbdev mailing list