Add server one time pin support to nvhttp

This commit is contained in:
Yukino Song
2024-08-27 13:28:55 +08:00
parent 19630a9cb5
commit 70fbd26906
3 changed files with 91 additions and 6 deletions

View File

@@ -8,6 +8,7 @@
// standard includes
#include <filesystem>
#include <utility>
#include <string>
// lib includes
#include <Simple-Web-Server/server_http.hpp>
@@ -17,7 +18,6 @@
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <string>
// local includes
#include "config.h"
@@ -47,6 +47,9 @@ namespace nvhttp {
namespace pt = boost::property_tree;
crypto::cert_chain_t cert_chain;
static std::string one_time_pin;
static std::string otp_passphrase;
static std::chrono::time_point<std::chrono::steady_clock> otp_creation_time;
class SunshineHttpsServer: public SimpleWeb::Server<SimpleWeb::HTTPS> {
public:
@@ -567,18 +570,19 @@ namespace nvhttp {
}
auto uniqID { get_arg(args, "uniqueid") };
auto deviceName { get_arg(args, "devicename") };
auto sess_it = map_id_sess.find(uniqID);
if (deviceName == "roth"sv) {
deviceName = "Legacy Moonlight Client";
}
args_t::const_iterator it;
if (it = args.find("phrase"); it != std::end(args)) {
if (it->second == "getservercert"sv) {
pair_session_t sess;
auto deviceName { get_arg(args, "devicename") };
if (deviceName == "roth"sv) {
deviceName = "Legacy Moonlight Client";
}
sess.client.uniqueID = std::move(uniqID);
sess.client.deviceName = std::move(deviceName);
sess.client.cert = util::from_hex_vec(get_arg(args, "clientcert"), true);
@@ -587,6 +591,30 @@ namespace nvhttp {
auto ptr = map_id_sess.emplace(sess.client.uniqueID, std::move(sess)).first;
ptr->second.async_insert_pin.salt = std::move(get_arg(args, "salt"));
auto it = args.find("otpauth");
if (it != std::end(args)) {
if (one_time_pin.empty() || (std::chrono::steady_clock::now() - otp_creation_time > OTP_EXPIRE_DURATION)) {
one_time_pin.clear();
otp_passphrase.clear();
tree.put("root.<xmlattr>.status_code", 503);
tree.put("root.<xmlattr>.status_message", "OTP auth not available.");
} else {
auto hash = util::hex(crypto::hash(one_time_pin + ptr->second.async_insert_pin.salt + otp_passphrase));
if (hash.to_string_view() == it->second) {
getservercert(ptr->second, tree, one_time_pin);
one_time_pin.clear();
otp_passphrase.clear();
return;
}
}
// Always return positive, attackers will fail in the next steps.
getservercert(ptr->second, tree, crypto::rand(16));
return;
}
if (config::sunshine.flags[config::flag::PIN_STDIN]) {
std::string pin;
@@ -1183,6 +1211,18 @@ namespace nvhttp {
tcp.join();
}
std::string request_otp(const std::string& passphrase) {
if (passphrase.size() < 4) {
return "";
}
otp_passphrase = passphrase;
one_time_pin = crypto::rand_alphabet(4, "0123456789"sv);
otp_creation_time = std::chrono::steady_clock::now();
return one_time_pin;
}
void
erase_all_clients() {
client_t client;