From da94184673b4f5d0e11f051d215d8c9647ec0e90 Mon Sep 17 00:00:00 2001 From: crueter Date: Sun, 19 Oct 2025 13:18:00 -0400 Subject: [PATCH] [update_checker] Use bundled Mozilla certificates for httplib 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 Signed-off-by: crueter --- 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 b61bb49359..9c1a50ad6f 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",