Hacked By AnonymousFox

Current Path : /usr/share/doc/pam-devel/
Upload File :
Current File : //usr/share/doc/pam-devel/Linux-PAM_ADG.txt

                  The Linux-PAM Application Developers' Guide

  Andrew G. Morgan

   <morgan@kernel.org>

  Thorsten Kukuk

   <kukuk@thkukuk.de>

   Version 1.1.2, 31. August 2010

   Abstract

   This manual documents what an application developer needs to know about
   the Linux-PAM library. It describes how an application might use the
   Linux-PAM library to authenticate users. In addition it contains a
   description of the functions to be found in libpam_misc library, that can
   be used in general applications. Finally, it contains some comments on PAM
   related security issues for the application developer.

   --------------------------------------------------------------------------

   1. Introduction

                1.1. Description

                1.2. Synopsis

   2. Overview

   3. The public interface to Linux-PAM

                3.1. What can be expected by the application

                             3.1.1. Initialization of PAM transaction

                             3.1.2. Termination of PAM transaction

                             3.1.3. Setting PAM items

                             3.1.4. Getting PAM items

                             3.1.5. Strings describing PAM error codes

                             3.1.6. Request a delay on failure

                             3.1.7. Authenticating the user

                             3.1.8. Setting user credentials

                             3.1.9. Account validation management

                             3.1.10. Updating authentication tokens

                             3.1.11. Start PAM session management

                             3.1.12. terminating PAM session management

                             3.1.13. Set or change PAM environment variable

                             3.1.14. Get a PAM environment variable

                             3.1.15. Getting the PAM environment

                3.2. What is expected of an application

                             3.2.1. The conversation function

                3.3. Programming notes

   4. Security issues of Linux-PAM

                4.1. Care about standard library calls

                4.2. Choice of a service name

                4.3. The conversation function

                4.4. The identity of the user

                4.5. Sufficient resources

   5. A library of miscellaneous helper functions

                5.1. Functions supplied

                             5.1.1. Text based conversation function

                             5.1.2. Transcribing an environment to that of
                             PAM

                             5.1.3. Liberating a locally saved environment

                             5.1.4. BSD like PAM environment variable setting

   6. Porting legacy applications

   7. Glossary of PAM related terms

   8. An example application

   9. Files

   10. See also

   11. Author/acknowledgments

   12. Copyright information for this document

                            Chapter 1. Introduction

1.1. Description

   Linux-PAM (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 Linux-PAM library
   see the Linux-PAM System Administrators' Guide.

   It is the purpose of the Linux-PAM 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.

   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 (authentication tokens).

1.2. Synopsis

   For general applications that wish to use the services provided by
   Linux-PAM the following is a summary of the relevant linking information:

 #include <security/pam_appl.h>

 cc -o application .... -lpam


   In addition to libpam, there is a library of miscellaneous functions that
   make the job of writing PAM-aware applications easier (this library is not
   covered in the DCE-RFC for PAM and is specific to the Linux-PAM
   distribution):

 #include <security/pam_appl.h>
 #include <security/pam_misc.h>

 cc -o application .... -lpam -lpam_misc


                              Chapter 2. Overview

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

   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.

   The PAM library, however, must work equally well for different styles of
   application. Some applications, like the familiar login and passwd 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 ftpd
   which prefixes each exchanged message with a numeric identifier.

   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 conversation function. This function is called from
   within 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.

   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 ftpd, this might involve prefixing the string with the number 331
   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.

   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.

   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 user's 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.

                 Chapter 3.  The public interface to Linux-PAM

   Firstly, the relevant include file for the Linux-PAM library is
   <security/pam_appl.h>. It contains the definitions for a number of
   functions. After listing these functions, we collect some guiding remarks
   for programmers.

3.1. What can be expected by the application

  3.1.1. Initialization of PAM transaction

 #include <security/pam_appl.h>

   int pam_start( service_name,
                  user,
                  pam_conversation,
                  pamh);

   const char *service_name;
   const char *user;
   const struct pam_conv *pam_conversation;
   pam_handle_t **pamh;


    3.1.1.1. DESCRIPTION

   The pam_start function creates the PAM context and initiates the PAM
   transaction. It is the first of the PAM functions that needs to be called
   by an application. The transaction state is contained entirely within the
   structure identified by this handle, so it is possible to have multiple
   transactions in parallel. But it is not possible to use the same handle
   for different transactions, a new one is needed for every new context.

   The service_name argument specifies the name of the service to apply and
   will be stored as PAM_SERVICE item in the new context. The policy for the
   service will be read from the file /etc/pam.d/service_name or, if that
   file does not exist, from /etc/pam.conf.

   The user argument can specify the name of the target user and will be
   stored as PAM_USER item. If the argument is NULL, the module has to ask
   for this item if necessary.

   The pam_conversation argument points to a struct pam_conv describing the
   conversation function to use. An application must provide this for direct
   communication between a loaded module and the application.

   Following a successful return (PAM_SUCCESS) the contents of pamh is a
   handle that contains the PAM context for successive calls to the PAM
   functions. In an error case is the content of pamh undefined.

   The pam_handle_t is a blind structure and the application should not
   attempt to probe it directly for information. Instead the PAM library
   provides the functions pam_set_item(3) and pam_get_item(3). The PAM handle
   cannot be used for mulitiple authentications at the same time as long as
   pam_end was not called on it before.

    3.1.1.2. RETURN VALUES

   PAM_ABORT

           General failure.

   PAM_BUF_ERR

           Memory buffer error.

   PAM_SUCCESS

           Transaction was successful created.

   PAM_SYSTEM_ERR

           System error, for example a NULL pointer was submitted instead of
           a pointer to data.

  3.1.2. Termination of PAM transaction

 #include <security/pam_appl.h>

   int pam_end( pamh,
                pam_status);

   pam_handle_t *pamh;
   int pam_status;


    3.1.2.1. DESCRIPTION

   The pam_end function terminates the PAM transaction and is the last
   function an application should call in the PAM context. Upon return the
   handle pamh is no longer valid and all memory associated with it will be
   invalid.

   The pam_status argument should be set to the value returned to the
   application by the last PAM library call.

   The value taken by pam_status is used as an argument to the module
   specific callback function, cleanup() (See pam_set_data(3) and
   pam_get_data(3)). 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. This
   argument can be logically OR'd with PAM_DATA_SILENT to indicate to
   indicate that the module should not treat the call too seriously. It is
   generally used to indicate that the current closing of the library is in a
   fork(2)ed process, and that the parent will take care of cleaning up
   things that exist outside of the current process space (files etc.).

   This function free's all memory for items associated with the
   pam_set_item(3) and pam_get_item(3) functions. Pointers associated with
   such objects are not valid anymore after pam_end was called.

    3.1.2.2. RETURN VALUES

   PAM_SUCCESS

           Transaction was successful terminated.

   PAM_SYSTEM_ERR

           System error, for example a NULL pointer was submitted as PAM
           handle or the function was called by a module.

  3.1.3. Setting PAM items

 #include <security/pam_modules.h>

   int pam_set_item( pamh,
                     item_type,
                     item);

   pam_handle_t *pamh;
   int item_type;
   const void *item;


    3.1.3.1. DESCRIPTION

   The pam_set_item function allows applications and PAM service modules to
   access and to update PAM informations of item_type. For this a copy of the
   object pointed to by the item argument is created. The following
   item_types are supported:

   PAM_SERVICE

           The service name (which identifies that PAM stack that the PAM
           functions will use to authenticate the program).

   PAM_USER

           The username of the entity under whose identity service will be
           given. That is, following authentication, PAM_USER identifies the
           local entity that gets to use the service. Note, this value can be
           mapped from something (eg., "anonymous") to something else (eg.
           "guest119") by any module in the PAM stack. As such an application
           should consult the value of PAM_USER after each call to a PAM
           function.

   PAM_USER_PROMPT

           The string used when prompting for a user's name. The default
           value for this string is a localized version of "login: ".

   PAM_TTY

           The terminal name: prefixed by /dev/ if it is a device file; for
           graphical, X-based, applications the value for this item should be
           the $DISPLAY variable.

   PAM_RUSER

           The requesting user name: local name for a locally requesting user
           or a remote user name for a remote requesting user.

           Generally an application or module will attempt to supply the
           value that is most strongly authenticated (a local account before
           a remote one. The level of trust in this value is embodied in the
           actual authentication stack associated with the application, so it
           is ultimately at the discretion of the system administrator.

           PAM_RUSER@PAM_RHOST should always identify the requesting user. In
           some cases, PAM_RUSER may be NULL. In such situations, it is
           unclear who the requesting entity is.

   PAM_RHOST

           The requesting hostname (the hostname of the machine from which
           the PAM_RUSER entity is requesting service). That is
           PAM_RUSER@PAM_RHOST does identify the requesting user. In some
           applications, PAM_RHOST may be NULL. In such situations, it is
           unclear where the authentication request is originating from.

   PAM_AUTHTOK

           The authentication token (often a password). This token should be
           ignored by all module functions besides pam_sm_authenticate(3) and
           pam_sm_chauthtok(3). 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(3).

   PAM_CONV

           The pam_conv structure. See pam_conv(3).

   The following additional items are specific to Linux-PAM and should not be
   used in portable applications:

   PAM_FAIL_DELAY

           A function pointer to redirect centrally managed failure delays.
           See pam_fail_delay(3).

   PAM_XDISPLAY

           The name of the X display. For graphical, X-based applications the
           value for this item should be the $DISPLAY variable. This value
           may be used independently of PAM_TTY for passing the name of the
           display.

   PAM_XAUTHDATA

           A pointer to a structure containing the X authentication data
           required to make a connection to the display specified by
           PAM_XDISPLAY, if such information is necessary. See
           pam_xauth_data(3).

   PAM_AUTHTOK_TYPE

           The default action is for the module to use the following prompts
           when requesting passwords: "New UNIX password: " and "Retype UNIX
           password: ". The example word UNIX can be replaced with this item,
           by default it is empty. This item is used by pam_get_authtok(3).

   For all item_types, other than PAM_CONV and PAM_FAIL_DELAY, item is a
   pointer to a <NUL> terminated character string. In the case of PAM_CONV,
   item points to an initialized pam_conv structure. In the case of
   PAM_FAIL_DELAY, item is a function pointer: void (*delay_fn)(int retval,
   unsigned usec_delay, void *appdata_ptr)

   Both, PAM_AUTHTOK and PAM_OLDAUTHTOK, will be reseted before returning to
   the application. Which means an application is not able to access the
   authentication tokens.

    3.1.3.2. RETURN VALUES

   PAM_BAD_ITEM

           The application attempted to set an undefined or inaccessible
           item.

   PAM_BUF_ERR

           Memory buffer error.

   PAM_SUCCESS

           Data was successful updated.

   PAM_SYSTEM_ERR

           The pam_handle_t passed as first argument was invalid.

  3.1.4. Getting PAM items

 #include <security/pam_modules.h>

   int pam_get_item( pamh,
                     item_type,
                     item);

   const pam_handle_t *pamh;
   int item_type;
   const void **item;


    3.1.4.1. DESCRIPTION

   The pam_get_item function allows applications and PAM service modules to
   access and retrieve PAM informations of item_type. Upon successful return,
   item contains a pointer to the value of the corresponding item. Note, this
   is a pointer to the actual data and should not be free()'ed or
   over-written! The following values are supported for item_type:

   PAM_SERVICE

           The service name (which identifies that PAM stack that the PAM
           functions will use to authenticate the program).

   PAM_USER

           The username of the entity under whose identity service will be
           given. That is, following authentication, PAM_USER identifies the
           local entity that gets to use the service. Note, this value can be
           mapped from something (eg., "anonymous") to something else (eg.
           "guest119") by any module in the PAM stack. As such an application
           should consult the value of PAM_USER after each call to a PAM
           function.

   PAM_USER_PROMPT

           The string used when prompting for a user's name. The default
           value for this string is a localized version of "login: ".

   PAM_TTY

           The terminal name: prefixed by /dev/ if it is a device file; for
           graphical, X-based, applications the value for this item should be
           the $DISPLAY variable.

   PAM_RUSER

           The requesting user name: local name for a locally requesting user
           or a remote user name for a remote requesting user.

           Generally an application or module will attempt to supply the
           value that is most strongly authenticated (a local account before
           a remote one. The level of trust in this value is embodied in the
           actual authentication stack associated with the application, so it
           is ultimately at the discretion of the system administrator.

           PAM_RUSER@PAM_RHOST should always identify the requesting user. In
           some cases, PAM_RUSER may be NULL. In such situations, it is
           unclear who the requesting entity is.

   PAM_RHOST

           The requesting hostname (the hostname of the machine from which
           the PAM_RUSER entity is requesting service). That is
           PAM_RUSER@PAM_RHOST does identify the requesting user. In some
           applications, PAM_RHOST may be NULL. In such situations, it is
           unclear where the authentication request is originating from.

   PAM_AUTHTOK

           The authentication token (often a password). This token should be
           ignored by all module functions besides pam_sm_authenticate(3) and
           pam_sm_chauthtok(3). 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(3).

   PAM_CONV

           The pam_conv structure. See pam_conv(3).

   The following additional items are specific to Linux-PAM and should not be
   used in portable applications:

   PAM_FAIL_DELAY

           A function pointer to redirect centrally managed failure delays.
           See pam_fail_delay(3).

   PAM_XDISPLAY

           The name of the X display. For graphical, X-based applications the
           value for this item should be the $DISPLAY variable. This value
           may be used independently of PAM_TTY for passing the name of the
           display.

   PAM_XAUTHDATA

           A pointer to a structure containing the X authentication data
           required to make a connection to the display specified by
           PAM_XDISPLAY, if such information is necessary. See
           pam_xauth_data(3).

   PAM_AUTHTOK_TYPE

           The default action is for the module to use the following prompts
           when requesting passwords: "New UNIX password: " and "Retype UNIX
           password: ". The example word UNIX can be replaced with this item,
           by default it is empty. This item is used by pam_get_authtok(3).

   If a service module wishes to obtain the name of the user, it should not
   use this function, but instead perform a call to pam_get_user(3).

   Only a service module is privileged to read the authentication tokens,
   PAM_AUTHTOK and PAM_OLDAUTHTOK.

    3.1.4.2. RETURN VALUES

   PAM_BAD_ITEM

           The application attempted to set an undefined or inaccessible
           item.

   PAM_BUF_ERR

           Memory buffer error.

   PAM_PERM_DENIED

           The value of item was NULL.

   PAM_SUCCESS

           Data was successful updated.

   PAM_SYSTEM_ERR

           The pam_handle_t passed as first argument was invalid.

  3.1.5. Strings describing PAM error codes

 #include <security/pam_appl.h>

   const char *pam_strerror( pamh,
                             errnum);

   pam_handle_t *pamh;
   int errnum;


    3.1.5.1. DESCRIPTION

   The pam_strerror function returns a pointer to a string describing the
   error code passed in the argument errnum, possibly using the LC_MESSAGES
   part of the current locale to select the appropriate language. This string
   must not be modified by the application. No library function will modify
   this string.

    3.1.5.2. RETURN VALUES

   This function returns always a pointer to a string.

  3.1.6. Request a delay on failure

 #include <security/pam_appl.h>

   int pam_fail_delay( pamh,
                       usec);

   pam_handle_t *pamh;
   unsigned int usec;


    3.1.6.1. DESCRIPTION

   The pam_fail_delay function provides a mechanism by which an application
   or module can suggest a minimum delay of usec micro-seconds. The function
   keeps a record of the longest time requested with this function. Should
   pam_authenticate(3) fail, the failing return to the application is delayed
   by an amount of time randomly distributed (by up to 50%) about this
   longest value.

   Independent of success, the delay time is reset to its zero default value
   when the PAM service module returns control to the application. The delay
   occurs after all authentication modules have been called, but before
   control is returned to the service application.

   When using this function the programmer should check if it is available
   with:

 #ifdef HAVE_PAM_FAIL_DELAY
     ....
 #endif /* HAVE_PAM_FAIL_DELAY */


   For applications written with a single thread that are event driven in
   nature, 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 the delay
   function can be changed with the PAM_FAIL_DELAY item. It can be queried
   and set with pam_get_item(3) and pam_set_item (3) respectively. The value
   used to set it should be a function pointer of the following prototype:

 void (*delay_fn)(int retval, unsigned usec_delay, void *appdata_ptr);


   The arguments being the retval return code of the module stack, the
   usec_delay micro-second delay that libpam is requesting and the
   appdata_ptr that the application has associated with the current pamh.
   This last value was set by the application when it called pam_start(3) or
   explicitly with pam_set_item(3). Note, if PAM_FAIL_DELAY item is unset (or
   set to NULL), then no delay will be performed.

    3.1.6.2. RETURN VALUES

   PAM_SUCCESS

           Delay was successful adjusted.

   PAM_SYSTEM_ERR

           A NULL pointer was submitted as PAM handle.

  3.1.7. Authenticating the user

 #include <security/pam_appl.h>

   int pam_authenticate( pamh,
                         flags);

   pam_handle_t *pamh;
   int flags;


    3.1.7.1. DESCRIPTION

   The pam_authenticate function is used to authenticate the user. The user
   is required to provide an authentication token depending upon the
   authentication service, usually this is a password, but could also be a
   finger print.

   The PAM service module may request that the user enter their username via
   the conversation mechanism (see pam_start(3) and pam_conv(3)). The name of
   the authenticated user will be present in the PAM item PAM_USER. This item
   may be recovered with a call to pam_get_item(3).

   The pamh argument is an authentication handle obtained by a prior call to
   pam_start(). The flags argument is the binary or of zero or more of the
   following values:

   PAM_SILENT

           Do not emit any messages.

   PAM_DISALLOW_NULL_AUTHTOK

           The PAM module service should return PAM_AUTH_ERR if the user does
           not have a registered authentication token.

    3.1.7.2. RETURN VALUES

   PAM_ABORT

           The application should exit immediately after calling pam_end(3)
           first.

   PAM_AUTH_ERR

           The user was not authenticated.

   PAM_CRED_INSUFFICIENT

           For some reason the application does not have sufficient
           credentials to authenticate the user.

   PAM_AUTHINFO_UNAVAIL

           The modules were not able to access the authentication
           information. This might be due to a network or hardware failure
           etc.

   PAM_MAXTRIES

           One or more of the authentication modules has reached its limit of
           tries authenticating the user. Do not try again.

   PAM_SUCCESS

           The user was successfully authenticated.

   PAM_USER_UNKNOWN

           User unknown to authentication service.

  3.1.8. Setting user credentials

 #include <security/pam_appl.h>

   int pam_setcred( pamh,
                    flags);

   pam_handle_t *pamh;
   int flags;


    3.1.8.1. DESCRIPTION

   The pam_setcred function is used to establish, maintain and delete the
   credentials of a user. It should be called to set the credentials after a
   user has been authenticated and before a session is opened for the user
   (with pam_open_session(3)). The credentials should be deleted after the
   session has been closed (with pam_close_session(3)).

   A credential is something that the user possesses. It is some property,
   such as a Kerberos ticket, or a supplementary group membership that make
   up the uniqueness of a given user. On a Linux system the user's UID and
   GID'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. Such credentials should be established, by the
   application, prior to a call to this function. For example, initgroups(2)
   (or equivalent) should have been performed.

   Valid flags, any one of which, may be logically OR'd with PAM_SILENT, are:

   PAM_ESTABLISH_CRED

           Initialize the credentials for the user.

   PAM_DELETE_CRED

           Delete the user's credentials.

   PAM_REINITIALIZE_CRED

           Fully reinitialize the user's credentials.

   PAM_REFRESH_CRED

           Extend the lifetime of the existing credentials.

    3.1.8.2. RETURN VALUES

   PAM_BUF_ERR

           Memory buffer error.

   PAM_CRED_ERR

           Failed to set user credentials.

   PAM_CRED_EXPIRED

           User credentials are expired.

   PAM_CRED_UNAVAIL

           Failed to retrieve user credentials.

   PAM_SUCCESS

           Data was successful stored.

   PAM_SYSTEM_ERR

           A NULL pointer was submitted as PAM handle, the function was
           called by a module or another system error occured.

   PAM_USER_UNKNOWN

           User is not known to an authentication module.

  3.1.9. Account validation management

 #include <security/pam_appl.h>

   int pam_acct_mgmt( pamh,
                      flags);

   pam_handle_t *pamh;
   int flags;


    3.1.9.1. DESCRIPTION

   The pam_acct_mgmt function is used to determine if the user's account is
   valid. It checks for authentication token and account expiration and
   verifies access restrictions. It is typically called after the user has
   been authenticated.

   The pamh argument is an authentication handle obtained by a prior call to
   pam_start(). The flags argument is the binary or of zero or more of the
   following values:

   PAM_SILENT

           Do not emit any messages.

   PAM_DISALLOW_NULL_AUTHTOK

           The PAM module service should return PAM_NEW_AUTHTOK_REQD if the
           user has a null authentication token.

    3.1.9.2. RETURN VALUES

   PAM_ACCT_EXPIRED

           User account has expired.

   PAM_AUTH_ERR

           Authentication failure.

   PAM_NEW_AUTHTOK_REQD

           The user account is valid but their authentication token is
           expired. The correct response to this return-value is to require
           that the user satisfies the 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.

   PAM_PERM_DENIED

           Permission denied.

   PAM_SUCCESS

           The authentication token was successfully updated.

   PAM_USER_UNKNOWN

           User unknown to password service.

  3.1.10. Updating authentication tokens

 #include <security/pam_appl.h>

   int pam_chauthtok( pamh,
                      flags);

   pam_handle_t *pamh;
   int flags;


    3.1.10.1. DESCRIPTION

   The pam_chauthtok function is used to change the authentication token for
   a given user (as indicated by the state associated with the handle pamh).

   The pamh argument is an authentication handle obtained by a prior call to
   pam_start(). The flags argument is the binary or of zero or more of the
   following values:

   PAM_SILENT

           Do not emit any messages.

   PAM_CHANGE_EXPIRED_AUTHTOK

           This argument indicates to the modules that the user's
           authentication token (password) should only be changed if it has
           expired. If this argument is not passed, the application requires
           that all authentication tokens are to be changed.

    3.1.10.2. RETURN VALUES

   PAM_AUTHTOK_ERR

           A module was unable to obtain the new authentication token.

   PAM_AUTHTOK_RECOVERY_ERR

           A module was unable to obtain the old authentication token.

   PAM_AUTHTOK_LOCK_BUSY

           One or more of the modules was unable to change the authentication
           token since it is currently locked.

   PAM_AUTHTOK_DISABLE_AGING

           Authentication token aging has been disabled for at least one of
           the modules.

   PAM_PERM_DENIED

           Permission denied.

   PAM_SUCCESS

           The authentication token was successfully updated.

   PAM_TRY_AGAIN

           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.

   PAM_USER_UNKNOWN

           User unknown to password service.

  3.1.11. Start PAM session management

 #include <security/pam_appl.h>

   int pam_open_session( pamh,
                         flags);

   pam_handle_t *pamh;
   int flags;


    3.1.11.1. DESCRIPTION

   The pam_open_session function sets up a user session for a previously
   successful authenticated user. The session should later be terminated with
   a call to pam_close_session(3).

   It should be noted that the effective uid, geteuid(2). of the application
   should be of sufficient privilege to perform such tasks as creating or
   mounting the user's home directory for example.

   The flags argument is the binary or of zero or more of the following
   values:

   PAM_SILENT

           Do not emit any messages.

    3.1.11.2. RETURN VALUES

   PAM_ABORT

           General failure.

   PAM_BUF_ERR

           Memory buffer error.

   PAM_SESSION_ERR

           Session failure.

   PAM_SUCCESS

           Session was successful created.

  3.1.12. terminating PAM session management

 #include <security/pam_appl.h>

   int pam_close_session( pamh,
                          flags);

   pam_handle_t *pamh;
   int flags;


    3.1.12.1. DESCRIPTION

   The pam_close_session function is used to indicate that an authenticated
   session has ended. The session should have been created with a call to
   pam_open_session(3).

   It should be noted that the effective uid, geteuid(2). of the application
   should be of sufficient privilege to perform such tasks as unmounting the
   user's home directory for example.

   The flags argument is the binary or of zero or more of the following
   values:

   PAM_SILENT

           Do not emit any messages.

    3.1.12.2. RETURN VALUES

   PAM_ABORT

           General failure.

   PAM_BUF_ERR

           Memory buffer error.

   PAM_SESSION_ERR

           Session failure.

   PAM_SUCCESS

           Session was successful terminated.

  3.1.13. Set or change PAM environment variable

 #include <security/pam_appl.h>

   int pam_putenv( pamh,
                   name_value);

   pam_handle_t *pamh;
   const char *name_value;


    3.1.13.1. DESCRIPTION

   The pam_putenv function is used to add or change the value of PAM
   environment variables as associated with the pamh handle.

   The pamh argument is an authentication handle obtained by a prior call to
   pam_start(). The name_value argument is a single NUL terminated string of
   one of the following forms:

   NAME=value of variable

           In this case the environment variable of the given NAME is set to
           the indicated value: value of variable. If this variable is
           already known, it is overwritten. Otherwise it is added to the PAM
           environment.

   NAME=

           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.

   NAME

           Without an '=' the pam_putenv() function will delete the
           corresponding variable from the PAM environment.

   pam_putenv() operates on a copy of name_value, which means in contrast to
   putenv(3), the application is responsible to free the data.

    3.1.13.2. RETURN VALUES

   PAM_PERM_DENIED

           Argument name_value given is a NULL pointer.

   PAM_BAD_ITEM

           Variable requested (for deletion) is not currently set.

   PAM_ABORT

           The pamh handle is corrupt.

   PAM_BUF_ERR

           Memory buffer error.

   PAM_SUCCESS

           The environment variable was successfully updated.

  3.1.14. Get a PAM environment variable

 #include <security/pam_appl.h>

   const char *pam_getenv( pamh,
                           name);

   pam_handle_t *pamh;
   const char *name;


    3.1.14.1. DESCRIPTION

   The pam_getenv function searches the PAM environment list as associated
   with the handle pamh for an item that matches the string pointed to by
   name and returns a pointer to the value of the environment variable. The
   application is not allowed to free the data.

    3.1.14.2. RETURN VALUES

   The pam_getenv function returns NULL on failure.

  3.1.15. Getting the PAM environment

 #include <security/pam_appl.h>

   char **pam_getenvlist( pamh);

   pam_handle_t *pamh;


    3.1.15.1. DESCRIPTION

   The pam_getenvlist function returns a complete copy of the PAM environment
   as associated with the handle pamh. The PAM environment variables
   represent the contents of the regular environment variables of the
   authenticated user when service is granted.

   The format of the memory is a malloc()'d array of char pointers, the last
   element of which is set to NULL. Each of the non-NULL entries in this
   array point to a NUL terminated and malloc()'d char string of the form:
   "name=value".

   It should be noted that this memory will never be free()'d by libpam. Once
   obtained by a call to pam_getenvlist, it is the responsibility of the
   calling application to free() this memory.

   It is by design, and not a coincidence, that the format and contents of
   the returned array matches that required for the third argument of the
   execle(3) function call.

    3.1.15.2. RETURN VALUES

   The pam_getenvlist function returns NULL on failure.

3.2. What is expected of an application

  3.2.1. The conversation function

 #include <security/pam_appl.h>

 struct pam_message {
     int msg_style;
     const char *msg;
 };

 struct pam_response {
     char *resp;
     int resp_retcode;
 };

 struct pam_conv {
     int (*conv)(int num_msg, const struct pam_message **msg,
                 struct pam_response **resp, void *appdata_ptr);
     void *appdata_ptr;
 };


    3.2.1.1. DESCRIPTION

   The PAM library uses an application-defined callback to allow a direct
   communication between a loaded module and the application. This callback
   is specified by the struct pam_conv passed to pam_start(3) at the start of
   the transaction.

   When a module calls the referenced conv() function, the argument
   appdata_ptr is set to the second element of this structure.

   The other arguments of a call to conv() concern the information exchanged
   by module and application. That is to say, num_msg holds the length of the
   array of pointers, msg. After a successful return, the pointer resp points
   to an array of pam_response structures, holding the application supplied
   text. The resp_retcode member of this struct is unused and should be set
   to zero. It is the caller's responsibility to release both, this array and
   the responses themselves, using free(3). Note, *resp is a struct
   pam_response array and not an array of pointers.

   The number of responses is always equal to the num_msg conversation
   function argument. This does require that the response array is free(3)'d
   after every call to the conversation function. The index of the responses
   corresponds directly to the prompt index in the pam_message array.

   On failure, the conversation function should release any resources it has
   allocated, and return one of the predefined PAM error codes.

   Each message can have one of four types, specified by the msg_style member
   of struct pam_message:

   PAM_PROMPT_ECHO_OFF

           Obtain a string without echoing any text.

   PAM_PROMPT_ECHO_ON

           Obtain a string whilst echoing text.

   PAM_ERROR_MSG

           Display an error message.

   PAM_TEXT_INFO

           Display some text.

   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.

   In passing, it is worth noting that there is a descrepency between the way
   Linux-PAM handles the const struct pam_message **msg conversation function
   argument from the way that Solaris' PAM (and derivitives, known to include
   HP/UX, are there others?) does. Linux-PAM interprets the msg argument as
   entirely equivalent to the following prototype const struct pam_message
   *msg[] (which, in spirit, is consistent with the commonly used prototypes
   for argv argument to the familiar main() function: char **argv; and char
   *argv[]). Said another way Linux-PAM interprets the msg argument as a
   pointer to an array of num_msg read only 'struct pam_message' pointers.
   Solaris' PAM implementation interprets this argument as a pointer to a
   pointer to an array of num_msg pam_message structures. Fortunately,
   perhaps, for most module/application developers when num_msg has a value
   of one these two definitions are entirely equivalent. Unfortunately,
   casually raising this number to two has led to unanticipated compatibility
   problems.

   For what its worth the two known module writer work-arounds for trying to
   maintain source level compatibility with both PAM implementations are:

     * never call the conversation function with num_msg greater than one.

     * set up msg as doubly referenced so both types of conversation function
       can find the messages. That is, make

        msg[n] = & (( *msg )[n])


    3.2.1.2. RETURN VALUES

   PAM_BUF_ERR

           Memory buffer error.

   PAM_CONV_ERR

           Conversation failure. The application should not set *resp.

   PAM_SUCCESS

           Success.

3.3. Programming notes

   Note, all of the authentication service function calls accept the token
   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. PAM_SILENT
   does not override the prompting of the user for passwords etc., it only
   stops informative messages from being generated.

                    Chapter 4.  Security issues of Linux-PAM

   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.

   A poorly (or maliciously) written application can defeat any 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 Linux-PAM library simply assumes the
   responsibility of authenticating the user; ascertaining that the user is
   who they say they are. Care should be taken to anticipate all of the
   documented behavior of the Linux-PAM library functions. A failure to do
   this will most certainly lead to a future security breach.

4.1. Care about standard library calls

   In general, writers of authorization-granting applications should assume
   that each module is likely to call any or 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
   '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 Linux-PAM
   library, or copy the structure contents to some safe area of memory before
   passing control to the Linux-PAM library.

   Two important function classes that fall into this category are
   getpwnam(3) and syslog(3).

4.2. Choice of a service name

   When picking the service-name that corresponds to the first entry in the
   Linux-PAM configuration file, the application programmer should avoid the
   temptation of choosing something related to 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.

   In general, this is always the right advice if the program is setuid, or
   otherwise more privileged than the user that invokes it. In some cases,
   avoiding this advice is convenient, but as an author of such an
   application, you should consider well the ways in which your program will
   be installed and used. (Its often the case that programs are not intended
   to be setuid, but end up being installed that way for convenience. If your
   program falls into this category, don't fall into the trap of making this
   mistake.)

   To invoke some 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, ln -s /target/application
   ./preferred_name and then run ./preferred_name.

   By studying the Linux-PAM configuration file(s), an attacker can choose
   the preferred_name to be that of a service enjoying minimal protection;
   for example a game which uses 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.

   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.

4.3. The conversation function

   Care should be taken to ensure that the conv() function is robust. Such a
   function is provided in the library libpam_misc (see below).

4.4. The identity of the user

   The 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.

   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 UID (user
   ID) of the running process; the identity of the privilege granting user is
   the EUID (effective user ID) of the running process; the identity of the
   user, under whose name the service will be executed, is given by the
   contents of the PAM_USER pam_get_item(3). Note, modules can change the
   values of PAM_USER and PAM_RUSER during any of the pam_*() library calls.
   For this reason, the application should take care to use the
   pam_get_item() every time it wishes to establish who the authenticated
   user is (or will currently be).

   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.

   A more portable solution to storing the identity of the requesting user is
   to use the PAM_RUSER pam_get_item(3). The application should supply this
   value before attempting to authenticate the user with 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 pam_set_item(3) to set
   PAM_RUSER.

   In addition to the PAM_RUSER item, the application should supply the
   PAM_RHOST (requesting host) item. As a general rule, the following
   convention for its value can be assumed: NULL = unknown; localhost =
   invoked directly from the local system; 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.

4.5. Sufficient resources

   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 setrlimit(2) family of commands should be taken into
   consideration.

   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 manner that preserves the PAM API. Such tolerance may be especially
   important when attempting to track a malicious adversary.

             Chapter 5. A library of miscellaneous helper functions

   To aid the work of the application developer a library of miscellaneous
   functions is provided. It is called libpam_misc, and contains a text based
   conversation function, and routines for enhancing the standard
   PAM-environment variable support.

   The functions, structures and macros, made available by this library can
   be defined by including <security/pam_misc.h>. It should be noted that
   this library is specific to Linux-PAM and is not referred to in the
   defining DCE-RFC (see See also) below.

5.1. Functions supplied

  5.1.1. Text based conversation function

 #include <security/pam_misc.h>

   int misc_conv( num_msg,
                  msgm,
                  response,
                  appdata_ptr);

   int num_msg;
   const struct pam_message **msgm;
   struct pam_response **response;
   void *appdata_ptr;


    5.1.1.1. DESCRIPTION

   The misc_conv function is part of libpam_misc and not of the standard
   libpam library. This function will prompt the user with the appropriate
   comments and obtain the appropriate inputs as directed by authentication
   modules.

   In addition to simply slotting into the appropriate pam_conv(3), 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. The five variabls are as follows:

   time_t pam_misc_conv_warn_time;

           This variable contains the time (as returned by time(2)) that the
           user should be first warned that the clock is ticking. By default
           it has the value 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
           Linux-PAM library.

   const char *pam_misc_conv_warn_line;

           Used in conjuction with 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 translated version of "...Time is running out...", but
           this can be changed by the application prior to passing control to
           Linux-PAM.

   time_t pam_misc_conv_die_time;

           This variable contains the time (as returned by time(2)) that the
           will time out. By default it has the value 0, which indicates that
           the conversation function will not timeout. The application may
           set its value to sometime in the future, but this should be done
           prior to passing control to the Linux-PAM library.

   const char *pam_misc_conv_die_line;

           Used in conjuction with 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 translated version of "...Sorry,
           your time is up!", but this can be changed by the application
           prior to passing control to Linux-PAM.

   int pam_misc_conv_died;

           Following a return from the Linux-PAM libraray, the value of this
           variable indicates whether the conversation has timed out. A value
           of 1 indicates the time-out occurred.

   The following two function pointers are available for supporting binary
   prompts in the conversation function. They are optimized for the current
   incarnation of the libpamc library and are subject to change.

   int (*pam_binary_handler_fn)(void *appdata, pamc_bp_t *prompt_p);

           This function pointer is initialized to 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.)

   int (*pam_binary_handler_free)(void *appdata, pamc_bp_t *delete_me);

           This function pointer is initialized to PAM_BP_RENEW(delete_me, 0,
           0), but can be redefined as desired by the application.

  5.1.2. Transcribing an environment to that of PAM

 #include <security/pam_misc.h>

   int pam_misc_paste_env( pamh,
                           user);

   pam_handle_t *pamh;
   const char * const *user;


    5.1.2.1. DESCRIPTION

   This function takes the supplied list of environment pointers and uploads
   its contents to the PAM environment. Success is indicated by PAM_SUCCESS.

  5.1.3. Liberating a locally saved environment

 #include <security/pam_misc.h>

   int pam_misc_drop_env( env);

   char **env;


    5.1.3.1. DESCRIPTION

   This function is defined to complement the pam_getenvlist(3) function. It
   liberates the memory associated with env, overwriting with 0 all memory
   before free()ing it.

  5.1.4. BSD like PAM environment variable setting

 #include <security/pam_misc.h>

   int pam_misc_setenv( pamh,
                        name,
                        value,
                        readonly);

   pam_handle_t *pamh;
   const char *name;
   const char *value;
   int readonly;


    5.1.4.1. DESCRIPTION

   This function performs a task equivalent to pam_putenv(3), its syntax is,
   however, more like the BSD style function; setenv(). The name and value
   are concatenated with an '=' to form a name=value and passed to
   pam_putenv(). If, however, the PAM variable is already set, the
   replacement will only be applied if the last argument, readonly, is zero.

                     Chapter 6. Porting legacy applications

   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.

   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".

   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.

   One simple test of a ported application would be to insert the pam_permit
   module and see if the application demands you type a password... In such a
   case, 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.

   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.

                    Chapter 7. Glossary of PAM related terms

   The following are a list of terms used within this document.

   Authentication token

           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 refreshing 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.

   Credentials

           Having successfully authenticated the user, PAM is able to
           establish certain characteristics/attributes of the user. These
           are termed credentials. Examples of which are group memberships to
           perform privileged tasks with, and tickets 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.

                       Chapter 8. An example application

   To get a flavor of the way a 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 (0 for success; 1 for failure).

 /*
   This program was contributed by Shane Watts
   [modifications by AGM and kukuk]

   You need to add the following (or equivalent) to the
   /etc/pam.d/check_user file:
   # check authorization
   auth       required     pam_unix.so
   account    required     pam_unix.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, &conv, &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 */
 }



                                Chapter 9. Files

   /usr/include/security/pam_appl.h

           Header file with interfaces for Linux-PAM applications.

   /usr/include/security/pam_misc.h

           Header file for useful library functions for making applications
           easier to write.

                              Chapter 10. See also

     * The Linux-PAM System Administrators' Guide.

     * The Linux-PAM Module Writers' Guide.

     * The V. Samar and R. Schemers (SunSoft), ``UNIFIED LOGIN WITH PLUGGABLE
       AUTHENTICATION MODULES'', Open Software Foundation Request For
       Comments 86.0, October 1995.

                       Chapter 11. Author/acknowledgments

   This document was written by Andrew G. Morgan (morgan@kernel.org) with
   many contributions from 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, Thorsten Kukuk, 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.

   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
   Linux-PAM, Sun graciously made the documentation for their implementation
   of PAM available. This act greatly accelerated the development of
   Linux-PAM.

              Chapter 12. Copyright information for this document

 Copyright (c) 2006 Thorsten Kukuk <kukuk@thkukuk.de>
 Copyright (c) 1996-2002 Andrew G. Morgan <morgan@kernel.org>


   Redistribution and use in source and binary 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 (GPL), 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


Hacked By AnonymousFox1.0, Coded By AnonymousFox