mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-08 13:31:03 +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:
@@ -29,6 +29,12 @@ use wallpaper;
|
||||
pub const PA_SAMPLE_RATE: u32 = 48000;
|
||||
static mut UNMODIFIED: bool = true;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct ActiveUserLookupCache {
|
||||
uid: String,
|
||||
username: String,
|
||||
}
|
||||
|
||||
const INVALID_TERM_VALUES: [&str; 3] = ["", "unknown", "dumb"];
|
||||
const SHELL_PROCESSES: [&str; 4] = ["bash", "zsh", "fish", "sh"];
|
||||
|
||||
@@ -50,6 +56,8 @@ lazy_static::lazy_static! {
|
||||
}
|
||||
}
|
||||
};
|
||||
static ref ACTIVE_USER_LOOKUP_CACHE: std::sync::Mutex<Option<ActiveUserLookupCache>> =
|
||||
std::sync::Mutex::new(None);
|
||||
// https://github.com/rustdesk/rustdesk/issues/13705
|
||||
// Check if `sudo -E` actually preserves environment.
|
||||
//
|
||||
@@ -82,6 +90,27 @@ lazy_static::lazy_static! {
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn update_active_user_lookup_cache(desktop: &Desktop) {
|
||||
if let Ok(mut cache) = ACTIVE_USER_LOOKUP_CACHE.lock() {
|
||||
if desktop.uid.is_empty() || desktop.username.is_empty() {
|
||||
*cache = None;
|
||||
} else {
|
||||
*cache = Some(ActiveUserLookupCache {
|
||||
uid: desktop.uid.clone(),
|
||||
username: desktop.username.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_active_user_id_name_from_cache() -> Option<(String, String)> {
|
||||
let cache = ACTIVE_USER_LOOKUP_CACHE.lock().ok()?;
|
||||
let entry = cache.as_ref()?;
|
||||
Some((entry.uid.clone(), entry.username.clone()))
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
// XDO context - created via libxdo-sys (which uses dynamic loading stub).
|
||||
// If libxdo is not available, xdo will be null and xdo-based functions become no-ops.
|
||||
@@ -789,6 +818,7 @@ pub fn start_os_service() {
|
||||
let mut last_restart = Instant::now();
|
||||
while running.load(Ordering::SeqCst) {
|
||||
desktop.refresh();
|
||||
update_active_user_lookup_cache(&desktop);
|
||||
|
||||
// Duplicate logic here with should_start_server
|
||||
// Login wayland will try to start a headless --server.
|
||||
@@ -861,13 +891,29 @@ pub fn start_os_service() {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns the cached active `(uid, username)` snapshot when available.
|
||||
/// Callers that require a fresh seat0 lookup should call `get_values_of_seat0` directly.
|
||||
pub fn get_active_user_id_name() -> (String, String) {
|
||||
if let Some(id_name) = get_active_user_id_name_from_cache() {
|
||||
return id_name;
|
||||
}
|
||||
let vec_id_name = get_values_of_seat0(&[1, 2]);
|
||||
(vec_id_name[0].clone(), vec_id_name[1].clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns the cached active uid when available.
|
||||
/// Callers that require a fresh seat0 lookup should call `get_values_of_seat0` directly.
|
||||
pub fn get_active_userid() -> String {
|
||||
if let Some((uid, _)) = get_active_user_id_name_from_cache() {
|
||||
return uid;
|
||||
}
|
||||
get_values_of_seat0(&[1])[0].clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns the active uid from a fresh seat0 lookup, bypassing the service-loop cache.
|
||||
pub fn get_active_userid_fresh() -> String {
|
||||
get_values_of_seat0(&[1])[0].clone()
|
||||
}
|
||||
|
||||
@@ -922,7 +968,12 @@ fn _get_display_manager() -> String {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns the cached active username when available.
|
||||
/// Callers that require a fresh seat0 lookup should call `get_values_of_seat0` directly.
|
||||
pub fn get_active_username() -> String {
|
||||
if let Some((_, username)) = get_active_user_id_name_from_cache() {
|
||||
return username;
|
||||
}
|
||||
get_values_of_seat0(&[2])[0].clone()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user