                           pam-afs-session 1.5
                   (PAM module for AFS PAGs and tokens)

                Written by Russ Allbery <rra@stanford.edu>

  Copyright 2006, 2007 Board of Trustees, Leland Stanford Jr. University.
  This software is distributed under a BSD-style license.  Please see the
  section LICENSE below for more 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:

   * If you have Heimdal's libkafs library available and build this module
     with Kerberos support (passing --with-kerberos to configure), the
     module can call libkafs's krb5_afslog function to obtain tokens
     directly.  If you are using Heimdal and obtaining tokens from
     Kerberos tickets, this is the recommended configuration, since it
     means the PAM module doesn't have to fork an external process.  If
     built in the fashion described above, this will be the default unless
     program is set in the module configuration.

   * Otherwise, the module will run an arbitrary external program to
     obtain tokens.  This is the most flexible option, works with MIT
     Kerberos in conjunction with the aklog program from OpenAFS or the
     afslog program from Heimdal, and can support programs that obtain AFS
     tokens via some means other than a Kerberos ticket cache created on
     login.

  For the AFS system call layer, pam-afs-session supports linking with the
  Heimdal libkafs library or the libkopenafs library that will ship with
  later versions of OpenAFS and provides a similar interface.  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,
  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

  If you have Kerberos libraries available and want pam-afs-session to be
  able to read options from krb5.conf, or if you want to use libkafs's
  internal functions for obtaining tokens (recommended if you have it
  available), add the --with-kerberos option to configure (optionally
  followed by the root of your Kerberos installation if krb5-config isn't
  on your PATH).

  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.

  On Solaris, expect a warning about a type mismatch for pam_get_user.
  This warning should be harmless.

  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 configured with --with-kerberos, 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.

 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.

  Note that this is not an authentication module and will always return
  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).

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

 Solaris

  For Solaris console login, add something like:

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

  (all on one line) in /etc/pam.conf.  Note that, on Solaris, if you want
  authentication to first try Kerberos v5 and then fall back to regular
  Unix authentication, you probably cannot include this module in the auth
  stack (for pam_setcred).  Solaris doesn't support the [] keywords that
  Linux PAM does.  However, including it in the session stack should be
  sufficient; most well-behaved applications will open a session as well
  as calling pam-setcred.

  See the man page for pam.conf on Solaris for more configuration
  information.  You may need to add additional lines for graphical login,
  ssh, or for "other" as a catch-all depending on which services you use.

 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 GSSAPI 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 built with Kerberos (--with-kerberos) support, 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).

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 Engart.  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 Engart 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.

LICENSE

  Copyright 2006, 2007 Board of Trustees, Leland Stanford Jr. University.
  All rights reserved.
    
  Permission to use, copy, modify, and distribute this software and its
  documentation for any purpose and without fee is hereby granted,
  provided that the above copyright notice appear in all copies and that
  both that copyright notice and this permission notice appear in
  supporting documentation, and that the name of Stanford University not
  be used in advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.  Stanford
  University makes no representations about the suitability of this
  software for any purpose.  It is provided "as is" without express or
  implied warranty.

  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
