From bff09f36cc33c57590831613808f27089c94809e Mon Sep 17 00:00:00 2001 From: crueter Date: Tue, 21 Oct 2025 20:43:42 +0200 Subject: [PATCH] [update_checker] Use bundled Mozilla certificates for httplib (#2785) Previously, using bundled OpenSSL would result in the SSL library to fail to resolve certificates due to weird system funkiness that is basically impossible to deal with in a way that won't give you anal cancer. So to solve this the OpenSSL CI now bundles a precompiled certificate from Mozilla, which makes the update checker work Needs update checker testing on Windows and Android first and foremost Signed-off-by: crueter Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2785 Reviewed-by: MaranBr --- CMakeLists.txt | 3 ++ src/yuzu/update_checker.cpp | 96 +++++++++++++++++++++++-------------- 2 files changed, 63 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 796a04b862..a41b8204d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -431,6 +431,9 @@ include(CPMUtil) if (ENABLE_OPENSSL) if (YUZU_USE_BUNDLED_OPENSSL) AddJsonPackage(openssl) + if (OpenSSL_ADDED) + add_compile_definitions(YUZU_BUNDLED_OPENSSL) + endif() endif() find_package(OpenSSL 1.1.1 REQUIRED) diff --git a/src/yuzu/update_checker.cpp b/src/yuzu/update_checker.cpp index e54eb8d7f8..af56068682 100644 --- a/src/yuzu/update_checker.cpp +++ b/src/yuzu/update_checker.cpp @@ -5,61 +5,85 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -// SPDX-FileCopyrightText: eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - #include "update_checker.h" #include "common/logging/log.h" +#include "common/scm_rev.h" #include + +#ifndef CPPHTTPLIB_OPENSSL_SUPPORT +#define CPPHTTPLIB_OPENSSL_SUPPORT +#endif + #include + +#ifdef YUZU_BUNDLED_OPENSSL +#include +#endif + #include #include +#include #include -#include "common/scm_rev.h" std::optional UpdateChecker::GetResponse(std::string url, std::string path) { - constexpr std::size_t timeout_seconds = 15; + try { + constexpr std::size_t timeout_seconds = 15; - std::unique_ptr client = std::make_unique(url); - client->set_connection_timeout(timeout_seconds); - client->set_read_timeout(timeout_seconds); - client->set_write_timeout(timeout_seconds); + std::unique_ptr client = std::make_unique(url); + client->set_connection_timeout(timeout_seconds); + client->set_read_timeout(timeout_seconds); + client->set_write_timeout(timeout_seconds); - if (client == nullptr) { - LOG_ERROR(Frontend, "Invalid URL {}{}", url, path); - return {}; - } +#ifdef YUZU_BUNDLED_OPENSSL + client->load_ca_cert_store(kCert, sizeof(kCert)); +#endif + + if (client == nullptr) { + LOG_ERROR(Frontend, "Invalid URL {}{}", url, path); + return {}; + } - httplib::Request request{ - .method = "GET", - .path = path, - }; + httplib::Request request{ + .method = "GET", + .path = path, + }; - client->set_follow_location(true); - const auto result = client->send(request); - if (!result) { - LOG_ERROR(Frontend, "GET to {}{} returned null", url, path); - return {}; - } + client->set_follow_location(true); + httplib::Result result; + result = client->send(request); - const auto& response = result.value(); - if (response.status >= 400) { - LOG_ERROR(Frontend, "GET to {}{} returned error status code: {}", url, path, response.status); - return {}; - } - if (!response.headers.contains("content-type")) { - LOG_ERROR(Frontend, "GET to {}{} returned no content", url, path); - return {}; - } + if (!result) { + LOG_ERROR(Frontend, "GET to {}{} returned null", url, path); + return {}; + } + + const auto &response = result.value(); + if (response.status >= 400) { + LOG_ERROR(Frontend, + "GET to {}{} returned error status code: {}", + url, + path, + response.status); + return {}; + } + if (!response.headers.contains("content-type")) { + LOG_ERROR(Frontend, "GET to {}{} returned no content", url, path); + return {}; + } - return response.body; + return response.body; + } catch (std::exception &e) { + qDebug() << e.what(); + return std::nullopt; + } } std::optional UpdateChecker::GetLatestRelease(bool include_prereleases) { const auto update_check_url = std::string{Common::g_build_auto_update_api}; - std::string update_check_path = fmt::format("/repos/{}", std::string{Common::g_build_auto_update_repo}); + std::string update_check_path = fmt::format("/repos/{}", + std::string{Common::g_build_auto_update_repo}); try { if (include_prereleases) { // This can return either a prerelease or a stable release, // whichever is more recent. @@ -95,14 +119,14 @@ std::optional UpdateChecker::GetLatestRelease(bool include_prerelea return latest_tag; } - } catch (nlohmann::detail::out_of_range&) { + } catch (nlohmann::detail::out_of_range &) { LOG_ERROR(Frontend, "Parsing JSON response from {}{} failed during update check: " "nlohmann::detail::out_of_range", update_check_url, update_check_path); return {}; - } catch (nlohmann::detail::type_error&) { + } catch (nlohmann::detail::type_error &) { LOG_ERROR(Frontend, "Parsing JSON response from {}{} failed during update check: " "nlohmann::detail::type_error",