How to Determine User Login Permissions in Linux: Shells, Shadow File, and System Accounts


60 views

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:

  1. Restricted Shells: The shell field in /etc/passwd specifies 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
  2. Password Locking: The /etc/shadow file 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/nologin or /bin/false shells
  • 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/false shell 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