IBackgroundCopyServerCertificateValidationCallback::ValidateServerCertificate 方法(bits10_3.h)

要实现的回调方法,将调用该方法,以便验证在打开 HTTPS 连接时发送的服务器证书。

语法

HRESULT ValidateServerCertificate(
  IBackgroundCopyJob  *job,
  IBackgroundCopyFile *file,
  DWORD               certLength,
  const BYTE []       certData,
  DWORD               certEncodingType,
  DWORD               certStoreLength,
  const BYTE []       certStoreData
);

参数

job

类型:IBackgroundCopyJob*

作业。

file

类型:IBackgroundCopyFile*

正在传输的文件。

certLength

类型:DWORD

证书数据的长度(以字节为单位)。

certData

类型:const BYTE []

包含证书数据的字节数组。 字节数必须与 certLength匹配。

certEncodingType

类型:DWORD

证书编码类型。

certStoreLength

类型:DWORD

证书存储数据的长度(以字节为单位)。

certStoreData

类型:const BYTE []

包含证书存储数据的字节数组。 字节数必须与 certStoreLength匹配。

返回值

返回 S_OK 以指示证书是可接受的。 否则,返回任何 HRESULT错误代码 以指示证书不可接受。

言论

证书验证在两个阶段执行。 第一阶段是操作系统(OS)阶段,操作系统对证书执行一组标准验证检查。 之后,如果 OS 阶段通过证书,将调用回调以执行其他验证。

如果要在服务器证书上执行自己的检查,请实现此验证方法。 除了正常的 OS 证书验证检查之外,你自己的检查也进行。

如果验证方法拒绝证书,则作业将转换为具有 BG_ERROR_CONTEXT_SERVER_CERTIFICATE_CALLBACK 作业错误上下文的 BG_JOB_STATE_TRANSIENT_ERROR,并从回调 HRESULT。 如果无法调用回调(例如,因为程序退出后需要 BITS 来验证服务器证书),则作业错误代码将 BG_E_SERVER_CERT_VALIDATION_INTERFACE_REQUIRED。 下次运行应用程序时,可以通过再次设置验证回调并恢复作业来修复此错误。

BITS 仅当实现 IBackgroundCopyServerCertificateValidationCallback 接口并将其传递到 IBackgroundCopyJobHttpOptions3::SetServerCertificateValidationInterface时,BITS 才会调用此回调方法。

当应用程序终止时,验证接口将变为无效;BITS 不维护验证接口的记录。 因此,应用程序的初始化过程应针对要接收证书验证请求的现有作业调用 SetServerCertificateValidationInterface

如果多个应用程序调用 SetServerCertificateValidationInterface 来设置作业的通知接口,则最后一个要调用的应用程序是接收通知的应用程序。 其他应用程序不会收到通知。

下面是验证证书的一般步骤。 请注意,这些步骤只是一个示例。 实际验证位于你的控制之下。 此外,步骤 5-7 与 OS 验证步骤中的操作大致相同。

  1. 使用 certEncodingTypecertDatacertLength 调用 CertCreateCertificateContext 以检索 CERT_CONTEXT

  2. 使用通过 certStoreLengthcertStoreData传递的序列化内存 blob 声明和初始化 CRYPT_DATA_BLOB 结构(在 wincrypt.h中定义)。

DATA_BLOB storeData{};
storeData.cbData = certStoreLength;
storeData.pbData = const_cast<PBYTE>(certStoreData);
  1. 通过使用 CERT_STORE_PROV_SERIALIZED、0、nullptr、标志和指向步骤 2 中的 CRYPT_DATA_BLOB 的指针调用 CertOpenStore 来获取证书链的句柄。
  2. 通过使用 nullptr、certContext、nullptr、步骤 3 中的句柄、链参数、标志和 nullptr 调用 CertGetCertificateChain 来获取指向证书链上下文的指针。
  3. 创建证书验证策略。
CERT_CHAIN_POLICY_PARA policyParams{};
policyParams.cbSize = sizeof(policyParams);
policyParams.dwFlags =
    CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG |
    CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG |
    CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG |
    CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG;
  1. 使用策略类型、链上下文、策略参数和策略状态调用 CertVerifyCertificateChainPolicy
  2. 将 Win32 错误(policyStatus.dwError)转换为 HRESULT 并返回此错误。

对 BITS 验证缓存行为的说明如下。 BITS 维护已通过自定义验证的证书的按作业缓存。 这是为了避免在作业的生存期内冗余且可能成本高昂的重新验证。 缓存由 <服务器终结点、证书哈希> 元组组成,其中 终结点 定义为 服务器名称:端口。 如果作业已允许来自特定终结点的特定证书,则不会再次调用回调。

当然,证书必须在每次连接尝试时都通过 OS 验证逻辑(可以使用调用 IBackgroundCopyJobHttpOptions::SetSecurityFlags)来自定义 OS 验证逻辑),这解决了时间敏感的角情况,例如证书最近有效(以秒为单位),但现在已过期。

BITS 不会缓存应用提供的验证回调认为无效的证书。 请务必了解所有未成功的连接尝试,以便可以在应用级别检测恶意部署。 例如,一次性错误的证书比同一服务器中的数千个错误的证书要少得多。

每次 调用 SetServerCertificateValidationInterface时,都会清除作业的证书缓存,因为它指示应用的服务器证书验证逻辑已更改。

要求

要求 价值
最低支持的客户端 Windows 10 版本 1809 [仅限桌面应用]
支持的最低服务器 Windows Server 2016 [仅限桌面应用]
标头 bits10_3.h (包括 Bits.h)
Bits.lib
DLL Bits.dll

另请参阅

IBackgroundCopyJobHttpOptions3::SetServerCertificateValidationInterface