|
|
|
@ -41,6 +41,8 @@ enum class IoMode : u32 { |
|
|
|
enum class OptionType : u32 { |
|
|
|
DoNotCloseSocket = 0, |
|
|
|
GetServerCertChain = 1, |
|
|
|
SkipDefaultVerify = 2, |
|
|
|
EnableAlpn = 3, |
|
|
|
}; |
|
|
|
|
|
|
|
// This is nn::ssl::sf::SslVersion
|
|
|
|
@ -61,6 +63,12 @@ struct SslContextSharedData { |
|
|
|
u32 connection_count = 0; |
|
|
|
}; |
|
|
|
|
|
|
|
struct Parameters { |
|
|
|
ContextOption option; |
|
|
|
s32 value; |
|
|
|
}; |
|
|
|
static_assert(sizeof(Parameters) == 0x8, "Parameters is an invalid size"); |
|
|
|
|
|
|
|
class ISslConnection final : public ServiceFramework<ISslConnection> { |
|
|
|
public: |
|
|
|
explicit ISslConnection(Core::System& system_in, SslVersion ssl_version_in, |
|
|
|
@ -96,8 +104,8 @@ public: |
|
|
|
{23, nullptr, "GetOption"}, |
|
|
|
{24, nullptr, "GetVerifyCertErrors"}, |
|
|
|
{25, nullptr, "GetCipherInfo"}, |
|
|
|
{26, nullptr, "SetNextAlpnProto"}, |
|
|
|
{27, nullptr, "GetNextAlpnProto"}, |
|
|
|
{26, &ISslConnection::SetNextAlpnProto, "SetNextAlpnProto"}, |
|
|
|
{27, &ISslConnection::GetNextAlpnProto, "GetNextAlpnProto"}, |
|
|
|
{28, nullptr, "SetDtlsSocketDescriptor"}, |
|
|
|
{29, nullptr, "GetDtlsHandshakeTimeout"}, |
|
|
|
{30, nullptr, "SetPrivateOption"}, |
|
|
|
@ -140,7 +148,10 @@ private: |
|
|
|
std::optional<int> fd_to_close; |
|
|
|
bool do_not_close_socket = false; |
|
|
|
bool get_server_cert_chain = false; |
|
|
|
bool skip_default_verify = false; |
|
|
|
bool enable_alpn = false; |
|
|
|
std::shared_ptr<Network::SocketBase> socket; |
|
|
|
std::vector<u8> next_alpn_proto; |
|
|
|
bool did_handshake = false; |
|
|
|
|
|
|
|
Result SetSocketDescriptorImpl(s32* out_fd, s32 fd) { |
|
|
|
@ -381,6 +392,12 @@ private: |
|
|
|
case OptionType::GetServerCertChain: |
|
|
|
get_server_cert_chain = static_cast<bool>(parameters.value); |
|
|
|
break; |
|
|
|
case OptionType::SkipDefaultVerify: |
|
|
|
skip_default_verify = static_cast<bool>(parameters.value); |
|
|
|
break; |
|
|
|
case OptionType::EnableAlpn: |
|
|
|
enable_alpn = static_cast<bool>(parameters.value); |
|
|
|
break; |
|
|
|
default: |
|
|
|
LOG_WARNING(Service_SSL, "Unknown option={}, value={}", parameters.option, |
|
|
|
parameters.value); |
|
|
|
@ -389,6 +406,31 @@ private: |
|
|
|
IPC::ResponseBuilder rb{ctx, 2}; |
|
|
|
rb.Push(ResultSuccess); |
|
|
|
} |
|
|
|
|
|
|
|
void SetNextAlpnProto(HLERequestContext& ctx) { |
|
|
|
const auto data = ctx.ReadBuffer(0); |
|
|
|
next_alpn_proto.assign(data.begin(), data.end()); |
|
|
|
|
|
|
|
LOG_DEBUG(Service_SSL, "SetNextAlpnProto called, size={}", next_alpn_proto.size()); |
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2}; |
|
|
|
rb.Push(ResultSuccess); |
|
|
|
} |
|
|
|
|
|
|
|
void GetNextAlpnProto(HLERequestContext& ctx) { |
|
|
|
const size_t writable = ctx.GetWriteBufferSize(); |
|
|
|
const size_t to_write = std::min(next_alpn_proto.size(), writable); |
|
|
|
|
|
|
|
if (to_write != 0) { |
|
|
|
ctx.WriteBuffer(std::span<const u8>(next_alpn_proto.data(), to_write)); |
|
|
|
} |
|
|
|
|
|
|
|
LOG_DEBUG(Service_SSL, "GetNextAlpnProto called, size={}", to_write); |
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 3}; |
|
|
|
rb.Push(ResultSuccess); |
|
|
|
rb.Push<u32>(static_cast<u32>(to_write)); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
class ISslContext final : public ServiceFramework<ISslContext> { |
|
|
|
@ -398,7 +440,7 @@ public: |
|
|
|
shared_data{std::make_shared<SslContextSharedData>()} { |
|
|
|
static const FunctionInfo functions[] = { |
|
|
|
{0, &ISslContext::SetOption, "SetOption"}, |
|
|
|
{1, nullptr, "GetOption"}, |
|
|
|
{1, &ISslContext::GetOption, "GetOption"}, |
|
|
|
{2, &ISslContext::CreateConnection, "CreateConnection"}, |
|
|
|
{3, &ISslContext::GetConnectionCount, "GetConnectionCount"}, |
|
|
|
{4, &ISslContext::ImportServerPki, "ImportServerPki"}, |
|
|
|
@ -420,17 +462,18 @@ private: |
|
|
|
std::shared_ptr<SslContextSharedData> shared_data; |
|
|
|
|
|
|
|
void SetOption(HLERequestContext& ctx) { |
|
|
|
struct Parameters { |
|
|
|
ContextOption option; |
|
|
|
s32 value; |
|
|
|
}; |
|
|
|
static_assert(sizeof(Parameters) == 0x8, "Parameters is an invalid size"); |
|
|
|
IPC::RequestParser rp{ctx}; |
|
|
|
const auto parameters = rp.PopRaw<ContextOption>(); |
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2}; |
|
|
|
rb.Push(ResultSuccess); |
|
|
|
} |
|
|
|
|
|
|
|
void GetOption(HLERequestContext& ctx) { |
|
|
|
IPC::RequestParser rp{ctx}; |
|
|
|
const auto parameters = rp.PopRaw<Parameters>(); |
|
|
|
const auto parameters = rp.PopRaw<OptionType>(); |
|
|
|
|
|
|
|
LOG_WARNING(Service_SSL, "(STUBBED) called. option={}, value={}", parameters.option, |
|
|
|
parameters.value); |
|
|
|
LOG_WARNING(Service_SSL, "(STUBBED) called. option={}", parameters); |
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2}; |
|
|
|
rb.Push(ResultSuccess); |
|
|
|
|