mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-03 16:39:01 -06:00 
			
		
		
		
	Updates:
- Address PR feedback. - Add SecureTransport backend for macOS.
This commit is contained in:
		@@ -64,8 +64,9 @@ option(YUZU_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" OFF)
 | 
				
			|||||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "NOT WIN32" OFF)
 | 
					CMAKE_DEPENDENT_OPTION(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "NOT WIN32" OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(DEFAULT_ENABLE_OPENSSL ON)
 | 
					set(DEFAULT_ENABLE_OPENSSL ON)
 | 
				
			||||||
if (ANDROID OR WIN32)
 | 
					if (ANDROID OR WIN32 OR APPLE)
 | 
				
			||||||
    # - Windows defaults to the Schannel backend.
 | 
					    # - Windows defaults to the Schannel backend.
 | 
				
			||||||
 | 
					    # - macOS defaults to the SecureTransport backend.
 | 
				
			||||||
    # - Android currently has no SSL backend as the NDK doesn't include any SSL
 | 
					    # - Android currently has no SSL backend as the NDK doesn't include any SSL
 | 
				
			||||||
    #   library; a proper 'native' backend would have to go through Java.
 | 
					    #   library; a proper 'native' backend would have to go through Java.
 | 
				
			||||||
    # But you can force builds for those platforms to use OpenSSL if you have
 | 
					    # But you can force builds for those platforms to use OpenSSL if you have
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -868,6 +868,10 @@ if(ENABLE_OPENSSL)
 | 
				
			|||||||
    target_sources(core PRIVATE
 | 
					    target_sources(core PRIVATE
 | 
				
			||||||
        hle/service/ssl/ssl_backend_openssl.cpp)
 | 
					        hle/service/ssl/ssl_backend_openssl.cpp)
 | 
				
			||||||
    target_link_libraries(core PRIVATE OpenSSL::SSL)
 | 
					    target_link_libraries(core PRIVATE OpenSSL::SSL)
 | 
				
			||||||
 | 
					elseif (APPLE)
 | 
				
			||||||
 | 
					    target_sources(core PRIVATE
 | 
				
			||||||
 | 
					        hle/service/ssl/ssl_backend_securetransport.cpp)
 | 
				
			||||||
 | 
					    target_link_libraries(core PRIVATE "-framework Security")
 | 
				
			||||||
elseif (WIN32)
 | 
					elseif (WIN32)
 | 
				
			||||||
    target_sources(core PRIVATE
 | 
					    target_sources(core PRIVATE
 | 
				
			||||||
        hle/service/ssl/ssl_backend_schannel.cpp)
 | 
					        hle/service/ssl/ssl_backend_schannel.cpp)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -443,15 +443,28 @@ void BSD::Close(HLERequestContext& ctx) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void BSD::DuplicateSocket(HLERequestContext& ctx) {
 | 
					void BSD::DuplicateSocket(HLERequestContext& ctx) {
 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					    struct InputParameters {
 | 
				
			||||||
    const s32 fd = rp.Pop<s32>();
 | 
					        s32 fd;
 | 
				
			||||||
    [[maybe_unused]] const u64 unused = rp.Pop<u64>();
 | 
					        u64 reserved;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(InputParameters) == 0x10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Expected<s32, Errno> res = DuplicateSocketImpl(fd);
 | 
					    struct OutputParameters {
 | 
				
			||||||
 | 
					        s32 ret;
 | 
				
			||||||
 | 
					        Errno bsd_errno;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(OutputParameters) == 0x8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    auto input = rp.PopRaw<InputParameters>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Expected<s32, Errno> res = DuplicateSocketImpl(input.fd);
 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 4};
 | 
					    IPC::ResponseBuilder rb{ctx, 4};
 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
    rb.Push(res.value_or(0));                         // ret
 | 
					    rb.PushRaw(OutputParameters{
 | 
				
			||||||
    rb.Push(res ? 0 : static_cast<s32>(res.error())); // bsd errno
 | 
					        .ret = res.value_or(0),
 | 
				
			||||||
 | 
					        .bsd_errno = res ? Errno::SUCCESS : res.error(),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void BSD::EventFd(HLERequestContext& ctx) {
 | 
					void BSD::EventFd(HLERequestContext& ctx) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -131,14 +131,15 @@ static std::vector<u8> SerializeAddrInfoAsHostEnt(const std::vector<Network::Add
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static std::pair<u32, GetAddrInfoError> GetHostByNameRequestImpl(HLERequestContext& ctx) {
 | 
					static std::pair<u32, GetAddrInfoError> GetHostByNameRequestImpl(HLERequestContext& ctx) {
 | 
				
			||||||
    struct Parameters {
 | 
					    struct InputParameters {
 | 
				
			||||||
        u8 use_nsd_resolve;
 | 
					        u8 use_nsd_resolve;
 | 
				
			||||||
        u32 cancel_handle;
 | 
					        u32 cancel_handle;
 | 
				
			||||||
        u64 process_id;
 | 
					        u64 process_id;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(InputParameters) == 0x10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
    const auto parameters = rp.PopRaw<Parameters>();
 | 
					    const auto parameters = rp.PopRaw<InputParameters>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LOG_WARNING(
 | 
					    LOG_WARNING(
 | 
				
			||||||
        Service,
 | 
					        Service,
 | 
				
			||||||
@@ -164,21 +165,39 @@ static std::pair<u32, GetAddrInfoError> GetHostByNameRequestImpl(HLERequestConte
 | 
				
			|||||||
void SFDNSRES::GetHostByNameRequest(HLERequestContext& ctx) {
 | 
					void SFDNSRES::GetHostByNameRequest(HLERequestContext& ctx) {
 | 
				
			||||||
    auto [data_size, emu_gai_err] = GetHostByNameRequestImpl(ctx);
 | 
					    auto [data_size, emu_gai_err] = GetHostByNameRequestImpl(ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct OutputParameters {
 | 
				
			||||||
 | 
					        NetDbError netdb_error;
 | 
				
			||||||
 | 
					        Errno bsd_errno;
 | 
				
			||||||
 | 
					        u32 data_size;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(OutputParameters) == 0xc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 5};
 | 
					    IPC::ResponseBuilder rb{ctx, 5};
 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
    rb.Push(static_cast<s32>(GetAddrInfoErrorToNetDbError(emu_gai_err))); // netdb error code
 | 
					    rb.PushRaw(OutputParameters{
 | 
				
			||||||
    rb.Push(static_cast<s32>(GetAddrInfoErrorToErrno(emu_gai_err)));      // errno
 | 
					        .netdb_error = GetAddrInfoErrorToNetDbError(emu_gai_err),
 | 
				
			||||||
    rb.Push(data_size);                                                   // serialized size
 | 
					        .bsd_errno = GetAddrInfoErrorToErrno(emu_gai_err),
 | 
				
			||||||
 | 
					        .data_size = data_size,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SFDNSRES::GetHostByNameRequestWithOptions(HLERequestContext& ctx) {
 | 
					void SFDNSRES::GetHostByNameRequestWithOptions(HLERequestContext& ctx) {
 | 
				
			||||||
    auto [data_size, emu_gai_err] = GetHostByNameRequestImpl(ctx);
 | 
					    auto [data_size, emu_gai_err] = GetHostByNameRequestImpl(ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct OutputParameters {
 | 
				
			||||||
 | 
					        u32 data_size;
 | 
				
			||||||
 | 
					        NetDbError netdb_error;
 | 
				
			||||||
 | 
					        Errno bsd_errno;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(OutputParameters) == 0xc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 5};
 | 
					    IPC::ResponseBuilder rb{ctx, 5};
 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
    rb.Push(data_size);                                                   // serialized size
 | 
					    rb.PushRaw(OutputParameters{
 | 
				
			||||||
    rb.Push(static_cast<s32>(GetAddrInfoErrorToNetDbError(emu_gai_err))); // netdb error code
 | 
					        .data_size = data_size,
 | 
				
			||||||
    rb.Push(static_cast<s32>(GetAddrInfoErrorToErrno(emu_gai_err)));      // errno
 | 
					        .netdb_error = GetAddrInfoErrorToNetDbError(emu_gai_err),
 | 
				
			||||||
 | 
					        .bsd_errno = GetAddrInfoErrorToErrno(emu_gai_err),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static std::vector<u8> SerializeAddrInfo(const std::vector<Network::AddrInfo>& vec,
 | 
					static std::vector<u8> SerializeAddrInfo(const std::vector<Network::AddrInfo>& vec,
 | 
				
			||||||
@@ -221,14 +240,15 @@ static std::vector<u8> SerializeAddrInfo(const std::vector<Network::AddrInfo>& v
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static std::pair<u32, GetAddrInfoError> GetAddrInfoRequestImpl(HLERequestContext& ctx) {
 | 
					static std::pair<u32, GetAddrInfoError> GetAddrInfoRequestImpl(HLERequestContext& ctx) {
 | 
				
			||||||
    struct Parameters {
 | 
					    struct InputParameters {
 | 
				
			||||||
        u8 use_nsd_resolve;
 | 
					        u8 use_nsd_resolve;
 | 
				
			||||||
        u32 cancel_handle;
 | 
					        u32 cancel_handle;
 | 
				
			||||||
        u64 process_id;
 | 
					        u64 process_id;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(InputParameters) == 0x10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
    const auto parameters = rp.PopRaw<Parameters>();
 | 
					    const auto parameters = rp.PopRaw<InputParameters>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LOG_WARNING(
 | 
					    LOG_WARNING(
 | 
				
			||||||
        Service,
 | 
					        Service,
 | 
				
			||||||
@@ -264,23 +284,42 @@ static std::pair<u32, GetAddrInfoError> GetAddrInfoRequestImpl(HLERequestContext
 | 
				
			|||||||
void SFDNSRES::GetAddrInfoRequest(HLERequestContext& ctx) {
 | 
					void SFDNSRES::GetAddrInfoRequest(HLERequestContext& ctx) {
 | 
				
			||||||
    auto [data_size, emu_gai_err] = GetAddrInfoRequestImpl(ctx);
 | 
					    auto [data_size, emu_gai_err] = GetAddrInfoRequestImpl(ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct OutputParameters {
 | 
				
			||||||
 | 
					        Errno bsd_errno;
 | 
				
			||||||
 | 
					        GetAddrInfoError gai_error;
 | 
				
			||||||
 | 
					        u32 data_size;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(OutputParameters) == 0xc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 5};
 | 
					    IPC::ResponseBuilder rb{ctx, 5};
 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
    rb.Push(static_cast<s32>(GetAddrInfoErrorToErrno(emu_gai_err))); // errno
 | 
					    rb.PushRaw(OutputParameters{
 | 
				
			||||||
    rb.Push(static_cast<s32>(emu_gai_err));                          // getaddrinfo error code
 | 
					        .bsd_errno = GetAddrInfoErrorToErrno(emu_gai_err),
 | 
				
			||||||
    rb.Push(data_size);                                              // serialized size
 | 
					        .gai_error = emu_gai_err,
 | 
				
			||||||
 | 
					        .data_size = data_size,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SFDNSRES::GetAddrInfoRequestWithOptions(HLERequestContext& ctx) {
 | 
					void SFDNSRES::GetAddrInfoRequestWithOptions(HLERequestContext& ctx) {
 | 
				
			||||||
    // Additional options are ignored
 | 
					    // Additional options are ignored
 | 
				
			||||||
    auto [data_size, emu_gai_err] = GetAddrInfoRequestImpl(ctx);
 | 
					    auto [data_size, emu_gai_err] = GetAddrInfoRequestImpl(ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct OutputParameters {
 | 
				
			||||||
 | 
					        u32 data_size;
 | 
				
			||||||
 | 
					        GetAddrInfoError gai_error;
 | 
				
			||||||
 | 
					        NetDbError netdb_error;
 | 
				
			||||||
 | 
					        Errno bsd_errno;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(OutputParameters) == 0x10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 6};
 | 
					    IPC::ResponseBuilder rb{ctx, 6};
 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
    rb.Push(data_size);                                                   // serialized size
 | 
					    rb.PushRaw(OutputParameters{
 | 
				
			||||||
    rb.Push(static_cast<s32>(emu_gai_err));                               // getaddrinfo error code
 | 
					        .data_size = data_size,
 | 
				
			||||||
    rb.Push(static_cast<s32>(GetAddrInfoErrorToNetDbError(emu_gai_err))); // netdb error code
 | 
					        .gai_error = emu_gai_err,
 | 
				
			||||||
    rb.Push(static_cast<s32>(GetAddrInfoErrorToErrno(emu_gai_err)));      // errno
 | 
					        .netdb_error = GetAddrInfoErrorToNetDbError(emu_gai_err),
 | 
				
			||||||
 | 
					        .bsd_errno = GetAddrInfoErrorToErrno(emu_gai_err),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SFDNSRES::ResolverSetOptionRequest(HLERequestContext& ctx) {
 | 
					void SFDNSRES::ResolverSetOptionRequest(HLERequestContext& ctx) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,7 +64,7 @@ public:
 | 
				
			|||||||
                            std::shared_ptr<SslContextSharedData>& shared_data,
 | 
					                            std::shared_ptr<SslContextSharedData>& shared_data,
 | 
				
			||||||
                            std::unique_ptr<SSLConnectionBackend>&& backend)
 | 
					                            std::unique_ptr<SSLConnectionBackend>&& backend)
 | 
				
			||||||
        : ServiceFramework{system_, "ISslConnection"}, ssl_version{version},
 | 
					        : ServiceFramework{system_, "ISslConnection"}, ssl_version{version},
 | 
				
			||||||
          shared_data_{shared_data}, backend_{std::move(backend)} {
 | 
					          shared_data{shared_data}, backend{std::move(backend)} {
 | 
				
			||||||
        // clang-format off
 | 
					        // clang-format off
 | 
				
			||||||
        static const FunctionInfo functions[] = {
 | 
					        static const FunctionInfo functions[] = {
 | 
				
			||||||
            {0, &ISslConnection::SetSocketDescriptor, "SetSocketDescriptor"},
 | 
					            {0, &ISslConnection::SetSocketDescriptor, "SetSocketDescriptor"},
 | 
				
			||||||
@@ -112,10 +112,10 @@ public:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ~ISslConnection() {
 | 
					    ~ISslConnection() {
 | 
				
			||||||
        shared_data_->connection_count--;
 | 
					        shared_data->connection_count--;
 | 
				
			||||||
        if (fd_to_close_.has_value()) {
 | 
					        if (fd_to_close.has_value()) {
 | 
				
			||||||
            const s32 fd = *fd_to_close_;
 | 
					            const s32 fd = *fd_to_close;
 | 
				
			||||||
            if (!do_not_close_socket_) {
 | 
					            if (!do_not_close_socket) {
 | 
				
			||||||
                LOG_ERROR(Service_SSL,
 | 
					                LOG_ERROR(Service_SSL,
 | 
				
			||||||
                          "do_not_close_socket was changed after setting socket; is this right?");
 | 
					                          "do_not_close_socket was changed after setting socket; is this right?");
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
@@ -132,30 +132,30 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    SslVersion ssl_version;
 | 
					    SslVersion ssl_version;
 | 
				
			||||||
    std::shared_ptr<SslContextSharedData> shared_data_;
 | 
					    std::shared_ptr<SslContextSharedData> shared_data;
 | 
				
			||||||
    std::unique_ptr<SSLConnectionBackend> backend_;
 | 
					    std::unique_ptr<SSLConnectionBackend> backend;
 | 
				
			||||||
    std::optional<int> fd_to_close_;
 | 
					    std::optional<int> fd_to_close;
 | 
				
			||||||
    bool do_not_close_socket_ = false;
 | 
					    bool do_not_close_socket = false;
 | 
				
			||||||
    bool get_server_cert_chain_ = false;
 | 
					    bool get_server_cert_chain = false;
 | 
				
			||||||
    std::shared_ptr<Network::SocketBase> socket_;
 | 
					    std::shared_ptr<Network::SocketBase> socket;
 | 
				
			||||||
    bool did_set_host_name_ = false;
 | 
					    bool did_set_host_name = false;
 | 
				
			||||||
    bool did_handshake_ = false;
 | 
					    bool did_handshake = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultVal<s32> SetSocketDescriptorImpl(s32 fd) {
 | 
					    ResultVal<s32> SetSocketDescriptorImpl(s32 fd) {
 | 
				
			||||||
        LOG_DEBUG(Service_SSL, "called, fd={}", fd);
 | 
					        LOG_DEBUG(Service_SSL, "called, fd={}", fd);
 | 
				
			||||||
        ASSERT(!did_handshake_);
 | 
					        ASSERT(!did_handshake);
 | 
				
			||||||
        auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u");
 | 
					        auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u");
 | 
				
			||||||
        ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; });
 | 
					        ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; });
 | 
				
			||||||
        s32 ret_fd;
 | 
					        s32 ret_fd;
 | 
				
			||||||
        // Based on https://switchbrew.org/wiki/SSL_services#SetSocketDescriptor
 | 
					        // Based on https://switchbrew.org/wiki/SSL_services#SetSocketDescriptor
 | 
				
			||||||
        if (do_not_close_socket_) {
 | 
					        if (do_not_close_socket) {
 | 
				
			||||||
            auto res = bsd->DuplicateSocketImpl(fd);
 | 
					            auto res = bsd->DuplicateSocketImpl(fd);
 | 
				
			||||||
            if (!res.has_value()) {
 | 
					            if (!res.has_value()) {
 | 
				
			||||||
                LOG_ERROR(Service_SSL, "Failed to duplicate socket with fd {}", fd);
 | 
					                LOG_ERROR(Service_SSL, "Failed to duplicate socket with fd {}", fd);
 | 
				
			||||||
                return ResultInvalidSocket;
 | 
					                return ResultInvalidSocket;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            fd = *res;
 | 
					            fd = *res;
 | 
				
			||||||
            fd_to_close_ = fd;
 | 
					            fd_to_close = fd;
 | 
				
			||||||
            ret_fd = fd;
 | 
					            ret_fd = fd;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            ret_fd = -1;
 | 
					            ret_fd = -1;
 | 
				
			||||||
@@ -165,34 +165,34 @@ private:
 | 
				
			|||||||
            LOG_ERROR(Service_SSL, "invalid socket fd {}", fd);
 | 
					            LOG_ERROR(Service_SSL, "invalid socket fd {}", fd);
 | 
				
			||||||
            return ResultInvalidSocket;
 | 
					            return ResultInvalidSocket;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        socket_ = std::move(*sock);
 | 
					        socket = std::move(*sock);
 | 
				
			||||||
        backend_->SetSocket(socket_);
 | 
					        backend->SetSocket(socket);
 | 
				
			||||||
        return ret_fd;
 | 
					        return ret_fd;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Result SetHostNameImpl(const std::string& hostname) {
 | 
					    Result SetHostNameImpl(const std::string& hostname) {
 | 
				
			||||||
        LOG_DEBUG(Service_SSL, "called. hostname={}", hostname);
 | 
					        LOG_DEBUG(Service_SSL, "called. hostname={}", hostname);
 | 
				
			||||||
        ASSERT(!did_handshake_);
 | 
					        ASSERT(!did_handshake);
 | 
				
			||||||
        Result res = backend_->SetHostName(hostname);
 | 
					        Result res = backend->SetHostName(hostname);
 | 
				
			||||||
        if (res == ResultSuccess) {
 | 
					        if (res == ResultSuccess) {
 | 
				
			||||||
            did_set_host_name_ = true;
 | 
					            did_set_host_name = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return res;
 | 
					        return res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Result SetVerifyOptionImpl(u32 option) {
 | 
					    Result SetVerifyOptionImpl(u32 option) {
 | 
				
			||||||
        ASSERT(!did_handshake_);
 | 
					        ASSERT(!did_handshake);
 | 
				
			||||||
        LOG_WARNING(Service_SSL, "(STUBBED) called. option={}", option);
 | 
					        LOG_WARNING(Service_SSL, "(STUBBED) called. option={}", option);
 | 
				
			||||||
        return ResultSuccess;
 | 
					        return ResultSuccess;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Result SetIOModeImpl(u32 _mode) {
 | 
					    Result SetIoModeImpl(u32 input_mode) {
 | 
				
			||||||
        auto mode = static_cast<IoMode>(_mode);
 | 
					        auto mode = static_cast<IoMode>(input_mode);
 | 
				
			||||||
        ASSERT(mode == IoMode::Blocking || mode == IoMode::NonBlocking);
 | 
					        ASSERT(mode == IoMode::Blocking || mode == IoMode::NonBlocking);
 | 
				
			||||||
        ASSERT_OR_EXECUTE(socket_, { return ResultNoSocket; });
 | 
					        ASSERT_OR_EXECUTE(socket, { return ResultNoSocket; });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const bool non_block = mode == IoMode::NonBlocking;
 | 
					        const bool non_block = mode == IoMode::NonBlocking;
 | 
				
			||||||
        const Network::Errno error = socket_->SetNonBlock(non_block);
 | 
					        const Network::Errno error = socket->SetNonBlock(non_block);
 | 
				
			||||||
        if (error != Network::Errno::SUCCESS) {
 | 
					        if (error != Network::Errno::SUCCESS) {
 | 
				
			||||||
            LOG_ERROR(Service_SSL, "Failed to set native socket non-block flag to {}", non_block);
 | 
					            LOG_ERROR(Service_SSL, "Failed to set native socket non-block flag to {}", non_block);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -200,18 +200,18 @@ private:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Result SetSessionCacheModeImpl(u32 mode) {
 | 
					    Result SetSessionCacheModeImpl(u32 mode) {
 | 
				
			||||||
        ASSERT(!did_handshake_);
 | 
					        ASSERT(!did_handshake);
 | 
				
			||||||
        LOG_WARNING(Service_SSL, "(STUBBED) called. value={}", mode);
 | 
					        LOG_WARNING(Service_SSL, "(STUBBED) called. value={}", mode);
 | 
				
			||||||
        return ResultSuccess;
 | 
					        return ResultSuccess;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Result DoHandshakeImpl() {
 | 
					    Result DoHandshakeImpl() {
 | 
				
			||||||
        ASSERT_OR_EXECUTE(!did_handshake_ && socket_, { return ResultNoSocket; });
 | 
					        ASSERT_OR_EXECUTE(!did_handshake && socket, { return ResultNoSocket; });
 | 
				
			||||||
        ASSERT_OR_EXECUTE_MSG(
 | 
					        ASSERT_OR_EXECUTE_MSG(
 | 
				
			||||||
            did_set_host_name_, { return ResultInternalError; },
 | 
					            did_set_host_name, { return ResultInternalError; },
 | 
				
			||||||
            "Expected SetHostName before DoHandshake");
 | 
					            "Expected SetHostName before DoHandshake");
 | 
				
			||||||
        Result res = backend_->DoHandshake();
 | 
					        Result res = backend->DoHandshake();
 | 
				
			||||||
        did_handshake_ = res.IsSuccess();
 | 
					        did_handshake = res.IsSuccess();
 | 
				
			||||||
        return res;
 | 
					        return res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -225,7 +225,7 @@ private:
 | 
				
			|||||||
            u32 size;
 | 
					            u32 size;
 | 
				
			||||||
            u32 offset;
 | 
					            u32 offset;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        if (!get_server_cert_chain_) {
 | 
					        if (!get_server_cert_chain) {
 | 
				
			||||||
            // Just return the first one, unencoded.
 | 
					            // Just return the first one, unencoded.
 | 
				
			||||||
            ASSERT_OR_EXECUTE_MSG(
 | 
					            ASSERT_OR_EXECUTE_MSG(
 | 
				
			||||||
                !certs.empty(), { return {}; }, "Should be at least one server cert");
 | 
					                !certs.empty(), { return {}; }, "Should be at least one server cert");
 | 
				
			||||||
@@ -248,9 +248,9 @@ private:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultVal<std::vector<u8>> ReadImpl(size_t size) {
 | 
					    ResultVal<std::vector<u8>> ReadImpl(size_t size) {
 | 
				
			||||||
        ASSERT_OR_EXECUTE(did_handshake_, { return ResultInternalError; });
 | 
					        ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; });
 | 
				
			||||||
        std::vector<u8> res(size);
 | 
					        std::vector<u8> res(size);
 | 
				
			||||||
        ResultVal<size_t> actual = backend_->Read(res);
 | 
					        ResultVal<size_t> actual = backend->Read(res);
 | 
				
			||||||
        if (actual.Failed()) {
 | 
					        if (actual.Failed()) {
 | 
				
			||||||
            return actual.Code();
 | 
					            return actual.Code();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -259,8 +259,8 @@ private:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultVal<size_t> WriteImpl(std::span<const u8> data) {
 | 
					    ResultVal<size_t> WriteImpl(std::span<const u8> data) {
 | 
				
			||||||
        ASSERT_OR_EXECUTE(did_handshake_, { return ResultInternalError; });
 | 
					        ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; });
 | 
				
			||||||
        return backend_->Write(data);
 | 
					        return backend->Write(data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultVal<s32> PendingImpl() {
 | 
					    ResultVal<s32> PendingImpl() {
 | 
				
			||||||
@@ -295,7 +295,7 @@ private:
 | 
				
			|||||||
    void SetIoMode(HLERequestContext& ctx) {
 | 
					    void SetIoMode(HLERequestContext& ctx) {
 | 
				
			||||||
        IPC::RequestParser rp{ctx};
 | 
					        IPC::RequestParser rp{ctx};
 | 
				
			||||||
        const u32 mode = rp.Pop<u32>();
 | 
					        const u32 mode = rp.Pop<u32>();
 | 
				
			||||||
        const Result res = SetIOModeImpl(mode);
 | 
					        const Result res = SetIoModeImpl(mode);
 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					        IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
        rb.Push(res);
 | 
					        rb.Push(res);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -307,22 +307,26 @@ private:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void DoHandshakeGetServerCert(HLERequestContext& ctx) {
 | 
					    void DoHandshakeGetServerCert(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					        struct OutputParameters {
 | 
				
			||||||
 | 
					            u32 certs_size;
 | 
				
			||||||
 | 
					            u32 certs_count;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        static_assert(sizeof(OutputParameters) == 0x8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const Result res = DoHandshakeImpl();
 | 
					        const Result res = DoHandshakeImpl();
 | 
				
			||||||
        u32 certs_count = 0;
 | 
					        OutputParameters out{};
 | 
				
			||||||
        u32 certs_size = 0;
 | 
					 | 
				
			||||||
        if (res == ResultSuccess) {
 | 
					        if (res == ResultSuccess) {
 | 
				
			||||||
            auto certs = backend_->GetServerCerts();
 | 
					            auto certs = backend->GetServerCerts();
 | 
				
			||||||
            if (certs.Succeeded()) {
 | 
					            if (certs.Succeeded()) {
 | 
				
			||||||
                const std::vector<u8> certs_buf = SerializeServerCerts(*certs);
 | 
					                const std::vector<u8> certs_buf = SerializeServerCerts(*certs);
 | 
				
			||||||
                ctx.WriteBuffer(certs_buf);
 | 
					                ctx.WriteBuffer(certs_buf);
 | 
				
			||||||
                certs_count = static_cast<u32>(certs->size());
 | 
					                out.certs_count = static_cast<u32>(certs->size());
 | 
				
			||||||
                certs_size = static_cast<u32>(certs_buf.size());
 | 
					                out.certs_size = static_cast<u32>(certs_buf.size());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 4};
 | 
					        IPC::ResponseBuilder rb{ctx, 4};
 | 
				
			||||||
        rb.Push(res);
 | 
					        rb.Push(res);
 | 
				
			||||||
        rb.Push(certs_size);
 | 
					        rb.PushRaw(out);
 | 
				
			||||||
        rb.Push(certs_count);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void Read(HLERequestContext& ctx) {
 | 
					    void Read(HLERequestContext& ctx) {
 | 
				
			||||||
@@ -371,10 +375,10 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        switch (parameters.option) {
 | 
					        switch (parameters.option) {
 | 
				
			||||||
        case OptionType::DoNotCloseSocket:
 | 
					        case OptionType::DoNotCloseSocket:
 | 
				
			||||||
            do_not_close_socket_ = static_cast<bool>(parameters.value);
 | 
					            do_not_close_socket = static_cast<bool>(parameters.value);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case OptionType::GetServerCertChain:
 | 
					        case OptionType::GetServerCertChain:
 | 
				
			||||||
            get_server_cert_chain_ = static_cast<bool>(parameters.value);
 | 
					            get_server_cert_chain = static_cast<bool>(parameters.value);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            LOG_WARNING(Service_SSL, "Unknown option={}, value={}", parameters.option,
 | 
					            LOG_WARNING(Service_SSL, "Unknown option={}, value={}", parameters.option,
 | 
				
			||||||
@@ -390,7 +394,7 @@ class ISslContext final : public ServiceFramework<ISslContext> {
 | 
				
			|||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit ISslContext(Core::System& system_, SslVersion version)
 | 
					    explicit ISslContext(Core::System& system_, SslVersion version)
 | 
				
			||||||
        : ServiceFramework{system_, "ISslContext"}, ssl_version{version},
 | 
					        : ServiceFramework{system_, "ISslContext"}, ssl_version{version},
 | 
				
			||||||
          shared_data_{std::make_shared<SslContextSharedData>()} {
 | 
					          shared_data{std::make_shared<SslContextSharedData>()} {
 | 
				
			||||||
        static const FunctionInfo functions[] = {
 | 
					        static const FunctionInfo functions[] = {
 | 
				
			||||||
            {0, &ISslContext::SetOption, "SetOption"},
 | 
					            {0, &ISslContext::SetOption, "SetOption"},
 | 
				
			||||||
            {1, nullptr, "GetOption"},
 | 
					            {1, nullptr, "GetOption"},
 | 
				
			||||||
@@ -412,7 +416,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    SslVersion ssl_version;
 | 
					    SslVersion ssl_version;
 | 
				
			||||||
    std::shared_ptr<SslContextSharedData> shared_data_;
 | 
					    std::shared_ptr<SslContextSharedData> shared_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void SetOption(HLERequestContext& ctx) {
 | 
					    void SetOption(HLERequestContext& ctx) {
 | 
				
			||||||
        struct Parameters {
 | 
					        struct Parameters {
 | 
				
			||||||
@@ -439,17 +443,17 @@ private:
 | 
				
			|||||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
					        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
				
			||||||
        rb.Push(backend_res.Code());
 | 
					        rb.Push(backend_res.Code());
 | 
				
			||||||
        if (backend_res.Succeeded()) {
 | 
					        if (backend_res.Succeeded()) {
 | 
				
			||||||
            rb.PushIpcInterface<ISslConnection>(system, ssl_version, shared_data_,
 | 
					            rb.PushIpcInterface<ISslConnection>(system, ssl_version, shared_data,
 | 
				
			||||||
                                                std::move(*backend_res));
 | 
					                                                std::move(*backend_res));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void GetConnectionCount(HLERequestContext& ctx) {
 | 
					    void GetConnectionCount(HLERequestContext& ctx) {
 | 
				
			||||||
        LOG_WARNING(Service_SSL, "connection_count={}", shared_data_->connection_count);
 | 
					        LOG_DEBUG(Service_SSL, "connection_count={}", shared_data->connection_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
					        IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					        rb.Push(ResultSuccess);
 | 
				
			||||||
        rb.Push(shared_data_->connection_count);
 | 
					        rb.Push(shared_data->connection_count);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void ImportServerPki(HLERequestContext& ctx) {
 | 
					    void ImportServerPki(HLERequestContext& ctx) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,37 +51,37 @@ public:
 | 
				
			|||||||
            return ResultInternalError;
 | 
					            return ResultInternalError;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ssl_ = SSL_new(ssl_ctx);
 | 
					        ssl = SSL_new(ssl_ctx);
 | 
				
			||||||
        if (!ssl_) {
 | 
					        if (!ssl) {
 | 
				
			||||||
            LOG_ERROR(Service_SSL, "SSL_new failed");
 | 
					            LOG_ERROR(Service_SSL, "SSL_new failed");
 | 
				
			||||||
            return CheckOpenSSLErrors();
 | 
					            return CheckOpenSSLErrors();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SSL_set_connect_state(ssl_);
 | 
					        SSL_set_connect_state(ssl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bio_ = BIO_new(bio_meth);
 | 
					        bio = BIO_new(bio_meth);
 | 
				
			||||||
        if (!bio_) {
 | 
					        if (!bio) {
 | 
				
			||||||
            LOG_ERROR(Service_SSL, "BIO_new failed");
 | 
					            LOG_ERROR(Service_SSL, "BIO_new failed");
 | 
				
			||||||
            return CheckOpenSSLErrors();
 | 
					            return CheckOpenSSLErrors();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        BIO_set_data(bio_, this);
 | 
					        BIO_set_data(bio, this);
 | 
				
			||||||
        BIO_set_init(bio_, 1);
 | 
					        BIO_set_init(bio, 1);
 | 
				
			||||||
        SSL_set_bio(ssl_, bio_, bio_);
 | 
					        SSL_set_bio(ssl, bio, bio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return ResultSuccess;
 | 
					        return ResultSuccess;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void SetSocket(std::shared_ptr<Network::SocketBase> socket) override {
 | 
					    void SetSocket(std::shared_ptr<Network::SocketBase> socket_in) override {
 | 
				
			||||||
        socket_ = socket;
 | 
					        socket = std::move(socket_in);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Result SetHostName(const std::string& hostname) override {
 | 
					    Result SetHostName(const std::string& hostname) override {
 | 
				
			||||||
        if (!SSL_set1_host(ssl_, hostname.c_str())) { // hostname for verification
 | 
					        if (!SSL_set1_host(ssl, hostname.c_str())) { // hostname for verification
 | 
				
			||||||
            LOG_ERROR(Service_SSL, "SSL_set1_host({}) failed", hostname);
 | 
					            LOG_ERROR(Service_SSL, "SSL_set1_host({}) failed", hostname);
 | 
				
			||||||
            return CheckOpenSSLErrors();
 | 
					            return CheckOpenSSLErrors();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (!SSL_set_tlsext_host_name(ssl_, hostname.c_str())) { // hostname for SNI
 | 
					        if (!SSL_set_tlsext_host_name(ssl, hostname.c_str())) { // hostname for SNI
 | 
				
			||||||
            LOG_ERROR(Service_SSL, "SSL_set_tlsext_host_name({}) failed", hostname);
 | 
					            LOG_ERROR(Service_SSL, "SSL_set_tlsext_host_name({}) failed", hostname);
 | 
				
			||||||
            return CheckOpenSSLErrors();
 | 
					            return CheckOpenSSLErrors();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -89,18 +89,18 @@ public:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Result DoHandshake() override {
 | 
					    Result DoHandshake() override {
 | 
				
			||||||
        SSL_set_verify_result(ssl_, X509_V_OK);
 | 
					        SSL_set_verify_result(ssl, X509_V_OK);
 | 
				
			||||||
        const int ret = SSL_do_handshake(ssl_);
 | 
					        const int ret = SSL_do_handshake(ssl);
 | 
				
			||||||
        const long verify_result = SSL_get_verify_result(ssl_);
 | 
					        const long verify_result = SSL_get_verify_result(ssl);
 | 
				
			||||||
        if (verify_result != X509_V_OK) {
 | 
					        if (verify_result != X509_V_OK) {
 | 
				
			||||||
            LOG_ERROR(Service_SSL, "SSL cert verification failed because: {}",
 | 
					            LOG_ERROR(Service_SSL, "SSL cert verification failed because: {}",
 | 
				
			||||||
                      X509_verify_cert_error_string(verify_result));
 | 
					                      X509_verify_cert_error_string(verify_result));
 | 
				
			||||||
            return CheckOpenSSLErrors();
 | 
					            return CheckOpenSSLErrors();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (ret <= 0) {
 | 
					        if (ret <= 0) {
 | 
				
			||||||
            const int ssl_err = SSL_get_error(ssl_, ret);
 | 
					            const int ssl_err = SSL_get_error(ssl, ret);
 | 
				
			||||||
            if (ssl_err == SSL_ERROR_ZERO_RETURN ||
 | 
					            if (ssl_err == SSL_ERROR_ZERO_RETURN ||
 | 
				
			||||||
                (ssl_err == SSL_ERROR_SYSCALL && got_read_eof_)) {
 | 
					                (ssl_err == SSL_ERROR_SYSCALL && got_read_eof)) {
 | 
				
			||||||
                LOG_ERROR(Service_SSL, "SSL handshake failed because server hung up");
 | 
					                LOG_ERROR(Service_SSL, "SSL handshake failed because server hung up");
 | 
				
			||||||
                return ResultInternalError;
 | 
					                return ResultInternalError;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -110,18 +110,18 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ResultVal<size_t> Read(std::span<u8> data) override {
 | 
					    ResultVal<size_t> Read(std::span<u8> data) override {
 | 
				
			||||||
        size_t actual;
 | 
					        size_t actual;
 | 
				
			||||||
        const int ret = SSL_read_ex(ssl_, data.data(), data.size(), &actual);
 | 
					        const int ret = SSL_read_ex(ssl, data.data(), data.size(), &actual);
 | 
				
			||||||
        return HandleReturn("SSL_read_ex", actual, ret);
 | 
					        return HandleReturn("SSL_read_ex", actual, ret);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultVal<size_t> Write(std::span<const u8> data) override {
 | 
					    ResultVal<size_t> Write(std::span<const u8> data) override {
 | 
				
			||||||
        size_t actual;
 | 
					        size_t actual;
 | 
				
			||||||
        const int ret = SSL_write_ex(ssl_, data.data(), data.size(), &actual);
 | 
					        const int ret = SSL_write_ex(ssl, data.data(), data.size(), &actual);
 | 
				
			||||||
        return HandleReturn("SSL_write_ex", actual, ret);
 | 
					        return HandleReturn("SSL_write_ex", actual, ret);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultVal<size_t> HandleReturn(const char* what, size_t actual, int ret) {
 | 
					    ResultVal<size_t> HandleReturn(const char* what, size_t actual, int ret) {
 | 
				
			||||||
        const int ssl_err = SSL_get_error(ssl_, ret);
 | 
					        const int ssl_err = SSL_get_error(ssl, ret);
 | 
				
			||||||
        CheckOpenSSLErrors();
 | 
					        CheckOpenSSLErrors();
 | 
				
			||||||
        switch (ssl_err) {
 | 
					        switch (ssl_err) {
 | 
				
			||||||
        case SSL_ERROR_NONE:
 | 
					        case SSL_ERROR_NONE:
 | 
				
			||||||
@@ -137,7 +137,7 @@ public:
 | 
				
			|||||||
            LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_WANT_WRITE", what);
 | 
					            LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_WANT_WRITE", what);
 | 
				
			||||||
            return ResultWouldBlock;
 | 
					            return ResultWouldBlock;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            if (ssl_err == SSL_ERROR_SYSCALL && got_read_eof_) {
 | 
					            if (ssl_err == SSL_ERROR_SYSCALL && got_read_eof) {
 | 
				
			||||||
                LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_SYSCALL because server hung up", what);
 | 
					                LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_SYSCALL because server hung up", what);
 | 
				
			||||||
                return size_t(0);
 | 
					                return size_t(0);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -147,7 +147,7 @@ public:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override {
 | 
					    ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override {
 | 
				
			||||||
        STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_);
 | 
					        STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
 | 
				
			||||||
        if (!chain) {
 | 
					        if (!chain) {
 | 
				
			||||||
            LOG_ERROR(Service_SSL, "SSL_get_peer_cert_chain returned nullptr");
 | 
					            LOG_ERROR(Service_SSL, "SSL_get_peer_cert_chain returned nullptr");
 | 
				
			||||||
            return ResultInternalError;
 | 
					            return ResultInternalError;
 | 
				
			||||||
@@ -169,8 +169,8 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ~SSLConnectionBackendOpenSSL() {
 | 
					    ~SSLConnectionBackendOpenSSL() {
 | 
				
			||||||
        // these are null-tolerant:
 | 
					        // these are null-tolerant:
 | 
				
			||||||
        SSL_free(ssl_);
 | 
					        SSL_free(ssl);
 | 
				
			||||||
        BIO_free(bio_);
 | 
					        BIO_free(bio);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static void KeyLogCallback(const SSL* ssl, const char* line) {
 | 
					    static void KeyLogCallback(const SSL* ssl, const char* line) {
 | 
				
			||||||
@@ -188,9 +188,9 @@ public:
 | 
				
			|||||||
    static int WriteCallback(BIO* bio, const char* buf, size_t len, size_t* actual_p) {
 | 
					    static int WriteCallback(BIO* bio, const char* buf, size_t len, size_t* actual_p) {
 | 
				
			||||||
        auto self = static_cast<SSLConnectionBackendOpenSSL*>(BIO_get_data(bio));
 | 
					        auto self = static_cast<SSLConnectionBackendOpenSSL*>(BIO_get_data(bio));
 | 
				
			||||||
        ASSERT_OR_EXECUTE_MSG(
 | 
					        ASSERT_OR_EXECUTE_MSG(
 | 
				
			||||||
            self->socket_, { return 0; }, "OpenSSL asked to send but we have no socket");
 | 
					            self->socket, { return 0; }, "OpenSSL asked to send but we have no socket");
 | 
				
			||||||
        BIO_clear_retry_flags(bio);
 | 
					        BIO_clear_retry_flags(bio);
 | 
				
			||||||
        auto [actual, err] = self->socket_->Send({reinterpret_cast<const u8*>(buf), len}, 0);
 | 
					        auto [actual, err] = self->socket->Send({reinterpret_cast<const u8*>(buf), len}, 0);
 | 
				
			||||||
        switch (err) {
 | 
					        switch (err) {
 | 
				
			||||||
        case Network::Errno::SUCCESS:
 | 
					        case Network::Errno::SUCCESS:
 | 
				
			||||||
            *actual_p = actual;
 | 
					            *actual_p = actual;
 | 
				
			||||||
@@ -207,14 +207,14 @@ public:
 | 
				
			|||||||
    static int ReadCallback(BIO* bio, char* buf, size_t len, size_t* actual_p) {
 | 
					    static int ReadCallback(BIO* bio, char* buf, size_t len, size_t* actual_p) {
 | 
				
			||||||
        auto self = static_cast<SSLConnectionBackendOpenSSL*>(BIO_get_data(bio));
 | 
					        auto self = static_cast<SSLConnectionBackendOpenSSL*>(BIO_get_data(bio));
 | 
				
			||||||
        ASSERT_OR_EXECUTE_MSG(
 | 
					        ASSERT_OR_EXECUTE_MSG(
 | 
				
			||||||
            self->socket_, { return 0; }, "OpenSSL asked to recv but we have no socket");
 | 
					            self->socket, { return 0; }, "OpenSSL asked to recv but we have no socket");
 | 
				
			||||||
        BIO_clear_retry_flags(bio);
 | 
					        BIO_clear_retry_flags(bio);
 | 
				
			||||||
        auto [actual, err] = self->socket_->Recv(0, {reinterpret_cast<u8*>(buf), len});
 | 
					        auto [actual, err] = self->socket->Recv(0, {reinterpret_cast<u8*>(buf), len});
 | 
				
			||||||
        switch (err) {
 | 
					        switch (err) {
 | 
				
			||||||
        case Network::Errno::SUCCESS:
 | 
					        case Network::Errno::SUCCESS:
 | 
				
			||||||
            *actual_p = actual;
 | 
					            *actual_p = actual;
 | 
				
			||||||
            if (actual == 0) {
 | 
					            if (actual == 0) {
 | 
				
			||||||
                self->got_read_eof_ = true;
 | 
					                self->got_read_eof = true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return actual ? 1 : 0;
 | 
					            return actual ? 1 : 0;
 | 
				
			||||||
        case Network::Errno::AGAIN:
 | 
					        case Network::Errno::AGAIN:
 | 
				
			||||||
@@ -246,11 +246,11 @@ public:
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SSL* ssl_ = nullptr;
 | 
					    SSL* ssl = nullptr;
 | 
				
			||||||
    BIO* bio_ = nullptr;
 | 
					    BIO* bio = nullptr;
 | 
				
			||||||
    bool got_read_eof_ = false;
 | 
					    bool got_read_eof = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::shared_ptr<Network::SocketBase> socket_;
 | 
					    std::shared_ptr<Network::SocketBase> socket;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {
 | 
					ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,6 +48,12 @@ static void OneTimeInit() {
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (getenv("SSLKEYLOGFILE")) {
 | 
				
			||||||
 | 
					        LOG_CRITICAL(Service_SSL, "SSLKEYLOGFILE was set but Schannel does not support exporting "
 | 
				
			||||||
 | 
					                                  "keys; not logging keys!");
 | 
				
			||||||
 | 
					        // Not fatal.
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    one_time_init_success = true;
 | 
					    one_time_init_success = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -70,25 +76,25 @@ public:
 | 
				
			|||||||
        return ResultSuccess;
 | 
					        return ResultSuccess;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void SetSocket(std::shared_ptr<Network::SocketBase> socket) override {
 | 
					    void SetSocket(std::shared_ptr<Network::SocketBase> socket_in) override {
 | 
				
			||||||
        socket_ = socket;
 | 
					        socket = std::move(socket_in);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Result SetHostName(const std::string& hostname) override {
 | 
					    Result SetHostName(const std::string& hostname_in) override {
 | 
				
			||||||
        hostname_ = hostname;
 | 
					        hostname = hostname_in;
 | 
				
			||||||
        return ResultSuccess;
 | 
					        return ResultSuccess;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Result DoHandshake() override {
 | 
					    Result DoHandshake() override {
 | 
				
			||||||
        while (1) {
 | 
					        while (1) {
 | 
				
			||||||
            Result r;
 | 
					            Result r;
 | 
				
			||||||
            switch (handshake_state_) {
 | 
					            switch (handshake_state) {
 | 
				
			||||||
            case HandshakeState::Initial:
 | 
					            case HandshakeState::Initial:
 | 
				
			||||||
                if ((r = FlushCiphertextWriteBuf()) != ResultSuccess ||
 | 
					                if ((r = FlushCiphertextWriteBuf()) != ResultSuccess ||
 | 
				
			||||||
                    (r = CallInitializeSecurityContext()) != ResultSuccess) {
 | 
					                    (r = CallInitializeSecurityContext()) != ResultSuccess) {
 | 
				
			||||||
                    return r;
 | 
					                    return r;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                // CallInitializeSecurityContext updated `handshake_state_`.
 | 
					                // CallInitializeSecurityContext updated `handshake_state`.
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            case HandshakeState::ContinueNeeded:
 | 
					            case HandshakeState::ContinueNeeded:
 | 
				
			||||||
            case HandshakeState::IncompleteMessage:
 | 
					            case HandshakeState::IncompleteMessage:
 | 
				
			||||||
@@ -96,20 +102,20 @@ public:
 | 
				
			|||||||
                    (r = FillCiphertextReadBuf()) != ResultSuccess) {
 | 
					                    (r = FillCiphertextReadBuf()) != ResultSuccess) {
 | 
				
			||||||
                    return r;
 | 
					                    return r;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if (ciphertext_read_buf_.empty()) {
 | 
					                if (ciphertext_read_buf.empty()) {
 | 
				
			||||||
                    LOG_ERROR(Service_SSL, "SSL handshake failed because server hung up");
 | 
					                    LOG_ERROR(Service_SSL, "SSL handshake failed because server hung up");
 | 
				
			||||||
                    return ResultInternalError;
 | 
					                    return ResultInternalError;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if ((r = CallInitializeSecurityContext()) != ResultSuccess) {
 | 
					                if ((r = CallInitializeSecurityContext()) != ResultSuccess) {
 | 
				
			||||||
                    return r;
 | 
					                    return r;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                // CallInitializeSecurityContext updated `handshake_state_`.
 | 
					                // CallInitializeSecurityContext updated `handshake_state`.
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            case HandshakeState::DoneAfterFlush:
 | 
					            case HandshakeState::DoneAfterFlush:
 | 
				
			||||||
                if ((r = FlushCiphertextWriteBuf()) != ResultSuccess) {
 | 
					                if ((r = FlushCiphertextWriteBuf()) != ResultSuccess) {
 | 
				
			||||||
                    return r;
 | 
					                    return r;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                handshake_state_ = HandshakeState::Connected;
 | 
					                handshake_state = HandshakeState::Connected;
 | 
				
			||||||
                return ResultSuccess;
 | 
					                return ResultSuccess;
 | 
				
			||||||
            case HandshakeState::Connected:
 | 
					            case HandshakeState::Connected:
 | 
				
			||||||
                LOG_ERROR(Service_SSL, "Called DoHandshake but we already handshook");
 | 
					                LOG_ERROR(Service_SSL, "Called DoHandshake but we already handshook");
 | 
				
			||||||
@@ -121,24 +127,24 @@ public:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Result FillCiphertextReadBuf() {
 | 
					    Result FillCiphertextReadBuf() {
 | 
				
			||||||
        const size_t fill_size = read_buf_fill_size_ ? read_buf_fill_size_ : 4096;
 | 
					        const size_t fill_size = read_buf_fill_size ? read_buf_fill_size : 4096;
 | 
				
			||||||
        read_buf_fill_size_ = 0;
 | 
					        read_buf_fill_size = 0;
 | 
				
			||||||
        // This unnecessarily zeroes the buffer; oh well.
 | 
					        // This unnecessarily zeroes the buffer; oh well.
 | 
				
			||||||
        const size_t offset = ciphertext_read_buf_.size();
 | 
					        const size_t offset = ciphertext_read_buf.size();
 | 
				
			||||||
        ASSERT_OR_EXECUTE(offset + fill_size >= offset, { return ResultInternalError; });
 | 
					        ASSERT_OR_EXECUTE(offset + fill_size >= offset, { return ResultInternalError; });
 | 
				
			||||||
        ciphertext_read_buf_.resize(offset + fill_size, 0);
 | 
					        ciphertext_read_buf.resize(offset + fill_size, 0);
 | 
				
			||||||
        const auto read_span = std::span(ciphertext_read_buf_).subspan(offset, fill_size);
 | 
					        const auto read_span = std::span(ciphertext_read_buf).subspan(offset, fill_size);
 | 
				
			||||||
        const auto [actual, err] = socket_->Recv(0, read_span);
 | 
					        const auto [actual, err] = socket->Recv(0, read_span);
 | 
				
			||||||
        switch (err) {
 | 
					        switch (err) {
 | 
				
			||||||
        case Network::Errno::SUCCESS:
 | 
					        case Network::Errno::SUCCESS:
 | 
				
			||||||
            ASSERT(static_cast<size_t>(actual) <= fill_size);
 | 
					            ASSERT(static_cast<size_t>(actual) <= fill_size);
 | 
				
			||||||
            ciphertext_read_buf_.resize(offset + actual);
 | 
					            ciphertext_read_buf.resize(offset + actual);
 | 
				
			||||||
            return ResultSuccess;
 | 
					            return ResultSuccess;
 | 
				
			||||||
        case Network::Errno::AGAIN:
 | 
					        case Network::Errno::AGAIN:
 | 
				
			||||||
            ciphertext_read_buf_.resize(offset);
 | 
					            ciphertext_read_buf.resize(offset);
 | 
				
			||||||
            return ResultWouldBlock;
 | 
					            return ResultWouldBlock;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            ciphertext_read_buf_.resize(offset);
 | 
					            ciphertext_read_buf.resize(offset);
 | 
				
			||||||
            LOG_ERROR(Service_SSL, "Socket recv returned Network::Errno {}", err);
 | 
					            LOG_ERROR(Service_SSL, "Socket recv returned Network::Errno {}", err);
 | 
				
			||||||
            return ResultInternalError;
 | 
					            return ResultInternalError;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -146,13 +152,13 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Returns success if the write buffer has been completely emptied.
 | 
					    // Returns success if the write buffer has been completely emptied.
 | 
				
			||||||
    Result FlushCiphertextWriteBuf() {
 | 
					    Result FlushCiphertextWriteBuf() {
 | 
				
			||||||
        while (!ciphertext_write_buf_.empty()) {
 | 
					        while (!ciphertext_write_buf.empty()) {
 | 
				
			||||||
            const auto [actual, err] = socket_->Send(ciphertext_write_buf_, 0);
 | 
					            const auto [actual, err] = socket->Send(ciphertext_write_buf, 0);
 | 
				
			||||||
            switch (err) {
 | 
					            switch (err) {
 | 
				
			||||||
            case Network::Errno::SUCCESS:
 | 
					            case Network::Errno::SUCCESS:
 | 
				
			||||||
                ASSERT(static_cast<size_t>(actual) <= ciphertext_write_buf_.size());
 | 
					                ASSERT(static_cast<size_t>(actual) <= ciphertext_write_buf.size());
 | 
				
			||||||
                ciphertext_write_buf_.erase(ciphertext_write_buf_.begin(),
 | 
					                ciphertext_write_buf.erase(ciphertext_write_buf.begin(),
 | 
				
			||||||
                                            ciphertext_write_buf_.begin() + actual);
 | 
					                                           ciphertext_write_buf.begin() + actual);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case Network::Errno::AGAIN:
 | 
					            case Network::Errno::AGAIN:
 | 
				
			||||||
                return ResultWouldBlock;
 | 
					                return ResultWouldBlock;
 | 
				
			||||||
@@ -175,9 +181,9 @@ public:
 | 
				
			|||||||
            // only used if `initial_call_done`
 | 
					            // only used if `initial_call_done`
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // [0]
 | 
					                // [0]
 | 
				
			||||||
                .cbBuffer = static_cast<unsigned long>(ciphertext_read_buf_.size()),
 | 
					                .cbBuffer = static_cast<unsigned long>(ciphertext_read_buf.size()),
 | 
				
			||||||
                .BufferType = SECBUFFER_TOKEN,
 | 
					                .BufferType = SECBUFFER_TOKEN,
 | 
				
			||||||
                .pvBuffer = ciphertext_read_buf_.data(),
 | 
					                .pvBuffer = ciphertext_read_buf.data(),
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // [1] (will be replaced by SECBUFFER_MISSING when SEC_E_INCOMPLETE_MESSAGE is
 | 
					                // [1] (will be replaced by SECBUFFER_MISSING when SEC_E_INCOMPLETE_MESSAGE is
 | 
				
			||||||
@@ -211,30 +217,30 @@ public:
 | 
				
			|||||||
            .pBuffers = output_buffers.data(),
 | 
					            .pBuffers = output_buffers.data(),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        ASSERT_OR_EXECUTE_MSG(
 | 
					        ASSERT_OR_EXECUTE_MSG(
 | 
				
			||||||
            input_buffers[0].cbBuffer == ciphertext_read_buf_.size(),
 | 
					            input_buffers[0].cbBuffer == ciphertext_read_buf.size(),
 | 
				
			||||||
            { return ResultInternalError; }, "read buffer too large");
 | 
					            { return ResultInternalError; }, "read buffer too large");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool initial_call_done = handshake_state_ != HandshakeState::Initial;
 | 
					        bool initial_call_done = handshake_state != HandshakeState::Initial;
 | 
				
			||||||
        if (initial_call_done) {
 | 
					        if (initial_call_done) {
 | 
				
			||||||
            LOG_DEBUG(Service_SSL, "Passing {} bytes into InitializeSecurityContext",
 | 
					            LOG_DEBUG(Service_SSL, "Passing {} bytes into InitializeSecurityContext",
 | 
				
			||||||
                      ciphertext_read_buf_.size());
 | 
					                      ciphertext_read_buf.size());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const SECURITY_STATUS ret =
 | 
					        const SECURITY_STATUS ret =
 | 
				
			||||||
            InitializeSecurityContextA(&cred_handle, initial_call_done ? &ctxt_ : nullptr,
 | 
					            InitializeSecurityContextA(&cred_handle, initial_call_done ? &ctxt : nullptr,
 | 
				
			||||||
                                       // Caller ensured we have set a hostname:
 | 
					                                       // Caller ensured we have set a hostname:
 | 
				
			||||||
                                       const_cast<char*>(hostname_.value().c_str()), req,
 | 
					                                       const_cast<char*>(hostname.value().c_str()), req,
 | 
				
			||||||
                                       0, // Reserved1
 | 
					                                       0, // Reserved1
 | 
				
			||||||
                                       0, // TargetDataRep not used with Schannel
 | 
					                                       0, // TargetDataRep not used with Schannel
 | 
				
			||||||
                                       initial_call_done ? &input_desc : nullptr,
 | 
					                                       initial_call_done ? &input_desc : nullptr,
 | 
				
			||||||
                                       0, // Reserved2
 | 
					                                       0, // Reserved2
 | 
				
			||||||
                                       initial_call_done ? nullptr : &ctxt_, &output_desc, &attr,
 | 
					                                       initial_call_done ? nullptr : &ctxt, &output_desc, &attr,
 | 
				
			||||||
                                       nullptr); // ptsExpiry
 | 
					                                       nullptr); // ptsExpiry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (output_buffers[0].pvBuffer) {
 | 
					        if (output_buffers[0].pvBuffer) {
 | 
				
			||||||
            const std::span span(static_cast<u8*>(output_buffers[0].pvBuffer),
 | 
					            const std::span span(static_cast<u8*>(output_buffers[0].pvBuffer),
 | 
				
			||||||
                                 output_buffers[0].cbBuffer);
 | 
					                                 output_buffers[0].cbBuffer);
 | 
				
			||||||
            ciphertext_write_buf_.insert(ciphertext_write_buf_.end(), span.begin(), span.end());
 | 
					            ciphertext_write_buf.insert(ciphertext_write_buf.end(), span.begin(), span.end());
 | 
				
			||||||
            FreeContextBuffer(output_buffers[0].pvBuffer);
 | 
					            FreeContextBuffer(output_buffers[0].pvBuffer);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -251,64 +257,64 @@ public:
 | 
				
			|||||||
            LOG_DEBUG(Service_SSL, "InitializeSecurityContext => SEC_I_CONTINUE_NEEDED");
 | 
					            LOG_DEBUG(Service_SSL, "InitializeSecurityContext => SEC_I_CONTINUE_NEEDED");
 | 
				
			||||||
            if (input_buffers[1].BufferType == SECBUFFER_EXTRA) {
 | 
					            if (input_buffers[1].BufferType == SECBUFFER_EXTRA) {
 | 
				
			||||||
                LOG_DEBUG(Service_SSL, "EXTRA of size {}", input_buffers[1].cbBuffer);
 | 
					                LOG_DEBUG(Service_SSL, "EXTRA of size {}", input_buffers[1].cbBuffer);
 | 
				
			||||||
                ASSERT(input_buffers[1].cbBuffer <= ciphertext_read_buf_.size());
 | 
					                ASSERT(input_buffers[1].cbBuffer <= ciphertext_read_buf.size());
 | 
				
			||||||
                ciphertext_read_buf_.erase(ciphertext_read_buf_.begin(),
 | 
					                ciphertext_read_buf.erase(ciphertext_read_buf.begin(),
 | 
				
			||||||
                                           ciphertext_read_buf_.end() - input_buffers[1].cbBuffer);
 | 
					                                          ciphertext_read_buf.end() - input_buffers[1].cbBuffer);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                ASSERT(input_buffers[1].BufferType == SECBUFFER_EMPTY);
 | 
					                ASSERT(input_buffers[1].BufferType == SECBUFFER_EMPTY);
 | 
				
			||||||
                ciphertext_read_buf_.clear();
 | 
					                ciphertext_read_buf.clear();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            handshake_state_ = HandshakeState::ContinueNeeded;
 | 
					            handshake_state = HandshakeState::ContinueNeeded;
 | 
				
			||||||
            return ResultSuccess;
 | 
					            return ResultSuccess;
 | 
				
			||||||
        case SEC_E_INCOMPLETE_MESSAGE:
 | 
					        case SEC_E_INCOMPLETE_MESSAGE:
 | 
				
			||||||
            LOG_DEBUG(Service_SSL, "InitializeSecurityContext => SEC_E_INCOMPLETE_MESSAGE");
 | 
					            LOG_DEBUG(Service_SSL, "InitializeSecurityContext => SEC_E_INCOMPLETE_MESSAGE");
 | 
				
			||||||
            ASSERT(input_buffers[1].BufferType == SECBUFFER_MISSING);
 | 
					            ASSERT(input_buffers[1].BufferType == SECBUFFER_MISSING);
 | 
				
			||||||
            read_buf_fill_size_ = input_buffers[1].cbBuffer;
 | 
					            read_buf_fill_size = input_buffers[1].cbBuffer;
 | 
				
			||||||
            handshake_state_ = HandshakeState::IncompleteMessage;
 | 
					            handshake_state = HandshakeState::IncompleteMessage;
 | 
				
			||||||
            return ResultSuccess;
 | 
					            return ResultSuccess;
 | 
				
			||||||
        case SEC_E_OK:
 | 
					        case SEC_E_OK:
 | 
				
			||||||
            LOG_DEBUG(Service_SSL, "InitializeSecurityContext => SEC_E_OK");
 | 
					            LOG_DEBUG(Service_SSL, "InitializeSecurityContext => SEC_E_OK");
 | 
				
			||||||
            ciphertext_read_buf_.clear();
 | 
					            ciphertext_read_buf.clear();
 | 
				
			||||||
            handshake_state_ = HandshakeState::DoneAfterFlush;
 | 
					            handshake_state = HandshakeState::DoneAfterFlush;
 | 
				
			||||||
            return GrabStreamSizes();
 | 
					            return GrabStreamSizes();
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            LOG_ERROR(Service_SSL,
 | 
					            LOG_ERROR(Service_SSL,
 | 
				
			||||||
                      "InitializeSecurityContext failed (probably certificate/protocol issue): {}",
 | 
					                      "InitializeSecurityContext failed (probably certificate/protocol issue): {}",
 | 
				
			||||||
                      Common::NativeErrorToString(ret));
 | 
					                      Common::NativeErrorToString(ret));
 | 
				
			||||||
            handshake_state_ = HandshakeState::Error;
 | 
					            handshake_state = HandshakeState::Error;
 | 
				
			||||||
            return ResultInternalError;
 | 
					            return ResultInternalError;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Result GrabStreamSizes() {
 | 
					    Result GrabStreamSizes() {
 | 
				
			||||||
        const SECURITY_STATUS ret =
 | 
					        const SECURITY_STATUS ret =
 | 
				
			||||||
            QueryContextAttributes(&ctxt_, SECPKG_ATTR_STREAM_SIZES, &stream_sizes_);
 | 
					            QueryContextAttributes(&ctxt, SECPKG_ATTR_STREAM_SIZES, &stream_sizes);
 | 
				
			||||||
        if (ret != SEC_E_OK) {
 | 
					        if (ret != SEC_E_OK) {
 | 
				
			||||||
            LOG_ERROR(Service_SSL, "QueryContextAttributes(SECPKG_ATTR_STREAM_SIZES) failed: {}",
 | 
					            LOG_ERROR(Service_SSL, "QueryContextAttributes(SECPKG_ATTR_STREAM_SIZES) failed: {}",
 | 
				
			||||||
                      Common::NativeErrorToString(ret));
 | 
					                      Common::NativeErrorToString(ret));
 | 
				
			||||||
            handshake_state_ = HandshakeState::Error;
 | 
					            handshake_state = HandshakeState::Error;
 | 
				
			||||||
            return ResultInternalError;
 | 
					            return ResultInternalError;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return ResultSuccess;
 | 
					        return ResultSuccess;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultVal<size_t> Read(std::span<u8> data) override {
 | 
					    ResultVal<size_t> Read(std::span<u8> data) override {
 | 
				
			||||||
        if (handshake_state_ != HandshakeState::Connected) {
 | 
					        if (handshake_state != HandshakeState::Connected) {
 | 
				
			||||||
            LOG_ERROR(Service_SSL, "Called Read but we did not successfully handshake");
 | 
					            LOG_ERROR(Service_SSL, "Called Read but we did not successfully handshake");
 | 
				
			||||||
            return ResultInternalError;
 | 
					            return ResultInternalError;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (data.size() == 0 || got_read_eof_) {
 | 
					        if (data.size() == 0 || got_read_eof) {
 | 
				
			||||||
            return size_t(0);
 | 
					            return size_t(0);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        while (1) {
 | 
					        while (1) {
 | 
				
			||||||
            if (!cleartext_read_buf_.empty()) {
 | 
					            if (!cleartext_read_buf.empty()) {
 | 
				
			||||||
                const size_t read_size = std::min(cleartext_read_buf_.size(), data.size());
 | 
					                const size_t read_size = std::min(cleartext_read_buf.size(), data.size());
 | 
				
			||||||
                std::memcpy(data.data(), cleartext_read_buf_.data(), read_size);
 | 
					                std::memcpy(data.data(), cleartext_read_buf.data(), read_size);
 | 
				
			||||||
                cleartext_read_buf_.erase(cleartext_read_buf_.begin(),
 | 
					                cleartext_read_buf.erase(cleartext_read_buf.begin(),
 | 
				
			||||||
                                          cleartext_read_buf_.begin() + read_size);
 | 
					                                         cleartext_read_buf.begin() + read_size);
 | 
				
			||||||
                return read_size;
 | 
					                return read_size;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (!ciphertext_read_buf_.empty()) {
 | 
					            if (!ciphertext_read_buf.empty()) {
 | 
				
			||||||
                SecBuffer empty{
 | 
					                SecBuffer empty{
 | 
				
			||||||
                    .cbBuffer = 0,
 | 
					                    .cbBuffer = 0,
 | 
				
			||||||
                    .BufferType = SECBUFFER_EMPTY,
 | 
					                    .BufferType = SECBUFFER_EMPTY,
 | 
				
			||||||
@@ -316,16 +322,16 @@ public:
 | 
				
			|||||||
                };
 | 
					                };
 | 
				
			||||||
                std::array<SecBuffer, 5> buffers{{
 | 
					                std::array<SecBuffer, 5> buffers{{
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        .cbBuffer = static_cast<unsigned long>(ciphertext_read_buf_.size()),
 | 
					                        .cbBuffer = static_cast<unsigned long>(ciphertext_read_buf.size()),
 | 
				
			||||||
                        .BufferType = SECBUFFER_DATA,
 | 
					                        .BufferType = SECBUFFER_DATA,
 | 
				
			||||||
                        .pvBuffer = ciphertext_read_buf_.data(),
 | 
					                        .pvBuffer = ciphertext_read_buf.data(),
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    empty,
 | 
					                    empty,
 | 
				
			||||||
                    empty,
 | 
					                    empty,
 | 
				
			||||||
                    empty,
 | 
					                    empty,
 | 
				
			||||||
                }};
 | 
					                }};
 | 
				
			||||||
                ASSERT_OR_EXECUTE_MSG(
 | 
					                ASSERT_OR_EXECUTE_MSG(
 | 
				
			||||||
                    buffers[0].cbBuffer == ciphertext_read_buf_.size(),
 | 
					                    buffers[0].cbBuffer == ciphertext_read_buf.size(),
 | 
				
			||||||
                    { return ResultInternalError; }, "read buffer too large");
 | 
					                    { return ResultInternalError; }, "read buffer too large");
 | 
				
			||||||
                SecBufferDesc desc{
 | 
					                SecBufferDesc desc{
 | 
				
			||||||
                    .ulVersion = SECBUFFER_VERSION,
 | 
					                    .ulVersion = SECBUFFER_VERSION,
 | 
				
			||||||
@@ -333,7 +339,7 @@ public:
 | 
				
			|||||||
                    .pBuffers = buffers.data(),
 | 
					                    .pBuffers = buffers.data(),
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                SECURITY_STATUS ret =
 | 
					                SECURITY_STATUS ret =
 | 
				
			||||||
                    DecryptMessage(&ctxt_, &desc, /*MessageSeqNo*/ 0, /*pfQOP*/ nullptr);
 | 
					                    DecryptMessage(&ctxt, &desc, /*MessageSeqNo*/ 0, /*pfQOP*/ nullptr);
 | 
				
			||||||
                switch (ret) {
 | 
					                switch (ret) {
 | 
				
			||||||
                case SEC_E_OK:
 | 
					                case SEC_E_OK:
 | 
				
			||||||
                    ASSERT_OR_EXECUTE(buffers[0].BufferType == SECBUFFER_STREAM_HEADER,
 | 
					                    ASSERT_OR_EXECUTE(buffers[0].BufferType == SECBUFFER_STREAM_HEADER,
 | 
				
			||||||
@@ -342,24 +348,23 @@ public:
 | 
				
			|||||||
                                      { return ResultInternalError; });
 | 
					                                      { return ResultInternalError; });
 | 
				
			||||||
                    ASSERT_OR_EXECUTE(buffers[2].BufferType == SECBUFFER_STREAM_TRAILER,
 | 
					                    ASSERT_OR_EXECUTE(buffers[2].BufferType == SECBUFFER_STREAM_TRAILER,
 | 
				
			||||||
                                      { return ResultInternalError; });
 | 
					                                      { return ResultInternalError; });
 | 
				
			||||||
                    cleartext_read_buf_.assign(static_cast<u8*>(buffers[1].pvBuffer),
 | 
					                    cleartext_read_buf.assign(static_cast<u8*>(buffers[1].pvBuffer),
 | 
				
			||||||
                                               static_cast<u8*>(buffers[1].pvBuffer) +
 | 
					                                              static_cast<u8*>(buffers[1].pvBuffer) +
 | 
				
			||||||
                                                   buffers[1].cbBuffer);
 | 
					                                                  buffers[1].cbBuffer);
 | 
				
			||||||
                    if (buffers[3].BufferType == SECBUFFER_EXTRA) {
 | 
					                    if (buffers[3].BufferType == SECBUFFER_EXTRA) {
 | 
				
			||||||
                        ASSERT(buffers[3].cbBuffer <= ciphertext_read_buf_.size());
 | 
					                        ASSERT(buffers[3].cbBuffer <= ciphertext_read_buf.size());
 | 
				
			||||||
                        ciphertext_read_buf_.erase(ciphertext_read_buf_.begin(),
 | 
					                        ciphertext_read_buf.erase(ciphertext_read_buf.begin(),
 | 
				
			||||||
                                                   ciphertext_read_buf_.end() -
 | 
					                                                  ciphertext_read_buf.end() - buffers[3].cbBuffer);
 | 
				
			||||||
                                                       buffers[3].cbBuffer);
 | 
					 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        ASSERT(buffers[3].BufferType == SECBUFFER_EMPTY);
 | 
					                        ASSERT(buffers[3].BufferType == SECBUFFER_EMPTY);
 | 
				
			||||||
                        ciphertext_read_buf_.clear();
 | 
					                        ciphertext_read_buf.clear();
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                case SEC_E_INCOMPLETE_MESSAGE:
 | 
					                case SEC_E_INCOMPLETE_MESSAGE:
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                case SEC_I_CONTEXT_EXPIRED:
 | 
					                case SEC_I_CONTEXT_EXPIRED:
 | 
				
			||||||
                    // Server hung up by sending close_notify.
 | 
					                    // Server hung up by sending close_notify.
 | 
				
			||||||
                    got_read_eof_ = true;
 | 
					                    got_read_eof = true;
 | 
				
			||||||
                    return size_t(0);
 | 
					                    return size_t(0);
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    LOG_ERROR(Service_SSL, "DecryptMessage failed: {}",
 | 
					                    LOG_ERROR(Service_SSL, "DecryptMessage failed: {}",
 | 
				
			||||||
@@ -371,43 +376,43 @@ public:
 | 
				
			|||||||
            if (r != ResultSuccess) {
 | 
					            if (r != ResultSuccess) {
 | 
				
			||||||
                return r;
 | 
					                return r;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (ciphertext_read_buf_.empty()) {
 | 
					            if (ciphertext_read_buf.empty()) {
 | 
				
			||||||
                got_read_eof_ = true;
 | 
					                got_read_eof = true;
 | 
				
			||||||
                return size_t(0);
 | 
					                return size_t(0);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultVal<size_t> Write(std::span<const u8> data) override {
 | 
					    ResultVal<size_t> Write(std::span<const u8> data) override {
 | 
				
			||||||
        if (handshake_state_ != HandshakeState::Connected) {
 | 
					        if (handshake_state != HandshakeState::Connected) {
 | 
				
			||||||
            LOG_ERROR(Service_SSL, "Called Write but we did not successfully handshake");
 | 
					            LOG_ERROR(Service_SSL, "Called Write but we did not successfully handshake");
 | 
				
			||||||
            return ResultInternalError;
 | 
					            return ResultInternalError;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (data.size() == 0) {
 | 
					        if (data.size() == 0) {
 | 
				
			||||||
            return size_t(0);
 | 
					            return size_t(0);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        data = data.subspan(0, std::min<size_t>(data.size(), stream_sizes_.cbMaximumMessage));
 | 
					        data = data.subspan(0, std::min<size_t>(data.size(), stream_sizes.cbMaximumMessage));
 | 
				
			||||||
        if (!cleartext_write_buf_.empty()) {
 | 
					        if (!cleartext_write_buf.empty()) {
 | 
				
			||||||
            // Already in the middle of a write.  It wouldn't make sense to not
 | 
					            // Already in the middle of a write.  It wouldn't make sense to not
 | 
				
			||||||
            // finish sending the entire buffer since TLS has
 | 
					            // finish sending the entire buffer since TLS has
 | 
				
			||||||
            // header/MAC/padding/etc.
 | 
					            // header/MAC/padding/etc.
 | 
				
			||||||
            if (data.size() != cleartext_write_buf_.size() ||
 | 
					            if (data.size() != cleartext_write_buf.size() ||
 | 
				
			||||||
                std::memcmp(data.data(), cleartext_write_buf_.data(), data.size())) {
 | 
					                std::memcmp(data.data(), cleartext_write_buf.data(), data.size())) {
 | 
				
			||||||
                LOG_ERROR(Service_SSL, "Called Write but buffer does not match previous buffer");
 | 
					                LOG_ERROR(Service_SSL, "Called Write but buffer does not match previous buffer");
 | 
				
			||||||
                return ResultInternalError;
 | 
					                return ResultInternalError;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return WriteAlreadyEncryptedData();
 | 
					            return WriteAlreadyEncryptedData();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            cleartext_write_buf_.assign(data.begin(), data.end());
 | 
					            cleartext_write_buf.assign(data.begin(), data.end());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::vector<u8> header_buf(stream_sizes_.cbHeader, 0);
 | 
					        std::vector<u8> header_buf(stream_sizes.cbHeader, 0);
 | 
				
			||||||
        std::vector<u8> tmp_data_buf = cleartext_write_buf_;
 | 
					        std::vector<u8> tmp_data_buf = cleartext_write_buf;
 | 
				
			||||||
        std::vector<u8> trailer_buf(stream_sizes_.cbTrailer, 0);
 | 
					        std::vector<u8> trailer_buf(stream_sizes.cbTrailer, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::array<SecBuffer, 3> buffers{{
 | 
					        std::array<SecBuffer, 3> buffers{{
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                .cbBuffer = stream_sizes_.cbHeader,
 | 
					                .cbBuffer = stream_sizes.cbHeader,
 | 
				
			||||||
                .BufferType = SECBUFFER_STREAM_HEADER,
 | 
					                .BufferType = SECBUFFER_STREAM_HEADER,
 | 
				
			||||||
                .pvBuffer = header_buf.data(),
 | 
					                .pvBuffer = header_buf.data(),
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
@@ -417,7 +422,7 @@ public:
 | 
				
			|||||||
                .pvBuffer = tmp_data_buf.data(),
 | 
					                .pvBuffer = tmp_data_buf.data(),
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                .cbBuffer = stream_sizes_.cbTrailer,
 | 
					                .cbBuffer = stream_sizes.cbTrailer,
 | 
				
			||||||
                .BufferType = SECBUFFER_STREAM_TRAILER,
 | 
					                .BufferType = SECBUFFER_STREAM_TRAILER,
 | 
				
			||||||
                .pvBuffer = trailer_buf.data(),
 | 
					                .pvBuffer = trailer_buf.data(),
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
@@ -431,17 +436,17 @@ public:
 | 
				
			|||||||
            .pBuffers = buffers.data(),
 | 
					            .pBuffers = buffers.data(),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const SECURITY_STATUS ret = EncryptMessage(&ctxt_, /*fQOP*/ 0, &desc, /*MessageSeqNo*/ 0);
 | 
					        const SECURITY_STATUS ret = EncryptMessage(&ctxt, /*fQOP*/ 0, &desc, /*MessageSeqNo*/ 0);
 | 
				
			||||||
        if (ret != SEC_E_OK) {
 | 
					        if (ret != SEC_E_OK) {
 | 
				
			||||||
            LOG_ERROR(Service_SSL, "EncryptMessage failed: {}", Common::NativeErrorToString(ret));
 | 
					            LOG_ERROR(Service_SSL, "EncryptMessage failed: {}", Common::NativeErrorToString(ret));
 | 
				
			||||||
            return ResultInternalError;
 | 
					            return ResultInternalError;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ciphertext_write_buf_.insert(ciphertext_write_buf_.end(), header_buf.begin(),
 | 
					        ciphertext_write_buf.insert(ciphertext_write_buf.end(), header_buf.begin(),
 | 
				
			||||||
                                     header_buf.end());
 | 
					                                    header_buf.end());
 | 
				
			||||||
        ciphertext_write_buf_.insert(ciphertext_write_buf_.end(), tmp_data_buf.begin(),
 | 
					        ciphertext_write_buf.insert(ciphertext_write_buf.end(), tmp_data_buf.begin(),
 | 
				
			||||||
                                     tmp_data_buf.end());
 | 
					                                    tmp_data_buf.end());
 | 
				
			||||||
        ciphertext_write_buf_.insert(ciphertext_write_buf_.end(), trailer_buf.begin(),
 | 
					        ciphertext_write_buf.insert(ciphertext_write_buf.end(), trailer_buf.begin(),
 | 
				
			||||||
                                     trailer_buf.end());
 | 
					                                    trailer_buf.end());
 | 
				
			||||||
        return WriteAlreadyEncryptedData();
 | 
					        return WriteAlreadyEncryptedData();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -451,15 +456,15 @@ public:
 | 
				
			|||||||
            return r;
 | 
					            return r;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // write buf is empty
 | 
					        // write buf is empty
 | 
				
			||||||
        const size_t cleartext_bytes_written = cleartext_write_buf_.size();
 | 
					        const size_t cleartext_bytes_written = cleartext_write_buf.size();
 | 
				
			||||||
        cleartext_write_buf_.clear();
 | 
					        cleartext_write_buf.clear();
 | 
				
			||||||
        return cleartext_bytes_written;
 | 
					        return cleartext_bytes_written;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override {
 | 
					    ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override {
 | 
				
			||||||
        PCCERT_CONTEXT returned_cert = nullptr;
 | 
					        PCCERT_CONTEXT returned_cert = nullptr;
 | 
				
			||||||
        const SECURITY_STATUS ret =
 | 
					        const SECURITY_STATUS ret =
 | 
				
			||||||
            QueryContextAttributes(&ctxt_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &returned_cert);
 | 
					            QueryContextAttributes(&ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &returned_cert);
 | 
				
			||||||
        if (ret != SEC_E_OK) {
 | 
					        if (ret != SEC_E_OK) {
 | 
				
			||||||
            LOG_ERROR(Service_SSL,
 | 
					            LOG_ERROR(Service_SSL,
 | 
				
			||||||
                      "QueryContextAttributes(SECPKG_ATTR_REMOTE_CERT_CONTEXT) failed: {}",
 | 
					                      "QueryContextAttributes(SECPKG_ATTR_REMOTE_CERT_CONTEXT) failed: {}",
 | 
				
			||||||
@@ -480,8 +485,8 @@ public:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ~SSLConnectionBackendSchannel() {
 | 
					    ~SSLConnectionBackendSchannel() {
 | 
				
			||||||
        if (handshake_state_ != HandshakeState::Initial) {
 | 
					        if (handshake_state != HandshakeState::Initial) {
 | 
				
			||||||
            DeleteSecurityContext(&ctxt_);
 | 
					            DeleteSecurityContext(&ctxt);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -509,21 +514,21 @@ public:
 | 
				
			|||||||
        // Another error was returned and we shouldn't allow initialization
 | 
					        // Another error was returned and we shouldn't allow initialization
 | 
				
			||||||
        // to continue.
 | 
					        // to continue.
 | 
				
			||||||
        Error,
 | 
					        Error,
 | 
				
			||||||
    } handshake_state_ = HandshakeState::Initial;
 | 
					    } handshake_state = HandshakeState::Initial;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CtxtHandle ctxt_;
 | 
					    CtxtHandle ctxt;
 | 
				
			||||||
    SecPkgContext_StreamSizes stream_sizes_;
 | 
					    SecPkgContext_StreamSizes stream_sizes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::shared_ptr<Network::SocketBase> socket_;
 | 
					    std::shared_ptr<Network::SocketBase> socket;
 | 
				
			||||||
    std::optional<std::string> hostname_;
 | 
					    std::optional<std::string> hostname;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::vector<u8> ciphertext_read_buf_;
 | 
					    std::vector<u8> ciphertext_read_buf;
 | 
				
			||||||
    std::vector<u8> ciphertext_write_buf_;
 | 
					    std::vector<u8> ciphertext_write_buf;
 | 
				
			||||||
    std::vector<u8> cleartext_read_buf_;
 | 
					    std::vector<u8> cleartext_read_buf;
 | 
				
			||||||
    std::vector<u8> cleartext_write_buf_;
 | 
					    std::vector<u8> cleartext_write_buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool got_read_eof_ = false;
 | 
					    bool got_read_eof = false;
 | 
				
			||||||
    size_t read_buf_fill_size_ = 0;
 | 
					    size_t read_buf_fill_size = 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {
 | 
					ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -570,10 +570,10 @@ Socket::Socket(Socket&& rhs) noexcept {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <typename T>
 | 
					template <typename T>
 | 
				
			||||||
std::pair<T, Errno> Socket::GetSockOpt(SOCKET fd_, int option) {
 | 
					std::pair<T, Errno> Socket::GetSockOpt(SOCKET fd_so, int option) {
 | 
				
			||||||
    T value{};
 | 
					    T value{};
 | 
				
			||||||
    socklen_t len = sizeof(value);
 | 
					    socklen_t len = sizeof(value);
 | 
				
			||||||
    const int result = getsockopt(fd_, SOL_SOCKET, option, reinterpret_cast<char*>(&value), &len);
 | 
					    const int result = getsockopt(fd_so, SOL_SOCKET, option, reinterpret_cast<char*>(&value), &len);
 | 
				
			||||||
    if (result != SOCKET_ERROR) {
 | 
					    if (result != SOCKET_ERROR) {
 | 
				
			||||||
        ASSERT(len == sizeof(value));
 | 
					        ASSERT(len == sizeof(value));
 | 
				
			||||||
        return {value, Errno::SUCCESS};
 | 
					        return {value, Errno::SUCCESS};
 | 
				
			||||||
@@ -582,9 +582,9 @@ std::pair<T, Errno> Socket::GetSockOpt(SOCKET fd_, int option) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <typename T>
 | 
					template <typename T>
 | 
				
			||||||
Errno Socket::SetSockOpt(SOCKET fd_, int option, T value) {
 | 
					Errno Socket::SetSockOpt(SOCKET fd_so, int option, T value) {
 | 
				
			||||||
    const int result =
 | 
					    const int result =
 | 
				
			||||||
        setsockopt(fd_, SOL_SOCKET, option, reinterpret_cast<const char*>(&value), sizeof(value));
 | 
					        setsockopt(fd_so, SOL_SOCKET, option, reinterpret_cast<const char*>(&value), sizeof(value));
 | 
				
			||||||
    if (result != SOCKET_ERROR) {
 | 
					    if (result != SOCKET_ERROR) {
 | 
				
			||||||
        return Errno::SUCCESS;
 | 
					        return Errno::SUCCESS;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user