summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2018-04-23 19:17:37 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2018-05-03 08:23:30 -0300
commitbd46e9fdf89df598336d1f0d1e295bce22eff6a5 (patch)
tree623aa8f49289be21bc38265146004a62c82ed243
parent0b070ccd77c44dc86a0cac64e2587cb0aa23ad2c (diff)
downloadmullvadvpn-bd46e9fdf89df598336d1f0d1e295bce22eff6a5.tar.xz
mullvadvpn-bd46e9fdf89df598336d1f0d1e295bce22eff6a5.zip
Check RPC file security
-rw-r--r--mullvad-ipc-client/src/lib.rs71
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(())
+ }
}