diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 2825f7f671..d744399323 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -921,7 +921,7 @@ target_include_directories(libslic3r_gui PRIVATE Utils ${CMAKE_CURRENT_BINARY_DI if (WIN32) target_include_directories(libslic3r_gui SYSTEM PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../deps/WebView2/include) - target_link_libraries(libslic3r_gui Advapi32) + target_link_libraries(libslic3r_gui Advapi32 Crypt32) endif() source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SLIC3R_GUI_SOURCES}) diff --git a/src/slic3r/Utils/Http.cpp b/src/slic3r/Utils/Http.cpp index c5c4946b32..4a15abdcc6 100644 --- a/src/slic3r/Utils/Http.cpp +++ b/src/slic3r/Utils/Http.cpp @@ -27,8 +27,19 @@ #include #include -#ifdef OPENSSL_CERT_OVERRIDE +#include +#include #include +#include + +#ifdef _WIN32 +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include +# include +// wincrypt.h uses this token for a certificate-name property identifier. +# undef X509_NAME #endif namespace fs = boost::filesystem; @@ -952,6 +963,45 @@ std::string Http::tls_system_cert_store() return ret; } +void Http::add_platform_root_certificates(SSL_CTX* ssl_context) +{ +#ifdef _WIN32 + X509_STORE* openssl_store = SSL_CTX_get_cert_store(ssl_context); + if (!openssl_store) + throw std::runtime_error("unable to get OpenSSL certificate store"); + + const auto load_store = [&](DWORD location) { + HCERTSTORE windows_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, + location | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, + L"ROOT"); + if (!windows_store) + return; + + PCCERT_CONTEXT windows_certificate = nullptr; + while ((windows_certificate = CertEnumCertificatesInStore(windows_store, windows_certificate)) != nullptr) { + const unsigned char* encoded = windows_certificate->pbCertEncoded; + X509* certificate = d2i_X509(nullptr, &encoded, static_cast(windows_certificate->cbCertEncoded)); + if (!certificate) { + ERR_clear_error(); + continue; + } + + ERR_clear_error(); + if (X509_STORE_add_cert(openssl_store, certificate) != 1) + ERR_clear_error(); + X509_free(certificate); + } + + CertCloseStore(windows_store, 0); + }; + + load_store(CERT_SYSTEM_STORE_CURRENT_USER); + load_store(CERT_SYSTEM_STORE_LOCAL_MACHINE); +#else + (void)ssl_context; +#endif +} + std::string Http::url_encode(const std::string &str) { ::CURL *curl = ::curl_easy_init(); diff --git a/src/slic3r/Utils/Http.hpp b/src/slic3r/Utils/Http.hpp index d8fa012124..9c22eecb19 100644 --- a/src/slic3r/Utils/Http.hpp +++ b/src/slic3r/Utils/Http.hpp @@ -13,6 +13,8 @@ #include "libslic3r/Exception.hpp" #include "libslic3r_version.h" +typedef struct ssl_ctx_st SSL_CTX; + #define MAX_SIZE_TO_FILE 3*1024 namespace Slic3r { @@ -200,6 +202,10 @@ public: // Return empty string on success or error message on fail. static std::string tls_global_init(); static std::string tls_system_cert_store(); + // Add platform root certificates to a standalone OpenSSL context. This + // supplements set_default_verify_paths() on platforms where OpenSSL does + // not use the native certificate store. + static void add_platform_root_certificates(SSL_CTX* ssl_context); // converts the given string to an url_encoded_string static std::string url_encode(const std::string &str);