Browse Source

[ssl] fix bundled OpenSSL ca cert issue (#2932)

I believe this is the final battle with OpenSSL

Signed-off-by: crueter <crueter@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2932
Reviewed-by: Maufeat <sahyno1996@gmail.com>
pull/2936/head
crueter 2 months ago
parent
commit
8ae7974092
No known key found for this signature in database GPG Key ID: 425ACD2D4830EBC6
  1. 78
      src/core/hle/service/ssl/ssl_backend_openssl.cpp

78
src/core/hle/service/ssl/ssl_backend_openssl.cpp

@ -19,6 +19,10 @@
#include "core/internal_network/network.h"
#include "core/internal_network/sockets.h"
#ifdef YUZU_BUNDLED_OPENSSL
#include <openssl/cert.h>
#endif
using namespace Common::FS;
namespace Service::SSL {
@ -41,11 +45,85 @@ void OneTimeInit();
void OneTimeInitLogFile();
bool OneTimeInitBIO();
#ifdef YUZU_BUNDLED_OPENSSL
// This is ported from httplib
struct scope_exit {
explicit scope_exit(std::function<void(void)> &&f)
: exit_function(std::move(f)), execute_on_destruction{true} {}
scope_exit(scope_exit &&rhs) noexcept
: exit_function(std::move(rhs.exit_function)),
execute_on_destruction{rhs.execute_on_destruction} {
rhs.release();
}
~scope_exit() {
if (execute_on_destruction) { this->exit_function(); }
}
void release() { this->execute_on_destruction = false; }
private:
scope_exit(const scope_exit &) = delete;
void operator=(const scope_exit &) = delete;
scope_exit &operator=(scope_exit &&) = delete;
std::function<void(void)> exit_function;
bool execute_on_destruction;
};
inline X509_STORE *CreateCaCertStore(const char *ca_cert,
std::size_t size) {
auto mem = BIO_new_mem_buf(ca_cert, static_cast<int>(size));
auto se = scope_exit([&] { BIO_free_all(mem); });
if (!mem) { return nullptr; }
auto inf = PEM_X509_INFO_read_bio(mem, nullptr, nullptr, nullptr);
if (!inf) { return nullptr; }
auto cts = X509_STORE_new();
if (cts) {
for (auto i = 0; i < static_cast<int>(sk_X509_INFO_num(inf)); i++) {
auto itmp = sk_X509_INFO_value(inf, i);
if (!itmp) { continue; }
if (itmp->x509) { X509_STORE_add_cert(cts, itmp->x509); }
if (itmp->crl) { X509_STORE_add_crl(cts, itmp->crl); }
}
}
sk_X509_INFO_pop_free(inf, X509_INFO_free);
return cts;
}
inline void SetCaCertStore(SSL_CTX *ctx, X509_STORE *ca_cert_store) {
if (ca_cert_store) {
if (ctx) {
if (SSL_CTX_get_cert_store(ctx) != ca_cert_store) {
// Free memory allocated for old cert and use new store `ca_cert_store`
SSL_CTX_set_cert_store(ctx, ca_cert_store);
}
} else {
X509_STORE_free(ca_cert_store);
}
}
}
inline void LoadCaCertStore(SSL_CTX* ctx, const char* ca_cert, std::size_t size)
{
SetCaCertStore(ctx, CreateCaCertStore(ca_cert, size));
}
#endif
} // namespace
class SSLConnectionBackendOpenSSL final : public SSLConnectionBackend {
public:
Result Init() {
// on bundled OpenSSL, load ca cert store
#ifdef YUZU_BUNDLED_OPENSSL
LoadCaCertStore(ssl_ctx, kCert, sizeof(kCert));
#endif
std::call_once(one_time_init_flag, OneTimeInit);
if (!one_time_init_success) {

Loading…
Cancel
Save