diff --git a/CMakeLists.txt b/CMakeLists.txt index 34ab23eafac..45e86ebd486 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -586,7 +586,7 @@ if (WIN32) target_link_libraries(torrent-rasterbar PRIVATE wsock32 ws2_32 Iphlpapi - debug dbghelp + debug dbghelp crypt32 ) add_definitions(-D_WIN32_WINNT=0x0600) # target Windows Vista or later diff --git a/ChangeLog b/ChangeLog index 2e56046f3dd..638a6ef40c8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * load SSL certificates from windows system certificate store, to authenticate trackers * introduce mitigation for Server Side Request Forgery in tracker announces * fix error handling for pool allocation failure diff --git a/Jamfile b/Jamfile index 744bbad9f5d..3171550b837 100644 --- a/Jamfile +++ b/Jamfile @@ -517,10 +517,13 @@ lib advapi32 : : advapi32 ; lib user32 : : user32 ; lib shell32 : : shell32 ; lib gdi32 : : gdi32 ; +lib crypt32 : : crypt32 ; lib z : : shared z ; # openssl libraries on windows -alias ssl-deps : advapi32 user32 shell32 gdi32 ; +# technically, crypt32 is not an OpenSSL dependency, but libtorrent needs it on +# windows to access the system certificate store, for authenticating trackers +alias ssl-deps : advapi32 user32 shell32 gdi32 crypt32 ; # pre OpenSSL 1.1 windows lib crypto : ssl-deps : windows pre1.1 libeay32 diff --git a/src/session_impl.cpp b/src/session_impl.cpp index a9a951ed255..892d9b895cb 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -171,6 +171,10 @@ namespace { } #endif +#ifdef TORRENT_WINDOWS +#include +#endif + #endif // TORRENT_USE_OPENSSL #ifdef TORRENT_WINDOWS @@ -559,6 +563,33 @@ namespace aux { m_ssl_ctx.set_verify_mode(boost::asio::ssl::context::verify_none, ec); m_ssl_ctx.set_default_verify_paths(ec); m_peer_ssl_ctx.set_verify_mode(boost::asio::ssl::context::verify_none, ec); +#ifdef TORRENT_WINDOWS + // load certificates from the windows system certificate store + X509_STORE* store = X509_STORE_new(); + if (store) + { + HCERTSTORE system_store = CertOpenSystemStoreA(0, "ROOT"); + // this is best effort + if (system_store) + { + CERT_CONTEXT const* ctx = nullptr; + while ((ctx = CertEnumCertificatesInStore(system_store, ctx)) != nullptr) + { + unsigned char const* cert_ptr = reinterpret_cast(ctx->pbCertEncoded); + X509* x509 = d2i_X509(nullptr, &cert_ptr, ctx->cbCertEncoded); + // this is best effort + if (!x509) continue; + X509_STORE_add_cert(store, x509); + X509_free(x509); + } + CertFreeCertificateContext(ctx); + CertCloseStore(system_store, 0); + } + } + + SSL_CTX* ssl_ctx = m_ssl_ctx.native_handle(); + SSL_CTX_set_cert_store(ssl_ctx, store); +#endif #if OPENSSL_VERSION_NUMBER >= 0x90812f aux::openssl_set_tlsext_servername_callback(m_peer_ssl_ctx.native_handle() , servername_callback);