pam_listfile
Authorize/deny logins based on file contents
SYNOPSIS
pam_listfile.so [options] onitem={user|group|tty|rhost|ruser|service|fgroup|pgrp} sense={allow|deny} file=/path/to/file
PARAMETERS
onitem={user|group|tty|rhost|ruser|service|fgroup|pgrp}
Specifies the type of item to be checked against the list file.
user: User's login name.
group: User's primary group name.
tty: Terminal name (e.g., /dev/pts/0).
rhost: Remote host name.
ruser: Remote user name.
service: PAM service name.
fgroup: Effective group name.
pgrp: Primary group name (from getpwuid()).
sense={allow|deny}
Determines the module's action if the item is found in the list file.
allow: If found, access is granted (returns PAM_SUCCESS). If not found, access is denied (returns PAM_AUTH_ERR).
deny: If found, access is denied (returns PAM_AUTH_ERR). If not found, access is granted (returns PAM_SUCCESS).
file=/path/to/file
Specifies the absolute path to the list file containing items, one per line by default.
nullok
If the item to be checked is NULL (e.g., rhost for a local login), the module returns PAM_SUCCESS instead of denying access or ignoring. Use with caution.
reverse
Inverts the meaning of the sense argument. If sense=allow is used with reverse, it behaves like sense=deny and vice-versa.
nonull
If the item to be checked is NULL, the module returns PAM_AUTH_ERR (access denied). This is the opposite of nullok and cannot be used with it.
apply
Modifies nullok behavior. If nullok is present and the item is NULL, the module returns PAM_IGNORE instead of PAM_SUCCESS (PAM 1.0) or PAM_SUCCESS (PAM 1.1), allowing subsequent modules to determine access.
debug
Enables verbose debugging messages to be logged via syslog.
quiet
Suppresses informational messages to syslog about allowing or denying access.
field=N
(PAM 1.4.0+) Specifies that the N-th field (column) in the list file should be matched. Fields are 1-indexed. Default is 1.
sep=char
(PAM 1.4.0+) Specifies the character used as a field separator in the list file. Default is whitespace.
comment=char
(PAM 1.4.0+) Specifies the character that denotes the start of a comment in the list file. Default is '#'.
DESCRIPTION
pam_listfile is a Pluggable Authentication Module (PAM) that allows or denies access based on whether a specific item (like a user, group, or TTY) is listed in a designated file. It provides a flexible and simple mechanism for implementing access policies directly within the PAM authentication stack. This module is typically configured in PAM service files (e.g., /etc/pam.d/sshd) to control access to system services. It can be used to create allow-lists (whitelists) or deny-lists (blacklists) for various system entities, offering granular control over who can access what, based on predefined lists maintained by the system administrator.
CAVEATS
The order of PAM modules in a service configuration file is critical, as modules are processed sequentially. Misconfiguring pam_listfile can lead to unintended access restrictions or security vulnerabilities. Ensure the list file's permissions are properly secured (e.g., readable only by root) to prevent unauthorized modification. For very large list files, there might be a minor performance overhead.
CONFIGURATION EXAMPLE
To deny SSH access to users listed in /etc/ssh/denied_users:
Add the following line to /etc/pam.d/sshd (typically in the auth section):
auth required pam_listfile.so onitem=user sense=deny file=/etc/ssh/denied_users
And create the file /etc/ssh/denied_users with one username per line:
baduser1
baduser2
LIST FILE FORMAT
By default, the list file should contain one item per line. Blank lines are ignored. Lines starting with '#' (or the character specified by comment) are treated as comments.
Example /etc/ssh/allowed_ttys (allowing SSH only from console and pts/0):
/dev/console
/dev/pts/0
With field and sep, the file can be more complex, e.g., matching the second field separated by colons:
# username:uid:group
john:1001:users
jane:1002:staff
To match 'john' using pam_listfile.so ... onitem=user sense=allow file=/path/to/file field=1 sep=:
SEE ALSO
pam(8), pam.d(5), pam_access(8), pam_succeed_if(8)