keyboard-interactive

Frank Cusack fcusack at fcusack.com
Thu Jan 10 19:10:26 EST 2002


On Wed, Jan 09, 2002 at 09:48:07PM -0600, Mark D. Roth wrote:
> On Wed Jan 09 23:21 2002 +0100, Markus Friedl wrote:
> > so when sshd receives a REQUEST message the mainloop calls
> > 	input_userauth_request()
> > 
> > input_userauth_request() needs to parse the REQUEST message and
> > (for kbd-interactive) contruct a INFO_REQUEST message by calling
> > some PAM API and return the control to the mainloop.
> > 
> > now the client can send _any_ packet, e.g. a KEXINIT
> > for rekeying or a new REQUEST message for a different 
> > authentication method (e.g. pubkey).

But KEXINIT (or any other non-auth message) /need not/ be handled
"synchronously".  Well, at best it's not clear that it /must be/ handled
synchronously.  Before I get to that, let me start with a problem in
draft-ietf-secsh-userauth-13.txt, sec 2.1.  As someone else mentioned,
it says

   An authentication request MAY result in a further exchange of
   messages.  All such messages depend on the authentication method
   used, and the client MAY at any time continue with a new
   SSH_MSG_USERAUTH_REQUEST message, in which case the server MUST
   abandon the previous authentication attempt and continue with the new
   one.

However, this conflicts with the text of sec 2.2, which says

   The client MAY send several authentication requests without waiting
   for responses from previous requests.  The server MUST acknowledge
   any failed requests with a SSH_MSG_USERAUTH_FAILURE message.
   However, SSH_MSG_USERAUTH_SUCCESS MUST be sent only once, and once
   SSH_MSG_USERAUTH_SUCCESS has been sent, any further authentication
   requests received after that SHOULD be silently ignored.

The conflict is that the server must acknowledge failed requests.
Sec 2.1 says the server must ABANDON previous authentications if it
receives another request.  So we're off to a bad start.

Sec. 2.2 goes on,

   Any non-authentication messages sent by the client after the request
   that resulted in SSH_MSG_USERAUTH_SUCCESS being sent MUST be passed
   to the service being run on top of this protocol.

indicating

   - non-auth messages can be sent at any time; this is clear since if
     they could only be sent AFTER completion of the authentication,
     the text should read "after the client receives [SUCCESS]".
   - non-auth messages sent after (during) a request that results in
     failure may be ignored (implied)

So a client could send a request for pk auth, during which he sends a
KEXINIT message.  That pk auth could fail, and then the client sends
kbd-interactive which succeeds.  The server may safely throw away the
KEXINIT message.

To me, that clearly means that non-auth messages need not be handled
immediately.  If they are to be handled immediately, there cannot be a
distiction between auth requests that result in success and auth requests
that result in failure.

However, given the precedent set by the earlier conflicting text
(re multiple auth requests and failure handling) and the lack of
explicit statements as to how non-auth messages are to be handled,
my conclusion, while valid based on the draft, may really just be an
unintended consequence of an incompletely specified protocol.  That is,
it may be legal, but unintended behaviour.

IMvHO, I would say the best course of action is to make no changes in
the current implementation (other than perhaps handling an abortive (new)
auth request), and instead spend energy getting the draft corrected/clarified.

> OK, so how about this:
> 
>  * Call the main loop from the PAM conversation function with some
>    state telling it where it was called from.
> 
>  * When the main loop gets the next message from the client, it can
>    return control to the PAM conversation function.
> 
>  * If the client sent an INFO_RESPONSE message, the PAM conversation
>    function returns the client's response, and the PAM transaction
>    continues normally.
> 
>  * If the client sent some other type of message, the conversation
>    function can return PAM_CONV_ERR to abort the PAM transaction.  It
>    should also set some state to indicate that the PAM transaction was
>    aborted.

But that would unnecessarily fail the authentication, which might have
gone on to success.  I'd say this is fairly undesirable.

I would say that instead of always returning control to "conv()", control
should only be returned if the client message is an INFO_RESPONSE or a
new userauth request.  You'd have to tell conv() which one it is so it can
continue or abort (fail) as needed.

>  * When pam_authenticate() returns, if the transaction was aborted,
>    return control to the main loop to handle the request that the
>    client sent.
> 
> There are some obvious semantics to be worked out in terms of how the
> state is maintained, but the PAM code itself would be fairly
> straightforward.  Or is there something I'm missing here?

I think you're missing that both the non-auth and auth messages should
continue as if they didn't overlap in sequence.  Otherwise, your suggestion
sounds reasonable (to me, anyway).

If we assume that non-auth messages can be handled "asynchronously", then
it's really easy.  Just use appdata_ptr to store the non-auth messages,
and if and after the authentication succeeds, then process them.

Again, I'd do nothing until the draft is clarified.  Especially given the
expectation that current clients don't/won't actually show this behaviour.

/fc




More information about the openssh-unix-dev mailing list