Securing Applications on Linux with PAM

The basic concepts of PAM (Pluggable Authentication Module), developing a PAM-enabled application, a PAM authentication module and writing the PAM configuration file.
Setting the User Credentials

Generally, an authentication module may have access to more information about a user than what is contained in their authentication token. The pam_sm_setcred function is used to make such information available to the application. A basic implementation of the pam_sm_setcred is shown in Listing 3. In this sample implementation of this function, we simply make available to the application the return code of the call to pam_sm_authenticate().

Listing 3. A Basic Implementation of pam_sm_setcred

Conversing with the Application

The converse() function acts as a front end for module-application conversations. A sample implementation of converse() is shown in Listing 4.

Listing 4. A Sample Implementation of converse()

The pointer to the conversation function is obtained using pam_get_item(pamh,PAM_CONV,&item). Using the pointer, the module now can start communicating directly with the application.

Taking Care of Statically Loaded Modules

Modules may be statically linked to libpam. In fact, this should be true of all the modules distributed with the basic PAM distribution. To be statically linked, a module needs to export information about the functions it contains in a manner that does not clash with other modules.

The extra code necessary to build a static module should be delimited with #ifdef PAM_STATIC and #endif. The static code should define a single structure, struct pam_module. This is called _pam_modname_modstruct, where modname is the name of the module used in the filesystem, minus the leading directory name (generally /usr/lib/security/) and the suffix (generally .so).

struct pam_module _pam_unix_auth_modstruct = {

Now our module is ready to be compiled as static or dynamic. Compile the module using the following command:

gcc -fPIC -c pam_module-name.c
ld -x --shared -o pam_module-name.o

Securing the Application: the PAM Configuration File

The local configuration of those aspects of system security controlled by Linux-PAM is contained in one of two places, either the single system file (/etc/pam.conf) or the /etc/pam.d/ directory.

A general configuration line of the /etc/pam.conf file has the form: service-name module-type control-flag module-path arguments.

We can also specify the PAM configuration for an application in a separate file in the /etc/pam.d folder, in which case the configuration file has the form: module-type control-flag module-path arguments. The service-name becomes the name of the configuration file. Frequently the service-name is the conventional name of the given application, for example, azServer.

Module Type

Four module types exist: auth, account, session and password.

  • auth: determines whether the user is who he claims to be, usually done with a password, but may be determined by a more sophisticated means, such as biometrics.

  • account: determines whether the user is allowed to access the service, whether his passwords have expired and so on.

  • password: provides a mechanism for the user to change his authentication token. Again, this is usually his password.

  • session: things that should be done before and/or after the user is authenticated. This might include things such as mounting/unmounting the user home directory, logging the login/logout and restricting/unrestricting the services available to the user.

In addition, there are four control flags: required, requisite, sufficient and optional.

  • Required: indicates that the success of the module is required for the module-type facility to succeed. Failure of this module will not be apparent to the user until all of the remaining modules (of the same module type) have been executed.

  • Requisite: same as required, except that in the case of a module failure, it directly returns the result to the application.

  • Sufficient: if this module has succeeded and all previous required modules have succeeded, then no more subsequent required modules are invoked.

  • Optional: marks the module as not critical to the success or failure of the user's application for service. Its value is taken into consideration only in the absence of any definite successes or failures of previous or subsequent stacked modules.

The pathname of the dynamically loadable object file (the pluggable module itself) is the module path. If the first character of the module path is /, it is assumed to be a complete path. If this is not the case, the given module path is appended to the default module path, /usr/lib/security.

The arguments are a list of tokens passed to the module when it is invoked, much like arguments to a typical Linux shell command. Generally, valid arguments are optional and specific to any given module.

Finally, to write the configuration file, edit the /etc/pam.conf file to add the following line of code:

check_user  auth  required  /lib/security/

This indicates that for the service-names, check_user and auth module-type are required. The module to be loaded to support this authentication method is, which is found in the directory /lib/security/.




Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

getPassword function is incorrect

prashanth's picture

your getPassword function is incorrect

while((i = getch()) != '\n')
buf[i++] = i;
is incorrect

Very crisp and to the point.

Sunil's picture

Very crisp and to the point. Great work !