mirror of
https://github.com/curl/curl.git
synced 2025-09-06 20:34:59 +03:00
schannel: allow partial chains for manual peer verification
- Align --cacert behaviour with OpenSSL and LibreSSL. This changes the default behavior of Schannel manual certificate verification, which is used when the user provides their own CA certificates for verification, to accept partial chains. In other words, the user may provide an intermediate certificate without having to provide the root CA. Win8/Server2012 widened the PKIX chain traversal API to allow certificate traversal to terminate at an intermediate. This behaviour (terminate at the fist matching intermediate) is the default for LibreSSL and OpenSSL (with OpenSSL allowing control via CURLSSLOPT_NO_PARTIALCHAIN). This change uses the new API if it is available, and also allows the behaviour to revert legacy if CURLSSLOPT_NO_PARTIALCHAIN is present. Closes https://github.com/curl/curl/pull/17418
This commit is contained in:
parent
49a0c27bbc
commit
df1ff17f88
|
@ -55,9 +55,13 @@ Untrusted Publishers block list which it seems cannot be bypassed. (Added in
|
|||
## CURLSSLOPT_NO_PARTIALCHAIN
|
||||
|
||||
Tells libcurl to not accept "partial" certificate chains, which it otherwise
|
||||
does by default. This option is only supported for OpenSSL and fails the
|
||||
certificate verification if the chain ends with an intermediate certificate
|
||||
and not with a root cert. (Added in 7.68.0)
|
||||
does by default. This option fails the certificate verification if the chain
|
||||
ends with an intermediate certificate and not with a root cert.
|
||||
|
||||
Works with OpenSSL and its forks (LibreSSL, BoringSSL, etc). (Added in 7.68.0)
|
||||
|
||||
Works with Schannel if the user specified certificates to verify the peer.
|
||||
(Added in 8.15.0)
|
||||
|
||||
## CURLSSLOPT_REVOKE_BEST_EFFORT
|
||||
|
||||
|
|
|
@ -53,9 +53,13 @@ Untrusted Publishers block list which it seems cannot be bypassed. (Added in
|
|||
## CURLSSLOPT_NO_PARTIALCHAIN
|
||||
|
||||
Tells libcurl to not accept "partial" certificate chains, which it otherwise
|
||||
does by default. This option is only supported for OpenSSL and fails the
|
||||
certificate verification if the chain ends with an intermediate certificate
|
||||
and not with a root cert. (Added in 7.68.0)
|
||||
does by default. This option fails the certificate verification if the chain
|
||||
ends with an intermediate certificate and not with a root cert.
|
||||
|
||||
Works with OpenSSL and its forks (LibreSSL, BoringSSL, etc). (Added in 7.68.0)
|
||||
|
||||
Works with Schannel if the user specified certificates to verify the peer.
|
||||
(Added in 8.15.0)
|
||||
|
||||
## CURLSSLOPT_REVOKE_BEST_EFFORT
|
||||
|
||||
|
|
|
@ -78,6 +78,28 @@
|
|||
#define BEGIN_CERT "-----BEGIN CERTIFICATE-----"
|
||||
#define END_CERT "\n-----END CERTIFICATE-----"
|
||||
|
||||
struct cert_chain_engine_config_win8 {
|
||||
DWORD cbSize;
|
||||
HCERTSTORE hRestrictedRoot;
|
||||
HCERTSTORE hRestrictedTrust;
|
||||
HCERTSTORE hRestrictedOther;
|
||||
DWORD cAdditionalStore;
|
||||
HCERTSTORE *rghAdditionalStore;
|
||||
DWORD dwFlags;
|
||||
DWORD dwUrlRetrievalTimeout;
|
||||
DWORD MaximumCachedCertificates;
|
||||
DWORD CycleDetectionModulus;
|
||||
HCERTSTORE hExclusiveRoot;
|
||||
HCERTSTORE hExclusiveTrustedPeople;
|
||||
DWORD dwExclusiveFlags;
|
||||
};
|
||||
|
||||
#ifndef CERT_CHAIN_EXCLUSIVE_ENABLE_CA_FLAG
|
||||
/* Not defined for any MINGW build */
|
||||
#define CERT_CHAIN_EXCLUSIVE_ENABLE_CA_FLAG 0x00000001
|
||||
#endif
|
||||
|
||||
/* Legacy structure to supply size to Win7 clients */
|
||||
struct cert_chain_engine_config_win7 {
|
||||
DWORD cbSize;
|
||||
HCERTSTORE hRestrictedRoot;
|
||||
|
@ -93,6 +115,7 @@ struct cert_chain_engine_config_win7 {
|
|||
HCERTSTORE hExclusiveTrustedPeople;
|
||||
};
|
||||
|
||||
|
||||
#ifndef UNDER_CE
|
||||
static int is_cr_or_lf(char c)
|
||||
{
|
||||
|
@ -838,13 +861,22 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
|
|||
}
|
||||
|
||||
if(result == CURLE_OK) {
|
||||
struct cert_chain_engine_config_win7 engine_config;
|
||||
struct cert_chain_engine_config_win8 engine_config;
|
||||
BOOL create_engine_result;
|
||||
|
||||
memset(&engine_config, 0, sizeof(engine_config));
|
||||
engine_config.cbSize = sizeof(engine_config);
|
||||
engine_config.hExclusiveRoot = trust_store;
|
||||
|
||||
/* Win8/Server2012 allows us to match partial chains */
|
||||
if(curlx_verify_windows_version(6, 2, 0, PLATFORM_WINNT,
|
||||
VERSION_GREATER_THAN_EQUAL) &&
|
||||
!ssl_config->no_partialchain) {
|
||||
engine_config.cbSize = sizeof(engine_config);
|
||||
engine_config.dwExclusiveFlags = CERT_CHAIN_EXCLUSIVE_ENABLE_CA_FLAG;
|
||||
}
|
||||
else
|
||||
engine_config.cbSize = sizeof(struct cert_chain_engine_config_win7);
|
||||
|
||||
/* CertCreateCertificateChainEngine will check the expected size of the
|
||||
* CERT_CHAIN_ENGINE_CONFIG structure and fail if the specified size
|
||||
* does not match the expected size. When this occurs, it indicates that
|
||||
|
|
Loading…
Reference in New Issue
Block a user