A few things to keep in mind:
- kbd-int should call pam_authenticate(), acct_mgmt(), chauthtok(), if
required, setcred(PAM_ESTABLISH_CRED) and open_session() ALL during
kbd-int so that modules in each of those PAM stacks can prompt the
user (pam_open_session(), for example, may prompt a user with an
informational message akin to the last login message)
- all userauth methods should call pam_acct_mgmt() and force kbd-int,
via partial userauth failure, if pam_acct_mgmt() returns
PAM_NEW_AUTHTOK_REQD (password expired)
- pam_setcred(PAM_ESTABLISH_CRED) and pam_open_session() should be
called by the end of userauth, regardless of which method(s) is(are)
tried by the client and completed successfully. (NOTE: there's no tty
at that point, nor any way to know if the client will want a tty
session)
- userauth methods other than kbd-int should have a null conversation
function (either NULL, literally, or a function that returns
PAM_CONV_ERR if any echo on/off prompts are issued)
- all of those PAM calls have to be done in a process which is an
ancestor to the user's actual session processes and those user
processes should not be created before calling PAM either
- preferably the process that calls pam_open_session() should be the
one to call pam_close_session(), on the same PAM handle on which
pam_open_session() was called
- no concurrence (threads) is needed for any of this, but because of
the way PAM conversations work
- the event loop must be nested (yes, this is workable, and 3.5p1
does nest the event loop in kbd-int userauth w/ PAM)
OR
- the PAM calls must be performed on alternative stacks (i.e., in a
different co-process)
OR
- the server must packet_disconnect() rather than allow kbd-int to
be abandoned or restarted
As Frank points out, multi-round-trip userauth methods can be
"abandoned" or "restarted" by the client; for kbd-int
userauth this
means that multiple PAM conversations may be active, waiting for
responses, concurrently (but only the last one started can succeed -
the others must be either fail or be left waiting for responses that
will never come).
Cheers,
Nico
--
On Wednesday, February 26, 2003, Frank Cusack wrote:> On Sun, Feb 02, 2003 at 01:48:52PM +0100, Dag-Erling Smorgrav wrote:
> > My code runs the PAM authentication in a separate thread or process to
> > avoid calling the main loop from the conversation function (which
> > won't work with privsep anyway). Modules like pam_krb5 where the
> > session management stage uses information stored by the authentication
> > stage only work when using threads, because threads can share a PAM
> > handle but processes can't.
>
> Here are my initial thoughts.
>
> The PAM stuff runs in the priv part. You communicate to the unpriv part
> via a socket. Why bother with threads? The thread is just an added
> complication. OK, it avoids having to grab control of the main loop
> from within the conversation function, but I just wonder if there's
> another way to do this. I mean, you're still stuck in the conv.
> function until the info response comes back, anyway. How do (will)
> you handle restarting the authentication (client sends USERAUTH_REQUEST
> instead of USERAUTH_INFO_RESPONSE)?
>
> In auth-pam.c:sshpam_thread_conv(), line 148, the two cases ECHO_OFF and
> ECHO_ON should be combined into a single case, as should the ERROR_MSG
> and TEXT_INFO cases; just as you do in sshpam_query().
>
> The code as a whole /is/ far cleaner than what exists currently, so that
> is a big plus.
>
> I dislike that kbdint is run via auth2_challenge() and all the refs
> to "challenge". It's not necessarily a challenge.
>
> /fc