diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.md b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.md index 62eafca48d..68a34b2123 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.md @@ -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 diff --git a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.md b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.md index a997a43c32..38e002e8f4 100644 --- a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.md +++ b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.md @@ -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 diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c index f843342b9c..6634cb7883 100644 --- a/lib/vtls/schannel_verify.c +++ b/lib/vtls/schannel_verify.c @@ -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