Skip navigation
Product & Engineering

What Duo Unix Administrators Need to Know About Pluggable Authentication Modules

One common hurdle for systems administrators setting up new Duo Unix integrations is PAM — Pluggable Authentication Modules.

With PAM, some advance planning will help prevent running into issues later on. That’s because modifying PAM incorrectly can lead to some serious problems, like bypassing Duo altogether or locking users out of their machines.

We hope that the guidance below, combined with our extensive documentation, will help those setting up new integrations get their systems configured quickly and easily.

What is PAM?

PAM stands for Pluggable Authentication Modules. It is used to standardize authentication for Linux systems.

What Does Duo Use PAM For?

Duo makes use of PAM to provide 2FA during login to a Unix system. We integrate with your existing PAM stack configuration, so it’s important that you have a working system before adding Duo.

PAM Basics

  • PAM has a global state that determines whether an authentication will fail or succeed. If the global state is true, then the authentication will pass; otherwise it will fail. This state is determined based on the outcome of the authentication passing through a module.

  • PAM has multiple service modules, such as “auth,” “password,” “account” and “session.” In this context, our concern is the “auth” service module.

  • Each module in the PAM stack will have a different control flag indicating what should happen if the module is passed or failed.

Setting Control Flags

For PAM to function as desired, make sure to properly configure control flags. These come in several different “flavors” that will determine the continuation or failure behavior of a module.

The requisite, sufficient and required flags each lead to different outcomes.

Requisite: If a requisite module passes, then continue down the PAM stack. If a requisite module fails, then set the global state to false and terminate the PAM stack, failing the authentication.

Sufficient: If a sufficient module passes then set the global state to true and return, succeeding the authentication (there are stipulations on this which will be detailed later). If a sufficient module fails, then do not set the global state to true and keep running the PAM stack.

Required: If a required module passes, then continue down the PAM stack. If a required module fails, then set the global state to false and continue down the PAM stack. This will continue to run the rest of the PAM stacks without setting the global state again.

For example, if the user fails a required module but succeeds a sufficient one, then the global state will NOT be set to true but the stack will terminate, ultimately failing the authentication.

This is useful against brute force attacks. The attacker will not be able to tell if for instance they failed the password authentication or the Duo authentication.

The requisite, sufficient, and required flags are the most common ones you’ll see in a PAM stack, but wait - there’s more!

Include and Substack: These flags allow you to include other PAM stacks within the larger stack. For Include, if the stack terminates with a sufficient, the auth ends. For Substack, if the stack terminates with a sufficient, then you continue with the parent stack.

Optional: This flag allows you to run a module without the outcome of the module affecting the global state.

Type: PAM modules are not limited to returning only pass or fail. Linux PAM defines over 30 different values that a module might return. Instead of one of the original control flags (required, sufficient, requisite, and optional) you can use the new syntax with square braces. You can list any one of seven different actions for each possible return type.

The action says how to combine this return value for the module in the overall pass or fail value that is returned to the application for the whole stack. Each of the four control-flag keywords (required, requisite, sufficient, and optional) have an equivalent expression in terms of the [...] syntax.

The Order of the Modules is Significant

Note: If a prior required module fails, and a later sufficient module passes, access will be denied. To say that another way, the order in which required modules are called doesn’t matter. Only the order of the sufficient and requisite control flags come into play.

The following module says access is allowed if both modules A and B pass, or if both modules A and C pass:

auth required pam_moduleA
auth sufficient pam_moduleB
auth required pam_moduleC

On the other hand, the policy implemented with the following says to allow access if module B passes, or if modules A and C both pass:

auth sufficient pam_moduleB
auth required pam_moduleA
auth required pam_moduleC

Common PAM Modules

These modules are among the most common ones seen in a PAM stack, particularly if you’re configuring a new system. Duo does not interact with them directly, but some of them are likely to be part of an authentication:

  • pam_unix.so: First factor authentication that uses /etc/passwd and /etc/shadow to check passwords

  • pam_permit.so: Always allows access

  • pam_deny.so: Always denies access

  • pam_sss.so: Allows authentication with LDAP

  • pam_krb5.so: Allows authentication with Kerberos

Other Flags

These flags are less common, but you may still encounter them as you configure your stack:

  • nullok: Users can have a blank password and still access the machine
  • nullok_secure: Same as nullok, but with added security - PAM_TTY needs to be set to a value found in /etc/security
  • try_first_pass: Try the password from a previous module first - if the password is wrong/not applicable, then ask for a new password
  • use_first_pass: Needs to use the previous password, and deny access if the password is not available/did not work

Putting the Pieces Together

Now that we know the basics, let’s talk about what’s going on in this authentication.

When a user tries to log in, we will run the auth service.

The user will be prompted for a password with pam_unix.so. If they type in the correct password, then they will be shown a Duo Unix prompt. If they successfully authenticate with Duo (via push/passcode/phone call/SMS), then the global state will be set to true and they will successfully authenticate.

If the user has a wrong password, then the global state will be set to false, though the user will still be shown a Duo Unix prompt. Even if the user succeeds with the Duo authentication, the sufficient condition will cause the PAM stack to terminate and the auth will fail.

If the user has a wrong password and does not authenticate successfully with Duo Unix, then the pam_deny.so module will run. This would set the state to false (though the state is already false) and then terminate running the PAM stack.

How Do I Navigate This as a Duo Administrator?

There are a lot of moving pieces here, and it can be tricky to pinpoint where Duo comes into play. Our documentation provides several examples to help you integrate the Duo module into your environment. It is important to remember that your PAM stack may not match our examples, and having a strong understanding of the control flags above will help you ensure that you’ve added Duo at the right step.

Our Support teams have seen an untold number of different configurations, and they’re here to help you if you’re seeing specific Duo-related errors. Because each PAM stack is different, they may not be able to assist you in troubleshooting your specific configuration. That being said, our engineers have built a tool that can pull the necessary logs for troubleshooting, and it’s a great place to start tracking down any issues.

One of the best ways to determine if you’re seeing a Duo-related issue or if the PAM stack is configured incorrectly is to check your logs to see if the Duo module is ever engaged. If it isn’t, something in the stack is causing the Duo portion to be skipped, and you’ll never see 2FA.

A few other best practices to follow:

  • Always make a backup copy of the /etc/ssh/sshd_config prior to implementing Duo.

  • Always make a backup copy of your PAM configuration files in /etc/pam.d prior to implementing Duo.

  • Always test logins post-configuration with a separate terminal session, to prevent yourself from being locked out.

One last thing to remember is that there are many different Unix distributions out there, each with its own configuration quirks. We do our best to ensure that pam_duo is as widely compatible as possible, but we’re not able to test every possibility. Ensuring that you have a strong understanding of how to configure your PAM stack before involving Duo will ensure that you’re ready for the next step of securing your systems.