From 36b1a15676c1c22b0ebbea7f949a5469e47529ba Mon Sep 17 00:00:00 2001 From: Yukino Song Date: Wed, 28 Aug 2024 23:52:02 +0800 Subject: [PATCH] Fix security risk in pairing process w/ add device name for OTP pair --- src/confighttp.cpp | 10 +++++++- src/nvhttp.cpp | 34 +++++++++++++++++---------- src/nvhttp.h | 2 +- src_assets/common/assets/web/pin.html | 8 ++++--- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index b7fd1552..b7e923ee 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -765,7 +765,15 @@ namespace confighttp { throw std::runtime_error("Passphrase too short!"); } - outputTree.put("otp", nvhttp::request_otp(it->second)); + std::string passphrase = it->second; + std::string deviceName; + + it = args.find("deviceName"); + if (it != std::end(args)) { + deviceName = it->second; + } + + outputTree.put("otp", nvhttp::request_otp(passphrase, deviceName)); outputTree.put("status", true); outputTree.put("message", "OTP created, effective within 3 minutes."); } diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 256e31a5..9536d816 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -49,6 +49,7 @@ namespace nvhttp { crypto::cert_chain_t cert_chain; static std::string one_time_pin; static std::string otp_passphrase; + static std::string otp_device_name; static std::chrono::time_point otp_creation_time; class SunshineHTTPS: public SimpleWeb::HTTPS { @@ -500,6 +501,13 @@ namespace nvhttp { auto it = map_id_sess.find(client.uniqueID); + // set up named cert + named_cert_t named_cert; + named_cert.name = client.deviceName; + named_cert.cert = client.cert; + named_cert.uuid = uuid_util::uuid_t::generate().string(); + client_root.named_devices.emplace_back(named_cert); + update_id_client(client.uniqueID, std::move(client.cert), op_e::ADD); map_id_sess.erase(it); } @@ -616,17 +624,22 @@ namespace nvhttp { if (one_time_pin.empty() || (std::chrono::steady_clock::now() - otp_creation_time > OTP_EXPIRE_DURATION)) { one_time_pin.clear(); otp_passphrase.clear(); + otp_device_name.clear(); tree.put("root..status_code", 503); tree.put("root..status_message", "OTP auth not available."); } else { auto hash = util::hex(crypto::hash(one_time_pin + ptr->second.async_insert_pin.salt + otp_passphrase), true); if (hash.to_string_view() == it->second) { - ptr->second.async_insert_pin.response = std::move(response); - fg.disable(); - pin(one_time_pin, deviceName); + if (!otp_device_name.empty()) { + ptr->second.client.deviceName = std::move(otp_device_name); + } + + getservercert(ptr->second, tree, one_time_pin); + one_time_pin.clear(); otp_passphrase.clear(); + otp_device_name.clear(); return; } } @@ -701,13 +714,9 @@ namespace nvhttp { auto &sess = std::begin(map_id_sess)->second; getservercert(sess, tree, pin); - // set up named cert - client_t &client = client_root; - named_cert_t named_cert; - named_cert.name = name.empty() ? sess.client.deviceName : name; - named_cert.cert = sess.client.cert; - named_cert.uuid = uuid_util::uuid_t::generate().string(); - client.named_devices.emplace_back(named_cert); + if (!name.empty()) { + sess.client.deviceName = name; + } // response to the request for pin std::ostringstream data; @@ -1232,13 +1241,14 @@ namespace nvhttp { tcp.join(); } - std::string request_otp(const std::string& passphrase) { + std::string request_otp(const std::string& passphrase, const std::string& deviceName) { if (passphrase.size() < 4) { return ""; } - otp_passphrase = passphrase; one_time_pin = crypto::rand_alphabet(4, "0123456789"sv); + otp_passphrase = passphrase; + otp_device_name = deviceName; otp_creation_time = std::chrono::steady_clock::now(); return one_time_pin; diff --git a/src/nvhttp.h b/src/nvhttp.h index ada9b197..757957ff 100644 --- a/src/nvhttp.h +++ b/src/nvhttp.h @@ -67,7 +67,7 @@ namespace nvhttp { bool pin(std::string pin, std::string name); - std::string request_otp(const std::string& passphrase); + std::string request_otp(const std::string& passphrase, const std::string& deviceName); /** * @brief Remove single client. diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index 5174c8cc..f45e7e48 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -29,7 +29,8 @@

{{ otp && otp || '????' }}

- + +
{{ otpMessage }}
@@ -67,7 +68,8 @@ otp: '', passphrase: '', otpMessage: '', - otpStatus: 'warning' + otpStatus: 'warning', + deviceName: '' } }, methods: { @@ -93,7 +95,7 @@ }); }, requestOTP() { - fetch(`/api/otp?passphrase=${this.passphrase}`) + fetch(`/api/otp?passphrase=${this.passphrase}${this.deviceName && `&deviceName=${this.deviceName}` || ''}`) .then(resp => resp.json()) .then(resp => { if (resp.status !== 'true') {