Перейти к содержимому

Certificate revocation: CRL and OCSP

An EAP-TLS client certificate can be checked for revocation two ways: against a CRL (the CA’s signed list of revoked certificates, held on disk) and with an OCSP responder (asked about one certificate at the moment it authenticates). Both are decided per CA: a CA is checked because something is configured on it, and a CA with nothing configured is not checked at all. The check itself is made by FreeRADIUS in the nac container, during the TLS handshake, before any policy rule runs.

This page covers what is checked and why. Where each CRL comes from, how it is downloaded and which alerts watch it is on PKI & trust → CRL.

TermWhat it means here
Enable CRL CheckThe one switch for CRL checking, on NAC → Settings, section CRL Control. Off: no client certificate is checked against any CRL. On: the chains below are checked. New installations start with it on.
CA with a CRL configuredAn Internal CA, always (Taranac signs its CRL). A Trusted CA or an LDAP EAP-TLS CA once it has a CRL URL or an uploaded CRL.
Issuing CAThe CA that signed the client certificate, the one directly above it. Its CRL is the one that lists the client.
Check revocation with OCSPA switch on a Trusted CA and on an LDAP configuration’s EAP-TLS tab. Independent of Enable CRL Check. Internal CAs have no OCSP.
OCSP responder URLThe responder to ask, set beside the switch. Empty means the OCSP address in the client certificate (its AIA).

With Enable CRL Check on, a client certificate is checked against a CRL when some CA of its chain, up to the root, has a CRL configured. A chain with no such CA is accepted without a CRL check, and FreeRADIUS logs a warning naming the issuer (CRL not checked for ’…’: no CA in its chain has a CRL configured), once per issuer.

What makes a CA “configured” is the data, not a per-CA switch:

SourceConfigured when
Internal CAAlways, while it is enabled and active.
Trusted CA / LDAP EAP-TLS CA with a stored CRLThe certificate of the record whose key signed that CRL. In a record that holds a chain, the other certificates are not configured by it.
Trusted CA / LDAP EAP-TLS CA with a CRL URL but no CRL yet, or a CRL whose signer is not in the recordEvery certificate of the record, until a CRL narrows it to its signer.
Trusted CA / LDAP EAP-TLS CA with neitherNothing: its clients are not checked.

A CA is recognised by its key, so the same CA in two places (a Trusted CA and an LDAP configuration, or a renewal with the same key) is configured in both as soon as it is configured in one. Adding a CRL can only make checking stricter; nothing turns checking off for the clients of a configured CA.

Once a chain is checked, the client certificate is looked up in the CRL of its issuing CA, and only there. That CRL must be present and current:

  • no CRL for the issuing CA: the client is refused, tls_crl_missing;
  • the CRL has passed its next update: the client is refused, tls_crl_expired;
  • the certificate is on it: refused, tls_client_cert_revoked.

A root’s CRL lists the sub-CAs the root revoked, not their clients. So a root’s CRL does not cover the clients of its sub-CA: configure a CRL on the root only and every client of the sub-CA is refused as CRL missing until the sub-CA’s own CRL is added, in the same record or in a record of its own. With a two-tier AD CS, that means the CRL of the issuing CA (the distribution point the client certificates name), not the root’s.

HierarchyWhat to configureResult
Root issues the client certificatesThe root, with its CRLClients checked against the root’s CRL
Root → issuing CA, record holds both, CRL of the issuing CAThe issuing CA’s CRL URL on the recordClients checked against the issuing CA’s CRL
Root → issuing CA, CRL of the root only—Every client refused, tls_crl_missing
Root → two issuing CAs, one record each, only one with a CRLOne issuing CA’s CRLIts clients checked; the other CA’s clients accepted unchecked
Any CA, no CRL URL and no uploaded CRL—Not checked

A revoked certificate found on a CRL is refused whatever the configuration, as long as Enable CRL Check is on. The issuing chain above an Internal CA signed by your corporate PKI is not part of EAP-TLS trust, so its CRLs are not used here (see Upper-chain CRLs).

Setting a CRL on a Trusted CA or an LDAP configuration

Section titled “Setting a CRL on a Trusted CA or an LDAP configuration”

The Revocation checking section of a Trusted CA, and the Certificate Revocation List (CRL) section of an LDAP configuration’s EAP-TLS tab, are always shown. The rules are the same on both:

  • Saving a CRL URL downloads the CRL. A new or changed CRL distribution URL is fetched in the same save and stored with the URL. If it cannot be downloaded or its signature does not verify against the CA, nothing is saved and the error is shown at the URL field. Fetch tests a URL without saving.
  • A distribution point that only another cluster node can reach: upload the CRL file (PEM or DER) in the same save. A CRL sent with the save replaces the download.
  • Clearing the URL removes its CRL too, unless you upload a CRL in the same save. A URL owns the CRL it downloads; a CRL left behind without one would one day expire and refuse every client of the CA.
  • Delete CRL removes the URL and the CRL together; the CA is then no longer checked against a CRL. The form says what will be removed before you save, and Keep CRL takes it back.

A CRL URL that has not delivered a CRL yet raises its download alert on the first failure, critical while CRL checking is on, because its clients are already being refused. The alerts are listed under CRL alerts.

The first CRL of a CA applies at once. A replaced CRL applies within 5 minutes: FreeRADIUS rebuilds its CA store from the CRL files at most every 5 minutes, on the first new TLS session after that interval. Adding or removing a CRL source on a CA changes the revocation policy itself, which is applied as a new NAC configuration (see Applying a configuration): EAP conversations in flight at that moment start again.

End to end, a revocation by an external CA reaches clients after: its publication in the CA’s next base CRL (delta CRLs are not used), plus up to the External CRL Fetch interval (15 minutes by default), plus up to 5 minutes, plus the port’s next authentication. A port that is already open stays open until it re-authenticates: a revocation sends no CoA. To shorten that, publish the CRL at once on the CA (certutil -CRL on AD CS) and give switch ports a re-authentication timer. A revocation in an Internal CA re-signs its CRL immediately.

Check revocation with OCSP on a Trusted CA or an LDAP EAP-TLS configuration makes FreeRADIUS ask an OCSP responder about the client certificates of that CA and its sub-CAs, and of no other CA. It is independent of Enable CRL Check: a CA can be checked by CRL, by OCSP, or by both (a certificate revoked on the CRL is then refused without asking the responder).

In a record that holds a chain, OCSP marks the lowest certificates, those that issued nothing else in the record. A record holding a root and its issuing CA checks the clients of the issuing CA; another issuing CA under the same root, in a record without OCSP, is not touched. Only the client certificate is asked about, once per authentication, after its chain, dates and CRL have been checked. Internal CAs are never checked with OCSP: Taranac re-signs their CRL the moment a certificate is revoked and runs no responder.

  1. The record’s OCSP responder URL, when it is set, whatever the certificate says. It is taken from the nearest checked CA of the chain, starting at the issuing CA.
  2. Otherwise the first http:// OCSP address in the client certificate’s Authority Information Access (AIA). https and ldap entries are skipped.
  3. Neither: the check cannot be made and the client is refused.

Requests carry no nonce (Microsoft’s Online Responder answers a nonce with unauthorized). A response signed by the CA itself is accepted without its certificate attached, and so is one from a delegated signer with the OCSP Signing purpose. A response is accepted within its thisUpdate/nextUpdate window (5 minutes’ tolerance); one without a nextUpdate only while it is at most 5 minutes old. There is no response cache: every full handshake asks.

A client is refused whenever the check cannot be made

Section titled “A client is refused whenever the check cannot be made”

There is no soft-fail. The client is refused when the responder says the certificate is revoked, when it does not know the certificate, and when there is no answer to use: no responder address, no reply in time, an HTTP error, a response that is not successful (for example unauthorized), a signature or a date that does not check out. Switch on OCSP only for a CA whose responder every node can reach.

  • Only http://. OCSP responses are signed, so TLS adds nothing; https:// is refused with its own message. A host is required (IPv6 in brackets), a port must be 1–65535, no user name or password (the URL is written into the daemon’s configuration and every OCSP refusal in the log), only printable ASCII with no spaces, ", \ or $, at most 512 characters.
  • Saving asks the responder first. When OCSP is on and a URL is set, and OCSP was just turned on, the URL changed, or (on an LDAP configuration) the CA certificate changed, Taranac asks that responder about this CA before anything is saved. If it does not answer as FreeRADIUS needs, the save is refused with the reason at the URL field: unreachable within 3 seconds, a redirect (FreeRADIUS does not follow one), an HTTP error, not an OCSP response, unauthorized, or revocation data out of date. The question comes from the api container of the node you save on; FreeRADIUS asks from the nac container of every node.
  • Leave it empty to use the address in the client certificates, when that address is right. No question is asked on save then. That is also the way around responders that answer unauthorized for serial numbers they never issued (cfssl, Boulder), which the save check would otherwise refuse.

A change of the switch or the URL is applied as a new NAC configuration: EAP conversations in flight at that moment start again.

One OCSP check gets about 3 seconds in total, waiting for a slot included. At most 8 checks are in flight and 8 more wait for a slot; beyond that a check is refused at once (tls_ocsp_failed, class busy). The NAC container runs 32 FreeRADIUS worker threads, so a dead or slow responder holds at most 16 of them and MAB, PEAP and MFA pushes keep the rest. The slots are shared by all CAs: while one CA’s responder is down, clients of another CA checked by OCSP may be refused as busy.

The nac container’s resolver gives up after 2 seconds with one retry, so a dead DNS server cannot push a check past the switch’s RADIUS timeout. Give the responder a name that resolves quickly from every node, or use its IP address.

TLS session resumption is off while any CA is checked by CRL or by OCSP: a resumed session skips the revocation check. Every EAP-TLS, PEAP and EAP-TTLS authentication then makes a full handshake.

The NAC Auth Log (Logging & Reports → NAC Logs → Auth Log) names the cause of a refused client certificate, with OpenSSL’s error and the certificate’s issuer in the message:

Reject reasonShown asMeaning
tls_client_cert_revokedEAP-TLS: the client certificate is revokedListed on its issuing CA’s CRL.
tls_crl_missingEAP-TLS: CRL checking is on, but no CRL is loaded for the client certificate’s CAThe chain is checked, and the issuing CA has no CRL: often a CRL configured on the root only.
tls_crl_expiredEAP-TLS: the CRL of the client certificate’s CA has expired — publish a fresh CRLThe issuing CA’s CRL is past its next update.
tls_client_cert_expiredEAP-TLS: the client certificate has expired
tls_client_cert_not_yet_validEAP-TLS: the client certificate is not yet valid (its start date is in the future)Often a clock.
tls_client_cert_untrustedEAP-TLS: the client certificate’s issuer is not in the NAC Trusted CAsNo trusted CA issued it.
tls_ocsp_revokedOCSP check failed: the client certificate is revokedThe responder says revoked; the message gives its reason and time.
tls_ocsp_unknownOCSP check failed: the responder does not know the client certificateOften a responder that serves another CA.
tls_ocsp_failedOCSP check failed: the check could not be completedThe class follows: transport (no usable answer in time), response (unauthorized, tryLater…), verify (signature, signer or dates), busy (no free slot), config (no responder address).

Each OCSP row names the responder asked and the issuer. The raw data of the entry keeps every failure message FreeRADIUS reported.

AlertRaised whenSeverity
OCSP responder not usable: <url> (nac_ocsp:responder_unreachable:<url>, per node)A client was refused because the responder gave no usable answer (transport, response or verify).error
OCSP check impossible for clients of <issuer> (nac_ocsp:config:<hash>, per node)The check could not be made at all, usually because there is no URL on the record and no OCSP address in the certificate.error
NAC CA bundle not updated: a trusted CA cannot be used (nac_ca_bundle:unreadable, per node)A trusted CA’s certificate does not decrypt on this node or cannot be parsed, or a stored OCSP responder URL cannot be used. The CA bundle and the EAP configuration are kept as they were until it is fixed.error
NAC daemon does not understand the per-CA revocation policy (nac_daemon:ca_policy_unsupported, per node)The node’s nac image is older than its api. It keeps requiring a CRL from every trusted CA, and is not given a configuration with OCSP: the previous one keeps running. Update the node’s images.error

The two OCSP alerts close after an hour without another such refusal, with no resolution notice: FreeRADIUS logs no success, and silence does not prove the responder answers again. CRL download and expiry alerts are on PKI & trust.

  • A Revocation Configuration for every issuing CA whose clients you check. Without one the responder answers unauthorized: a saved URL is refused, and with the URL empty every client is refused.
  • The signing certificate from the OCSP Response Signing template. The responder attaches it to its answers.
  • Nonce support can stay as it is. Taranac sends no nonce.
  • Set the Web Proxy cache to 0 entries. By default the responder answers from its cache until the response’s nextUpdate, and a revocation is not seen until then. Restarting the OCSP service does not clear that cache; recycling the OCSPISAPIAppPool application pool does.
  • The responder learns of a revocation from its CA’s CRL. A revocation reaches it once the CA publishes a CRL and the responder’s CRL refresh interval has passed.
  • The OCSP address reaches the AIA only of certificates issued after it was configured on the CA. For older certificates, set the OCSP responder URL on the Trusted CA or LDAP configuration.

Each node downloads CRLs and asks OCSP responders on its own, so a distribution point or a responder must be reachable from every node. Refusals in the log and the OCSP alerts carry the node. A responder that only one node can reach is saved on that node, or left empty if the certificates’ AIA is right.

./taranac diagnose --protocol nac collects what the daemon sees: which CAs are checked against a CRL and why, which clients would be refused for a CRL of the wrong level, the CRLs on disk against those in the database, which CAs are checked with OCSP and with which responder, the last day’s OCSP refusals, and a live question to each responder URL.

SymptomCauseFix
Every client of one sub-CA refused, tls_crl_missingA CRL is configured on the root (or on a record holding the chain), not on the issuing CAAdd the issuing CA’s CRL, on the same record or a record of its own
Every client of one CA refused, tls_crl_expiredIts CRL stopped being refreshedCheck the Last fetch error and the CRL alerts; publish a fresh base CRL
A revoked certificate still gets inEnable CRL Check is off, no CA of the chain has a CRL, the CA has not published a new base CRL yet, or the port has not re-authenticatedCheck the switch and the CA’s CRL; give the port a re-authentication timer
Every client of an OCSP-checked CA refused, tls_ocsp_failed transportThe responder is not reachable from the nac container of this nodeOpen HTTP from every node, or fix the URL
tls_ocsp_failed response with unauthorizedThe responder does not serve this CA (on AD CS: no Revocation Configuration)Configure the responder for the issuing CA
tls_ocsp_unknownThe responder serves another CA, or does not know this certificate yetPoint the URL at the responder of the issuing CA
tls_ocsp_failed configNo URL on the record and no OCSP address in the certificateSet the OCSP responder URL
A revocation takes a day or more to show over OCSPThe Online Responder answers from its Web Proxy cacheSet the cache to 0 entries