pam-afs-session 1.7

(PAM module for AFS PAGs and tokens)

Written by Russ Allbery <rra@stanford.edu>

See the LICENSE file, included in this distribution, for copyright and redistribution information.

BLURB

pam-afs-session is a PAM module intended for use with a Kerberos v5 PAM module to obtain an AFS PAG and AFS tokens on login. It puts every new session in a PAG regardless of whether it was authenticated with Kerberos and either uses Heimdal's libkafs or runs a configurable external program to obtain tokens. It supports using Heimdal's libkafs for the AFS interface and falls back to an internal implementation if libkafs isn't available.

DESCRIPTION

pam-afs-session is a PAM module that isolates each login in a separate AFS PAG (so that they will not trample on each other's AFS tokens) and supports either running an external program to obtain AFS tokens from a Kerberos v5 ticket cache or using Heimdal's libkafs library. It does not obtain tickets itself and must be used in conjunction with a Kerberos v5 PAM module to obtain tokens (setting up PAGs can be done without any Kerberos implementations). It provides only the setcred and session PAM functions.

There are two ways this module can obtain tokens:

For the AFS system call layer, pam-afs-session supports linking with the Heimdal libkafs library. As a fallback, and to support a low-dependency build, it also comes with a simple AFS system call implementation for either Linux or platforms that use syscall to call AFS functions. To use the built-in system call interface on Linux, the system must run a new enough version of OpenAFS or Arla to support AFS system calls through ioctl on a file in proc. On other systems, configure must be able to find the AFS header afs/param.h in order to get the system call numbers for that platform.

Right now, this module will probably only work on Linux, Solaris, HP-UX, AIX, and Mac OS X, and will require gcc to even attempt to build on any other platform. Other PAM implementations will likely require some porting work.

The module can optionally be linked with Kerberos libraries to obtain configuration information from krb5.conf, to support the kdestroy option, and to use libkafs's functions for obtaining tokens. Either MIT Kerberos or Heimdal should work.

COMPILING AND INSTALLING

To build the module, just run:

    ./configure
    make

Kerberos support is enabled by default if configure can find Kerberos libraries. If your Kerberos libraries aren't installed in a location found by your compiler by default and krb5-config isn't on your PATH, use the --with-krb5=PATH option to configure. The Kerberos libraries will then be expected in PATH/lib and the headers in PATH/include.

To specify a particular krb5-config script to use, either set the KRB5_CONFIG environment variable or pass it to configure like:

    ./configure KRB5_CONFIG=/path/to/krb5-config

To not use krb5-config and force library probing even if there is a krb5-config script on your path, set KRB5_CONFIG to a nonexistent path:

    ./configure KRB5_CONFIG=/nonexistent

To disable Kerberos support, even if you have Kerberos libraries available, pass --without-krb5 to configure.

By default, the first aklog program found on the PATH will be compiled into the module as the default aklog program to run. This can be overridden by the program PAM option. To specify an explicit path to aklog, use:

    ./configure --with-aklog=/path/to/aklog

instead.

To install the module into /usr/local/lib/security and the man page into /usr/local/share/man/man5, run:

    make install

You can change the installation locations with the --prefix, --mandir, and --libdir options to configure. The module will be installed in a subdirectory of $libdir named security and, on x86_64 Linux, $libdir will be changed to lib64 to match the default PAM configuration. Alternately, you can simply copy pam_afs_session.so to whatever directory you use for PAM modules. On Solaris, you will need to make the module executable.

By default, if libkafs or libkopenafs are available, pam-afs-session will use them in preference to its own system call implementation. If for some reason you want to build pam-afs-session without a dependency on those libraries even though you have them installed, pass the --without-libkafs flag to configure.

If you are building this module without libkafs on a platform other than Linux, configure needs to find the AFS header afs/param.h. If this is not in the normal include path, pass the --with-afs-headers option to configure to point the compiler at the correct path. For example, if your AFS headers are in /usr/afsws/include, run:

    ./configure --with-afs-headers=/usr/afsws/include

instead.

You can pass the --enable-reduced-depends flag to configure to try to minimize the shared library dependencies encoded in the binaries. This omits from the link line all the libraries included solely because libkafs or the Kerberos libraries depend on them and instead links the programs only against libraries whose APIs are called directly. This will only work with shared libraries and will only work on platforms where shared libraries properly encode their own dependencies (such as Linux). It is intended primarily for building packages for Linux distributions to avoid encoding unnecessary shared library dependencies that make shared library migrations more difficult. If none of the above made any sense to you, don't bother with this flag.

CONFIGURING

Just installing the module does not enable it or change anything about your system authentication configuration. You have to add the module to your PAM configuration, generally in the session group and possibly in the auth group as well. See the platform-specific instructions below.

On all platforms, options can be put after the module name in the PAM configuration file. This is useful if you don't have Kerberos libraries available or if you want different configurations for different services.

If Kerberos support was enabled, configuration options may also be put in the krb5.conf file used by your Kerberos libraries (usually /etc/krb5.conf or /usr/local/etc/krb5.conf) instead or in addition to the PAM configuration. See the man page for more details. This is recommended for general system configuration, since the krb5.conf configuration syntax is a little nicer and more flexible.

See the files in the examples directory for examples of PAM configuration for various operating systems. Contributions for additional operating systems are welcome.

Linux

To use it in conjunction with pam_krb5 on a Debian system, put something like:

    auth [success=ok default=1] pam_krb5.so
    auth [default=done]         pam_afs_session.so program=/usr/bin/aklog
    auth required               pam_unix.so try_first_pass nullok_secure

in /etc/pam.d/common-auth and something like:

    session optional pam_krb5.so
    session required pam_afs_session.so program=/usr/bin/aklog

in /etc/pam.d/common-session. The program= setting is optional if /usr/bin/aklog was in your path when the module was compiled or was specified via the --with-aklog option to configure.

You may want to stack your Kerberos v5 PAM module and the Unix module differently, but note that this module should always run after the Kerberos v5 PAM module. If there is no ticket cache available in the PAM environment, it will succeed silently.

On Red Hat systems, modify /etc/pam.d/system-auth instead; it contains all of the configuration for the different stacks.

Be careful if your PAM configuration uses pam_keyinit. This module initializes a new kernel keyring and will remove the keyring created by pam_afs_session to hold your tokens. When using pam_afs_session, either remove this PAM module or make sure pam_afs_session only runs after it in the PAM session group. This can be tricky with OpenSSH since OpenSSH calls setcred, then open_session, then setcred again, which means that if you list pam_afs_session in the auth stack and pam_keyinit in the session stack, pam_afs_session will create a PAG during setcred, pam_keyinit will destroy the PAG in the session stack, and then pam_afs_session won't recreate it because it believes it has already run. You may want to remove pam_afs_session from the auth stack of only OpenSSH, or remove pam_keyinit entirely if you use OpenSSH and pam_keyinit isn't doing anything useful for you.

Note that this is not an authentication module and will always return PAM_SUCCESS to any authentication attempt, so never make this module sufficient in your authentication stack. It's only listed as an auth module because it provides a pam_setcred implementation and some programs need to call pam_setcred rather than pam_open_session (screen savers, for instance, to refresh credentials).

Solaris

Solaris doesn't support the [] keywords that Linux PAM does, so if you want to mark the Kerberos v5 PAM module as sufficient and fall back on the Unix module only if it fails, you won't be able to easily run pam_afs_session in the auth group. For most applications, this isn't a problem; running pam_afs_session only from the session group with something like:

    other session required /usr/local/lib/security/pam_afs_session.so 
        minimum_uid=100 retain_after_close

(all on one line) in /etc/pam.conf will be sufficient. Make sure this line is after the Kerberos v5 PAM module's session call.

However, note that login and dtlogin, at least under Solaris 10, apparently call pam_open_session before pam_setcred, and the open_session function of the native Kerberos v5 PAM module doesn't set up the ticket cache. This means that calling pam_afs_session only in the session group won't work, since it will be called before the setcred function of the Kerberos v5 PAM module and hence won't have a ticket cache available yet. There are two possible solutions: replace the native Kerberos v5 PAM module with another module, such as:

    http://www.eyrie.org/~eagle/software/pam-krb5/

that does the same thing in open_session as in setcred, or also call pam_afs_session from the auth group:

    login auth required /usr/local/lib/security/pam_afs_session.so
        minimum_uid=100

after the Kerberos v5 PAM module (and likewise for dtlogin). This means that you cannot use sufficient in the auth group for the Kerberos v5 PAM module, since that will then abort the group before pam_afs_session runs.

See the man page for pam.conf on Solaris for more configuration information.

HP-UX

HP-UX configuration is very similar to Solaris. Something like:

    dtaction session required /usr/lib/security/pam_afs_session.so
    dtlogin  session required /usr/lib/security/pam_afs_session.so
    login    session required /usr/lib/security/pam_afs_session.so
    OTHER    session required /usr/lib/security/pam_afs_session.so

will use pam-afs-session for most login sessions.

Mac OS X

For Mac OS X, PAM isn't used for system login and is therefore mostly useful for remote ssh. To use this module with sshd, add it to the session group of the sshd PAM configuration, and it will then obtain tokens with forwarded tickets via GSS-API or tickets obtained via KerberosAuthentication.

IMPLEMENTATION NOTES

pam-afs-session supports three basic usage patterns: creating a new session using either pam_open_session or pam_setcred(PAM_ESTABLISH_CRED) (or both), closing a session with pam_close_session or pam_setcred(PAM_DELETE_CRED), and refreshing credentials with pam_setcred(PAM_REINITIALIZE_CRED). In general, the same behavior occurs whether using the pam_*_session interface or the pam_setcred interface, since some PAM-using programs call one and some call the other. In all cases, pam-afs-session will log an error and then successfully exit if AFS doesn't appear to be running (checked with the k_hasafs interface).

pam-afs-session stores a PAM data key named "pam_afs_session" once it has successfully created a PAG and a token. If this key is present in the PAM data when pam_open_session or pam_setcred with the PAM_ESTABLISH_CRED flag is called, it will successfully do nothing to keep from doing duplicate work. Otherwise, it will always create a PAG and then will either call krb5_afslog or run an external program to obtain tokens provided that the environment variable KRB5CCNAME is set in the PAM environment.

If libkafs was found and used at compile time and if krb5_afslog is available, the default is to run krb5_afslog to obtain tokens. Otherwise, the default is to run whatever aklog program was found at compile time. If program is set explicitly in the configuration, pam-afs-session will always run that program rather than calling krb5_afslog.

When pam_close_session or pam_setcred(PAM_DELETE_CRED) is called, pam-afs-session will destroy the user's tokens only if the PAM data key "pam_afs_session" is present (meaning that pam-afs-session previously obtained tokens). This check is present to avoid deleting tokens when session initialization failed, since in that case no new PAG may have been created and we may be deleting tokens that are not ours to delete.

pam_setcred(PAM_REINITIALIZE_CRED) is treated similarly to the opening of a new session except that no PAG is created. Instead, only the program to obtain tokens is run, provided that KRB5CCNAME is set in the PAM environment. This interface is used by programs such as screen savers and lockers to refresh a user's credentials.

pam-afs-session requires that the user (obtained via pam_get_user) exists in the local passwd file or equivalent (using getpwnam). If running an external program, the program is run under that user's UID and primary GID. If calling krb5_afslog, that user's UID is used for the "AFS ID" field in the tokens display (which is entirely cosmetic).

HOMEPAGE AND SOURCE REPOSITORY

The pam-afs-session web page at:

    http://www.eyrie.org/~eagle/software/pam-afs-session/

will always have the current version of this package, the current documentation, and pointers to any additional resources.

pam-afs-session is maintained using Git. You can access the current source by cloning the repository at:

    git://git.eyrie.org/afs/pam-afs-session.git

or view the repository via the web at:

    http://git.eyrie.org/?p=afs/pam-afs-session.git

THANKS

Some of the ideas behind this PAM module (although not the code) are taken from the libpam-openafs-session Debian package written by Sam Hartman and the pam_afs2 module written by Douglas Engert. Thanks to both of them for their previous work. Any errors in this implementation are mine.

The Linux system call layer was based on inspection of the code in OpenAFS and on discussions with Jeffrey Hutzelman on how best to implement an AFS system call layer and on how the pieces work. I couldn't have written this code without his explanations.

Thanks to Douglas Engert for an initial code review, for Solaris porting, for suggesting the always_aklog and aklog_homedir options, and for catching various other problems and missing features.

Thanks to Sean O'Malley for additional Solaris porting information and for testing with the Sun C compiler.

Thanks to Joe Buehler for porting and testing on HP-UX.

Thanks to Markus Moeller for multiple patches and suggestions for improved portability for pam-krb5, from which this module has also benefitted.

Converted to XHTML by faq2html version 1.29