LDAPS Fails After the Domain Controller Certificate Expires
LDAPS binds that worked for months start failing the moment a domain controller’s Server Authentication certificate crosses its expiration date, and the fix depends entirely on whether autoenrollment quietly stopped renewing it or a new certificate is already sitting there unused because Schannel cached the old one.
The security support provider that negotiates TLS for LDAPS on port 636 and caches whichever certificate it loaded at startup.
The certificate store AD DS checks first, ahead of the Local Computer\Personal store, when it looks for an LDAPS certificate.
The GPO-driven mechanism that is supposed to renew a domain controller’s certificate before this ever becomes a problem.
Introduction
A domain controller’s LDAPS certificate has a lifetime like any other certificate, and for a long stretch of that lifetime nobody thinks about it at all. Then one day, with no change deployed, no patch installed, and no configuration touched, LDAPS binds start failing across the environment. The common thread is a date on a calendar: the certificate’s NotAfter value quietly passed, and nothing renewed it in time.
This is rarely a one-off. If autoenrollment is broken for one domain controller’s certificate, it is often broken the same way for every domain controller enrolled from the same template, which is why this tends to surface as a cluster of failures rather than a single server going dark.
What the Error Looks Like
On the client side – anything binding to port 636, from ldp.exe to an application’s LDAP library – the System event log records a Schannel error the moment the TLS handshake rejects the expired certificate:
Log Name: System
Source: Schannel
Event ID: 36881
Level: Error
Description:
The certificate received from the remote server has expired.
The SSL connection request has failed. The attached data contains the server certificate.
On the domain controller itself, if the certificate has expired badly enough that Schannel has nothing valid left to offer at all, two companion events show up instead:
Log Name: System
Source: Schannel
Event ID: 36886
Level: Error
Description:
No suitable default server credential exists on this system. This will prevent
server applications that expect to make use of the system default credentials
from accepting SSL connections. An example of such an application is the
directory server.
Log Name: Directory Service
Source: Microsoft-Windows-ActiveDirectory_DomainService
Event ID: 1220
Level: Error
Description:
LDAP over Secure Sockets Layer (SSL) will be unavailable at this time because
the server was unable to obtain a certificate.
What It Actually Means
LDAPS has no separate configuration switch to turn on. Any domain controller with a valid Server Authentication certificate sitting in its NTDS\Personal store, or failing that its Local Computer\Personal store, automatically starts accepting SSL connections on 636 and the global catalog on 3269. The certificate has to satisfy a specific set of conditions: the domain controller’s FQDN in the Subject CN or a Subject Alternative Name entry, the Server Authentication EKU (1.3.6.1.5.5.7.3.1), a matching private key present on the machine, and a chain the clients trust. Once issued, that certificate is only valid until its expiration date – there is nothing that extends it automatically except whatever renewal process was supposed to replace it before that date arrived.
In most enterprise environments that renewal process is autoenrollment: a GPO-driven Certificate Services Client policy that watches enrolled certificates and requests a replacement before expiry. When it works, nobody notices a domain controller certificate ever expiring. When it silently stops – a GPO link removed, the enterprise CA unreachable at the moment the renewal window opened, a template permission change – the certificate keeps counting down toward its NotAfter date with nothing watching it.
There is a second, less obvious way this shows up even after the certificate has been renewed. Schannel loads a certificate once and caches it for the life of the process. If a new, valid certificate replaces the old one – through renewal or a CA change – Schannel keeps using the cached, now-expired certificate until something tells it to reload. That specific trap has its own event:
Log Name: System
Source: Schannel
Event ID: 36876
Level: Error
Description:
The certificate received from the remote server has not validated correctly.
The error code is 0x80090328. The SSL connection request has failed.
The attached data contains the server certificate.
How to Diagnose
Start by confirming the certificate is actually the problem, then work out why it was not renewed or reloaded in time.
# 1. Confirm expiry and basic health of every DC's LDAPS certificate for the domain
# (requires Domain Admins or Enterprise Admins)
certutil -dcinfo corp.example.com Verify
# 2. List certificates in the Local Computer Personal store on the DC and check NotAfter
Get-ChildItem Cert:\LocalMachine\My | Select-Object Subject, NotAfter, Thumbprint
# 3. Confirm the private key is present and usable for the candidate certificate
certutil -verifykeys
# 4. Check whether the certificate chain itself validates
certutil -verifystore My
# 5. Check the System event log for the Schannel/Directory Service events above
Get-WinEvent -LogName System | Where-Object { $_.Id -in 36876,36881,36886 } |
Select-Object -First 10 TimeCreated, Id, Message
Get-WinEvent -LogName "Directory Service" | Where-Object { $_.Id -eq 1220 } |
Select-Object -First 5 TimeCreated, Id, Message
# 6. Confirm from the DC itself that LDAPS actually answers on 636
ldp.exe
# Connection > Connect, host = dc01.corp.example.com, port = 636, SSL checked
certutil -dcinfo before touching anything else. It reports every domain controller’s certificate status in one pass, so you find out immediately whether this is a single DC or a whole autoenrollment cohort.
Common Causes
| Cause | How to Confirm | Fix |
|---|---|---|
| Autoenrollment GPO never ran or was unlinked | Certificate’s NotAfter has passed and no newer certificate for the same template exists in the store. |
Confirm the Certificate Services Client – Auto-Enrollment policy is linked and enabled, then force it with gpupdate /force followed by certutil -pulse. |
| A new certificate was issued, but Schannel is still using the cached, expired one | Event 36876 (error 0x80090328) appears even though a valid, unexpired certificate is visible in the store. |
Trigger the renewServerCertificate rootDSE operation, or restart the domain controller if that is not practical right now. |
| Multiple certificates in the store, Schannel picked the wrong one | Get-ChildItem Cert:\LocalMachine\My shows more than one certificate with the Server Authentication EKU. |
Remove the expired/invalid duplicate, or move the intended certificate into the NTDS service’s own Personal store, which AD DS checks first. |
| Certificate expired and no CA was reachable to renew it | Autoenrollment event log (Application and Services Logs > Microsoft > Windows > CertificateServicesClient-CertEnroll) shows enrollment failures around the expiry date. | Confirm the issuing CA is online and reachable, then re-trigger enrollment; if no CA exists, use certreq to request and accept a certificate manually. |
| Private key not accessible (strong private key protection, ACL, or profile issue) | certutil -verifykeys reports the key as missing or inaccessible even though the certificate itself is present. |
Re-issue the certificate without strong private key protection enabled, and confirm the machine key store permissions have not been altered. |
| Certificate name mismatch, not expiration (a different, look-alike failure) | Event 36884 – “does not contain the expected name” – appears instead of 36881; the certificate itself is still within its validity period. | Not the same issue as this post covers: add the missing SAN entry or fix the DNS alias resolution instead of renewing a certificate that has not actually expired. |
Working Through a Fix
First confirm whether this is a renewal failure or a reload failure – the fix is different for each, and applying the wrong one wastes a maintenance window.
If certutil -dcinfo and Get-ChildItem Cert:\LocalMachine\My agree that no current, valid certificate exists at all, the renewal itself did not happen. Confirm the autoenrollment GPO first:
# Confirm the Auto-Enrollment policy is applied to the DC
gpresult /r /scope:computer
# Force a Group Policy refresh, then ask the client to
# immediately re-evaluate autoenrollment rather than waiting
# for its normal cycle
gpupdate /force
certutil -pulse
certutil -pulse with no arguments defaults to the autoenrollment event. Run it right after gpupdate /force so the machine re-evaluates enrollment immediately instead of on its normal interval.
If the enterprise CA is unreachable or autoenrollment is not configured for this template at all, request the certificate manually instead:
# request.inf - replace <DC fqdn> with the domain controller's FQDN
[Version]
Signature="$Windows NT$"
[NewRequest]
Subject = "CN=<DC fqdn>"
KeySpec = 1
KeyLength = 2048
Exportable = TRUE
MachineKeySet = TRUE
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
RequestType = PKCS10
KeyUsage = 0xa0
[EnhancedKeyUsageExtension]
OID=1.3.6.1.5.5.7.3.1 ; Server Authentication
# Build the request, submit it to the CA, then accept the issued certificate
certreq -new request.inf request.req
certreq -accept certnew.cer
Once a valid, unexpired certificate is confirmed present, verify the chain and key before assuming the fix is complete:
certutil -verifystore My
certutil -verifykeys
If a valid certificate is already sitting in the store and the failures persist, this is the caching case (event 36876), not a missing-certificate case. Trigger a reload without a full reboot using the renewServerCertificate rootDSE operation through ldifde, or restart the domain controller if that is simpler for this environment:
# renew.ldf
dn:
changetype: modify
add: renewServerCertificate
renewServerCertificate: 1
-
ldifde -i -f renew.ldf
dn: line is left blank because renewServerCertificate is a rootDSE attribute, not an attribute of a normal directory object – it does not take a distinguished name.
Confirm the fix from the domain controller itself with ldp.exe: Connect using port 636 with SSL checked, then Bind. A successful bind that returns the connecting user and domain name confirms LDAPS is functioning again.
How to Prevent It
Treat domain controller certificate expiry as a monitored date, not a background assumption. Autoenrollment removes the manual work of renewal, but nothing in the default configuration tells anyone it stopped working – build that visibility in deliberately, whether through a scheduled script checking NotAfter against a threshold, or a monitoring system that already tracks certificate expiry across the environment.
Confirm the Certificate Services Client – Auto-Enrollment policy is linked at the Domain Controllers OU (or wherever domain controller computer objects actually live) with both “Renew expired certificates, update pending certificates, and remove revoked certificates” and “Update certificates that use certificate templates” checked. After any CA maintenance, certificate template change, or GPO reorganisation that touches domain controllers, re-run certutil -dcinfo across the domain as a sanity check rather than waiting for the next expiry date to prove it either way.
Quick Reference
| Command / Event | Use |
|---|---|
| Event 36881 (Schannel, client) | The certificate the DC presented has expired. |
| Event 36886 (Schannel) / 1220 (Directory Service) | The domain controller has no usable LDAPS certificate at all. |
Event 36876 (Schannel, error 0x80090328) | A valid certificate exists but Schannel is still using a cached, expired one. |
certutil -dcinfo <domain> Verify | Report every domain controller’s LDAPS certificate status in one pass. |
certutil -verifykeys / -verifystore My | Confirm the private key and certificate chain are both usable. |
certutil -pulse | Force immediate autoenrollment re-evaluation instead of waiting for the normal cycle. |
renewServerCertificate (via ldifde) | Force Schannel to reload the LDAPS certificate without a restart. |
ldp.exe Connect/Bind on port 636 | Confirm LDAPS is actually accepting and authenticating connections again. |
Final Thoughts
An expired LDAPS certificate is not a mysterious failure – it is a certificate lifecycle problem wearing an SSL error message. The domain controller behaves exactly as designed: no valid Server Authentication certificate, no LDAPS. The actual work is finding out why the renewal that should have prevented this never happened, and confirming whether Schannel just needs to notice the fix that already exists.
Autoenrollment is reliable enough that most environments never think about domain controller certificates again once it is configured correctly – which is exactly why nobody notices the day it quietly stops.
certutil -dcinfo <domain> Verify first. If it shows an expired certificate with nothing newer behind it, this is an autoenrollment failure – fix the GPO and force enrollment. If a valid certificate already exists, this is a Schannel caching issue – reload it with renewServerCertificate or a restart instead of re-issuing anything.
If LDAPS itself is fine but binds are failing for a different reason, check whether LDAP signing and channel binding enforcement is the actual cause – it produces failures that look similar at first glance but have nothing to do with certificate expiry.