pam_modules-3.html
Next
pam_modules-1.html
Previous
pam_modules.html#toc2
Contents
2. What can be expected by the module
Here we list the interface that the conventions that all
Linux-PAM
modules must adhere to.
2.1 Getting and setting
PAM_ITEM
s and
data
First, we cover what the module should expect from the
Linux-PAM
library and a
Linux-PAM
aware
application. Essesntially this
is the
libpam.*
library.
Setting data
Synopsis:
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) );
The modules may be dynamically loadable objects. In general such files
should not contain
static
variables. This and the subsequent
function provide a mechanism for a module to associate some data with
the handle
pamh
. Typically a module will call the
pam_set_data()
function to register some data under a (hopefully)
unique
module_data_name
. The data is available for use by other
modules too but
not
by an application.
The function
cleanup()
is associated with the
data
and, if
non-
NULL
, it is called when this data is over-written or
following a call to
pam_end()
(see the Linux-PAM Application
Developers' Guide).
The
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
pam_end()
is called by the module, the
error_status
carries the return value of the
pam_authenticate()
or other
libpam
function as appropriate. Based on this value the Kerberos
module may choose to delete the ticket file (
authentication
failure
) or leave it in place.
The
error_status
may have been logically OR'd with either of the
following two values:
PAM_DATA_REPLACE
When a data item is being replaced (through a second call to
pam_set_data()
) this mask is used. Otherwise, the call is assumed
to be from
pam_end()
.
PAM_DATA_SILENT
Which indicates that the process would prefer to perform the
cleanup()
quietly. That is, discourages logging/messages to the
user.
Getting data
Synopsis:
extern int pam_get_data(const pam_handle_t *pamh,
const char *module_data_name,
const void **data);
This function together with the previous one provides a method of
associating module-specific data with the handle
pamh
. A
successful call to
pam_get_data
will result in
*data
pointing to the data associated with the
module_data_name
. Note,
this data is
not
a copy and should be treated as
constant
by the module.
Note, if there is an entry but it has the value
NULL
, then this
call returns
PAM_NO_MODULE_DATA
.
Setting items
Synopsis:
extern int pam_set_item(pam_handle_t *pamh,
int item_type,
const void *item);
This function is used to (re)set the value of one of the
item_type
s.  The reader is urged to read the entry for this
function in the
Linux-PAM
application developers' manual.
In addition to the
item
s listed there, the module can set the
following two
item_type
s:
PAM_AUTHTOK
The authentication token (often a password). This token should be
ignored by all module functions besides
pam_sm_authenticate()
and
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.
PAM_OLDAUTHTOK
The old authentication token. This token should be ignored by all
module functions except
pam_sm_chauthtok()
.
Both of these items are reset before returning to the application.
When resetting these items, the
Linux-PAM
library first writes
0
's to the current tokens and then
free()
's the associated
memory.
The return values for this function are listed in the
Linux-PAM
Application Developers' Guide.
Getting items
Synopsis:
extern int pam_get_item(const pam_handle_t *pamh,
int item_type,
const void **item);
This function is used to obtain the value of the specified
item_type
. It is better documented in the
Linux-PAM
Application Developers' Guide. However, there are three things worth
stressing here:
Generally, if the module wishes to obtain the name of the user, it
should not use this function, but instead perform a call to
pam_get_user()
(see section
#pam-get-user
below
).
The module is additionally privileged to read the authentication
tokens,
PAM_AUTHTOK
and
PAM_OLDAUTHTOK
(see the section
above on
pam_set_data()
).
The module should
not
free()
or alter the data pointed to by
*item
after a successful return from
pam_get_item()
. This
pointer points directly at the data contained within the
*pamh
structure.  Should a module require that a change is made to the this
ITEM
it should make the appropriate call to
pam_set_item()
.
The
conversation
mechanism
Following the call
pam_get_item(pamh,PAM_CONV,&item)
, the
pointer
item
points to a structure containing an a pointer to a
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.
The reader is strongly urged to read the more complete description of
the
pam_conv
structure, written from the perspective of the
application developer, in the
Linux-PAM
Application Developers'
Guide.
The return values for this function are listed in the
Linux-PAM
Application Developers' Guide.
The
pam_response
structure returned after a call to the
pam_conv
function must be
free()
'd by the module. Since the
call to the conversation function originates from the module, it is
clear that this
pam_response
structure could be either statically
or dynamically (using
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
malloc()
family of commands and
must
be
free()
'd by the
module.
If the
pam_conv
mechanism is used to enter authentication tokens,
the module should either pass the result to the
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
0
's, and
then
free()
'd.
There is a handy macro
_pam_drop_reply()
to be found in
<security/_pam_macros.h>
that can be used to
conveniently cleanup a
pam_response
structure. (Note, this
include file is specific to the Linux-PAM sources, and whilst it will
work with Sun derived PAM implementations, it is not generally
distributed by Sun.)
Getting the name of a user
Synopsis:
extern int pam_get_user(pam_handle_t *pamh,
const char **user,
const char *prompt);
This is a
Linux-PAM
library function that returns the
(prospective) name of the user. To determine the username it does the
following things, in this order:
checks what
pam_get_item(pamh, PAM_USER, ... );
would have
returned. If this is not
NULL
this is what it returns. Otherwise,
obtains a username from the application via the
pam_conv
mechanism, it prompts the user with the first non-
NULL
string in
the following list:
The
prompt
argument passed to the function
What is returned by
pam_get_item(pamh,PAM_USER_PROMPT, ... );
The default prompt: ``Please enter username: ''
By whatever means the username is obtained, a pointer to it is
returned as the contents of
*user
. Note, this memory should
not
be
free()
'd by the module. Instead, it will be liberated
on the next call to
pam_get_user()
, or by
pam_end()
when the
application ends its interaction with
Linux-PAM
.
Also, in addition, it should be noted that this function sets the
PAM_USER
item that is associated with the
pam_[gs]et_item()
function.
The return value of this function is one of the following:
PAM_SUCCESS
- username obtained.
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
pam_get_user()
that obtains this return code,
should return
PAM_INCOMPLETE
and be prepared (when invoked the
next time) to recall
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.
PAM_CONV_ERR
- the conversation method supplied by the
application failed to obtain the username.
Setting a Linux-PAM environment variable
Synopsis:
extern int pam_putenv(pam_handle_t *pamh, const char *name_value);
Linux-PAM
comes equipped with a series of functions for
maintaining a set of
environment
variables. The environment is
initialized by the call to
pam_start()
and is
erased
with a
call to
pam_end()
.  This
environment
is associated with the
pam_handle_t
pointer returned by the former call.
The default environment is all but empty. It contains a single
NULL
pointer, which is always required to terminate the
variable-list.  The
pam_putenv()
function can be used to add a
new environment variable, replace an existing one, or delete an old
one.
Adding/replacing a variable
To add or overwrite a
Linux-PAM
environment variable the value of
the argument
name_value
, should be of the following form:
name_value="VARIABLE=VALUE OF VARIABLE"
Here,
VARIABLE
is the environment variable's name and what
follows the `
=
' is its (new) value. (Note, that
"VARIABLE="
is a valid value for
name_value
, indicating that the variable is
set to
""
.)
Deleting a variable
To delete a
Linux-PAM
environment variable the value of
the argument
name_value
, should be of the following form:
name_value="VARIABLE"
Here,
VARIABLE
is the environment variable's name and the absence
of an `
=
' indicates that the variable should be removed.
In all cases
PAM_SUCCESS
indicates success.
Getting a Linux-PAM environment variable
Synopsis:
extern const char *pam_getenv(pam_handle_t *pamh, const char *name);
This function can be used to return the value of the given
variable. If the returned value is
NULL
, the variable is not
known.
Listing the Linux-PAM environment
Synopsis:
extern char * const *pam_getenvlist(pam_handle_t *pamh);
This function returns a pointer to the entire
Linux-PAM
environment array.  At first sight the
type
of the returned data
may appear a little confusing.  It is basically a
read-only
array
of character pointers, that lists the
NULL
terminated list of
environment variables set so far.
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
pam_end()
otherwise all the variable information
will be lost. (There are functions in
libpam_misc
for this
purpose:
pam_misc_copy_env()
and
pam_misc_drop_env()
.)
2.2 Other functions provided by
libpam
Understanding errors
extern const char *pam_strerror(pam_handle_t *pamh, int errnum);
This function returns some text describing the
Linux-PAM
error
associated with the argument
errnum
.  If the error is not
recognized
``Unknown Linux-PAM error''
is returned.
Planning for delays
extern int pam_fail_delay(pam_handle_t *pamh, unsigned int
micro_sec)
This function is offered by
Linux-PAM
to facilitate time delays
following a failed call to
pam_authenticate()
and before control
is returned to the application. When using this function the module
programmer should check if it is available with,
#ifdef PAM_FAIL_DELAY
....
#endif /* PAM_FAIL_DELAY */
Generally, an application requests that a user is authenticated by
Linux-PAM
through a call to
pam_authenticate()
or
pam_chauthtok()
.  These functions call each of the
stacked
authentication modules listed in the
Linux-PAM
configuration
file.  As directed by this file, one of more of the modules may fail
causing the
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
brute force
dictionary attacks primarily, but also
helps hinder
timed
(cf. covert channel) attacks.
The
pam_fail_delay()
function provides the mechanism by which an
application or module can suggest a minimum delay (of
micro_sec
micro-seconds
).
Linux-PAM
keeps a record of the longest time
requested with this function. Should
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.
Independent of success, the delay time is reset to its zero default
value when
Linux-PAM
returns control to the application.
pam_modules-3.html
Next
pam_modules-1.html
Previous
pam_modules.html#toc2
Contents
