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 setrlimit(2)
family of commands
should be taken into consideration.
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 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.
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 su program: user joe
executes
su to become the user jane. In this situation X=joe
,
Y=root
and Z=jane
. Clearly, it is important that the module
does not confuse these different users and grant an inappropriate
level of privilege.
The following is the convention to be adhered to when juggling user-identities.
getuid(2)
.
geteuid(2)
.
pam_get_user(2)
and also stored
in the Linux-PAM item, PAM_USER
.
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.
Note, if a module wishes to modify the identity of either the uid
or euid
of the running process, it should take care to restore
the original values prior to returning control to the Linux-PAM
library.
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!
The module should be prepared for a failure from the conversation. The
generic error would be PAM_CONV_ERR
, but anything other than
PAM_SUCCESS
should be treated as indicating failure.
To ensure that the authentication tokens are not left lying around the
items, PAM_AUTHTOK
and PAM_OLDAUTHTOK
, are not available to
the application: they are defined in
<security/pam_modules.h>
. 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 free()
'ing them. The Linux-PAM library is
required to do this when either of these authentication token items
are (re)set.
Not to dwell too little on this concern; should the module store the
authentication tokens either as (automatic) function variables or
using 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 cleanup()
function
should explicitly overwrite the *data
before free()
'ing it:
for example,
/*
* 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;
}