From a3b7d20122c77aa7aac82c30af01c9e9aa274327 Mon Sep 17 00:00:00 2001 From: Hugo Osvaldo Barrera Date: Thu, 2 Jun 2022 18:52:49 +0200 Subject: [PATCH] Add support for sandboxed socket path Rather than try a single path, try all supported paths, in the preferred order. This avoids breaking compatibility with previous KeePassXC versions. See: https://github.com/keepassxreboot/keepassxc/issues/8018 Fixes: https://github.com/varjolintu/keepassxc-proxy-rust/issues/8 Supercedes: https://github.com/varjolintu/keepassxc-proxy-rust/pull/7 --- src/proxy_socket.rs | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/src/proxy_socket.rs b/src/proxy_socket.rs index 02269f8..fa6fd33 100644 --- a/src/proxy_socket.rs +++ b/src/proxy_socket.rs @@ -4,6 +4,7 @@ use std::io::{self, Read, Write}; #[cfg(not(windows))] use std::os::unix::io::AsRawFd; use std::os::unix::net::UnixStream; +use std::path::PathBuf; use nix::sys::socket; use nix::sys::socket::sockopt::SndBuf; use nix::sys::socket::sockopt::RcvBuf; @@ -39,17 +40,45 @@ pub fn connect(buffer_size: usize) -> io::Result> { Ok(ProxySocket { inner: client }) } +#[cfg(not(windows))] +/// Returns the directories where the socket could possible be located. +/// +/// These directories should be tried in sequence, until one of them is found +/// to contain the socket. +fn get_socket_dirs() -> Vec { + let mut dirs = Vec::new(); + + if !cfg!(target_os = "macos") { + if let Ok(dir) = env::var("XDG_RUNTIME_DIR") { + let xdg_runtime_dir: PathBuf = dir.into(); + + // Sandbox-friendly path. + // Used in KeePassXC >= 2.7.2 and for all versions on Flatpak. + dirs.push(xdg_runtime_dir.join("app/org.keepassxc.KeePassXC/")); + + // Legacy path. + // Used by KeePassXC < 2.7.2. + dirs.push(xdg_runtime_dir); + }; + }; + + // Default for macOS, and final fallback for Linux. + dirs.push(env::temp_dir()); + + dirs +} + #[cfg(not(windows))] pub fn connect(buffer_size: usize) -> io::Result> { use std::time::Duration; let socket_name = "org.keepassxc.KeePassXC.BrowserServer"; - let socket = if let Ok(dir) = if cfg!(target_os = "macos") {env::var("TMPDIR") } else { env::var("XDG_RUNTIME_DIR") } { - format!("{}/{}", dir, socket_name) - } else { - format!("/tmp/{}", socket_name) - }; - let s = UnixStream::connect(socket)?; + let dirs = get_socket_dirs(); + let s = dirs + .iter() + .find_map(|dir| UnixStream::connect(dir.join(socket_name)).ok()) + .ok_or_else(|| io::Error::from(io::ErrorKind::NotFound))?; + socket::setsockopt(s.as_raw_fd(), SndBuf, &buffer_size).expect("setsockopt for SndBuf failed"); socket::setsockopt(s.as_raw_fd(), RcvBuf, &buffer_size).expect("setsockopt for RcvBuf failed"); let timeout: Option = Some(Duration::from_secs(1));