Hello All,
I have run into a situation where a user exiting from a
PAM_KERBEROS-authenticated session runs the risk of deleting a
kinit-generated credentials file that was already sitting on the server. I
will explain the problem in detail, but let me begin with my question. It
has a specific reference to PAM_KERBEROS, but it can also be a general
question.
If a user (ssh) session was such that it skipped pam_authenticate() during
login (probably because it used a Key-based auth method), then is it all
right for sshd to correspondingly skip pam_setcred() during session exit?
What will happen if we take that approach?
As I understand it, pam_setcred() is called as part of the authentication
phase as well as part of the session exit phase. When called during
authentication, pam_setcred() sets the KRB5CCNAME environment variable to
the credentials file name, and when called during session exit,
pam_setcred() is called to delete that credentials file.
The problem:
Consider a server with pam.conf set up for PAM_KERBEROS all the way
(authentication, acct management, session management, the works). This is
done, presumably, because most all users connecting to the sshd instance on
this machine are to be PAM_KERBEROS authenticated, with some exceptions.
1. And now a telnet user U1 comes along, logs into the server machine, and
does a kinit (on the server). There may be very good reasons for doing so,
and I will not go into those reasons here. We do not control those reasons
anyway. As a result of the kinit, a ticket file /tmp/krb5cc_U1uid is
created on the server (where U1uid is the UID of this telnet user).
2. Now user U1 logs in via SSH into this machine, this time with a
PublicKey. This will cause sshd to skip pam_authenticate(), and therefore
also skip the pam_setcred() call. As a result, the KRB5CCNAME variable will
remain unset. No harm so far.
3. Now, this user (U1, with PublicKey auth) exits. Since session management
is also set to PAM_KERBEROS, sshd will call pam_setcred(), but this time to
delete the credentials file. Note that the credentials file was never
created, but sshd still calls pam_setcred(). And even that should not have
been a problem. But it is, for a few PAM_KERBEROS implementations.
Typical pam_setcred() implementations for the deletion of credentials work
in the following way:
* Either directly or indirectly, they call the standard kerberos5 function
krb5_cc_default_name(), to first determine the credentials file name. This
function does not know whether it is being called from PAM_KERBEROS or from
a GSSAPI environment. It first checks to see if KRB5CCNAME is set. If set,
it returns the file name that the variable is set to. If not set, then this
function assumes it is being called from a regular GSSAPI environment, and
returns a filename that matches what a kinit would have generated. So for
instance, for user U1, it will return a file name /tmp/krb5cc_U1uid.
* Remove the file whose name is returned by krb5_cc_default_name() !!
Not good.
Of course, the file generated by PAM_KERBEROS itself has a different naming
convention, intentionally so, in order not to cause overlap between
kinit-generated ticket filenames and PAM_KERBEROS generated file names. So
if authentication had indeed been done via PAM, then sshd would have called
pam_setcred () to establish the credentials file. Generally speaking,
pam_setcred() would create the credentials file, and then make the
appropriate kerberos function calls to set the name of the cred cache file
and the KRB5CCNAME environment variable. It is important to note here that
the file name generated by pam_setcred() for the credentials file is
different from that of a kinit-generated file for the same user.
However, a combination of the following events makes a valid server-resident
kinit-generated ticket disappear:
A kinit-generated ticket exists on the server for user U1 (how it got there
is not relevant. Let us assume it is there)
pam.conf is set to have authentication and session management both done via
PAM_KERBEROS
User U1 logs in via SSH, using a non-PAM method (e.g. Public Key), thereby
causing KRB5CCNAME to be not set.
User U1 exits
When the user (U1) 's session terminates, the kinit-generated ticket will be
deleted.
Fixing the problem:
I see at least two ways of fixing the problem. The first of course, would
be for PAM_KERBEROS to first check if KRB5CCNAME is set. If not, it should
probably just skip the file delete. That would be ideal for us.
Alternatively, we could do something in sshd. If pam_setcred() was not
called during authentication, then don't call pam_setcred() during session
exit either.
Could there be any problems with this approach?
thanks
Senthil