html
When managing a Linux system, it's crucial to identify which user accounts have login privileges. Contrary to common assumption, not all entries in /etc/passwd represent actual login-capable users. Here's how to properly distinguish them.
Two primary methods prevent user logins:
- Restricted Shells: The shell field in
/etc/passwdspecifies login capability:# Example of non-login users in /etc/passwd mail:x:8:8:mail:/var/mail:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/bin/false - Password Locking: The
/etc/shadowfile controls authentication:# Disabled account examples in /etc/shadow disableduser:!:19185:0:99999:7::: lockeduser:*:19185:0:99999:7:::
Here are several ways to list login-capable users:
# Method 1: Filter valid shells from /etc/passwd
grep -vE '/nologin$|/false$|/sync$|/halt$' /etc/passwd | cut -d: -f1
# Method 2: Check accounts with valid passwords in /etc/shadow
awk -F: '($2 != "*" && $2 != "!" && $2 !~ /^!/) {print $1}' /etc/shadow
# Method 3: Combined check using getent
getent passwd | awk -F: '$7 !~ /(false|nologin|sync|halt)/ {print $1}' | \
while read user; do
getent shadow "$user" | awk -F: '$2 !~ /^[*!]/ {print $1}'
done
Linux systems create various service accounts during installation. These typically:
- Have UIDs below 1000 (varies by distribution)
- Use
/usr/sbin/nologinor/bin/falseshells - Have locked passwords in
/etc/shadow
For comprehensive checking, use this Bash script:
#!/bin/bash
echo "Users with login capability:"
echo "---------------------------"
while IFS=: read -r user _ uid _ _ shell _; do
# Skip system accounts (UID < 1000)
[ "$uid" -ge 1000 ] || continue
# Check shadow entry if shell appears valid
if [[ "$shell" != *"nologin"* && "$shell" != *"false"* ]]; then
pass_status=$(getent shadow "$user" | cut -d: -f2)
case "$pass_status" in
'!'|'*'|'!!') continue ;; # Skip locked accounts
*) echo "$user" ;;
esac
fi
done < /etc/passwd
Some exceptions require attention:
- SSH Key Authentication: Users with
/bin/falseshell can still login via SSH keys if configured - PAM Modules: Custom PAM configurations might override standard login restrictions
- SUDO Privileges: Some services might allow privilege escalation without shell access
In Linux systems, determining whether a user can log in involves examining multiple configuration files and authentication mechanisms. The /etc/passwd file alone doesn't tell the complete story - we need to analyze both shell assignments and password status.
These are the primary ways a user account can be prevented from logging in:
# Example of non-login users in /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/bin/false
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
To thoroughly check login capability, examine these aspects:
#!/bin/bash
# Script to list all login-capable users
echo "Login-capable users:"
getent passwd | while IFS=: read -r user _ uid _ _ shell _; do
# Check for valid shell
if grep -q "$shell" /etc/shells || [[ "$shell" == "/bin/bash" ]]; then
# Check shadow status
passwd_status=$(getent shadow "$user" | cut -d: -f2)
if [[ "$passwd_status" != "!"* && "$passwd_status" != "*" && "$passwd_status" != "!!" ]]; then
echo "$user (UID: $uid)"
fi
fi
done
Here are useful one-liners for different verification needs:
# List all users with interactive shells
getent passwd | grep -Ev '(/usr/sbin/nologin|/bin/false|/sbin/nologin|/bin/sync|/bin/true)$'
# Check if specific user can login
can_user_login() {
user="$1"
shell=$(getent passwd "$user" | cut -d: -f7)
[[ -f "/etc/shells" ]] && valid_shell=$(grep -q "^$shell$" /etc/shells)
[[ "$shell" == "/bin/bash" || "$valid_shell" ]] && \
! grep -q "^$user:.*[!*]" /etc/shadow
}
For systems using PAM (Pluggable Authentication Modules), additional restrictions might apply. Check these files:
/etc/pam.d/login
/etc/pam.d/sshd
/etc/security/access.conf
/etc/security/time.conf
Example access.conf entry that would prevent login even with valid shell and password:
-:wheel:ALL EXCEPT LOCAL .example.com