Home / Alt manpages / pam_debug(8)

  • pam_debug(8)
  • Admin command
  • linux

Test PAM Stack Decisions Safely with pam_debug

You will finish with a way to make one PAM module return a known result, then observe how the surrounding stack handles it. That is useful when a service behaves differently after a PAM configuration change and the real question is whether control flow reached the next module. This guide uses the pam_debug module from Linux-PAM 1.5.3-5ubuntu5.7, installed here as part of libpam-modules:amd64.

Allow about 15 minutes for a small test and longer if you are tracing a production service. You need root access to change a PAM service file, a text editor, and a test service whose failure will not lock you out. The examples below do not alter a live configuration until you deliberately copy a line into one.

1. Confirm the module is installed

Check the package version and the shared object first. These commands only read local files and can run as an ordinary user:

$ dpkg-query -W -f='${Package} ${Version}\n' libpam-modules
libpam-modules 1.5.3-5ubuntu5.7
$ ls -l /lib/x86_64-linux-gnu/security/pam_debug.so
-rw-r--r-- 1 root root ... /lib/x86_64-linux-gnu/security/pam_debug.so

The path contains the architecture, so it may differ on another machine. PAM loads modules by name from its normal module directory; the service configuration uses pam_debug.so, not this absolute path.

Checkpoint

If the file is absent, stop here and install or repair the distribution package through your normal change process. Do not copy a module from another machine.

2. Choose a disposable PAM service

A PAM line is not a command that you run directly. An application selects a service name, then PAM reads the matching file under /etc/pam.d/ and calls each module for the requested operation. The module provides auth, account, password and session types.

Security warning

Never experiment first in sshd, sudo, login or another path you need for recovery. A malformed PAM stack can deny access or make a service unusable. Keep an existing root shell open, record the original file, and use a test service or a disposable virtual machine.

For a test service named pam-debug-lab, the file would be /etc/pam.d/pam-debug-lab. Creating or editing that file requires elevated privileges. The application used for testing must itself ask PAM for that service; a file that no program opens will produce no result.

3. Force a known authentication result

Add one auth line to the disposable service:

auth    required    pam_debug.so auth=perm_denied

When PAM calls this module's authentication function, it returns PAM_PERM_DENIED. The option name is the PAM operation, and its value is the result to return. The module does not decide whether a password is correct and does not change an account. It is a controllable test result.

To make the same call succeed, change only the value:

auth    required    pam_debug.so auth=success

The documented result names include success, perm_denied, auth_err, user_unknown, ignore, try_again and abort, among others. Use the names from pam_debug(8); do not substitute an arbitrary PAM constant or a decimal number. With no auth= option, the default is PAM_SUCCESS.

Checkpoint

Ask your test application to use the service, then check its exit status or diagnostic. A real application is required to exercise the line. If the result never changes, first verify the service name and that the application is reading the file you edited.

4. Test stack control flow deliberately

The control flag decides what PAM does after the module returns. For a simple failure that must stop the stack, use required:

auth    required    pam_debug.so auth=perm_denied
auth    required    pam_debug.so auth=success

Both modules can be called, but the overall authentication result remains a failure because a required module failed. This is a useful test for code that continues collecting results before returning.

To test a short-circuiting success, use sufficient on the first line:

auth    sufficient  pam_debug.so auth=success
auth    required    pam_debug.so auth=perm_denied

A sufficient success can complete the stack before the later required failure is reached. That is precisely why control flags deserve testing rather than being inferred from the module's return value alone. The manual's larger example also demonstrates bracketed controls such as [success=2 default=ok], where a result can skip a number of following stack entries or select another action.

5. Exercise other PAM operations

Use the option matching the function you want to test. These lines are examples for the same disposable service, not a recommendation to put every type in one stack:

account  required  pam_debug.so acct=user_unknown
session  required  pam_debug.so open_session=session_err
session  required  pam_debug.so close_session=success
password required  pam_debug.so chauthtok=authtok_err

cred= controls the result of setting credentials. acct= controls account management. open_session= and close_session= cover the two session calls. Password changes have two phases: prechauthtok= applies when PAM_PRELIM_CHECK is set, while chauthtok= applies when it is not. A line is only exercised when the application requests that PAM operation.

Do not mistake a successful module call for a successful whole transaction. PAM combines results according to the stack's control flags, and the application may make several PAM calls during one login or session.

6. Restore the test and verify the boundary

Remove the temporary service file or restore its saved contents as soon as the test is complete. This is a state-changing step requiring root, and deleting the wrong PAM file is irreversible without a backup:

# sudo cp --preserve=all /etc/pam.d/pam-debug-lab /root/pam-debug-lab.test-backup
# sudo rm /etc/pam.d/pam-debug-lab
# test ! -e /etc/pam.d/pam-debug-lab && echo 'test service removed'
test service removed

If the file was an existing test configuration, copy the backup back instead of removing it. Do not restart or reload an unrelated service just to prove that a PAM file was restored. Let the service owner choose its normal validation procedure.

For a final read-only check, inspect the module's exported PAM entry points:

$ readelf -Ws /lib/x86_64-linux-gnu/security/pam_debug.so | grep 'pam_sm_'
... pam_sm_authenticate
... pam_sm_setcred
... pam_sm_acct_mgmt
... pam_sm_chauthtok
... pam_sm_open_session
... pam_sm_close_session

This confirms the installed object exposes the operation handlers described by the local manual. It does not prove that a particular application loaded the module, so keep the application-level test as the decisive check.

Done means

  • The installed package and module path were checked before configuration.
  • A disposable PAM service returned a deliberately selected result.
  • You tested the difference between a module result and stack control flow.
  • The relevant auth, account, password or session operation was actually requested by an application.
  • The test service was removed or restored, and no production login path was changed.