diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-04-23 19:17:37 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-05-03 08:23:30 -0300 |
| commit | bd46e9fdf89df598336d1f0d1e295bce22eff6a5 (patch) | |
| tree | 623aa8f49289be21bc38265146004a62c82ed243 | |
| parent | 0b070ccd77c44dc86a0cac64e2587cb0aa23ad2c (diff) | |
| download | mullvadvpn-bd46e9fdf89df598336d1f0d1e295bce22eff6a5.tar.xz mullvadvpn-bd46e9fdf89df598336d1f0d1e295bce22eff6a5.zip | |
Check RPC file security
| -rw-r--r-- | mullvad-ipc-client/src/lib.rs | 71 |
1 files changed, 60 insertions, 11 deletions
diff --git a/mullvad-ipc-client/src/lib.rs b/mullvad-ipc-client/src/lib.rs index d0bebd7143..2faed8b6c5 100644 --- a/mullvad-ipc-client/src/lib.rs +++ b/mullvad-ipc-client/src/lib.rs @@ -3,13 +3,16 @@ extern crate error_chain; extern crate serde; extern crate talpid_ipc; -use std::fs::File; +use std::fs::{File, Metadata}; use std::io::{BufRead, BufReader}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use serde::{Deserialize, Serialize}; use talpid_ipc::WsIpcClient; +use platform_specific::ensure_written_by_admin; +pub use platform_specific::rpc_file_path; + error_chain! { errors { EmptyRpcFile(file_path: String) { @@ -17,6 +20,17 @@ error_chain! { display("RPC connection file \"{}\" is empty", file_path) } + InsecureRpcFile(file_path: String) { + description( + "RPC connection file is insecure because it might not have been written by an \ + administrator user" + ) + display( + "RPC connection file \"{}\" is insecure because it might not have been written by \ + an administrator user", file_path + ) + } + ReadRpcFileError(file_path: String) { description("Failed to read RPC connection information") display("Failed to read RPC connection information from {}", file_path) @@ -56,6 +70,13 @@ impl DaemonRpcClient { let file_path_string = || file_path.display().to_string(); let rpc_file = File::open(&file_path).chain_err(|| ErrorKind::ReadRpcFileError(file_path_string()))?; + + let file_metadata = rpc_file + .metadata() + .chain_err(|| ErrorKind::ReadRpcFileError(file_path_string()))?; + + ensure_written_by_admin(&file_path, file_metadata)?; + let reader = BufReader::new(rpc_file); let mut lines = reader.lines(); @@ -84,18 +105,46 @@ impl DaemonRpcClient { } #[cfg(unix)] -pub fn rpc_file_path() -> Result<PathBuf> { - use std::path::Path; +mod platform_specific { + use std::os::unix::fs::MetadataExt; + + use super::*; + + pub fn rpc_file_path() -> Result<PathBuf> { + Ok(Path::new("/tmp/.mullvad_rpc_address").to_path_buf()) + } + + pub fn ensure_written_by_admin<P: AsRef<Path>>(file_path: P, metadata: Metadata) -> Result<()> { + let is_owned_by_root = metadata.uid() == 0; + let is_read_only_by_non_owner = (metadata.mode() & 0o022) == 0; - Ok(Path::new("/tmp/.mullvad_rpc_address").to_path_buf()) + ensure!( + is_owned_by_root && is_read_only_by_non_owner, + ErrorKind::InsecureRpcFile(file_path.as_ref().display().to_string()) + ); + + Ok(()) + } } #[cfg(windows)] -pub fn rpc_file_path() -> Result<PathBuf> { - let windows_directory = - ::std::env::var_os("WINDIR").ok_or_else(|| ErrorKind::UnknownRpcFilePath)?; +mod platform_specific { + use super::*; - Ok(PathBuf::from(windows_directory) - .join("Temp") - .join(".mullvad_rpc_address")) + pub fn rpc_file_path() -> Result<PathBuf> { + let windows_directory = + ::std::env::var_os("WINDIR").ok_or_else(|| ErrorKind::UnknownRpcFilePath)?; + + Ok(PathBuf::from(windows_directory) + .join("Temp") + .join(".mullvad_rpc_address")) + } + + pub fn ensure_written_by_admin<P: AsRef<Path>>( + _file_path: P, + _metadata: Metadata, + ) -> Result<()> { + // TODO: Check permissions correctly + Ok(()) + } } |
