[TRex - Web based e-mail]

TRex::PAM - Developer's arena

SourceForge Logo

NAME

TRex::PAM - TRex internal authentication interface

SYNOPSIS

  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.


DESCRIPTION

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.

TRex's PAM implementation details

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.


Initialization

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 :

In case of failure $pamh will return an error code instead of a handler.


Termination

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.

PAM items

$ret = pam_get_item($pamh, $item_type, $item);
This function retrieves the value for the desired item. The parameters are: The possible returned status ($ret) are:

$ret = pam_set_item($pamh, $item_type, $item);
This function sets the value for the desired item. The parameters are: The possible returned status ($ret) are:

Authentication

  $ret = pam_authenticate($pamh);
This function allows us to authenticate the user. The values returned by this one are:

Account management

  $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:

Session opening

  $ret = pam_open_session($pamh);
This function is used to indicate that an authenticated session has begun. The values returned by this one are:

Session termination

  $ret = pam_close_session($pamh);
This function is used to indicate that an authenticated session has ended. The values returned by this one are:

Updating authentication tokens

  $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:

Item names

The item names allowed are: Please, note that the only the standard item names start with PAM_. The "ad hoc" extensions have a different naming convention

Conversation function format

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: 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)

EXAMPLES

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

SEE ALSO

Nikolay Pelov's Authen::PAM module

The Linux-PAM Application Developers' Guide
[TRex documentation]

TRex::PAM - Developer's arena