From 028767da8b0f06e90f156960340787aa481eda2c Mon Sep 17 00:00:00 2001 From: Awalon Date: Sun, 23 Apr 2023 03:43:47 +0200 Subject: [PATCH] Fix for #4136 connection to linux refused by using wrong Xauthority file Solution: 1. Get file from sddm-greeter and startplasma-x11 (aka KDE) processes as well 2. Get users home dir from system instead of hard coded pattern /home/ 3. Prefer XAUTHORITY environment variable over Xorg -auth if available --- Cargo.toml | 4 +- libs/hbb_common/src/config.rs | 14 ++- src/platform/linux.rs | 157 ++++++++++++++++++++++++++-------- 3 files changed, 138 insertions(+), 37 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 49e2b66fc..0200e0fee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ flutter = ["flutter_rust_bridge"] default = ["use_dasp"] hwcodec = ["scrap/hwcodec"] mediacodec = ["scrap/mediacodec"] -linux_headless = ["pam", "users"] +linux_headless = ["pam" ] virtual_display_driver = ["virtual_display"] plugin_framework = [] @@ -126,7 +126,7 @@ evdev = { git="https://github.com/fufesou/evdev" } dbus = "0.9" dbus-crossroads = "0.5" pam = { git="https://github.com/fufesou/pam", optional = true } -users = { version = "0.11.0", optional = true } +users = { version = "0.11.0" } [target.'cfg(target_os = "android")'.dependencies] android_logger = "0.11" diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 369920982..a5423c4cf 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -322,7 +322,19 @@ fn patch(path: PathBuf) -> PathBuf { .trim() .to_owned(); if user != "root" { - return format!("/home/{user}").into(); + let cmd = format!("getent passwd '{}' | awk -F':' '{{print $6}}'", user); + if let Ok(output) = std::process::Command::new(cmd).output() { + let home_dir = String::from_utf8_lossy(&output.stdout) + .to_string() + .trim() + .to_owned(); + if home_dir.is_empty() { + return format!("/home/{user}").into(); + } else { + log::info!("config::patch: got home dir from: {}", home_dir); + return home_dir.into(); + } + } } } } diff --git a/src/platform/linux.rs b/src/platform/linux.rs index 33ebcc82c..2cab7edbf 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -9,6 +9,7 @@ use hbb_common::{ regex::{Captures, Regex}, }; use std::{ + string::String, cell::RefCell, path::{Path, PathBuf}, process::{Child, Command}, @@ -18,6 +19,7 @@ use std::{ }, time::{Duration, Instant}, }; +use users::{get_user_by_name, os::unix::UserExt}; type Xdo = *const c_void; @@ -449,12 +451,37 @@ pub fn get_active_username() -> String { get_values_of_seat0(&[2])[0].clone() } +pub fn get_user_home_by_name(username: &str) -> Option { + return match get_user_by_name(username) { + None => { + log::debug!("no uid found for user: {}", username); + None } + Some(user) => { + log::debug!("user '{:?}' (uid {:?}) with home dir: {:?}", user.uid(), user.name(), user.home_dir()); + let home = user.home_dir(); + if Path::is_dir(home) { + Some(PathBuf::from(home)) + } else { + None + } + } + } +} + pub fn get_active_user_home() -> Option { let username = get_active_username(); if !username.is_empty() { - let home = PathBuf::from(format!("/home/{}", username)); - if home.exists() { - return Some(home); + match get_user_home_by_name(&username) { + None => { + // fallback to most common default pattern + let home = PathBuf::from(format!("/home/{}", username)); + if home.exists() { + return Some(home); + } + } + Some(home) => { + return Some(home); + } } } None @@ -774,6 +801,8 @@ mod desktop { pub const XFCE4_PANEL: &str = "xfce4-panel"; pub const GNOME_SESSION_BINARY: &str = "gnome-session-binary"; + pub const SDDM_GREETER: &str = "sddm-greeter"; + pub const PLASMA_X11: &str = "startplasma-x11"; #[derive(Debug, Clone, Default)] pub struct Desktop { @@ -803,10 +832,19 @@ mod desktop { } fn get_display(&mut self) { - self.display = get_env_tries("DISPLAY", &self.uid, GNOME_SESSION_BINARY, 10); - if self.display.is_empty() { - self.display = get_env_tries("DISPLAY", &self.uid, XFCE4_PANEL, 10); + let display_envs = vec![ + GNOME_SESSION_BINARY, + XFCE4_PANEL, + SDDM_GREETER, + PLASMA_X11, + ]; + for diplay_env in display_envs { + self.display = get_env_tries("DISPLAY", &self.uid, diplay_env, 10); + if !self.display.is_empty() { + break; + } } + if self.display.is_empty() { self.display = Self::get_display_by_user(&self.username); } @@ -824,56 +862,107 @@ mod desktop { "ps -u {} -f | grep 'Xorg' | grep -v 'grep'", &self.uid )) { + log::debug!("extracting xauth file for Xorg running with uid: {}", self.uid); for line in output.lines() { let mut auth_found = false; - for v in line.split_whitespace() { - if v == "-auth" { - auth_found = true; - } else if auth_found { - if std::path::Path::new(v).is_absolute() { - self.xauth = v.to_string(); - } else { - if let Some(pid) = line.split_whitespace().nth(1) { - let home_dir = get_env_from_pid("HOME", pid); - if home_dir.is_empty() { - self.xauth = format!("/home/{}/{}", self.username, v); - } else { - self.xauth = format!("{}/{}", home_dir, v); - } + + if let Some(pid) = line.split_whitespace().nth(1) { + for v in line.split_whitespace() { + if v == "-auth" { + log::debug!("- auth parameter detected"); + auth_found = true; + } else if auth_found { + if std::path::Path::new(v).is_absolute() + && std::path::Path::new(v).exists() { + + self.xauth = v.to_string(); + log::debug!("+ auth file with absolute path detected: {}", self.xauth); } else { - // unreachable! + log::debug!("- auth file with relative path detected: {}", v); + if let Some(pid) = line.split_whitespace().nth(1) { + let mut base_dir: String = String::from("/home"); // default pattern + let home_dir = get_env_from_pid("HOME", pid); + if home_dir.is_empty() { + if let Some(home) = get_user_home_by_name(&self.username) { + base_dir = home.as_path().to_string_lossy().to_string(); + }; + } else { + base_dir = home_dir; + } + if Path::new(&base_dir).exists() { + self.xauth = format!("{}/{}", base_dir, v); + log::debug!("+ auth file with home path added: {}", self.xauth); + }; + } else { + // unreachable! + } } + return; } - return; + } + + // get from environment variable if parameter wasn't found + let xauth = get_env_from_pid("XAUTHORITY", pid); + if !xauth.is_empty() { + if Path::new(&xauth).exists() { + log::debug!("+ auth file from environment detected: {}", xauth); + self.xauth = xauth; + }; } } } } + log::debug!("- auth file detected by Xorg: {}", self.xauth); } fn get_xauth(&mut self) { - self.xauth = get_env_tries("XAUTHORITY", &self.uid, GNOME_SESSION_BINARY, 10); - if self.xauth.is_empty() { - get_env_tries("XAUTHORITY", &self.uid, XFCE4_PANEL, 10); + log::debug!("guessing xauth file..."); + // try by direct access to window manager process by name + let display_envs = vec![ + GNOME_SESSION_BINARY, + XFCE4_PANEL, + SDDM_GREETER, + PLASMA_X11, + ]; + for diplay_env in display_envs { + self.xauth = get_env_tries("XAUTHORITY", &self.uid, diplay_env, 10); + if self.xauth.is_empty() { + log::debug!("- nothing for {} {} (GNOME)", self.uid, diplay_env); + } else { + log::debug!("+ found {} for {} {} (GNOME)", self.xauth, self.uid, diplay_env); + break; + } } + + // get from Xorg process, parameter and environment if self.xauth.is_empty() { self.get_xauth_from_xorg(); } - let gdm = format!("/run/user/{}/gdm/Xauthority", self.uid); + // fallback to default file name if self.xauth.is_empty() { + let gdm = format!("/run/user/{}/gdm/Xauthority", self.uid); self.xauth = if std::path::Path::new(&gdm).exists() { + log::debug!("+ found gdm for {}: {}", self.uid, gdm); gdm } else { let username = &self.username; - if username == "root" { - format!("/{}/.Xauthority", username) - } else { - let tmp = format!("/home/{}/.Xauthority", username); - if std::path::Path::new(&tmp).exists() { - tmp - } else { - format!("/var/lib/{}/.Xauthority", username) + match get_user_home_by_name(username) { + None => { + log::debug!("- user home dir not detected: {}", username); + if username == "root" { + format!("/{}/.Xauthority", username) + } else { + let tmp = format!("/home/{}/.Xauthority", username); + if std::path::Path::new(&tmp).exists() { + tmp + } else { + format!("/var/lib/{}/.Xauthority", username) + } + } + } + Some(home) => { + format!("{}/.Xauthority", home.as_path().to_string_lossy().to_string()) } } };