Configure PAM

PAM is a powerful suite of shared libraries used to dynamically authenticate a user to applications (or services) in a Linux system. It integrates multiple low-level authentication modules into a high-level API that provides dynamic authentication support for applications.

To employ PAM, an application/program needs to be “PAM-aware“; it needs to have been written and compiled specifically to use PAM. To find out if a program is “PAM-aware” or not, check if it has been compiled with the PAM library using the ldd command:

sudo ldd /usr/sbin/sshd | grep libpam.so
> libpam.so.0 => /lib/x86_64-linux-gnu/libpam.so.0 (0x00007effddbe2000)

The main configuration file for PAM is /etc/pam.conf and the /etc/pam.d/ directory contains the PAM configuration files for each PAM-aware application/services.

The syntax for the main configuration file is as follows: the file is made up of a list of rules written on a single line (you can extend rules using the “\” escape character) and comments are preceded with “#” marks and extend to the next end of line.

The format of each rule is a space separated collection of tokens (the first three are case-insensitive): service type control-flag module module-arguments; where:

  • service: actual application name
  • type: module type/context/interface
  • control-flag: indicates the behavior of the PAM-API should the module fail to succeed in its authentication task
  • module: the absolute filename or relative pathname of the PAM
  • module-arguments: space separated list of tokens for controlling module behavior.

The syntax of each file in /etc/pam.d/ is similar to that of the main file and is made up of lines of the following form: type control-flag module module-arguments

A module is associated to one these management group types:

  • account: provide services for account verification
  • authentication: authenticate a user and set up user credentials
  • password: are responsible for updating user passwords and work together with authentication modules
  • session: manage actions performed at the beginning of a session and end of a session.

PAM loadable object files (i.e. the modules) are to be located in the following directory: /lib/security/ or /lib64/security depending on the architecture.

The supported control-flags are:

  • requisite: failure instantly returns control to the application indicating the nature of the first module failure
  • required: all these modules are required to succeed for libpam to return success to the application
  • sufficient: given that all preceding modules have succeeded, the success of this module leads to an immediate and successful return to the application (failure of this module is ignored)
  • optional: the success or failure of this module is generally not recorded.

In addition to the above keywords, there are two other valid control flags:

  • include: include all lines of given type from the configuration file specified as an argument to this control
  • substack: this differs from the previous one in that evaluation of the done and die actions in a substack does not cause skipping the rest of the complete module stack, but only of the substack..

Example: how to use PAM to disable root user access to a system via SSH and login.

We can use the /lib/security/pam_listfile.so module which offers great flexibility in limiting the privileges of specific accounts. Open and edit the file for the target service in the /etc/pam.d/ directory as shown.

sudo vim /etc/pam.d/sshd
sudo vim /etc/pam.d/login

Add this rule in both files:

auth    required       pam_listfile.so \
    onerr=succeed  item=user  sense=deny  file=/etc/ssh/deniedusers

Explaining the tokens in the above rule:

  • auth: is the module type (or context)
  • required: is a control-flag that means if the module is used, it must pass or the overall result will be fail, regardless of the status of other modules
  • pam_listfile.so: is a module which provides a way to deny or allow services based on an arbitrary file
  • onerr=succeed: module argument
  • item=user: module argument which specifies what is listed in the file and should be checked for
  • sense=deny: module argument which specifies action to take if found in file, if the item is NOT found in the file, then the opposite action is requested
  • file=/etc/ssh/deniedusers: module argument which specifies file containing one item per line.

Next, we need to create the file /etc/ssh/deniedusers and add the name root in it: sudo vim /etc/ssh/deniedusers

Save the changes and close the file, then set the required permissions on it: sudo chmod 600 /etc/ssh/deniedusers

From now on, the above rule will tell PAM to consult the /etc/ssh/deniedusers file and deny access to the SSH and login services for any listed user.

Another good example of PAM configuration is showed in pam_tally2 module man page: it explains how to configure login to lock the account after 4 failed logins.