[krbdev.mit.edu #9046] requires_hwauth can cause a preauth loop with PKINIT

Ken Hornstein kenh at cmf.nrl.navy.mil
Wed Jan 19 22:07:07 EST 2022

(Forgive me for redirecting this to krbdev, but it does raise some issues
that I have been thinking about for a while and I felt it was worth having
a larger discussion about it).

>If an admin sets requires_hwauth on a principal and configures PKINIT but not
>a certauth module to set the hw-authent ticket flag, this happens during an AS
>1. The client sends an unauthenticated request.
>2. The KDC responds with PREAUTH_REQUIRED and a hint list offering PKINIT.
>3. The client sends a PKINIT-authenticated request.
>4. The KDC validates the PKINIT padata, but determines that the preauth
>requirements are not met, so reponds again with PREAUTH_REQUIRED and the same
>hint list.

This touches a larger issue that I've run into, in that the client-side
preauth loop is ... kind of a mess.  I mean, I understand WHY it's a mess
and why it's doing what it does.  But let me explain (and I know that
most people here know this stuff, but I want to restate my understanding
in case it is wrong).

My general understanding of the client preauth loop is that it tries to
distinguish between "real" preauth mechanisms and "non-real" mechanisms
that are just being used as a protocol extension.  It will try to pick
the "best" real mechanism it can do out of the list.

Where things get confusing (aside from the distinction between "real"
and "non-real" mechanisms) is what to do when a mechanism fails.
There's kind of a distinction between a failure that lets you silently
skip over a mechanism to another and something that halts the entire
preauth process (it seems to me that if the mechanism returns a failure
code from prep_questions, it's consider a soft failure and other
mechanisms can be attempted).  I understand why it is this way, but
besides from complicating the code this causes two other problems: it
can obscure the "true" error when a preauth mechanism fails, and presents
a sub-optimal user experience (besides the obscured error).  The big
example is if PKINIT fails via a soft error, it falls back to a regular
password prompt (or another preauth mechanism), which is always confusing
to end users.

I realize these are _client_ issues and this issue you are mentioning is
a KDC issue, but I think the basic concern is the same: it's not always
obvious when you need to continue and when you need to fail and stop.
And the answer to that sometimes varies depending on your site.

In our specific setup, we have users in the same realm that offers both
PKINIT and SAM-2 (the medium-term plan is to switch SAM-2 to FAST OTP,
but that is going to take some time).  So that means that generally
we offer both PKINIT and SAM-2 as available preauth types (not all
users are configured for both, but many are).  We have some contortions
to allow us to select a preferred preauth at run time (described in
previous emails), but it's sub-optimal based on the existing preauth
loop.  Really, in a perfect world I'd like to be able to say, "Only use
this preauth type" (possibly more than one) and if that failed I'd like
to get an error back even in the soft failure PKINIT case.  But I can
also appreciate that this situation is a bit unusual and the default of
"try the best mechanism" is probably the most useful.

I realize this is sort of vague, but I guess what I was thinking was
I'd like to advocate to moving towards:

- Moving towards a way of explicitly configuring allowed preauth
- Redoing the preauth loop so explicitly configured mechanisms can fail back

I'm not sure if it would make sense if you specify more than one preauth
mechanism you provide a way of saying, "Go to the next one on failure"
or "Stop on failure".  Requires more thought.


More information about the krbdev mailing list