Comprehensive Guide to Allowable Password Characters in Linux Authentication Systems (passwd/shadow/PAM)


2 views

When configuring Linux systems, password policies vary depending on the authentication backend being used. The fundamental constraints come from:

  • The system's PAM (Pluggable Authentication Modules) configuration
  • The specific hashing algorithm in use (SHA-512, bcrypt, etc.)
  • Any additional restrictions in /etc/security/pwquality.conf

For traditional /etc/passwd and /etc/shadow files, Linux typically accepts:

ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
0123456789
!\"#$%&'()*+,-./:;<=>?@[\\]^_{|}~

Example password that would work on most systems:

P@$$w0rd_With-Spec!al-Ch@rs

Some characters may need escaping in shell environments:

# These need special handling:
! $ & * ( ) [ ] { } | ; ' " < > ?  ~

For system-generated passwords, consider this Python example:

import random
import string

def generate_linux_password(length=16):
    chars = string.ascii_letters + string.digits + "!@#$%^&*()_-+=[]{}|;:,.<>?~"
    return ''.join(random.SystemRandom().choice(chars) for _ in range(length))

print(generate_linux_password())

On modern systems using pam_pwquality, check the configuration:

# View current settings:
grep ^min /etc/security/pwquality.conf

# Common parameters:
minlen = 8
minclass = 4
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1

Use chpasswd to test password validity:

echo "testuser:NewP@ssw0rd$" | sudo chpasswd

For debugging PAM authentication:

# Add to /etc/pam.d/common-password
password required pam_pwquality.so debug

For OpenLDAP or Active Directory integration, additional restrictions may apply:

  • OpenLDAP typically inherits system PAM policies
  • AD integration may impose additional character set limitations
  • Some special characters may need URL encoding

Example of an AD-compatible password generator:

# PowerShell snippet for AD-compatible passwords
function Get-AdPassword {
    param([int]$Length=12)
    $chars = [char[]]"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;:,.<>?"
    $rng = New-Object System.Security.Cryptography.RNGCryptoServiceProvider
    $bytes = New-Object byte[]($Length)
    $rng.GetBytes($bytes)
    $result = ""
    foreach ($byte in $bytes) {
        $result += $chars[$byte % $chars.Length]
    }
    return $result
}

When configuring authentication on Linux systems, the allowable password characters primarily depend on two factors:

  1. The PAM (Pluggable Authentication Modules) configuration
  2. The specific authentication backend being used (passwd/shadow, LDAP, etc.)

For traditional /etc/passwd and /etc/shadow authentication, most Linux systems accept the following character set:

ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
0123456789
!@#$%^&*()-_=+[]{}|;:'",.<>/?~

The actual limitations come from several sources:

  • PAM cracklib: Often enforces complexity rules but doesn't restrict character types
  • System crypt(): The hashing function must support the characters
  • Terminal/shell escaping: Special characters may need escaping when entered

You can test character support with this simple bash script:

#!/bin/bash
for char in \! \\ \" \# \$ % \& \' $$ \* \+ \, \- \. \/ \: \; \< \= \> \? \@ $$\\$$ \^ \_ \ \{ \| \} \~
do
    echo "Testing character: $char"
    if sudo passwd --stdin testuser <<< "password$char" &>/dev/null; then
        echo "$char - ALLOWED"
    else
        echo "$char - REJECTED"
    fi
done

Different authentication backends may impose additional restrictions:

Backend Special Character Notes
LDAP May reject characters that need URL encoding
Active Directory Often has stricter rules than standard Linux
PAM limits Can be modified in /etc/security/pwquality.conf

When creating password policies that involve special characters:

  1. Test your exact authentication stack
  2. Document allowed characters for your organization
  3. Consider UI implications (web interfaces may have different rules)
  4. Account for international keyboards if relevant

To customize character restrictions in RHEL/CentOS:

# Edit /etc/security/pwquality.conf
minlen = 14
minclass = 4
maxrepeat = 3
dictcheck = 1
usercheck = 1
enforcing = 1
# No direct character restrictions here, but controls complexity