Start a conversation

Authenticating WebNative against local Linux system users (RHEL 9)

Applies to: Xinet Server 2023.6.4 and later on RHEL 9 (and compatible rebuilds), using the alternate Xinet Apache authentication module (mod_auth_xinet2.so).

Summary: WebNative can authenticate local Linux (/etc/passwd + /etc/shadow) accounts, but not through PAM alone. Because WebNative's Apache runs as the unprivileged apache user, it cannot verify another account's password directly. A privileged broker must perform the check on Apache's behalf. This article explains why, and gives the supported configuration using the SSSD proxy provider.

Symptom

You have installed the Xinet Apache authentication module, replaced AuthUserFile with XinetAuthUserFile in httpd.conf, and created /etc/pam.d/xinet. Active Directory logins worked previously, but local Linux accounts are rejected at the WebNative login page even with the correct password.

/var/log/secure on the WebNative server shows:

unix_chkpwd[32329]: check pass; user unknown
unix_chkpwd[32330]: check pass; user unknown
unix_chkpwd[32330]: password check failed for user (jsmith)
httpd[13472]: pam_unix(xinet:auth): authentication failure; logname= uid=48 euid=48 tty= ruser= rhost= user=jsmith

Why this happens

This is expected Linux security behaviour, not a WebNative fault.

When a user signs in to WebNative, the Xinet Apache module hands the credentials to PAM using the service name xinet (this is why the configuration file is /etc/pam.d/xinet). That PAM call is made inside the httpd process, which runs as the unprivileged apache user — uid=48 euid=48 in the log above.

/etc/shadow is readable only by root. The pam_unix helper unix_chkpwd therefore enforces a hard rule: a non-root caller may verify only its own account's password. Asked to verify a different user, it refuses and reports the generic check pass; user unknown, regardless of whether the password was correct and regardless of what /etc/pam.d/xinet contains.

The check pass; user unknown message does not mean the account is missing. It is the refusal message. getent passwd jsmith will still show the account.

Active Directory worked for exactly this reason in reverse: with AD, the password check is not performed by Apache but by a privileged daemon (SSSD or winbind) acting on Apache's behalf. Local /etc/shadow has no such broker by default — so we add one.

Two details worth knowing, because they rule out common false leads:

  • Only the PAM auth stack is used. The module calls pam_authenticate() and nothing else, so account, session, and password lines in /etc/pam.d/xinet are never consulted.
  • User listing and password verification are separate. system.userlist and the group-list settings control which users appear in WebNative Admin → Users; they do not change how passwords are checked, so no user-list setting can work around the restriction above.

Choosing an approach


Option 1 — SSSD proxy to local shadow Option 2 — Directory service via SSSD
Accounts live in This server's /etc/passwd A directory (Red Hat IdM/FreeIPA, 389-DS, OpenLDAP, or AD over LDAP)
Extra host required No Yes (directory server)
Centralized across servers No — each server keeps its own accounts Yes
Effort Low Moderate
Best for A single WebNative server; reusing accounts that already exist locally Several servers sharing one set of accounts

Both work by the same mechanism: a root-privileged SSSD daemon performs the credential check for Apache. This article covers Option 1. For Option 2, configure SSSD against your directory as normal — the Xinet-side configuration is identical, and no AD domain join is required.

Option 1 — Configure SSSD to broker local shadow authentication

Prerequisite check — confirm SSSD runs as root

The whole method depends on this. It is the default on RHEL 9 (SSSD 2.9.x).

sssd --version
grep -RiE '^[[:space:]]*user[[:space:]]*=' /etc/sssd/sssd.conf /etc/sssd/conf.d 2>/dev/null
ps -eo user,euid,comm | grep '[s]ssd_be'

Expected: version 2.9.x; no output from the grep (SSSD is not pinned to a non-root user); sssd_be running as root. If sssd_be is not yet running, re-check after Step 4.

Forward-looking caveat. SSSD 2.10 and later change the default to an unprivileged sssd user, where the proxy helper is no longer privileged and this method stops working without additional configuration. It is a good fit for RHEL 9; do not assume it survives an OS major-version upgrade unchanged. If you need a configuration that is not tied to this default, use Option 2.

Step 1 — Install the proxy back end

sudo dnf install -y sssd-proxy
ls -l /etc/pam.d/sssd-shadowutils
grep -nE 'pam_sss|system-auth|password-auth' /etc/pam.d/sssd-shadowutils

The grep must return nothing. /etc/pam.d/sssd-shadowutils is a small helper that calls pam_unix directly. Do not repoint it at system-auth or add pam_sss to it — that creates an infinite authentication loop.

Step 2 — Define the proxy domain

Write /etc/sssd/sssd.conf. If the server was previously joined to AD, replace any leftover AD domain with this:

[sssd]
config_file_version = 2
services = nss, pam
domains = shadowutils

[domain/shadowutils]
id_provider = proxy
proxy_lib_name = files
auth_provider = proxy
proxy_pam_target = sssd-shadowutils
access_provider = permit
enumerate = false
use_fully_qualified_names = false
  • proxy_lib_name = files takes account identities from local /etc/passwd.
  • proxy_pam_target = sssd-shadowutils performs the password check against /etc/shadow via pam_unix — run by SSSD as root, which is what makes it work.
  • access_provider = permit is the simplest starting point. Change it to proxy if you also want SSSD to honour account expiry and locked accounts.

Set permissions and validate:

sudo chown root:root /etc/sssd/sssd.conf
sudo chmod 600 /etc/sssd/sssd.conf
sudo sssctl config-check

Step 3 — Put pam_sss into the system login stack

This is the step most often missed, and it differs depending on the server's history.

  • A server that was previously joined to AD already had authselect configured by the AD tooling, so pam_sss is already present. Here, Step 3 is only a verification.
  • A server that was never joined to AD has never had authselect run. pam_sss is not in the login stack and must be enabled explicitly.

Check the current state first:

authselect current
grep pam_sss.so /etc/pam.d/system-auth /etc/pam.d/password-auth

On a server that has never been configured, expect No existing configuration detected. and no output from the grep. That is normal.

Enable the profile:

sudo authselect select sssd --force
  • --force is required on a never-configured server. The current PAM/NSS files were written by the OS installer and are not yet managed by authselect, so it will not take them over without explicit permission. It backs up whatever it replaces. Without --force the command refuses and no change is made — which leaves the symptom in this article unchanged.
  • Safe to run before the SSSD domain is live: the profile keeps the local pam_unix check first, so existing logins keep working, and pam_sss sits inert until SSSD has a domain to answer with.
  • --force resets optional authselect features. If you use any (for example faillock or mkhomedir), re-list them on the same line: sudo authselect select sssd with-faillock with-mkhomedir --force. The Enabled features: line in authselect current tells you which are set.

Verify it took effect:

grep pam_sss.so /etc/pam.d/system-auth /etc/pam.d/password-auth
authselect check

Do not hand-edit /etc/pam.d/system-auth or /etc/pam.d/password-authauthselect owns and regenerates them.

Step 4 — Confirm /etc/pam.d/xinet delegates to system-auth

pam_sss in system-auth only helps WebNative if the xinet PAM service actually includes system-auth. Copying /etc/pam.d/login achieves this, because that file delegates to system-auth:

grep -nE 'system-auth|pam_sss' /etc/pam.d/xinet

You should see at least one system-auth line (typically auth substack system-auth). If /etc/pam.d/xinet instead contains only a bare pam_unix line, it will never reach pam_sss no matter how system-auth is configured. In that case, recreate it:

sudo cp -p /etc/pam.d/xinet /etc/pam.d/xinet.backup 2>/dev/null
sudo cp /etc/pam.d/login /etc/pam.d/xinet

You do not need to edit the file beyond this — because it references system-auth by name, it picks up the Step 3 change automatically.

Step 5 — Start SSSD and restart Apache

sudo systemctl enable --now sssd
sudo systemctl restart sssd
sudo systemctl restart httpd
sudo httpd -t

httpd -t should report Syntax OK.

Step 6 — Leave the Xinet-side configuration as it is

The authentication module, the XinetAuthUserFile entries in httpd.conf, /etc/pam.d/xinet, and /usr/etc/webnative/system.userlist all stay as configured for the module.

Because these are real local /etc/passwd accounts, they enumerate normally and appear in WebNative Admin → Users through the standard system-users mode. No group-list configuration is needed for this option.

To keep the built-in WebNative web accounts (including nativeadmin) available alongside the system accounts, ensure /usr/etc/webnative/system.userlist contains:

UseApacheList=1

and contains no UseGroupList or GroupList entries.

Verifying success

Sign in to WebNative with a local Linux account, then check /var/log/secure:

sudo tail -n 20 /var/log/secure

Success looks like this:

unix_chkpwd[4489]: check pass; user unknown
unix_chkpwd[4490]: check pass; user unknown
unix_chkpwd[4490]: password check failed for user (jsmith)
httpd[3318]: pam_unix(xinet:auth): authentication failure; logname= uid=48 euid=48 ... user=jsmith
httpd[3318]: pam_sss(xinet:auth): authentication success; logname= uid=48 euid=48 ... user=jsmith
The unix_chkpwd and pam_unix failure lines are expected and harmless. RHEL tries the local pam_unix check first, which still cannot read /etc/shadow as apache, then hands the check to SSSD. The decisive line is pam_sss(xinet:auth): authentication success.

This applies to regular login accounts (UID ≥ 1000). The RHEL login stack deliberately skips pam_sss for low-numbered system/service accounts.

Troubleshooting by log signature

What /var/log/secure shows after a failed login Meaning Action
pam_unix(xinet:auth) failure and no pam_sss line at all pam_sss is not being executed in the xinet auth path Work through Steps 3 and 4. Most often the sssd profile is not active (authselect current shows no configuration, or authselect select sssd was run without --force and refused). Otherwise /etc/pam.d/xinet is not delegating to system-auth, or the account is UID < 1000.
pam_sss ... User not known to the underlying authentication module pam_sss is running, but SSSD cannot resolve the account Check Step 2 (id_provider = proxy, proxy_lib_name = files), then sudo sssctl config-check and id <user>.
pam_sss ... Request to sssd failed / cannot connect pam_sss is running but the SSSD daemon is not reachable systemctl status sssd; confirm Step 5. If SELinux is enforcing, see below.
Login hangs, or SSSD logs recursion The proxy PAM target chains back into pam_sss Restore the packaged /etc/pam.d/sssd-shadowutils (Step 1) so it calls pam_unix only.
No xinet service lines in the log at all The request is not reaching the Xinet auth module Confirm the module is loaded and that LoadModule appears before Include conf.modules.d/*.conf in httpd.conf, and that AuthUserFile was replaced by XinetAuthUserFile.

SELinux. The RHEL 9 Xinet installation guide expects SELINUX=disabled. If this server was built without that step, confirm with getenforce. If it reports Enforcing, check for denials with sudo ausearch -m avc -ts recent before making other changes — httpd's access to the SSSD PAM socket is SELinux-gated.

Configurations to avoid

  • Do not run Apache as root. A uid-0 caller is exempt from the unix_chkpwd restriction, so this would appear to fix the symptom. It exposes a web-facing process with full root privileges, defeats Apache's privilege-drop design, causes file-ownership side effects, and is outside the supported Xinet configuration. Use a privileged broker instead, as above.
  • Do not loosen permissions on /etc/shadow. Making the password database readable by the web server user exposes every account hash on the system.
  • Do not hand-edit /etc/pam.d/system-auth or /etc/pam.d/password-auth. authselect regenerates them and your edits will be lost.
  • Do not point /etc/pam.d/sssd-shadowutils at system-auth. This creates an authentication loop.

Related

If you work through this article and the pam_sss(xinet:auth): authentication success line still does not appear, contact Support with the output of authselect current, grep pam_sss.so /etc/pam.d/system-auth, cat /etc/pam.d/xinet, sudo sssctl config-check, and a /var/log/secure extract covering one failed login attempt.

Choose files or drag and drop files
Was this article helpful?
Yes
No
  1. Matthew Mrosko

  2. Posted

Comments