summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2021-04-08 14:13:50 +0200
committerDavid Lönnhager <david.l@mullvad.net>2021-04-08 14:13:50 +0200
commit041f348a07b3044499f79aea413668ef82b8381e (patch)
tree35341a9ba060706af4c7894c2f92dfd9e30bc8dd
parenteb0c1ddff764f77c3960b041e63527cfbbe668fb (diff)
parent24d8ce38d0d39810780c80a842b6bfeda1aaed8a (diff)
downloadmullvadvpn-041f348a07b3044499f79aea413668ef82b8381e.tar.xz
mullvadvpn-041f348a07b3044499f79aea413668ef82b8381e.zip
Merge branch 'restrict-socket-perms'
-rw-r--r--CHANGELOG.md2
-rw-r--r--Cargo.lock2
-rw-r--r--README.md4
-rw-r--r--mullvad-management-interface/Cargo.toml4
-rw-r--r--mullvad-management-interface/src/lib.rs38
-rw-r--r--talpid-core/src/tunnel/openvpn/mod.rs5
6 files changed, 44 insertions, 11 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 760fe1b88f..ac2bb198a9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,6 +25,8 @@ Line wrap the file at 100 chars. Th
## [Unreleased]
### Added
- Preserve log of old daemon instance when upgrading on Desktop.
+- When `MULLVAD_MANAGEMENT_SOCKET_GROUP` is set, only allow the specified group to access the
+ management interface UDS socket. This means that only users in that group can use the CLI and GUI.
#### Linux
- Always enable `src_valid_mark` config option when connecting to allow policty based routing.
diff --git a/Cargo.lock b/Cargo.lock
index 93fe8d713f..f6ee1fbb81 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1331,7 +1331,9 @@ version = "0.1.0"
dependencies = [
"err-derive 0.3.0",
"futures",
+ "lazy_static",
"mullvad-paths",
+ "nix 0.19.1",
"parity-tokio-ipc",
"prost",
"prost-types",
diff --git a/README.md b/README.md
index e3fa150e8d..6d3c970c82 100644
--- a/README.md
+++ b/README.md
@@ -434,6 +434,10 @@ echo "org.gradle.jvmargs=-Xmx4608M" >> ~/.gradle/gradle.properties
servers are used.
* `TALPID_DISABLE_OFFLINE_MONITOR` - Forces the daemon to always assume the host is online.
+* `MULLVAD_MANAGEMENT_SOCKET_GROUP` - On Linux and macOS, this restricts access to the management
+ interface UDS socket to users in the specified group. This means that only users in that group can
+ use the CLI and GUI. By default, everyone has access to the socket.
+
#### Setting environment variable
- On Windows, one can use `setx` from an elevated shell, like so
```bat
diff --git a/mullvad-management-interface/Cargo.toml b/mullvad-management-interface/Cargo.toml
index 2219fc728f..cb28f4b9ed 100644
--- a/mullvad-management-interface/Cargo.toml
+++ b/mullvad-management-interface/Cargo.toml
@@ -19,5 +19,9 @@ futures = "0.3"
tokio = { version = "0.2", features = [ "rt-util" ] }
triggered = "0.1.1"
+[target.'cfg(unix)'.dependencies]
+nix = "0.19"
+lazy_static = "1.0"
+
[build-dependencies]
tonic-build = { version = "0.3", default-features = false, features = ["transport", "prost"] }
diff --git a/mullvad-management-interface/src/lib.rs b/mullvad-management-interface/src/lib.rs
index 8b16aff46e..abf4282923 100644
--- a/mullvad-management-interface/src/lib.rs
+++ b/mullvad-management-interface/src/lib.rs
@@ -6,7 +6,7 @@ pub mod types {
use parity_tokio_ipc::Endpoint as IpcEndpoint;
#[cfg(unix)]
-use std::{fs, os::unix::fs::PermissionsExt};
+use std::{env, fs, os::unix::fs::PermissionsExt};
use std::{
io,
pin::Pin,
@@ -22,6 +22,12 @@ pub type ManagementServiceClient =
types::management_service_client::ManagementServiceClient<Channel>;
pub use types::management_service_server::{ManagementService, ManagementServiceServer};
+#[cfg(unix)]
+lazy_static::lazy_static! {
+ static ref MULLVAD_MANAGEMENT_SOCKET_GROUP: Option<String> = env::var("MULLVAD_MANAGEMENT_SOCKET_GROUP")
+ .ok();
+}
+
#[derive(err_derive::Error, Debug)]
#[error(no_from)]
pub enum Error {
@@ -36,6 +42,18 @@ pub enum Error {
#[error(display = "Unable to set permissions for IPC endpoint")]
PermissionsError(#[error(source)] io::Error),
+
+ #[cfg(unix)]
+ #[error(display = "Group not found")]
+ NoGidError,
+
+ #[cfg(unix)]
+ #[error(display = "Failed to obtain group ID")]
+ ObtainGidError(#[error(source)] nix::Error),
+
+ #[cfg(unix)]
+ #[error(display = "Failed to set group ID")]
+ SetGidError(#[error(source)] nix::Error),
}
pub async fn new_rpc_client() -> Result<ManagementServiceClient, Error> {
@@ -60,22 +78,26 @@ pub async fn spawn_rpc_server<T: ManagementService>(
use futures::stream::TryStreamExt;
use parity_tokio_ipc::SecurityAttributes;
- let socket_path = mullvad_paths::get_rpc_socket_path()
- .to_string_lossy()
- .to_string();
+ let socket_path = mullvad_paths::get_rpc_socket_path();
- let mut endpoint = IpcEndpoint::new(socket_path.to_string());
+ let mut endpoint = IpcEndpoint::new(socket_path.to_string_lossy().to_string());
endpoint.set_security_attributes(
SecurityAttributes::allow_everyone_create()
.map_err(Error::SecurityAttributes)?
- .set_mode(777)
+ .set_mode(0o766)
.map_err(Error::SecurityAttributes)?,
);
let incoming = endpoint.incoming().map_err(Error::StartServerError)?;
#[cfg(unix)]
- fs::set_permissions(&socket_path, PermissionsExt::from_mode(0o766))
- .map_err(Error::PermissionsError)?;
+ if let Some(group_name) = &*MULLVAD_MANAGEMENT_SOCKET_GROUP {
+ let group = nix::unistd::Group::from_name(group_name)
+ .map_err(Error::ObtainGidError)?
+ .ok_or(Error::NoGidError)?;
+ nix::unistd::chown(&socket_path, None, Some(group.gid)).map_err(Error::SetGidError)?;
+ fs::set_permissions(&socket_path, PermissionsExt::from_mode(0o760))
+ .map_err(Error::PermissionsError)?;
+ }
let _ = server_start_tx.send(());
diff --git a/talpid-core/src/tunnel/openvpn/mod.rs b/talpid-core/src/tunnel/openvpn/mod.rs
index 520181d3cc..cbb89f912e 100644
--- a/talpid-core/src/tunnel/openvpn/mod.rs
+++ b/talpid-core/src/tunnel/openvpn/mod.rs
@@ -901,7 +901,7 @@ impl ProcessHandle for OpenVpnProcHandle {
mod event_server {
use futures::stream::TryStreamExt;
- use parity_tokio_ipc::{Endpoint as IpcEndpoint, SecurityAttributes};
+ use parity_tokio_ipc::Endpoint as IpcEndpoint;
use std::{
collections::HashMap,
convert::TryFrom,
@@ -973,8 +973,7 @@ mod event_server {
where
L: Fn(openvpn_plugin::EventType, HashMap<String, String>) + Send + Sync + 'static,
{
- let mut endpoint = IpcEndpoint::new(ipc_path.clone());
- endpoint.set_security_attributes(SecurityAttributes::allow_everyone_create().unwrap());
+ let endpoint = IpcEndpoint::new(ipc_path);
let incoming = endpoint.incoming().map_err(Error::StartServer)?;
let _ = server_start_tx.send(());