1100 lines
39 KiB
Text
1100 lines
39 KiB
Text
<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook V4.1-Based Extension//EN" [
|
|
<!ENTITY % man PUBLIC "-//FreeBSD//ENTITIES DocBook Manual Page Entities//EN">
|
|
%man;
|
|
]>
|
|
|
|
<!--
|
|
- Copyright (c) 2001,2002 Networks Associates Technology, Inc.
|
|
- All rights reserved.
|
|
-
|
|
- This software was developed for the FreeBSD Project by ThinkSec AS and
|
|
- Network Associates Laboratories, the Security Research Division of
|
|
- Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
|
|
- ("CBOSS"), as part of the DARPA CHATS research program.
|
|
-
|
|
- Redistribution and use in source and binary forms, with or without
|
|
- modification, are permitted provided that the following conditions
|
|
- are met:
|
|
- 1. Redistributions of source code must retain the above copyright
|
|
- notice, this list of conditions and the following disclaimer.
|
|
- 2. Redistributions in binary form must reproduce the above copyright
|
|
- notice, this list of conditions and the following disclaimer in the
|
|
- documentation and/or other materials provided with the distribution.
|
|
- 3. The name of the author may not be used to endorse or promote
|
|
- products derived from this software without specific prior written
|
|
- permission.
|
|
-
|
|
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- SUCH DAMAGE.
|
|
-->
|
|
|
|
<article>
|
|
<articleinfo>
|
|
<title>Pluggable Authentication Modules</title>
|
|
|
|
<pubdate>$FreeBSD$</pubdate>
|
|
|
|
<abstract>
|
|
<para>This article describes the underlying principles and
|
|
mechanisms of the Pluggable Authentication Modules (PAM)
|
|
library, and explains how to configure PAM, how to integrate
|
|
PAM into applications, and how to write PAM modules.</para>
|
|
</abstract>
|
|
|
|
<copyright>
|
|
<year>2001</year>
|
|
<year>2002</year>
|
|
<holder>Networks Associates Technology, Inc.</holder>
|
|
</copyright>
|
|
|
|
<authorgroup>
|
|
<author>
|
|
<firstname>Dag-Erling</firstname>
|
|
<surname>Smørgrav</surname>
|
|
<contrib>Contributed by </contrib>
|
|
</author>
|
|
</authorgroup>
|
|
|
|
<legalnotice>
|
|
<para>This article was written for the FreeBSD Project by
|
|
ThinkSec AS and Network Associates Laboratories, the Security
|
|
Research Division of Network Associates, Inc. under
|
|
DARPA/SPAWAR contract N66001-01-C-8035 (<quote>CBOSS</quote>),
|
|
as part of the DARPA CHATS research program.</para>
|
|
</legalnotice>
|
|
</articleinfo>
|
|
|
|
<section id="pam-intro">
|
|
<title id="pam-intro.title">Introduction</title>
|
|
|
|
<para>The Pluggable Authentication Modules (PAM) library is a
|
|
generalized API for authentication-related services which allows
|
|
a system administrator to add new authentication methods simply
|
|
by installing new PAM modules, and to modify authentication
|
|
policies by editing configuration files.</para>
|
|
|
|
<para>PAM was defined and developed in 1995 by Vipin Samar and
|
|
Charlie Lai of Sun Microsystems, and has not changed much since.
|
|
In 1997, the Open Group published the X/Open Single Sign-on
|
|
(XSSO) preliminary specification, which standardized the PAM API
|
|
and added extensions for single (or rather integrated) sign-on.
|
|
At the time of this writing, this specification has not yet been
|
|
adopted as a standard.</para>
|
|
|
|
<para>Although this article focuses primarily on FreeBSD 5.x,
|
|
which uses OpenPAM, it should be equally applicable to FreeBSD
|
|
4.x, which uses Linux-PAM, and other operating systems such as
|
|
Linux and Solaris.</para>
|
|
|
|
<section id="pam-trademarks">
|
|
<title id="pam-trademarks.title">Trademarks</title>
|
|
|
|
<para>Sun, Sun Microsystems and Solaris are trademarks or
|
|
registered trademarks of Sun Microsystems, Inc.</para>
|
|
|
|
<para>UNIX and The Open Group are trademarks or registered
|
|
trademarks of The Open Group.</para>
|
|
|
|
<para>All other brand or product names mentioned in this
|
|
document may be trademarks or registered trademarks of their
|
|
respective owners.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="pam-terms">
|
|
<title id="pam-terms.title">Terms and conventions</title>
|
|
|
|
<section id="pam-definitions">
|
|
<title id="pam-definitions.title">Definitions</title>
|
|
|
|
<para>The terminology surrounding PAM is rather confused.
|
|
Neither Samar and Lai's original paper nor the XSSO
|
|
specification made any attempt at formally defining terms for
|
|
the various actors and entities involved in PAM, and the terms
|
|
that they do use (but do not define) are sometimes misleading
|
|
and ambiguous. The first attempt at establishing a consistent
|
|
and unambiguous terminology was a whitepaper written by Andrew
|
|
G. Morgan (author of Linux-PAM) in 1999. While Morgan's
|
|
choice of terminology was a huge leap forward, it is in this
|
|
author's opinion by no means perfect. What follows is an
|
|
attempt, heavily inspired by Morgan, to define precise and
|
|
unambiguous terms for all actors and entities involved in
|
|
PAM.</para>
|
|
|
|
<glosslist>
|
|
<glossentry>
|
|
<glossterm>account</glossterm>
|
|
<glossdef>
|
|
<para>The set of credentials the applicant is requesting
|
|
from the arbitrator.</para>
|
|
</glossdef>
|
|
</glossentry>
|
|
|
|
<glossentry>
|
|
<glossterm>applicant</glossterm>
|
|
<glossdef>
|
|
<para>The user or entity requesting authentication.</para>
|
|
</glossdef>
|
|
</glossentry>
|
|
|
|
<glossentry>
|
|
<glossterm>arbitrator</glossterm>
|
|
<glossdef>
|
|
<para>The user or entity who has the privileges necessary
|
|
to verify the applicant's credentials and the authority
|
|
to grant or deny the request.</para>
|
|
</glossdef>
|
|
</glossentry>
|
|
|
|
<glossentry>
|
|
<glossterm>chain</glossterm>
|
|
<glossdef>
|
|
<para>A sequence of modules that will be invoked in
|
|
response to a PAM request. The chain includes
|
|
information about the order in which to invoke the
|
|
modules, what arguments to pass to them, and how to
|
|
interpret the results.</para>
|
|
</glossdef>
|
|
</glossentry>
|
|
|
|
<glossentry>
|
|
<glossterm>client</glossterm>
|
|
<glossdef>
|
|
<para>The application responsible for initiating an
|
|
authentication request on behalf of the applicant and
|
|
for obtaining the necessary authentication information
|
|
from him.</para>
|
|
</glossdef>
|
|
</glossentry>
|
|
|
|
<glossentry>
|
|
<glossterm>facility</glossterm>
|
|
<glossdef>
|
|
<para>One of the four basic groups of functionality
|
|
provided by PAM: authentication, account management,
|
|
session management and authentication token
|
|
update.</para>
|
|
</glossdef>
|
|
</glossentry>
|
|
|
|
<glossentry>
|
|
<glossterm>module</glossterm>
|
|
<glossdef>
|
|
<para>A collection of one or more related functions
|
|
implementing a particular authentication facility,
|
|
gathered into a single (normally dynamically loadable)
|
|
binary file and identified by a single name.</para>
|
|
</glossdef>
|
|
</glossentry>
|
|
|
|
<glossentry>
|
|
<glossterm>policy</glossterm>
|
|
<glossdef>
|
|
<para>The complete set of configuration statements
|
|
describing how to handle PAM requests for a particular
|
|
service. A policy normally consists of four chains, one
|
|
for each facility, though some services do not use all
|
|
four facilities.</para>
|
|
</glossdef>
|
|
</glossentry>
|
|
|
|
<glossentry>
|
|
<glossterm>server</glossterm>
|
|
<glossdef>
|
|
<para>The application acting on behalf of the arbitrator
|
|
to converse with the client, retrieve authentication
|
|
information, verify the applicant's credentials and
|
|
grant or deny requests.</para>
|
|
</glossdef>
|
|
</glossentry>
|
|
|
|
<glossentry>
|
|
<glossterm>service</glossterm>
|
|
<glossdef>
|
|
<para>A class of servers providing similar or related
|
|
functionality and requiring similar authentication. PAM
|
|
policies are defined on a per-service basis, so all
|
|
servers that claim the same service name will be subject
|
|
to the same policy.</para>
|
|
</glossdef>
|
|
</glossentry>
|
|
|
|
<glossentry>
|
|
<glossterm>session</glossterm>
|
|
<glossdef>
|
|
<para>The context within which service is rendered to the
|
|
applicant by the server. One of PAM's four facilities,
|
|
session management, is concerned exclusively with
|
|
setting up and tearing down this context.</para>
|
|
</glossdef>
|
|
</glossentry>
|
|
|
|
<glossentry>
|
|
<glossterm>token</glossterm>
|
|
<glossdef>
|
|
<para>A chunk of information associated with the account,
|
|
such as a password or passphrase, which the applicant
|
|
must provide to prove his identity.</para>
|
|
</glossdef>
|
|
</glossentry>
|
|
|
|
<glossentry>
|
|
<glossterm>transaction</glossterm>
|
|
<glossdef>
|
|
<para>A sequence of requests from the same applicant to
|
|
the same instance of the same server, beginning with
|
|
authentication and session set-up and ending with
|
|
session tear-down.</para>
|
|
</glossdef>
|
|
</glossentry>
|
|
</glosslist>
|
|
</section>
|
|
|
|
<section id="pam-usage-examples">
|
|
<title id="pam-usage-examples.title">Usage examples</title>
|
|
|
|
<para>This section aims to illustrate the meanings of some of
|
|
the terms defined above by way of a handful of simple
|
|
examples.</para>
|
|
|
|
<section>
|
|
<title>Client and server are one</title>
|
|
|
|
<para>This simple example shows <literal>alice</literal>
|
|
&man.su.1;'ing to <literal>root</literal>.</para>
|
|
|
|
<screen>&prompt.user; <userinput>whoami</userinput>
|
|
alice
|
|
&prompt.user; <userinput>ls -l `which su`</userinput>
|
|
-r-sr-xr-x 1 root wheel 10744 Dec 6 19:06 /usr/bin/su
|
|
&prompt.user; <userinput>su -</userinput>
|
|
Password: <userinput>xi3kiune</userinput>
|
|
&prompt.root; whoami
|
|
root
|
|
</screen>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>The applicant is <literal>alice</literal>.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>The account is <literal>root</literal>.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>The &man.su.1; process is both client and
|
|
server.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>The authentication token is
|
|
<literal>xi3kiune</literal>.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>The arbitrator is <literal>root</literal>, which is
|
|
why &man.su.1; is setuid <literal>root</literal>.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Client and server are separate</title>
|
|
|
|
<para>The example below shows <literal>eve</literal> try to
|
|
initiate an &man.ssh.1; connection to
|
|
<literal>login.example.com</literal>, ask to log in as
|
|
<literal>bob</literal>, and succeed. Bob should have chosen
|
|
a better password!</para>
|
|
|
|
<screen>&prompt.user; <userinput>whoami</userinput>
|
|
eve
|
|
&prompt.user; <userinput>ssh bob@login.example.com</userinput>
|
|
bob@login.example.com's password: <userinput>god</userinput>
|
|
Last login: Thu Oct 11 09:52:57 2001 from 192.168.0.1
|
|
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
|
|
The Regents of the University of California. All rights reserved.
|
|
FreeBSD 4.4-STABLE (LOGIN) #4: Tue Nov 27 18:10:34 PST 2001
|
|
|
|
Welcome to FreeBSD!
|
|
&prompt.user;</screen>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>The applicant is <literal>eve</literal>.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>The client is Eve's &man.ssh.1; process.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>The server is the &man.sshd.8; process on
|
|
<literal>login.example.com</literal></para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>The account is <literal>bob</literal>.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>The authentication token is
|
|
<literal>god</literal>.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Although this is not shown in this example, the
|
|
arbitrator is <literal>root</literal>.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Sample policy</title>
|
|
|
|
<para>The following is FreeBSD's default policy for
|
|
<literal>sshd</literal>:</para>
|
|
|
|
<programlisting>sshd auth required pam_nologin.so no_warn
|
|
sshd auth required pam_unix.so no_warn try_first_pass
|
|
sshd account required pam_login_access.so
|
|
sshd account required pam_unix.so
|
|
sshd session required pam_lastlog.so no_fail
|
|
sshd password required pam_permit.so</programlisting>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>This policy applies to the <literal>sshd</literal>
|
|
service (which is not necessarily restricted to the
|
|
&man.sshd.8; server.)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><literal>auth</literal>, <literal>account</literal>,
|
|
<literal>session</literal> and
|
|
<literal>password</literal> are facilities.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><filename>pam_nologin.so</filename>,
|
|
<filename>pam_unix.so</filename>,
|
|
<filename>pam_login_access.so</filename>,
|
|
<filename>pam_lastlog.so</filename> and
|
|
<filename>pam_permit.so</filename> are modules. It is
|
|
clear from this example that
|
|
<filename>pam_unix.so</filename> provides at least two
|
|
facilities (authentication and account
|
|
management.)</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="pam-conventions">
|
|
<title id="pam-conventions.title">Conventions</title>
|
|
|
|
<para><!--XXX-->This section has not yet been written.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="pam-essentials">
|
|
<title id="pam-essentials.title">PAM Essentials</title>
|
|
|
|
<section id="pam-facilities-primitives">
|
|
<title id="pam-facilities-primitives.title">Facilities and
|
|
primitives</title>
|
|
|
|
<para>The PAM API offers six different authentication primitives
|
|
grouped in four facilities, which are described below.</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>auth</literal></term>
|
|
<listitem>
|
|
<para><emphasis>Authentication.</emphasis> This facility
|
|
concerns itself with authenticating the applicant and
|
|
establishing the account credentials. It provides two
|
|
primitives:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>&man.pam.authenticate.3; authenticates the
|
|
applicant, usually by requesting an authentication
|
|
token and comparing it with a value stored in a
|
|
database or obtained from an authentication
|
|
server.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>&man.pam.setcred.3; establishes account
|
|
credentials such as user ID, group membership and
|
|
resource limits.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>account</literal></term>
|
|
<listitem>
|
|
<para><emphasis>Account management.</emphasis> This
|
|
facility handles non-authentication-related issues of
|
|
account availability, such as access restrictions based
|
|
on the time of day or the server's work load. It
|
|
provides a single primitive:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>&man.pam.acct.mgmt.3; verifies that the
|
|
requested account is available.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>session</literal></term>
|
|
<listitem>
|
|
<para><emphasis>Session management.</emphasis> This
|
|
facility handles tasks associated with session set-up
|
|
and tear-down, such as login accounting. It provides
|
|
two primitives:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>&man.pam.open.session.3; performs tasks
|
|
associated with session set-up: add an entry in the
|
|
<filename>utmp</filename> and
|
|
<filename>wtmp</filename> databases, start an SSH
|
|
agent, etc.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>&man.pam.close.session.3; performs tasks
|
|
associated with session tear-down: add an entry in
|
|
the <filename>utmp</filename> and
|
|
<filename>wtmp</filename> databases, stop the SSH
|
|
agent, etc.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>password</literal></term>
|
|
<listitem>
|
|
<para><emphasis>Password management.</emphasis> This
|
|
facility is used to change the authentication token
|
|
associated with an account, either because it has
|
|
expired or because the user wishes to change it. It
|
|
provides a single primitive:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>&man.pam.chauthtok.3; changes the authentication
|
|
token, optionally verifying that it is sufficiently
|
|
hard to guess, has not been used previously,
|
|
etc.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
</section>
|
|
|
|
<section id="pam-modules">
|
|
<title id="pam-modules.title">Modules</title>
|
|
|
|
<para>Modules are a very central concept in PAM; after all,
|
|
they are the <quote>M</quote> in <quote>PAM</quote>. A PAM
|
|
module is a self-contained piece of program code that
|
|
implements the primitives in one or more facilities for one
|
|
particular mechanism; possible mechanisms for the
|
|
authentication facility, for instance, include the UNIX
|
|
password database, NIS, LDAP and Radius.</para>
|
|
|
|
<section id="pam-module-naming">
|
|
<title id="pam-module-naming.title">Module Naming</title>
|
|
|
|
<para>FreeBSD implements each mechanism in a single module,
|
|
named
|
|
<literal>pam_<replaceable>mechanism</replaceable>.so</literal>
|
|
(for instance, <literal>pam_unix.so</literal> for the Unix
|
|
mechanism.) Other implementations sometimes have separate
|
|
modules for separate facilities, and include the facility
|
|
name as well as the mechanism name in the module name. To
|
|
name one example, Solaris has a
|
|
<literal>pam_dial_auth.so.1</literal> module which is
|
|
commonly used to authenticate dialup users.</para>
|
|
</section>
|
|
|
|
<section id="pam-module-versioning">
|
|
<title id="pam-module-versioning.title">Module Versioning</title>
|
|
|
|
<para>FreeBSD's original PAM implementation, based on
|
|
Linux-PAM, did not use version numbers for PAM modules.
|
|
This would commonly cause problems with legacy applications,
|
|
which might be linked against older versions of the system
|
|
libraries, as there was no way to load a matching version of
|
|
the required modules.</para>
|
|
|
|
<para>OpenPAM, on the other hand, looks for modules that have
|
|
the same version number as the PAM library (currently 2),
|
|
and only falls back to an unversioned module if no versioned
|
|
module could be loaded. Thus legacy modules can be provided
|
|
for legacy applications, while allowing new (or newly built)
|
|
applications to take advantage of the most recent
|
|
modules.</para>
|
|
|
|
<para>Although Solaris PAM modules commonly have a version
|
|
number, they're not truly versioned, because the number is a
|
|
part of the module name and must be included in the
|
|
configuration.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="pam-chains-policies">
|
|
<title id="pam-chains-policies.title">Chains and
|
|
policies</title>
|
|
|
|
<para>When a server initiates a PAM transaction, the PAM library
|
|
tries to load a policy for the service specified in the
|
|
&man.pam.start.3; call. The policy specifies how
|
|
authentication requests should be processed, and is defined in
|
|
a configuration file. This is the other central concept in
|
|
PAM: the possibility for the admin to tune the system security
|
|
policy (in the wider sense of the word) simply by editing a
|
|
text file.</para>
|
|
|
|
<para>A policy consists of four chains, one for each of the four
|
|
PAM facilities. Each chain is a sequence of configuration
|
|
statements, each specifying a module to invoke, some
|
|
(optional) parameters to pass to the module, and a control
|
|
flag that describes how to interpret the return code from the
|
|
module.</para>
|
|
|
|
<para>Understanding the control flags is essential to
|
|
understanding PAM configuration files. There are four
|
|
different control flags:</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>required</literal></term>
|
|
<listitem>
|
|
<para>Success is required, but the chain continues no
|
|
matter what this module returns, so that later modules
|
|
can override it.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>requisite</literal></term>
|
|
<listitem>
|
|
<para>A negative result from this module will immediately
|
|
terminate the chain and deny the request.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>sufficient</literal></term>
|
|
<listitem>
|
|
<para>A positive result from this module will immediately
|
|
terminate the chain and grant the request. On failure,
|
|
the chain continues.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>optional</literal></term>
|
|
<listitem>
|
|
<para>A negative result from this module will be
|
|
ignored.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
<para>When a server invokes one of the six PAM primitives, PAM
|
|
retrieves the chain for the facility the primitive belongs to,
|
|
and invokes each of the modules listed in the chain, in the
|
|
order they are listed, until it reaches the end, or determines
|
|
that no further processing is necessary (either because a
|
|
<literal>sufficient</literal> module succeeded, or because a
|
|
<literal>requisite</literal> module failed.) The request is
|
|
granted if and only if at least one module was invoked, and
|
|
all non-optional modules succeeded.</para>
|
|
|
|
<para>Note that it is possible, though not very common, to have
|
|
the same module listed several times in the same chain. For
|
|
instance, a module that looks up user names and passwords in a
|
|
directory server could be invoked multiple times with
|
|
different parameters specifying different directory servers to
|
|
contact. PAM treat different occurrences of the same module
|
|
in the same chain as different, unrelated modules.</para>
|
|
</section>
|
|
|
|
<section id="pam-transactions">
|
|
<title id="pam-transactions.title">Transactions</title>
|
|
|
|
<para>The lifecycle of a typical PAM transaction is described
|
|
below. Note that if any of these steps fails, the server
|
|
should report a suitable error message to the client and abort
|
|
the transaction.</para>
|
|
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>If necessary, the server obtains arbitrator
|
|
credentials through a mechanism independent of
|
|
PAM—most commonly by virtue of having been started
|
|
by <literal>root</literal>, or of being setuid
|
|
<literal>root</literal>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The server calls &man.pam.start.3; to initialize the
|
|
PAM library and specify its service name and the target
|
|
account, and register a suitable conversation
|
|
function.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The server obtains various information relating to the
|
|
transaction (such as the applicant's user name and the
|
|
name of the host the client runs on) and submits it to PAM
|
|
using &man.pam.set.item.3;.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The server calls &man.pam.authenticate.3; to
|
|
authenticate the applicant.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The server calls &man.pam.acct.mgmt.3; to verify that the
|
|
requested account is available and valid. If the password
|
|
is correct but has expired, &man.pam.acct.mgmt.3; will
|
|
return <literal>PAM_NEW_AUTHTOK_REQD</literal> instead of
|
|
<literal>PAM_SUCCESS</literal>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>If the previous step returned
|
|
<literal>PAM_NEW_AUTHTOK_REQD</literal>, the server now
|
|
calls &man.pam.chauthtok.3; to force the client to change
|
|
the authentication token for the requested account.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Now that the applicant has been properly
|
|
authenticated, the server calls &man.pam.setcred.3; to
|
|
establish the credentials of the requested account. It is
|
|
able to do this because it acts on behalf of the
|
|
arbitrator, and holds the arbitrator's credentials.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Once the correct credentials have been established,
|
|
the server calls &man.pam.open.session.3; to set up the
|
|
session.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The server now performs whatever service the client
|
|
requested—for instance, provide the applicant with a
|
|
shell.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Once the server is done serving the client, it calls
|
|
&man.pam.close.session.3; to tear down the session.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Finally, the server calls &man.pam.end.3; to notify
|
|
the PAM library that it is done and that it can release
|
|
whatever resources it has allocated in the course of the
|
|
transaction.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="pam-config">
|
|
<title id="pam-config.title">PAM Configuration</title>
|
|
|
|
<section id="pam-config-file-locations">
|
|
<title id="pam-config-file-locations.title">Location of
|
|
configuration files</title>
|
|
|
|
<para>The traditional PAM configuration file is
|
|
<filename>/etc/pam.conf</filename>. This file contains all
|
|
the PAM policies for your system. Each line of the file
|
|
describes one step in a chain, as shown below:</para>
|
|
|
|
<programlisting>login auth required pam_nologin.so no_warn</programlisting>
|
|
|
|
<para>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.</para>
|
|
|
|
<para>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—except that entries for the <literal>other</literal>
|
|
service, which serves as a fall-back, should come last. The
|
|
examples in the original PAM paper grouped configuration lines
|
|
by facility, and Solaris' stock <filename>pam.conf</filename>
|
|
still does that, but FreeBSD's stock configuration groups
|
|
configuration lines by service. Either way is fine; either
|
|
way makes equal sense.</para>
|
|
|
|
<para>OpenPAM and Linux-PAM offer an alternate configuration
|
|
mechanism, where policies are contained in separate files,
|
|
named for the service they apply to, in
|
|
<filename>/etc/pam.d/</filename>, with only four fields
|
|
instead of five—the service name field is omitted. This
|
|
is the preferred mechanism in FreeBSD 5.x. Note, however,
|
|
that if <filename>/etc/pam.conf</filename> exists, and
|
|
contains configuration statements for services which do not
|
|
have a specific policy in <filename>/etc/pam.d/</filename>, it
|
|
will be used as a fall-back for these services.</para>
|
|
|
|
<para>The great advantage of <filename>/etc/pam.d/</filename>
|
|
over <filename>/etc/pam.conf</filename> is that 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 <literal>su</literal> and
|
|
<literal>sudo</literal> services, one could do as
|
|
follows:</para>
|
|
|
|
<screen>&prompt.root; <userinput>cd /etc/pam.d</userinput>
|
|
&prompt.root; <userinput>ln -s su sudo</userinput></screen>
|
|
|
|
<para>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.</para>
|
|
|
|
<para>One other advantage is that third-party software can
|
|
easily install policies for their services without the need to
|
|
edit <filename>/etc/pam.conf</filename>. True to the FreeBSD
|
|
tradition, OpenPAM will even look for policy files in
|
|
<filename>/usr/local/etc/pam.d/</filename> if no configuration
|
|
for the requested service is present in
|
|
<filename>/etc/pam.d/</filename> or
|
|
<filename>/etc/pam.conf</filename>.</para>
|
|
|
|
<para>Finally, whichever configuration mechanism you choose, the
|
|
<quote>magic</quote> policy <literal>other</literal> is used
|
|
as a fall-back for any service that does not have its own
|
|
policy.</para>
|
|
</section>
|
|
|
|
<section id="pam-config-breakdown">
|
|
<title id="pam-config-breakdown.title">Breakdown of a
|
|
configuration line</title>
|
|
|
|
<para>As explained in the <link
|
|
linkend="pam-config-file-locations"
|
|
endterm="pam-config-file-locations.title"></link> section,
|
|
each line in <filename>/etc/pam.conf</filename> consists of
|
|
four or more fields: the service name, the facility name, the
|
|
control flag, the module name, and zero or more module
|
|
arguments.</para>
|
|
|
|
<para>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.</para>
|
|
|
|
<para>Note that if you use <filename>/etc/pam.d/</filename>
|
|
instead of <filename>/etc/pam.conf</filename>, 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.</para>
|
|
|
|
<para>The facility is one of the four facility keywords
|
|
described in the <link linkend="pam-facilities-primitives"
|
|
endterm="pam-facilities-primitives.title"></link>
|
|
section.</para>
|
|
|
|
<para>Likewise, the control flag is one of the four keywords
|
|
described in the <link linkend="pam-chains-policies"
|
|
endterm="pam-chains-policies.title"></link> section,
|
|
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.</para>
|
|
</section>
|
|
|
|
<section id="pam-policies">
|
|
<title id="pam-policies.title">Policies</title>
|
|
|
|
<para>To configure PAM correctly, it is essential to understand
|
|
how chains are executed.</para>
|
|
|
|
<para>When an application calls &man.pam.start.3;, the PAM
|
|
library loads the configuration for the specified service and
|
|
constructs four module chains (one for each facility.) If the
|
|
configuration does not specify any modules for one or more
|
|
facilities, the configuration for the <literal>other</literal>
|
|
service is used instead for these facilities.</para>
|
|
|
|
<para>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 will discuss
|
|
later, the following table applies:</para>
|
|
|
|
<table>
|
|
<title>PAM chain execution summary</title>
|
|
<tgroup cols="4">
|
|
<colspec colwidth="1*" colname="type">
|
|
<colspec colwidth="1*" colname="success">
|
|
<colspec colwidth="1*" colname="ignore">
|
|
<colspec colwidth="1*" colname="other">
|
|
<thead>
|
|
<row>
|
|
<entry colname="type"></entry>
|
|
<entry colname="success"><literal>PAM_SUCCESS</literal></entry>
|
|
<entry colname="ignore"><literal>PAM_IGNORE</literal></entry>
|
|
<entry colname="other"><literal>other</literal></entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry colname="type">required</entry>
|
|
<entry colname="success">-</entry>
|
|
<entry colname="ignore">-</entry>
|
|
<entry colname="other">fail = true</entry>
|
|
</row>
|
|
<row>
|
|
<entry colname="type">requisite</entry>
|
|
<entry colname="success">-</entry>
|
|
<entry colname="ignore">-</entry>
|
|
<entry colname="other">fail = true, break</entry>
|
|
</row>
|
|
<row>
|
|
<entry colname="type">sufficient</entry>
|
|
<entry colname="success">if (!fail) break</entry>
|
|
<entry colname="ignore">-</entry>
|
|
<entry colname="other">fail = true</entry>
|
|
</row>
|
|
<row>
|
|
<entry colname="type">optional</entry>
|
|
<entry colname="success">-</entry>
|
|
<entry colname="ignore">-</entry>
|
|
<entry colname="other">-</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>If <varname>fail</varname> is true at the end of a chain,
|
|
or when a <quote>break</quote> is reached, the dispatcher
|
|
returns the error code returned by the first module that
|
|
failed. Otherwise, it returns
|
|
<literal>PAM_SUCCESS</literal>.</para>
|
|
|
|
<para>The first exception of note is that the error code
|
|
<literal>PAM_NEW_AUTHTOK_REQD</literal> is treated like a
|
|
success, except that if no module failed, and at least one
|
|
module returned <literal>PAM_NEW_AUTHTOK_REQD</literal>, the
|
|
dispatcher will return
|
|
<literal>PAM_NEW_AUTHTOK_REQD</literal>.</para>
|
|
|
|
<para>The second exception is that &man.pam.setcred.3; treats
|
|
<literal>sufficient</literal> modules as if they were
|
|
<literal>required</literal>.</para>
|
|
|
|
<para>The third and final exception is that
|
|
&man.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
|
|
<literal>sufficient</literal> modules as if they were
|
|
<literal>required</literal>.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="pam-freebsd-modules">
|
|
<title id="pam-freebsd-modules.title">FreeBSD PAM Modules</title>
|
|
|
|
<para><!--XXX-->This section has not yet been written.</para>
|
|
</section>
|
|
|
|
<section id="pam-appl-prog">
|
|
<title id="pam-appl-prog.title">PAM Application Programming</title>
|
|
|
|
<para><!--XXX-->This section has not yet been written.</para>
|
|
|
|
<!--
|
|
|
|
Note that while the original PAM paper includes a sample PAM
|
|
application that calls pam_open_session() before pam_setcred(),
|
|
the Linux-PAM documentation states that pam_setcred() must be
|
|
called first, which makes more sense.
|
|
|
|
Also note that the example in the paper calls setgid(),
|
|
initgroups() and setuid() itself rather than rely on
|
|
pam_setcred() to do it.
|
|
|
|
-->
|
|
|
|
</section>
|
|
|
|
<section id="pam-module-prog">
|
|
<title id="pam-module-prog.title">PAM Module Programming</title>
|
|
|
|
<para><!--XXX-->This section has not yet been written.</para>
|
|
</section>
|
|
|
|
<appendix id="pam-sample-appl">
|
|
<title id="pam-sample-appl.title">Sample PAM Application</title>
|
|
|
|
<para>The following is a minimal implementation of &man.su.1;
|
|
using PAM. Note that it uses the OpenPAM-specific
|
|
&man.openpam.ttyconv.3; conversation function, which is
|
|
prototyped in <filename
|
|
class="headerfile">security/openpam.h</filename>. If you wish
|
|
build this application on a system with a different PAM library,
|
|
you will have to provide your own conversation function. A
|
|
robust conversation function is surprisingly difficult to
|
|
implement; the one presented in the <link
|
|
linkend="pam-sample-conv"
|
|
endterm="pam-sample-conv.title"></link> appendix is a good
|
|
starting point, but should not be used in real-world
|
|
applications.</para>
|
|
|
|
<programlisting><inlinegraphic fileref="pam_app.c"
|
|
format="linespecific"></programlisting>
|
|
</appendix>
|
|
|
|
<appendix id="pam-sample-module">
|
|
<title id="pam-sample-module.title">Sample PAM Module</title>
|
|
|
|
<para>The following is a minimal implementation of
|
|
&man.pam.unix.8;, offering only authentication services. It
|
|
should build and run with most PAM implementations, but takes
|
|
advantage of OpenPAM extensions if available: note the use of
|
|
&man.pam.get.authtok.3;, which enormously simplifies prompting
|
|
the user for a password.</para>
|
|
|
|
<programlisting><inlinegraphic fileref="pam_module.c"
|
|
format="linespecific"></programlisting>
|
|
</appendix>
|
|
|
|
<appendix id="pam-sample-conv">
|
|
<title id="pam-sample-conv.title">Sample PAM Conversation
|
|
Function</title>
|
|
|
|
<para>The conversation function presented below is a greatly
|
|
simplified version of OpenPAM's &man.openpam.ttyconv.3;. It is
|
|
fully functional, and should give the reader a good idea of how
|
|
a conversation function should behave, but it is far too simple
|
|
for real-world use. Even if you're not using OpenPAM, feel free
|
|
to download the source code and adapt &man.openpam.ttyconv.3; to
|
|
your uses; we believe it to be as robust as a tty-oriented
|
|
conversation function can reasonably get.</para>
|
|
|
|
<programlisting><inlinegraphic fileref="pam_conv.c"
|
|
format="linespecific"></programlisting>
|
|
</appendix>
|
|
|
|
<bibliography id="pam-further">
|
|
<title id="pam-further.title">Further Reading</title>
|
|
|
|
<abstract>
|
|
<para>This is a list of documents relevant to PAM and related
|
|
issues. It is by no means complete.</para>
|
|
</abstract>
|
|
|
|
<bibliodiv>
|
|
<title>Papers</title>
|
|
|
|
<biblioentry>
|
|
<title><ulink
|
|
url="http://www.sun.com/software/solaris/pam/pam.external.pdf">
|
|
Making Login Services Independent of Authentication
|
|
Technologies</ulink></title>
|
|
<authorgroup>
|
|
<author>
|
|
<surname>Samar</surname>
|
|
<firstname>Vipin</firstname>
|
|
</author>
|
|
<author>
|
|
<surname>Lai</surname>
|
|
<firstname>Charlie</firstname>
|
|
</author>
|
|
</authorgroup>
|
|
<orgname>Sun Microsystems</orgname>
|
|
</biblioentry>
|
|
|
|
<biblioentry>
|
|
<title><ulink
|
|
url="http://www.opengroup.org/pubs/catalog/p702.htm">X/Open
|
|
Single Sign-on Preliminary Specification</ulink></title>
|
|
<orgname>The Open Group</orgname>
|
|
<isbn>1-85912-144-6</isbn>
|
|
<pubdate>June 1997</pubdate>
|
|
</biblioentry>
|
|
|
|
<biblioentry>
|
|
<title><ulink
|
|
url="http://www.kernel.org/pub/linux/libs/pam/pre/doc/current-draft.txt">
|
|
Pluggable Authentication Modules</ulink></title>
|
|
<author>
|
|
<surname>Morgan</surname>
|
|
<firstname>Andrew</firstname>
|
|
<othername role="mi">G.</othername>
|
|
</author>
|
|
<pubdate>October 6, 1999</pubdate>
|
|
</biblioentry>
|
|
</bibliodiv>
|
|
|
|
<bibliodiv>
|
|
<title>User Manuals</title>
|
|
|
|
<biblioentry>
|
|
<title><ulink
|
|
url="http://www.sun.com/software/solaris/pam/pam.admin.pdf">PAM
|
|
Administration</ulink></title>
|
|
<orgname>Sun Microsystems</orgname>
|
|
</biblioentry>
|
|
</bibliodiv>
|
|
|
|
<bibliodiv>
|
|
<title>Related Web pages</title>
|
|
|
|
<biblioentry>
|
|
<title><ulink url="http://openpam.sourceforge.net/">OpenPAM homepage</ulink></title>
|
|
<author>
|
|
<surname>Smørgrav</surname>
|
|
<firstname>Dag-Erling</firstname>
|
|
</author>
|
|
<orgname>ThinkSec AS</orgname>
|
|
</biblioentry>
|
|
|
|
<biblioentry>
|
|
<title><ulink url="http://www.kernel.org/pub/linux/libs/pam/">Linux-PAM homepage</ulink></title>
|
|
<author>
|
|
<surname>Morgan</surname>
|
|
<firstname>Andrew</firstname>
|
|
<othername role="mi">G.</othername>
|
|
</author>
|
|
</biblioentry>
|
|
|
|
<biblioentry>
|
|
<title><ulink url="http://wwws.sun.com/software/solaris/pam/">Solaris PAM homepage</ulink></title>
|
|
<orgname>Sun Microsystems</orgname>
|
|
</biblioentry>
|
|
</bibliodiv>
|
|
</bibliography>
|
|
</article>
|