Home / Alt manpages / pam_succeed_if(8)

  • pam_succeed_if(8)
  • Admin command
  • linux

Gate PAM Rules with pam_succeed_if Conditions

You will finish with a PAM rule that tests an account characteristic, a way to choose the right condition syntax, and a recovery plan for a rule that rejects the wrong users. The examples target the locally installed pam_succeed_if.so from libpam-modules version 1.5.3-5ubuntu5.7.

Allow about fifteen minutes for a read-only inspection, or thirty minutes if you need to edit a service stack. You need a shell for the inspection. Editing files under /etc/pam.d/ requires root and can lock out users, so keep an existing root session or console access open while testing.

1. Confirm the module and read the local contract

Start with ordinary, read-only commands. They confirm the package version and the module path without changing authentication:

$ dpkg-query -W -f='${Package} ${Version}\n' libpam-modules:amd64
libpam-modules 1.5.3-5ubuntu5.7
$ dpkg -L libpam-modules:amd64 | grep '/pam_succeed_if\.so$'
/lib/x86_64-linux-gnu/security/pam_succeed_if.so

Your architecture path may differ. The module is normally named in a PAM configuration line as pam_succeed_if.so, not as the full path.

Checkpoint

If the second command prints nothing, stop. The package may not be installed for this architecture, or the package contents may differ from this machine. Do not copy a rule into a stack until the module is present.

2. Pick one field and one test

Each condition has three words: a field, a test, and a value. Available fields include user, uid, gid, shell, home, ruser, rhost, tty and service. All conditions on one module line must be true for the module to return success.

Use numeric operators for numeric fields. For example, this checks that the authenticated user has a UID of at least 1000:

uid >= 1000

Use exact or pattern matching for strings. These are distinct:

shell = /bin/bash
home =~ /home/*

The = test is an exact string match. The =~ test uses a glob, so the asterisk in the second example can match the rest of the path. For a list, use a colon-separated value:

user in alice:bob:carol

Group membership has its own form. This checks membership of either named group:

user ingroup wheel:root

Do not use a numeric operator for group names, and do not put spaces inside a condition. PAM splits module arguments on spaces, so user ingroup wheel:root is three arguments while user in group is not the same test.

3. Write a narrowly scoped rule

In a file under /etc/pam.d/, the service name is supplied by the filename. For example, a service stack could contain this account rule:

account required pam_succeed_if.so quiet user ingroup wheel:root

It returns success for a user in wheel or root, and a failure result otherwise. The quiet flag suppresses this module's success and failure logging. Remove quiet temporarily when you need the module's own messages in the system log.

This line is a policy decision, not a harmless filter. With required, a failed condition contributes a failure to the PAM stack. The application may still invoke later modules before PAM reports the overall failure. If you need an immediate stop, PAM's requisite control has different stack behaviour, but choose it only after considering information leakage and the service's existing policy.

Security warning

Do not replace an existing stack with a guessed one. Copy the file to a root-readable backup before editing, and record the original file mode:

# cp -p /etc/pam.d/EXAMPLE_SERVICE /root/EXAMPLE_SERVICE.pam.before-succeed-if
# stat -c '%A %U %G %n' /etc/pam.d/EXAMPLE_SERVICE
 -rw-r--r-- root root /etc/pam.d/EXAMPLE_SERVICE

Replace EXAMPLE_SERVICE with the real filename. The copy is a recovery aid; it does not validate the rule.

4. Combine conditions only when they describe the policy

To require both a group and a minimum UID, put both conditions after the module name:

account required pam_succeed_if.so quiet uid >= 1000 user ingroup operators

This is an AND operation. It does not mean "UID at least 1000 or member of operators". The module has no OR operator on a single line. If you need alternatives, express them with separate PAM stack rules and an explicit control action, or use a group that represents the intended policy.

For conditional loading, the module can use bracketed PAM control syntax. The installed manual gives this pattern:

auth [default=1 success=ignore] pam_succeed_if.so quiet uid > 500
auth required othermodule.so arguments...

Here, success is ignored and the default action skips the next rule. The number is a stack jump, not a UID threshold. Count the following module lines carefully, including any lines introduced by the service's existing configuration. A wrong count can bypass authentication or call an unintended module.

5. Validate without locking yourself out

There is no general standalone command that can prove a PAM stack is safe. Before a live test, inspect the complete service file and any included or substacked files. Then test with a disposable account that is deliberately inside or outside the condition, while an existing privileged session remains available.

$ getent passwd TEST_USER
TEST_USER:x:1001:1001:Test User:/home/TEST_USER:/bin/bash
$ id TEST_USER
uid=1001(TEST_USER) gid=1001(TEST_USER) groups=1001(TEST_USER),1002(operators)

These commands only inspect account data. They do not prove that the service will reach this rule, because the service's PAM stack, control flags and earlier modules also matter.

After a controlled service test, check the relevant authentication log using the logging system configured on the host. Search for the service name and the time of the test. With quiet, you should not expect a success or failure message from pam_succeed_if itself; a failure may instead appear only through the surrounding PAM service.

6. Recover a bad rule

Recovery warning: if a login or administrative command starts failing, stop testing new variants. From the console or an already-open root shell, restore the exact backup:

# cp -p /root/EXAMPLE_SERVICE.pam.before-succeed-if /etc/pam.d/EXAMPLE_SERVICE
# stat -c '%A %U %G %n' /etc/pam.d/EXAMPLE_SERVICE

If the problem is only the new line, remove that line and preserve the rest of the distribution-managed file. Do not delete the whole PAM file. Some services read their stack for every request; others hold state in a long-running process, so follow the service's documented reload procedure only after the file is restored.

Done means

  • The installed module and package version are confirmed.
  • Every condition uses the correct field type and exact, glob, list or group syntax.
  • You know that conditions on one line are combined with AND.
  • The PAM control flag and any jump count match the intended stack behaviour.
  • The rule was tested with a recovery session available, and the original file can be restored.