Apply suggestions
This commit is contained in:
parent
13418013a4
commit
b8c3f0648b
@ -65,13 +65,6 @@ const ResultCode ERROR_WRONG_CERT_HANDLE = // 0xD8A0A0C9
|
||||
const ResultCode ERROR_CERT_ALREADY_SET = // 0xD8A0A03D
|
||||
ResultCode(61, ErrorModule::HTTP, ErrorSummary::InvalidState, ErrorLevel::Permanent);
|
||||
|
||||
struct URLInfo {
|
||||
bool is_https;
|
||||
std::string host;
|
||||
int port;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
// Splits URL into its components. Example: https://citra-emu.org:443/index.html
|
||||
// is_https: true; host: citra-emu.org; port: 443; path: /index.html
|
||||
static URLInfo SplitUrl(const std::string& url) {
|
||||
@ -166,7 +159,6 @@ void Context::MakeRequest() {
|
||||
URLInfo url_info = SplitUrl(url);
|
||||
|
||||
httplib::Request request;
|
||||
httplib::Error error{-1};
|
||||
std::vector<Context::RequestHeader> pending_headers;
|
||||
request.method = request_method_strings.at(method);
|
||||
request.path = url_info.path;
|
||||
@ -178,11 +170,6 @@ void Context::MakeRequest() {
|
||||
return true;
|
||||
};
|
||||
|
||||
auto header_writter = [&pending_headers](httplib::Stream& strm,
|
||||
httplib::Headers& httplib_headers) {
|
||||
return HandleHeaderWrite(pending_headers, strm, httplib_headers);
|
||||
};
|
||||
|
||||
for (const auto& header : headers) {
|
||||
pending_headers.push_back(header);
|
||||
}
|
||||
@ -200,59 +187,67 @@ void Context::MakeRequest() {
|
||||
|
||||
state = RequestState::InProgress;
|
||||
|
||||
// Sadly, we have to duplicate code, the class hierarchy in httplib is not very useful...
|
||||
if (url_info.is_https) {
|
||||
X509* cert = nullptr;
|
||||
EVP_PKEY* key = nullptr;
|
||||
{
|
||||
std::unique_ptr<httplib::SSLClient> client;
|
||||
if (uses_default_client_cert) {
|
||||
const unsigned char* tmpCertPtr = clcert_data->certificate.data();
|
||||
const unsigned char* tmpKeyPtr = clcert_data->private_key.data();
|
||||
cert = d2i_X509(nullptr, &tmpCertPtr, (long)clcert_data->certificate.size());
|
||||
key = d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &tmpKeyPtr,
|
||||
(long)clcert_data->private_key.size());
|
||||
client =
|
||||
std::make_unique<httplib::SSLClient>(url_info.host, url_info.port, cert, key);
|
||||
} else if (auto client_cert = ssl_config.client_cert_ctx.lock()) {
|
||||
const unsigned char* tmpCertPtr = client_cert->certificate.data();
|
||||
const unsigned char* tmpKeyPtr = client_cert->private_key.data();
|
||||
cert = d2i_X509(nullptr, &tmpCertPtr, (long)client_cert->certificate.size());
|
||||
key = d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &tmpKeyPtr,
|
||||
(long)client_cert->private_key.size());
|
||||
client =
|
||||
std::make_unique<httplib::SSLClient>(url_info.host, url_info.port, cert, key);
|
||||
} else {
|
||||
client = std::make_unique<httplib::SSLClient>(url_info.host, url_info.port);
|
||||
}
|
||||
|
||||
// TODO(B3N30): Check for SSLOptions-Bits and set the verify method accordingly
|
||||
// https://www.3dbrew.org/wiki/SSL_Services#SSLOpt
|
||||
// Hack: Since for now RootCerts are not implemented we set the VerifyMode to None.
|
||||
client->enable_server_certificate_verification(false);
|
||||
|
||||
client->set_header_writer(header_writter);
|
||||
|
||||
if (!client->send(request, response, error)) {
|
||||
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
||||
state = RequestState::TimedOut;
|
||||
} else {
|
||||
LOG_DEBUG(Service_HTTP, "Request successful");
|
||||
// TODO(B3N30): Verify this state on HW
|
||||
state = RequestState::ReadyToDownloadContent;
|
||||
}
|
||||
}
|
||||
if (cert) {
|
||||
X509_free(cert);
|
||||
}
|
||||
if (key) {
|
||||
EVP_PKEY_free(key);
|
||||
}
|
||||
MakeRequestSSL(request, url_info, pending_headers);
|
||||
} else {
|
||||
std::unique_ptr<httplib::Client> client =
|
||||
std::make_unique<httplib::Client>(url_info.host, url_info.port);
|
||||
MakeRequestNonSSL(request, url_info, pending_headers);
|
||||
}
|
||||
}
|
||||
|
||||
client->set_header_writer(header_writter);
|
||||
void Context::MakeRequestNonSSL(httplib::Request& request, const URLInfo& url_info,
|
||||
std::vector<Context::RequestHeader>& pending_headers) {
|
||||
httplib::Error error{-1};
|
||||
std::unique_ptr<httplib::Client> client =
|
||||
std::make_unique<httplib::Client>(url_info.host, url_info.port);
|
||||
|
||||
client->set_header_writer(
|
||||
[&pending_headers](httplib::Stream& strm, httplib::Headers& httplib_headers) {
|
||||
return HandleHeaderWrite(pending_headers, strm, httplib_headers);
|
||||
});
|
||||
|
||||
if (!client->send(request, response, error)) {
|
||||
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
||||
state = RequestState::TimedOut;
|
||||
} else {
|
||||
LOG_DEBUG(Service_HTTP, "Request successful");
|
||||
// TODO(B3N30): Verify this state on HW
|
||||
state = RequestState::ReadyToDownloadContent;
|
||||
}
|
||||
}
|
||||
void Context::MakeRequestSSL(httplib::Request& request, const URLInfo& url_info,
|
||||
std::vector<Context::RequestHeader>& pending_headers) {
|
||||
httplib::Error error{-1};
|
||||
X509* cert = nullptr;
|
||||
EVP_PKEY* key = nullptr;
|
||||
{
|
||||
std::unique_ptr<httplib::SSLClient> client;
|
||||
if (uses_default_client_cert) {
|
||||
const unsigned char* tmpCertPtr = clcert_data->certificate.data();
|
||||
const unsigned char* tmpKeyPtr = clcert_data->private_key.data();
|
||||
cert = d2i_X509(nullptr, &tmpCertPtr, (long)clcert_data->certificate.size());
|
||||
key = d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &tmpKeyPtr,
|
||||
(long)clcert_data->private_key.size());
|
||||
client = std::make_unique<httplib::SSLClient>(url_info.host, url_info.port, cert, key);
|
||||
} else if (auto client_cert = ssl_config.client_cert_ctx.lock()) {
|
||||
const unsigned char* tmpCertPtr = client_cert->certificate.data();
|
||||
const unsigned char* tmpKeyPtr = client_cert->private_key.data();
|
||||
cert = d2i_X509(nullptr, &tmpCertPtr, (long)client_cert->certificate.size());
|
||||
key = d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &tmpKeyPtr,
|
||||
(long)client_cert->private_key.size());
|
||||
client = std::make_unique<httplib::SSLClient>(url_info.host, url_info.port, cert, key);
|
||||
} else {
|
||||
client = std::make_unique<httplib::SSLClient>(url_info.host, url_info.port);
|
||||
}
|
||||
|
||||
// TODO(B3N30): Check for SSLOptions-Bits and set the verify method accordingly
|
||||
// https://www.3dbrew.org/wiki/SSL_Services#SSLOpt
|
||||
// Hack: Since for now RootCerts are not implemented we set the VerifyMode to None.
|
||||
client->enable_server_certificate_verification(false);
|
||||
|
||||
client->set_header_writer(
|
||||
[&pending_headers](httplib::Stream& strm, httplib::Headers& httplib_headers) {
|
||||
return HandleHeaderWrite(pending_headers, strm, httplib_headers);
|
||||
});
|
||||
|
||||
if (!client->send(request, response, error)) {
|
||||
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
||||
@ -263,6 +258,12 @@ void Context::MakeRequest() {
|
||||
state = RequestState::ReadyToDownloadContent;
|
||||
}
|
||||
}
|
||||
if (cert) {
|
||||
X509_free(cert);
|
||||
}
|
||||
if (key) {
|
||||
EVP_PKEY_free(key);
|
||||
}
|
||||
}
|
||||
|
||||
void HTTP_C::Initialize(Kernel::HLERequestContext& ctx) {
|
||||
|
@ -61,6 +61,13 @@ enum class ClientCertID : u32 {
|
||||
Default = 0x40, // Default client cert
|
||||
};
|
||||
|
||||
struct URLInfo {
|
||||
bool is_https;
|
||||
std::string host;
|
||||
int port;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
/// Represents a client certificate along with its private key, stored as a byte array of DER data.
|
||||
/// There can only be at most one client certificate context attached to an HTTP context at any
|
||||
/// given time.
|
||||
@ -134,8 +141,6 @@ public:
|
||||
Context(const Context&) = delete;
|
||||
Context& operator=(const Context&) = delete;
|
||||
|
||||
void MakeRequest();
|
||||
|
||||
struct Proxy {
|
||||
std::string url;
|
||||
std::string username;
|
||||
@ -215,6 +220,12 @@ public:
|
||||
size_t current_copied_data;
|
||||
bool uses_default_client_cert{};
|
||||
httplib::Response response;
|
||||
|
||||
void MakeRequest();
|
||||
void MakeRequestNonSSL(httplib::Request& request, const URLInfo& url_info,
|
||||
std::vector<Context::RequestHeader>& pending_headers);
|
||||
void MakeRequestSSL(httplib::Request& request, const URLInfo& url_info,
|
||||
std::vector<Context::RequestHeader>& pending_headers);
|
||||
};
|
||||
|
||||
struct SessionData : public Kernel::SessionRequestHandler::SessionDataBase {
|
||||
|
Loading…
Reference in New Issue
Block a user