Sunday, July 13, 2008

Caching Kerberos credentials for offline logins

Having kerberos is a nice way to centralize your user passwords, but what if you have laptops that you would like to log onto away from your network? You have to setup credential caching. This is achieved through PAM and the pam_ccreds module. On a Fedora, or a Red Hat derivative, system, you only need to edit one file, /etc/pam.d/system-auth-ac. This file exists on any PAM aware system. Here is mine in its entirety.

auth required pam_env.so
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 500 quiet
auth [default=ignore success=1 service_err=reset] pam_krb5.so use_first_pass
auth [default=die success=done] pam_ccreds.so action=validate use_first_pass
auth sufficient pam_ccreds.so action=store use_first_pass
auth required pam_deny.so

account required pam_unix.so broken_shadow
account sufficient pam_localuser.so
account sufficient pam_succeed_if.so uid < 500 quiet
account [default=bad success=ok user_unknown=ignore] pam_krb5.so
account required pam_permit.so

password requisite pam_cracklib.so try_first_pass retry=3
password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password sufficient pam_krb5.so use_authtok
password required pam_deny.so

session optional pam_keyinit.so revoke
session required pam_limits.so
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session required pam_unix.so
session optional pam_krb5.so

I've highlighted the lines that do the work. It took me a while to make this. I've read tons of tutorials, as you probably have, to get this to work. In the end, I ended up mastering PAM configuration since none of the tutorial worked properly. I'm going to explain each line so that you will understand what is happening.

auth [default=ignore success=1 service_err=reset] pam_krb5.so use_first_pass

This line is the most complicated. The default=ignore tells PAM, if this module fails, like cannot reach kerberos server or password does not match, go on to the next step. The success=1 tells PAM if the module succeeds, a correct password verified by the kerberos server, skip one step. The service_err=reset, tells PAM to try again if the server reachable but down for some reason. The pam_krb5.so is the name of the module. Finally, the use_first_pass tells PAM to use the password that was first given to PAM during this run through and do not ask for a new one.

auth [default=die success=done] pam_ccreds.so action=validate use_first_pass

If kerberos was unavailable, PAM will run this line. The default=die means, if this module fails, everything fails and don't give the user access. The success=done means the auth portion of PAM is complete if this succeeds. pam_ccreds.so is the module name. The module, pam_ccreds, takes arguments and the action=validate has pam_ccreds check to see if the given password matches what is cached in /var/cache/.security.db.

auth sufficient pam_ccreds.so action=store use_first_pass

If the user entered a password that was verified by the kerberos server, PAM will apply this rule. The sufficient tells PAM if this module succeeds, the auth portion is complete. Otherwise, continue through the rest of the auth portion. The action=store, if you haven't guessed, stores the encrypted password in /var/cache/.security.db.

Now the system will cache kerberos credentials!

One gotcha on SELinux enabled systems, I have not been able to get this to work in enforcing mode. PAM is horrible restricted. I cannot find an appropriate file context to apply to /var/cache/.security.db that will allow pam_ccreds to write to it. I recommend using Permissive mode until I find a solution. This should not be too big a deal because you should only be using this on laptops, not critical systems.

One more gotcha. For some reason I have not discovered yet, xscreensaver cannot use ccreds properly. If you lock your machine, then you will not be able to log in without setting up a local password. I'm working on a solution for this.