Helpdesk: "Since about 7:30 this morning the 802.1X Wi-Fi rejects every laptop, the VPN says the certificate couldn't be validated, and the issuing CA service won't start. Its error says the revocation function was unable to check revocation because the revocation server was offline, 0x80092013. The PKI admin is out; the offline root has been powered off in a closet since spring. A forum post says to set CRLF_REVCHECK_IGNORE_OFFLINE on the CA, set NoRevocationCheck on both NPS servers, and turn off revocation checking in the VPN profile. Can we start with that?"

Not yet. "Revocation server offline" almost never means a server is down. It means a client building a certificate chain couldn't get a current CRL for one of the certificates in it: the CRL expired, the CDP URL can't be reached from that client's network or security context, the URL was never published, or the client is still using a stale cached copy. Microsoft's DirectAccess article for 0x80092013 lists those four causes word for word, starting with "The CRL location (CDP) is unreachable." and ending with "The CRL is reachable but the client is picking from an old cache." Its chain-validation note explains the blast radius: "Revocation checking is performed from the root CA certificate down to the evaluated certificate." One expired root CRL breaks every certificate under it, and Wi-Fi, VPN, and the CA itself fail together. Turning off revocation checking hides the failed link and leaves it failed, and a CRL that's still expired tomorrow breaks the next app nobody exempted. Work through it as a chain: which app, which error code, which certificate, which context, since when → certutil -verify -urlfetch on that certificate, from the failing machine → which CRL failed: issuing, root, or delta, and its NextUpdate → can this client, in this context, reach the CDP URL? → does the web or LDAP location serve the current file? → CAPI2 events, which name the exact action that failed → caches → the CA: publication events, schedule, and CDP settings → the offline root's CRL → what each relying party does with an unknown result. certutil, Get-WinEvent, wevtutil, Invoke-WebRequest, Test-NetConnection, Get-CACrlDistributionPoint, and Get-ItemProperty are the sources for that chain. Set the ignore flags everywhere, and you'll be turning them back off one app at a time, with the CRL still expired.

If certificates aren't arriving at all, start with Certificate Autoenrollment Not Working; its Step 9 is where this post picks up. If the failure is a Wi-Fi profile on Intune-managed devices, Intune Wi-Fi Profile Not Applying covers the profile side. This post covers "Windows clients, servers, or the CA itself fail to validate certificates from an AD CS hierarchy with 'the revocation server was offline' (0x80092013) or 'unable to check revocation' (0x80092012), and you need a read-first path before you turn off revocation checking, set ignore-offline flags, or republish over the top."

TL;DR

  • Read the chain before you touch the CA. certutil -verify -urlfetch on the failing certificate fetches every AIA and CDP URL in the chain and shows which one failed (Step 2). Microsoft's autoenrollment blog: "Verify that all certification authorities in the chain have valid CRL's published."
  • Check NextUpdate on every CRL in the chain. Microsoft's CAPI2 guide: "If the current date is later than the date in the nextUpdate field in the CRL, it means that the CRL has expired." The offline root's CRL is the usual suspect, because nothing publishes it on a schedule (Steps 3, 9).
  • Test from the context that fails. Microsoft's 0x80092013 article says to "verify that the CRL is downloadable from the system context". Services run as SYSTEM with WinHTTP proxy settings, not yours (Step 4).
  • Publishing isn't delivering. Microsoft: certutil -CRL "writes new CRL data according to the CA configuration; it doesn't prove that a web server, replication process, or external transfer makes the new files available." (Step 5).
  • A fixed CRL can still fail from cache. Microsoft's fix for the old-cache cause is certutil -setreg chain\ChainCacheResyncFiletime @now and certutil -urlcache * delete (Steps 7, 11).
  • Ignore-offline flags are a stopgap with an owner and an end date, not a fix. The CA flag, the NPS keys, and the curl and Git switches all weaken validation (Step 10, common false starts).

Where in the chain did it break?

Step What should be true Typical symptom when it breaks
1. Symptom captured Which app, error code, certificate, context, network, since when "Certificates are broken" with no certificate exported
2. Chain read certutil -verify -urlfetch run on the failing certificate, in the failing context Only the admin's browser was tested
3. CRL time-valid Every CRL in the chain is before its NextUpdate Root CRL expired over a weekend
4. CDP reachable The client can resolve and reach the first usable CDP URL as the identity that validates Works for the admin, fails as SYSTEM or over VPN
5. Location current HTTP and LDAP locations serve the CRL the CA last generated CA has a new CRL; the web server has last month's
6. CAPI2 read The failing action is named "Offline" with no detail
7. Caches The client uses the current CRL, not a cached old one Fixed on the server, still failing on clients
8. CA side CRLs publish on schedule to every location; CDP settings match what certificates carry Events 65/74 nobody reads; CDP URL changed last year
9. Offline root The root's CRL was renewed and distributed before NextUpdate The root has been off since its last CRL
10. Relying parties Each app's revocation policy is known and unchanged NPS keys flipped during the last outage and never flipped back
11. Change Only after Steps 1-10 agree: one link, one change Ignore flags everywhere, same expired CRL

Step 1: Capture the symptom (read-only)

Write these on the ticket first:

Fact Why it matters
Which app, and its exact error 0x80092013 and 0x80092012 are different results (table below); app wording varies, the code doesn't
Which certificate Export it (public part only, .cer) from the app's server, the client's store, or the CA. Step 2 needs the file
Which context validates it A service, NPS, the CA service, and scheduled tasks validate as SYSTEM or a service account; a browser validates as the user (our reading)
Which network LAN, VPN, Wi-Fi onboarding VLAN, internet. A CDP reachable from one isn't proof for another
Since when, and what changed A date matching a CRL's NextUpdate is the strongest lead; also CA renewal, web server or DNS change, proxy change, firewall change

The codes, each from Microsoft's Winerror.h page:

Code Name Microsoft's text Usually points at (our reading unless noted)
0x80092013 CRYPT_E_REVOCATION_OFFLINE "The revocation function was unable to check revocation because the revocation server was offline." A CRL that couldn't be retrieved or isn't valid (Steps 3-7)
0x80092012 CRYPT_E_NO_REVOCATION_CHECK "The revocation function was unable to check revocation for the certificate." No usable revocation information at all, often no CDP; common from curl and Git on Windows (Step 10)
0x80092010 CRYPT_E_REVOKED "The certificate is revoked." Revocation worked: the certificate is revoked. Don't clear caches to make it go away
0x80090358 SEC_E_REVOCATION_OFFLINE_KDC "The revocation status of the domain controller certificate used for smartcard authentication could not be determined." Smart card or certificate logon: the DC certificate's CRL (Step 10)

Then branch on what you see:

What you see What it usually means (our reading unless noted) Start at
Everything certificate-based failed at the same time One CRL high in the chain expired, usually the root's Steps 2, 3, 9
CA service won't start, Event 100 or 48 The CA can't check its own chain: usually the parent CA's CRL (Microsoft's Event 100 page) Steps 8, 9
Works on the LAN, fails over VPN or the internet The CDP URL is internal-only, or LDAP-only Step 4
Works for you, fails for the service SYSTEM proxy, or a CDP that needs authentication Step 4
Fails right after a CRL was republished Stale web copy, or cached old CRL Steps 5, 7
Base CRL fine, delta fails Delta not served (IIS double escaping), or not published Step 5
Pages slow, no error Revocation fetches timing out (SharePoint's 15-second example) Steps 4, 10

Step 2: Read the chain with certutil -verify -urlfetch (read-only)

This is the one test that answers most of the questions at once. Microsoft's autoenrollment blog: "The client does not have a valid certificate revocation list (CRL) from the issuing CA that it can use to check if a certificate has been revoked." Its test is to run certutil -v -verify -urlfetch against the issuing CA's certificate. Microsoft's CDP article uses the same test for any certificate: "From each representative network zone, validate the test certificate and retrieve its revocation data". Run it on the certificate that fails, on the machine that fails:

:: Read-only (writes one local file). Verify the chain and fetch every AIA and CDP URL in it (file names are examples) certutil -v -verify -urlfetch C:\Temp\failing.cer > C:\Temp\verify-failing.txt  :: Read-only (writes one local file). The issuing CA's own certificate, from the CA (config string is an example) certutil -config "CA01.contoso.com\Contoso Issuing CA" -ca.cert C:\Temp\issuing-ca.cer certutil -verify -urlfetch C:\Temp\issuing-ca.cer 

Microsoft's description of -verify: "Verifies a certificate, certificate revocation list (CRL), or certificate chain." Microsoft's caution on running it: "it will use the security and proxy settings of the user that runs it". An admin session that passes doesn't clear the SYSTEM account; Step 4 has the SYSTEM form.

How to read the output (structure from the sample output a user posted on Microsoft Q&A, community; status wording is our reading):

Part of the output What it tells you
One CertContext[0][n] block per certificate [0][0] is the certificate you passed; the last one is the root
Certificate AIA / Certificate CDP under each block Each URL that block's certificate points at, with a status. Verified is good; anything else is the lead
Base CRL CDP Where the CRL says its delta CRL lives (empty if the CA doesn't publish deltas)
CRL nn: with ThisUpdate / NextUpdate The CRL that was used, and when it stops being valid
The last lines A pass shows a completed message; a failure names the error code (our reading)
# Read-only. Pull the lines that matter out of the saved output (pattern list is ours) Select-String -Path C:\Temp\verify-failing.txt -Pattern 'CertContext|CDP|CRL \d|ThisUpdate|NextUpdate|Verified|Expired|Failed|0x8009' | Select-Object LineNumber, Line 
Finding What it means (our reading unless noted) Next
The root's block shows no CDP Normal. Microsoft's CAPI2 guide: a CDP is necessary "for any certificate except for a root CA certificate" The next block down
The issuing CA's block: CDP URL not Verified The root's CRL (it covers the issuing CA's certificate) is expired or unreachable Steps 3, 9
The leaf's block: CDP URL not Verified The issuing CA's CRL is expired or unreachable Steps 3-5
NextUpdate in the past on any CRL Expired. Republish it (Step 11) Step 3
First CDP URL fails, a later one is Verified Validation can still pass, but slowly; Microsoft says Windows clients try them in order Step 4
Passes for you, fails in the app Different context, proxy, or network Step 4
A block with no CDP and no OCSP that isn't the root Nothing to check against: 0x80092012 territory Step 8: the CA's CDP settings

Step 3: Which CRL, and is it still time-valid? (read-only)

Every CA in the chain except the root's own certificate needs a current CRL: the root's CRL covers the issuing CA's certificate, and the issuing CA's CRL covers the leaf. Microsoft's CAPI2 guide on what expired looks like: "If the current date is later than the date in the nextUpdate field in the CRL, it means that the CRL has expired." Its fix is one line: "To fix this error, publish a time-valid CRL on the server."

Read the CRLs the clients actually download, not only the CA's copy. Take the HTTP URL from Step 2's output:

# Read-only (writes local files). Download each CRL from its HTTP CDP and read its validity (URLs are examples) $crls = @{ 'issuing' = 'http://pki.contoso.com/pki/ContosoIssuingCA.crl' 'root' = 'http://pki.contoso.com/pki/ContosoRootCA.crl' } foreach ($name in $crls.Keys) { Invoke-WebRequest -Uri $crls[$name] -OutFile "C:\Temp\$name.crl" -UseBasicParsing "== $name" certutil -dump "C:\Temp\$name.crl" | Select-String -Pattern 'ThisUpdate|NextUpdate' } 

certutil -dump "Dumps the configuration information or files." certutil -URL opens the same check interactively: it "Verifies certificate or CRL URLs." On the CA, read what the CA itself generated and what it thinks it published:

# Read-only. On the CA: the CRL files the CA writes locally (default CertEnroll path) and their timestamps Get-ChildItem -Path "$env:SystemRoot\System32\CertSrv\CertEnroll" -Filter *.crl | Select-Object Name, Length, LastWriteTime 
:: Read-only. On the CA: base and delta CRL publish status, then the CRL schedule values (Name* is certutil's prefix match) certutil -CAInfo crlstatus certutil -CAInfo deltacrlstatus certutil -getreg ca\CRLPeriod* certutil -getreg ca\CRLOverlap* certutil -getreg ca\CRLDelta* 

certutil -CAInfo lists crlstatus as "CRL Publish Status" and deltacrlstatus as "Delta CRL Publish Status". The CRL period is how long each CRL is valid; the overlap is the head start clients get. Microsoft's two-tier PKI lab guide: "The overlap period for CRLs is the amount of time at the end of a published CRLs lifetime that a client can use to obtain a new CRL before the old CRL is considered unusable". And: "The default setting for this value is 10% of the CRL lifetime." Microsoft's CDP article keeps the two ideas apart: "A publishing interval and a CRL validity period are different settings."

LDAP CDPs live in AD. Read when each CDP object last changed (our form; whenChanged moves when a CRL is written there, our reading):

# Read-only. CRL distribution point objects in the configuration partition and when each last changed $config = (Get-ADRootDSE).configurationNamingContext Get-ADObject -SearchBase "CN=CDP,CN=Public Key Services,CN=Services,$config" `  -Filter "objectClass -eq 'cRLDistributionPoint'" -Properties whenChanged | Select-Object DistinguishedName, whenChanged | Sort-Object whenChanged 

certutil -dsCRL "Displays DS CRLs." Add -config to point it at one CA (our reading of its options).

Finding What it means (our reading unless noted) Next
Root CRL past NextUpdate Nobody renewed the offline root's CRL Step 9
Issuing CRL past NextUpdate, CA running The CA isn't publishing, or publishes somewhere clients don't read Steps 5, 8
CertEnroll copy current, HTTP copy old Publication worked, delivery didn't Step 5
HTTP copy current, LDAP object old LDAP publication failing (Events 65/74) Step 8
All current, still failing Reachability, context, or cache Steps 4, 7
Overlap of zero or a few minutes Clients get no head start; any delay becomes an outage Step 11

Step 4: Can this client, in this context, reach the CDP? (read-only)

Microsoft's 0x80092013 article lists five reasons a CRL location is unreachable, including "System context proxy is applied but unreachable and requires user authentication." and "CRL Location requires authentication before access is granted." Microsoft's CDP article puts the test plainly: "Test the exact CDP URL from that client network."

Name and port first, from the failing machine:

# Read-only. The CDP host from Step 2: DNS answer, then TCP 80 (host name is an example) $cdpHost = 'pki.contoso.com' Resolve-DnsName -Name $cdpHost Test-NetConnection -ComputerName $cdpHost -Port 80 -WarningAction SilentlyContinue | Select-Object ComputerName, RemoteAddress, TcpTestSucceeded 

Then the context. Services don't use your browser's proxy. Read the machine's WinHTTP proxy and the two hives Microsoft's article checks for the system context:

:: Read-only. WinHTTP proxy (what many services use), then the proxy values Microsoft's 0x80092013 article reads netsh winhttp show proxy reg query "HKU\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable reg query "HKU\S-1-5-18\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer reg query "HKU\S-1-5-18\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v AutoConfigURL 

Then repeat Step 2 as SYSTEM. Sysinternals PsExec's -s switch will "Run the remote process in the System account." Run locally, it does the same on this machine (our reading):

:: Read-only (writes one local file). Step 2's test as SYSTEM on the failing machine psexec -s cmd /c "certutil -verify -urlfetch C:\Temp\failing.cer > C:\Temp\verify-system.txt" 

Then the URL list. Microsoft's PKI design page: "Remember that Windows clients always retrieve the list of URLs in sequential order until a valid CRL is retrieved." An LDAP URL first in the list costs a non-domain or off-network client a timeout before it reaches HTTP. The same page: "Use HTTP CDP locations to provide accessible CRL locations for clients running non-Windows operating systems." For Entra joined devices, Microsoft's Windows Hello for Business guide says the same: "Publish your certificate revocation list to a location that is available to Microsoft Entra joined devices, such as a web-based URL". Microsoft's CAPI2 guide rules one scheme out: "CryptoAPI does not support the FTP protocol for network retrieval."

Finding What it means (our reading unless noted) Next
Name doesn't resolve off-LAN Internal-only DNS name in the CDP Step 11: an HTTP name every zone can resolve, for new certificates (Step 8)
TCP 80 blocked from the VPN pool Firewall rule missing for the CDP host Network change for that one host and port
Passes as you, fails as SYSTEM WinHTTP or system-context proxy Step 11: proxy bypass for the CDP host
Only LDAP URLs in the CDP Non-domain, Entra joined, and off-network clients can't use them Step 8: add HTTP for new certificates
The proxy asks for credentials SYSTEM can't answer (Microsoft's cause) Proxy exception for the CDP host

Step 5: Does the web or LDAP location serve the current file? (read-only)

The CA writing a CRL and a client getting it are separate jobs. Microsoft: "The CA's local generation result doesn't validate the delivery chain." Its monitoring advice: "At each HTTP endpoint, verify that the expected CRL file is current, complete, and readable by the intended clients." Compare the CA's file with what the web server hands out:

# Read-only. Same bytes on the CA and at the HTTP CDP? (file names are examples; C:\Temp\issuing.crl is Step 3's download) Get-FileHash -Path "$env:SystemRoot\System32\CertSrv\CertEnroll\ContosoIssuingCA.crl", 'C:\Temp\issuing.crl' -Algorithm SHA256 | Select-Object Hash, Path 

Different hashes with a current CA file means the copy job, the share, or the replication between web servers didn't run (our reading). Microsoft's lab guide grants Cert Publishers modify rights on the web server's pki folder so the CA can write there; its 0x80092013 article adds "check File System Permissions on the CRL and Delta CRL files."

Delta CRLs and IIS. A delta CRL's file name carries a +. Microsoft's lab guide: "Allowing double escaping is needed if you are publishing Delta CRLs to IIS because the Delta CRL file contains a + symbol." IIS's request filtering reference: "If set to true, request filtering will allow URLs with doubly-escaped characters." and "The default value is false." Read the setting on the CDP's site or folder:

# Read-only. On the IIS server: double escaping on the CDP folder (site and folder names are examples) Import-Module WebAdministration Get-WebConfigurationProperty -PSPath 'IIS:\Sites\Default Web Site\pki' -Filter system.webServer/security/requestFiltering -Name allowDoubleEscaping 

Microsoft's CDP article also asks for "the .crl MIME mapping required by your web-server policy" and for checking "the actual HTTP response after deployment". Step 3's Invoke-WebRequest download is that check for the base CRL; repeat it with the delta file name (the + one) from Step 2's Base CRL CDP line.

Finding What it means (our reading unless noted) Next
Hashes differ The web copy is stale Step 11: the copy or replication job
Base downloads, delta returns 404 Double escaping off, or the delta was never copied Step 11: double escaping (Microsoft's lab form)
401 or 403 from the CDP URL Anonymous read missing on the folder or site Folder permissions
CRL downloads, certutil -dump can't parse it The server returns something else (an error page, a captive portal) The response itself

Step 6: Turn on CAPI2 logging and read the action that failed (read-only, one log switch)

When -urlfetch passes and the app still fails, the CAPI2 log shows what the app's own validation did. Microsoft's CAPI2 guide on why the app's message isn't enough: the API "was designed to return an error code and string", so many network problems reach the app as revocation offline. Enable the log, make it bigger, reproduce once, export, and turn it off. Microsoft: "The default size for the event log is 1 MB." It recommends "at least 4 MB to capture relevant events".

:: Low-risk. Enable CAPI2 logging at 4 MB, reproduce the failure, export, then disable (Microsoft's wevtutil forms) wevtutil sl Microsoft-Windows-CAPI2/Operational /ms:4194304 wevtutil sl Microsoft-Windows-CAPI2/Operational /e:true :: reproduce the failure now, then: wevtutil epl Microsoft-Windows-CAPI2/Operational C:\Temp\capi2.evtx wevtutil sl Microsoft-Windows-CAPI2/Operational /e:false 
# Read-only. CAPI2 errors, then the ones whose XML names a known revocation action (action list from Microsoft's guide; the filter is ours) $capi = Get-WinEvent -LogName 'Microsoft-Windows-CAPI2/Operational' -MaxEvents 2000 -ErrorAction SilentlyContinue $capi | Where-Object Level -eq 2 | Select-Object TimeCreated, Id, TaskDisplayName | Format-Table -AutoSize $capi | Where-Object { $_.ToXml() -match 'CheckTimeValidity|CanRetrieveFromNetwork|CanCheckServerForUpdatedCrl|BadProxy|GetCrlOrOcspUrls|IsCrlSignatureValid|2EE7|2EFD' } | Select-Object TimeCreated, Id, TaskDisplayName 

Microsoft's guide names the events to open: results are in CertVerifyRevocation, and "To find the cause, you need to look at the" CertRejectedRevocationInfo and CryptRetrieveObjectByUrlWire events nested under it. In CertGetCertificateChain, the status flags CERT_TRUST_REVOCATION_STATUS_UNKNOWN plus CERT_TRUST_IS_OFFLINE_REVOCATION mean the revocation information couldn't be retrieved or was invalid. The actions, each from Microsoft's guide:

Action or code in the event Microsoft's meaning Link in the chain
CheckTimeValidity (CertRejectedRevocationInfo) The CRL is expired: now is past its nextUpdate Steps 3, 9
IsCrlSignatureValid "If the signature of the CRL cannot be verified" The CRL file at that location is wrong or corrupt (Step 5)
GetCrlOrOcspUrls No CDP and no OCSP URL in the certificate Step 8
CanRetrieveFromNetwork Back-off: "CAPI2 avoids contacting the server too often for repeated offline responses." Wait for EarliestOnlineTime, or Step 7
BadProxy (CryptRetrieveObjectByUrlWire) The proxy is wrong; usually the first in the list Step 4
2EE7 ERROR_WINHTTP_NAME_NOT_RESOLVED DNS for the CDP or proxy host
2EFD ERROR_WINHTTP_CANNOT_CONNECT The CDP host's port, or the host is down

Microsoft's summary for the network rows: "fix the underlying component (such as network, proxy settings, Web server, or LDAP) that is causing failure."

Step 7: Is the client using a cached old CRL? (read-only)

Clients keep CRLs. Microsoft's 0x80092013 article: "The CRL is retrieved by clients who can then cache the CRL (based on the configured lifetime of the CRL)". So a CRL you republished an hour ago doesn't help a client that cached the old one, and its fourth cause is exactly that: "The CRL is reachable but the client is picking from an old cache." Read the cache before you clear it:

:: Read-only. Cached CRL URLs for the current user's context (certutil's CRL filter), saved for the ticket certutil -urlcache CRL > C:\Temp\urlcache-crl.txt 

Microsoft's syntax note for -URLCache: delete "deletes relevant URLs from the current user's local cache." Run the read in the same context as the failure: as the user for a user app, and as SYSTEM (Step 4's PsExec form) for a service (our reading).

CAPI2's back-off is a second kind of cache. After repeated offline results it stops asking; the CanRetrieveFromNetwork event gives the EarliestOnlineTime it will try again (Step 6).

Finding What it means (our reading unless noted) Next
Cached CRL for the failing URL, and the server copy is newer Client still holds the old one Step 11: Microsoft's two cache commands, after the server side is fixed
No cached entry, still failing Not a cache problem Steps 4, 5
CanRetrieveFromNetwork in CAPI2 Back-off after repeated failures Fix the URL first, then Step 11

Step 8: The CA side: publication, schedule, and CDP settings (read-only)

Did the CA publish? Microsoft's AD CS event list gives the CRL publication events in the Application log:

Event Microsoft's text (event list for AD CS) Means (our reading)
48 "Revocation status for a certificate in the chain for CA certificate %3 for %1 could not be verified because a server is currently unavailable." The CA can't check its own chain (usually the parent's CRL)
49 "could not be verified because no information is available describing how to check the revocation status." A certificate in the CA's chain has no usable CDP
65 / 66 "Active Directory Certificate Services could not publish a Base CRL for key %1 to the following location: %2." (66: Delta) A publication location refused the write: path, share, or LDAP rights
67 "made %1 attempts to publish a CRL and will stop publishing attempts until the next CRL is generated." Retries ran out; that location stays stale until the next CRL
74 / 75 The same base / delta failure "to the following location on server %4" Same, for a named server
100 "Active Directory Certificate Services did not start: Could not load or verify the current CA certificate." (Microsoft's Event 100 page) The CA won't start; the CRL for a CA above it is the common cause
# Read-only. On the CA: chain, publication, and startup events, last 30 days (IDs from Microsoft's AD CS event list) Get-WinEvent -FilterHashtable @{ LogName = 'Application'; ProviderName = 'Microsoft-Windows-CertificationAuthority' Id = 48, 49, 65, 66, 67, 74, 75, 100; StartTime = (Get-Date).AddDays(-30) } -ErrorAction SilentlyContinue | Select-Object TimeCreated, Id, Message | Format-List # Read-only. Is Certificate Services running? Get-Service -Name CertSvc | Select-Object Name, Status, StartType 

A Microsoft Q&A post shows what a failed LDAP publish looks like in practice: "could not publish a Base CRL for key 0 to the following location: ldap:///" with a logon failure code (community; the location is redacted in the post).

Where does the CA publish, and what do certificates carry? Microsoft: the CA's CDP configuration "represents both publication and retrieval settings". Read both:

# Read-only. On the CA: every CDP and AIA entry with its flags (Microsoft's lab guide uses the same Format-List form) Get-CACrlDistributionPoint | Format-List Get-CAAuthorityInformationAccess | Format-List 

Microsoft's cmdlet page lists the flags on each CDP entry: PublishToServer, PublishDeltaToServer, AddToCertificateCdp, AddToFreshestCrl, AddToCrlCdp, AddToCrlIdp, and Uri. PublishToServer is where the CA writes; AddToCertificateCdp is what clients get told. A URL with AddToCertificateCdp and nothing that copies the file there is a CDP that goes stale on its own (our reading).

The trap with CDP changes: "Changing a CDP URL affects only certificates issued after the change." Microsoft's design page says the same: "Modifying the URL for a CRL distribution point only affects newly issued certificates." Certificates issued before a change still point at the old URL. Microsoft's troubleshooting table for that case: "Keep the old CDP online and restore current CRL content there. A CDP configuration change doesn't repair old certificates."

The CA's own startup. Microsoft's Event 100 page: AD CS "startup can fail if there are problems with availability, validity, and chain validation for the CA certificate." Its resolution includes: "If a CRL for a CA in the chain has expired, generate new base and delta CRLs on this CA and copy them to the required locations." Microsoft's lab guide is blunt about the subordinate: if it can't find its parent's CRLs, the service "will fail to start on the subordinate CA". For the issuing CA, the parent is usually the offline root, so Step 9 is the fix. Read the CA's current ignore flags before anyone changes them:

:: Read-only. On the CA: CRLFlags as set now (a stopgap someone set last year shows up here) certutil -getreg ca\CRLFlags 
Finding What it means (our reading unless noted) Next
Events 65/74 for an LDAP location The CA can't write its CDP object Rights on the CDP container; Step 11
Events 65/74 for a file or UNC location Share, NTFS, or path problem The share and Cert Publishers rights (Step 5)
Event 100 or 48 at startup The parent CA's CRL is expired or unreachable from the CA Step 9
CRLF_REVCHECK_IGNORE_OFFLINE already set A stopgap from an earlier outage, hiding offline results on the CA Fix the CRL, then remove it (Step 11)
CDP URL in certificates differs from where the CA publishes Old certificates point at a location nobody updates Keep the old location current (Microsoft)
No HTTP URL with AddToCertificateCdp Off-network and non-Windows clients can't fetch Step 11: staged CDP add for new certificates

Step 9: The offline root's CRL (read-only)

The offline root is the one CA nobody turns on, so its CRL is the one that expires. Microsoft's CDP article: "For an offline root CA, avoid delta CRLs unless a documented requirement justifies them. Use a scheduled, witnessed process to publish a new ba...