The traditional PAM policy file is
/etc/pam.conf
. This file contains all
the PAM policies for your system. Each line of the file
describes one step in a chain, as shown below:
login auth required pam_nologin.so no_warn
The fields are, in order: service name, facility name, control flag, module name, and module arguments. Any additional fields are interpreted as additional module arguments.
A separate chain is constructed for each service /
facility pair, so while the order in which lines for the
same service and facility appear is significant, the order
in which the individual services and facilities are listed
is not. The examples in the original PAM paper grouped
configuration lines by facility, and the Solaris™ stock
pam.conf
still does that, but FreeBSD's
stock configuration groups configuration lines by service.
Either way is fine; either way makes equal sense.
OpenPAM and Linux-PAM support an alternate configuration
mechanism, which is the preferred mechanism in FreeBSD. In
this scheme, each policy is contained in a separate file
bearing the name of the service it applies to. These files
are stored in /etc/pam.d/
.
These per-service policy files have only four fields
instead of pam.conf
's five: the service
name field is omitted. Thus, instead of the sample
pam.conf
line from the previous
section, one would have the following line in
/etc/pam.d/login
:
auth required pam_nologin.so no_warn
As a consequence of this simplified syntax, it is
possible to use the same policy for multiple services by
linking each service name to a same policy file. For
instance, to use the same policy for the
su
and sudo
services,
one could do as follows:
#
cd /etc/pam.d
#
ln -s su sudo
This works because the service name is determined from the file name rather than specified in the policy file, so the same file can be used for multiple differently-named services.
Since each service's policy is stored in a separate
file, the pam.d
mechanism also makes it
very easy to install additional policies for third-party
software packages.
As explained in Section 4.1, “PAM policy files”, each line in
/etc/pam.conf
consists of four or more
fields: the service name, the facility name, the control flag,
the module name, and zero or more module arguments.
The service name is generally (though not always) the name of the application the statement applies to. If you are unsure, refer to the individual application's documentation to determine what service name it uses.
Note that if you use /etc/pam.d/
instead of /etc/pam.conf
, the service
name is specified by the name of the policy file, and omitted
from the actual configuration lines, which then start with the
facility name.
The facility is one of the four facility keywords described in Section 3.1, “Facilities and primitives”.
Likewise, the control flag is one of the four keywords described in Section 3.3, “Chains and policies”, describing how to interpret the return code from the module. Linux-PAM supports an alternate syntax that lets you specify the action to associate with each possible return code, but this should be avoided as it is non-standard and closely tied in with the way Linux-PAM dispatches service calls (which differs greatly from the way Solaris™ and OpenPAM do it.) Unsurprisingly, OpenPAM does not support this syntax.
To configure PAM correctly, it is essential to understand how policies are interpreted.
When an application calls pam_start(3), the PAM
library loads the policy for the specified service and
constructs four module chains (one for each facility.) If one
or more of these chains are empty, the corresponding chains
from the policy for the other
service are
substituted.
When the application later calls one of the six PAM primitives, the PAM library retrieves the chain for the corresponding facility and calls the appropriate service function in each module listed in the chain, in the order in which they were listed in the configuration. After each call to a service function, the module type and the error code returned by the service function are used to determine what happens next. With a few exceptions, which we discuss below, the following table applies:
PAM_SUCCESS | PAM_IGNORE | other | |
---|---|---|---|
binding | if (!fail) break; | - | fail = true; |
required | - | - | fail = true; |
requisite | - | - | fail = true; break; |
sufficient | if (!fail) break; | - | - |
optional | - | - | - |
If fail
is true at the end of a chain,
or when a “break” is reached, the dispatcher
returns the error code returned by the first module that
failed. Otherwise, it returns
PAM_SUCCESS
.
The first exception of note is that the error code
PAM_NEW_AUTHTOK_REQD
is treated like a
success, except that if no module failed, and at least one
module returned PAM_NEW_AUTHTOK_REQD
, the
dispatcher will return
PAM_NEW_AUTHTOK_REQD
.
The second exception is that pam_setcred(3) treats
binding
and
sufficient
modules as if they were
required
.
The third and final exception is that
pam_chauthtok(3) runs the entire chain twice (once for
preliminary checks and once to actually set the password), and
in the preliminary phase it treats
binding
and
sufficient
modules as if they were
required
.
All FreeBSD documents are available for download at http://ftp.FreeBSD.org/pub/FreeBSD/doc/
Questions that are not answered by the
documentation may be
sent to <[email protected]>.
Send questions about this document to <[email protected]>.