<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>NSS Archives - Linuxcent</title>
	<atom:link href="https://linuxcent.com/tag/nss/feed/" rel="self" type="application/rss+xml" />
	<link>https://linuxcent.com/tag/nss/</link>
	<description>Infrastructure security, from the kernel up.</description>
	<lastBuildDate>Sat, 09 May 2026 18:38:36 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.4</generator>

<image>
	<url>https://linuxcent.com/wp-content/uploads/2026/04/favicon-512x512-1-150x150.png</url>
	<title>NSS Archives - Linuxcent</title>
	<link>https://linuxcent.com/tag/nss/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">211632295</site>	<item>
		<title>How LDAP Authentication Works on Linux: PAM, NSS, and the Login Stack</title>
		<link>https://linuxcent.com/ldap-authentication-linux-pam-nss/</link>
					<comments>https://linuxcent.com/ldap-authentication-linux-pam-nss/#respond</comments>
		
		<dc:creator><![CDATA[Vamshi Krishna Santhapuri]]></dc:creator>
		<pubDate>Sun, 26 Apr 2026 19:46:19 +0000</pubDate>
				<category><![CDATA[Identity & Authentication]]></category>
		<category><![CDATA[Authentication]]></category>
		<category><![CDATA[LDAP]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[linux-security]]></category>
		<category><![CDATA[NSS]]></category>
		<category><![CDATA[PAM]]></category>
		<category><![CDATA[SSSD]]></category>
		<guid isPermaLink="false">https://linuxcent.com/ldap-authentication-linux-pam-nss/</guid>

					<description><![CDATA[<p><span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 8</span> <span class="rt-label rt-postfix">minutes</span></span>How LDAP authentication works on Linux: trace an SSH login through PAM, nsswitch.conf, and SSSD to understand exactly what happens before the shell opens.</p>
<p>The post <a href="https://linuxcent.com/ldap-authentication-linux-pam-nss/">How LDAP Authentication Works on Linux: PAM, NSS, and the Login Stack</a> appeared first on <a href="https://linuxcent.com">Linuxcent</a>.</p>
]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 8</span> <span class="rt-label rt-postfix">minutes</span></span><style>
pre{position:relative;background:#1e1e1e;color:#d4d4d4;
    padding:16px 16px 16px 20px;border-radius:6px;overflow-x:auto;
    font-family:'JetBrains Mono','Fira Code','Cascadia Code',Consolas,'Courier New',monospace;
    font-size:.88em;line-height:1.6;border-left:4px solid #555}
code{background:#f4f4f4;padding:2px 5px;border-radius:3px;font-size:.9em}
pre code{background:transparent;padding:0;color:inherit}
pre[data-lang="bash"],pre[data-lang="sh"],
pre[data-lang="shell"],pre[data-lang="zsh"]{border-left-color:#4ec9b0}
pre[data-lang="yaml"],pre[data-lang="json"],
pre[data-lang="toml"],pre[data-lang="xml"]{border-left-color:#569cd6}
pre[data-lang="python"],pre[data-lang="go"],pre[data-lang="rust"],
pre[data-lang="java"],pre[data-lang="c"],pre[data-lang="cpp"]{border-left-color:#c586c0}
pre[data-lang="text"],pre[data-lang="output"],
pre[data-lang="console"]{border-left-color:#888}
.lc-copy-btn{position:absolute;top:8px;right:8px;background:#2d2d2d;color:#ccc;
    border:1px solid #444;border-radius:4px;padding:3px 9px;font-size:.75em;
    font-family:system-ui,sans-serif;cursor:pointer;opacity:0;
    transition:opacity .15s,background .15s;line-height:1.6}
pre:hover .lc-copy-btn{opacity:1}
.lc-copy-btn:hover{background:#3a3a3a;color:#fff}
.lc-copy-btn.copied{color:#4ec9b0;border-color:#4ec9b0}
.lc-lang-badge{position:absolute;top:8px;left:20px;font-family:system-ui,sans-serif;
    font-size:.7em;color:#666;text-transform:uppercase;letter-spacing:.04em;
    line-height:1;pointer-events:none;opacity:0;transition:opacity .15s}
pre:hover .lc-lang-badge{opacity:1}
table{border-collapse:collapse;width:100%;margin:16px 0}
th,td{border:1px solid #ddd;padding:10px 14px;text-align:left}
th{background:#f0f0f0;font-weight:600}
tr:nth-child(even){background:#fafafa}
</style>
<p><script>
(function(){
  if(window.__lcCodeEnhanced)return;
  window.__lcCodeEnhanced=true;
  function enhance(){
    document.querySelectorAll('pre').forEach(function(pre){
      var code=pre.querySelector('code');
      var lang='';
      if(code){var m=(code.className||'').match(/language-(\S+)/);if(m)lang=m[1].toLowerCase();}
      if(lang)pre.setAttribute('data-lang',lang);
      if(lang){var badge=document.createElement('span');badge.className='lc-lang-badge';badge.textContent=lang;pre.insertBefore(badge,pre.firstChild);}
      var btn=document.createElement('button');
      btn.className='lc-copy-btn';btn.textContent='Copy';btn.setAttribute('aria-label','Copy code to clipboard');
      pre.appendChild(btn);
      btn.addEventListener('click',function(){
        var text=code?code.innerText:pre.innerText;
        if(navigator.clipboard&&window.isSecureContext){
          navigator.clipboard.writeText(text).then(function(){ok(btn);}).catch(function(){fb(text,btn);});
        }else{fb(text,btn);}
      });
    });
  }
  function ok(btn){btn.textContent='Copied!';btn.classList.add('copied');setTimeout(function(){btn.textContent='Copy';btn.classList.remove('copied');},2000);}
  function fb(text,btn){
    try{var ta=document.createElement('textarea');ta.value=text;ta.style.cssText='position:fixed;left:-9999px;top:-9999px;opacity:0';document.body.appendChild(ta);ta.select();document.execCommand('copy');document.body.removeChild(ta);ok(btn);}
    catch(e){btn.textContent='✗ Failed';setTimeout(function(){btn.textContent='Copy';},2000);}
  }
  if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',enhance);}else{enhance();}
})();
</script></p>
<p><em>The Identity Stack, Episode 3</em><br />
<a href="/what-is-ldap/">EP01: What Is LDAP</a> → <a href="/ldap-internals-directory-structure/">EP02: LDAP Internals</a> → <strong>EP03</strong> → <a href="/sssd-linux-authentication/">EP04: SSSD</a> → &#8230;</p>
<hr />
<h2 id="tldr">TL;DR</h2>
<ul>
<li>LDAP is a directory protocol — it stores identity information and can verify a password via Bind, but authentication on Linux runs through PAM, not directly through LDAP</li>
<li>NSS (<code class="" data-line="">/etc/nsswitch.conf</code>) answers &#8220;who is this user?&#8221; — it resolves UIDs, group memberships, and home directories by querying LDAP (or the local files, or SSSD)</li>
<li>PAM (<code class="" data-line="">/etc/pam.d/</code>) answers &#8220;are they allowed in?&#8221; — it enforces authentication, account validity, session setup, and password policy</li>
<li><code class="" data-line="">pam_ldap</code> (the old way) opened a direct LDAP connection on every login — fragile, no caching, broken when the LDAP server was unreachable</li>
<li><code class="" data-line="">pam_sss</code> (the modern way) delegates to SSSD, which caches credentials and handles failover — SSSD is the layer between Linux and the directory</li>
<li>Tracing a single SSH login: <code class="" data-line="">sshd</code> → PAM → <code class="" data-line="">pam_sss</code> → SSSD → LDAP Bind + Search → session created</li>
</ul>
<hr />
<h2 id="the-big-picture-one-ssh-login-four-layers">The Big Picture: One SSH Login, Four Layers</h2>
<pre><code class="" data-line="">You type: ssh vamshi@server.corp.com

  sshd
    │
    ▼
  PAM  (/etc/pam.d/sshd)          ← &quot;Is this user allowed in?&quot;
    │
    ├── pam_sss    (auth)          ← sends credentials to SSSD
    ├── pam_sss    (account)       ← checks account not expired/locked
    ├── pam_sss    (session)       ← logs the session open/close
    └── pam_mkhomedir (session)    ← creates /home/vamshi if it doesn&#039;t exist
    │
    ▼
  SSSD  (/etc/sssd/sssd.conf)     ← &quot;Let me check the directory&quot;
    │
    ├── NSS responder              ← answers getent, id, getpwnam
    └── LDAP/Kerberos provider     ← talks to the actual directory
    │
    ▼
  LDAP Server (AD / OpenLDAP)
    │
    ├── Bind: uid=vamshi + password (or Kerberos ticket)
    └── Search: posixAccount attrs for uid=vamshi
    │
    ▼
  Linux session created
  UID=1001, GID=1001, HOME=/home/vamshi, SHELL=/bin/bash
</code></pre>
<p>EP02 showed what the directory contains and what travels on the wire. What it left open is how Linux uses that to grant a login — and why LDAP is not, by itself, an authentication protocol.</p>
<hr />
<h2 id="why-ldap-is-not-an-authentication-protocol">Why LDAP Is Not an Authentication Protocol</h2>
<p>This is the confusion that trips people most. LDAP can verify a password — the Bind operation does exactly that. But authentication on Linux means something broader: checking credentials, checking account validity, enforcing password policy, setting up a session, creating a home directory. LDAP handles one piece of that. PAM handles the rest.</p>
<p>More precisely: LDAP doesn&#8217;t know what a Linux session is. It doesn&#8217;t know about <code class="" data-line="">/etc/pam.d/</code>. It doesn&#8217;t enforce login hours, account expiry, or concurrent session limits. It returns directory entries and verifies binds. The intelligence about what to do with those results lives in the Linux authentication stack.</p>
<p>When you run <code class="" data-line="">ssh vamshi@server</code>, the OS doesn&#8217;t open an LDAP connection and ask &#8220;can this user log in?&#8221; It calls PAM. PAM consults its configuration, and PAM decides whether to call LDAP (directly or via SSSD), whether to check the shadow file, whether to enforce MFA. LDAP is one possible backend. It&#8217;s not the gatekeeper.</p>
<hr />
<h2 id="nss-the-traffic-controller">NSS: The Traffic Controller</h2>
<p>Before PAM runs, Linux needs to know if the user exists at all. That&#8217;s NSS&#8217;s job.</p>
<p><code class="" data-line="">/etc/nsswitch.conf</code> is a routing table for name resolution. It tells the OS where to look when something asks &#8220;who is UID 1001?&#8221; or &#8220;what groups is vamshi in?&#8221;:</p>
<pre><code class="" data-line=""># /etc/nsswitch.conf

passwd:     files sss        ← user lookups: check /etc/passwd first, then SSSD
group:      files sss        ← group lookups: check /etc/group first, then SSSD
shadow:     files sss        ← shadow password lookups
hosts:      files dns        ← hostname lookups (not identity-related)
netgroup:   sss              ← NIS netgroups from SSSD only
automount:  sss              ← autofs maps from SSSD
</code></pre>
<p>Every call to <code class="" data-line="">getpwnam()</code>, <code class="" data-line="">getpwuid()</code>, <code class="" data-line="">getgrnam()</code>, <code class="" data-line="">getgrgid()</code> in any process — including <code class="" data-line="">sshd</code> — goes through NSS. The entries in nsswitch.conf control which backends are tried in order.</p>
<p>With <code class="" data-line="">passwd: files sss</code>, a lookup for user <code class="" data-line="">vamshi</code>:<br />
1. Checks <code class="" data-line="">/etc/passwd</code> — not found (vamshi is a domain user, not in local files)<br />
2. Queries SSSD — SSSD checks its cache, or queries LDAP, and returns the <code class="" data-line="">posixAccount</code> attributes</p>
<p>Without the <code class="" data-line="">sss</code> entry in <code class="" data-line="">passwd:</code>, domain users don&#8217;t exist on the system — <code class="" data-line="">getent passwd vamshi</code> returns nothing, <code class="" data-line="">id vamshi</code> fails, SSH login never gets to PAM&#8217;s authentication step.</p>
<pre><code class="" data-line=""># Verify NSS is routing to SSSD correctly
getent passwd vamshi
# vamshi:*:1001:1001:Vamshi K:/home/vamshi:/bin/bash

# If this returns nothing, NSS isn&#039;t reaching SSSD
# Check: systemctl status sssd &amp;&amp; grep passwd /etc/nsswitch.conf

# See what groups the user is in (NSS group lookup)
id vamshi
# uid=1001(vamshi) gid=1001(engineers) groups=1001(engineers),1002(ops)
</code></pre>
<hr />
<h2 id="pam-the-real-gatekeeper">PAM: The Real Gatekeeper</h2>
<p>PAM (Pluggable Authentication Modules) is the framework that lets Linux swap authentication backends without recompiling anything. Every service that needs to authenticate users — <code class="" data-line="">sshd</code>, <code class="" data-line="">sudo</code>, <code class="" data-line="">login</code>, <code class="" data-line="">su</code>, <code class="" data-line="">gdm</code> — has a PAM configuration file in <code class="" data-line="">/etc/pam.d/</code>.</p>
<p>Each PAM config defines four stacks:</p>
<pre><code class="" data-line="">auth        ← verify credentials (password, key, MFA)
account     ← check if the account is valid (not expired, not locked, login hours)
password    ← password change policy
session     ← set up/tear down the session (home dir, limits, logging)
</code></pre>
<p>A typical <code class="" data-line="">/etc/pam.d/sshd</code> on a system joined to AD via SSSD:</p>
<pre><code class="" data-line=""># /etc/pam.d/sshd

# auth stack — verify the user&#039;s credentials
auth    required      pam_sepermit.so
auth    substack      password-auth   ← usually includes pam_sss.so

# account stack — check account validity
account required      pam_nologin.so
account include       password-auth

# password stack — handle password changes
password include      password-auth

# session stack — set up the session
session required      pam_selinux.so close
session required      pam_loginuid.so
session optional      pam_keyinit.so force revoke
session include       password-auth
session optional      pam_motd.so
session optional      pam_mkhomedir.so skel=/etc/skel/ umask=0077
session required      pam_selinux.so open
</code></pre>
<p>The <code class="" data-line="">include</code> and <code class="" data-line="">substack</code> directives pull in shared stacks from other files (like <code class="" data-line="">/etc/pam.d/password-auth</code>). On a system with SSSD, <code class="" data-line="">password-auth</code> contains:</p>
<pre><code class="" data-line="">auth    required      pam_env.so
auth    sufficient    pam_sss.so      ← try SSSD first
auth    required      pam_deny.so     ← if pam_sss fails, deny

account required      pam_unix.so
account sufficient    pam_localuser.so
account sufficient    pam_sss.so      ← SSSD account check
account required      pam_permit.so

session optional      pam_sss.so      ← SSSD session tracking
</code></pre>
<p>The <code class="" data-line="">sufficient</code> flag means: if this module succeeds, stop checking this stack and consider it passed. <code class="" data-line="">required</code> means: this must pass (but continue checking other modules and report failure at the end). <code class="" data-line="">requisite</code> means: if this fails, stop immediately.</p>
<hr />
<h2 id="pam-control-flags-at-a-glance">PAM Control Flags at a Glance</h2>
<pre><code class="" data-line="">required   — must succeed; failure reported after remaining modules run
requisite  — must succeed; failure reported immediately, stack stops
sufficient — if success, stop stack (ignore remaining); failure continues
optional   — result ignored unless it&#039;s the only module in the stack
</code></pre>
<p>This matters for debugging. If <code class="" data-line="">pam_sss.so</code> is <code class="" data-line="">sufficient</code> and SSSD is down, PAM falls through to <code class="" data-line="">pam_deny.so</code> — login denied. If it were <code class="" data-line="">optional</code>, the login would proceed to the next module. The control flag is the policy decision.</p>
<hr />
<h2 id="the-old-way-pam_ldap">The Old Way: pam_ldap</h2>
<p>Before SSSD, Linux systems used <code class="" data-line="">pam_ldap</code> and <code class="" data-line="">nss_ldap</code> directly:</p>
<pre><code class="" data-line=""># Old /etc/pam.d/common-auth (Ubuntu pre-SSSD era)
auth    sufficient    pam_ldap.so    ← direct LDAP connection per login
auth    required      pam_unix.so nullok_secure

# Old /etc/nsswitch.conf
passwd: files ldap    ← nss_ldap for user lookups
group:  files ldap
</code></pre>
<p><code class="" data-line="">pam_ldap</code> opened a fresh LDAP connection on every login attempt. No caching. If the LDAP server was unreachable for 3 seconds, the login hung for 3 seconds — sometimes much longer. If the LDAP server was down, all domain logins failed immediately. Previously logged-in users with active sessions were fine; new logins simply didn&#8217;t work.</p>
<p><code class="" data-line="">nss_ldap</code> had the same problem for NSS lookups: every <code class="" data-line="">getpwnam()</code> call hit the LDAP server directly. On a busy system with many processes doing user lookups, this meant hundreds of LDAP queries per second, no connection reuse, and no way to survive a brief network blip.</p>
<p>The problems were structural:<br />
&#8211; No credential caching — offline logins impossible<br />
&#8211; No connection pooling — LDAP server saw one connection per login attempt<br />
&#8211; No failover logic — one LDAP server down meant all logins down<br />
&#8211; Slow timeouts that blocked login sessions</p>
<p>SSSD was built to fix all of this.</p>
<hr />
<h2 id="the-modern-way-pam_sss-sssd">The Modern Way: pam_sss + SSSD</h2>
<p><code class="" data-line="">pam_sss</code> doesn&#8217;t talk to LDAP directly. It&#8217;s a thin client that passes authentication requests to SSSD over a Unix domain socket. SSSD manages the LDAP connection, the credential cache, and the failover logic.</p>
<pre><code class="" data-line="">sshd  →  PAM (pam_sss)  →  SSSD (Unix socket)  →  LDAP server
                                   │
                                   └── credential cache
                                       (survives brief LDAP outages)
</code></pre>
<p>When <code class="" data-line="">pam_sss</code> sends a credential to SSSD:<br />
1. SSSD checks its in-memory cache — if the credential hash matches a recent successful auth, it can satisfy the request without hitting LDAP<br />
2. If not cached (or cache expired), SSSD sends a Bind to the LDAP server<br />
3. On success, SSSD caches the result and returns success to <code class="" data-line="">pam_sss</code><br />
4. <code class="" data-line="">pam_sss</code> returns PAM_SUCCESS, and the auth stack continues</p>
<p>The credential cache is what enables offline logins. If the LDAP server is unreachable and a user has authenticated successfully within the cache TTL (default: 1 day for credentials, configurable via <code class="" data-line="">cache_credentials = True</code> in sssd.conf), SSSD satisfies the auth from cache and the login succeeds. The user never knows the LDAP server was down.</p>
<hr />
<h2 id="tracing-a-full-ssh-login">Tracing a Full SSH Login</h2>
<p>Here&#8217;s every step of an SSH login for a domain user, in order:</p>
<pre><code class="" data-line="">1.  sshd accepts the TCP connection
2.  sshd calls PAM: pam_start(&quot;sshd&quot;, &quot;vamshi&quot;, ...)

3.  PAM auth stack runs pam_sss:
      pam_sss sends credentials to SSSD via /var/lib/sss/pipes/pam

4.  SSSD auth provider:
      a. Check credential cache — miss (first login)
      b. Resolve user: NSS lookup for uid=vamshi
         → SSSD LDAP provider searches dc=corp,dc=com for (uid=vamshi)
         → Returns: uidNumber=1001, gidNumber=1001, homeDirectory=/home/vamshi
      c. Authenticate: LDAP Simple Bind as uid=vamshi,ou=engineers,dc=corp,dc=com
         → Server returns: success
      d. Cache the credential hash + POSIX attrs

5.  SSSD returns PAM_SUCCESS to pam_sss

6.  PAM account stack runs pam_sss:
      SSSD checks: account not expired, not locked, login permitted
      → PAM_ACCT_MGMT success

7.  PAM session stack:
      pam_loginuid sets /proc/self/loginuid = 1001
      pam_mkhomedir creates /home/vamshi if missing
      pam_sss opens session (records in SSSD session tracking)

8.  sshd creates the shell, sets environment:
      USER=vamshi, HOME=/home/vamshi, SHELL=/bin/bash, LOGNAME=vamshi

9.  Shell prompt appears
</code></pre>
<p>Steps 4b and 4c are the only two LDAP operations in the entire login flow: one Search to resolve the user&#8217;s attributes, one Bind to verify the password. Everything else is PAM and SSSD.</p>
<hr />
<h2 id="debugging-the-stack">Debugging the Stack</h2>
<p>When a login fails, the failure could be in any layer. Work top-down:</p>
<pre><code class="" data-line=""># 1. Does NSS resolve the user at all?
getent passwd vamshi
# If empty: NSS isn&#039;t reaching SSSD, or SSSD isn&#039;t finding the user in LDAP

# 2. Is SSSD running and healthy?
systemctl status sssd
sssctl domain-status corp.com      # shows SSSD&#039;s view of domain connectivity

# 3. What does SSSD think about the user?
sssctl user-checks vamshi          # runs auth + account checks internally
id vamshi                          # forces NSS resolution and shows group memberships

# 4. What does SSSD&#039;s log say?
journalctl -u sssd -f              # tail SSSD logs live, then attempt login

# 5. Can you reach the LDAP server at all?
ldapsearch -x -H ldap://dc.corp.com \
  -D &quot;cn=svc-ldap,ou=services,dc=corp,dc=com&quot; \
  -w &quot;password&quot; \
  -b &quot;dc=corp,dc=com&quot; \
  &quot;(uid=vamshi)&quot; dn

# 6. Force a cache flush if entries are stale
sss_cache -u vamshi                # invalidate this user&#039;s cache entry
sss_cache -G engineers             # invalidate a group
</code></pre>
<p>The <code class="" data-line="">sssctl user-checks</code> command is the single most useful diagnostic — it simulates the full PAM auth + account check flow without actually creating a session, and prints exactly what SSSD would do on a real login attempt.</p>
<hr />
<h2 id="common-misconceptions"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Common Misconceptions</h2>
<p><strong>&#8220;If ldapsearch works, SSH login should work.&#8221;</strong> Not necessarily. <code class="" data-line="">ldapsearch</code> tests the LDAP layer. An SSH login requires NSS to resolve the user, PAM to authenticate, SSSD to be running and configured correctly, and <code class="" data-line="">pam_mkhomedir</code> to create the home directory if it&#8217;s the first login. Any of these can fail independently.</p>
<p><strong>&#8220;pam_ldap and pam_sss do the same thing.&#8221;</strong> They have the same job (authenticate via LDAP) but completely different architectures. <code class="" data-line="">pam_ldap</code> is a direct-connect, no-cache module. <code class="" data-line="">pam_sss</code> is a client of SSSD, which provides caching, connection pooling, failover, and offline support. On any modern system, you want <code class="" data-line="">pam_sss</code>.</p>
<p><strong>&#8220;nsswitch.conf order doesn&#8217;t matter much.&#8221;</strong> It matters exactly as much as the order suggests. <code class="" data-line="">passwd: files sss</code> means local <code class="" data-line="">/etc/passwd</code> is always checked first — if a domain username collides with a local user, the local account wins. This is the intended behavior (local accounts should always be reachable), but it means you&#8217;ll never override a local account with a directory entry.</p>
<p><strong>&#8220;SSSD cache = security risk.&#8221;</strong> The cache stores a credential hash, not the cleartext password. An attacker with access to the SSSD cache database (<code class="" data-line="">/var/lib/sss/db/</code>) would see hashed credentials — the same situation as <code class="" data-line="">/etc/shadow</code>. The real concern is whether offline authentication is appropriate for your security posture; it can be disabled with <code class="" data-line="">offline_credentials_expiration = 0</code>.</p>
<hr />
<h2 id="framework-alignment">Framework Alignment</h2>
<table>
<thead>
<tr>
<th>Domain</th>
<th>Relevance</th>
</tr>
</thead>
<tbody>
<tr>
<td>CISSP Domain 5: Identity and Access Management</td>
<td>PAM is the enforcement layer for authentication policy on Linux — understanding its stack is foundational to any Linux IAM deployment</td>
</tr>
<tr>
<td>CISSP Domain 3: Security Architecture and Engineering</td>
<td>The separation between NSS (resolution) and PAM (authentication) is an architectural boundary — misunderstanding it leads to misconfigured systems where account checks are bypassed</td>
</tr>
<tr>
<td>CISSP Domain 4: Communications and Network Security</td>
<td>pam_ldap vs pam_sss affects whether credentials travel over a direct LDAP connection (one socket per login, no TLS guarantee) or through SSSD&#8217;s managed, pooled connection</td>
</tr>
</tbody>
</table>
<hr />
<h2 id="key-takeaways">Key Takeaways</h2>
<ul>
<li>LDAP alone is not an authentication protocol for Linux — authentication flows through PAM, and LDAP is one of PAM&#8217;s possible backends</li>
<li>NSS (<code class="" data-line="">/etc/nsswitch.conf</code>) resolves user identity (who is UID 1001?); PAM enforces it (are they allowed in?)</li>
<li><code class="" data-line="">pam_ldap</code> talks to LDAP directly — no cache, no failover, login blocked when LDAP is unreachable</li>
<li><code class="" data-line="">pam_sss</code> delegates to SSSD — credential caching, connection pooling, offline login, and failover are all built in</li>
<li>A full SSH login touches LDAP exactly twice: one Search for POSIX attributes, one Bind to verify the password</li>
<li>When login fails, debug top-down: NSS resolution → SSSD status → LDAP reachability → PAM config</li>
</ul>
<hr />
<h2 id="whats-next">What&#8217;s Next</h2>
<p>EP03 showed how authentication reaches LDAP — through PAM, through SSSD, through a Bind. What it assumed is that SSSD is healthy and the LDAP server is reachable. The moment either goes wrong, the behavior depends entirely on how SSSD is configured — its cache TTLs, its failover order, its offline credential policy.</p>
<p>EP04 goes inside SSSD: the architecture, the sssd.conf knobs that matter, how to read the logs, and how to break it intentionally and fix it.</p>
<p><em>Next: <a href="/sssd-linux-authentication/">SSSD: The Caching Daemon That Powers Every Enterprise Linux Login</a></em></p>
<p>Get EP04 in your inbox when it publishes → <a href="https://linuxcent.com/subscribe">linuxcent.com/subscribe</a></p>
<p><a class="a2a_button_mastodon" href="https://www.addtoany.com/add_to/mastodon?linkurl=https%3A%2F%2Flinuxcent.com%2Fldap-authentication-linux-pam-nss%2F&amp;linkname=How%20LDAP%20Authentication%20Works%20on%20Linux%3A%20PAM%2C%20NSS%2C%20and%20the%20Login%20Stack" title="Mastodon" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Flinuxcent.com%2Fldap-authentication-linux-pam-nss%2F&amp;linkname=How%20LDAP%20Authentication%20Works%20on%20Linux%3A%20PAM%2C%20NSS%2C%20and%20the%20Login%20Stack" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Flinuxcent.com%2Fldap-authentication-linux-pam-nss%2F&amp;linkname=How%20LDAP%20Authentication%20Works%20on%20Linux%3A%20PAM%2C%20NSS%2C%20and%20the%20Login%20Stack" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_reddit" href="https://www.addtoany.com/add_to/reddit?linkurl=https%3A%2F%2Flinuxcent.com%2Fldap-authentication-linux-pam-nss%2F&amp;linkname=How%20LDAP%20Authentication%20Works%20on%20Linux%3A%20PAM%2C%20NSS%2C%20and%20the%20Login%20Stack" title="Reddit" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_x" href="https://www.addtoany.com/add_to/x?linkurl=https%3A%2F%2Flinuxcent.com%2Fldap-authentication-linux-pam-nss%2F&amp;linkname=How%20LDAP%20Authentication%20Works%20on%20Linux%3A%20PAM%2C%20NSS%2C%20and%20the%20Login%20Stack" title="X" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Flinuxcent.com%2Fldap-authentication-linux-pam-nss%2F&amp;linkname=How%20LDAP%20Authentication%20Works%20on%20Linux%3A%20PAM%2C%20NSS%2C%20and%20the%20Login%20Stack" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_copy_link" href="https://www.addtoany.com/add_to/copy_link?linkurl=https%3A%2F%2Flinuxcent.com%2Fldap-authentication-linux-pam-nss%2F&amp;linkname=How%20LDAP%20Authentication%20Works%20on%20Linux%3A%20PAM%2C%20NSS%2C%20and%20the%20Login%20Stack" title="Copy Link" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Flinuxcent.com%2Fldap-authentication-linux-pam-nss%2F&#038;title=How%20LDAP%20Authentication%20Works%20on%20Linux%3A%20PAM%2C%20NSS%2C%20and%20the%20Login%20Stack" data-a2a-url="https://linuxcent.com/ldap-authentication-linux-pam-nss/" data-a2a-title="How LDAP Authentication Works on Linux: PAM, NSS, and the Login Stack"></a></p><p>The post <a href="https://linuxcent.com/ldap-authentication-linux-pam-nss/">How LDAP Authentication Works on Linux: PAM, NSS, and the Login Stack</a> appeared first on <a href="https://linuxcent.com">Linuxcent</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://linuxcent.com/ldap-authentication-linux-pam-nss/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1777</post-id>	</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: linuxcent.com @ 2026-09-01 04:43:29 by W3 Total Cache
-->