Fix client UUID resolution from SSL peer certificate
Some checks failed
ci-bundle.yml / Fix client UUID resolution from SSL peer certificate (push) Failing after 0s
ci-copr.yml / Fix client UUID resolution from SSL peer certificate (push) Failing after 0s
ci-homebrew.yml / Fix client UUID resolution from SSL peer certificate (push) Failing after 0s
Some checks failed
ci-bundle.yml / Fix client UUID resolution from SSL peer certificate (push) Failing after 0s
ci-copr.yml / Fix client UUID resolution from SSL peer certificate (push) Failing after 0s
ci-homebrew.yml / Fix client UUID resolution from SSL peer certificate (push) Failing after 0s
This commit is contained in:
parent
6c3a91357c
commit
0f070b144f
3 changed files with 61 additions and 4 deletions
|
|
@ -279,6 +279,53 @@ namespace nvhttp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resolve the real paired client UUID from the SSL peer certificate.
|
||||||
|
* @param request The HTTPS request whose peer cert identifies the client.
|
||||||
|
* @return The paired client's UUID, or empty string if not found.
|
||||||
|
*
|
||||||
|
* Moonlight sends a placeholder uniqueid ("0123456789ABCDEF") in the launch
|
||||||
|
* query string. The real identity is the SSL client certificate presented
|
||||||
|
* during the TLS handshake, which we match against our paired device list.
|
||||||
|
*/
|
||||||
|
std::string resolve_client_uuid(req_https_t request) {
|
||||||
|
auto conn = request->connection_shared();
|
||||||
|
if (!conn) {
|
||||||
|
BOOST_LOG(warning) << "resolve_client_uuid: connection expired"sv;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ssl = conn->socket->native_handle();
|
||||||
|
if (!ssl) {
|
||||||
|
BOOST_LOG(warning) << "resolve_client_uuid: no SSL handle"sv;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto::x509_t peer_cert {
|
||||||
|
#if OPENSSL_VERSION_MAJOR >= 3
|
||||||
|
SSL_get1_peer_certificate(ssl)
|
||||||
|
#else
|
||||||
|
SSL_get_peer_certificate(ssl)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
if (!peer_cert) {
|
||||||
|
BOOST_LOG(warning) << "resolve_client_uuid: no peer certificate"sv;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto peer_pem = crypto::pem(peer_cert);
|
||||||
|
|
||||||
|
for (const auto &device : client_root.named_devices) {
|
||||||
|
if (device.cert == peer_pem) {
|
||||||
|
BOOST_LOG(info) << "resolve_client_uuid: matched paired client '"sv << device.name << "' uuid="sv << device.uuid;
|
||||||
|
return device.uuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_LOG(warning) << "resolve_client_uuid: peer cert did not match any paired device"sv;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<rtsp_stream::launch_session_t> make_launch_session(bool host_audio, const args_t &args) {
|
std::shared_ptr<rtsp_stream::launch_session_t> make_launch_session(bool host_audio, const args_t &args) {
|
||||||
auto launch_session = std::make_shared<rtsp_stream::launch_session_t>();
|
auto launch_session = std::make_shared<rtsp_stream::launch_session_t>();
|
||||||
|
|
||||||
|
|
@ -868,6 +915,11 @@ namespace nvhttp {
|
||||||
host_audio = util::from_view(get_arg(args, "localAudioPlayMode"));
|
host_audio = util::from_view(get_arg(args, "localAudioPlayMode"));
|
||||||
auto launch_session = make_launch_session(host_audio, args);
|
auto launch_session = make_launch_session(host_audio, args);
|
||||||
|
|
||||||
|
auto resolved_uuid = resolve_client_uuid(request);
|
||||||
|
if (!resolved_uuid.empty()) {
|
||||||
|
launch_session->unique_id = std::move(resolved_uuid);
|
||||||
|
}
|
||||||
|
|
||||||
if (rtsp_stream::session_count() == 0) {
|
if (rtsp_stream::session_count() == 0) {
|
||||||
// The display should be restored in case something fails as there are no other sessions.
|
// The display should be restored in case something fails as there are no other sessions.
|
||||||
revert_display_configuration = true;
|
revert_display_configuration = true;
|
||||||
|
|
@ -976,6 +1028,11 @@ namespace nvhttp {
|
||||||
}
|
}
|
||||||
const auto launch_session = make_launch_session(host_audio, args);
|
const auto launch_session = make_launch_session(host_audio, args);
|
||||||
|
|
||||||
|
auto resolved_uuid = resolve_client_uuid(request);
|
||||||
|
if (!resolved_uuid.empty()) {
|
||||||
|
launch_session->unique_id = std::move(resolved_uuid);
|
||||||
|
}
|
||||||
|
|
||||||
if (no_active_sessions) {
|
if (no_active_sessions) {
|
||||||
// We want to prepare display only if there are no active sessions at
|
// We want to prepare display only if there are no active sessions at
|
||||||
// the moment. This should be done before probing encoders as it could
|
// the moment. This should be done before probing encoders as it could
|
||||||
|
|
|
||||||
|
|
@ -1972,9 +1972,9 @@ namespace stream {
|
||||||
{"keyboard_active", kb_ago <= KB_ACTIVE_WINDOW_MS},
|
{"keyboard_active", kb_ago <= KB_ACTIVE_WINDOW_MS},
|
||||||
{"mouse_active", mouse_ago <= MOUSE_ACTIVE_WINDOW_MS},
|
{"mouse_active", mouse_ago <= MOUSE_ACTIVE_WINDOW_MS},
|
||||||
{"gamepad_active", gp_ago <= GAMEPAD_ACTIVE_WINDOW_MS},
|
{"gamepad_active", gp_ago <= GAMEPAD_ACTIVE_WINDOW_MS},
|
||||||
{"last_keyboard_ms_ago", last_kb > 0 ? kb_ago : -1},
|
{"last_keyboard_ms_ago", last_kb > 0 ? (int64_t) kb_ago : (int64_t) -1},
|
||||||
{"last_mouse_ms_ago", last_mouse > 0 ? mouse_ago : -1},
|
{"last_mouse_ms_ago", last_mouse > 0 ? (int64_t) mouse_ago : (int64_t) -1},
|
||||||
{"last_gamepad_ms_ago", last_gp > 0 ? gp_ago : -1},
|
{"last_gamepad_ms_ago", last_gp > 0 ? (int64_t) gp_ago : (int64_t) -1},
|
||||||
};
|
};
|
||||||
|
|
||||||
result.push_back(std::move(entry));
|
result.push_back(std::move(entry));
|
||||||
|
|
|
||||||
2
third-party/Simple-Web-Server
vendored
2
third-party/Simple-Web-Server
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 546895a93a29062bb178367b46c7afb72da9881e
|
Subproject commit 99c1f621ebd8d119c5d2dc3a88ecf255058acec0
|
||||||
Loading…
Add table
Add a link
Reference in a new issue