PAM and Account PolicyLesson 3 of 3
Why can't this user log in?
Work through password, account state, shell, PAM restrictions, sshd rules and SELinux labels using the logs.
journalctl _COMM=sshd/var/log/securesshd -Tsshd -tausearch -m user_authlastlastbgetent passwdnamei -lrestoreconvisudo -csudo -l -U/etc/nologin/etc/security/access.conf
After this lesson you can
- Read sshd and PAM messages in /var/log/secure and the journal and map each to a cause.
- Check the effective sshd configuration with sshd -T and the drop-in order.
- Diagnose key-based login failures from permissions and SELinux labels, and restrictions from pam_access and /etc/nologin.
The idea
“I can’t log in” is a symptom with at least a dozen causes, and the fastest way to the right one is to let the system tell you. Every login attempt is logged twice: by the service that handled it (sshd, login, su) and by the PAM modules it called. Both write to /var/log/secure on RHEL (and to the journal), with enough text to name the stage that refused.
sudo tail -f /var/log/secure # watch while the user retries
sudo journalctl _COMM=sshd -S "10 min ago" # sshd entries from the journal
sudo ausearch -m user_auth,user_acct -ts recent # audit records of auth and account decisions
last -n 10 # recent successful logins
sudo lastb -n 10 # recent failed logins
Ask the user to retry while you watch. A message written at that moment is worth more than any theory.
Which stage refused?
A login passes through these checks, in order. The first that fails ends the attempt.
| # | Stage | Fails with | Evidence | Check |
|---|---|---|---|---|
| 1 | Does the user exist? | invalid user X | sshd log | getent passwd X |
| 2 | sshd rules | not allowed because not listed in AllowUsers, DenyUsers, PermitRootLogin no | sshd log | sshd -T, drop-ins |
| 3 | Authentication: password | Failed password, authentication failure | pam_unix(...:auth) | faillock --user, the password itself, passwd -S |
| 3 | Authentication: key | Authentication refused: bad ownership or modes, or silence then password prompt | sshd log, ssh -v | Permissions, label, key content |
| 4 | PAM account | expired, account locked, pam_nologin: Refused, pam_access: access denied | pam_unix(...:account) | chage -l, /etc/nologin, access.conf |
| 5 | Shell | Connection opens and closes at once | This account is currently not available. | getent passwd field 7 |
| 6 | Session | pam_limits, pam_selinux, home missing | pam_*(...:session) | ls -ld ~, getsebool, limits |
sshd: read the effective configuration
Editing /etc/ssh/sshd_config is not enough to know what sshd does. On RHEL it includes /etc/ssh/sshd_config.d/*.conf, and for most options the first value wins. Packaged defaults live in 50-redhat.conf; put your local settings in a file that sorts earlier, such as 01-local.conf.
sudo sshd -t # syntax check; prints nothing when OK
sudo sshd -T | grep -iE 'permitrootlogin|passwordauthentication|allowusers|allowgroups|pubkeyauthentication'
ls /etc/ssh/sshd_config.d/
sudo systemctl reload sshd # not restart: keeps existing sessions
sshd -T prints the configuration as sshd actually parsed it, including defaults. If a setting you edited is not what -T shows, a drop-in earlier in the order overrides it, or the daemon was not reloaded.
Key login: three families of fault
If key login falls back to a password prompt, one of the following is wrong on the server:
- Ownership and modes. With
StrictModes yes(default), sshd refuses a key if the home directory,~/.sshorauthorized_keysis writable by group or others, or not owned by the user. Required: home not writable by others (755 or 750),.ssh700,authorized_keys600. - SELinux labels. sshd runs confined; files must be
ssh_home_t(for.sshandauthorized_keys). Copying files in as root from elsewhere leaves wrong labels. The log shows nothing useful;ausearch -m avcdoes. Repair withrestorecon -Rv ~/.ssh. - The key itself. Wrong public key, truncated line, a
from=orcommand=option, or the file is not in a location named byAuthorizedKeysFile.
On the client, ssh -v user@host shows which keys are offered and the server’s reply; -vvv adds the details.
Restrictions outside sshd
| Mechanism | File | Effect |
|---|---|---|
pam_nologin | /etc/nologin exists | Non-root logins refused with its text |
pam_access | /etc/security/access.conf | Allow/deny by user, group, origin: -:u4:ALL |
pam_time | /etc/security/time.conf | Allow only at certain times |
pam_limits | /etc/security/limits.d/*.conf | Resource limits, can cause session failures for extreme values |
pam_listfile, pam_wheel | the service’s /etc/pam.d/FILE | Lists and group requirements (su requires wheel in many setups) |
| shell | getent passwd field 7 | /sbin/nologin or /bin/false refuses interactive login |
sudo is a separate decision after login: sudo -l -U alex lists what a user may run; sudo visudo -c checks the syntax of all sudoers files. A syntax error in /etc/sudoers breaks sudo for everybody; edit with visudo, never with an editor directly.
Try it
Reading a failed attempt
sudo journalctl _COMM=sshd -n 6 --no-pager
Nov 04 13:02:11 node2 sshd[2201]: Failed password for alex from 192.168.50.11 port 40122 ssh2
Nov 04 13:02:19 node2 sshd[2203]: User carol not allowed because account is locked
Nov 04 13:02:25 node2 sshd[2205]: pam_nologin(sshd:account): Refused user dave
Nov 04 13:02:31 node2 sshd[2207]: Authentication refused: bad ownership or modes for directory /home/erin
Nov 04 13:02:37 node2 sshd[2209]: User frank from 192.168.50.11 not allowed because not listed in AllowUsers
Nov 04 13:02:44 node2 sshd[2211]: Failed password for invalid user bob from 192.168.50.11 port 40130 ssh2
Every line names its cause. Notice that “Failed password for invalid user bob” is a nonexistent account, and the same text without “invalid user” is a real account with a wrong password. Do not read the first as a password problem.
The home directory and the label
namei -l /home/erin/.ssh/authorized_keys
ls -Z /home/erin/.ssh
f: /home/erin/.ssh/authorized_keys
dr-xr-xr-x root root /
drwxr-xr-x root root home
drwxrwxr-x erin erin erin
drwx------ erin erin .ssh
-rw------- erin erin authorized_keys
unconfined_u:object_r:user_home_t:s0 authorized_keys
(Representative output.) Two faults in one view: the home directory erin is drwxrwxr-x (group writable, which StrictModes refuses), and the file’s type is user_home_t instead of ssh_home_t. Fix the first with chmod 755 /home/erin (or 750), the second with restorecon -Rv /home/erin/.ssh, and test again. If SELinux were the only fault, the log would show no “bad ownership” line at all, only a failed key and a fallback to a password prompt.
Account state at a glance
Three commands that answer most account questions:
getent passwd labuser1
passwd -S labuser1
chage -l labuser1 | sed -n 1,4p
labuser1:x:30033:30033::/home/labuser1:/sbin/nologin
labuser1 P 2026-11-04 7 90 14 5
Last password change : Nov 04, 2026
Password expires : Feb 02, 2027
Password inactive : Feb 07, 2027
Account expires : Jan 01, 2020
(Real output from a test account.) Three separate things are wrong with this account: the shell is /sbin/nologin, the account expired in 2020, and the password has an inactivity limit. passwd -S alone says P (fine), which is why you need all three commands. After each change, test the login again, because the next fault only shows up once the first is fixed.
A routine for any login failure
- Reproduce it yourself (
ssh -v, orsu - user) while watching/var/log/secure. - Read the exact message and place it in the table above.
- Confirm with one command (
getent,passwd -S,chage -l,sshd -T,namei -l,ls -Z,ausearch). - Change one thing, retry, and read the log again.
- When it works, check that the fix is persistent (a file, not a runtime tweak) and that you have not relaxed security to get there.
Going further
Locked out as root. If PAM or sshd configuration prevents every login, the console and the recovery path from the boot lessons (rd.break, rescue media, authselect apply-changes) are the way back. Having a tested recovery path is part of changing authentication. Beyond the exam: with SSSD and IdM, failures involve the sssd cache, Kerberos tickets and clock skew (sssctl user-checks USER, klist); the local checks above still apply first, and sssctl user-checks shows how the PAM stack sees the user.
Practice
0 of 3 done
Do these on your own system. They get harder. Check each result, then tick it off.
- Warm-up
Match the message to the cause
For each log line, name the cause and the check that confirms it:
sshd[2201]: Failed password for alex from 192.168.50.11 port 40122 ssh2 sshd[2201]: Failed password for invalid user bob from 192.168.50.11 port 40130 ssh2 sshd[2203]: User carol not allowed because account is locked sshd[2205]: pam_nologin(sshd:account): Refused user dave sshd[2207]: Authentication refused: bad ownership or modes for directory /home/erin sshd[2209]: User frank from 192.168.50.11 not allowed because not listed in AllowUsersCheck your result
- 1: wrong password for an existing user (
faillock --user alex, expiry withchage -l). - 2: the user does not exist (
getent passwd bob). - 3: the account is locked (
passwd -S carol,usermod -U). - 4:
/etc/nologinexists (ls -l /etc/nologin, remove or wait for maintenance end). - 5: home directory is group/world writable (
ls -ld /home/erin,chmod 755or750). - 6:
AllowUsers/AllowGroupsin the effective configuration (sshd -T | grep -i allow).
Hint
sshd names the stage in the text:
invalid usermeans no such account;not allowed because ...is a rule;Authentication refusedis a permission problem with a file or directory;pam_*(...)names the PAM module and group that refused.Solution
sudo grep sshd /var/log/secure | tail -20 getent passwd bob sudo passwd -S carol ls -l /etc/nologin ls -ld /home/erin sudo sshd -T | grep -iE 'allowusers|allowgroups|denyusers' - 1: wrong password for an existing user (
- Practice
The key is right but the server says no
Setup (server node2):
sudo useradd -m keyuser sudo -u keyuser mkdir -m 755 /home/keyuser/.ssh echo "ssh-ed25519 AAAA...your public key... keyuser@lab" | sudo tee /home/keyuser/.ssh/authorized_keys sudo chmod 664 /home/keyuser/.ssh/authorized_keys sudo chmod 775 /home/keyuser sudo chcon -t user_home_t /home/keyuser/.ssh /home/keyuser/.ssh/authorized_keysssh keyuser@node2.lab.exampleasks for a password or saysPermission denied (publickey). Find all three causes usingssh -von the client and the log,namei -landls -Zon the server, and fix them with the minimum change. Then log in with the key.Check your result
ssh -o PreferredAuthentications=publickey keyuser@node2.lab.example idworks.- On node2:
ls -ld /home/keyusershows no group/other write;.sshis700,authorized_keysis600;ls -Zshowsssh_home_tfor both.
Hint
The log says
Authentication refused: bad ownership or modesfor the permission faults (StrictModes yesis the default). The label fault leaves no such message: sshd simply cannot read the file, andausearch -m avcshows a denial.restorecon -Rv ~keyuser/.sshrepairs labels from policy.Solution
ssh -v keyuser@node2.lab.example 2>&1 | grep -iE 'offering|denied|authenticat' | head sudo journalctl _COMM=sshd -n 5 --no-pager namei -l /home/keyuser/.ssh/authorized_keys ls -Z /home/keyuser/.ssh sudo chmod 755 /home/keyuser sudo chmod 700 /home/keyuser/.ssh && sudo chmod 600 /home/keyuser/.ssh/authorized_keys sudo restorecon -Rv /home/keyuser/.ssh ssh keyuser@node2.lab.example id - Challenge
Five users, five reasons
Setup (lab VM; keep a root session open): create five users
u1..u5with a known password and cause one different fault for each, without telling yourself which is which:for u in u1 u2 u3 u4 u5; do sudo useradd -m $u; echo "$u:Lab-Pass-12345" | sudo chpasswd; done sudo usermod -L u1 sudo chage -E 2020-01-01 u2 sudo usermod -s /sbin/nologin u3 echo '-:u4:ALL' | sudo tee -a /etc/security/access.conf sudo chage -d 0 -M 1 -I 0 u5 && sudo chage -d 2020-01-01 u5(the
pam_accessline only takes effect if theaccountstack includespam_access.so; add it withauthselectfeatures or a custom profile, or use the equivalentDenyUsers u4in an sshd drop-in). Trysu - uNorssh uN@localhostfor each, and for every one name the cause, the single command that proves it, and the fix. Make sure the final state lets all five log in and you have changed no more than needed.Check your result
- u1:
passwd -S u1isL→usermod -U u1. - u2:
chage -l u2Account expires in the past →chage -E -1 u2. - u3:
getent passwd u3shell/sbin/nologin→usermod -s /bin/bash u3. - u4: rule in
access.conforDenyUsers→ remove it. - u5: password expired and inactive period over →
chage -I -1 -M 99999 -d $(date +%F) u5(or set a new password). - Each
su - uN -c idsucceeds.
Hint
Four checks cover almost everything:
getent passwd(shell),passwd -S(lock),chage -l(expiry and aging), and the logsjournalctl _COMM=sshd,/var/log/secure. The message text tells which PAM group refused:pam_unix(sshd:account): expiredis account,authentication failureis auth.Solution
for u in u1 u2 u3 u4 u5; do echo "== $u"; getent passwd $u | cut -d: -f1,7; sudo passwd -S $u; sudo chage -l $u | sed -n '2,4p'; done sudo grep -E 'u[1-5]' /var/log/secure | tail -15 sudo usermod -U u1 sudo chage -E -1 u2 sudo usermod -s /bin/bash u3 sudo sed -i '/^-:u4:ALL/d' /etc/security/access.conf sudo chage -I -1 -M 99999 -d $(date +%F) u5 for u in u1 u2 u3 u4 u5; do sudo su - $u -c 'id -un'; done - u1: