1676 lines
57 KiB
Plaintext
1676 lines
57 KiB
Plaintext
<!doctype linuxdoc system>
|
|
|
|
<!--
|
|
|
|
$Id: pam_appl.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 Application Developers' Guide
|
|
<author>Andrew G. Morgan, <tt>morgan@kernel.org</tt>
|
|
<date>DRAFT v0.75 2001/03/18
|
|
<abstract>
|
|
This manual documents what an application developer needs to know
|
|
about the <bf>Linux-PAM</bf> library. It describes how an application
|
|
might use the <bf>Linux-PAM</bf> library to authenticate users. In
|
|
addition it contains a description of the funtions to be found in
|
|
<tt/libpam_misc/ library, that can be used in general applications.
|
|
Finally, it contains some comments on PAM related security issues for
|
|
the application developer.
|
|
</abstract>
|
|
|
|
<toc>
|
|
|
|
<sect>Introduction
|
|
|
|
<sect1>Synopsis
|
|
|
|
<p>
|
|
For general applications that wish to use the services provided by
|
|
<bf/Linux-PAM/ the following is a summary of the relevant linking
|
|
information:
|
|
<tscreen>
|
|
<verb>
|
|
#include <security/pam_appl.h>
|
|
|
|
cc -o application .... -lpam -ldl
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
In addition to <tt/libpam/, there is a library of miscellaneous
|
|
functions that make the job of writing <em/PAM-aware/ applications
|
|
easier (this library is not covered in the DCE-RFC for PAM and is
|
|
specific to the Linux-PAM distribution):
|
|
<tscreen>
|
|
<verb>
|
|
...
|
|
#include <security/pam_misc.h>
|
|
|
|
cc -o application .... -lpam -lpam_misc -ldl
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<sect1> Description
|
|
|
|
<p>
|
|
<bf>Linux-PAM</bf> (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</bf> library see the <bf/Linux-PAM/ System
|
|
Administrators' Guide.
|
|
|
|
<p>
|
|
It is the purpose of the <bf>Linux-PAM</bf> project to liberate the
|
|
development of privilege granting software from the development of
|
|
secure and appropriate authentication schemes. This is accomplished
|
|
by providing a documented library of functions that an application may
|
|
use for all forms of user authentication management. This library
|
|
dynamically loads locally configured authentication modules that
|
|
actually perform the authentication tasks.
|
|
|
|
<p>
|
|
From the perspective of an application developer the information
|
|
contained in the local configuration of the PAM library should not be
|
|
important. Indeed it is intended that an application treat the
|
|
functions documented here as a ``black box'' that will deal with all
|
|
aspects of user authentication. ``All aspects'' includes user
|
|
verification, account management, session initialization/termination
|
|
and also the resetting of passwords (<em/authentication tokens/).
|
|
|
|
<sect>Overview
|
|
|
|
<p>
|
|
Most service-giving applications are restricted. In other words,
|
|
their service is not available to all and every prospective client.
|
|
Instead, the applying client must jump through a number of hoops to
|
|
convince the serving application that they are authorized to obtain
|
|
service.
|
|
|
|
The process of <em/authenticating/ a client is what PAM is designed to
|
|
manage. In addition to authentication, PAM provides account
|
|
management, credential management, session management and
|
|
authentication-token (password changing) management services. It is
|
|
important to realize when writing a PAM based application that these
|
|
services are provided in a manner that is <bf>transparent</bf> to
|
|
the application. That is to say, when the application is written, no
|
|
assumptions can be made about <em>how</em> the client will be
|
|
authenticated.
|
|
|
|
<p>
|
|
The process of authentication is performed by the PAM library via a
|
|
call to <tt>pam_authenticate()</tt>. The return value of this
|
|
function will indicate whether a named client (the <em>user</em>) has
|
|
been authenticated. If the PAM library needs to prompt the user for
|
|
any information, such as their <em>name</em> or a <em>password</em>
|
|
then it will do so. If the PAM library is configured to authenticate
|
|
the user using some silent protocol, it will do this too. (This
|
|
latter case might be via some hardware interface for example.)
|
|
|
|
<p>
|
|
It is important to note that the application must leave all decisions
|
|
about when to prompt the user at the discretion of the PAM library.
|
|
|
|
<p>
|
|
The PAM library, however, must work equally well for different styles
|
|
of application. Some applications, like the familiar <tt>login</tt>
|
|
and <tt>passwd</tt> are terminal based applications, exchanges of
|
|
information with the client in these cases is as plain text messages.
|
|
Graphically based applications, however, have a more sophisticated
|
|
interface. They generally interact with the user via specially
|
|
constructed dialogue boxes. Additionally, network based services
|
|
require that text messages exchanged with the client are specially
|
|
formatted for automated processing: one such example is <tt>ftpd</tt>
|
|
which prefixes each exchanged message with a numeric identifier.
|
|
|
|
<p>
|
|
The presentation of simple requests to a client is thus something very
|
|
dependent on the protocol that the serving application will use. In
|
|
spite of the fact that PAM demands that it drives the whole
|
|
authentication process, it is not possible to leave such protocol
|
|
subtleties up to the PAM library. To overcome this potential problem,
|
|
the application provides the PAM library with a <em>conversation</em>
|
|
function. This function is called from <bf>within</bf> the PAM
|
|
library and enables the PAM to directly interact with the client. The
|
|
sorts of things that this conversation function must be able to do are
|
|
prompt the user with text and/or obtain textual input from the user
|
|
for processing by the PAM library. The details of this function are
|
|
provided in a later section.
|
|
|
|
<p>
|
|
For example, the conversation function may be called by the PAM library
|
|
with a request to prompt the user for a password. Its job is to
|
|
reformat the prompt request into a form that the client will
|
|
understand. In the case of <tt>ftpd</tt>, this might involve prefixing
|
|
the string with the number <tt>331</tt> and sending the request over
|
|
the network to a connected client. The conversation function will
|
|
then obtain any reply and, after extracting the typed password, will
|
|
return this string of text to the PAM library. Similar concerns need
|
|
to be addressed in the case of an X-based graphical server.
|
|
|
|
<p>
|
|
There are a number of issues that need to be addressed when one is
|
|
porting an existing application to become PAM compliant. A section
|
|
below has been devoted to this: Porting legacy applications.
|
|
|
|
<p>
|
|
Besides authentication, PAM provides other forms of management.
|
|
Session management is provided with calls to
|
|
<tt>pam_open_session()</tt> and <tt>pam_close_session()</tt>. What
|
|
these functions actually do is up to the local administrator. But
|
|
typically, they could be used to log entry and exit from the system or
|
|
for mounting and unmounting the user's home directory. If an
|
|
application provides continuous service for a period of time, it
|
|
should probably call these functions, first open after the user is
|
|
authenticated and then close when the service is terminated.
|
|
|
|
<p>
|
|
Account management is another area that an application developer
|
|
should include with a call to <tt/pam_acct_mgmt()/. This call will
|
|
perform checks on the good health of the user's account (has it
|
|
expired etc.). One of the things this function may check is whether
|
|
the user's authentication token has expired - in such a case the
|
|
application may choose to attempt to update it with a call to
|
|
<tt/pam_chauthtok()/, although some applications are not suited to
|
|
this task (<em>ftp</em> for example) and in this case the application
|
|
should deny access to the user.
|
|
|
|
<p>
|
|
PAM is also capable of setting and deleting the users credentials with
|
|
the call <tt>pam_setcred()</tt>. This function should always be
|
|
called after the user is authenticated and before service is offered
|
|
to the user. By convention, this should be the last call to the PAM
|
|
library before the PAM session is opened. What exactly a credential
|
|
is, is not well defined. However, some examples are given in the
|
|
glossary below.
|
|
|
|
<sect>The public interface to <bf>Linux-PAM</bf>
|
|
|
|
<p>
|
|
Firstly, the relevant include file for the <bf>Linux-PAM</bf> library
|
|
is <tt><security/pam_appl.h></tt>. It contains the definitions
|
|
for a number of functions. After listing these functions, we collect
|
|
some guiding remarks for programmers.
|
|
|
|
<sect1>What can be expected by the application
|
|
|
|
<p>
|
|
Below we document those functions in the <bf/Linux-PAM/ library that
|
|
may be called from an application.
|
|
|
|
<sect2>Initialization of Linux-PAM
|
|
<label id="pam-start-section">
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_start(const char *service_name, const char *user,
|
|
const struct pam_conv *pam_conversation,
|
|
pam_handle_t **pamh);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This is the first of the <bf>Linux-PAM</bf> functions that must be
|
|
called by an application. It initializes the interface and reads the
|
|
system configuration file, <tt>/etc/pam.conf</tt> (see the
|
|
<bf/Linux-PAM/ System Administrators' Guide). Following a successful
|
|
return (<tt/PAM_SUCCESS/) the contents of <tt/*pamh/ is a handle that
|
|
provides continuity for successive calls to the <bf/Linux-PAM/
|
|
library. The arguments expected by <tt/pam_start/ are as follows: the
|
|
<tt/service_name/ of the program, the <tt/user/name of the individual
|
|
to be authenticated, a pointer to an application-supplied
|
|
<tt/pam_conv/ structure and a pointer to a <tt/pam_handle_t/
|
|
<em/pointer/.
|
|
|
|
<p>
|
|
The <tt>pam_conv</tt> structure is discussed more fully in the section
|
|
<ref id="the-conversation-function" name="below">. The
|
|
<tt>pam_handle_t</tt> is a <em>blind</em> structure and the
|
|
application should not attempt to probe it directly for information.
|
|
Instead the <bf>Linux-PAM</bf> library provides the functions
|
|
<tt>pam_set_item</tt> and <tt>pam_get_item</tt>. These functions are
|
|
documented below.
|
|
|
|
<sect2>Termination of the library
|
|
<label id="pam-end-section">
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_end(pam_handle_t *pamh, int pam_status);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function is the last function an application should call in the
|
|
<bf>Linux-PAM</bf> library. Upon return the handle <tt/pamh/ is no
|
|
longer valid and all memory associated with it will be invalid (likely
|
|
to cause a segmentation fault if accessed).
|
|
|
|
<p>
|
|
Under normal conditions the argument <tt/pam_status/ has the value
|
|
PAM_SUCCESS, but in the event of an unsuccessful application for
|
|
service the appropriate <bf/Linux-PAM/ error-return value should be
|
|
used here. Note, <tt/pam_end()/ unconditionally shuts down the
|
|
authentication stack associated with the <tt/pamh/ handle. The value
|
|
taken by <tt/pam_status/ is used as an argument to the module specific
|
|
callback functions, <tt/cleanup()/ (see the <bf/Linux-PAM/ <htmlurl
|
|
url="pam_modules.html" name="Module Developers' Guide">). In this way,
|
|
the module can be given notification of the pass/fail nature of the
|
|
tear-down process, and perform any last minute tasks that are
|
|
appropriate to the module before it is unlinked.
|
|
|
|
<sect2>Setting PAM items
|
|
<label id="pam-set-item-section">
|
|
|
|
<p>
|
|
<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 following
|
|
<bf/item_type/s:
|
|
|
|
<p><descrip>
|
|
<tag><tt/PAM_SERVICE/</tag>
|
|
The service name
|
|
|
|
<tag><tt/PAM_USER/</tag>
|
|
The user name
|
|
|
|
<tag><tt/PAM_USER_PROMPT/</tag>
|
|
The string used when prompting for a user's name. The default
|
|
value for this string is ``Please enter username: ''.
|
|
|
|
<tag><tt/PAM_TTY/</tag>
|
|
The terminal name: prefixed by <tt>/dev/</tt> if it is a
|
|
device file; for graphical, X-based, applications the value for this
|
|
item should be the <tt/$DISPLAY/ variable.
|
|
|
|
<tag><tt/PAM_RUSER/</tag>
|
|
The requesting user's username
|
|
|
|
<tag><tt/PAM_RHOST/</tag>
|
|
The requesting hostname (the hostname of the machine from which
|
|
the <tt/PAM_RUSER/ is requesting service)
|
|
|
|
<tag><tt/PAM_CONV/</tag>
|
|
The conversation structure (see section <ref
|
|
id="the-conversation-function" name="below">)
|
|
|
|
<tag><tt/PAM_FAIL_DELAY/</tag> A function pointer to redirect
|
|
centrally managed failure delays (see section <ref
|
|
id="the-failure-delay-function" name="below">).
|
|
|
|
</descrip>
|
|
|
|
<p>
|
|
For all <tt/item_type/s, other than <tt/PAM_CONV/ and
|
|
<tt/PAM_FAIL_DELAY/, <tt/item/ is a pointer to a <tt><NUL></tt>
|
|
terminated character string. In the case of <tt/PAM_CONV/, <tt/item/
|
|
points to an initialized <tt/pam_conv/ structure (see section <ref
|
|
id="the-conversation-function" name="below">). In the case of
|
|
<tt/PAM_FAIL_DELAY/, <tt/item/ is a function pointer: <tt/void
|
|
(*delay_fn)(int retval, unsigned usec_delay, void *appdata_ptr)/ (see
|
|
section <ref id="the-failure-delay-function" name="below">).
|
|
|
|
<p>
|
|
A successful call to this function returns <tt/PAM_SUCCESS/. However,
|
|
the application should expect one of the following errors:
|
|
|
|
<p>
|
|
<descrip>
|
|
<tag><tt/PAM_SYSTEM_ERR/</tag>
|
|
The <tt/pam_handle_t/ passed as a first argument to this
|
|
function was invalid.
|
|
<tag><tt/PAM_PERM_DENIED/</tag>
|
|
An attempt was made to replace the conversation structure with
|
|
a <tt/NULL/ value.
|
|
<tag><tt/PAM_BUF_ERR/</tag>
|
|
The function ran out of memory making a copy of the item.
|
|
<tag><tt/PAM_BAD_ITEM/</tag>
|
|
The application attempted to set an undefined or inaccessible
|
|
item.
|
|
</descrip>
|
|
|
|
<sect2>Getting PAM items
|
|
<label id="pam-get-item-section">
|
|
|
|
<p>
|
|
<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 indicated
|
|
<tt/item_type/. Upon successful return, <tt/*item/ contains a pointer
|
|
to the value of the corresponding item. Note, this is a pointer to
|
|
the <em/actual/ data and should <em/not/ be <tt/free()/'ed or
|
|
over-written!
|
|
|
|
<p>
|
|
A successful call is signaled by a return value of <tt/PAM_SUCCESS/.
|
|
However, the application should expect one of the following errors:
|
|
|
|
<p>
|
|
<descrip>
|
|
<tag><tt/PAM_SYSTEM_ERR/</tag>
|
|
The <tt/pam_handle_t/ passed as a first argument to this
|
|
function was invalid.
|
|
<tag><tt/PAM_PERM_DENIED/</tag>
|
|
The value of <tt/item/ was <tt/NULL/.
|
|
<tag><tt/PAM_BAD_ITEM/</tag>
|
|
The application attempted to set an undefined or inaccessible
|
|
item.
|
|
</descrip>
|
|
|
|
<p>
|
|
Note, in the case of an error, the contents of <tt/item/ is not
|
|
modified - that is, it retains its pre-call value. One should take
|
|
care to initialize this value prior to calling
|
|
<tt/pam_get_item()/. Since, if its value - despite the
|
|
<tt/pam_get_item()/ function failing - is to be used the consequences
|
|
are undefined.
|
|
|
|
<sect2>Understanding errors
|
|
<label id="pam-strerror-section">
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern const char *pam_strerror(pam_handle_t *pamh, int errnum);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function returns some text describing the <bf>Linux-PAM</bf>
|
|
error associated with the argument <tt/errnum/. If the error is not
|
|
recognized ``<tt/Unknown Linux-PAM error/'' is returned.
|
|
|
|
<sect2>Planning for delays
|
|
<label id="the-failure-delay-function">
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_fail_delay(pam_handle_t *pamh, unsigned int micro_sec);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<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
|
|
application 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 relevant <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/ (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.
|
|
|
|
<p>
|
|
For applications written with a single thread that are event driven in
|
|
nature, <tt/libpam/ generating this delay may be undesirable. Instead,
|
|
the application may want to register the delay in some other way. For
|
|
example, in a single threaded server that serves multiple
|
|
authentication requests from a single event loop, the application
|
|
might want to simply mark a given connection as blocked until an
|
|
application timer expires. For this reason, <bf/Linux-PAM/ supplies
|
|
the <tt/PAM_FAIL_DELAY/ item. It can be queried and set with
|
|
<tt/pam_get_item()/ and <tt/pam_set_item()/ respectively. The value
|
|
used to set it should be a function pointer of the following
|
|
prototype:
|
|
|
|
<tscreen>
|
|
<verb>
|
|
void (*delay_fn)(int retval, unsigned usec_delay, void *appdata_ptr);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
The arguments being the <tt/retval/ return code of the module stack,
|
|
the <tt/usec_delay/ micro-second delay that libpam is requesting and
|
|
the <tt/appdata_ptr/ that the application has associated with the
|
|
current <tt/pamh/ (<tt/pam_handle_t/). This last value was set by the
|
|
application when it called <tt/pam_start/ or explicitly with
|
|
<tt/pam_set_item(... , PAM_CONV, ...)/. Note, if <tt/PAM_FAIL_DELAY/
|
|
is unset (or set to <tt/NULL/), then <tt/libpam/ will perform any
|
|
delay.
|
|
|
|
<sect2>Authenticating the user
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_authenticate(pam_handle_t *pamh, int flags);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function serves as an interface to the authentication mechanisms
|
|
of the loaded modules. The single <em/optional/ flag, which may be
|
|
logically OR'd with <tt/PAM_SILENT/, takes the following value,
|
|
|
|
<p><descrip>
|
|
|
|
<tag><tt/PAM_DISALLOW_NULL_AUTHTOK/</tag>
|
|
Instruct the authentication modules to return
|
|
<tt/PAM_AUTH_ERR/ if the user does not have a registered
|
|
authorization token---it is set to <tt/NULL/ in the system database.
|
|
</descrip>
|
|
|
|
<p>
|
|
The value returned by this function is one of the following:
|
|
|
|
<p><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>
|
|
|
|
<p>
|
|
If one or more of the authentication modules fails to load, for
|
|
whatever reason, this function will return <tt/PAM_ABORT/.
|
|
|
|
<sect2>Setting user credentials
|
|
<label id="pam-setcred-section">
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_setcred(pam_handle_t *pamh, int flags);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function is used to set the module-specific credentials of the
|
|
user. It is usually called after the user has been authenticated,
|
|
after the account management function has been called but before a
|
|
session has been opened for the user.
|
|
|
|
<p>
|
|
A credential is something that the user possesses. It is some
|
|
property, such as a <em>Kerberos</em> ticket, or a supplementary group
|
|
membership that make up the uniqueness of a given user. On a Linux
|
|
(or UN*X system) the user's <tt>UID</tt> and <tt>GID</tt>'s are
|
|
credentials too. However, it has been decided that these properties
|
|
(along with the default supplementary groups of which the user is a
|
|
member) are credentials that should be set directly by the application
|
|
and not by PAM.
|
|
|
|
<p>
|
|
This function simply calls the <tt/pam_sm_setcred/ functions of each
|
|
of the loaded modules. Valid <tt/flags/, any 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>
|
|
A successful return is signalled with <tt/PAM_SUCCESS/. Errors that
|
|
are especially relevant to this function are the following:
|
|
|
|
<p><descrip>
|
|
<tag><tt/PAM_CRED_UNAVAIL/</tag>
|
|
A 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 an authentication module.
|
|
<tag><tt/PAM_CRED_ERR/</tag>
|
|
A module was unable to set the credentials of the user.
|
|
</descrip>
|
|
|
|
<sect2>Account management
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_acct_mgmt(pam_handle_t *pamh, int flags);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function is typically called after the user has been
|
|
authenticated. It establishes whether the user's account is healthy.
|
|
That is to say, whether the user's account is still active and whether
|
|
the user is permitted to gain access to the system at this time.
|
|
Valid flags, any one of which, may be logically OR'd with
|
|
<tt/PAM_SILENT/, and are the same as those applicable to the
|
|
<tt/flags/ argument of <tt/pam_authenticate/.
|
|
|
|
<p>
|
|
This function simply calls the corresponding functions of each of the
|
|
loaded modules, as instructed by the configuration file,
|
|
<tt>/etc/pam.conf</tt>.
|
|
|
|
<p>
|
|
The normal response from this function is <tt/PAM_SUCCESS/, however,
|
|
specific failures are indicated by the following error returns:
|
|
|
|
<descrip>
|
|
<tag><tt/PAM_AUTHTOKEN_REQD/</tag>
|
|
The user <bf/is/ valid but their authentication token has
|
|
<em/expired/. The correct response to this return-value is to require
|
|
that the user satisfies the <tt/pam_chauthtok()/ function before
|
|
obtaining service. It may not be possible for some applications to do
|
|
this. In such cases, the user should be denied access until such time
|
|
as they can update their password.
|
|
|
|
<tag><tt/PAM_ACCT_EXPIRED/</tag>
|
|
The user is no longer permitted to access the system.
|
|
<tag><tt/PAM_AUTH_ERR/</tag>
|
|
There was an authentication error.
|
|
|
|
<tag><tt/PAM_PERM_DENIED/</tag>
|
|
The user is not permitted to gain access at this time.
|
|
<tag><tt/PAM_USER_UNKNOWN/</tag>
|
|
The user is not known to a module's account management
|
|
component.
|
|
|
|
</descrip>
|
|
|
|
<sect2>Updating authentication tokens
|
|
<label id="pam-chauthtok-section">
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_chauthtok(pam_handle_t *pamh, const int flags);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function is used to change the authentication token for a given
|
|
user (as indicated by the state associated with the handle,
|
|
<tt/pamh/). The following is a valid but optional flag which may be
|
|
logically OR'd with <tt/PAM_SILENT/,
|
|
|
|
<descrip>
|
|
<tag><tt/PAM_CHANGE_EXPIRED_AUTHTOK/</tag>
|
|
This argument indicates to the modules that the users
|
|
authentication token (password) should only be changed if it has
|
|
expired.
|
|
</descrip>
|
|
|
|
<p>
|
|
Note, if this argument is not passed, the application requires that
|
|
<em/all/ authentication tokens are to be changed.
|
|
|
|
<p>
|
|
<tt/PAM_SUCCESS/ is the only successful return value, valid
|
|
error-returns are:
|
|
|
|
<descrip>
|
|
<tag><tt/PAM_AUTHTOK_ERR/</tag>
|
|
A module was unable to obtain the new authentication token.
|
|
|
|
<tag><tt/PAM_AUTHTOK_RECOVERY_ERR/</tag>
|
|
A module was unable to obtain the old authentication token.
|
|
|
|
<tag><tt/PAM_AUTHTOK_LOCK_BUSY/</tag>
|
|
One or more of the modules was unable to change the
|
|
authentication token since it is currently locked.
|
|
|
|
<tag><tt/PAM_AUTHTOK_DISABLE_AGING/</tag>
|
|
Authentication token aging has been disabled for at least one
|
|
of the modules.
|
|
|
|
<tag><tt/PAM_PERM_DENIED/</tag>
|
|
Permission denied.
|
|
|
|
<tag><tt/PAM_TRY_AGAIN/</tag>
|
|
Not all of the modules were in a position to update the
|
|
authentication token(s). In such a case none of the user's
|
|
authentication tokens are updated.
|
|
|
|
<tag><tt/PAM_USER_UNKNOWN/</tag>
|
|
The user is not known to the authentication token changing
|
|
service.
|
|
|
|
</descrip>
|
|
|
|
<sect2>Session initialization
|
|
<label id="pam-open-session-section">
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_open_session(pam_handle_t *pamh, int flags);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function is used to indicate that an authenticated session has
|
|
begun. It is used to inform the modules that the user is currently in
|
|
a session. It should be possible for the <bf>Linux-PAM</bf> library
|
|
to open a session and close the same session (see section <ref
|
|
id="pam-close-session-section" name="below">) from different
|
|
applications.
|
|
|
|
<p>
|
|
Currently, this function simply calls each of the corresponding
|
|
functions of the loaded modules. The only valid flag is
|
|
<tt/PAM_SILENT/ and this is, of course, <em/optional/.
|
|
|
|
<p>
|
|
If any of the <em/required/ loaded modules are unable to open a
|
|
session for the user, this function will return <tt/PAM_SESSION_ERR/.
|
|
|
|
<sect2>Terminating sessions
|
|
<label id="pam-close-session-section">
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_close_session(pam_handle_t *pamh, int flags);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function is used to indicate that an authenticated session has
|
|
ended. It is used to inform the modules that the user is exiting a
|
|
session. It should be possible for the <bf>Linux-PAM</bf> library to
|
|
open a session and close the same session from different applications.
|
|
|
|
<p>
|
|
This function simply calls each of the corresponding functions of the
|
|
loaded modules in the same order that they were invoked with
|
|
<tt/pam_open_session()/. The only valid flag is <tt/PAM_SILENT/ and
|
|
this is, of course, <em/optional/.
|
|
|
|
<p>
|
|
If any of the <em/required/ loaded modules are unable to close a
|
|
session for the user, this function will return <tt/PAM_SESSION_ERR/.
|
|
|
|
<sect2>Setting PAM environment variables
|
|
<label id="pam-putenv-section">
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_putenv(pam_handle_t *pamh, const char *name_value);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This function attempts to (re)set a <bf/Linux-PAM/ environment
|
|
variable. The <tt/name_value/ argument is a single <tt/NUL/ terminated
|
|
string of one of the following forms:
|
|
<descrip>
|
|
<tag>``<tt/NAME=value of variable/''</tag>
|
|
|
|
In this case the environment variable of the given <tt/NAME/ is set to
|
|
the indicated value: ``<tt/value of variable/''. If this variable is
|
|
already known, it is overwritten. Otherwise it is added to the
|
|
<bf/Linux-PAM/ environment.
|
|
|
|
<tag>``<tt/NAME=/''</tag>
|
|
|
|
This function sets the variable to an empty value. It is listed
|
|
separately to indicate that this is the correct way to achieve such a
|
|
setting.
|
|
|
|
<tag>``<tt/NAME/''</tag>
|
|
|
|
Without an `<tt/=/' the <tt/pam_putenv()/ function will delete the
|
|
corresponding variable from the <bf/Linux-PAM/ environment.
|
|
|
|
</descrip>
|
|
|
|
<p>
|
|
Success is indicated with a return value of <tt/PAM_SUCCESS/. Failure
|
|
is indicated by one of the following returns:
|
|
|
|
<descrip>
|
|
<tag><tt/PAM_PERM_DENIED/</tag>
|
|
name given is a <tt/NULL/ pointer
|
|
|
|
<tag><tt/PAM_BAD_ITEM/</tag>
|
|
variable requested (for deletion) is not currently set
|
|
|
|
<tag><tt/PAM_ABORT/</tag>
|
|
the <bf/Linux-PAM/ handle, <tt/pamh/, is corrupt
|
|
|
|
<tag><tt/PAM_BUF_ERR/</tag>
|
|
failed to allocate memory when attempting update
|
|
|
|
</descrip>
|
|
|
|
<sect2>Getting a PAM environment variable
|
|
<label id="pam-getenv-section">
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern const char *pam_getenv(pam_handle_t *pamh, const char *name);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
<em>
|
|
Warning, the environment support in <bf/Linux-PAM/ is based solely
|
|
on a six-line email from the developers at Sun. Its interface is
|
|
likely to be generally correct, however, the details are likely to be
|
|
changed as more information becomes available.
|
|
</em>
|
|
|
|
<p>
|
|
Obtain the value of the indicated <bf/Linux-PAM/ environment
|
|
variable. On error, internal failure or the unavailability of the
|
|
given variable (unspecified), this function simply returns <tt/NULL/.
|
|
|
|
<sect2>Getting the PAM environment
|
|
<label id="pam-getenvlist-section">
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern const char * const *pam_getenvlist(pam_handle_t *pamh);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
<em>
|
|
Warning, the environment support in <bf/Linux-PAM/ is based solely
|
|
on a six line email from the developers at Sun. Its interface is
|
|
likely to be generally correct, however, the details are likely to be
|
|
changed as more information becomes available.
|
|
</em>
|
|
|
|
<p>
|
|
This function returns a pointer to the complete <tt/Linux-PAM/
|
|
environment. It is a pointer to a <em/read-only/ list of
|
|
<em/read-only/ environment variables. It should be noted that this
|
|
memory will become invalid after a call to <tt/pam_end()/ (see the
|
|
section <ref id="pam-end-section" name="above">). If application
|
|
wishes to make use of this list after such a call, it should first
|
|
make a copy of all the set variables. (A function that performs such a
|
|
transcription is to be found in <tt/libpam_misc/.)
|
|
|
|
<sect1>What is expected of an application
|
|
|
|
<sect2>The conversation function
|
|
<label id="the-conversation-function">
|
|
|
|
<p>
|
|
An application must provide a ``conversation function''. It is used
|
|
for direct communication between a loaded module and the application
|
|
and will typically provide a means for the module to prompt the user
|
|
for a password etc. . The structure, <tt/pam_conv/, is defined by
|
|
including <tt><security/pam_appl.h></tt>; to be,
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
struct pam_conv {
|
|
int (*conv)(int num_msg,
|
|
const struct pam_message **msg,
|
|
struct pam_response **resp,
|
|
void *appdata_ptr);
|
|
void *appdata_ptr;
|
|
};
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
It is initialized by the application before it is passed to the
|
|
library. The <em/contents/ of this structure are attached to the
|
|
<tt/*pamh/ handle. The point of this argument is to provide a
|
|
mechanism for any loaded module to interact directly with the
|
|
application program. This is why it is called a <em/conversation/
|
|
structure.
|
|
|
|
<p>
|
|
When a module calls the referenced <tt/conv()/ function, the argument
|
|
<tt/*appdata_ptr/ is set to the second element of this structure.
|
|
|
|
<p>
|
|
The other arguments of a call to <tt/conv()/ concern the information
|
|
exchanged by module and application. That is to say, <tt/num_msg/
|
|
holds the length of the array of pointers, <tt/msg/. After a
|
|
successful return, the pointer <tt/*resp/ points to an array of
|
|
<tt/pam_response/ structures, holding the application supplied text.
|
|
Note, <tt/*resp/ is an <tt/struct pam_response/ array and <em/not/ an
|
|
array of pointers.
|
|
|
|
<p>
|
|
The message (from the module to the application) passing structure is
|
|
defined by <tt><security/pam_appl.h></tt> as:
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
struct pam_message {
|
|
int msg_style;
|
|
const char *msg;
|
|
};
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
Valid choices for <tt/msg_style/ are:
|
|
|
|
<p><descrip>
|
|
<tag><tt/PAM_PROMPT_ECHO_OFF/</tag>
|
|
Obtain a string without echoing any text
|
|
<tag><tt/PAM_PROMPT_ECHO_ON/</tag>
|
|
Obtain a string whilst echoing text
|
|
<tag><tt/PAM_ERROR_MSG/</tag>
|
|
Display an error
|
|
<tag><tt/PAM_TEXT_INFO/</tag>
|
|
Display some text.
|
|
</descrip>
|
|
|
|
<p>
|
|
The point of having an array of messages is that it becomes possible
|
|
to pass a number of things to the application in a single call from
|
|
the module. It can also be convenient for the application that related
|
|
things come at once: a windows based application can then present a
|
|
single form with many messages/prompts on at once.
|
|
|
|
<p>
|
|
The response (from the application to the module) passing structure is
|
|
defined by including <tt><security/pam_appl.h></tt> as:
|
|
|
|
<p><tscreen><verb>
|
|
struct pam_response {
|
|
char *resp;
|
|
int resp_retcode;
|
|
};
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Currently, there are no definitions for <tt/resp_retcode/ values; the
|
|
normal value is <tt/0/.
|
|
|
|
<p>
|
|
Prior to the 0.59 release of Linux-PAM, the length of the returned
|
|
<tt/pam_response/ array was equal to the number of <em/prompts/ (types
|
|
<tt/PAM_PROMPT_ECHO_OFF/ and <tt/PAM_PROMPT_ECHO_ON/) in the
|
|
<tt/pam_message/ array with which the conversation function was
|
|
called. This meant that it was not always necessary for the module to
|
|
<tt/free(3)/ the responses if the conversation function was only used
|
|
to display some text.
|
|
|
|
<p>
|
|
Post Linux-PAM-0.59 (and in the interests of compatibility with
|
|
Sunsoft). The number of responses is always equal to the <tt/num_msg/
|
|
conversation function argument. This is slightly easier to program
|
|
but does require that the response array is <tt/free(3)/'d after every
|
|
call to the conversation function. The index of the responses
|
|
corresponds directly to the prompt index in the <tt/pam_message/
|
|
array.
|
|
|
|
<p>
|
|
The maximum length of the <tt/pam_msg.msg/ and <tt/pam_response.resp/
|
|
character strings is <tt/PAM_MAX_MSG_SIZE/. (This is not enforced by
|
|
Linux-PAM.)
|
|
|
|
<p>
|
|
<tt/PAM_SUCCESS/ is the expected return value of this
|
|
function. However, should an error occur the application should not
|
|
set <tt/*resp/ but simply return <tt/PAM_CONV_ERR/.
|
|
|
|
<p>
|
|
Note, if an application wishes to use two conversation functions, it
|
|
should activate the second with a call to <tt/pam_set_item()/.
|
|
|
|
<p>
|
|
<bf>Notes:</bf> New item types are being added to the conversation
|
|
protocol. Currently Linux-PAM supports: <tt>PAM_BINARY_PROMPT</tt>
|
|
and <tt>PAM_BINARY_MSG</tt>. These two are intended for server-client
|
|
hidden information exchange and may be used as an interface for
|
|
maching-machine authentication.
|
|
|
|
<sect1>Programming notes
|
|
|
|
<p>
|
|
Note, all of the authentication service function calls accept the
|
|
token <tt/PAM_SILENT/, which instructs the modules to not send
|
|
messages to the application. This token can be logically OR'd with any
|
|
one of the permitted tokens specific to the individual function calls.
|
|
<tt/PAM_SILENT/ does not override the prompting of the user for
|
|
passwords etc., it only stops informative messages from being
|
|
generated.
|
|
|
|
<sect>Security issues of <bf>Linux-PAM</bf>
|
|
|
|
<p>
|
|
PAM, from the perspective of an application, is a convenient API for
|
|
authenticating users. PAM modules generally have no increased
|
|
privilege over that possessed by the application that is making use of
|
|
it. For this reason, the application must take ultimate responsibility
|
|
for protecting the environment in which PAM operates.
|
|
|
|
<p>
|
|
A poorly (or maliciously) written application can defeat any
|
|
<bf/Linux-PAM/ module's authentication mechanisms by simply ignoring
|
|
it's return values. It is the applications task and responsibility to
|
|
grant privileges and access to services. The <bf/Linux-PAM/ library
|
|
simply assumes the responsibility of <em/authenticating/ the user;
|
|
ascertaining that the user <em/is/ who they say they are. Care should
|
|
be taken to anticipate all of the documented behavior of the
|
|
<bf/Linux-PAM/ library functions. A failure to do this will most
|
|
certainly lead to a future security breach.
|
|
|
|
<sect1>Care about standard library calls
|
|
|
|
<p>
|
|
In general, writers of authorization-granting applications should
|
|
assume that each module is likely to call any or <em/all/ `libc'
|
|
functions. For `libc' functions that return pointers to
|
|
static/dynamically allocated structures (ie. the library allocates the
|
|
memory and the user is not expected to `<tt/free()/' it) any module
|
|
call to this function is likely to corrupt a pointer previously
|
|
obtained by the application. The application programmer should either
|
|
re-call such a `libc' function after a call to the <bf/Linux-PAM/
|
|
library, or copy the structure contents to some safe area of memory
|
|
before passing control to the <bf/Linux-PAM/ library.
|
|
|
|
<p>
|
|
Two important function classes that fall into this category are
|
|
<tt>getpwnam(3)</tt> and <tt>syslog(3)</tt>.
|
|
|
|
<sect1>Choice of a service name
|
|
|
|
<p>
|
|
When picking the <em/service-name/ that corresponds to the first entry
|
|
in the <bf/Linux-PAM/ configuration file, the application programmer
|
|
should <bf/avoid/ the temptation of choosing something related to
|
|
<tt/argv[0]/. It is a trivial matter for any user to invoke any
|
|
application on a system under a different name and this should not be
|
|
permitted to cause a security breach.
|
|
|
|
<p>
|
|
To invoke some <tt/target/ application by another name, the user may
|
|
symbolically link the target application with the desired name. To be
|
|
precise all the user need do is,
|
|
<tscreen>
|
|
<verb>
|
|
ln -s /target/application ./preferred_name
|
|
</verb>
|
|
</tscreen>
|
|
and then <em/run/ <tt>./preferred_name</tt>
|
|
|
|
<p>
|
|
By studying the <bf/Linux-PAM/ configuration file(s), an attacker can
|
|
choose the <tt/preferred_name/ to be that of a service enjoying
|
|
minimal protection; for example a game which uses <bf/Linux-PAM/ to
|
|
restrict access to certain hours of the day. If the service-name were
|
|
to be linked to the filename under which the service was invoked, it
|
|
is clear that the user is effectively in the position of dictating
|
|
which authentication scheme the service uses. Needless to say, this
|
|
is not a secure situation.
|
|
|
|
<p>
|
|
The conclusion is that the application developer should carefully
|
|
define the service-name of an application. The safest thing is to make
|
|
it a single hard-wired name.
|
|
|
|
<sect1>The conversation function
|
|
|
|
<p>
|
|
Care should be taken to ensure that the <tt/conv()/ function is
|
|
robust. Such a function is provided in the library <tt/libpam_misc/
|
|
(see <ref id="libpam-misc-section" name="below">).
|
|
|
|
<sect1>The identity of the user
|
|
|
|
<p>
|
|
The <bf/Linux-PAM/ modules will need to determine the identity of the
|
|
user who requests a service, and the identity of the user who grants
|
|
the service. These two users will seldom be the same. Indeed there
|
|
is generally a third user identity to be considered, the new (assumed)
|
|
identity of the user once the service is granted.
|
|
|
|
<p>
|
|
The need for keeping tabs on these identities is clearly an issue of
|
|
security. One convention that is actively used by some modules is
|
|
that the identity of the user requesting a service should be the
|
|
current <tt/uid/ (userid) of the running process; the identity of the
|
|
privilege granting user is the <tt/euid/ (effective userid) of the
|
|
running process; the identity of the user, under whose name the
|
|
service will be executed, is given by the contents of the
|
|
<tt/PAM_USER/ <tt/pam_get_item(3)/.
|
|
|
|
<p>
|
|
For network-serving databases and other applications that provide
|
|
their own security model (independent of the OS kernel) the above
|
|
scheme is insufficient to identify the requesting user.
|
|
|
|
<p>
|
|
A more portable solution to storing the identity of the requesting
|
|
user is to use the <tt/PAM_RUSER/ <tt/pam_get_item(3)/. The
|
|
application should supply this value before attempting to authenticate
|
|
the user with <tt/pam_authenticate()/. How well this name can be
|
|
trusted will ultimately be at the discretion of the local
|
|
administrator (who configures PAM for your application) and a selected
|
|
module may attempt to override the value where it can obtain more
|
|
reliable data. If an application is unable to determine the identity
|
|
of the requesting entity/user, it should not call <tt/pam_set_item(3)/
|
|
to set <tt/PAM_RUSER/.
|
|
|
|
<p>
|
|
In addition to the <tt/PAM_RUSER/ item, the application should supply
|
|
the <tt/PAM_RHOST/ (<em/requesting host/) item. As a general rule, the
|
|
following convention for its value can be assumed: <tt/<unset>/
|
|
= unknown; <tt/localhost/ = invoked directly from the local system;
|
|
<em/other.place.xyz/ = some component of the user's connection
|
|
originates from this remote/requesting host. At present, PAM has no
|
|
established convention for indicating whether the application supports
|
|
a trusted path to communication from this host.
|
|
|
|
<sect1>Sufficient resources
|
|
|
|
<p>
|
|
Care should be taken to ensure that the proper execution of an
|
|
application is not compromised by a lack of system resources. If an
|
|
application is unable to open sufficient files to perform its service,
|
|
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.
|
|
|
|
<p>
|
|
This is also true of conversation prompts. The application should not
|
|
accept prompts of arbitrary length with out checking for resource
|
|
allocation failure and dealing with such extreme conditions gracefully
|
|
and in a mannor that preserves the PAM API. Such tolerance may be
|
|
especially important when attempting to track a malicious adversary.
|
|
|
|
<sect>A library of miscellaneous helper functions
|
|
<label id="libpam-misc-section">
|
|
|
|
<p>
|
|
To aid the work of the application developer a library of
|
|
miscellaneous functions is provided. It is called <tt/libpam_misc/,
|
|
and contains functions for allocating memory (securely), a text based
|
|
conversation function, and routines for enhancing the standard
|
|
PAM-environment variable support.
|
|
|
|
<sect1>Requirements
|
|
|
|
<p>
|
|
The functions, structures and macros, made available by this library
|
|
can be defined by including <tt><security/pam_misc.h></tt>. It
|
|
should be noted that this library is specific to <bf/Linux-PAM/ and is
|
|
not referred to in the defining DCE-RFC (see <ref id="bibliography"
|
|
name="the bibliography">) below.
|
|
|
|
<sect1>Functions supplied
|
|
|
|
<sect2>Safe string duplication
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern char *xstrdup(const char *s)
|
|
</verb>
|
|
</tscreen>
|
|
Return a duplicate copy of the <tt/NUL/ terminated string,
|
|
<tt/s/. <tt/NULL/ is returned if there is insufficient memory
|
|
available for the duplicate or if <tt/s=NULL/.
|
|
|
|
<sect2>A text based conversation function
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern int misc_conv(int num_msg, const struct pam_message **msgm,
|
|
struct pam_response **response, void *appdata_ptr);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<p>
|
|
This is a function that will prompt the user with the appropriate
|
|
comments and obtain the appropriate inputs as directed by
|
|
authentication modules.
|
|
|
|
<p>
|
|
In addition to simply slotting into the appropriate <tt/struct
|
|
pam_conv/, this function provides some time-out facilities. The
|
|
function exports five variables that can be used by an application
|
|
programmer to limit the amount of time this conversation function will
|
|
spend waiting for the user to type something.
|
|
|
|
<p>
|
|
The five variables are as follows:
|
|
<descrip>
|
|
<tag><tt>extern time_t pam_misc_conv_warn_time;</tt></tag>
|
|
|
|
This variable contains the <em/time/ (as returned by <tt/time()/) that
|
|
the user should be first warned that the clock is ticking. By default
|
|
it has the value <tt/0/, which indicates that no such warning will be
|
|
given. The application may set its value to sometime in the future,
|
|
but this should be done prior to passing control to the <bf/Linux-PAM/
|
|
library.
|
|
|
|
<tag><tt>extern const char *pam_misc_conv_warn_line;</tt></tag>
|
|
|
|
Used in conjuction with <tt/pam_misc_conv_warn_time/, this variable is
|
|
a pointer to the string that will be displayed when it becomes time to
|
|
warn the user that the timeout is approaching. Its default value is
|
|
``..\a.Time is running out...\n'', but this can be changed
|
|
by the application prior to passing control to <bf/Linux-PAM/.
|
|
|
|
<tag><tt>extern time_t pam_misc_conv_die_time;</tt></tag>
|
|
|
|
This variable contains the <em/time/ (as returned by <tt/time()/) that
|
|
the conversation will time out. By default it has the value <tt/0/,
|
|
which indicates that the conversation function will not timeout. The
|
|
application may set its value to sometime in the future, this should
|
|
be done prior to passing control to the <bf/Linux-PAM/ library.
|
|
|
|
<tag><tt>extern const char *pam_misc_conv_die_line;</tt></tag>
|
|
|
|
Used in conjuction with <tt/pam_misc_conv_die_time/, this variable is
|
|
a pointer to the string that will be displayed when the conversation
|
|
times out. Its default value is ``..\a.Sorry, your time is
|
|
up!\n'', but this can be changed by the application prior to
|
|
passing control to <bf/Linux-PAM/.
|
|
|
|
<tag><tt>extern int pam_misc_conv_died;</tt></tag>
|
|
|
|
Following a return from the <bf/Linux-PAM/ libraray, the value of this
|
|
variable indicates whether the conversation has timed out. A value of
|
|
<tt/1/ indicates the time-out occurred.
|
|
|
|
<tag><tt>extern int (*pam_binary_handler_fn)(const union pam_u_packet_p send,
|
|
union pam_u_packet_p *receive);</tt></tag>
|
|
|
|
This function pointer is initialized to <tt/NULL/ but can be filled
|
|
with a function that provides machine-machine (hidden) message
|
|
exchange. It is intended for use with hidden authentication protocols
|
|
such as RSA or Diffie-Hellman key exchanges. (This is still under
|
|
development.)
|
|
|
|
</descrip>
|
|
|
|
<sect2>Transcribing an environment to that of Linux-PAM
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_misc_paste_env(pam_handle_t *pamh,
|
|
const char * const * user_env);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
This function takes the supplied list of environment pointers and
|
|
<em/uploads/ its contents to the <bf/Linux-PAM/ environment. Success
|
|
is indicated by <tt/PAM_SUCCESS/.
|
|
|
|
<sect2>Saving the Linux-PAM environment for later use
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern char **pam_misc_copy_env(pam_handle_t *pamh);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
This function returns a pointer to a list of environment variables
|
|
that are a direct copy of the <bf/Linux-PAM/ environment. The memory
|
|
associated with these variables are the responsibility of the
|
|
application and should be liberated with a call to
|
|
<tt/pam_misc_drop_env()/.
|
|
|
|
<sect2>Liberating a locally saved environment
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern char **pam_misc_drop_env(char **env);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
This function is defined to complement the <tt/pam_misc_copy_env()/
|
|
function. It liberates the memory associated with <tt/env/,
|
|
<em/overwriting/ with <tt/0/ all memory before <tt/free()/ing it.
|
|
|
|
<sect2>BSD like Linux-PAM environment variable setting
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
extern int pam_misc_setenv(pam_handle_t *pamh, const char *name,
|
|
const char *value, int readonly);
|
|
</verb>
|
|
</tscreen>
|
|
|
|
This function performs a task equivalent to <tt/pam_putenv()/, its
|
|
syntax is, however, more like the BSD style function; <tt/setenv()/.
|
|
The <tt/name/ and <tt/value/ are concatenated with an ``<tt/=/'' to
|
|
form a <tt/name_value/ and passed to <tt/pam_putenv()/. If, however,
|
|
the <bf/Linux-PAM/ variable is already set, the replacement will only
|
|
be applied if the last argument, <tt/readonly/, is zero.
|
|
|
|
<sect>Porting legacy applications
|
|
|
|
<p>
|
|
The following is extracted from an email. I'll tidy it up later.
|
|
|
|
<p>
|
|
The point of PAM is that the application is not supposed to have any
|
|
idea how the attached authentication modules will choose to
|
|
authenticate the user. So all they can do is provide a conversation
|
|
function that will talk directly to the user(client) on the modules'
|
|
behalf.
|
|
|
|
<p>
|
|
Consider the case that you plug a retinal scanner into the login
|
|
program. In this situation the user would be prompted: "please look
|
|
into the scanner". No username or password would be needed - all this
|
|
information could be deduced from the scan and a database lookup. The
|
|
point is that the retinal scanner is an ideal task for a "module".
|
|
|
|
<p>
|
|
While it is true that a pop-daemon program is designed with the POP
|
|
protocol in mind and no-one ever considered attaching a retinal
|
|
scanner to it, it is also the case that the "clean" PAM'ification of
|
|
such a daemon would allow for the possibility of a scanner module
|
|
being be attached to it. The point being that the "standard"
|
|
pop-authentication protocol(s) [which will be needed to satisfy
|
|
inflexible/legacy clients] would be supported by inserting an
|
|
appropriate pam_qpopper module(s). However, having rewritten popd
|
|
once in this way any new protocols can be implemented in-situ.
|
|
|
|
<p>
|
|
One simple test of a ported application would be to insert the
|
|
<tt/pam_permit/ module and see if the application demands you type a
|
|
password... In such a case, <tt/xlock/ would fail to lock the
|
|
terminal - or would at best be a screen-saver, ftp would give password
|
|
free access to all etc.. Neither of these is a very secure thing to
|
|
do, but they do illustrate how much flexibility PAM puts in the hands
|
|
of the local admin.
|
|
|
|
<p>
|
|
The key issue, in doing things correctly, is identifying what is part
|
|
of the authentication procedure (how many passwords etc..) the
|
|
exchange protocol (prefixes to prompts etc., numbers like 331 in the
|
|
case of ftpd) and what is part of the service that the application
|
|
delivers. PAM really needs to have total control in the
|
|
authentication "procedure", the conversation function should only
|
|
deal with reformatting user prompts and extracting responses from raw
|
|
input.
|
|
|
|
<sect>Glossary of PAM related terms
|
|
|
|
<p>
|
|
The following are a list of terms used within this document.
|
|
|
|
<p>
|
|
<descrip>
|
|
|
|
<tag>Authentication token</tag>
|
|
Generally, this is a password. However, a user can authenticate
|
|
him/herself in a variety of ways. Updating the user's authentication
|
|
token thus corresponds to <em>refreshing</em> the object they use to
|
|
authenticate themself with the system. The word password is avoided
|
|
to keep open the possibility that the authentication involves a
|
|
retinal scan or other non-textual mode of challenge/response.
|
|
|
|
<tag>Credentials</tag>
|
|
Having successfully authenticated the user, PAM is able to establish
|
|
certain characteristics/attributes of the user. These are termed
|
|
<em>credentials</em>. Examples of which are group memberships to
|
|
perform privileged tasks with, and <em>tickets</em> in the form of
|
|
environment variables etc. . Some user-credentials, such as the
|
|
user's UID and GID (plus default group memberships) are not deemed to
|
|
be PAM-credentials. It is the responsibility of the application to
|
|
grant these directly.
|
|
|
|
</descrip>
|
|
|
|
<sect>An example application
|
|
|
|
<p>
|
|
To get a flavor of the way a <tt/Linux-PAM/ application is written we
|
|
include the following example. It prompts the user for their password
|
|
and indicates whether their account is valid on the standard output,
|
|
its return code also indicates the success (<tt/0/ for success; <tt/1/
|
|
for failure).
|
|
|
|
<p>
|
|
<tscreen>
|
|
<verb>
|
|
/*
|
|
This program was contributed by Shane Watts
|
|
[modifications by AGM]
|
|
|
|
You need to add the following (or equivalent) to the /etc/pam.conf file.
|
|
# check authorization
|
|
check_user auth required /usr/lib/security/pam_unix_auth.so
|
|
check_user account required /usr/lib/security/pam_unix_acct.so
|
|
*/
|
|
|
|
#include <security/pam_appl.h>
|
|
#include <security/pam_misc.h>
|
|
#include <stdio.h>
|
|
|
|
static struct pam_conv conv = {
|
|
misc_conv,
|
|
NULL
|
|
};
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
pam_handle_t *pamh=NULL;
|
|
int retval;
|
|
const char *user="nobody";
|
|
|
|
if(argc == 2) {
|
|
user = argv[1];
|
|
}
|
|
|
|
if(argc > 2) {
|
|
fprintf(stderr, "Usage: check_user [username]\n");
|
|
exit(1);
|
|
}
|
|
|
|
retval = pam_start("check_user", user, &ero;conv, &ero;pamh);
|
|
|
|
if (retval == PAM_SUCCESS)
|
|
retval = pam_authenticate(pamh, 0); /* is user really user? */
|
|
|
|
if (retval == PAM_SUCCESS)
|
|
retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
|
|
|
|
/* This is where we have been authorized or not. */
|
|
|
|
if (retval == PAM_SUCCESS) {
|
|
fprintf(stdout, "Authenticated\n");
|
|
} else {
|
|
fprintf(stdout, "Not Authenticated\n");
|
|
}
|
|
|
|
if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
|
|
pamh = NULL;
|
|
fprintf(stderr, "check_user: failed to release authenticator\n");
|
|
exit(1);
|
|
}
|
|
|
|
return ( retval == PAM_SUCCESS ? 0:1 ); /* indicate success */
|
|
}
|
|
</verb>
|
|
</tscreen>
|
|
|
|
<sect>Files
|
|
|
|
<p><descrip>
|
|
|
|
<tag><tt>/usr/include/security/pam_appl.h</tt></tag>
|
|
|
|
header file for <bf/Linux-PAM/ applications interface
|
|
|
|
<tag><tt>/usr/include/security/pam_misc.h</tt></tag>
|
|
|
|
header file for useful library functions for making applications
|
|
easier to write
|
|
|
|
<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="bibliography">
|
|
|
|
<p><itemize>
|
|
|
|
<item>The <bf/Linux-PAM/
|
|
<htmlurl url="pam.html" name="System Administrators' Guide">.
|
|
|
|
<item>The <bf/Linux-PAM/
|
|
<htmlurl url="pam_modules.html" name="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.
|
|
|
|
</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> <tt/pam_strerror()/ should be internationalized....
|
|
|
|
<item>
|
|
Note, the <tt/resp_retcode/ of struct <tt/pam_message/, has no
|
|
purpose at the moment. Ideas/suggestions welcome!
|
|
|
|
<item> more security issues are required....
|
|
|
|
</itemize>
|
|
|
|
<sect>Author/acknowledgments
|
|
|
|
<p>
|
|
This document was written by Andrew G. Morgan
|
|
(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_appl.sgml,v 1.5 2001/03/19 01:46:41 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>
|
|
This manual 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-9. 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_appl.sgml,v 1.5 2001/03/19 01:46:41 agmorgan Exp $</tt>
|
|
|
|
</article>
|