mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-04-15 13:21:27 +03:00
fix: linux, home (#13879)
Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -3749,6 +3749,7 @@ dependencies = [
|
|||||||
"toml 0.7.8",
|
"toml 0.7.8",
|
||||||
"tungstenite",
|
"tungstenite",
|
||||||
"url",
|
"url",
|
||||||
|
"users 0.11.0",
|
||||||
"uuid",
|
"uuid",
|
||||||
"webpki-roots 1.0.4",
|
"webpki-roots 1.0.4",
|
||||||
"webrtc",
|
"webrtc",
|
||||||
@@ -7231,7 +7232,6 @@ dependencies = [
|
|||||||
"tray-icon",
|
"tray-icon",
|
||||||
"ttf-parser",
|
"ttf-parser",
|
||||||
"url",
|
"url",
|
||||||
"users 0.11.0",
|
|
||||||
"uuid",
|
"uuid",
|
||||||
"virtual_display",
|
"virtual_display",
|
||||||
"wallpaper",
|
"wallpaper",
|
||||||
|
|||||||
@@ -176,7 +176,6 @@ evdev = { git="https://github.com/rustdesk-org/evdev" }
|
|||||||
dbus = "0.9"
|
dbus = "0.9"
|
||||||
dbus-crossroads = "0.5"
|
dbus-crossroads = "0.5"
|
||||||
pam = { git="https://github.com/rustdesk-org/pam" }
|
pam = { git="https://github.com/rustdesk-org/pam" }
|
||||||
users = { version = "0.11" }
|
|
||||||
x11-clipboard = {git="https://github.com/clslaid/x11-clipboard", branch = "feat/store-batch", optional = true}
|
x11-clipboard = {git="https://github.com/clslaid/x11-clipboard", branch = "feat/store-batch", optional = true}
|
||||||
x11rb = {version = "0.12", features = ["all-extensions"], optional = true}
|
x11rb = {version = "0.12", features = ["all-extensions"], optional = true}
|
||||||
percent-encoding = {version = "2.3", optional = true}
|
percent-encoding = {version = "2.3", optional = true}
|
||||||
|
|||||||
Submodule libs/hbb_common updated: 8b0e258673...fa157108be
@@ -1,21 +1,20 @@
|
|||||||
use super::{gtk_sudo, CursorData, ResultType};
|
use super::{gtk_sudo, CursorData, ResultType};
|
||||||
use desktop::Desktop;
|
use desktop::Desktop;
|
||||||
use hbb_common::config::keys::OPTION_ALLOW_LINUX_HEADLESS;
|
|
||||||
pub use hbb_common::platform::linux::*;
|
pub use hbb_common::platform::linux::*;
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err,
|
allow_err,
|
||||||
anyhow::anyhow,
|
anyhow::anyhow,
|
||||||
bail,
|
bail,
|
||||||
config::Config,
|
config::{keys::OPTION_ALLOW_LINUX_HEADLESS, Config},
|
||||||
libc::{c_char, c_int, c_long, c_void},
|
libc::{c_char, c_int, c_long, c_void},
|
||||||
log,
|
log,
|
||||||
message_proto::{DisplayInfo, Resolution},
|
message_proto::{DisplayInfo, Resolution},
|
||||||
regex::{Captures, Regex},
|
regex::{Captures, Regex},
|
||||||
|
users::{get_user_by_name, os::unix::UserExt},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
ffi::{OsStr, OsString},
|
ffi::{OsStr, OsString},
|
||||||
os::unix::ffi::OsStrExt,
|
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::{Child, Command},
|
process::{Child, Command},
|
||||||
string::String,
|
string::String,
|
||||||
@@ -26,7 +25,6 @@ use std::{
|
|||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use terminfo::{capability as cap, Database};
|
use terminfo::{capability as cap, Database};
|
||||||
use users::{get_user_by_name, os::unix::UserExt};
|
|
||||||
use wallpaper;
|
use wallpaper;
|
||||||
|
|
||||||
type Xdo = *const c_void;
|
type Xdo = *const c_void;
|
||||||
@@ -1714,26 +1712,57 @@ pub fn run_cmds_privileged(cmds: &str) -> bool {
|
|||||||
crate::platform::gtk_sudo::run(vec![cmds]).is_ok()
|
crate::platform::gtk_sudo::run(vec![cmds]).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Spawn the current executable after a delay.
|
||||||
|
///
|
||||||
|
/// # Security
|
||||||
|
/// The executable path is safely quoted using `shell_quote()` to prevent
|
||||||
|
/// command injection vulnerabilities. The `secs` parameter is a u32, so it
|
||||||
|
/// cannot contain malicious input.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
/// * `secs` - Number of seconds to wait before spawning
|
||||||
pub fn run_me_with(secs: u32) {
|
pub fn run_me_with(secs: u32) {
|
||||||
let exe = std::env::current_exe()
|
let exe = match std::env::current_exe() {
|
||||||
.unwrap_or("".into())
|
Ok(path) => path,
|
||||||
.to_string_lossy()
|
Err(e) => {
|
||||||
.to_string();
|
log::error!("Failed to get current exe: {}", e);
|
||||||
// We use `CMD_SH` instead of `sh` to suppress some audit messages on some systems.
|
return;
|
||||||
std::process::Command::new(CMD_SH.as_str())
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// SECURITY: Use shell_quote to safely escape the executable path,
|
||||||
|
// preventing command injection even if the path contains special characters.
|
||||||
|
let exe_quoted = shell_quote(&exe.to_string_lossy());
|
||||||
|
|
||||||
|
// Spawn a background process that sleeps and then executes.
|
||||||
|
// The child process is automatically orphaned when parent exits,
|
||||||
|
// and will be adopted by init (PID 1).
|
||||||
|
Command::new(CMD_SH.as_str())
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(&format!("sleep {secs}; {exe}"))
|
.arg(&format!("sleep {secs}; exec {exe_quoted}"))
|
||||||
.spawn()
|
.spawn()
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn switch_service(stop: bool) -> String {
|
fn switch_service(stop: bool) -> String {
|
||||||
let home = std::env::var("HOME").unwrap_or_default();
|
// SECURITY: Use trusted home directory lookup via getpwuid instead of $HOME env var
|
||||||
|
// to prevent confused-deputy attacks where an attacker manipulates environment variables.
|
||||||
|
let home = get_home_dir_trusted()
|
||||||
|
.map(|p| p.to_string_lossy().to_string())
|
||||||
|
.unwrap_or_default();
|
||||||
Config::set_option("stop-service".into(), if stop { "Y" } else { "" }.into());
|
Config::set_option("stop-service".into(), if stop { "Y" } else { "" }.into());
|
||||||
if home != "/root" && !Config::get().is_empty() {
|
if !home.is_empty() && home != "/root" && !Config::get().is_empty() {
|
||||||
let p = format!(".config/{}", crate::get_app_name().to_lowercase());
|
let app_name_lower = crate::get_app_name().to_lowercase();
|
||||||
let app_name0 = crate::get_app_name();
|
let app_name0 = crate::get_app_name();
|
||||||
format!("cp -f {home}/{p}/{app_name0}.toml /root/{p}/; cp -f {home}/{p}/{app_name0}2.toml /root/{p}/;")
|
let config_subdir = format!(".config/{}", app_name_lower);
|
||||||
|
|
||||||
|
// SECURITY: Quote all paths to prevent shell injection from paths containing
|
||||||
|
// spaces, semicolons, or other special characters.
|
||||||
|
let src1 = shell_quote(&format!("{}/{}/{}.toml", home, config_subdir, app_name0));
|
||||||
|
let src2 = shell_quote(&format!("{}/{}/{}2.toml", home, config_subdir, app_name0));
|
||||||
|
let dst = shell_quote(&format!("/root/{}/", config_subdir));
|
||||||
|
|
||||||
|
format!("cp -f {} {}; cp -f {} {};", src1, dst, src2, dst)
|
||||||
} else {
|
} else {
|
||||||
"".to_owned()
|
"".to_owned()
|
||||||
}
|
}
|
||||||
@@ -1787,7 +1816,15 @@ fn check_if_stop_service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_autostart_config() -> ResultType<()> {
|
pub fn check_autostart_config() -> ResultType<()> {
|
||||||
let home = std::env::var("HOME").unwrap_or_default();
|
// SECURITY: Use trusted home directory lookup via getpwuid instead of $HOME env var
|
||||||
|
// to prevent confused-deputy attacks where an attacker manipulates environment variables.
|
||||||
|
let home = match get_home_dir_trusted() {
|
||||||
|
Some(p) => p.to_string_lossy().to_string(),
|
||||||
|
None => {
|
||||||
|
log::warn!("Failed to get trusted home directory for autostart config check");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
let app_name = crate::get_app_name().to_lowercase();
|
let app_name = crate::get_app_name().to_lowercase();
|
||||||
let path = format!("{home}/.config/autostart");
|
let path = format!("{home}/.config/autostart");
|
||||||
let file = format!("{path}/{app_name}.desktop");
|
let file = format!("{path}/{app_name}.desktop");
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ use crate::client::{
|
|||||||
LOGIN_MSG_DESKTOP_SESSION_NOT_READY, LOGIN_MSG_DESKTOP_XORG_NOT_FOUND,
|
LOGIN_MSG_DESKTOP_SESSION_NOT_READY, LOGIN_MSG_DESKTOP_XORG_NOT_FOUND,
|
||||||
LOGIN_MSG_DESKTOP_XSESSION_FAILED,
|
LOGIN_MSG_DESKTOP_XSESSION_FAILED,
|
||||||
};
|
};
|
||||||
use hbb_common::{allow_err, bail, log, rand::prelude::*, tokio::time};
|
use hbb_common::{
|
||||||
|
allow_err, bail, log,
|
||||||
|
rand::prelude::*,
|
||||||
|
tokio::time,
|
||||||
|
users::{get_user_by_name, os::unix::UserExt, User},
|
||||||
|
};
|
||||||
use pam;
|
use pam;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
@@ -18,7 +23,6 @@ use std::{
|
|||||||
},
|
},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use users::{get_user_by_name, os::unix::UserExt, User};
|
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref DESKTOP_RUNNING: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
|
static ref DESKTOP_RUNNING: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
|
||||||
|
|||||||
Reference in New Issue
Block a user