2008/05/07

PAM notes

Much of these notes are taken from the Linux-PAM man page, from http://www.kernel.org/pub/linux/libs/pam/Linux-PAM-html/Linux-PAM_SAG.html, and from http://www.hccfl.edu/pollock/AUnix2/PAM-Help.htm .

Linux PAM (Pluggable Authentication Modules) "is a system of libraries that handle the authentication tasks of applications (services) on the system."

Configuration for individual applications/services may reside in /etc/pam.d . If that directory does not exist, then PAM will look for the single config file /etc/pam.conf . The configuration file(s) define the connection between applications (services) and the pluggable authentication modules (PAMs) that perform the actual authentication tasks.

PAM policy/config file syntax
Each line (rule) in a policy file has 4 parts:
  1. context (service type) - what aspect of the user's request for a restricted service does this line affect?
    1. auth -- (authentication) authenticate a user and set up user credentials. Authentication means that the user proves his identity; typically, this involves entering a password, but it may include a hardware based authentication scheme (e.g., smart card). The setting up of user credentials may include setting up group memberships or other privileges.
    2. account -- (authorization?) -- provide account verification types of service: e.g., has the user's password expired? is this user permitted access to the requested service at this time? Are sufficient system resources available? is this account allowed on the console?
    3. password -- update authentication tokens, for example, "please enter a new password". Typically, there is one module for each challenge/response based auth type.
    4. session -- session setup and cleanup; covers things that should be done prior to a service being given, and after it is withdrawn. For example, leaving audit trails, mounting the user's home dir, or unmounting it after logoff.
  2. control - tells PAM how to handle a "fail" result from a module's authentication task. There are two types of syntax for this control field: the simple one has a single simple keyword; the more complicated one involves a square-bracketed selection of value=action pairs.
    1. For the historical/simple control field, valid values are
      1. required -- "if fail, then ultimately fail, but first finish the remaining stacked modules." failure of such a PAM will ultimately lead to the PAM-API returning a failure after the remaining stacked modules (for this service and type) have been invoked.
      2. requisite -- "if fail, then return to the app now with a failure". like required, but in the case where such a module returns a failure, control is directly returned to the application (without attempting the other stacked modules). The returned value is that associated with the first required or requisite module to fail. This flag may protect, for example, against the possibility of a user getting the opportunity to enter credentials over an unsafe medium; but it may also inform an attacker of valid accounts on a system.
      3. sufficient -- "if a prior required module has not failed, then a success here is good enough to return to the app immediately with success". success of such a module is enough to satisfy the authentication requirements of the stack of modules (if a prior required module has failed, then the success of this one is ignored). A failure of this module is not deemed as fatal to satisfying the application that this type has succeeded. If the module succeeds, the PAM framework returns success to the application immediately, without trying other modules
      4. optional -- the success of this module is only important if it is the only module in the stack associated with this service+type.
      5. include -- include all lines of given type from the configuration file specified as an argument to this control. (On recent RH-based systems, individual application files will tend to include system-auth instead of "other".)
      6. substack -- include all lines of given type from the configuration file specified as an argument to this control. This differs from include in that evaluation of the done and actions in a substack does not cause skipping the rest of the complete module stack, but only of the substack. Jumps in a substack also can not make evaluation jump out of it, and the whole substack is counted as one module when the jump is done in a parent stack. The reset action will reset the state of a module stack to the state it was in as of beginning of the substack evaluation.
  3. module path - the PAM module being called
  4. module arguments (optional) -- options passed to the PAM module. This is a space separated list of tokens that can be used to modify the specific behavior of the given PAM. See individual module documentation for details of that module's options. For arguments that include spaces, surround that argument with square brackets.
In the case where the /etc/pam.conf file is used, an additional service field (e.g. login or su, or other (=default)) appears at the beginning of each line, and describes which service the line applies to.

The lines/modules are run in the order in which they occur in the file. They're passed the module options (if any) and user/request info, and they return a pass/fail (or other) result. The modules are run until an overall pass/fail result is reached, and that result is passed back to the service to which the user has requested access.

Any line in the config file that is not formatted correctly will generally tend to make the authentication process fail.

Errors are written to syslog.

Detail on Control types
  1. For the historical/simple control field, valid values are
    1. required -- failure of such a PAM will ultimately lead to the PAM-API returning a failure after the remaining stacked modules (for this service and type) have been invoked.
    2. requisite -- like required, but in the case where such a module returns a failure, control is directly returned to the application (without attempting the other stacked modules). The returned value is that associated with the first required or requisite module to fail. This flag may protect, for example, against the possibility of a user getting the opportunity to enter credentials over an unsafe medium; but it may also inform an attacker of valid accounts on a system.
    3. sufficient -- success of such a module is enough to satisfy the authentication requirements of the stack of modules (if a prior required module has failed, then the success of this one is ignored). A failure of this module is not deemed as fatal to satisfying the application that this type has succeeded. If the module succeeds, the PAM framework returns success to the application immediately, without trying other modules
    4. optional -- the success of this module is only important if it is the only module in the stack associated with this service+type.
    5. include -- include all lines of given type from the configuration file specified as an argument to this control. (On recent RH-based systems, individual application files will tend to include system-auth instead of "other".)
    6. substack -- include all lines of given type from the configuration file specified as an argument to this control. This differs from include in that evaluation of the done and actions in a substack does not cause skipping the rest of the complete module stack, but only of the substack. Jumps in a substack also can not make evaluation jump out of it, and the whole substack is counted as one module when the jump is done in a parent stack. The reset action will reset the state of a module stack to the state it was in as of beginning of the substack evaluation.
  2. The more complicated syntax is as follows:
    1. valid control values have the following form: [value1=action1 value2=action2 ...]
    2. ...where valueN corresponds to the return code from the function invoked in that module line, and is one of these:
      1. success, open_err, symbol_err, service_err, system_err, buf_err, perm_denied, auth_err, cred_insufficient, authinfo_unavail, user_unknown, maxtries, new_authtok_reqd, acct_expired, session_err, cred_unavail, cred_expired, cred_err, no_module_data, conv_err, authtok_err, authtok_recover_err, authtok_lock_busy, authtok_disable_aging, try_again, ignore, abort, authtok_expired, module_unknown, bad_item, conv_again, incomplete, and default.
    3. ActionN can be either an unsigned integer, n, signifying an action of "jump over the next n modules in the stack', or it can take one of the following forms:
      1. ignore -- when used with a stack of modules, the module's return status will not contribute to the return code the application obtains.
      2. bad -- this action indicates that the return code should be thought of as indicative of the module failing. If this module is the first in the stack to fail, its status value will be used for that of the whole stack.
      3. die -- equivalent to bad, with the side effect of terminating the module stack and PAM , and immediately returning to the application
      4. ok -- this tells PAM that the administrator thinks this return code should contribute directly to the return code of the full stack of modules. IE, if the former state of the stack would lead to a return of PAM_SUCCESS, then the module's return code will override thei value. However, if the former state of the stack holds some value that is indicative of a module's failure, this 'ok' value will not be used to override that data.
      5. done -- equivalent to ok, with the side effect of terminating the module stack and PAM immediately and returning to the application.
      6. reset -- clear all memory of the state of the module stack and start again with the next stacked module.
    4. Each of the four keywords, required, requisite, sufficient, and optional, have an equivalent expression in terms of the [...] syntax as follows:
      1. required -- [success=ok new_authtok=ok ignore=ignore default=bad]
      2. requisite -- [success=ok new_authtok=ok ignore=ignore default=die]
      3. sufficient -- [success=done new_authtok=done default=ignore]
      4. optional -- [success=ok new_authtok_reqd=ok default=ignore]