Adding support for optimistic preauth to kinit

Ken Hornstein kenh at
Tue Apr 6 10:39:09 EDT 2021

>I'm curious what this was needed for.  Our initial ticket code is pretty
>aggressive about trying PKINIT if the KDC offers it.  Not only do KDCs
>tend to offer PKINIT first when they're configured for it, but even if
>they don't, the client code sorts the PKINIT types to the front of the
>list (overridable with [libdefaults] preferred_preauth_types).  So,
>putting PKINIT in the optimistic preauth list wouldn't seem to change
>the behavior of kinit except to save a round trip.

Well, SINCE you're asking ... we put this in our distributed krb5.conf:

	preferred_preauth_types = 30,31

As you note, you can't do optimistic preauth with SAM2.  Because of the
sorting with PKINIT, the default configuration means it will try PKINIT
first if the KDC offers it.  But, effectively, this means that if there
is a problem with PKINIT then you're kind of locked out even if you have
another type of working hardware preauth mechanism.  I realize that if
your client isn't configured for PKINIT at all then it will skip over
it, but typically we ARE configured for PKINIT but unfortunately there
are a large number of failure modes with PKINIT so it's very easy to
get into a situation where the default configuration doesn't work.

The way this works for us in practice is we ship a "kinit" program and a
"pkinit" program; the pkinit program sets the optimistic preauth list to
include PKINIT which has the effect of overriding the preferred preauth
list.  This I believe was the only reasonable solution available to us
given the existing APIs without totally rototilling the preauth layer
which nobody wants to do (because as it has been noted here, it's very
complicated to get it right for all cases).

I realize that there isn't a wonderful no-configuration general-purpose
solution; it's tough to make it work right for all use cases.  Typically,
in our environment a user has one of 3 configurations:

- Has a single hardware token configured and their principal is configured
  so it is required they use it
- Has multiple hardware tokens configured and their principal is configured
  that it is required they use one of them
- Has zero or more hardware tokens configured, but the use of the hardware
  token is optional.

But we never are really in the situation a user wants to just use "the
best token available".  They know "I have a smartcard" or "I have this
other type of token" and want to use that particular one.  I mean, they
don't really know that smartcard == PKINIT and token == SAM2, they know
that when they use their smartcard they have to run "pkinit" and the
rest of the time they use "kinit".

>>> A path of lower resistance is to add an option to force a particular
>>> preauth mech (single choice, hard-failing if it isn't available or
>>> doesn't work).  clpreauth modules already declare names like "pkinit"
>>> and "sam2" which could be matched against.
>> Honestly, I'd be fine with this (although it does occur to me that you
> might want to specify more than one preauth to use)
>What use cases do you have in mind for specifying more than one?

Hm ... good question!  I'm not honestly sure.  I guess I was thinking
that for no other reason than in development it sure would be nice to
test how things behave when one mechanism fails but others could still
potentially work.  I'd like to have the capability in the API to open up
other potential uses that I couldn't think of right now.


More information about the krbdev mailing list