防火墙替换证书链后CertVerifyCertificateChainPolicy验证失败但.NET X509Chain成功
企业环境下TLS证书验证失败:.NET与C++实现的差异解析
我的C++应用(WinSCP)通过neon和OpenSSL库实现HTTPS连接,用于检查服务器新版本,证书验证环节使用CertVerifyCertificateChainPolicy函数。以下是验证证书与Windows系统证书存储匹配的简化示例代码(省略错误检查):
const CERT_CONTEXT * CertContext = CertCreateCertificateContext( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, Certificate, Len); CERT_CHAIN_PARA ChainPara; memset(&ChainPara, 0, sizeof(ChainPara)); ChainPara.cbSize = sizeof(ChainPara); CERT_CHAIN_ENGINE_CONFIG ChainConfig; memset(&ChainConfig, 0, sizeof(ChainConfig)); ChainConfig.cbSize = sizeof(ChainConfig); ChainConfig.dwFlags = CERT_CHAIN_CACHE_END_CERT; HCERTCHAINENGINE ChainEngine; CertCreateCertificateChainEngine(&ChainConfig, &ChainEngine); const CERT_CHAIN_CONTEXT * ChainContext = NULL; CertGetCertificateChain( ChainEngine, CertContext, NULL, NULL, &ChainPara, CERT_CHAIN_CACHE_END_CERT | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT, NULL, &ChainContext); CERT_CHAIN_POLICY_PARA PolicyPara; PolicyPara.cbSize = sizeof(PolicyPara); CERT_CHAIN_POLICY_STATUS PolicyStatus; PolicyStatus.cbSize = sizeof(PolicyStatus); CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL, ChainContext, &PolicyPara, &PolicyStatus); int PolicyError = PolicyStatus.dwError;
这段代码在常规环境下运行正常,但有用户反馈在企业环境中验证失败——当企业防火墙替换证书链时,PolicyStatus.dwError被设置为800B0109(对应CERT_E_UNTRUSTEDROOT错误)。
按照@bartonjs的建议,我尝试用HCCE_CURRENT_USER(即NULL)替代自行创建的ChainEngine,但问题依旧。
不过其他应用却能正常连接我的网站:
- 用户可通过浏览器连接(已知浏览器有独立信任存储,此情况在意料之中)
- 用户可通过PowerShell的
Invoke-WebRequest命令连接 - 使用.NET的
X509Chain.Build方法也能成功验证站点证书(推测Invoke-WebRequest内部也是基于此实现):
X509Chain chain = new(); chain.Build(sslStream.RemoteCertificate); // chain.ChainStatus为空,表示证书验证通过
我查看过.NET的X509Chain.Build源码,逻辑看似和我的C++代码非常相似,但肯定存在未被发现的细微差异。想请教:.NET的处理方式到底有何不同,使其能成功验证被防火墙替换的证书链?
内容的提问来源于stack exchange,提问作者Martin Prikryl
相关产品推荐
相关产品推荐

