|
TRex::PAM - Developer's arena
|
|
TRex::PAM - TRex internal authentication interface
use TRex::PAM;
$res = pam_start($service_name, $user, $pamh);
$res = pam_start($service_name, $user, \&my_conv_func, $pamh);
$res = pam_end($pamh, $pam_status);
If you prefer to use an object oriented style for accessing the PAM
library here is the interface:
use TRex::PAM qw(:constants);
$pamh = new TRex::PAM($service_name, $user);
$pamh = new TRex::PAM($service_name, $user, \&my_conv_func);
ref($pamh) || die "Error code $pamh during PAM init!";
$pamh = 0 ## This calls the object destructor
The constructor new will call the pam_start function and if successfull
will return an object reference. Otherwise the $pamh will contain the
error number returned by pam_start.
The pam_end function will be called automatically when the object is no
longer referenced.
The TRex::PAM module provides an internal interface to be used
by TRex. The main idea is to use an already designed interface
instead of build a new one from scratch (why to reinvent the wheel ??)
The goal, in this first stage, is imply that and NOT to use PAM (just
the API). Despite of this, some efforts are made to maintain it
complaint to the real PAM API.
This work is based in Nikolay Pelov's Authen::PAM module, just to
not build the interface from ground up.
Before this implementation, TRex was tied to its own authentication schema
and the code to do it was spread all over the code. Now any method can be
used just with building a simple module that ties to the PAM definitions
and behaviuor described in this document.
The process of 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 transparent to the application. That is to say, when the application
is written, no assumptions can be made about how the client will be authenticated.
The process of authentication is performed by the PAM library via a call to
pam_authenticate(). The return value of this function will indicate whether
a named client (the user) has been authenticated. If the PAM library needs
to prompt the user for any information, such as their name or a password
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.)
Besides authentication, PAM provides other forms of management. Session
management is provided with calls to pam_open_session() and pam_close_session().
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.
Account management is another area that an application developer should
include with a call to 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 pam_chauthtok(), although some applications are not suited
to this task (ftp for example) and in this case the application should deny
access to the user.
PAM is also capable of setting and deleting the users credentials with the
call pam_setcred(). 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.
This implementation, in this first version, has some differences with the
original PAM, mainly originated for compatibility with previuos TRex versions.
This will change in future releases.
- There's no pam.conf file, mainly because this is a PAM implementation
only for TRex. In the future is desired that native PAM would be used instead.
- The password and SID (Session ID) have the same meaning, and any of
them can be supplied when calling the conversational function and
requesting PAM_PROMPT_ECHO_ON() or PAM_PROMPT_ECHO_OFF().
- The initialization process (pam_start, pam_authenticate
and pam_acct_mgmt) should be called each time a script is started
- pam_open_session() is called every time a script is started (after the
initialization process is done) just to maintain the PAM style, and
only when logging off pam_close_session() should be called. This
one is used to break the "Session ID"/user relationship.
use TRex::PAM;
pam_start($service_name, $user, \&my_conv_func, $pamh);
print "Error initializong PAM module !!" unless ( ref($pamh) );
This is the first line, the starting point, for everything where :
- $service_name : unused (commonly "TRex" is passed)
- $user : the aMail ID
- \&my_conv_func: pointer to the conversational function (see
below)
- $pamh : the handler returned by pam_start
In case of failure $pamh will return an error code instead of a handler.
pam_end($pamh);
This is the last sentence called, and close all conversation with the
underlying security mechanisms. Usually it returns PAM_SUCCESS(), but any
error value can be returned.
$ret = pam_get_item($pamh, $item_type, $item);
This function retrieves the value for the desired item. The parameters are:
- $pamh: the handler to PAM
- $item_type: the item name to be retrieved
- $item: a pointer to a scalar where the value will be stored
The possible returned status ($ret) are:
- PAM_SUCCESS(): The operation was successful
- PAM_SYSTEM_ERR(): The handle was invalid
- PAM_PERM_DENIED(): no permissions to access the desired item
- PAM_BAD_ITEM(): An unidentified item was attempted to be accessed
$ret = pam_set_item($pamh, $item_type, $item);
This function sets the value for the desired item. The parameters are:
- $pamh: the handler to PAM
- $item_type: the item name to be set (see below)
- $item: value to be set
The possible returned status ($ret) are:
- PAM_SUCCESS(): The operation was successful
- PAM_SYSTEM_ERR(): Tha handle was invalid
- PAM_PERM_DENIED(): no permissions to access the desired item
- PAM_BAD_ITEM(): An unidentified item was attempted to be accessed
$ret = pam_authenticate($pamh);
This function allows us to authenticate the user. The values returned by
this one are:
- PAM_SUCCESS() : the authentication was successful
- PAM_AUTH_ERR() : The user was not authenticated
- PAM_CRED_INSUFFICIENT() : The application has not sufficient
credentials to authenticate the user
- PAM_AUTHINFO_UNAVAIL() : The module was not able to access
the authentication information. This might be due to a network or
hardware failure etc
- PAM_USER_UNKNOWN() : The supplied username is not known to the
authentication service
- PAM_MAXTRIES() : the authentication module has reached its
limit of tries authenticating the user. Do not try again.
$ret = pam_acct_mgmt($pamh);
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. The values returned by this one are:
- PAM_SUCCESS() : the account is healthy
- PAM_AUTH_ERR() : There was an authentication error.
- PAM_AUTHTOKEN_REQD() : he user is valid but their
authentication token has expired
- PAM_ACCT_EXPIRED() : The account expired, and the user is no
longer permitted to access the system
- PAM_PERM_DENIED() : The user is not permitted to gain access
at this time
- PAM_USER_UNKNOWN() : The user is not known to a module's
account management component
$ret = pam_open_session($pamh);
This function is used to indicate that an authenticated session has begun.
The values returned by this one are:
- PAM_SUCCESS() : the operation was successful
- PAM_SESSION_ERR() : There was an error.
$ret = pam_close_session($pamh);
This function is used to indicate that an authenticated session has ended.
The values returned by this one are:
- PAM_SUCCESS() : the operation was successful
- PAM_SESSION_ERR() : There was an error.
$ret = pam_chauthtok($pamh);
This function is used to change the authentication token for a given user
(as indicated by the state associated with the handle, pamh).
The values returned by this one are:
- PAM_SUCCESS() : The operation was successful
- PAM_AUTHTOK_ERR() : Unab le to obtain the new authentication token.
- PAM_AUTHTOK_RECOVERY_ERR() : Unable to obtain the old
authetication token
- PAM_AUTHTOK_LOCK_BUSY() : Unable to change the authentication
token since it is currently locked
- PAM_AUTHTOK_DISABLE_AGING() : Authentication token aging has
been disabled
- PAM_PERM_DENIED() : Permission Denied
- PAM_TRY_AGAIN() : The authentication token was not updated
- PAM_USER_UNKNOWN() : The user is not known
The item names allowed are:
- PAM_SERVICE(): service name
- PAM_USER(): user name
- PAM_USER_PROMPT(): string used to prompt for the user name
- PAM_TTY(): terminal name
- PAM_RUSER(): requesting user name
- PAM_RHOST(): requesting hostname
- PAM_CONV(): conversation function
- "SID": session ID
- "SESS_TIME_TIL_EXPIRE": Time left until the current session ends
- "BG_ERROR_TEXT": the background mechanism for authentication (LDAP, NIS, etc.)
returns completion codes, whose descriptions are placed in this item (only for the last error).
Please, note that the only the standard item names start with PAM_.
The "ad hoc" extensions have a different naming convention
When starting the PAM the user must supply a conversation function.
It is used for interaction between the PAM modules and the user.
The argument of the function is a list of pairs ($msg_type, $msg) and it must
return a list with the same number of pairs ($resp_retcode, $resp) with
replies to the input messages. In addition the user must append to the end
of the resulting list the return code of the conversation function (usually
PAM_SUCCESS).
Here is a sample form of the PAM conversation function:
sub my_conv_func {
my @res;
while ( @_ ) {
my $msg_type = shift;
my $msg = shift;
print $msg;
# switch ($msg_type) { obtain value for $ans; }
push @res, (PAM_SUCCESS(),$ans);
}
push @res, PAM_SUCCESS();
return @res;
}
The expected $msg_type values are:
- PAM_PROMPT_ECHO_OFF(): Obtain the authentication string without
echoing any text
- PAM_PROMPT_ECHO_ON(): Obtain the authentication string while
echoing a requestingtext
- PAM_ERROR_MSG(): Error message
- PAM_TEXT_INFO(): Information message
In case of PAM_PROMPT_ECHO_OFF() and PAM_PROMPT_ECHO_ON(), the authentication
string can be a password or a session ID (is a kind of password that expires
at the end of a session)
Here is an example of using PAM for changing the password of the current
user:
use TRex::PAM;
$login_name = getpwuid($<);
pam_start("passwd", $login_name, $pamh);
die "No reference was obtained" if ( ! ref($pamh) );
$ret = pam_chauthtok($pamh);
die "Cannot change password" if ( $ret != PAM_SUCESS() );
pam_end($pamh);
or the same thing but using OO style:
use TRex::PAM;
$login_name = getpwuid($<);
$pamh = new TRex::PAM("passwd", $login_name);
die "No reference was obtained" if ( ! ref($pamh) );
$ret = $pamh->pam_chauthtok;
die "Cannot change password" if ( $ret != PAM_SUCESS() );
$pamh = 0; # Force perl to call the destructor for the $pamh
Nikolay Pelov's Authen::PAM module
The Linux-PAM
Application Developers' Guide
|
TRex::PAM - Developer's arena
|