1126 lines
44 KiB
Plaintext
1126 lines
44 KiB
Plaintext
<!doctype linuxdoc system>
|
|
|
|
<!--
|
|
|
|
$Id: pam_source.sgml,v 1.5 2001/03/19 01:46:41 agmorgan Exp $
|
|
|
|
Copyright (c) Andrew G. Morgan 1996-2001. All rights reserved.
|
|
|
|
Redistribution and use in source (sgml) and binary (derived) 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, and the entire permission notice in its entirety,
|
|
including the disclaimer of warranties.
|
|
|
|
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.
|
|
|
|
ALTERNATIVELY, this product may be distributed under the terms of the
|
|
GNU General Public License, in which case the provisions of the GNU
|
|
GPL are required INSTEAD OF the above restrictions. (This clause is
|
|
necessary due to a potential bad interaction between the GNU GPL and
|
|
the restrictions contained in a BSD-style copyright.)
|
|
|
|
THIS SOFTWARE IS PROVIDED ``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 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>
|
|
|
|
<title>The Linux-PAM System Administrators' Guide
|
|
<author>Andrew G. Morgan, <tt>morgan@kernel.org</tt>
|
|
<date>DRAFT v0.75 2001/03/18
|
|
<abstract>
|
|
This manual documents what a system-administrator needs to know about
|
|
the <bf>Linux-PAM</bf> library. It covers the correct syntax of the
|
|
PAM configuration file and discusses strategies for maintaining a
|
|
secure system.
|
|
</abstract>
|
|
|
|
<!-- Table of contents -->
|
|
<toc>
|
|
|
|
<!-- Begin the document -->
|
|
|
|
<sect>Introduction
|
|
|
|
<p><bf/Linux-PAM/ (Pluggable Authentication Modules for Linux) is a
|
|
suite of shared libraries that enable the local system administrator
|
|
to choose how applications authenticate users.
|
|
|
|
<p>In other words, without (rewriting and) recompiling a PAM-aware
|
|
application, it is possible to switch between the authentication
|
|
mechanism(s) it uses. Indeed, one may entirely upgrade the local
|
|
authentication system without touching the applications themselves.
|
|
|
|
<p>Historically an application that has required a given user to be
|
|
authenticated, has had to be compiled to use a specific authentication
|
|
mechanism. For example, in the case of traditional UN*X systems, the
|
|
identity of the user is verified by the user entering a correct
|
|
password. This password, after being prefixed by a two character
|
|
``salt'', is encrypted (with crypt(3)). The user is then authenticated
|
|
if this encrypted password is identical to the second field of the
|
|
user's entry in the system password database (the <tt>/etc/passwd</tt>
|
|
file). On such systems, most if not all forms of privileges are
|
|
granted based on this single authentication scheme. Privilege comes in
|
|
the form of a personal user-identifier (<tt/uid/) and membership of
|
|
various groups. Services and applications are available based on the
|
|
personal and group identity of the user. Traditionally, group
|
|
membership has been assigned based on entries in the
|
|
<tt>/etc/group</tt> file.
|
|
|
|
<p>
|
|
Unfortunately, increases in the speed of computers and the
|
|
widespread introduction of network based computing, have made once
|
|
secure authentication mechanisms, such as this, vulnerable to
|
|
attack. In the light of such realities, new methods of authentication
|
|
are continuously being developed.
|
|
|
|
<p>
|
|
It is the purpose of the <bf/Linux-PAM/ project to separate the
|
|
development of privilege granting software from the development of
|
|
secure and appropriate authentication schemes. This is accomplished
|
|
by providing a library of functions that an application may use to
|
|
request that a user be authenticated. This PAM library is configured
|
|
locally with a system file, <tt>/etc/pam.conf</tt> (or a series of
|
|
configuration files located in <tt>/etc/pam.d/</tt>) to authenticate a
|
|
user request via the locally available authentication modules. The
|
|
modules themselves will usually be located in the directory
|
|
<tt>/usr/lib/security</tt> and take the form of dynamically loadable
|
|
object files (see <tt/dlopen(3)/).
|
|
|
|
<sect>Some comments on the text<label id="text-conventions">
|
|
|
|
<p>
|
|
Before proceeding to read the rest of this document, it should be
|
|
noted that the text assumes that certain files are placed in certain
|
|
directories. Where they have been specified, the conventions we adopt
|
|
here for locating these files are those of the relevant RFC (RFC-86.0,
|
|
see <ref id="see-also-sec" name="bibliography">). If you are using a
|
|
distribution of Linux (or some other operating system) that supports
|
|
PAM but chooses to distribute these files in a diferent way (Red Hat
|
|
is one such distribution), you should be careful when copying examples
|
|
directly from the text.
|
|
|
|
<p>
|
|
As an example of the above, where it is explicit, the text assumes
|
|
that PAM loadable object files (the <em/modules/) are to be located in
|
|
the following directory: <tt>/usr/lib/security/</tt>. However, Red Hat
|
|
Linux, in agreement with the Linux File System Standard (the FSSTND),
|
|
places these files in <tt>/lib/security</tt>. Please be careful to
|
|
perform the necessary transcription when using the examples from the
|
|
text.
|
|
|
|
<sect>Overview<label id="overview-section">
|
|
|
|
<p>
|
|
For the uninitiated, we begin by considering an example. We take an
|
|
application that grants some service to users; <em/login/ is one such
|
|
program. <em/Login/ does two things, it first establishes that the
|
|
requesting user is whom they claim to be and second provides them with
|
|
the requested service: in the case of <em/login/ the service is a
|
|
command shell (<em>bash, tcsh, zsh, etc.</em>) running with the
|
|
identity of the user.
|
|
|
|
<p>
|
|
Traditionally, the former step is achieved by the <em/login/
|
|
application prompting the user for a password and then verifying that
|
|
it agrees with that located on the system; hence verifying that
|
|
as far as the system is concerned the user is who they claim to be.
|
|
This is the task that is delegated to <bf/Linux-PAM/.
|
|
|
|
<p>
|
|
From the perspective of the application programmer (in this case the
|
|
person that wrote the <em/login/ application), <bf/Linux-PAM/ takes
|
|
care of this authentication task -- verifying the identity of the user.
|
|
|
|
<p>
|
|
The flexibility of <bf/Linux-PAM/ is that <em/you/, the system
|
|
administrator, have the freedom to stipulate which authentication
|
|
scheme is to be used. You have the freedom to set the scheme for
|
|
any/all PAM-aware applications on your Linux system. That is, you can
|
|
authenticate from anything as naive as <em/simple trust/
|
|
(<tt/pam_permit/) to something as paranoid as a combination of a
|
|
retinal scan, a voice print and a one-time password!
|
|
|
|
<p>
|
|
To illustrate the flexibility you face, consider the following
|
|
situation: a system administrator (parent) wishes to improve the
|
|
mathematical ability of her users (children). She can configure their
|
|
favorite ``Shoot 'em up game'' (PAM-aware of course) to authenticate
|
|
them with a request for the product of a couple of random numbers less
|
|
than 12. It is clear that if the game is any good they will soon learn
|
|
their <em/multiplication tables/. As they mature, the authentication
|
|
can be upgraded to include (long) division!
|
|
|
|
<p>
|
|
<bf/Linux-PAM/ deals with four separate types of (management)
|
|
task. These are: <em/authentication management/; <em/account
|
|
management/; <em/session management/; and <em/password management/.
|
|
The association of the preferred management scheme with the behavior
|
|
of an application is made with entries in the relevant <bf/Linux-PAM/
|
|
configuration file. The management functions are performed by
|
|
<em/modules/ specified in the configuration file. The syntax for this
|
|
file is discussed in the section <ref id="configuration"
|
|
name="below">.
|
|
|
|
<p>
|
|
Here is a figure that describes the overall organization of
|
|
<bf/Linux-PAM/.
|
|
<tscreen>
|
|
<verb>
|
|
+----------------+
|
|
| application: X |
|
|
+----------------+ / +----------+ +================+
|
|
| authentication-[---->--\--] Linux- |--<--| PAM config file|
|
|
| + [----<--/--] PAM | |================|
|
|
|[conversation()][--+ \ | | | X auth .. a.so |
|
|
+----------------+ | / +-n--n-----+ | X auth .. b.so |
|
|
| | | __| | | _____/
|
|
| service user | A | | |____,-----'
|
|
| | | V A
|
|
+----------------+ +------|-----|---------+ -----+------+
|
|
+---u-----u----+ | | |
|
|
| auth.... |--[ a ]--[ b ]--[ c ]
|
|
+--------------+
|
|
| acct.... |--[ b ]--[ d ]
|
|
+--------------+
|
|
| password |--[ b ]--[ c ]
|
|
+--------------+
|
|
| session |--[ e ]--[ c ]
|
|
+--------------+
|
|
</verb>
|
|
</tscreen>
|
|
By way of explanation, the left of the figure represents the
|
|
application; application X. Such an application interfaces with the
|
|
<bf/Linux-PAM/ library and knows none of the specifics of its
|
|
configured authentication method. The <bf/Linux-PAM/ library (in the
|
|
center) consults the contents of the PAM configuration file and loads
|
|
the modules that are appropriate for application-X. These modules fall
|
|
into one of four management groups (lower-center) and are stacked in
|
|
the order they appear in the configuration file. These modules, when
|
|
called by <bf/Linux-PAM/, perform the various authentication tasks for
|
|
the application. Textual information, required from/or offered to the
|
|
user, can be exchanged through the use of the application-supplied
|
|
<em/conversation/ function.
|
|
|
|
<sect1>Getting started
|
|
|
|
<p>
|
|
The following text was contributed by Seth Chaiklin:
|
|
<tscreen>
|
|
<verb>
|
|
To this point, we have described how PAM should work in an
|
|
ideal world, in which all applications are coded properly.
|
|
However, at the present time (October 1998), this is far
|
|
from the case. Therefore, here are some practical considerations
|
|
in trying to use PAM in your system.
|
|
|
|
Why bother, is it really worth all the trouble?
|
|
|
|
If you running Linux as a single user system, or in an
|
|
environment where all the users are trusted, then there
|
|
is no real advantage for using PAM.
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
<BF>Ed:</BF> there is actually an advantage since you can <em/dummy
|
|
down/ the authentication to the point where you don't have
|
|
any... Almost like Win95.
|
|
<p>
|
|
In a networked environment, it is clear that you need to think a
|
|
little more about how users etc., are authenticated:]
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
If you are running Linux as a server, where several different
|
|
services are being provided (e.g., WWW with areas restricted by
|
|
password control, PPP), then there can be some real and interesting
|
|
value for PAM. In particular, through the use of modules, PAM can
|
|
enable a program to search through several different password
|
|
databases, even if that program is not explicitly coded for
|
|
that particular database. Here are some examples of the possibilities
|
|
that this enables.
|
|
|
|
o Apache has a module that provides PAM services. Now
|
|
authentication
|
|
to use particular directories can be conducted by PAM, which
|
|
means that the range of modules that are available to PAM can
|
|
be used, including RADIUS, NIS, NCP (which means that Novell
|
|
password databases can be used).
|
|
|
|
o pppd has a PAMified version (available from RedHat) Now it is
|
|
possible to use a series of databases to authenticate ppp users.
|
|
In addition to the normal Linux-based password databases (such
|
|
as /etc/passwd and /etc/shadow), you can use PAM modules to
|
|
authenticate against Novell password databases or NT-based
|
|
password databases.
|
|
|
|
o The preceding two examples can be combined. Imagaine that the
|
|
persons in your office/department are already registered with a
|
|
username and password in a Novell or NT LAN. If you wanted to
|
|
use this database on your Linux server (for PPP access, for
|
|
web access, or even for normal shell access), you can use PAM
|
|
to authenticate against this existing database, rather than
|
|
maintain a separate database on both Linux and the LAN server.
|
|
|
|
|
|
Can I use PAM for any program that requires authentication?
|
|
|
|
Yes and no. Yes, if you have access to the source code, and can
|
|
add the appropriate PAM functions. No, if you do not have access
|
|
to the source code, and the binary does not have the PAM functions
|
|
included.
|
|
|
|
In other words, if a program is going to use PAM, then it has to
|
|
have PAM functions explicitly coded into the program. If they
|
|
are not, then it is not possible to use PAM.
|
|
|
|
How can I tell whether a program has PAM coded into it or not?
|
|
|
|
A quick-and-dirty (but not always reliable) method is to ldd
|
|
<programname>
|
|
If libpam and libpam_misc are not among the libraries that the program
|
|
uses, then it is not going to work with PAM. However, it is possible
|
|
that the libraries are included, but there are still problems, because
|
|
the PAM coding in the program does not work as it should. So a
|
|
more reliable method is to make the follow tests.
|
|
|
|
In the /etc/pam.d directory, one needs to make a configuration file
|
|
for the program that one wants to run. The exact name of the
|
|
configuration
|
|
file is hard-coded into the program. Usually, it is the same name as
|
|
the
|
|
program, but not always. For sake of illustration, let's assume that
|
|
the program is named "pamprog" and the name of the configuration file
|
|
is /etc/pam.d/pamprog.
|
|
|
|
In the /etc/pam.d/pamprog but the following two lines:
|
|
|
|
auth required pam_permit.so
|
|
auth required pam_warn.so
|
|
|
|
|
|
Now try to use pamprog. The first line in the configuration file
|
|
says that all users are permitted. The second line will write a
|
|
warning to your syslog file (or whether you syslog is writing
|
|
|
|
messages). If this test succeeds, then you know that you have
|
|
a program that can understand pam, and you can start the more
|
|
interesting work of deciding how to stack modules in your
|
|
/etc/pam.d/pamprog file.
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<sect>The Linux-PAM configuration file
|
|
<label id="configuration">
|
|
|
|
<p>
|
|
<bf/Linux-PAM/ is designed to provide the system administrator with a
|
|
great deal of flexibility in configuring the privilege granting
|
|
applications of their system. The local configuration of those aspects
|
|
of system security controlled by <tt/Linux-PAM/ is contained in one of
|
|
two places: either the single system file, <tt>/etc/pam.conf</tt>; or
|
|
the <tt>/etc/pam.d/</tt> directory. In this section we discuss the
|
|
correct syntax of and generic options respected by entries to these
|
|
files.
|
|
|
|
<sect1>Configuration file syntax
|
|
|
|
<p>
|
|
The reader should note that the <bf/Linux-PAM/ specific tokens in this
|
|
file are case <em/insensitive/. The module paths, however, are case
|
|
sensitive since they indicate a file's <em/name/ and reflect the case
|
|
dependence of typical Linux file-systems. The case-sensitivity of the
|
|
arguments to any given module is defined for each module in turn.
|
|
|
|
<p>
|
|
In addition to the lines described below, there are two <em/special/
|
|
characters provided for the convenience of the system administrator:
|
|
comments are preceded by a `<tt/#/' and extend to the
|
|
next end-of-line; also, module specification lines may be extended
|
|
with a `<tt/\/' escaped newline.
|
|
|
|
<p>
|
|
A general configuration line of the <tt>/etc/pam.conf</tt> file has
|
|
the following form:
|
|
<tscreen>
|
|
<verb>
|
|
service-name module-type control-flag module-path arguments
|
|
</verb>
|
|
</tscreen>
|
|
Below, we explain the meaning of each of these tokens. The second (and
|
|
more recently adopted) way of configuring <bf/Linux-PAM/ is via the
|
|
contents of the <tt>/etc/pam.d/</tt> directory. Once we have explained
|
|
the meaning of the above tokens, we will describe this method.
|
|
|
|
<p>
|
|
<descrip>
|
|
<tag><tt/service-name/</tag>
|
|
The name of the service associated with this entry. Frequently the
|
|
service name is the conventional name of the given application. For
|
|
example, `<tt/ftpd/', `<tt/rlogind/' and `<tt/su/', <em/etc./ .
|
|
|
|
<p>
|
|
There is a special <tt/service-name/, reserved for defining a default
|
|
authentication mechanism. It has the name `<tt/OTHER/' and may be
|
|
specified in either lower or upper case characters. Note, when there
|
|
is a module specified for a named service, the `<tt/OTHER/' entries
|
|
are ignored.
|
|
|
|
<tag><tt/module-type/</tag>
|
|
One of (currently) four types of module. The four types are as
|
|
follows:
|
|
<itemize>
|
|
<item> <tt/auth/; this module type provides two aspects of
|
|
authenticating the user. Firstly, it establishes that the user is who
|
|
they claim to be, by instructing the application to prompt the user
|
|
for a password or other means of identification. Secondly, the module
|
|
can grant <tt/group/ membership (independently of the
|
|
<tt>/etc/groups</tt> file discussed above) or other privileges through
|
|
its <em/credential/ granting properties.
|
|
|
|
<item> <tt/account/; this module performs non-authentication based
|
|
account management. It is typically used to restrict/permit access to
|
|
a service based on the time of day, currently available system
|
|
resources (maximum number of users) or perhaps the location of the
|
|
applicant user---`<tt/root/' login only on the console.
|
|
|
|
<item> <tt/session/; primarily, this module is associated with doing
|
|
things that need to be done for the user before/after they can be
|
|
given service. Such things include the logging of information
|
|
concerning the opening/closing of some data exchange with a user,
|
|
mounting directories, etc. .
|
|
|
|
<item> <tt/password/; this last module type is required for updating the
|
|
authentication token associated with the user. Typically, there is one
|
|
module for each `challenge/response' based authentication (<tt/auth/)
|
|
module-type.
|
|
|
|
</itemize>
|
|
|
|
<tag><tt/control-flag/</tag>
|
|
|
|
The control-flag is used to indicate how the PAM library will react to
|
|
the success or failure of the module it is associated with. Since
|
|
modules can be <em/stacked/ (modules of the same type execute in
|
|
series, one after another), the control-flags determine the relative
|
|
importance of each module. The application is not made aware of the
|
|
individual success or failure of modules listed in the
|
|
`<tt>/etc/pam.conf</tt>' file. Instead, it receives a summary
|
|
<em/success/ or <em/fail/ response from the <bf/Linux-PAM/ library.
|
|
The order of execution of these modules is that of the entries in the
|
|
<tt>/etc/pam.conf</tt> file; earlier entries are executed before later
|
|
ones. As of Linux-PAM v0.60, this <em/control-flag/ can be defined
|
|
with one of two syntaxes.
|
|
|
|
<p>
|
|
The simpler (and historical) syntax for the control-flag is a single
|
|
keyword defined to indicate the severity of concern associated with
|
|
the success or failure of a specific module. There are four such
|
|
keywords: <tt/required/, <tt/requisite/, <tt/sufficient/ and
|
|
<tt/optional/.
|
|
|
|
<p>
|
|
The Linux-PAM library interprets these keywords in the following
|
|
manner:
|
|
|
|
<itemize>
|
|
|
|
<item> <tt/required/; this indicates that the success of the module is
|
|
required for the <tt/module-type/ facility to succeed. Failure of this
|
|
module will not be apparent to the user until all of the remaining
|
|
modules (of the same <tt/module-type/) have been executed.
|
|
|
|
<item> <tt/requisite/; like <tt/required/, however, in the case that
|
|
such a module returns a failure, control is directly returned to the
|
|
application. The return value is that associated with the <em/first/
|
|
<tt/required/ or <tt/requisite/ module to fail. Note, this flag can be
|
|
used to protect against the possibility of a user getting the
|
|
opportunity to enter a password over an unsafe medium. It is
|
|
conceivable that such behavior might inform an attacker of valid
|
|
accounts on a system. This possibility should be weighed against the
|
|
not insignificant concerns of exposing a sensitive password in a
|
|
hostile environment.
|
|
|
|
<item> <tt/sufficient/; the success of this module is deemed
|
|
`<em/sufficient/' to satisfy the <bf/Linux-PAM/ library that this
|
|
module-type has succeeded in its purpose. In the event that no
|
|
previous <tt/required/ module has failed, no more `<em/stacked/'
|
|
modules of this type are invoked. (Note, in this case subsequent
|
|
<tt/required/ modules are <bf/not/ invoked.). A failure of this module
|
|
is not deemed as fatal to satisfying the application that this
|
|
<tt/module-type/ has succeeded.
|
|
|
|
<item> <tt/optional/; as its name suggests, this <tt/control-flag/
|
|
marks the module as not being critical to the success or failure of
|
|
the user's application for service. In general, <bf/Linux-PAM/
|
|
ignores such a module when determining if the module stack will
|
|
succeed or fail. However, in the absence of any definite successes or
|
|
failures of previous or subsequent stacked modules this module will
|
|
determine the nature of the response to the application. One example
|
|
of this latter case, is when the other modules return something like
|
|
<tt/PAM_IGNORE/.
|
|
|
|
</itemize>
|
|
|
|
<p>
|
|
The more elaborate (newer) syntax is much more specific and gives the
|
|
administrator a great deal of control over how the user is
|
|
authenticated. This form of the control flag is delimeted with square
|
|
brackets and consists of a series of <tt/value=action/ tokens:
|
|
<tscreen>
|
|
<verb>
|
|
[value1=action1 value2=action2 ...]
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
Here, <tt/valueI/ is one of the following <em/return values/:
|
|
<tt/success/; <tt/open_err/; <tt/symbol_err/; <tt/service_err/;
|
|
<tt/system_err/; <tt/buf_err/; <tt/perm_denied/; <tt/auth_err/;
|
|
<tt/cred_insufficient/; <tt/authinfo_unavail/; <tt/user_unknown/;
|
|
<tt/maxtries/; <tt/new_authtok_reqd/; <tt/acct_expired/;
|
|
<tt/session_err/; <tt/cred_unavail/; <tt/cred_expired/; <tt/cred_err/;
|
|
<tt/no_module_data/; <tt/conv_err/; <tt/authtok_err/;
|
|
<tt/authtok_recover_err/; <tt/authtok_lock_busy/;
|
|
<tt/authtok_disable_aging/; <tt/try_again/; <tt/ignore/; <tt/abort/;
|
|
<tt/authtok_expired/; <tt/module_unknown/; <tt/bad_item/; and
|
|
<tt/default/. The last of these (<tt/default/) can be used to set the
|
|
action for those return values that are not explicitly defined.
|
|
|
|
<p>
|
|
The <tt/actionI/ can be a positive integer or one of the following
|
|
tokens: <tt/ignore/; <tt/ok/; <tt/done/; <tt/bad/; <tt/die/; and
|
|
<tt/reset/. A positive integer, <tt/J/, when specified as the action,
|
|
can be used to indicate that the next <em/J/ modules of the current
|
|
type will be skipped. In this way, the administrator can develop a
|
|
moderately sophisticated stack of modules with a number of different
|
|
paths of execution. Which path is taken can be determined by the
|
|
reactions of individual modules.
|
|
|
|
<p>
|
|
<itemize>
|
|
<item><tt/ignore/ - when used with a stack of modules, the module's
|
|
return status will not contribute to the return code the application
|
|
obtains.
|
|
<item><tt/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.
|
|
<item><tt/die/ - equivalent to <tt/bad/ with the side effect of
|
|
terminating the module stack and PAM immediately returning to the
|
|
application.
|
|
<item><tt/ok/ - this tells <bf/PAM/ that the administrator thinks this
|
|
return code should contribute directly to the return code of the full
|
|
stack of modules. In other words, if the former state of the stack
|
|
would lead to a return of <tt/PAM_SUCCESS/, the module's return code
|
|
will override this value. Note, if the former state of the stack
|
|
holds some value that is indicative of a modules failure, this 'ok'
|
|
value will not be used to override that value.
|
|
<item><tt/done/ - equivalent to <tt/ok/ with the side effect of
|
|
terminating the module stack and PAM immediately returning to the
|
|
application.
|
|
<item><tt/reset/ - clear all memory of the state of the module stack and
|
|
start again with the next stacked module.
|
|
</itemize>
|
|
|
|
<p>
|
|
Just to get a feel for the power of this new syntax, here is a taste
|
|
of what you can do with it. With <bf/Linux-PAM-0.63/, the notion of
|
|
client plug-in agents was introduced. This is something that makes it
|
|
possible for PAM to support machine-machine authentication using the
|
|
transport protocol inherent to the client/server application. With
|
|
the ``<tt/[ ... value=action ... ]/'' control syntax, it is possible
|
|
for an application to be configured to support binary prompts with
|
|
compliant clients, but to gracefully fall over into an alternative
|
|
authentication mode for older, legacy, applications. Flexible eh?
|
|
|
|
<tag> <tt/module-path/</tag>
|
|
|
|
The path-name of the dynamically loadable object file; <em/the
|
|
pluggable module/ itself. If the first character of the module path is
|
|
`<tt>/</tt>', it is assumed to be a complete path. If this is not the
|
|
case, the given module path is appended to the default module path:
|
|
<tt>/usr/lib/security</tt> (but see the notes <ref
|
|
id="text-conventions" name="above">).
|
|
|
|
<tag> <tt/args/</tag>
|
|
|
|
The <tt/args/ are a list of tokens that are passed to the module when
|
|
it is invoked. Much like arguments to a typical Linux shell command.
|
|
Generally, valid arguments are optional and are specific to any given
|
|
module. Invalid arguments are ignored by a module, however, when
|
|
encountering an invalid argument, the module is required to write an
|
|
error to <tt/syslog(3)/. For a list of <em/generic/ options see the
|
|
next section.
|
|
|
|
</descrip>
|
|
|
|
<p>
|
|
Any line in (one of) the configuration file(s), that is not formatted
|
|
correctly, will generally tend (erring on the side of caution) to make
|
|
the authentication process fail. A corresponding error is written to
|
|
the system log files with a call to <tt/syslog(3)/.
|
|
|
|
<sect1>Directory based configuration
|
|
|
|
<p>
|
|
More flexible than the single configuration file, as of version 0.56,
|
|
it is possible to configure <tt>libpam</tt> via the contents of the
|
|
<tt>/etc/pam.d/</tt> directory. In this case the directory is filled
|
|
with files each of which has a filename equal to a service-name (in
|
|
lower-case): it is the personal configuration file for the named
|
|
service.
|
|
|
|
<p>
|
|
<bf/Linux-PAM/ can be compiled in one of two modes. The preferred
|
|
mode uses either <tt>/etc/pam.d/</tt> or <tt>/etc/pam.conf</tt>
|
|
configuration but not both. That is to say, if there is a
|
|
<tt>/etc/pam.d/</tt> directory then libpam only uses the files
|
|
contained in this directory. However, in the absence of the
|
|
<tt>/etc/pam.d/</tt> directory the <tt>/etc/pam.conf</tt> file is
|
|
used. The other mode (and the one currently supported by Red Hat 4.2
|
|
and higher) is to use both <tt>/etc/pam.d/</tt> and
|
|
<tt>/etc/pam.conf</tt> in sequence. In this mode, entries in
|
|
<tt>/etc/pam.d/</tt> override those of <tt>/etc/pam.conf</tt>.
|
|
|
|
The syntax of each file in <tt>/etc/pam.d/</tt> is similar to that of
|
|
the <tt>/etc/pam.conf</tt> file and is made up of lines of the
|
|
following form:
|
|
<tscreen>
|
|
<verb>
|
|
module-type control-flag module-path arguments
|
|
</verb>
|
|
</tscreen>
|
|
The only difference being that the <tt>service-name</tt> is not
|
|
present. The service-name is of course the name of the given
|
|
configuration file. For example, <tt>/etc/pam.d/login</tt> contains
|
|
the configuration for the <em>login</em> service.
|
|
|
|
<p>
|
|
This method of configuration has a number of advantages over the
|
|
single file approach. We list them here to assist the reader in
|
|
deciding which scheme to adopt:
|
|
|
|
<p>
|
|
<itemize>
|
|
|
|
<item>A lower chance of misconfiguring an application. There is one
|
|
less field to mis-type when editing the configuration files by hand.
|
|
|
|
<item>Easier to maintain. One application may be reconfigured without
|
|
risk of interfering with other applications on the system.
|
|
|
|
<item>It is possible to symbolically link different services
|
|
configuration files to a single file. This makes it easier to keep the
|
|
system policy for access consistent across different applications.
|
|
(It should be noted, to conserve space, it is equally possible to
|
|
<em>hard</em> link a number of configuration files. However, care
|
|
should be taken when administering this arrangement as editing a hard
|
|
linked file is likely to break the link.)
|
|
|
|
<item>A potential for quicker configuration file parsing. Only the
|
|
relevant entries are parsed when a service gets bound to its modules.
|
|
|
|
<item>It is possible to limit read access to individual <bf/Linux-PAM/
|
|
configuration files using the file protections of the filesystem.
|
|
|
|
<item>Package management becomes simpler. Every time a new
|
|
application is installed, it can be accompanied by an
|
|
<tt>/etc/pam.d/</tt><em>xxxxxx</em> file.
|
|
|
|
</itemize>
|
|
|
|
<sect1>Generic optional arguments
|
|
|
|
<p>
|
|
The following are optional arguments which are likely to be understood
|
|
by any module. Arguments (including these) are in general
|
|
<em/optional/.
|
|
|
|
<p>
|
|
<descrip>
|
|
<tag><tt/debug/</tag>
|
|
|
|
Use the <tt/syslog(3)/ call to log debugging information to the system
|
|
log files.
|
|
|
|
<tag> <tt/no_warn/</tag>
|
|
|
|
Instruct module to not give warning messages to the application.
|
|
|
|
<tag> <tt/use_first_pass/</tag>
|
|
|
|
The module should not prompt the user for a password. Instead, it
|
|
should obtain the previously typed password (from the preceding
|
|
<tt/auth/ module), and use that. If that doesn't work, then the user
|
|
will not be authenticated. (This option is intended for <tt/auth/
|
|
and <tt/password/ modules only).
|
|
|
|
<tag> <tt/try_first_pass/</tag>
|
|
|
|
The module should attempt authentication with the previously typed
|
|
password (from the preceding <tt/auth/ module). If that doesn't work,
|
|
then the user is prompted for a password. (This option is intended for
|
|
<tt/auth/ modules only).
|
|
|
|
<tag> <tt/use_mapped_pass/</tag>
|
|
|
|
This argument is not currently supported by any of the modules in the
|
|
<bf/Linux-PAM/ distribution because of possible consequences
|
|
associated with U.S. encryption exporting restrictions. Within the
|
|
U.S., module developers are, of course, free to implement it (as are
|
|
developers in other countries). For compatibility reasons we describe
|
|
its use as suggested in the <bf/DCE-RFC 86.0/, see section <ref
|
|
id="see-also-sec" name="bibliography"> for a pointer to this document.
|
|
|
|
<p>
|
|
The <tt/use_mapped_pass/ argument instructs the module to take the
|
|
clear text authentication token entered by a previous module (that
|
|
requests such a token) and use it to generate an encryption/decryption
|
|
key with which to safely store/retrieve the authentication token
|
|
required for this module. In this way the user can enter a single
|
|
authentication token and be quietly authenticated by a number of
|
|
stacked modules. Obviously a convenient feature that necessarily
|
|
requires some reliably strong encryption to make it secure.
|
|
This argument is intended for the <tt/auth/ and <tt/password/ module
|
|
types only.
|
|
|
|
<tag><tt/expose_account/</tag>
|
|
|
|
<p>
|
|
In general the leakage of some information about user accounts is not
|
|
a secure policy for modules to adopt. Sometimes information such as
|
|
users names or home directories, or preferred shell, can be used to
|
|
attack a user's account. In some circumstances, however, this sort of
|
|
information is not deemed a threat: displaying a user's full name when
|
|
asking them for a password in a secured environment could also be
|
|
called being 'friendly'. The <tt/expose_account/ argument is a
|
|
standard module argument to encourage a module to be less discrete
|
|
about account information as it is deemed appropriate by the local
|
|
administrator.
|
|
|
|
</descrip>
|
|
|
|
<sect1>Example configuration file entries
|
|
|
|
<p>
|
|
In this section, we give some examples of entries that can be present
|
|
in the <bf/Linux-PAM/ configuration file. As a first attempt at
|
|
configuring your system you could do worse than to implement these.
|
|
|
|
<sect2>Default policy
|
|
|
|
<p>
|
|
If a system is to be considered secure, it had better have a
|
|
reasonably secure `<tt/OTHER/' entry. The following is a paranoid
|
|
setting (which is not a bad place to start!):
|
|
<tscreen>
|
|
<verb>
|
|
#
|
|
# default; deny access
|
|
#
|
|
OTHER auth required /usr/lib/security/pam_deny.so
|
|
OTHER account required /usr/lib/security/pam_deny.so
|
|
OTHER password required /usr/lib/security/pam_deny.so
|
|
OTHER session required /usr/lib/security/pam_deny.so
|
|
</verb>
|
|
</tscreen>
|
|
Whilst fundamentally a secure default, this is not very sympathetic to
|
|
a misconfigured system. For example, such a system is vulnerable to
|
|
locking everyone out should the rest of the file become badly written.
|
|
|
|
<p>
|
|
The module <tt/pam_deny/ (documented in a later section) is not very
|
|
sophisticated. For example, it logs no information when it is invoked
|
|
so unless the users of a system contact the administrator when failing
|
|
to execute a service application, the administrator may go for a long
|
|
while in ignorance of the fact that his system is misconfigured.
|
|
|
|
<p>
|
|
The addition of the following line before those in the above example
|
|
would provide a suitable warning to the administrator.
|
|
<tscreen>
|
|
<verb>
|
|
#
|
|
# default; wake up! This application is not configured
|
|
#
|
|
OTHER auth required /usr/lib/security/pam_warn.so
|
|
OTHER password required /usr/lib/security/pam_warn.so
|
|
</verb>
|
|
</tscreen>
|
|
Having two ``<tt/OTHER auth/'' lines is an example of stacking.
|
|
|
|
<p>
|
|
On a system that uses the <tt>/etc/pam.d/</tt> configuration, the
|
|
corresponding default setup would be achieved with the following file:
|
|
<tscreen>
|
|
<verb>
|
|
#
|
|
# default configuration: /etc/pam.d/other
|
|
#
|
|
auth required /usr/lib/security/pam_warn.so
|
|
auth required /usr/lib/security/pam_deny.so
|
|
account required /usr/lib/security/pam_deny.so
|
|
password required /usr/lib/security/pam_warn.so
|
|
password required /usr/lib/security/pam_deny.so
|
|
session required /usr/lib/security/pam_deny.so
|
|
</verb>
|
|
</tscreen>
|
|
This is the only explicit example we give for an <tt>/etc/pam.d/</tt>
|
|
file. In general, it should be clear how to transpose the remaining
|
|
examples to this configuration scheme.
|
|
|
|
<p>
|
|
On a less sensitive computer, one on which the system administrator
|
|
wishes to remain ignorant of much of the power of <tt/Linux-PAM/, the
|
|
following selection of lines (in <tt>/etc/pam.conf</tt>) is likely to
|
|
mimic the historically familiar Linux setup.
|
|
<tscreen>
|
|
<verb>
|
|
#
|
|
# default; standard UNIX access
|
|
#
|
|
OTHER auth required /usr/lib/security/pam_unix_auth.so
|
|
OTHER account required /usr/lib/security/pam_unix_acct.so
|
|
OTHER password required /usr/lib/security/pam_unix_passwd.so
|
|
OTHER session required /usr/lib/security/pam_unix_session.so
|
|
</verb>
|
|
</tscreen>
|
|
In general this will provide a starting place for most applications.
|
|
Unfortunately, most is not all. One application that might require
|
|
additional lines is <em/ftpd/ if you wish to enable
|
|
<em/anonymous-ftp/.
|
|
|
|
<p>
|
|
To enable anonymous-ftp, the following lines might be used to replace
|
|
the default (<tt/OTHER/) ones. (<bf/*WARNING*/ as of 1996/12/28 this
|
|
does not work correctly with any ftpd. Consequently, this description
|
|
may be subject to change or the application will be fixed.)
|
|
<tscreen>
|
|
<verb>
|
|
#
|
|
# ftpd; add ftp-specifics. These lines enable anonymous ftp over
|
|
# standard UNIX access (the listfile entry blocks access to
|
|
# users listed in /etc/ftpusers)
|
|
#
|
|
ftpd auth sufficient /usr/lib/security/pam_ftp.so
|
|
ftpd auth required /usr/lib/security/pam_unix_auth.so use_first_pass
|
|
ftpd auth required /usr/lib/security/pam_listfile.so \
|
|
onerr=succeed item=user sense=deny file=/etc/ftpusers
|
|
</verb>
|
|
</tscreen>
|
|
Note, the second line is necessary since the default entries are
|
|
ignored by a service application (here <em/ftpd/) if there are
|
|
<em/any/ entries in <tt>/etc/pam.conf</tt> for that specified service.
|
|
Again, this is an example of authentication module stacking. Note the
|
|
use of the <tt/sufficient/ control-flag. It says that ``if this module
|
|
authenticates the user, ignore the subsequent <tt/auth/
|
|
modules''. Also note the use of the ``<tt/use_first_pass/''
|
|
module-argument, this instructs the UNIX authentication module that it
|
|
is not to prompt for a password but rely one already having been
|
|
obtained by the ftp module.
|
|
|
|
<sect>Security issues of Linux-PAM
|
|
|
|
<p>
|
|
This section will discuss good practices for using Linux-PAM in a
|
|
secure manner. <em>It is currently sadly lacking...suggestions are
|
|
welcome!</em>
|
|
|
|
<sect1>If something goes wrong
|
|
|
|
<p>
|
|
<bf/Linux-PAM/ has the potential to seriously change the security of
|
|
your system. You can choose to have no security or absolute security
|
|
(no access permitted). In general, <bf/Linux-PAM/ errs towards the
|
|
latter. Any number of configuration errors can dissable access to
|
|
your system partially, or completely.
|
|
|
|
<p>
|
|
The most dramatic problem that is likely to be encountered when
|
|
configuring <bf/Linux-PAM/ is that of <em>deleting</em> the
|
|
configuration file(s): <tt>/etc/pam.d/*</tt> and/or
|
|
<tt>/etc/pam.conf</tt>. This will lock you out of your own system!
|
|
|
|
<p>
|
|
To recover, your best bet is to reboot the system in single user mode
|
|
and set about correcting things from there. The following has been
|
|
<em>adapted</em> from a life-saving email on the subject from David
|
|
Wood:
|
|
<verb>
|
|
> What the hell do I do now?
|
|
|
|
OK, don't panic. The first thing you have to realize is that
|
|
this happens to 50% of users who ever do anything with PAM.
|
|
It happened here, not once, not twice, but three times, all
|
|
different, and in the end, the solution was the same every
|
|
time.
|
|
|
|
First, I hope you installed LILO with a delay. If you can,
|
|
reboot, hit shift or tab or something and type:
|
|
|
|
LILO boot: linux single
|
|
|
|
(Replace 'linux' with 'name-of-your-normal-linux-image').
|
|
This will let you in without logging in. Ever wondered how
|
|
easy it is to break into a linux machine from the console?
|
|
Now you know.
|
|
|
|
If you can't do that, then get yourself a bootkernel floppy
|
|
and a root disk a-la slackware's rescue.gz. (Red Hat's
|
|
installation disks can be used in this mode too.)
|
|
|
|
In either case, the point is to get back your root prompt.
|
|
|
|
Second, I'm going to assume that you haven't completely
|
|
nuked your pam installation - just your configuration files.
|
|
Here's how you make your configs nice again:
|
|
|
|
cd /etc
|
|
mv pam.conf pam.conf.orig
|
|
mv pam.d pam.d.orig
|
|
mkdir pam.d
|
|
cd pam.d
|
|
|
|
and then use vi to create a file called "other" in this
|
|
directory. It should contain the following four lines:
|
|
|
|
auth required pam_unix_auth.so
|
|
account required pam_unix_acct.so
|
|
password required pam_unix_passwd.so
|
|
session required pam_unix_session.so
|
|
|
|
Now you have the simplest possible PAM configuration that
|
|
will work the way you're used to. Everything should
|
|
magically start to work again. Try it out by hitting ALT-F2
|
|
and logging in on another virtual console. If it doesn't
|
|
work, you have bigger problems, or you've mistyped
|
|
something. One of the wonders of this system (seriously,
|
|
perhaps) is that if you mistype anything in the conf files,
|
|
you usually get no error reporting of any kind on the
|
|
console - just some entries in the log file. So look there!
|
|
(Try 'tail /var/log/messages'.)
|
|
|
|
From here you can go back and get a real configuration
|
|
going, hopefully after you've tested it first on a machine
|
|
you don't care about screwing up. :/
|
|
|
|
Some pointers (to make everything "right" with Red Hat...):
|
|
|
|
Install the newest pam, pamconfig, and pwdb from the
|
|
redhat current directory, and do it all on the same
|
|
command line with rpm...
|
|
|
|
rpm -Uvh [maybe --force too] pam-* pamconfig-* pwdb-*
|
|
|
|
Then make sure you install (or reinstall) the newest
|
|
version of libc, util-linux, wuftp, and NetKit. For
|
|
kicks you might try installing the newest versions of
|
|
the affected x apps, like xlock, but I haven't gotten
|
|
those to work at all yet.
|
|
|
|
</verb>
|
|
|
|
<sect1>Avoid having a weak `other' configuration
|
|
|
|
<p>
|
|
It is not a good thing to have a weak default (<tt/OTHER/) entry.
|
|
This service is the default configuration for all PAM aware
|
|
applications and if it is weak, your system is likely to be vulnerable
|
|
to attack.
|
|
|
|
<p>
|
|
Here is a sample "other" configuration file. The <em/pam_deny/ module will
|
|
deny access and the <em/pam_warn/ module will send a syslog message to
|
|
<tt/auth.notice/:
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
#
|
|
# The PAM configuration file for the `other' service
|
|
#
|
|
auth required pam_deny.so
|
|
auth required pam_warn.so
|
|
account required pam_deny.so
|
|
account required pam_warn.so
|
|
password required pam_deny.so
|
|
password required pam_warn.so
|
|
session required pam_deny.so
|
|
session required pam_warn.so
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<sect>A reference guide for available modules
|
|
|
|
<p>
|
|
Here, we collect together some descriptions of the various modules
|
|
available for <bf/Linux-PAM/. In general these modules should be
|
|
freely available. Where this is not the case, it will be indicated.
|
|
|
|
<p>
|
|
Also please note the comments contained in the section <ref
|
|
id="text-conventions" name="on text conventions above"> when copying
|
|
the examples listed below.
|
|
|
|
<!-- insert-file MODULES-SGML -->
|
|
|
|
<sect>Files
|
|
|
|
<p><descrip>
|
|
|
|
<tag><tt>/usr/lib/libpam.so.*</tt></tag>
|
|
|
|
the shared library providing applications with access to
|
|
<bf/Linux-PAM/.
|
|
|
|
<tag><tt>/etc/pam.conf</tt></tag>
|
|
|
|
the <bf/Linux-PAM/ configuration file.
|
|
|
|
<tag><tt>/usr/lib/security/pam_*.so</tt></tag>
|
|
|
|
the primary location for <bf/Linux-PAM/ dynamically loadable object
|
|
files; the modules.
|
|
|
|
</descrip>
|
|
|
|
<sect>See also<label id="see-also-sec">
|
|
|
|
<p><itemize>
|
|
|
|
<item>The <bf/Linux-PAM/ Application Writers' Guide.
|
|
|
|
<item>The <bf/Linux-PAM/ Module Writers' Guide.
|
|
|
|
<item>The V. Samar and R. Schemers (SunSoft), ``UNIFIED LOGIN WITH
|
|
PLUGGABLE AUTHENTICATION MODULES'', Open Software Foundation Request
|
|
For Comments 86.0, October 1995. See this url:
|
|
<tt><htmlurl
|
|
url="http://www.kernel.org/pub/linux/libs/pam/pre/doc/rfc86.0.txt.gz"
|
|
name="http://www.kernel.org/pub/linux/libs/pam/pre/doc/rfc86.0.txt.gz"></tt>
|
|
|
|
</itemize>
|
|
|
|
<sect>Notes
|
|
|
|
<p>
|
|
I intend to put development comments here... like ``at the moment
|
|
this isn't actually supported''. At release time what ever is in
|
|
this section will be placed in the Bugs section below! :)
|
|
|
|
<p>
|
|
Are we going to be able to support the <tt/use_mapped_pass/ module
|
|
argument? Anyone know a cheap (free) good lawyer?!
|
|
|
|
<p>
|
|
<itemize>
|
|
<item>
|
|
This issue may go away, as Sun have investigated adding a new
|
|
management group for mappings. In this way, libpam would have mapping
|
|
modules that could securely store passwords using strong cryptography
|
|
and in such a way that they need not be distributed with Linux-PAM.
|
|
</itemize>
|
|
|
|
<sect>Author/acknowledgments
|
|
|
|
<p>
|
|
This document was written by Andrew G. Morgan (morgan@kernel.org)
|
|
with many contributions from
|
|
<!-- insert-file CREDITS -->
|
|
|
|
<p>
|
|
Thanks are also due to Sun Microsystems, especially to Vipin Samar and
|
|
Charlie Lai for their advice. At an early stage in the development of
|
|
<bf/Linux-PAM/, Sun graciously made the documentation for their
|
|
implementation of PAM available. This act greatly accelerated the
|
|
development of <bf/Linux-PAM/.
|
|
|
|
<sect>Bugs/omissions
|
|
|
|
<p>
|
|
More PAM modules are being developed all the time. It is unlikely that
|
|
this document will ever be truely up to date!
|
|
|
|
<p>
|
|
This manual is unfinished. Only a partial list of people is credited
|
|
for all the good work they have done.
|
|
|
|
<sect>Copyright information for this document
|
|
|
|
<p>
|
|
Copyright (c) Andrew G. Morgan 1996-9. All rights reserved.
|
|
<newline>
|
|
Email: <tt><morgan@linux.kernel.org></tt>
|
|
|
|
<p>
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are
|
|
met:
|
|
|
|
<p>
|
|
<itemize>
|
|
|
|
<item>
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, and the entire permission notice in its entirety,
|
|
including the disclaimer of warranties.
|
|
|
|
<item>
|
|
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.
|
|
|
|
<item>
|
|
3. The name of the author may not be used to endorse or promote
|
|
products derived from this software without specific prior
|
|
written permission.
|
|
|
|
</itemize>
|
|
|
|
<p>
|
|
<bf/Alternatively/, this product may be distributed under the terms of
|
|
the GNU General Public License (GPL), in which case the provisions of
|
|
the GNU GPL are required <bf/instead of/ the above restrictions.
|
|
(This clause is necessary due to a potential bad interaction between
|
|
the GNU GPL and the restrictions contained in a BSD-style copyright.)
|
|
|
|
<p>
|
|
THIS SOFTWARE IS PROVIDED ``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 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.
|
|
|
|
<p>
|
|
<tt>$Id: pam_source.sgml,v 1.5 2001/03/19 01:46:41 agmorgan Exp $</tt>
|
|
|
|
</article>
|