Setting TLSOptions.VerifyCertificate to True establishes that the server certificate chain is trusted and that it names the host being connected to. It says nothing about whether that certificate has been revoked since it was issued.
That gap matters: a stolen private key whose certificate has been revoked but has not yet expired still authenticates successfully, which is precisely the case revocation exists to cover. Revocation is checked only when it is asked for, through TLSOptions.SChannel_Options.Revocation.
oClient.TLS := True;
oClient.TLSOptions.IOHandler := iohSChannel;
oClient.TLSOptions.VerifyCertificate := True;
oClient.TLSOptions.SChannel_Options.Revocation.Check := scrcChainExcludeRoot;
The status is retrieved while the certificate chain is built, which means the CRL distribution point or OCSP responder named by the certificate is contacted during the handshake. That is why the check is off by default: enabling it adds network traffic to every new connection.
Selects how much of the chain has its revocation status looked up.
| scrcDisabled | Default. No revocation status is retrieved and none is required. |
| scrcEndCertificate | Only the server certificate is checked. The cheapest option, one lookup per connection. |
| scrcChainExcludeRoot | The server certificate and the intermediate certificates are checked, the root is not. The usual choice, because a self-signed root rarely publishes a CRL for itself. |
| scrcChain | The whole chain including the root. |
Milliseconds allowed for the whole revocation retrieval, not per URL, so a responder that does not answer cannot stall the handshake. Default 5000. A value of zero leaves the Windows default in force, which can be considerably longer.
When True, only revocation data Windows has already cached is used and the handshake never goes to the network, so it is never delayed. A cold cache then leaves the status unknown, which IgnoreNoRevocationCheck decides. Default False.
Decides what happens when the responder could not be reached. Default True, accept the certificate, which is the soft-fail behaviour web browsers use. Set it to False to reject instead. Rejecting is stricter, but it makes every connection depend on the responder being reachable, so a responder outage becomes an outage of your application.
Decides what happens when the certificate publishes no CRL distribution point and no OCSP responder at all, so its status cannot be established. Default True, accept it.
Neither Ignore property ever accepts a certificate that came back confirmed revoked. That outcome is always rejected.
When the connection is refused, the reason reaches the OnSChannelVerifyPeer event as one of:
| ecCryptRevoked | The certificate has been revoked by its issuer. Always rejected. |
| ecCryptRevocationOffline | The responder could not be reached. Only rejected when IgnoreRevocationOffline is False. |
| ecCryptNoRevocationCheck | The certificate publishes no revocation information. Only rejected when IgnoreNoRevocationCheck is False. |
Setting TLSOptions.Preset to tlspSecureDefaults enables the check as scrcChainExcludeRoot, together with the other hardened defaults, and keeps the two soft-fail settings, so switching it on does not break a connection that used to work. A scope you chose yourself before applying the preset is left untouched.
oClient.TLSOptions.Preset := tlspSecureDefaults;