1499 lines
49 KiB
Plaintext
1499 lines
49 KiB
Plaintext
<!doctype linuxdoc system>
|
|
|
|
<!--
|
|
|
|
$Id: pam_modules.sgml,v 1.6 2001/02/22 04:58:51 agmorgan Exp $
|
|
|
|
Copyright (c) Andrew G. Morgan 1996-2001. All rights reserved.
|
|
|
|
** some sections, in this document, were contributed by other
|
|
** authors. They carry individual copyrights.
|
|
|
|
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, 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 Module Writers' Guide
|
|
<author>Andrew G. Morgan, <tt>morgan@kernel.org</tt>
|
|
<date>DRAFT v0.75 2001/02/21
|
|
<abstract>
|
|
This manual documents what a programmer needs to know in order to
|
|
write a module that conforms to the <bf/Linux-PAM/ standard. It also
|
|
discusses some security issues from the point of view of the module
|
|
programmer.
|
|
</abstract>
|
|
|
|
<toc>
|
|
|
|
<sect>Introduction
|
|
|
|
<sect1> Synopsis
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
#include <security/pam_modules.h>
|
|
|
|
gcc -fPIC -c pam_module-name.c
|
|
ld -x --shared -o pam_module-name.so pam_module-name.o
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<sect1> Description
|
|
|
|
<p>
|
|
<bf/Linux-PAM/ (Pluggable Authentication Modules for Linux) is a
|
|
library that enables the local system administrator to choose how
|
|
individual applications authenticate users. For an overview of the
|
|
<bf/Linux-PAM/ library see the <bf/Linux-PAM/ System Administrators'
|
|
Guide.
|
|
|
|
<p>
|
|
A <bf/Linux-PAM/ module is a single executable binary file that can be
|
|
loaded by the <bf/Linux-PAM/ interface library. This PAM library is
|
|
configured locally with a system file, <tt>/etc/pam.conf</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 dlopen(3)). Alternatively, the modules can
|
|
be statically linked into the <bf/Linux-PAM/ library; this is mostly to
|
|
allow <bf/Linux-PAM/ to be used on platforms without dynamic linking
|
|
available, but the two forms can be used together. It is the
|
|
<bf/Linux-PAM/ interface that is called by an application and it is
|
|
the responsibility of the library to locate, load and call the
|
|
appropriate functions in a <bf/Linux-PAM/-module.
|
|
|
|
<p>
|
|
Except for the immediate purpose of interacting with the user
|
|
(entering a password etc..) the module should never call the
|
|
application directly. This exception requires a "conversation
|
|
mechanism" which is documented below.
|
|
|
|
<sect>What can be expected by the module
|
|
|
|
<p>
|
|
Here we list the interface that the conventions that all
|
|
<bf/Linux-PAM/ modules must adhere to.
|
|
|
|
<sect1>Getting and setting <tt/PAM_ITEM/s and <em/data/
|
|
|
|
<p>
|
|
First, we cover what the module should expect from the <bf/Linux-PAM/
|
|
library and a <bf/Linux-PAM/ <em/aware/ application. Essesntially this
|
|
is the <tt/libpam.*/ library.
|
|
|
|
<sect2>
|
|
Setting data
|
|
|
|
<p>
|
|
Synopsis:
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_set_data(pam_handle_t *pamh,
|
|
const char *module_data_name,
|
|
void *data,
|
|
void (*cleanup)(pam_handle_t *pamh,
|
|
void *data, int error_status) );
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
The modules may be dynamically loadable objects. In general such files
|
|
should not contain <tt/static/ variables. This and the subsequent
|
|
function provide a mechanism for a module to associate some data with
|
|
the handle <tt/pamh/. Typically a module will call the
|
|
<tt/pam_set_data()/ function to register some data under a (hopefully)
|
|
unique <tt/module_data_name/. The data is available for use by other
|
|
modules too but <em/not/ by an application.
|
|
|
|
<p>
|
|
The function <tt/cleanup()/ is associated with the <tt/data/ and, if
|
|
non-<tt/NULL/, it is called when this data is over-written or
|
|
following a call to <tt/pam_end()/ (see the Linux-PAM Application
|
|
Developers' Guide).
|
|
|
|
<p>
|
|
The <tt/error_status/ argument is used to indicate to the module the
|
|
sort of action it is to take in cleaning this data item. As an
|
|
example, Kerberos creates a ticket file during the authentication
|
|
phase, this file might be associated with a data item. When
|
|
<tt/pam_end()/ is called by the module, the <tt/error_status/
|
|
carries the return value of the <tt/pam_authenticate()/ or other
|
|
<tt/libpam/ function as appropriate. Based on this value the Kerberos
|
|
module may choose to delete the ticket file (<em/authentication
|
|
failure/) or leave it in place.
|
|
|
|
<p>
|
|
The <tt/error_status/ may have been logically OR'd with either of the
|
|
following two values:
|
|
|
|
<p>
|
|
<descrip>
|
|
<tag><tt/PAM_DATA_REPLACE/</tag>
|
|
When a data item is being replaced (through a second call to
|
|
<tt/pam_set_data()/) this mask is used. Otherwise, the call is assumed
|
|
to be from <tt/pam_end()/.
|
|
|
|
<tag><tt/PAM_DATA_SILENT/</tag>
|
|
Which indicates that the process would prefer to perform the
|
|
<tt/cleanup()/ quietly. That is, discourages logging/messages to the
|
|
user.
|
|
|
|
</descrip>
|
|
|
|
|
|
<sect2>
|
|
Getting data
|
|
|
|
<p>
|
|
Synopsis:
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_get_data(const pam_handle_t *pamh,
|
|
const char *module_data_name,
|
|
const void **data);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function together with the previous one provides a method of
|
|
associating module-specific data with the handle <tt/pamh/. A
|
|
successful call to <tt/pam_get_data/ will result in <tt/*data/
|
|
pointing to the data associated with the <tt/module_data_name/. Note,
|
|
this data is <em/not/ a copy and should be treated as <em/constant/
|
|
by the module.
|
|
|
|
<p>
|
|
Note, if there is an entry but it has the value <tt/NULL/, then this
|
|
call returns <tt/PAM_NO_MODULE_DATA/.
|
|
|
|
<sect2>
|
|
Setting items
|
|
|
|
<p>
|
|
Synopsis:
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_set_item(pam_handle_t *pamh,
|
|
int item_type,
|
|
const void *item);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function is used to (re)set the value of one of the
|
|
<tt/item_type/s. The reader is urged to read the entry for this
|
|
function in the <bf/Linux-PAM/ application developers' manual.
|
|
|
|
<p>
|
|
In addition to the <tt/item/s listed there, the module can set the
|
|
following two <tt/item_type/s:
|
|
|
|
<p>
|
|
<descrip>
|
|
<tag><tt/PAM_AUTHTOK/</tag>
|
|
|
|
The authentication token (often a password). This token should be
|
|
ignored by all module functions besides <tt/pam_sm_authenticate()/ and
|
|
<tt/pam_sm_chauthtok()/. In the former function it is used to pass the
|
|
most recent authentication token from one stacked module to
|
|
another. In the latter function the token is used for another
|
|
purpose. It contains the currently active authentication token.
|
|
|
|
<tag><tt/PAM_OLDAUTHTOK/</tag>
|
|
|
|
The old authentication token. This token should be ignored by all
|
|
module functions except <tt/pam_sm_chauthtok()/.
|
|
|
|
</descrip>
|
|
|
|
<p>
|
|
Both of these items are reset before returning to the application.
|
|
When resetting these items, the <bf/Linux-PAM/ library first writes
|
|
<tt/0/'s to the current tokens and then <tt/free()/'s the associated
|
|
memory.
|
|
|
|
<p>
|
|
The return values for this function are listed in the
|
|
<bf>Linux-PAM</bf> Application Developers' Guide.
|
|
|
|
<sect2>
|
|
Getting items
|
|
|
|
<p>
|
|
Synopsis:
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_get_item(const pam_handle_t *pamh,
|
|
int item_type,
|
|
const void **item);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function is used to obtain the value of the specified
|
|
<tt/item_type/. It is better documented in the <bf/Linux-PAM/
|
|
Application Developers' Guide. However, there are three things worth
|
|
stressing here:
|
|
<itemize>
|
|
|
|
<item>
|
|
Generally, if the module wishes to obtain the name of the user, it
|
|
should not use this function, but instead perform a call to
|
|
<tt/pam_get_user()/ (see section <ref id="pam-get-user"
|
|
name="below">).
|
|
|
|
<item>
|
|
The module is additionally privileged to read the authentication
|
|
tokens, <tt/PAM_AUTHTOK/ and <tt/PAM_OLDAUTHTOK/ (see the section
|
|
above on <tt/pam_set_data()/).
|
|
|
|
<item>
|
|
The module should <em/not/ <tt/free()/ or alter the data pointed to by
|
|
<tt/*item/ after a successful return from <tt/pam_get_item()/. This
|
|
pointer points directly at the data contained within the <tt/*pamh/
|
|
structure. Should a module require that a change is made to the this
|
|
<tt/ITEM/ it should make the appropriate call to <tt/pam_set_item()/.
|
|
</itemize>
|
|
|
|
<sect2>The <em/conversation/ mechanism
|
|
|
|
<p>
|
|
Following the call <tt>pam_get_item(pamh,PAM_CONV,&item)</tt>, the
|
|
pointer <tt/item/ points to a <em/conversation/-function that provides
|
|
limited but direct access to the application. The purpose of this
|
|
function is to allow the module to prompt the user for their password
|
|
and pass other information in a manner consistent with the
|
|
application. For example, an X-windows based program might pop up a
|
|
dialog box to report a login failure. Just as the application should
|
|
not be concerned with the method of authentication, so the module
|
|
should not dictate the manner in which input (output) is
|
|
obtained from (presented to) to the user.
|
|
|
|
<p>
|
|
The reader is strongly urged to read the more complete description of
|
|
the <tt/pam_conv/ structure, written from the perspective of the
|
|
application developer, in the <bf/Linux-PAM/ Application Developers'
|
|
Guide.
|
|
|
|
<p>
|
|
The <tt/pam_response/ structure returned after a call to the
|
|
<tt/pam_conv/ function must be <tt/free()/'d by the module. Since the
|
|
call to the conversation function originates from the module, it is
|
|
clear that either this <tt/pam_response/ structure could be either
|
|
statically or dynamically (using <tt/malloc()/ etc.) allocated within
|
|
the application. Repeated calls to the conversation function would
|
|
likely overwrite static memory, so it is required that for a
|
|
successful return from the conversation function the memory for the
|
|
response structure is dynamically allocated by the application with
|
|
one of the <tt/malloc()/ family of commands and <em/must/ be
|
|
<tt/free()/'d by the module.
|
|
|
|
<p>
|
|
If the <tt/pam_conv/ mechanism is used to enter authentication tokens,
|
|
the module should either pass the result to the <tt/pam_set_item()/
|
|
library function, or copy it itself. In such a case, once the token
|
|
has been stored (by one of these methods or another one), the memory
|
|
returned by the application should be overwritten with <tt/0/'s, and
|
|
then <tt/free()/'d.
|
|
|
|
<p>
|
|
The return values for this function are listed in the
|
|
<bf>Linux-PAM</bf> Application Developers' Guide.
|
|
|
|
<sect2>Getting the name of a user<label id="pam-get-user">
|
|
|
|
<p>
|
|
Synopsis:
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_get_user(pam_handle_t *pamh,
|
|
const char **user,
|
|
const char *prompt);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This is a <bf/Linux-PAM/ library function that returns the
|
|
(prospective) name of the user. To determine the username it does the
|
|
following things, in this order:
|
|
<itemize>
|
|
|
|
<item> checks what <tt/pam_get_item(pamh, PAM_USER, ... );/ would have
|
|
returned. If this is not <tt/NULL/ this is what it returns. Otherwise,
|
|
|
|
<item> obtains a username from the application via the <tt/pam_conv/
|
|
mechanism, it prompts the user with the first non-<tt/NULL/ string in
|
|
the following list:
|
|
<itemize>
|
|
|
|
<item> The <tt/prompt/ argument passed to the function
|
|
<item> What is returned by <tt/pam_get_item(pamh,PAM_USER_PROMPT, ... );/
|
|
<item> The default prompt: ``Please enter username: ''
|
|
|
|
</itemize>
|
|
</itemize>
|
|
|
|
<p>
|
|
By whatever means the username is obtained, a pointer to it is
|
|
returned as the contents of <tt/*user/. Note, this memory should
|
|
<em/not/ be <tt/free()/'d by the module. Instead, it will be liberated
|
|
on the next call to <tt/pam_get_user()/, or by <tt/pam_end()/ when the
|
|
application ends its interaction with <bf/Linux-PAM/.
|
|
|
|
<p>
|
|
Also, in addition, it should be noted that this function sets the
|
|
<tt/PAM_USER/ item that is associated with the <tt/pam_[gs]et_item()/
|
|
function.
|
|
|
|
<p>
|
|
The return value of this function is one of the following:
|
|
<itemize>
|
|
|
|
<item> <tt/PAM_SUCCESS/ - username obtained.
|
|
|
|
<item> <tt/PAM_CONV_AGAIN/ - converstation did not complete and the
|
|
caller is required to return control to the application, until such
|
|
time as the application has completed the conversation process. A
|
|
module calling <tt/pam_get_user()/ that obtains this return code,
|
|
should return <tt/PAM_INCOMPLETE/ and be prepared (when invoked the
|
|
next time) to recall <tt/pam_get_user()/ to fill in the user's name,
|
|
and then pick up where it left off as if nothing had happened. This
|
|
procedure is needed to support an event-driven application programming
|
|
model.
|
|
|
|
<item> <tt/PAM_CONV_ERR/ - the conversation method supplied by the
|
|
application failed to obtain the username.
|
|
|
|
</itemize>
|
|
|
|
<sect2>Setting a Linux-PAM environment variable
|
|
|
|
<p>
|
|
Synopsis:
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_putenv(pam_handle_t *pamh, const char *name_value);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
<bf/Linux-PAM/ comes equipped with a series of functions for
|
|
maintaining a set of <em/environment/ variables. The environment is
|
|
initialized by the call to <tt/pam_start()/ and is <bf/erased/ with a
|
|
call to <tt/pam_end()/. This <em/environment/ is associated with the
|
|
<tt/pam_handle_t/ pointer returned by the former call.
|
|
|
|
<p>
|
|
The default environment is all but empty. It contains a single
|
|
<tt/NULL/ pointer, which is always required to terminate the
|
|
variable-list. The <tt/pam_putenv()/ function can be used to add a
|
|
new environment variable, replace an existing one, or delete an old
|
|
one.
|
|
|
|
<p>
|
|
<itemize>
|
|
<item>Adding/replacing a variable<newline>
|
|
|
|
To add or overwrite a <bf/Linux-PAM/ environment variable the value of
|
|
the argument <tt/name_value/, should be of the following form:
|
|
<tscreen>
|
|
<verb>
|
|
name_value="VARIABLE=VALUE OF VARIABLE"
|
|
</verb>
|
|
</tscreen>
|
|
Here, <tt/VARIABLE/ is the environment variable's name and what
|
|
follows the `<tt/=/' is its (new) value. (Note, that <tt/"VARIABLE="/
|
|
is a valid value for <tt/name_value/, indicating that the variable is
|
|
set to <tt/""/.)
|
|
|
|
<item> Deleting a variable<newline>
|
|
|
|
To delete a <bf/Linux-PAM/ environment variable the value of
|
|
the argument <tt/name_value/, should be of the following form:
|
|
<tscreen>
|
|
<verb>
|
|
name_value="VARIABLE"
|
|
</verb>
|
|
</tscreen>
|
|
Here, <tt/VARIABLE/ is the environment variable's name and the absence
|
|
of an `<tt/=/' indicates that the variable should be removed.
|
|
|
|
</itemize>
|
|
|
|
<p>
|
|
In all cases <tt/PAM_SUCCESS/ indicates success.
|
|
|
|
<sect2>Getting a Linux-PAM environment variable
|
|
|
|
<p>
|
|
Synopsis:
|
|
<tscreen>
|
|
<verb>
|
|
extern const char *pam_getenv(pam_handle_t *pamh, const char *name);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function can be used to return the value of the given
|
|
variable. If the returned value is <tt/NULL/, the variable is not
|
|
known.
|
|
|
|
<sect2>Listing the Linux-PAM environment
|
|
|
|
<p>
|
|
Synopsis:
|
|
<tscreen>
|
|
<verb>
|
|
extern char * const *pam_getenvlist(pam_handle_t *pamh);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function returns a pointer to the entire <bf/Linux-PAM/
|
|
environment array. At first sight the <em/type/ of the returned data
|
|
may appear a little confusing. It is basically a <em/read-only/ array
|
|
of character pointers, that lists the <tt/NULL/ terminated list of
|
|
environment variables set so far.
|
|
|
|
<p>
|
|
Although, this is not a concern for the module programmer, we mention
|
|
here that an application should be careful to copy this entire array
|
|
before executing <tt/pam_end()/ otherwise all the variable information
|
|
will be lost. (There are functions in <tt/libpam_misc/ for this
|
|
purpose: <tt/pam_misc_copy_env()/ and <tt/pam_misc_drop_env()/.)
|
|
|
|
<sect1>Other functions provided by <tt/libpam/
|
|
|
|
<sect2>Understanding errors
|
|
|
|
<p>
|
|
<itemize>
|
|
|
|
<item>
|
|
<tt>extern const char *pam_strerror(pam_handle_t *pamh, int errnum);</tt>
|
|
|
|
<p>
|
|
This function returns some text describing the <bf/Linux-PAM/ error
|
|
associated with the argument <tt/errnum/. If the error is not
|
|
recognized <tt/``Unknown Linux-PAM error''/ is returned.
|
|
|
|
</itemize>
|
|
|
|
<sect2>Planning for delays
|
|
|
|
<p>
|
|
<itemize>
|
|
|
|
<item>
|
|
<tt>extern int pam_fail_delay(pam_handle_t *pamh, unsigned int
|
|
micro_sec)</tt>
|
|
|
|
<p>
|
|
This function is offered by <bf/Linux-PAM/ to facilitate time delays
|
|
following a failed call to <tt/pam_authenticate()/ and before control
|
|
is returned to the application. When using this function the module
|
|
programmer should check if it is available with,
|
|
<tscreen>
|
|
<verb>
|
|
#ifdef PAM_FAIL_DELAY
|
|
....
|
|
#endif /* PAM_FAIL_DELAY */
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
Generally, an application requests that a user is authenticated by
|
|
<bf/Linux-PAM/ through a call to <tt/pam_authenticate()/ or
|
|
<tt/pam_chauthtok()/. These functions call each of the <em/stacked/
|
|
authentication modules listed in the <bf/Linux-PAM/ configuration
|
|
file. As directed by this file, one of more of the modules may fail
|
|
causing the <tt/pam_...()/ call to return an error. It is desirable
|
|
for there to also be a pause before the application continues. The
|
|
principal reason for such a delay is security: a delay acts to
|
|
discourage <em/brute force/ dictionary attacks primarily, but also
|
|
helps hinder <em/timed/ (cf. covert channel) attacks.
|
|
|
|
<p>
|
|
The <tt/pam_fail_delay()/ function provides the mechanism by which an
|
|
application or module can suggest a minimum delay (of <tt/micro_sec/
|
|
<em/micro-seconds/). <bf/Linux-PAM/ keeps a record of the longest time
|
|
requested with this function. Should <tt/pam_authenticate()/ fail,
|
|
the failing return to the application is delayed by an amount of time
|
|
randomly distributed (by up to 25%) about this longest value.
|
|
|
|
<p>
|
|
Independent of success, the delay time is reset to its zero default
|
|
value when <bf/Linux-PAM/ returns control to the application.
|
|
|
|
</itemize>
|
|
|
|
<sect>What is expected of a module
|
|
|
|
<p>
|
|
The module must supply a sub-set of the six functions listed
|
|
below. Together they define the function of a <bf/Linux-PAM
|
|
module/. Module developers are strongly urged to read the comments on
|
|
security that follow this list.
|
|
|
|
<sect1> Overview
|
|
|
|
<p>
|
|
The six module functions are grouped into four independent management
|
|
groups. These groups are as follows: <em/authentication/,
|
|
<em/account/, <em/session/ and <em/password/. To be properly defined,
|
|
a module must define all functions within at least one of these
|
|
groups. A single module may contain the necessary functions for
|
|
<em/all/ four groups.
|
|
|
|
<sect2> Functional independence
|
|
|
|
<p>
|
|
The independence of the four groups of service a module can offer
|
|
means that the module should allow for the possibility that any one of
|
|
these four services may legitimately be called in any order. Thus, the
|
|
module writer should consider the appropriateness of performing a
|
|
service without the prior success of some other part of the module.
|
|
|
|
<p>
|
|
As an informative example, consider the possibility that an
|
|
application applies to change a user's authentication token, without
|
|
having first requested that <bf/Linux-PAM/ authenticate the user. In
|
|
some cases this may be deemed appropriate: when <tt/root/ wants to
|
|
change the authentication token of some lesser user. In other cases it
|
|
may not be appropriate: when <tt/joe/ maliciously wants to reset
|
|
<tt/alice/'s password; or when anyone other than the user themself
|
|
wishes to reset their <em/KERBEROS/ authentication token. A policy for
|
|
this action should be defined by any reasonable authentication scheme,
|
|
the module writer should consider this when implementing a given
|
|
module.
|
|
|
|
<sect2> Minimizing administration problems
|
|
|
|
<p>
|
|
To avoid system administration problems and the poor construction of a
|
|
<tt>/etc/pam.conf</tt> file, the module developer may define all
|
|
six of the following functions. For those functions that would not be
|
|
called, the module should return <tt/PAM_SERVICE_ERR/ and write an
|
|
appropriate message to the system log. When this action is deemed
|
|
inappropriate, the function would simply return <tt/PAM_IGNORE/.
|
|
|
|
<sect2> Arguments supplied to the module
|
|
|
|
<p>
|
|
The <tt/flags/ argument of each of the following functions can be
|
|
logically OR'd with <tt/PAM_SILENT/, which is used to inform the
|
|
module to not pass any <em/text/ (errors or warnings) to the
|
|
application.
|
|
|
|
<p>
|
|
The <tt/argc/ and <tt/argv/ arguments are taken from the line
|
|
appropriate to this module---that is, with the <em/service_name/
|
|
matching that of the application---in the configuration file (see the
|
|
<bf/Linux-PAM/ System Administrators' Guide). Together these two
|
|
parameters provide the number of arguments and an array of pointers to
|
|
the individual argument tokens. This will be familiar to C programmers
|
|
as the ubiquitous method of passing command arguments to the function
|
|
<tt/main()/. Note, however, that the first argument (<tt/argv[0]/) is
|
|
a true argument and <bf/not/ the name of the module.
|
|
|
|
<sect1> Authentication management
|
|
|
|
<p>
|
|
To be correctly initialized, <tt/PAM_SM_AUTH/ must be <tt/#define/'d
|
|
prior to including <tt><security/pam_modules.h></tt>. This will
|
|
ensure that the prototypes for static modules are properly declared.
|
|
|
|
<p>
|
|
<itemize>
|
|
|
|
<item>
|
|
<tt>PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags,
|
|
int argc, const char **argv);</tt>
|
|
|
|
<p>
|
|
This function performs the task of authenticating the user.
|
|
|
|
<p>
|
|
The <tt/flags/ argument can be a logically OR'd with <tt/PAM_SILENT/
|
|
and optionally take the following value:
|
|
|
|
<p><descrip>
|
|
<tag><tt/PAM_DISALLOW_NULL_AUTHTOK/</tag>
|
|
return <tt/PAM_AUTH_ERR/ if the database of authentication
|
|
tokens for this authentication mechanism has a <tt/NULL/ entry for the
|
|
user. Without this flag, such a <tt/NULL/ token will lead to a success
|
|
without the user being prompted.
|
|
</descrip>
|
|
|
|
<p>
|
|
Besides <tt/PAM_SUCCESS/ return values that can be sent by this
|
|
function are one of the following:
|
|
|
|
<descrip>
|
|
|
|
<tag><tt/PAM_AUTH_ERR/</tag>
|
|
The user was not authenticated
|
|
<tag><tt/PAM_CRED_INSUFFICIENT/</tag>
|
|
For some reason the application does not have sufficient
|
|
credentials to authenticate the user.
|
|
<tag><tt/PAM_AUTHINFO_UNAVAIL/</tag>
|
|
The modules were not able to access the authentication
|
|
information. This might be due to a network or hardware failure etc.
|
|
<tag><tt/PAM_USER_UNKNOWN/</tag>
|
|
The supplied username is not known to the authentication
|
|
service
|
|
<tag><tt/PAM_MAXTRIES/</tag>
|
|
One or more of the authentication modules has reached its
|
|
limit of tries authenticating the user. Do not try again.
|
|
|
|
</descrip>
|
|
|
|
<item>
|
|
<tt>PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int
|
|
argc, const char **argv);</tt>
|
|
|
|
<p>
|
|
This function performs the task of altering the credentials of the
|
|
user with respect to the corresponding authorization
|
|
scheme. Generally, an authentication module may have access to more
|
|
information about a user than their authentication token. This
|
|
function is used to make such information available to the
|
|
application. It should only be called <em/after/ the user has been
|
|
authenticated but before a session has been established.
|
|
|
|
<p>
|
|
Permitted flags, one of which, may be logically OR'd with
|
|
<tt/PAM_SILENT/ are,
|
|
|
|
<p><descrip>
|
|
<tag><tt/PAM_ESTABLISH_CRED/</tag>
|
|
Set the credentials for the authentication service,
|
|
<tag><tt/PAM_DELETE_CRED/</tag>
|
|
Delete the credentials associated with the authentication service,
|
|
<tag><tt/PAM_REINITIALIZE_CRED/</tag>
|
|
Reinitialize the user credentials, and
|
|
<tag><tt/PAM_REFRESH_CRED/</tag>
|
|
Extend the lifetime of the user credentials.
|
|
</descrip>
|
|
|
|
<p>
|
|
Prior to <bf/Linux-PAM-0.75/, and due to a deficiency with the way the
|
|
<tt/auth/ stack was handled in the case of the setcred stack being
|
|
processed, the module was required to attempt to return the same error
|
|
code as <tt/pam_sm_authenticate/ did. This was necessary to preserve
|
|
the logic followed by libpam as it executes the stack of
|
|
<em/authentication/ modules, when the application called either
|
|
<tt/pam_authenticate()/ or <tt/pam_setcred()/. Failing to do this,
|
|
led to confusion on the part of the System Administrator.
|
|
|
|
<p>
|
|
For <bf/Linux-PAM-0.75/ and later, libpam handles the credential stack
|
|
much more sanely. The way the <tt/auth/ stack is navigated in order to
|
|
evaluate the <tt/pam_setcred()/ function call, independent of the
|
|
<tt/pam_sm_setcred()/ return codes, is exactly the same way that it
|
|
was navigated when evaluating the <tt/pam_authenticate()/ library
|
|
call. Typically, if a stack entry was ignored in evaluating
|
|
<tt/pam_authenticate()/, it will be ignored when libpam evaluates the
|
|
<tt/pam_setcred()/ function call. Otherwise, the return codes from
|
|
each module specific <tt/pam_sm_setcred()/ call are treated as
|
|
<tt/required/.
|
|
|
|
<p>
|
|
Besides <tt/PAM_SUCCESS/, the module may return one of the following
|
|
errors:
|
|
|
|
<p><descrip>
|
|
<tag><tt/PAM_CRED_UNAVAIL/</tag>
|
|
This module cannot retrieve the user's credentials.
|
|
<tag><tt/PAM_CRED_EXPIRED/</tag>
|
|
The user's credentials have expired.
|
|
<tag><tt/PAM_USER_UNKNOWN/</tag>
|
|
The user is not known to this authentication module.
|
|
<tag><tt/PAM_CRED_ERR/</tag>
|
|
This module was unable to set the credentials of the user.
|
|
</descrip>
|
|
|
|
<p>
|
|
these, non-<tt/PAM_SUCCESS/, return values will typically lead to the
|
|
credential stack <em/failing/. The first such error will dominate in
|
|
the return value of <tt/pam_setcred()/.
|
|
|
|
</itemize>
|
|
|
|
<sect1> Account management
|
|
|
|
<p>
|
|
To be correctly initialized, <tt/PAM_SM_ACCOUNT/ must be
|
|
<tt/#define/'d prior to including <tt><security/pam_modules.h></tt>.
|
|
This will ensure that the prototype for a static module is properly
|
|
declared.
|
|
|
|
<p>
|
|
<itemize>
|
|
|
|
<item>
|
|
<tt>PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int
|
|
argc, const char **argv);</tt>
|
|
|
|
<p>
|
|
This function performs the task of establishing whether the user is
|
|
permitted to gain access at this time. It should be understood that
|
|
the user has previously been validated by an authentication
|
|
module. This function checks for other things. Such things might be:
|
|
the time of day or the date, the terminal line, remote
|
|
hostname, etc. .
|
|
|
|
<p>
|
|
This function may also determine things like the expiration on
|
|
passwords, and respond that the user change it before continuing.
|
|
|
|
<p>
|
|
Valid flags, which may be logically OR'd with <tt/PAM_SILENT/, are the
|
|
same as those applicable to the <tt/flags/ argument of
|
|
<tt/pam_sm_authenticate/.
|
|
|
|
<p>
|
|
This function may return one of the following errors,
|
|
|
|
<descrip>
|
|
|
|
<tag><tt/PAM_ACCT_EXPIRED/</tag>
|
|
The user is no longer permitted access to the system.
|
|
<tag><tt/PAM_AUTH_ERR/</tag>
|
|
There was an authentication error.
|
|
<tag><tt/PAM_AUTHTOKEN_REQD/</tag>
|
|
The user's authentication token has expired. Before calling
|
|
this function again the application will arrange for a new one to be
|
|
given. This will likely result in a call to <tt/pam_sm_chauthtok()/.
|
|
<tag><tt/PAM_USER_UNKNOWN/</tag>
|
|
The user is not known to the module's account management
|
|
component.
|
|
|
|
</descrip>
|
|
|
|
</itemize>
|
|
|
|
<sect1> Session management
|
|
|
|
<p>
|
|
To be correctly initialized, <tt/PAM_SM_SESSION/ must be
|
|
<tt/#define/'d prior to including
|
|
<tt><security/pam_modules.h></tt>. This will ensure that the
|
|
prototypes for static modules are properly declared.
|
|
|
|
<p>
|
|
The following two functions are defined to handle the
|
|
initialization/termination of a session. For example, at the beginning
|
|
of a session the module may wish to log a message with the system
|
|
regarding the user. Similarly, at the end of the session the module
|
|
would inform the system that the user's session has ended.
|
|
|
|
<p>
|
|
It should be possible for sessions to be opened by one application and
|
|
closed by another. This either requires that the module uses only
|
|
information obtained from <tt/pam_get_item()/, or that information
|
|
regarding the session is stored in some way by the operating system
|
|
(in a file for example).
|
|
|
|
<p>
|
|
<itemize>
|
|
|
|
<item>
|
|
<tt>PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int
|
|
argc, const char **argv);</tt>
|
|
|
|
<p>
|
|
This function is called to commence a session. The only valid, but
|
|
optional, flag is <tt/PAM_SILENT/.
|
|
|
|
<p>
|
|
As a return value, <tt/PAM_SUCCESS/ signals success and
|
|
<tt/PAM_SESSION_ERR/ failure.
|
|
|
|
<item>
|
|
<tt>PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int
|
|
argc, const char **argv);</tt>
|
|
|
|
<p>
|
|
This function is called to terminate a session. The only valid, but
|
|
optional, flag is <tt/PAM_SILENT/.
|
|
|
|
<p>
|
|
As a return value, <tt/PAM_SUCCESS/ signals success and
|
|
<tt/PAM_SESSION_ERR/ failure.
|
|
|
|
</itemize>
|
|
|
|
<sect1> Password management
|
|
|
|
<p>
|
|
To be correctly initialized, <tt/PAM_SM_PASSWORD/ must be
|
|
<tt/#define/'d prior to including <tt><security/pam_modules.h></tt>.
|
|
This will ensure that the prototype for a static module is properly
|
|
declared.
|
|
|
|
<p>
|
|
<itemize>
|
|
|
|
<item>
|
|
<tt>PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int
|
|
argc, const char **argv);</tt>
|
|
|
|
<p>
|
|
This function is used to (re-)set the authentication token of the
|
|
user. A valid flag, which may be logically OR'd with <tt/PAM_SILENT/,
|
|
can be built from the following list,
|
|
|
|
<descrip>
|
|
<tag><tt/PAM_CHANGE_EXPIRED_AUTHTOK/</tag>
|
|
This argument indicates to the module that the users
|
|
authentication token (password) should only be changed if it has
|
|
expired. This flag is optional and <em/must/ be combined with one of
|
|
the following two flags. Note, however, the following two options are
|
|
<em/mutually exclusive/.
|
|
|
|
<tag><tt/PAM_PRELIM_CHECK/</tag>
|
|
This indicates that the modules are being probed as to their
|
|
ready status for altering the user's authentication token. If the
|
|
module requires access to another system over some network it should
|
|
attempt to verify it can connect to this system on receiving this
|
|
flag. If a module cannot establish it is ready to update the user's
|
|
authentication token it should return <tt/PAM_TRY_AGAIN/, this
|
|
information will be passed back to the application.
|
|
|
|
<tag><tt/PAM_UPDATE_AUTHTOK/</tag>
|
|
This informs the module that this is the call it should change
|
|
the authorization tokens. If the flag is logically OR'd with
|
|
<tt/PAM_CHANGE_EXPIRED_AUTHTOK/, the token is only changed if it has
|
|
actually expired.
|
|
|
|
</descrip>
|
|
|
|
<p>
|
|
Note, the <bf/Linux-PAM/ library calls this function twice in
|
|
succession. The first time with <tt/PAM_PRELIM_CHECK/ and then, if the
|
|
module does not return <tt/PAM_TRY_AGAIN/, subsequently with
|
|
<tt/PAM_UPDATE_AUTHTOK/. It is only on the second call that the
|
|
authorization token is (possibly) changed.
|
|
|
|
<p>
|
|
<tt/PAM_SUCCESS/ is the only successful return value, valid
|
|
error-returns are:
|
|
|
|
<descrip>
|
|
<tag><tt/PAM_AUTHTOK_ERR/</tag>
|
|
The module was unable to obtain the new authentication token.
|
|
|
|
<tag><tt/PAM_AUTHTOK_RECOVERY_ERR/</tag>
|
|
The module was unable to obtain the old authentication token.
|
|
|
|
<tag><tt/PAM_AUTHTOK_LOCK_BUSY/</tag>
|
|
Cannot change the authentication token since it is currently
|
|
locked.
|
|
|
|
<tag><tt/PAM_AUTHTOK_DISABLE_AGING/</tag>
|
|
Authentication token aging has been disabled.
|
|
|
|
<tag><tt/PAM_PERM_DENIED/</tag>
|
|
Permission denied.
|
|
|
|
<tag><tt/PAM_TRY_AGAIN/</tag>
|
|
Preliminary check was unsuccessful. Signals an immediate return
|
|
to the application is desired.
|
|
|
|
<tag><tt/PAM_USER_UNKNOWN/</tag>
|
|
The user is not known to the authentication token changing
|
|
service.
|
|
|
|
</descrip>
|
|
|
|
</itemize>
|
|
|
|
<sect>Generic optional arguments
|
|
|
|
<p>
|
|
Here we list the generic arguments that all modules can expect to
|
|
be passed. They are not mandatory, and their absence should be
|
|
accepted without comment by the module.
|
|
|
|
<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 (by a call to
|
|
<tt/pam_get_item()/ for the <tt/PAM_AUTHTOK/ item), and use that. If
|
|
that doesn't work, then the user will not be authenticated. (This
|
|
option is intended for <tt/auth/ and <tt/passwd/ modules only).
|
|
|
|
<tag><tt/try_first_pass/</tag>
|
|
|
|
The module should attempt authentication with the previously typed
|
|
password (by a call to <tt/pam_get_item()/ for the <tt/PAM_AUTHTOK/
|
|
item). 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>
|
|
|
|
<bf/WARNING:/ coding this functionality may cause the module writer to
|
|
break <em/local/ encryption laws. For example, in the U.S. there are
|
|
restrictions on the export computer code that is capable of strong
|
|
encryption. It has not been established whether this option is
|
|
affected by this law, but one might reasonably assume that it does
|
|
until told otherwise. For this reason, this option is not supported
|
|
by any of the modules distributed with <bf/Linux-PAM/.
|
|
|
|
The intended function of this argument, however, is that the module
|
|
should take the existing authentication token from a previously
|
|
invoked module and use it as a key to retrieve the authentication
|
|
token for this module. For example, the module might create a strong
|
|
hash of the <tt/PAM_AUTHTOK/ item (established by a previously
|
|
executed module). Then, with logical-exclusive-or, use the result as a
|
|
<em/key/ to safely store/retrieve the authentication token for this
|
|
module in/from a local file <em/etc/. .
|
|
|
|
<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>
|
|
|
|
<sect>Programming notes
|
|
|
|
<p>
|
|
Here we collect some pointers for the module writer to bear in mind
|
|
when writing/developing a <bf/Linux-PAM/ compatible module.
|
|
|
|
<sect1>Security issues for module creation
|
|
|
|
<sect2>Sufficient resources
|
|
|
|
<p>
|
|
Care should be taken to ensure that the proper execution of a module
|
|
is not compromised by a lack of system resources. If a module is
|
|
unable to open sufficient files to perform its task, it should fail
|
|
gracefully, or request additional resources. Specifically, the
|
|
quantities manipulated by the <tt/setrlimit(2)/ family of commands
|
|
should be taken into consideration.
|
|
|
|
<sect2>Who's who?
|
|
|
|
<p>
|
|
Generally, the module may wish to establish the identity of the user
|
|
requesting a service. This may not be the same as the username
|
|
returned by <tt/pam_get_user()/. Indeed, that is only going to be the
|
|
name of the user under whose identity the service will be given. This
|
|
is not necessarily the user that requests the service.
|
|
|
|
<p>
|
|
In other words, user X runs a program that is setuid-Y, it grants the
|
|
user to have the permissions of Z. A specific example of this sort of
|
|
service request is the <em/su/ program: user <tt/joe/ executes
|
|
<em/su/ to become the user <em/jane/. In this situation X=<tt/joe/,
|
|
Y=<tt/root/ and Z=<tt/jane/. Clearly, it is important that the module
|
|
does not confuse these different users and grant an inappropriate
|
|
level of privilege.
|
|
|
|
<p>
|
|
The following is the convention to be adhered to when juggling
|
|
user-identities.
|
|
|
|
<p>
|
|
<itemize>
|
|
<item>X, the identity of the user invoking the service request.
|
|
This is the user identifier; returned by the function <tt/getuid(2)/.
|
|
|
|
<item>Y, the privileged identity of the application used to grant the
|
|
requested service. This is the <em/effective/ user identifier;
|
|
returned by the function <tt/geteuid(2)/.
|
|
|
|
<item>Z, the user under whose identity the service will be granted.
|
|
This is the username returned by <tt/pam_get_user(2)/ and also stored
|
|
in the <bf/Linux-PAM/ item, <tt/PAM_USER/.
|
|
|
|
<item><bf/Linux-PAM/ has a place for an additional user identity that
|
|
a module may care to make use of. This is the <tt/PAM_RUSER/ item.
|
|
Generally, network sensitive modules/applications may wish to set/read
|
|
this item to establish the identity of the user requesting a service
|
|
from a remote location.
|
|
|
|
</itemize>
|
|
|
|
<p>
|
|
Note, if a module wishes to modify the identity of either the <tt/uid/
|
|
or <tt/euid/ of the running process, it should take care to restore
|
|
the original values prior to returning control to the <bf/Linux-PAM/
|
|
library.
|
|
|
|
<sect2>Using the conversation function
|
|
<p>
|
|
Prior to calling the conversation function, the module should reset
|
|
the contents of the pointer that will return the applications
|
|
response. This is a good idea since the application may fail to fill
|
|
the pointer and the module should be in a position to notice!
|
|
|
|
<p>
|
|
The module should be prepared for a failure from the conversation. The
|
|
generic error would be <tt/PAM_CONV_ERR/, but anything other than
|
|
<tt/PAM_SUCCESS/ should be treated as indicating failure.
|
|
|
|
<sect2>Authentication tokens
|
|
|
|
<p>
|
|
To ensure that the authentication tokens are not left lying around the
|
|
items, <tt/PAM_AUTHTOK/ and <tt/PAM_OLDAUTHTOK/, are not available to
|
|
the application: they are defined in
|
|
<tt><security/pam_modules.h></tt>. This is ostensibly for
|
|
security reasons, but a maliciously programmed application will always
|
|
have access to all memory of the process, so it is only superficially
|
|
enforced. As a general rule the module should overwrite
|
|
authentication tokens as soon as they are no longer needed.
|
|
Especially before <tt/free()/'ing them. The <bf/Linux-PAM/ library is
|
|
required to do this when either of these authentication token items
|
|
are (re)set.
|
|
|
|
<p>
|
|
Not to dwell too little on this concern; should the module store the
|
|
authentication tokens either as (automatic) function variables or
|
|
using <tt/pam_[gs]et_data()/ the associated memory should be
|
|
over-written explicitly before it is released. In the case of the
|
|
latter storage mechanism, the associated <tt/cleanup()/ function
|
|
should explicitly overwrite the <tt/*data/ before <tt/free()/'ing it:
|
|
for example,
|
|
|
|
<tscreen>
|
|
<verb>
|
|
/*
|
|
* An example cleanup() function for releasing memory that was used to
|
|
* store a password.
|
|
*/
|
|
|
|
int cleanup(pam_handle_t *pamh, void *data, int error_status)
|
|
{
|
|
char *xx;
|
|
|
|
if ((xx = data)) {
|
|
while (*xx)
|
|
*xx++ = '\0';
|
|
free(data);
|
|
}
|
|
return PAM_SUCCESS;
|
|
}
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<sect1>Use of <tt/syslog(3)/
|
|
|
|
<p>
|
|
Only rarely should error information be directed to the user. Usually,
|
|
this is to be limited to ``<em/sorry you cannot login now/'' type
|
|
messages. Information concerning errors in the configuration file,
|
|
<tt>/etc/pam.conf</tt>, or due to some system failure encountered by
|
|
the module, should be written to <tt/syslog(3)/ with
|
|
<em/facility-type/ <tt/LOG_AUTHPRIV/.
|
|
|
|
<p>
|
|
With a few exceptions, the level of logging is, at the discretion of
|
|
the module developer. Here is the recommended usage of different
|
|
logging levels:
|
|
|
|
<p>
|
|
<itemize>
|
|
|
|
<item>
|
|
As a general rule, errors encountered by a module should be logged at
|
|
the <tt/LOG_ERR/ level. However, information regarding an unrecognized
|
|
argument, passed to a module from an entry in the
|
|
<tt>/etc/pam.conf</tt> file, is <bf/required/ to be logged at the
|
|
<tt/LOG_ERR/ level.
|
|
|
|
<item>
|
|
Debugging information, as activated by the <tt/debug/ argument to the
|
|
module in <tt>/etc/pam.conf</tt>, should be logged at the
|
|
<tt/LOG_DEBUG/ level.
|
|
|
|
<item>
|
|
If a module discovers that its personal configuration file or some
|
|
system file it uses for information is corrupted or somehow unusable,
|
|
it should indicate this by logging messages at level, <tt/LOG_ALERT/.
|
|
|
|
<item>
|
|
Shortages of system resources, such as a failure to manipulate a file
|
|
or <tt/malloc()/ failures should be logged at level <tt/LOG_CRIT/.
|
|
|
|
<item>
|
|
Authentication failures, associated with an incorrectly typed password
|
|
should be logged at level, <tt/LOG_NOTICE/.
|
|
|
|
</itemize>
|
|
|
|
<sect1> Modules that require system libraries
|
|
|
|
<p>
|
|
Writing a module is much like writing an application. You have to
|
|
provide the "conventional hooks" for it to work correctly, like
|
|
<tt>pam_sm_authenticate()</tt> etc., which would correspond to the
|
|
<tt/main()/ function in a normal function.
|
|
|
|
<p>
|
|
Typically, the author may want to link against some standard system
|
|
libraries. As when one compiles a normal program, this can be done for
|
|
modules too: you simply append the <tt>-l</tt><em>XXX</em> arguments
|
|
for the desired libraries when you create the shared module object. To
|
|
make sure a module is linked to the <tt>lib<em>whatever</em>.so</tt>
|
|
library when it is <tt>dlopen()</tt>ed, try:
|
|
<tscreen>
|
|
<verb>
|
|
% gcc -shared -Xlinker -x -o pam_module.so pam_module.o -lwhatever
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<sect1> Added requirements for <em/statically/ loaded modules.
|
|
|
|
<!--
|
|
Copyright (C) Michael K. Johnson 1996.
|
|
Last modified: AGM 1996/5/31.
|
|
-->
|
|
|
|
<p>
|
|
Modules may be statically linked into libpam. This should be true of
|
|
all the modules distributed with the basic <bf/Linux-PAM/
|
|
distribution. To be statically linked, a module needs to export
|
|
information about the functions it contains in a manner that does not
|
|
clash with other modules.
|
|
|
|
The extra code necessary to build a static module should be delimited
|
|
with <tt/#ifdef PAM_STATIC/ and <tt/#endif/. The static code should do
|
|
the following:
|
|
<itemize>
|
|
<item> Define a single structure, <tt/struct pam_module/, called
|
|
<tt>_pam_<it>modname</it>_modstruct</tt>, where
|
|
<tt><it>modname</it></tt> is the name of the module <bf/as used in the
|
|
filesystem/ but without the leading directory name (generally
|
|
<tt>/usr/lib/security/</tt> or the suffix (generally <tt/.so/).
|
|
|
|
</itemize>
|
|
|
|
<p>
|
|
As a simple example, consider the following module code which defines
|
|
a module that can be compiled to be <em/static/ or <em/dynamic/:
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
#include <stdio.h> /* for NULL define */
|
|
|
|
#define PAM_SM_PASSWORD /* the only pam_sm_... function declared */
|
|
#include <security/pam_modules.h>
|
|
|
|
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
|
|
int argc, const char **argv)
|
|
{
|
|
return PAM_SUCCESS;
|
|
}
|
|
|
|
#ifdef PAM_STATIC /* for the case that this module is static */
|
|
|
|
struct pam_module _pam_modname_modstruct = { /* static module data */
|
|
"pam_modname",
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
pam_sm_chauthtok,
|
|
};
|
|
|
|
#endif /* end PAM_STATIC */
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
To be linked with <em/libpam/, staticly-linked modules must be built
|
|
from within the <tt>Linux-PAM-X.YY/modules/</tt> subdirectory of the
|
|
<bf/Linux-PAM/ source directory as part of a normal build of the
|
|
<bf/Linux-PAM/ system.
|
|
|
|
The <em/Makefile/, for the module in question, must execute the
|
|
<tt/register_static/ shell script that is located in the
|
|
<tt>Linux-PAM-X.YY/modules/</tt> subdirectory. This is to ensure that
|
|
the module is properly registered with <em/libpam/.
|
|
|
|
The <bf/two/ manditory arguments to <tt/register_static/ are the
|
|
title, and the pathname of the object file containing the module's
|
|
code. The pathname is specified relative to the
|
|
<tt>Linux-PAM-X.YY/modules</tt> directory. The pathname may be an
|
|
empty string---this is for the case that a single object file needs to
|
|
register more than one <tt/struct pam_module/. In such a case, exactly
|
|
one call to <tt/register_static/ must indicate the object file.
|
|
|
|
<p>
|
|
Here is an example; a line in the <em/Makefile/ might look like this:
|
|
<tscreen>
|
|
<verb>
|
|
register:
|
|
ifdef STATIC
|
|
(cd ..; ./register_static pam_modname pam_modname/pam_modname.o)
|
|
endif
|
|
</verb>
|
|
</tscreen>
|
|
|
|
For some further examples, see the <tt>modules</tt> subdirectory of
|
|
the current <bf/Linux-PAM/ distribution.
|
|
|
|
<sect>An example module file
|
|
|
|
<p>
|
|
At some point, we may include a fully commented example of a module in
|
|
this document. For now, we point the reader to these two locations in
|
|
the public CVS repository:
|
|
<itemize>
|
|
<item> A module that always succeeds: <tt><htmlurl
|
|
url="http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/Linux-PAM/modules/pam_permit/?cvsroot=pam"
|
|
name="http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/Linux-PAM/modules/pam_permit/?cvsroot=pam"
|
|
></tt>
|
|
<item> A module that always fails: <tt><htmlurl
|
|
url="http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/Linux-PAM/modules/pam_deny/?cvsroot=pam"
|
|
name="http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/Linux-PAM/modules/pam_deny/?cvsroot=pam"
|
|
></tt>
|
|
</itemize>
|
|
|
|
<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
|
|
|
|
<p><itemize>
|
|
<item>The <bf/Linux-PAM/ System Administrators' Guide.
|
|
<item>The <bf/Linux-PAM/ Application Writers' Guide.
|
|
<item>
|
|
V. Samar and R. Schemers (SunSoft), ``UNIFIED LOGIN WITH PLUGGABLE
|
|
AUTHENTICATION MODULES'', Open Software Foundation Request For
|
|
Comments 86.0, October 1995.
|
|
</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>
|
|
<itemize>
|
|
<item>
|
|
Perhaps we should keep a registry of data-names as used by
|
|
<tt/pam_[gs]et_data()/ so there are no unintentional problems due to
|
|
conflicts?
|
|
|
|
<item>
|
|
<tt/pam_strerror()/ should be internationalized....
|
|
|
|
<item>
|
|
There has been some debate about whether <tt/initgroups()/ should be
|
|
in an application or in a module. It was settled by Sun who stated
|
|
that initgroups is an action of the <em/application/. The modules are
|
|
permitted to add additional groups, however.
|
|
|
|
<item>
|
|
Refinements/futher suggestions to <tt/syslog(3)/ usage by modules are
|
|
needed.
|
|
|
|
</itemize>
|
|
|
|
<sect>Author/acknowledgments
|
|
|
|
<p>
|
|
This document was written by Andrew G. Morgan
|
|
(<tt/morgan@transmeta.com/) with many contributions from
|
|
<!-- insert credits here -->
|
|
<!--
|
|
an sgml list of people to credit for their contributions to Linux-PAM
|
|
$Id: pam_modules.sgml,v 1.6 2001/02/22 04:58:51 agmorgan Exp $
|
|
-->
|
|
Chris Adams,
|
|
Peter Allgeyer,
|
|
Tim Baverstock,
|
|
Tim Berger,
|
|
Craig S. Bell,
|
|
Derrick J. Brashear,
|
|
Ben Buxton,
|
|
Seth Chaiklin,
|
|
Oliver Crow,
|
|
Chris Dent,
|
|
Marc Ewing,
|
|
Cristian Gafton,
|
|
Emmanuel Galanos,
|
|
Brad M. Garcia,
|
|
Eric Hester,
|
|
Roger Hu,
|
|
Eric Jacksch,
|
|
Michael K. Johnson,
|
|
David Kinchlea,
|
|
Olaf Kirch,
|
|
Marcin Korzonek,
|
|
Stephen Langasek,
|
|
Nicolai Langfeldt,
|
|
Elliot Lee,
|
|
Luke Kenneth Casson Leighton,
|
|
Al Longyear,
|
|
Ingo Luetkebohle,
|
|
Marek Michalkiewicz,
|
|
Robert Milkowski,
|
|
Aleph One,
|
|
Martin Pool,
|
|
Sean Reifschneider,
|
|
Jan Rekorajski,
|
|
Erik Troan,
|
|
Theodore Ts'o,
|
|
Jeff Uphoff,
|
|
Myles Uyema,
|
|
Savochkin Andrey Vladimirovich,
|
|
Ronald Wahl,
|
|
David Wood,
|
|
John Wilmes,
|
|
Joseph S. D. Yao
|
|
and
|
|
Alex O. Yuriev.
|
|
|
|
<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>
|
|
Few PAM modules currently exist. Few PAM-aware applications exist.
|
|
This document is hopelessly 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, 1997. All rights reserved.
|
|
<newline>
|
|
Email: <tt><morgan@transmeta.com></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_modules.sgml,v 1.6 2001/02/22 04:58:51 agmorgan Exp $</tt>
|
|
|
|
</article>
|