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.
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, soaccount,session, andpasswordlines in/etc/pam.d/xinetare never consulted. - User listing and password verification are separate.
system.userlistand 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.
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 = filestakes account identities from local/etc/passwd.proxy_pam_target = sssd-shadowutilsperforms the password check against/etc/shadowviapam_unix— run by SSSD as root, which is what makes it work.access_provider = permitis the simplest starting point. Change it toproxyif 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
authselectconfigured by the AD tooling, sopam_sssis already present. Here, Step 3 is only a verification. - A server that was never joined to AD has never had
authselectrun.pam_sssis 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
--forceis required on a never-configured server. The current PAM/NSS files were written by the OS installer and are not yet managed byauthselect, so it will not take them over without explicit permission. It backs up whatever it replaces. Without--forcethe 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_unixcheck first, so existing logins keep working, andpam_ssssits inert until SSSD has a domain to answer with. --forceresets optionalauthselectfeatures. 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. TheEnabled features:line inauthselect currenttells 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-auth — authselect 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
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_chkpwdrestriction, 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-author/etc/pam.d/password-auth.authselectregenerates them and your edits will be lost. - Do not point
/etc/pam.d/sssd-shadowutilsatsystem-auth. This creates an authentication loop.
Related
-
Xinet Active Directory Integration Support — Xinet-side mechanics (module installation,
XinetAuthUserFile,/etc/pam.d/xinet,system.userlist). The module and SSSD pattern are identical whether SSSD's back end is AD, a directory service, or the local proxy described here; the AD/domain-join-specific parts do not apply. -
Red Hat: Configuring authentication and authorization in RHEL 9 —
authselect, thesssdprofile, and SSSD providers. - unix_chkpwd(8) man page — the underlying non-root restriction.
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.
Matthew Mrosko
Comments