mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-05-10 08:08:09 +03:00
fix(ipc): harden local IPC authorization and portable-service bootstrap flow (#14671)
* fix(ipc): harden ipc access Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): full cmd path, comments, simple refactor Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): portable service, ipc exit Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): Remove unused logs Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): Use SetEntriesInAclW instead of icacls Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): Comments Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): check is_reparse_point Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): shmem name, no fallback Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): Simple refactor Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): better exit and clear Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): portable service, better exit Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): comments, id -u Signed-off-by: fufesou <linlong1266@gmail.com> * fix: comments linux headless, rx desktop ready Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): magic number Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): update deps Signed-off-by: fufesou <linlong1266@gmail.com> * Update Cargo.lock * Update Cargo.lock * fix(ipc): harden ipc, test `identity_unavailable` Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): portable service, check dir of shmem Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): macos, better check exe allowed Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): update hbb_common Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): update hbb_common Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): harden ipc, better active uid for uinput Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): harden portable service token validation Compare portable service IPC tokens in constant time and document the CSPRNG source used for one-time token generation. Clarify Windows IPC authorization comments around canonical path matching and partial peer identity lookup. Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): simple refactor Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): harden portable service token handling Generate the portable service IPC token directly from OsRng, keep token comparison in the IPC layer as a fixed-length byte-wise check, and document the malformed-frame behavior for protected service IPC. Signed-off-by: fufesou <linlong1266@gmail.com> * fix(ipc): comments Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com> Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
This commit is contained in:
@@ -185,9 +185,13 @@ pub mod client {
|
||||
pub mod service {
|
||||
use super::*;
|
||||
use hbb_common::lazy_static;
|
||||
#[cfg(target_os = "linux")]
|
||||
use parity_tokio_ipc::Connection as RawIpcConnection;
|
||||
use scrap::wayland::{
|
||||
pipewire::RDP_SESSION_INFO, remote_desktop_portal::OrgFreedesktopPortalRemoteDesktop,
|
||||
};
|
||||
#[cfg(target_os = "linux")]
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::{collections::HashMap, sync::Mutex};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
@@ -602,7 +606,10 @@ pub mod service {
|
||||
}
|
||||
DataKeyboard::KeyDown(enigo::Key::Raw(code)) => {
|
||||
if *code < 8 {
|
||||
log::error!("Invalid Raw keycode {} (must be >= 8 due to XKB offset), skipping", code);
|
||||
log::error!(
|
||||
"Invalid Raw keycode {} (must be >= 8 due to XKB offset), skipping",
|
||||
code
|
||||
);
|
||||
} else {
|
||||
let down_event = InputEvent::new(EventType::KEY, *code - 8, 1);
|
||||
allow_err!(keyboard.emit(&[down_event]));
|
||||
@@ -610,7 +617,10 @@ pub mod service {
|
||||
}
|
||||
DataKeyboard::KeyUp(enigo::Key::Raw(code)) => {
|
||||
if *code < 8 {
|
||||
log::error!("Invalid Raw keycode {} (must be >= 8 due to XKB offset), skipping", code);
|
||||
log::error!(
|
||||
"Invalid Raw keycode {} (must be >= 8 due to XKB offset), skipping",
|
||||
code
|
||||
);
|
||||
} else {
|
||||
let up_event = InputEvent::new(EventType::KEY, *code - 8, 0);
|
||||
allow_err!(keyboard.emit(&[up_event]));
|
||||
@@ -909,6 +919,35 @@ pub mod service {
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn authorize_uinput_peer(postfix: &str, stream: &RawIpcConnection) -> bool {
|
||||
if !hbb_common::config::is_service_ipc_postfix(postfix) {
|
||||
return true;
|
||||
}
|
||||
let peer_uid = ipc::peer_uid_from_fd(stream.as_raw_fd());
|
||||
let active_uid = crate::platform::linux::get_active_userid_fresh()
|
||||
.trim()
|
||||
.parse::<u32>()
|
||||
.ok();
|
||||
let authorized =
|
||||
peer_uid.is_some_and(|uid| ipc::is_allowed_service_peer_uid(uid, active_uid));
|
||||
if !authorized {
|
||||
crate::ipc::log_rejected_uinput_connection(postfix, peer_uid, active_uid);
|
||||
return false;
|
||||
}
|
||||
if let Err(err) =
|
||||
ipc::ensure_peer_executable_matches_current_by_fd(stream.as_raw_fd(), postfix)
|
||||
{
|
||||
log::warn!(
|
||||
"Rejected connection on protected uinput ipc channel due to executable mismatch: postfix={}, err={}",
|
||||
postfix,
|
||||
err
|
||||
);
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// Start uinput service.
|
||||
async fn start_service<F: FnOnce(ipc::Connection) + Copy>(postfix: &str, handler: F) {
|
||||
match new_listener(postfix).await {
|
||||
@@ -916,6 +955,10 @@ pub mod service {
|
||||
while let Some(result) = incoming.next().await {
|
||||
match result {
|
||||
Ok(stream) => {
|
||||
#[cfg(target_os = "linux")]
|
||||
if !authorize_uinput_peer(postfix, &stream) {
|
||||
continue;
|
||||
}
|
||||
log::debug!("Got new connection of uinput ipc {}", postfix);
|
||||
handler(Connection::new(stream));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user