PAM notes
Linux-related notes
Shell, admin, and both:
|
Security related stuff.
Securing services
Unsorted - · Anonymization notes · website security notes · integrated security hardware · Glossary · unsorted |
pam rules
Simple example of a PAM rule file:
auth [success=1 default=ignore] pam_unix.so nullok_secure auth requisite pam_deny.so auth required pam_permit.so
The columns are:
- module interface (facility)
- control flag - controls how rules can short-circuit yes/no answers, avoid doing so, and such
- module name
- module arguments - often empty
module interfaces
one of:
- auth - authentication - requests and verifies the validity of login, e.g. a password
- can also set credentials, such as group memberships or Kerberos tickets
- account - account management, including authorization i.e. verifies that access is allowed - considering e.g. account expiry, time-of-day logic
- password - authentication token update (often mostly meaning password changes)
- session - configures/manages user sessions
- can e.g. mount a home directory, figure out user mailbox
Few modules take part in all of these. Consider e.g.
- pam_nologin is only there to deny a specific case, so only need be in auth
- pam_unix can be used to authenticate, do extra checks, to change password, and affects the session - so plays in all
- pam_cracklib is used to deny setting bad passwords (e.g. minor variations), so only needs to be in password
See also:
Control field
Conceptually, each line can decide
- to change what we return (and each line can only return one thing)
- whether to go on, or stop now
It's actually a little more interesting - PAM builds a stack of state, one for each module -
yet most uses are much simpler than what you could do.
The logic allows things like
- having distinct modules that can accept authentication,
- complex logic, e.g. have elements that get executed in multiple paths
If you don't keep it simple, you may want to draw out a state diagram, to make sure you don't mess up...
Control field:
- binding
- If the module succeeds and no earlier module in the chain has failed, the chain is immediately terminated and the request is granted
- If the module fails, the rest of the chain is executed, but the request will ultimately be denied
- required
- If the module succeeds, the rest of the chain is executed, and the request is granted unless some other module fails.
- If the module fails, the rest of the chain is still executed, but the request will ultimately be denied.
- requisite
- If the module succeeds, the rest of the chain is executed, and the request is granted unless some other module fails.
- If the module fails, the chain is immediately terminated and the request is denied.
- sufficient
- If the module succeeds and no earlier module in the chain has failed, the chain is immediately terminated and the request is granted.
- If the module fails, the module is ignored and the rest of the chain is executed.
- As the semantics of this flag may be somewhat confusing, especially when it is used for the last module in a chain, it is recommended that the binding control flag be used instead if the implementation supports it.
- optional
- The module is executed, but its result is ignored.
- If all modules in a chain are marked optional, all requests will always be granted.
- useful when setting environment, hooking in features
- include - ...lines from another file at this point.
- Useful for sharing logic.
- But since it acts like 'insert lines here', try to avoid jumps, they can get confusing.
- substack - like include, but the whole thing is executed as if it were a single module - we get its eventual result.
- more precisely, termination within it skips only the rest of the included lines. (and jumps cannot jump out)
The default reaction to a return value is a basic mapping to pass or fail(verify).
You can set your own ruleset with:
[value=action ...]
value is one of:
- success - module says it's happy
- ignore - module signals it wants its return value to be ignored
- abort - module says stop now
- default - 'all return values not explicitly mentioned in this [set]', often used to catch all errors/failures (because there's a bunch of those)
- having this often forces you to mention ignore=ignore (and sometimes other things = some obvious thing), or they would fall under the default action
- errors/failures include:
- open_err, symbol_err, service_err, system_err, buf_err, auth_err, session_err, cred_err, conv_err, authtok_err, authtok_recover_err
- user_unknown, perm_denied, cred_insufficient, authinfo_unavail, new_authtok_reqd, authtok_lock_busy, authtok_disable_aging, authtok_expired, acct_expired, maxtries, cred_unavail, cred_expired, try_again, module_unknown, bad_item, conv_again, incomplete, no_module_data
action is one of
- ignore - module's return status will not contribute to the stack's return code
- bad - flag ourselves as having failed (doesn't terminate)
- die - bad, and terminate
- ok - this module's return code should be considered (...if there are no errors)
- done - ok, and termination
- n (an integer ≥1) - ok, and skip the next n rules
- reset - clear stack module state
Note that the singe-world control fields are essentially shorthands for common cases, of the verbose form explained above.
- required is [success=ok new_authtok_reqd=ok ignore=ignore default=bad]
- requisite is [success=ok new_authtok_reqd=ok ignore=ignore default=die]
- sufficient is [success=done new_authtok_reqd=done default=ignore]
- optional is [success=ok new_authtok_reqd=ok default=ignore]
Example
For example:
[success=2 ignore=ignore default=die]
means:
- if the module succeeds, skip the next two lines
- ignore=ignore is primarily so that ignore doesn't get swallowed by default
- ...default triggers on every return value other than success or ignore
Basic login via a unix terminal looks like:
auth [success=1 default=ignore] pam_unix.so nullok_secure auth requisite pam_deny.so auth required pam_permit.so
If you e.g. use PBIS for authentication via AD, then you can decide you add a fallback source for the additional logins:
auth [success=2 default=ignore] pam_unix.so nullok_secure auth [success=1 default=ignore] pam_lsass.so try_first_pass auth requisite pam_deny.so auth required pam_permit.so
Notes:
- success=n means "skip the next n rules", in here skipping past the "deny auth" rule (to the permit rule)
- nullok_secure means empty passwords are permitted
- control flags:
- requisite for the pam_deny line so that it will unconditionally fail and deny access -- unless this line is not executed at all
- When you have additional things to be run (non-auth things, e.g. controlling the user's environment), you would often avoid binding and sufficient (in the control field) as they can make things unpredictable.
PAM modules include...
- pam_env - read environment variables from a file
- pam_fprint - fingerprint reader
- pam_unix - system's auth as configured in /etc/nsswitch.conf (which often just means reading /etc/passwd and /etc/shadow)
- pam_nologin - when /etc/nologin exists, this denies login from anyone but root.
- Used e.g. while booting.
- pam_securetty - root login to special devices (typically hardware terminals)
- pam_deny - always denies access. e.g. used after a line that does success=1.
- pam_permit - always succeeds, and sets the result values with a positive result.
- Used to avoid the case where nothing set success (e.g. when using skip rules)
- and can avoid some unpredictability from earlier variable sets (verify)
- pam_rootok - authenticates when the uid is 0
- e.g. for su
- pam_succeed_if
- e.g. pam_succeed_if.so user ingroup nopasswdlogin
- useful for passwordless guest accounts(verify)
- pam_krb5 - integrate Kerberos 5
- pam_access - logdaemon style login access control, via /etc/security/access.conf
- pam_limits - limit resources, according to /etc/security/limits.conf
- pam_faildelay - per-application delay on auth failure(verify)
- pam_cap - set capabilities, according to /etc/security/capability.conf (verify)
- pam_mkhomedir
- pam_group - /etc/security/group.conf
- pam_loginuid
- pam_ecryptfs - for encrypted homedirs, where a passphrase can be unwrapped using the supplied password
- pam_motd - print message of the day
- pam_mail - print status of the user's mail
- pam_mount - mount filesystems at login time (commonly for remote shares)
- pam_keyinit -
- pam_gnome_keyring -
- pam_kwallet -
- pam_selinux -
pam_systemd
for the password facility:
pam_pwcheck
pam_unix2
pam_make
Various files
debug
To turn on debug for every module:
touch /etc/pam_debug
To turn it on for a specific module, add debug as an argument to it, e.g.
login auth required pam_unix.so debug
There are sometimes specific debug-related arguments, e.g. pam_mysql has verbose=1