mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-02-20 15:40:56 +00:00
Prevent unauthorized access to the HTTPS server
This commit is contained in:
parent
a1f144db61
commit
c63029239f
@ -5,6 +5,29 @@
|
||||
#include <openssl/pem.h>
|
||||
#include "crypto.h"
|
||||
namespace crypto {
|
||||
cert_chain_t::cert_chain_t() : _certs {}, _cert_store {X509_STORE_new() }, _cert_ctx {X509_STORE_CTX_new() } {}
|
||||
void cert_chain_t::add(x509_t &&cert) {
|
||||
_certs.emplace_back(std::move(cert));
|
||||
|
||||
X509_STORE_add_cert(_cert_store.get(), _certs.back().get());
|
||||
}
|
||||
|
||||
const char *cert_chain_t::verify(x509_t::element_type *cert) {
|
||||
util::fail_guard([this]() {
|
||||
X509_STORE_CTX_cleanup(_cert_ctx.get());
|
||||
});
|
||||
|
||||
X509_STORE_CTX_init(_cert_ctx.get(), _cert_store.get(), nullptr, nullptr);
|
||||
X509_STORE_CTX_set_cert(_cert_ctx.get(), cert);
|
||||
|
||||
auto err = X509_verify_cert(_cert_ctx.get());
|
||||
if(err != 1) {
|
||||
return X509_verify_cert_error_string(X509_STORE_CTX_get_error(_cert_ctx.get()));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cipher_t::cipher_t(const crypto::aes_t &key) : ctx { EVP_CIPHER_CTX_new() }, key { key }, padding { true } {}
|
||||
int cipher_t::decrypt(const std::string_view &cipher, std::vector<std::uint8_t> &plaintext) {
|
||||
int len;
|
||||
|
@ -23,6 +23,8 @@ using sha256_t = std::array<std::uint8_t, SHA256_DIGEST_LENGTH>;
|
||||
|
||||
using aes_t = std::array<std::uint8_t, 16>;
|
||||
using x509_t = util::safe_ptr<X509, X509_free>;
|
||||
using x509_store_t = util::safe_ptr<X509_STORE, X509_STORE_free>;
|
||||
using x509_store_ctx_t = util::safe_ptr<X509_STORE_CTX, X509_STORE_CTX_free>;
|
||||
using cipher_ctx_t = util::safe_ptr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>;
|
||||
using md_ctx_t = util::safe_ptr<EVP_MD_CTX, md_ctx_destroy>;
|
||||
using bio_t = util::safe_ptr<BIO, BIO_free_all>;
|
||||
@ -42,6 +44,19 @@ std::string_view signature(const x509_t &x);
|
||||
|
||||
std::string rand(std::size_t bytes);
|
||||
|
||||
class cert_chain_t {
|
||||
public:
|
||||
KITTY_DECL_CONSTR(cert_chain_t)
|
||||
|
||||
void add(x509_t &&cert);
|
||||
|
||||
const char *verify(x509_t::element_type *cert);
|
||||
private:
|
||||
std::vector<x509_t> _certs;
|
||||
x509_store_t _cert_store;
|
||||
x509_store_ctx_t _cert_ctx;
|
||||
};
|
||||
|
||||
class cipher_t {
|
||||
public:
|
||||
cipher_t(const aes_t &key);
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <Simple-Web-Server/server_http.hpp>
|
||||
#include <Simple-Web-Server/server_https.hpp>
|
||||
#include <boost/asio/ssl/context_base.hpp>
|
||||
|
||||
#include "uuid.h"
|
||||
#include "config.h"
|
||||
@ -211,7 +212,7 @@ void clientchallenge(pair_session_t &sess, pt::ptree &tree, const args_t &args)
|
||||
tree.put("root.<xmlattr>.status_code", 200);
|
||||
}
|
||||
|
||||
void clientpairingsecret(pair_session_t &sess, pt::ptree &tree, const args_t &args) {
|
||||
void clientpairingsecret(std::shared_ptr<safe::queue_t<crypto::x509_t>> &add_cert, pair_session_t &sess, pt::ptree &tree, const args_t &args) {
|
||||
auto &client = sess.client;
|
||||
|
||||
auto pairingsecret = util::from_hex_vec(args.at("clientpairingsecret"), true);
|
||||
@ -243,6 +244,7 @@ void clientpairingsecret(pair_session_t &sess, pt::ptree &tree, const args_t &ar
|
||||
|
||||
if(crypto::verify256(crypto::x509(client.cert), secret, sign)) {
|
||||
tree.put("root.paired", 1);
|
||||
add_cert->raise(crypto::x509(client.cert));
|
||||
|
||||
auto it = map_id_sess.find(client.uniqueID);
|
||||
|
||||
@ -307,7 +309,7 @@ void not_found(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> resp
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void pair(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) {
|
||||
void pair(std::shared_ptr<safe::queue_t<crypto::x509_t>> &add_cert, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) {
|
||||
print_req<T>(request);
|
||||
|
||||
auto args = request->parse_query_string();
|
||||
@ -343,7 +345,7 @@ void pair(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response,
|
||||
serverchallengeresp(sess_it->second, tree, args);
|
||||
}
|
||||
else if(it = args.find("clientpairingsecret"); it != std::end(args)) {
|
||||
clientpairingsecret(sess_it->second, tree, args);
|
||||
clientpairingsecret(add_cert, sess_it->second, tree, args);
|
||||
}
|
||||
else {
|
||||
tree.put("root.<xmlattr>.status_code", 404);
|
||||
@ -627,12 +629,53 @@ void start() {
|
||||
conf_intern.pkey = read_file(config::nvhttp.pkey.c_str());
|
||||
conf_intern.servercert = read_file(config::nvhttp.cert.c_str());
|
||||
|
||||
https_server_t https_server { config::nvhttp.cert, config::nvhttp.pkey };
|
||||
auto ctx = std::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tls);
|
||||
ctx->use_certificate_chain_file(config::nvhttp.cert);
|
||||
ctx->use_private_key_file(config::nvhttp.pkey, boost::asio::ssl::context::pem);
|
||||
for(auto &[_,client] : map_id_client) {
|
||||
ctx->add_certificate_authority(boost::asio::buffer(client.cert));
|
||||
}
|
||||
|
||||
auto add_cert = std::make_shared<safe::queue_t<crypto::x509_t>>();
|
||||
crypto::cert_chain_t cert_chain;
|
||||
|
||||
// When Moonlight has recently paired, the certificate has not yet been added to ctx
|
||||
// Thus it needs to be verified manually
|
||||
ctx->set_verify_callback([&cert_chain, add_cert](int verified, boost::asio::ssl::verify_context &ctx) {
|
||||
util::fail_guard([&]() {
|
||||
char subject_name[256];
|
||||
|
||||
auto x509 = ctx.native_handle();
|
||||
X509_NAME_oneline(X509_get_subject_name(X509_STORE_CTX_get_current_cert(x509)), subject_name, sizeof(subject_name));
|
||||
|
||||
std::cout << subject_name << " -- "sv << (verified ? "verfied"sv : "denied"sv) << std::endl;
|
||||
});
|
||||
|
||||
if(verified) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while(add_cert->peek()) {
|
||||
cert_chain.add(add_cert->pop());
|
||||
}
|
||||
|
||||
auto err_str = cert_chain.verify(X509_STORE_CTX_get_current_cert(ctx.native_handle()));
|
||||
if(err_str) {
|
||||
std::cout << "SSL Verification error :: "sv << err_str << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
verified = true;
|
||||
return 1;
|
||||
});
|
||||
|
||||
|
||||
https_server_t https_server { ctx, boost::asio::ssl::verify_peer | boost::asio::ssl::verify_fail_if_no_peer_cert | boost::asio::ssl::verify_client_once };
|
||||
http_server_t http_server;
|
||||
|
||||
https_server.default_resource = not_found<SimpleWeb::HTTPS>;
|
||||
https_server.resource["^/serverinfo$"]["GET"] = serverinfo<SimpleWeb::HTTPS>;
|
||||
https_server.resource["^/pair$"]["GET"] = pair<SimpleWeb::HTTPS>;
|
||||
https_server.resource["^/pair$"]["GET"] = [&add_cert](auto resp, auto req) { pair<SimpleWeb::HTTPS>(add_cert, resp, req); };
|
||||
https_server.resource["^/applist$"]["GET"] = applist;
|
||||
https_server.resource["^/appasset$"]["GET"] = appasset;
|
||||
https_server.resource["^/launch$"]["GET"] = launch;
|
||||
@ -646,7 +689,7 @@ void start() {
|
||||
|
||||
http_server.default_resource = not_found<SimpleWeb::HTTP>;
|
||||
http_server.resource["^/serverinfo$"]["GET"] = serverinfo<SimpleWeb::HTTP>;
|
||||
http_server.resource["^/pair$"]["GET"] = pair<SimpleWeb::HTTP>;
|
||||
http_server.resource["^/pair$"]["GET"] = [&add_cert](auto resp, auto req) { pair<SimpleWeb::HTTP>(add_cert, resp, req); };
|
||||
http_server.resource["^/pin/([0-9]+)$"]["GET"] = pin<SimpleWeb::HTTP>;
|
||||
|
||||
http_server.config.reuse_address = true;
|
||||
|
@ -10,6 +10,10 @@
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <string_view>
|
||||
#define KITTY_DECL_CONSTR(x)\
|
||||
x(x&&) noexcept = default;\
|
||||
x&operator=(x&&) noexcept = default;\
|
||||
x();
|
||||
|
||||
#define KITTY_DEFAULT_CONSTR(x)\
|
||||
x(x&&) noexcept = default;\
|
||||
|
Loading…
x
Reference in New Issue
Block a user