Subject: [kitten] WGLC of draft-ietf-kitten-gss-loop-00

From: ⌘ Matt Miller <[email-masked]>
Date: Wed, 15 Oct 2014 10:42:56 -0600

This message begins the Working Group Last Call (WGLC) of "Structure
of the GSS Negotiation Loop" < draft-ietf-kitten-gss-loop-00 >.  WGLC
will end in two weeks, on October 29.  The draft is available at:

http://tools.ietf.org/html/draft-ietf-kitten-gss-loop-00

Please review the document and send comments to the Working Gorup
mailing list < kitten at itef.org > or the co-chairs < kitten-chairs
at tools.ietf.org > before the end of the WGLC.  Any and all comments
on the document are sought in order to access the strength of
consensus.  Even if you have read and commented on this or earlier
versions of the draft, please feel free to comment again.

As a reminder, comments can be anything from "this looks fine" to
"this is a horrible idea"; they can include suggestions for minor
editorial corrections to significant editorial changes.

- -- Your Kitten Chairs

---

From: Greg Hudson <[email-masked]>
Date: Thu, 16 Oct 2014 16:03:27 -0400

I am confused about the paragraph beginning "Extra security context
tokens can also be emitted if...".  This is not a scenario I'm familiar
with.

On that note, some (most?) protocols do not have a means of transmitting
extra context tokens; I guess implementations of those protocols don't
have to worry about receiving them, so won't need guidance.

I am not convinced that "These resources may be non-local to the current
process" is a realistic concern for GSS applications.

The example code includes <assert.h> but doesn't use any asserts.

GSS_C_EMPTY_BUFFER initializers might be more correct and elegant than
memsets.

Here are a few editorial comments:

* I found this a little confusing: "For the first call to each routine
in the loop, the major status code from the previous call to
GSS_Init_sec_context() or GSS_Accept_sec_context() should be taken as
GSS_S_CONTINUE_NEEDED."  I believe this is aimed at the
sanity-checking/input validation sections, which use text like "for
example, if the initiator's previous call to GSS_Init_sec_context()
returned GSS_S_COMPLETE."  But I don't think it is really needed.

* The example code contains "must not directly cause termination of the
process (i.e., by errx())" in two places.  I would suggest removing the
parentheticals.  As it stands, I have to wonder if "i.e." is being used
to mean "for example," which is incorrect.

* "Upon completion of security context negotiation, the initiator must
verify that the values of the [...] flags from the last call to
GSS_Init_sec_context() corresponding to the requested flags."  This is
not grammatically correct.

* "avaialble" is a typo.

* The document borders on overuse of parentheticals--something I have to
fight in my own writing.  Some of the parentheticals may be too
important to be included as parentheticals; some others could probably
be omitted.

---

From: Benjamin Kaduk <[email-masked]>
Date: Fri, 24 Oct 2014 15:37:48 -0400 (EDT)

Sorry for the slow response.
(Everyone else, note that there's less than a week left in the WGLC.)

> tokens can also be emitted if...".  This is not a scenario I'm familiar

This came from my reading of the last paragraph of section 1.2.1.2 of RFC
2743, where the normative requirement is conditional on the requested
flags input to GSS_Init_sec_context().  Looking at it again, I see an
alternate reading which is normative on mechanism specifications to
disallow single-token context establishment when optional features are
present.  So maybe this is not an actual scenario.  In any case, I agree
that this is not a something of practical concern.

> have to worry about receiving them, so won't need guidance.

Right.

We highly discourage the use of deletion tokens, which is the only place
where process_context_token is likely to arise, so applications basically
don't need to care about it.

> process" is a realistic concern for GSS applications.

RFC 2743 does speculate about """using interprocess tokens as a means to
reference local interprocess communication facilities (protected by other
means) rather than storing the context data directly within the tokens."""
(for export_sec_context tokens), admitting the possibility of resources
attached to GSS objects which are non-local to the current process.
I don't know of any implementations using that freedom, but it does seem
pretty clear as something permitted by the spec.

> The example code includes <assert.h> but doesn't use any asserts.

My local version of send_token and receive_token have asserts in them, but
I should remove the header from the published document, thanks.

> GSS_C_EMPTY_BUFFER initializers might be more correct and elegant than

That's a good point; fixed in my local tree.  The declaration spills out
to one variable per line due to the line length limitations of the RFC
format, but it's still a net shrinkage.

> returned GSS_S_COMPLETE."  But I don't think it is really needed.

There is text in 2.7 about "the previous call to GSS_Init_sec_context()
returned GSS_S_CONTINUE_NEEDED" for which the text you find confusing
would be applicable.  I think previous revisions of this draft had more
such places.

Having looked again, I agree that it is not really needed; I've removed it
from my working copy.

> to mean "for example," which is incorrect.

Removing the parentheticals seems fine, I'll do that.
(And yes, the "i.e." are wrong.)

> not grammatically correct.

s/corresponding/correspond/ is the big braino on my part, but I also added
a "the" before "security context negotiation" for kicks.

> important to be included as parentheticals; some others could probably

I went through and changed several of them (mostly just converting to
comma-offset phrases).  I don't think I removed any, though...
There was one spot where I had to reorder things and reword a bit so that
it still makes sense (about using the context before negotiation is
complete).

The updates I've made are visible on my github repo,
https://github.com/kaduk/gssdoc/commits/master .

-Ben

---

From: Nico Williams <[email-masked]>
Date: Mon, 27 Oct 2014 15:39:33 -0500

> http://tools.ietf.org/html/draft-ietf-kitten-gss-loop-00

Comments:

 - In some places you add non-RFC2119 language to what RFC2743 says
   (e.g., which arguments to GSS_Init/Accept_sec_context() must stay the
   same during an exchange).  Should we be updating RFC2743 here, and
   just aim for the Standards track (and use RFC2119 language)?

   (There is the risk that this I-D will have mistakes that we don't
   want to make normative, but those would be errata.)

 - "Such a security context allows for mutual authentication of the
   two..."

   Strictly speaking it allows for authentication of either party to the
   other.  Speaking of "mutual authentication" here is probably not a
   good idea: there are two very different meanings of "mutual
   authentication"; readers are bound to be confused.

 - s/confidential or integrity-protected/confidentiality and\/or integrity-protected/

 - Add a paragraph break just before "The number of tokens which must be
   exchanged..."

 - Add "Security context tokens are exchanged synchronously, one at a
   time; the initiator sends the initial context token." just before
   that sentence.

   Might as well also point out that the only asynchronously exchanged
   security context tokens are:

    - error tokens sent by one side to another than had just returned
      GSS_S_COMPLETE (and an output token, the one that elicits the
      error)

    - security context deletion tokens (which are obsoleted and,
      therefore, best not mentioned)

   Mentioning these very basic aspects of GSS context token exchanges
   early on should be very useful to the reader.  It's quite handy for
   me to always keep this in mind when coding a GSS security context
   token exchange loop; it should be for others too, I think.

 - We should say, in the intro, something about the expectation that the
   application will add such things as:

    - authentication + authorization success/failure messages
    - token framing

 - ...described in a single specification...

   Er, do we want application protocols using GSS to reference this
   document normatively?  If so this should aim to be on the Standards
   track.  Or perhaps we want them to reference RFC2743 _and_ this one?

 - s/scattered in many different places/scattered about/.

 - Section 2, last sentence/para: I'm not sure that this is needed at
   all.  Where you discuss GSS_Init/Accept_sec_context() you generally
   talk about the first call anyways (e.g., section 2.4, first
   sentence).

 - Section 2.1.  Perhaps initiators wanting anonymity should also
   GSS_Acquire_cred() for a desired_name of GSS_C_NT_ANONYMOUS name
   type.  This was never clear in RFC2743.

   Alternatively, having a credential handle for an anonymous name, must
   anon_req_flag be set?

   Consider an API that takes a credential handle from a caller and then
   uses it to initiate security context tokens.  If the implementation
   of the API needs to inquire the credential to see if it's for a
   GSS_C_NT_ANONYMOUS desired_name... that could get annoying.

   My theory is that anon_req_flag is for use when a non-anonymous
   [e.g., perhaps a default] credential handle is used by the caller.
   Otherwise, if the credential handle is for an anon name then
   anon_req_flag is not / should not need to be set!

   Conversely, an API that wants anonymity but doesn't know if the given
   credential handle would obtain it... MUST set anon_req_flag.

 - "If the major status code is GSS_S_CONTINUE_NEEDED and the
   output_token is empty, ..."

   Are there examples of such implementations?

   Are there bindings other than C where this could not be handled as
   proposed?

 - s/if an appropriate channel/if an appropriate application-protocol
   message (or transport operation, e.g., TCP close)/

 - Section 2.3, what is a "synchronous TCP channel"?

 - Section 2.3, the key thing to note is that GSS tokens are NOT
   self-delimiting.  Therefore the application must always provide
   framing.

   (Some of us want a req_flag/ret_flag for requesting self-framing by
   the mechanism.  It'd be quite handy for some mechanisms and
   protocols.  E.g., the old Globus SSL mechanism, which *is* SSL/TLS on
   the wire when the tokens are sent with no additional framing.)

 - Section 2.3, "the application protocol must provide some means by
   which the GSS context tokens can be identified" -- in particular:
   their _length_ (and start location in a stream/message) must be
   identified.

 - Section 2.3, perhaps there should be a list of things the application
   protocol must provide:

    - per-message token framing
    - security context token framing
    - optional authentication/authorization status message

      (optional because for some protocols GSS security context
      establishment is always sufficient to proceed, or because when it
      isn't the acceptor can simply withold the last security context
      token [though I'd not recommend that])

    - Error handling is completely optional.  Applications can send or
      not send error tokens.  Applications can "close the connection"
      when the transport is connection-oriented.  Applications can even
      stop responding to peers.

   There's probably no need to discuss security context deletion tokens
   (since they are obsolete).

   Framing is needed even when there is no multiplexing.

   A list like this seems likely to be easier to read than prose.

   Most of this is applicable to both, the initiator and the acceptor,
   therefore a new section slotted before the current 2.2 or 2.3, with
   the above content (wordsmithed) would be convenient.

 - Section 2.3, first para, remove the last sentence.  It's difficult to
   parse and adds little (especially if a list of requirements as above
   is provided).

 - Section 2.4, second para: this applies to the initiator and acceptor
   equally.

   Can we refactor this out?  After all, the GSS_Step_sec_context()
   extension would be all about doing just that.  Might as well do it
   here in the prose too.

 - Section 2.6, last para is redundant (repeats instructions given
   earlier).

 - "...should assume that the [peer's] state is invalid..." is an odd
   construction.  Is there a difference between "time out" and "the
   peer's state is invalid"?

 - Section 2.8, should there be a maximum number of loop iterations?

   No!  There shouldn't be, at least not a constant one.  If a maximum
   is used, it should be configurable.

 - Section 3, don't list the req_flags that must remain fixed.  Say that
   all of them must.  Remember, we can (and probably will) add new
   flags.  Alternatively say "and any future new req_flags".

 - Section 3, last para, both, the initiator and acceptor receive these
   (and future) ret_flags.  Might as well merge this paragraph with the
   text from two paragraphs earlier.  (See above comment about
   refactoring common parts.)

 - Section 3.1, first para, last sentence: this is a bit of an
   exageration.  Applications should do whatever is appropriate as to
   prot_ready per-message tokens' lack of replay protection.

   While we're at it, the intention in RFC2743 was that protection
   services can't be counted as applied to prot_ready per-message tokens
   until after the security context is fully established.  Which means
   that prot_ready per-message tokens:

    - don't get effective confidentiality and/or integrity protection
      until full security context establishment;

    - never get replay detection services, not at the time that they are
      consumed (since this would potentially require a replay cache on
      acceptors and possibly even initiators for some mechs, and to my
      knowledge no implementations use a replay cache for prot_ready
      per-message tokens), and not at some point later when the security
      context is fully establised (since it'd be too late then to report
      errors about specific already-consumed per-message tokens).

 - Section 3.1, last para.  See above.

 - Section 3.2, page 9, second para (I think that's the third para),
   error context tokens can arise in more common cases:

    - initiator sent the last token and was GSS_S_COMPLETE but the
      acceptor rejects that token (e.g., Kerberos w/o mutual auth, with
      any of many common Kerberos errors, and even application
      authorization errors)

      A three-message Kerberos exchange (e.g., see
      draft-williams-kitten-krb5-extra-rt) would also run into this.

    - acceptor sent the last token and was GSS_S_COMPETE but the
      initiator rejects that token.

   Calling these cases "rare" is asking for trouble.

   The thing that is rare is the "optional to implement" thing, and a)
   that never happens now, b) it's no different than any other error
   that could happen as mentioned above.  (Once
   upon a time we had export restrictions on crypto, and as a result
   some implementations shipped an RFC1964 implementation without
   confidentiality protection, and this could cause an error token to be
   sent back when the initiator hadn't requested mutual auth, this is
   true.  Well, maybe it didn't even produce an error token -- this was
   fifteen years ago, with code long since obsolete, and I doubt anyone
   will check the specifics now.)

 - Section 3.2, last para: the best advice to give as to asynchronous
   (i.e., unexpected) security context tokens, is that the application
   must always act as though they terminate the security context, even
   when they don't.  We should deprecate the optional-to-implement
   thing that led you to write this.

 - Section 4:

    - There is no need to use GSS_ERROR() to handle major status codes
      from gss_init/accept_sec_context() because the is never a success
      or continue needed case with other supplemental codes or any error
      codes.  Always use equality comparison for gss_init/
      accept_sec_context() major status codes to check for
      complete/continue_needed status.

      Moreover, it's best to discourage use of GSS_ERROR().  Its use
      with gss_unwrap() major status codes has led to a number of
      security vulnerabilities in protocoles that were trying to make an
      octet stream.

      GSS_ERROR() is only ever of use to applications using an
      unreliable datagram transport, or to applications that have no
      need for replay and/or out-of-sequence detection services from the
      GSS-API (e.g., ONC RPC doesn't, even when running over TCP).

    - The sample code doesn't do what the prose says as to empty output
      tokens when one is expected...

    - The while loop should probably be a do while loop.

    - There is no need to memset(&name_buf, 0, sizeof(name_buf));

    - memset() to zero doesn't work on architectures where the
      zero-valued pointer isn't the all-zero bit pattern.

    - The major status of gss_import_name() should be checked.

    - Why not mention authorization (use a stub function) and
      application-level status message in do_acceptor()?

    - This:

        } else {
            /* This situation is forbidden by RFC 2743.  Bail out. */
            warnx("major not complete or continue but not error\n");
            goto cleanup;
        }

      would be an internal error, not behavior forbidden by RFC2743,
      because you break out of the loop in this case before ever getting
      here.  You should either assert() or ignore this.

 - What about mentioning the possible need to check -on the acceptor
   side- the name of the acceptor as used by the initiator?  That's a
   gss_inquire_context() call to get the name of the acceptor, then a
   gss_compare_name() function call (or any of the other methods of
   comparing names given in RFC2743).

Nico
--

---

From: Greg Hudson <[email-masked]>
Date: Fri, 31 Oct 2014 14:39:18 -0400

>       GSS_S_COMPLETE (and an output token, the one that elicits the

Does this really happen in practice?  On the mech implementation side,
the krb5 mech in MIT krb5 only generates an error token in the acceptor
if the initiator requested mutual auth, and never generates an error
token in the initiator.  On the application side, I have never heard of
an application containing a call to gss_process_context_token.

If this is a facility that we don't seem to require or use in the real
world, then my preference is that we not talk about it in the gss-loop
document.

---

From: Nico Williams <[email-masked]>
Date: Fri, 31 Oct 2014 14:13:47 -0500

> Does this really happen in practice?  On the mech implementation side,

It can.  It will generally only happen in the case of exchanges with
an odd number of tokens in the successful case (e.g., Kerberos w/o
mutual auth).

> an application containing a call to gss_process_context_token.

I believe that's a mistake.  Not requesting mutual auth != "don't ever
send me an extra token".  Errors are errors.

> world, then my preference is that we not talk about it in the gss-loop

If we progress our extra tokens/round trips I-D then it may well matter.

It doesn't really cost much, and correctness for this makes a big difference.

Some SSHv2 w/ GSS implementations, for example, don't send error
tokens, which makes diagnosing failures rather difficult.

Error tokens may be optional, but they are quite handy.

Nico
--

---

From: Nico Williams <[email-masked]>
Date: Fri, 31 Oct 2014 14:42:13 -0500

> If we progress our extra tokens/round trips I-D then it may well matter.

Speaking of which: I'd like to request adoption of that as a WG work item.

Nico
--

---

From: Benjamin Kaduk <[email-masked]>
Date: Fri, 31 Oct 2014 17:58:05 -0400 (EDT)

Hi Nico,

Thanks for the review.

I'll trim the minor items that I took without change, so this email
doesn't get too long.

>    want to make normative, but those would be errata.)

I think we had discussed the question of whether to make this document
standards-track earlier in its lifecycle, and decided that there were not
significant changes from 2743 that we would want to make, so it wasn't
worth adding the extra overhead of going standards-track.  (This may have
been the only such change, though I can't seem to findi where we listed
them out...)

>    authentication"; readers are bound to be confused.

Okay, I went with "allows for each party to authenticate the other" in my
working copy.

>  - s/confidential or integrity-protected/confidentiality and\/or integrity-protected/

You can't get confidentiality without integrity protection in the GSS-API,
but I'll take that change.

>    time; the initiator sends the initial context token." just before

Given the following, I went with "During context establishment, security
context tokens are exchanged synchronously, one at a time; the initiator
sends the first context token." ...

>    token exchange loop; it should be for others too, I think.

... but I'll hold off on this until we resolve Greg's comment.

>     - authentication + authorization success/failure messages

I'm not entirely convinced about this.  We don't even necessarily know
that there is a user to see such messages.

>     - token framing

I would have thought this was implicit, but let's see what we can do.
        [...] an error condition.  The GSS-API specifies the format and
        encoding of the context tokens themselves, but the application
        protocol must specify the necessary framing for the application
        to determine what octet strings constitute GSS security context
        tokens and pass them into the GSS-API implementation as
        appropriate.

>    track.  Or perhaps we want them to reference RFC2743 _and_ this one?

We want them to reference 2743 and this one; see the last paragraph of the
introduction.

>  - s/scattered in many different places/scattered about/.

"scattered about" feels too informal to me, so I didn't take this.

>    talk about the first call anyways (e.g., section 2.4, first

Greg thought so, too (it's already gone in my git repo).

>    type.  This was never clear in RFC2743.

I don't think there's sufficient precedent for this document to mention
that possibility.  (My reading of 2743 is that you acquire credentials as
yourself, but can sometimes use them anonymously.)

>    anon_req_flag is not / should not need to be set!

That seems to be the only sensible reading, to me.  I still don't think
that this document needs to cover it.

Right.

>    Are there examples of such implementations?

IIRC this happens for Windows GSS-NTLM implementations, or something of
that nature.

>    Are there bindings other than C where this could not be handled as

"I don't know of any."  But this is trying to prove a negative, so there
doesn't seem to be a whole lot to say.  In an ideal world, there would not
be such mechanisms; IIRC RFC 2743 forbids this situation.  But, there is
deployed code that does it, and the behavior I describe seems more
friendly than just aborting the negotiation (which is what a previous
version did).

>    message (or transport operation, e.g., TCP close)/

I want to stick with "channel", here (that word is used a lot in the
following section), but will add "application-protocol" for clarity.
(This same text occurs in the GSS_Accept_sec_context section; I'll change
both places.)

>  - Section 2.3, what is a "synchronous TCP channel"?

A TCP connection that doesn't carry any other application's traffic.
(I'm not tied to this text at all, and it evolved in a kind of odd way;
please feel free to suggest alternate text.)

>    self-delimiting.  Therefore the application must always provide

This seems to be covered again below.

>    the wire when the tokens are sent with no additional framing.)

Maybe, but such a flag doesn't exist yet, to I can't talk about it :)

>    their _length_ (and start location in a stream/message) must be

I can add "(e.g., length and start location)"; it's unclear if you want
more than that.

>    the above content (wordsmithed) would be convenient.

I'm not specifically opposed to a section covering the requirements for an
application protocol which will be passing GSS structures as part of its
protocol, but it's not clear to me that it brings a noticable advantage in
this document.  We don't cover message tokens at all, just context
establishment, and everything else in your list is optional.

Such a list would be a useful resource to offer to application protocol
designers, I'm just not sure that this is the best place for it.

>    parse and adds little (especially if a list of requirements as above

I won't dispute that it's difficult to parse, but since I'm reluctant to
add the list of requirements, I want to give it some replacement.  How
about:
          The application protocol may also include a facility for
          indicating errors from one party to the other, which can be
          used to convey errors resulting from GSS-API calls, when
          appropriate.  Note that GSS major and minor status codes
          are specified by language bindings, not the abstract API,
          so may not be directly interpretable by the other peer.

>    extension would be all about doing just that.  Might as well do it

We could, but I'm not sure it would help the document as a whole.
I like the current flow, which describes the flow from the initiator to
the acceptor and back, with a neat loop structure.  Yes, there is
duplication, but that may be the price for clarity and readability.

>  - Section 2.6, last para is redundant (repeats instructions given

Redendancy may be okay in this document (per previous).

>    peer's state is invalid"?

Not really.  Do you think the "time out" language is preferrable in a
document of this nature?

>    flags.  Alternatively say "and any future new req_flags".

The flags are separate arguments in the abstract API, so I feel like they
should be listed explicitly.  "Any additional request flags that may be
added" is a good point, though; thanks.

>    refactoring common parts.)

(See above comment about redundancy.)
I will add the note about potential future extensions.

>  - Section 3.1, last para.  See above.

It's not really clear what (if any) changes you want to the document text.
I replaced the last sentence of the first paragraph:
          Applications using per-message operations
          on a partially complete security context should take into
          consideration the fact that replay protection is not avaiable
          from the GSS-API for those messages, and take the appropriate
          protective measures.

>    will check the specifics now.)

Our IRC discussions have mostly convinced me that the "optional to
implement" case was a misreading of 2743 by me; that text has already been
stricken.

Regarding the non-rarity of error context tokens, I'll leave that to the
other fork of the thread for now (that's coming in as I write this
message).

>    thing that led you to write this.

Well, we need to document what exists, not what we want to exist.

Why do you think that applications should treat all "extra" context toksn
as terminating the context in the absense of a signal from the GSS-API
that that is the case?

>       codes.  Always use equality comparison for gss_init/

Are you sure?  Where does the spec say that must be the case?

>       security vulnerabilities in protocoles that were trying to make an

This document does not cover GSS_Wrap() or friends.  We should give better
guidance for their use, but this is not the place.

>       tokens when one is expected...

The check I see is
        if ((major & GSS_S_CONTINUE_NEEDED) ||
            output_token.length > 0) {
which I thought matched up.  As alluded to previously, though, the
behavior specified by the prose has changed over the evolution of this
document, and it's possible the code missed a spot catching up.  Can you
be more specific about which behavior is inconsistent?

>     - The while loop should probably be a do while loop.

Maybe.  We probably shouldn't get into debates about purely stylistic
issues, though...

>     - There is no need to memset(&name_buf, 0, sizeof(name_buf));

It zeros out the padding, but hmm, okay, I guess no one should need to
care about that.  (Actually, Greg already told me to use
GSS_C_EMPTY_BUFFER as an initializer instead.  I guess I'll keep that so
things look consistent at the top of the function.)

>     - The major status of gss_import_name() should be checked.

Oops, I do that in my local version (preprocessor conditional) for testing
but not the generic one for the spec.

>       application-level status message in do_acceptor()?

I believe there were previous discussions around this, and Greg convinced
me that such checks fit more naturally outside of do_acceptor(), which
should just be about establishing the context.  This may be another case
where guidance on the use of the GSS-API is lacking, but this document is
not the appropriate place to rectify that.

The closest we get is to pass &client_name to gss_accept_sec_context(),
which we then proceed to not do anything with.

>       here.  You should either assert() or ignore this.

Hmm?  I think this case covers at least a major status code with
no fatal error codes set but a per-message-token informatory status code
set, which is indeed forbidden by 2743.

>    comparing names given in RFC2743).

"What is the possible need for that check?"

Changes are visible at https://github.com/kaduk/gssdoc/commits/master .

-Ben

---

From: Nico Williams <[email-masked]>
Date: Fri, 31 Oct 2014 18:13:23 -0500

> but I'll take that change.

Maybe "and/or" doesn't make it clear, but I thought it did, that you
always get the latter.  (You get both, or just the latter.)

> ... but I'll hold off on this until we resolve Greg's comment.

I'm very interested in the extra tokens I-D.  One way or another I'll
see it to publication.  If the WG doesn't take it, then I'll follow the
individual submission path.  PKU2U is three tokens.  The Globus SSL
mechanism is three tokens.  Basically, there exist, and soon more will,
odd-number-of-security-context-token mechanisms.

Since your I-D is Informational, leaving out some information is not
necessarily bad, but it'd be terrible if implementors used this as a
guide and then had their implementations not work well with such
mechanisms.

> that there is a user to see such messages.

The message could be a boolean (success/fail), but it's necessary in
many (but not all) applications.

> I would have thought this was implicit, but let's see what we can do.

It is as soon as you realize that all these functions want a buffer with
a length.

If we were to add a self-framing option we'd probably have to add a
function to extract token lengths from bytes received so far, or perhaps
we'd need functions with bytes-left-unused and more-bytes-needed
outputs.  So, yeah, it's implicit.

> yourself, but can sometimes use them anonymously.)

Since there's an anonymous name-type, it makes sense to be able to
acquire a credential handle for anonymous desired_names.  There's no
stricture against it.  It'd be convenient too.  Anyways, ignore this for
now.

> that this document needs to cover it.

Sure.

> IIRC this happens for Windows GSS-NTLM implementations, or something of

Oh right, NTLM.  Thanks for the reminder.

> please feel free to suggest alternate text.)

That's very non-obvious.  You want an antonym for "multiplexed", I
think.

> I can add "(e.g., length and start location)"; it's unclear if you want

That works.

> >    [...]

For me it's easier to read something like that given that most of the
list's elements can be a single line each.  Distilling the same from
lengthy prose is harder.

It's just a matter of style.

> designers, I'm just not sure that this is the best place for it.

True.  But we'll want application protocol specifications to reference
this, so it might as well be useful to them too (or their readers: as a
source of explanation).

>           so may not be directly interpretable by the other peer.

I have a lot of experience with this from deploying SSHv2 w/ GSS more
than a dozen years ago: anything other than sending a GSS error token is
TERRIBLE.

First, the minor status is utterly useless, especially now that some
implementations allocate those dynamically.

Second, the major status is to coarse to be of much use.

Third, the major and minor status display strings won't be localized to
the other peer's locale.

Fourth, the major and minor status codes and display strings will not
necessarily be as informational to the peer as the GSS error token.
(They weren't, back then, for a variety of common errors.)

Sending major & minor status codes/messages instead of an error token is
only to be done when there's an error but no error token (because the
mechanism implementation doesn't produce them, but should have, say).

The SSHv2 w/ GSS implementation in question did not even do that at
first (or maybe it sent an error message, but not the token, and the
client did nothing with the error message).  Users merely saw
"Connection closed by <IP address>" when something went wrong with
Kerberos.  It was _awful_.  Please, please, let's not perpetuate these
mistakes -- that's what they are, mistakes, ones that punish the users.

ASIDE: Years ago Sam Hartman insisted that error tokens should be
       optional, that local policy should be allowed to say "no error
       tokens" on account of wanting to limit information leaks through
       error tokens.  That could be OK as an application policy, but if
       it's a mechanism-specific configuration, then the application
       would be violating that policy if it then sent its own error
       message with the major & minor status codes & messages!  Anyways,
       when an error occurs the only choices are: a) send it, b) send a
       censored version, c) shut the door (close the connection, or
       whatever is appropriate for the given transport), d) stop talking
       and let the peer timeout.  (b) seems like a task for the
       mechanism, not the application, unless the application distills
       it to just a boolean (success/failure).  For the general case the
       clearly best advice is to just send the bloody error token when
       there is one.

> We could, but I'm not sure it would help the document as a whole.

You might be right.  I'd have to see the refactored text first.

> Not really.  Do you think the "time out" language is preferrable in a

 "...should assume that the [peer's] state is invalid..." just strikes
 me as really weird.  Developers understand "timeout".

> added" is a good point, though; thanks.

You can list them if you like, but please say that all request flags
must be kept the same throughout.

>           from the GSS-API for those messages, and take the appropriate

You also need to say that they shouldn't send data requiring
confidentiality protection (since at the time the per-message token is
sent the peer may not yet be authenticated).

> >    [...]

Thanks.

> other fork of the thread for now (that's coming in as I write this

It's natural that they seem rare to a Kerberos implementor.  It'd be
rather bad -and ironic- if developers following this I-D produced apps
that don't work well with mechanisms that produce an odd number of
context tokens, or future Kerberos extensions that do that.

> Well, we need to document what exists, not what we want to exist.

The API exists.  That's RFC2743.  You're focusing on the mechanisms that
you use.  There are other mechanisms.  And I intend to extend Kerberos
to get this same behavior.  Dismissing the others as not existing is not
appropriate.

> Why do you think that applications should treat all "extra" context
> toksn as terminating the context in the absense of a signal from the
> GSS-API that that is the case?

The GSS-API as specified today can only produce asynchronous (to one
peer) context tokens as a result of an error while processing what
should have been the last context token, or as a result of calling the
obsoleted GSS_Delete_sec_context().  As there are no recoverable context
establishment errors, the first case clearly results in the context not
becoming established on one side, and the peer gets no benefit from
ignoring this (what's it gonna do, send per-message tokens anyways to
the unwilling peer?).  The second case clearly results in the security
context no longer being usable either.

Therefore both cases result in the security context no longer being
established.

See RFC2743, section 2.2.4.

It's true that we could someday add a re-key token, and we'd extend
GSS_Process_context_token() to handle it.  But unfortunately when
GSS_Process_context_token() returns GSS_S_COMPLETE the security context
must be deleted -- see RFC2743, section 1, page 5, last paragraph:

   If a context_token is transferred, the client passes the
   context_token to GSS_Process_context_token(), which returns
   GSS_S_COMPLETE status after deleting context-level information at the
   client system.

Section 2.2.4 does not repeat this.  In the C bindings
gss_process_context_token() does not take a gss_ctx_id_t * argument, so
it can't quite delete the context.

I think we could simply agree that RFC2743 is ambiguous as to this and
so say that the application must inquire the security context after
processing an unexpected/async context token -- if GSS_Inquire_context()
function fails with GSS_S_NO_CONTEXT, then the token was an error or
context deletion token.

It's also the case that both RFCs are ambiguous as to how the error
information from an error token is to be indicated to the application.
I think the only reasonable thing to do is for
GSS_Process_context_token() to return the intended error information.
The minor status code can be used to disambiguate local errors (arising
from processing this token) from error information in the token.

Sorry that got long.

> Are you sure?  Where does the spec say that must be the case?

I'm dead certain.  GSS_Init/Accept_sec_context() never return
GSS_S_COMPLETE with supplementary status codes other than
GSS_S_CONTINUE_NEEDED.

> guidance for their use, but this is not the place.

Sure.  Though I've seen this security bug half a dozen times, committed
independently by roughly that many authors.  That's a problem.  This
macro should be deprecated.  This I-D could be the PSA that alerts
developers as to this (e.g., in the security considerations section).

> be more specific about which behavior is inconsistent?

Excuse me, I'd misread that.

> Maybe.  We probably shouldn't get into debates about purely stylistic

It's stylistic, yes, that loops that must run at least once be do-while
loops.  I'm surprised to see a difference of opinion as to that though!

:)

> things look consistent at the top of the function.)

Excellent.

> not the appropriate place to rectify that.

This is asking for a security vulnerability.  We must teach proper use
of the API.

> which we then proceed to not do anything with.

Just add a call to a stub function.

> set, which is indeed forbidden by 2743.

Right, which answers your question about as to GSS_ERROR().  Don't use
GSS_ERROR().  Instead treat any GSS_S_COMPLETE-with-supplementary-
status-codes-other-than-GSS_S_CONTINUE_NEEDED as errors.  It's easier,
it's less code, easier to explain.

> "What is the possible need for that check?"

Consider an application with keys for many principals in its keytab...

Such an application might want to accept contexts for any host-based
service principal with a given service but any host, or just some hosts.
It's unlikely that it'd want to accept contexts for other services, and
it could lead to a security vulnerability to do so.

But at the same time, if the application wants to be able to accept
contexts for more than one acceptor principal then it has to use
GSS_C_NO_CREDENTIAL, therefore it could accept for any and all services
for which it has keys in its keytab.

It's unfortunate that the GSS-API doesn't have a simpler way to express
more than one acceptor principal.

There's two things that could be said (in the I-D) about this: a)
limiting credentials availability is required but out of scope, or b)
inquire the context, and check the acceptor's name against local policy.

> Changes are visible at https://github.com/kaduk/gssdoc/commits/master .

Thanks, I'll look later.

Nico
--

---

From: Greg Hudson <[email-masked]>
Date: Fri, 31 Oct 2014 21:23:11 -0400

> odd-number-of-security-context-token mechanisms.

I assume this is relevant because you expect failures to commonly result
when the acceptor processes the third message, rather than the first?

> guide and then had their implementations not work well with such

Terrible or not, I believe that is the situation we're in today for
applications, mechanisms, and perhaps even protocols (in that protocols
may not have a way to transport context tokens except when the other
endpoint expects one as part of context establishment).

I am dubious that this document is a good vehicle to change that
situation, as we'll be telling people to do something more complex than
anyone actually does.  But I will drop my objection if we can iron out
the other details of calling gss_process_context_token.

[From another branch of the thread:]
> send me an extra token".  Errors are errors.

I am kind of morbidly curious what would happen if the krb5
gss_accept_sec_context started generating error tokens without the
initiator requesting mutual auth.  I feel like a lot of protocols and
their implementations just assume that under normal non-malicious
operation, the acceptor and initiator will stop generating tokens at the
same time as the other endpoint stops expecting them, and will throw a
less-than-graceful failure if that doesn't happen.

> (They weren't, back then, for a variety of common errors.)

I am not sure when the error token is more informational than the
display string.  But I would worry about it being too
informational--conveying information about server filesystem paths, for
instance.  And the potential for incorrect localization is definitely an
issue.  So I agree that an application-level error cannot reasonably
convey any more information about a failure than the major code.

>>>    when they don't. [...]

> The API exists.  That's RFC2743.

The API exists, but RFC 2743 section 2.2.4 does not appear to specify
that the context is always terminated by the call.

>    GSS_S_COMPLETE status after deleting context-level information at the

This paragraph appears as part of an example scenario involving a call
to gss_delete_sec_context (see the previous paragraph).  I do not read
it as specifying the result of all successful calls to
GSS_Process_context_token.

> I think we could simply agree that RFC2743 is ambiguous as to this

I don't think there's really any ambiguity; it just doesn't appear to be
specified under the assumption that the context is always terminated.

> GSS_Process_context_token() to return the intended error information.

I think that would be a clear violation of the spec, which lists four
possible major results and states that GSS_S_FAILURE indicates a failure
to process the context token.

We could perhaps reasonably amend the spec if we believe (as I do) that
no one is using gss_process_context_token.  Such amendments aren't
currently in scope for the gss-loop document, however.

> GSS_S_COMPLETE with supplementary status codes other than

I agree that this is true in practice, but I'm not sure that it's
clearly true from the spec.  Of the currently specified supplementary
bits, the four that aren't GSS_S_CONTINUE_NEEDED only apply to
per-message tokens, but I don't see any specific guarantees about the
return values of gss_accept_sec_context or gss_init_sec_context and
supplementary bits.

> it's less code, easier to explain.

... that said, I wouldn't object to doing this in the gss-loop document,
as it's probably what I would do.  I don't think we would ever try to
specify a new supplementary bit applying to context tokens, as it would
break everybody's code.

> it could lead to a security vulnerability to do so.

It seems like you would need mechanism-specific knowledge to enforce
this using gss_inquire_context.  You suggested using gss_compare_name,
but what would you compare against?

> more than one acceptor principal.

Possibly relevant: In MIT krb5 1.10 and later, you can import a
hostbased name like "host" (no @hostname part), acquire an acceptor cred
for it, and get the desired behavior.  Against older versions or
Heimdal, such a name will behave like "host@<gethostbyname>", which
might or might not be acceptable fallback behavior.

---

From: Nico Williams <[email-masked]>
Date: Sat, 1 Nov 2014 01:07:58 -0500

> when the acceptor processes the third message, rather than the first?

No.  When errors occur the people suffering them need to be able to
diagnose them.

It doesn't matter how rare the error is.  Indeed, the rarer it is, the
more obnoxious the lack of diagnostics information.

> Terrible or not, I believe that is the situation we're in today for

If we're not out to improve the state of the world, then what are we
doing.

> endpoint expects one as part of context establishment).

SSHv2 w/ GSS can do it.  Damn it, I've implemented it.

> the other details of calling gss_process_context_token.

I'm not asking that you update RFC2743.  I'm asking that this I-D not
create an excuse for getting something wrong that the normative
references make plain is wrong.

> gss_accept_sec_context started generating error tokens without the

We're talking about applications here, not the mechanism.  Even if we
never make Kerberos w/o mutual produce an error token, that does not
mean that Kerberos w/ replay cache avoidance shouldn't.

> display string.  But I would worry about it being too

For one thing: it gets localized properly.

I don't recall the details from 2001 with enough clarity, but the
KRB-ERROR resulted in clearer error messages on the client side than
merely sending the major and minor status strings.

You could search the list archives though, I might have posted about it
then or some years later when the issue was discussed (I forget what
context; maybe Sam remembers).

> instance.  And the potential for incorrect localization is definitely an

That's certainly not true of KRB-ERROR!

Ironically, the strings produced by GSS_Display_status() on one side are
intended for consumption on _that_ side, not the other.  Sending those
strings is much more likely to reveal too much information than is
sending the error token.

The best censor of error messages is the producer.  In this case it's
the mechanism.

> that the context is always terminated by the call.

I've quoted and referenced text in the two relevant RFCs that leaves no
doubt as to what the result of an asynchronous context token is.  It can
only be one of two things: a context deletion token, or an error token.

If you think there is a third case, please demonstrate it.

If you think we could add a third case, please explain how that would
mean that applications shouldn't send or consume an error token in the
meantime.

> specified under the assumption that the context is always terminated.

There are ambiguities.  For example, the two RFCs fail to discuss how
the error information from an asynchronous error token is conveyed --
they only say that it is to be processed with
GSS_Process_context_token().  But it's clearly possible to convey that
information, and so there's only one ambiguity as to that: failures in
processing the error token itself, and distinguishing these from the
error conveyed by the token is easy (see below).

> to process the context token.

There is no conceivable way in which returning other error codes here
could break backwards-compatibility, but if there was, the obvious thing
to do is to encode the token's error information in the minor status.

> currently in scope for the gss-loop document, however.

But this I-D can still say what RFC2 2743 and 2744 say to do: send the
token, and process it.

> return values of gss_accept_sec_context or gss_init_sec_context and

The "informatory"/"suplementary" errors are that, so that they don't
modify the success conveyed by GSS_S_COMPLETE.  But if any such other
than GSS_S_CONTINUE_NEEDED had been meaningful for these two functions
-- or any others for which GSS_S_COMPLETE is listed w/o mention of
supplemental status codes -- then surely they would have been mentioned,
or else we must conclude that RFCs 2743/2744 do not mean to give
exhaustive lists of major statuses that may be returned by the functions
they document.

Also, none of the other supplementary status codes make any sense here,
except as errors:

 - GSS_S_DUPLICATE_TOKEN -> it's an error, not supplementary, when it
   comes to context tokens!

 - GSS_S_OLD_TOKEN -> just like GSS_S_DUPLICATE_TOKEN, and anyways,
   makes no sense in a context token exchange of just a handful of
   tokens

 - GSS_S_GAP_TOKEN -> can't possibly happen in a synchronous token
   exchange!

 - GSS_S_UNSEQ_TOKEN -> ditto

Above you say that GSS_Proces_context_token() can't return major status
codes not listed.  Here you say GSS_Init/Accept_sec_context() can.
Which is it?

> specify a new supplementary bit applying to context tokens, as it would

More than that: we'd *want* existing code to have to request the new
feature before new supplementary codes are returned.

> but what would you compare against?

A white-list.  Ditto GSS_Export_name() with GSS_C_NT_EXPORTED_NAME +
memcmp().

Or GSS_Display_name_ext(), which is there to avoid the need for
mechanism-specific knowledge.

Or GSS_Get_name_attribute(), to decompose an MN into components like
"service name" and "hostname".

> for it, and get the desired behavior.  Against older versions or

Great ad-hoc extension.  But we're talking about portable and
mechanism-generic application code.  Standardize this extension and I'll
be happy to see this I-D mention it.

Nico
--