Skip to content

Commit 93f729c

Browse files
Johncomplexspaces
authored andcommitted
fix win7 crash due to CERT_CHAIN_ENGINE_CONFIG
1 parent 345c4ad commit 93f729c

1 file changed

Lines changed: 35 additions & 5 deletions

File tree

  • rustls-platform-verifier/src/verification

rustls-platform-verifier/src/verification/windows.rs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,21 @@ use windows_sys::Win32::{
4343
CertFreeCertificateChain, CertFreeCertificateChainEngine, CertFreeCertificateContext,
4444
CertGetCertificateChain, CertOpenStore, CertSetCertificateContextProperty,
4545
CertVerifyCertificateChainPolicy, HTTPSPolicyCallbackData, AUTHTYPE_SERVER,
46-
CERT_CHAIN_CACHE_END_CERT, CERT_CHAIN_CONTEXT, CERT_CHAIN_ENGINE_CONFIG,
46+
CERT_CHAIN_CACHE_END_CERT, CERT_CHAIN_CONTEXT,
4747
CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS, CERT_CHAIN_POLICY_PARA,
4848
CERT_CHAIN_POLICY_SSL, CERT_CHAIN_POLICY_STATUS,
4949
CERT_CHAIN_REVOCATION_ACCUMULATIVE_TIMEOUT, CERT_CHAIN_REVOCATION_CHECK_END_CERT,
5050
CERT_CONTEXT, CERT_OCSP_RESPONSE_PROP_ID, CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG,
5151
CERT_STORE_ADD_ALWAYS, CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, CERT_STORE_PROV_MEMORY,
5252
CERT_STRONG_SIGN_PARA, CERT_TRUST_IS_PARTIAL_CHAIN, CERT_USAGE_MATCH, CRYPT_INTEGER_BLOB,
53-
CTL_USAGE, USAGE_MATCH_TYPE_AND, X509_ASN_ENCODING,
53+
CTL_USAGE, HCERTSTORE, USAGE_MATCH_TYPE_AND, X509_ASN_ENCODING,
5454
},
5555
};
5656

5757
use super::{log_server_cert, ALLOWED_EKUS};
5858

5959
// The `windows-sys` definition for `CERT_CHAIN_PARA` does not take old OS versions
60-
// into account so we define it ourselves for better (hypothetical) OS backwards compat.
60+
// into account so we define it ourselves for better OS backwards compat.
6161
// In the future a compile-time size assertion can be added against the upstream type to help stay in sync.
6262
#[allow(non_camel_case_types, non_snake_case)]
6363
#[repr(C)]
@@ -77,6 +77,29 @@ struct CERT_CHAIN_PARA {
7777
pub dwStrongSignFlags: u32,
7878
}
7979

80+
// Same workaround with CERT_CHAIN_PARA
81+
#[allow(non_camel_case_types, non_snake_case)]
82+
#[repr(C)]
83+
#[derive(Clone, Copy)]
84+
pub struct CERT_CHAIN_ENGINE_CONFIG {
85+
pub cbSize: u32,
86+
pub hRestrictedRoot: HCERTSTORE,
87+
pub hRestrictedTrust: HCERTSTORE,
88+
pub hRestrictedOther: HCERTSTORE,
89+
pub cAdditionalStore: u32,
90+
pub rghAdditionalStore: *mut HCERTSTORE,
91+
pub dwFlags: u32,
92+
pub dwUrlRetrievalTimeout: u32,
93+
pub MaximumCachedCertificates: u32,
94+
pub CycleDetectionModulus: u32,
95+
pub hExclusiveRoot: HCERTSTORE,
96+
pub hExclusiveTrustedPeople: HCERTSTORE,
97+
// XXX: `dwExclusiveFlags` started being available in Windows 8 and Windows Server 2012
98+
// See https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cert_chain_engine_config
99+
#[cfg(not(target_vendor = "win7"))]
100+
pub dwExclusiveFlags: u32,
101+
}
102+
80103
use crate::verification::invalid_certificate;
81104

82105
// SAFETY: see method implementation
@@ -231,8 +254,13 @@ impl CertEngine {
231254
config.hExclusiveRoot = exclusive_store.inner.as_ptr();
232255

233256
let mut engine = EnginePtr::NULL;
257+
258+
// XXX: Due to the redefinition of `CERT_CHAIN_ENGINE_CONFIG`, we need to do pointer casts
259+
// in order to pass our expanded structure into `CertCreateCertificateChainEngine`.
260+
// See also `CERT_CHAIN_PARA` casting below.
261+
let config = NonNull::from(&config).cast().as_ptr();
234262
// SAFETY: `engine` is valid to be written to and the config is valid to be read.
235-
let res = unsafe { CertCreateCertificateChainEngine(&config, &mut engine) };
263+
let res = unsafe { CertCreateCertificateChainEngine(config, &mut engine) };
236264

237265
#[allow(clippy::as_conversions)]
238266
let engine = call_with_last_error(|| match NonNull::new(engine as *mut c_void) {
@@ -265,8 +293,10 @@ impl CertEngine {
265293
config.hExclusiveRoot = root_store.inner.as_ptr();
266294

267295
let mut engine = EnginePtr::NULL;
296+
// Same workaround with as above when creating the engine.
297+
let config = NonNull::from(&config).cast().as_ptr();
268298
// SAFETY: `engine` is valid to be written to and the config is valid to be read.
269-
let res = unsafe { CertCreateCertificateChainEngine(&config, &mut engine) };
299+
let res = unsafe { CertCreateCertificateChainEngine(config, &mut engine) };
270300

271301
#[allow(clippy::as_conversions)]
272302
let engine = call_with_last_error(|| match NonNull::new(engine as *mut c_void) {

0 commit comments

Comments
 (0)