lightdm uses wrong ccache name on pam_krb5 credentials refresh

Bug #1336663 reported by Sergio Gelato
26
This bug affects 5 people
Affects Status Importance Assigned to Milestone
Light Display Manager
Triaged
Medium
Unassigned
gdm
New
Undecided
Unassigned
libpam-krb5 (Ubuntu)
Invalid
Undecided
Unassigned
lightdm (Ubuntu)
Triaged
Medium
Unassigned

Bug Description

As already noted by Brian Knoll in https://bugs.launchpad.net/ubuntu/+source/lightdm/+bug/1296276/comments/24
lightdm 1.10.1-0ubuntu1 uses an inappropriate credentials cache, /tmp/krb5cc_0, when refreshing Kerberos credentials on screen unlock.

I couldn't find the new bug Robert Ancell called for in https://bugs.launchpad.net/ubuntu/+source/lightdm/+bug/1296276/comments/27 so I'm opening one now.

Changed in lightdm:
importance: Undecided → Medium
Changed in lightdm (Ubuntu):
importance: Undecided → Medium
Changed in lightdm:
status: New → Triaged
Changed in lightdm (Ubuntu):
status: New → Triaged
Revision history for this message
Robert Ancell (robert-ancell) wrote :

This bug occurs when when using LightDM as a lockscreen and pam-krb5 not correctly updating the credentials of the session you switch back to.

It's not clear if the problem is the way we are using PAM in LightDM (i.e. insufficient/wrong information for pam-krb5 to do the right thing) or an assumption by pam-krb5 that is not occurring.

Revision history for this message
Sergio Gelato (sergio-gelato) wrote : Re: [Bug 1336663] Re: lightdm uses wrong ccache name on pam_krb5 credentials refresh

* Robert Ancell [2014-07-08 04:27:34 -0000]:
> It's not clear if the problem is the way we are using PAM in LightDM
> (i.e. insufficient/wrong information for pam-krb5 to do the right thing)
> or an assumption by pam-krb5 that is not occurring.

pam_krb5 needs to be told the name of the credentials cache for the session
being unlocked; it can't very well guess it by itself. I believe it looks
for the environment variable KRB5CCNAME. This may need to be made a part of
the session state as seen by LightDM. pam_krb5 will set this variable (to an
unpredictable value) on initial login, so perhaps LightDM should stash its
value somewhere at that time; or else it can be retrieved (but is that
portable enough?) from /proc/<pid>/environ for the session's main process.
Either way, it needs to be made visible to pam_krb5 at setcred time on unlock.
libpam-krb5/cache.c:pamk5_get_krb5ccname() tries pam_getenv() first, then
regular getenv().

Revision history for this message
Steve Langasek (vorlon) wrote :

Yes. This bug probably means that lightdm is not associating the login session's environment with the pam handle for the unlock action. It looks like lightdm correctly copies the contents of the pam env (pam_getenvlist) to the session environment (judging by the $KRB5CCNAME that I have in my environment here), but evidently it doesn't save this information for later use for the unlock screen, which it needs to do.

A valid way to do this would be to keep the pam handle open for the duration of the login session, and reference it for any unlock actions.

Revision history for this message
Robert Ancell (robert-ancell) wrote :

We do have the PAM handle open but it's in a subprocess that the daemon has no communication with. It was my assumption (fear) that we might need to access it for credential refreshing. This will take quite some refactoring to make this work but should be possible.

Revision history for this message
Russ Allbery (rra-debian) wrote :

Note that all that pam-krb5 specifically cares about is KRB5CCNAME, so an alternative approach that may require less refactoring and would work for that PAM module would be to preserve the PAM environment from pam_getenvlist and set those variables in the environment before invoking PAM for unlock. That should not require reusing the same PAM handle.

I don't know if that would be sufficient for other PAM modules, however.

Revision history for this message
Launchpad Janitor (janitor) wrote :

Status changed to 'Confirmed' because the bug affects multiple users.

Changed in libpam-krb5 (Ubuntu):
status: New → Confirmed
Revision history for this message
Cédric Dufour (cedric.dufour) wrote :

Hello,
Has any progress been made with this issue?
Is there any workaround to circumvent it?
Thanks for the feedback and best

Revision history for this message
Sergio Gelato (sergio-gelato) wrote :

I'm not aware of any activity on this since Robert Ancell's comment #4 indicating that a proper fix might require extensive refactoring (too extensive for Ubuntu T?). As a workaround I've added an Upstart configuration file to run krenew in every user's session; it's as simple as

start on xsession
stop on desktop-end
respawn
exec /usr/bin/krenew -K 60

(One may need to add a -t flag if AFS token renewal is desired.)
Lightdm still refreshes the wrong ccache but krenew independently takes care of the right one.

Revision history for this message
Cédric Dufour (cedric.dufour) wrote :

Hello again,

Thanks @Sergio for the krenew tip.

I'd rather not automatically renew a user ticket without having him supply its password from time to time.

I came up with a *horrible* workaround which I believe does not break the entire Kerberos security (please correct me if I'm wrong):

In /etc/pam.d/common-auth:
auth optional pam_script.so dir=/etc/security/pam-script.d

In /etc/security/pam-script.d/pam_script_auth:
#!/bin/sh

## Kerberos 5 credential cache (ticket) hack
# REF: https://bugs.launchpad.net/ubuntu/+source/lightdm/+bug/1336663
sh -c "sleep 3; PAM_USER=${PAM_USER} /etc/security/pam-script.d/krb5cc_rename" &

In /etc/security/pam-script.d/krb5cc_rename:
#!/bin/sh

## Kerberos 5 credential cache (ticket) hack
# REF: https://bugs.launchpad.net/ubuntu/+source/lightdm/+bug/1336663

# Parameters
KRB5CC_DIR='/tmp'

# Look for matching - although misnamed - credential cache
# ... retrieve user UID
KRB5CC_UID="$(id -u "${PAM_USER}")"
[ -z "${KRB5CC_UID}" ] && echo 'ERROR: Failed to retrieve user UID' && exit 1
# ... look for user matching/misnamed ticket
KRB5CC_SRC="$(find "${KRB5CC_DIR}" -maxdepth 1 -uid "${KRB5CC_UID}" -name 'krb5cc_0')"
[ -z "${KRB5CC_SRC}" ] && echo 'INFO: No matching/misnamed Kerberos 5 ticket found' && exit 0
# ... look for *older* user ticket (do not replace a newer one)
KRB5CC_DST="$(find "${KRB5CC_DIR}" -maxdepth 1 -uid "${KRB5CC_UID}" -name "krb5cc_${KRB5CC_UID}_*" -not -newer "${KRB5CC_SRC}" | head -n 1)"
[ -z "${KRB5CC_DST}" ] && echo 'INFO: No previous/user Kerberos 5 ticket found' && exit 0
# ... check Kerberos principal matches (just to be on the safe side; let's not rely only on files ownership)
[ "$(klist "${KRB5CC_SRC}" | grep '^Default principal:')" != "$(klist "${KRB5CC_DST}" | grep '^Default principal:')" ] && echo 'ERROR: Mismatched principal' && exit 1

# Replace user credential cache by matching/misnamed one
mv "${KRB5CC_SRC}" "${KRB5CC_DST}"
[ $? -ne 0 ] && echo 'ERROR: Failed to rename matching/misnamed Kerberos 5 ticket' && exit 1
echo 'INFO: Successfully renamed matching/misnamed Kerberos 5 ticket'
exit 0

The 'sh -c "sleep 3; ..."' is required to handle the fact that the misnamed ticket is created only after pam_script is invoked (I guess when pam_end is called).

Gut-wrenching... but working :-/

Revision history for this message
Craig G (cgallek) wrote :

FWIW, this issue is also present using gdm3 in Ubuntu 16.04. With pam_krb5's debug option set, I see the following during initial login (with successful credential cache construction):

gdm-password]: pam_krb5(gdm-password:auth): pam_sm_authenticate: entry
gdm-password]: pam_krb5(gdm-password:auth): (user cgallek) attempting authentication as <email address hidden>
gdm-password]: pam_krb5(gdm-password:auth): user cgallek authenticated as <email address hidden>
gdm-password]: pam_krb5(gdm-password:auth): (user cgallek) temporarily storing credentials in /tmp/krb5cc_pam_LB8CeL
gdm-password]: pam_krb5(gdm-password:auth): pam_sm_authenticate: exit (success)
gdm-password]: pam_krb5(gdm-password:setcred): pam_sm_setcred: entry (establish)
gdm-password]: pam_krb5(gdm-password:setcred): (user cgallek) initializing ticket cache FILE:/tmp/krb5cc_1000_3BiTY0
gdm-password]: pam_krb5(gdm-password:setcred): pam_sm_setcred: exit (success)

When unlocking the screen, I see the following successful credential refresh, but to the wrong cache filename (/tmp/krb5cc_0):

gdm-password]: pam_krb5(gdm-password:auth): pam_sm_authenticate: entry
gdm-password]: pam_krb5(gdm-password:auth): (user cgallek) attempting authentication as <email address hidden>
gdm-password]: pam_krb5(gdm-password:auth): user cgallek authenticated as <email address hidden>
gdm-password]: pam_krb5(gdm-password:auth): (user cgallek) temporarily storing credentials in /tmp/krb5cc_pam_Dkg5Ip
gdm-password]: pam_krb5(gdm-password:auth): pam_sm_authenticate: exit (success)
gdm-password]: pam_krb5(gdm-password:setcred): pam_sm_setcred: entry (reinit)
gdm-password]: pam_krb5(gdm-password:setcred): (user cgallek) refreshing ticket cache /tmp/krb5cc_0
gdm-password]: pam_krb5(gdm-password:setcred): pam_sm_setcred: exit (success)

The _0 cache that is created has the correct new credential in it, but is obviously not known by any other process as it does not match the earlier version of $KRB5CCNAME. I imagine this is the same issue described above where the $KRB5CCNAME environment variable is not available in the gdm context which unlocks the screen.

It's worth noting that in the GDM case, there appears to be a per-session helper process (gdm-session-worker) used to communicate with the GDM service. This process _does not_ have the $KRB5CCNAME variable set in its environment. Would storing the value in this processes environment fix the problem?

~: ps -ef | grep gdm-session-worker
root 11364 11203 0 Jun25 ? 00:00:00 gdm-session-worker [pam/gdm-password]

~: cat /proc/11364/environ
LANG=en_US.UTF-8PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binGDM_SESSION_DBUS_ADDRESS=unix:abstract=/tmp/dbus-oTnmcExV

Revision history for this message
Cédric Dufour (cedric.dufour) wrote :

On Debian/Stretch - lightdm 1.18.3 - this issue is still present.

The script mentioned in comment 9 has served us well for the past 3+ years and is "maintained" on https://github.com/cedric-dufour/custom-conf/tree/master/generic/all/custom-conf-pam-krb5/usr/share/custom-conf-pam-krb5/config/etc/security/pam-script.d as part of our "standard" Kerberos/PAM configuration.

Best

Revision history for this message
Russ Allbery (rra-debian) wrote :

Yes, if KRB5CCNAME were set in the environment of the screen saver, it would fix this problem.

To be clear, this isn't a bug in libpam-krb5, but in the means by which the screen saver is launched without the user's environment set properly (which should be created via the pam_setcred and pam_open_session steps of the PAM call sequence, and the new user environment generated by PAM). Without KRB5CCNAME, there's no way for the PAM module to find the user's ticket cache to renew it on subsequent unlocks; somehow, it does need that information conveyed to it.

You can work around this by using a predictable ticket cache name that embeds only the user's UID and setting that as the default ticket cache (in various ways -- PAM configuration, Kerberos configuration, etc.). But this isn't a general solution that can be adapted by the package because it means every user session for the same user uses the same Kerberos ticket cache, which means that, say, logging on to the system via ssh and then logging out will delete the ticket cache underneath the local console login.

Changed in libpam-krb5 (Ubuntu):
status: Confirmed → Invalid
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.