@ -19,6 +19,10 @@
# include "core/internal_network/network.h"
# include "core/internal_network/network.h"
# include "core/internal_network/sockets.h"
# include "core/internal_network/sockets.h"
# ifdef YUZU_BUNDLED_OPENSSL
# include <openssl/cert.h>
# endif
using namespace Common : : FS ;
using namespace Common : : FS ;
namespace Service : : SSL {
namespace Service : : SSL {
@ -41,11 +45,85 @@ void OneTimeInit();
void OneTimeInitLogFile ( ) ;
void OneTimeInitLogFile ( ) ;
bool OneTimeInitBIO ( ) ;
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
} // namespace
class SSLConnectionBackendOpenSSL final : public SSLConnectionBackend {
class SSLConnectionBackendOpenSSL final : public SSLConnectionBackend {
public :
public :
Result Init ( ) {
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 ) ;
std : : call_once ( one_time_init_flag , OneTimeInit ) ;
if ( ! one_time_init_success ) {
if ( ! one_time_init_success ) {