@@ -185,6 +185,9 @@ using ssize_t = long;
185185#endif // NOMINMAX
186186
187187#include < io.h>
188+ #if defined(CPPHTTPLIB_OPENSSL_SUPPORT)
189+ #define CERT_CHAIN_PARA_HAS_EXTRA_FIELDS
190+ #endif
188191#include < winsock2.h>
189192#include < ws2tcpip.h>
190193
@@ -5580,34 +5583,7 @@ inline bool is_ssl_peer_could_be_closed(SSL *ssl, socket_t sock) {
55805583 SSL_get_error (ssl, 0 ) == SSL_ERROR_ZERO_RETURN;
55815584}
55825585
5583- #ifdef _WIN32
5584- // NOTE: This code came up with the following stackoverflow post:
5585- // https://stackoverflow.com/questions/9507184/can-openssl-on-windows-use-the-system-certificate-store
5586- inline bool load_system_certs_on_windows (X509_STORE *store) {
5587- auto hStore = CertOpenSystemStoreW ((HCRYPTPROV_LEGACY)NULL , L" ROOT" );
5588- if (!hStore) { return false ; }
5589-
5590- auto result = false ;
5591- PCCERT_CONTEXT pContext = NULL ;
5592- while ((pContext = CertEnumCertificatesInStore (hStore, pContext)) !=
5593- nullptr ) {
5594- auto encoded_cert =
5595- static_cast <const unsigned char *>(pContext->pbCertEncoded );
5596-
5597- auto x509 = d2i_X509 (NULL , &encoded_cert, pContext->cbCertEncoded );
5598- if (x509) {
5599- X509_STORE_add_cert (store, x509);
5600- X509_free (x509);
5601- result = true ;
5602- }
5603- }
5604-
5605- CertFreeCertificateContext (pContext);
5606- CertCloseStore (hStore, 0 );
5607-
5608- return result;
5609- }
5610- #elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)
5586+ #if defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)
56115587#if TARGET_OS_OSX
56125588template <typename T>
56135589using CFObjectPtr =
@@ -5697,7 +5673,7 @@ inline bool load_system_certs_on_macos(X509_STORE *store) {
56975673 return result;
56985674}
56995675#endif // TARGET_OS_OSX
5700- #endif // _WIN32
5676+ #endif // CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN && __APPLE__
57015677#endif // CPPHTTPLIB_OPENSSL_SUPPORT
57025678
57035679#ifdef _WIN32
@@ -9643,14 +9619,11 @@ inline bool SSLClient::load_certs() {
96439619 }
96449620 } else {
96459621 auto loaded = false ;
9646- #ifdef _WIN32
9647- loaded =
9648- detail::load_system_certs_on_windows (SSL_CTX_get_cert_store (ctx_));
9649- #elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)
9622+ #if defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)
96509623#if TARGET_OS_OSX
96519624 loaded = detail::load_system_certs_on_macos (SSL_CTX_get_cert_store (ctx_));
96529625#endif // TARGET_OS_OSX
9653- #endif // _WIN32
9626+ #endif // CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN && __APPLE__
96549627 if (!loaded) { SSL_CTX_set_default_verify_paths (ctx_); }
96559628 }
96569629 });
@@ -9690,12 +9663,14 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
96909663 }
96919664
96929665 if (verification_status == SSLVerifierResponse::NoDecisionMade) {
9666+ #ifndef _WIN32
96939667 verify_result_ = SSL_get_verify_result (ssl2);
96949668
96959669 if (verify_result_ != X509_V_OK) {
96969670 error = Error::SSLServerVerification;
96979671 return false ;
96989672 }
9673+ #endif
96999674
97009675 auto server_cert = SSL_get1_peer_certificate (ssl2);
97019676 auto se = detail::scope_exit ([&] { X509_free (server_cert); });
@@ -9705,12 +9680,92 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
97059680 return false ;
97069681 }
97079682
9683+ #ifdef _WIN32
9684+ // Convert OpenSSL certificate to DER format
9685+ auto der_cert =
9686+ std::vector<unsigned char >(i2d_X509 (server_cert, nullptr ));
9687+ auto der_cert_data = der_cert.data ();
9688+ if (i2d_X509 (server_cert, &der_cert_data) < 0 ) {
9689+ error = Error::SSLServerVerification;
9690+ return false ;
9691+ }
9692+
9693+ // Create a certificate context from the DER-encoded certificate
9694+ auto cert_context = CertCreateCertificateContext (
9695+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, der_cert.data (),
9696+ static_cast <DWORD>(der_cert.size ()));
9697+
9698+ if (cert_context == nullptr ) {
9699+ error = Error::SSLServerVerification;
9700+ return false ;
9701+ }
9702+
9703+ auto chain_para = CERT_CHAIN_PARA{};
9704+ chain_para.cbSize = sizeof (chain_para);
9705+ chain_para.dwUrlRetrievalTimeout = 10 * 1000 ;
9706+
9707+ auto chain_context = PCCERT_CHAIN_CONTEXT{};
9708+ auto result = CertGetCertificateChain (
9709+ nullptr , cert_context, nullptr , cert_context->hCertStore ,
9710+ &chain_para,
9711+ CERT_CHAIN_CACHE_END_CERT |
9712+ CERT_CHAIN_REVOCATION_CHECK_END_CERT |
9713+ CERT_CHAIN_REVOCATION_ACCUMULATIVE_TIMEOUT,
9714+ nullptr , &chain_context);
9715+
9716+ CertFreeCertificateContext (cert_context);
9717+
9718+ if (!result || chain_context == nullptr ) {
9719+ error = Error::SSLServerVerification;
9720+ return false ;
9721+ }
9722+
9723+ // Verify chain policy
9724+ auto extra_policy_para = SSL_EXTRA_CERT_CHAIN_POLICY_PARA{};
9725+ extra_policy_para.cbSize = sizeof (extra_policy_para);
9726+ extra_policy_para.dwAuthType = AUTHTYPE_SERVER;
9727+ auto whost = detail::u8string_to_wstring (host_.c_str ());
9728+ if (server_hostname_verification_) {
9729+ extra_policy_para.pwszServerName =
9730+ const_cast <wchar_t *>(whost.c_str ());
9731+ }
9732+
9733+ auto policy_para = CERT_CHAIN_POLICY_PARA{};
9734+ policy_para.cbSize = sizeof (policy_para);
9735+ policy_para.dwFlags =
9736+ CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS;
9737+ policy_para.pvExtraPolicyPara = &extra_policy_para;
9738+
9739+ auto policy_status = CERT_CHAIN_POLICY_STATUS{};
9740+ policy_status.cbSize = sizeof (policy_status);
9741+
9742+ result = CertVerifyCertificateChainPolicy (
9743+ CERT_CHAIN_POLICY_SSL, chain_context, &policy_para,
9744+ &policy_status);
9745+
9746+ CertFreeCertificateChain (chain_context);
9747+
9748+ if (!result) {
9749+ error = Error::SSLServerVerification;
9750+ return false ;
9751+ }
9752+
9753+ if (policy_status.dwError != 0 ) {
9754+ if (policy_status.dwError == CERT_E_CN_NO_MATCH) {
9755+ error = Error::SSLServerHostnameVerification;
9756+ } else {
9757+ error = Error::SSLServerVerification;
9758+ }
9759+ return false ;
9760+ }
9761+ #else
97089762 if (server_hostname_verification_) {
97099763 if (!verify_host (server_cert)) {
97109764 error = Error::SSLServerHostnameVerification;
97119765 return false ;
97129766 }
97139767 }
9768+ #endif
97149769 }
97159770 }
97169771
0 commit comments