diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 07c486242c..bf0047644c 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -908,7 +908,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 6f43df74e4..86c2d681bc 100644 --- a/src/slic3r/Utils/Http.cpp +++ b/src/slic3r/Utils/Http.cpp @@ -14,8 +14,19 @@ #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; @@ -939,6 +950,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 a44a95e605..87dd57d8cb 100644 --- a/src/slic3r/Utils/Http.hpp +++ b/src/slic3r/Utils/Http.hpp @@ -11,6 +11,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 { @@ -198,6 +200,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);