SafeFreeCertContext? remoteContext = null;
try
{
- // SECPKG_ATTR_REMOTE_CERT_CHAIN can be used even before the TLS handshake completes, which is necessary
- // in order to supply the certificate to the client cert selection callback. However, it is not available on
- // windows 7, so use the SECPKG_ATTR_REMOTE_CERT_CONTEXT as a fallback option.
- if (!SSPIWrapper.QueryContextAttributes_SECPKG_ATTR_REMOTE_CERT_CHAIN(GlobalSSPI.SSPISecureChannel, securityContext, out remoteContext))
+ // SECPKG_ATTR_REMOTE_CERT_CONTEXT will not succeed before TLS handshake completes. Inside the handshake,
+ // we need to use (more expensive) SECPKG_ATTR_REMOTE_CERT_CHAIN. That one may be unsupported on older
+ // versions of windows. In that case, we have no option than to return null.
+ //
+ // We can use retrieveCollection to distinguish between in-handshake and after-handshake calls, because
+ // the collection is retrieved for cert validation purposes after the handshake completes.
+ if (retrieveCollection) // handshake completed
{
SSPIWrapper.QueryContextAttributes_SECPKG_ATTR_REMOTE_CERT_CONTEXT(GlobalSSPI.SSPISecureChannel, securityContext, out remoteContext);
}
+ else // in handshake
+ {
+ SSPIWrapper.QueryContextAttributes_SECPKG_ATTR_REMOTE_CERT_CHAIN(GlobalSSPI.SSPISecureChannel, securityContext, out remoteContext);
+ }
if (remoteContext != null && !remoteContext.IsInvalid)
{