@@ -185,6 +185,9 @@ using ssize_t = long;
185
185
#endif // NOMINMAX
186
186
187
187
#include < io.h>
188
+ #if defined(CPPHTTPLIB_OPENSSL_SUPPORT)
189
+ #define CERT_CHAIN_PARA_HAS_EXTRA_FIELDS
190
+ #endif
188
191
#include < winsock2.h>
189
192
#include < ws2tcpip.h>
190
193
@@ -5580,34 +5583,7 @@ inline bool is_ssl_peer_could_be_closed(SSL *ssl, socket_t sock) {
5580
5583
SSL_get_error (ssl, 0 ) == SSL_ERROR_ZERO_RETURN;
5581
5584
}
5582
5585
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__)
5611
5587
#if TARGET_OS_OSX
5612
5588
template <typename T>
5613
5589
using CFObjectPtr =
@@ -5697,7 +5673,7 @@ inline bool load_system_certs_on_macos(X509_STORE *store) {
5697
5673
return result;
5698
5674
}
5699
5675
#endif // TARGET_OS_OSX
5700
- #endif // _WIN32
5676
+ #endif // CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN && __APPLE__
5701
5677
#endif // CPPHTTPLIB_OPENSSL_SUPPORT
5702
5678
5703
5679
#ifdef _WIN32
@@ -9643,14 +9619,11 @@ inline bool SSLClient::load_certs() {
9643
9619
}
9644
9620
} else {
9645
9621
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__)
9650
9623
#if TARGET_OS_OSX
9651
9624
loaded = detail::load_system_certs_on_macos (SSL_CTX_get_cert_store (ctx_));
9652
9625
#endif // TARGET_OS_OSX
9653
- #endif // _WIN32
9626
+ #endif // CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN && __APPLE__
9654
9627
if (!loaded) { SSL_CTX_set_default_verify_paths (ctx_); }
9655
9628
}
9656
9629
});
@@ -9690,12 +9663,14 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
9690
9663
}
9691
9664
9692
9665
if (verification_status == SSLVerifierResponse::NoDecisionMade) {
9666
+ #ifndef _WIN32
9693
9667
verify_result_ = SSL_get_verify_result (ssl2);
9694
9668
9695
9669
if (verify_result_ != X509_V_OK) {
9696
9670
error = Error::SSLServerVerification;
9697
9671
return false ;
9698
9672
}
9673
+ #endif
9699
9674
9700
9675
auto server_cert = SSL_get1_peer_certificate (ssl2);
9701
9676
auto se = detail::scope_exit ([&] { X509_free (server_cert); });
@@ -9705,12 +9680,92 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
9705
9680
return false ;
9706
9681
}
9707
9682
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
9708
9762
if (server_hostname_verification_) {
9709
9763
if (!verify_host (server_cert)) {
9710
9764
error = Error::SSLServerHostnameVerification;
9711
9765
return false ;
9712
9766
}
9713
9767
}
9768
+ #endif
9714
9769
}
9715
9770
}
9716
9771
0 commit comments