summaryrefslogtreecommitdiffhomepage
path: root/mullvad-paths/src
diff options
context:
space:
mode:
authorSebastian Holmin <sebastian.holmin@mullvad.net>2025-04-09 13:47:36 +0200
committerSebastian Holmin <sebastian.holmin@mullvad.net>2025-05-28 13:25:27 +0200
commit23e7acba0f8afd4d238df067c836ae649fa80b84 (patch)
treebd658b140a9f27066d1d7ae6788d84c3f4af2eef /mullvad-paths/src
parentc525c77d54f5c449f872094a804d77b7e85bfc55 (diff)
downloadmullvadvpn-23e7acba0f8afd4d238df067c836ae649fa80b84.tar.xz
mullvadvpn-23e7acba0f8afd4d238df067c836ae649fa80b84.zip
Add in app upgrades to the daemon
--------- Co-authored-by: Markus Pettersson <markus.pettersson@mullvad.net>
Diffstat (limited to 'mullvad-paths/src')
-rw-r--r--mullvad-paths/src/cache.rs9
-rw-r--r--mullvad-paths/src/lib.rs17
-rw-r--r--mullvad-paths/src/logs.rs16
-rw-r--r--mullvad-paths/src/settings.rs10
-rw-r--r--mullvad-paths/src/unix.rs30
-rw-r--r--mullvad-paths/src/windows.rs46
6 files changed, 76 insertions, 52 deletions
diff --git a/mullvad-paths/src/cache.rs b/mullvad-paths/src/cache.rs
index 3b31a9460b..26f36a4629 100644
--- a/mullvad-paths/src/cache.rs
+++ b/mullvad-paths/src/cache.rs
@@ -4,10 +4,11 @@ use std::{env, path::PathBuf};
/// Creates and returns the cache directory pointed to by `MULLVAD_CACHE_DIR`, or the default
/// one if that variable is unset.
pub fn cache_dir() -> Result<PathBuf> {
- #[cfg(unix)]
- let permissions = crate::unix::Permissions::ReadExecOnly;
- #[cfg(target_os = "windows")]
- let permissions = true;
+ let permissions = Some(crate::UserPermissions {
+ read: true,
+ write: false,
+ execute: true,
+ });
crate::create_dir(get_cache_dir()?, permissions)
}
diff --git a/mullvad-paths/src/lib.rs b/mullvad-paths/src/lib.rs
index c5eb5b9a52..508a3e8956 100644
--- a/mullvad-paths/src/lib.rs
+++ b/mullvad-paths/src/lib.rs
@@ -46,6 +46,23 @@ pub enum Error {
NoDataDir,
}
+#[derive(Clone, Copy)]
+pub struct UserPermissions {
+ pub read: bool,
+ pub write: bool,
+ pub execute: bool,
+}
+
+impl UserPermissions {
+ pub fn read_only() -> Self {
+ UserPermissions {
+ read: true,
+ write: false,
+ execute: false,
+ }
+ }
+}
+
#[cfg(unix)]
use unix::create_dir;
diff --git a/mullvad-paths/src/logs.rs b/mullvad-paths/src/logs.rs
index 03ab990632..5a1fb2034d 100644
--- a/mullvad-paths/src/logs.rs
+++ b/mullvad-paths/src/logs.rs
@@ -4,14 +4,14 @@ use std::{env, path::PathBuf};
/// Creates and returns the logging directory pointed to by `MULLVAD_LOG_DIR`, or the default
/// one if that variable is unset.
pub fn log_dir() -> Result<PathBuf> {
- #[cfg(unix)]
- {
- crate::create_dir(get_log_dir()?, crate::unix::Permissions::ReadExecOnly)
- }
- #[cfg(target_os = "windows")]
- {
- crate::create_dir(get_log_dir()?, true)
- }
+ let permissions = Some(crate::UserPermissions {
+ read: true,
+ write: false,
+ // Unix: Make directory contents readable
+ execute: cfg!(unix),
+ });
+
+ crate::create_dir(get_log_dir()?, permissions)
}
/// Get the logging directory, but don't try to create it.
diff --git a/mullvad-paths/src/settings.rs b/mullvad-paths/src/settings.rs
index 016e158bee..3852c56ddd 100644
--- a/mullvad-paths/src/settings.rs
+++ b/mullvad-paths/src/settings.rs
@@ -4,15 +4,7 @@ use std::{env, path::PathBuf};
/// Creates and returns the settings directory pointed to by `MULLVAD_SETTINGS_DIR`, or the default
/// one if that variable is unset.
pub fn settings_dir() -> Result<PathBuf> {
- #[cfg(unix)]
- {
- crate::create_dir(get_settings_dir()?, crate::unix::Permissions::Any)
- }
-
- #[cfg(target_os = "windows")]
- {
- crate::create_dir(get_settings_dir()?, false)
- }
+ crate::create_dir(get_settings_dir()?, None)
}
fn get_settings_dir() -> Result<PathBuf> {
diff --git a/mullvad-paths/src/unix.rs b/mullvad-paths/src/unix.rs
index 90a5d2fc5c..5d5b3b03a1 100644
--- a/mullvad-paths/src/unix.rs
+++ b/mullvad-paths/src/unix.rs
@@ -4,35 +4,29 @@ use std::{
path::{Path, PathBuf},
};
-use crate::{Error, Result};
+use crate::{Error, Result, UserPermissions};
pub const PRODUCT_NAME: &str = "mullvad-vpn";
-#[derive(Clone, Copy, PartialEq)]
-pub enum Permissions {
- /// Do not set any particular permissions. They will be inherited instead.
- Any,
- /// Only root should have write access. Other users will have
- /// read and execute permissions (0o755).
- ReadExecOnly,
-}
+impl UserPermissions {
+ fn fs_permissions(self) -> fs::Permissions {
+ const OWNER_BITS: u32 = 0o700;
-impl Permissions {
- fn fs_permissions(self) -> Option<fs::Permissions> {
- match self {
- Permissions::Any => None,
- Permissions::ReadExecOnly => Some(std::os::unix::fs::PermissionsExt::from_mode(0o755)),
- }
+ let rbits = if self.read { 0o044 } else { 0 };
+ let wbits = if self.write { 0o022 } else { 0 };
+ let ebits = if self.execute { 0o011 } else { 0 };
+
+ std::os::unix::fs::PermissionsExt::from_mode(OWNER_BITS | rbits | wbits | ebits)
}
}
/// Create a directory at `dir`, setting the permissions given by `permissions`, unless it exists.
/// If the directory already exists, but the permissions are not at least as strict as expected,
/// then it will be deleted and recreated.
-pub fn create_dir(dir: PathBuf, permissions: Permissions) -> Result<PathBuf> {
+pub fn create_dir(dir: PathBuf, permissions: Option<UserPermissions>) -> Result<PathBuf> {
let mut dir_builder = fs::DirBuilder::new();
- let fs_perms = permissions.fs_permissions();
- if let Some(fs_perms) = fs_perms.as_ref() {
+ let fs_perms = permissions.as_ref().map(|perms| perms.fs_permissions());
+ if let Some(fs_perms) = &fs_perms {
dir_builder.mode(fs_perms.mode());
}
match dir_builder.create(&dir) {
diff --git a/mullvad-paths/src/windows.rs b/mullvad-paths/src/windows.rs
index 102fa53f5f..5bab1c68f3 100644
--- a/mullvad-paths/src/windows.rs
+++ b/mullvad-paths/src/windows.rs
@@ -1,6 +1,6 @@
#![allow(clippy::undocumented_unsafe_blocks)] // Remove me if you dare.
-use crate::{Error, Result};
+use crate::{Error, Result, UserPermissions};
use once_cell::sync::OnceCell;
use std::{
ffi::OsStr,
@@ -15,7 +15,7 @@ use windows_sys::{
Win32::{
Foundation::{
CloseHandle, LocalFree, ERROR_INSUFFICIENT_BUFFER, ERROR_SUCCESS, GENERIC_ALL,
- GENERIC_READ, HANDLE, INVALID_HANDLE_VALUE, LUID, S_OK,
+ GENERIC_EXECUTE, GENERIC_READ, GENERIC_WRITE, HANDLE, INVALID_HANDLE_VALUE, LUID, S_OK,
},
Security::{
self, AdjustTokenPrivileges,
@@ -58,9 +58,10 @@ pub fn get_allusersprofile_dir() -> Result<PathBuf> {
/// file permissions corresponding to Authenticated Users - Read Only and Administrators - Full
/// Access. Only directories that do not already exist and the leaf directory will have their
/// permissions set.
-pub fn create_dir(path: PathBuf, set_security_permissions: bool) -> Result<PathBuf> {
- if set_security_permissions {
- create_dir_with_permissions_recursive(&path)?;
+#[cfg(windows)]
+pub fn create_dir(path: PathBuf, user_permissions: Option<UserPermissions>) -> Result<PathBuf> {
+ if let Some(user_permissions) = user_permissions {
+ create_dir_recursive_with_permissions(&path, user_permissions)?;
} else {
std::fs::create_dir_all(&path).map_err(|e| {
Error::CreateDirFailed(
@@ -93,12 +94,31 @@ fn get_wide_str<S: AsRef<OsStr>>(string: S) -> Vec<u16> {
wide_string
}
+impl UserPermissions {
+ fn flags(self) -> u32 {
+ let mut flags = 0;
+ if self.read {
+ flags |= GENERIC_READ;
+ }
+ if self.write {
+ flags |= GENERIC_WRITE;
+ }
+ if self.execute {
+ flags |= GENERIC_EXECUTE;
+ }
+ flags
+ }
+}
+
/// If directory at path already exists, set permissions for it.
/// If directory at path don't exist but parent does, create directory and set permissions.
/// If parent directory at path does not exist then recurse and create parent directory and set
/// permissions for it, then create child directory and set permissions.
/// This does not set permissions for parent directories that already exists.
-fn create_dir_with_permissions_recursive(path: &Path) -> Result<()> {
+fn create_dir_recursive_with_permissions(
+ path: &Path,
+ user_permissions: UserPermissions,
+) -> Result<()> {
// No directory to create
if path == Path::new("") {
return Ok(());
@@ -106,13 +126,13 @@ fn create_dir_with_permissions_recursive(path: &Path) -> Result<()> {
match std::fs::create_dir(path) {
Ok(()) => {
- return set_security_permissions(path);
+ return set_security_permissions(path, user_permissions);
}
// Could not find parent directory, try creating parent
Err(e) if e.kind() == io::ErrorKind::NotFound => (),
// Directory already exists, set permissions
Err(e) if e.kind() == io::ErrorKind::AlreadyExists && path.is_dir() => {
- return set_security_permissions(path);
+ return set_security_permissions(path, user_permissions);
}
Err(e) => {
return Err(Error::CreateDirFailed(
@@ -124,7 +144,7 @@ fn create_dir_with_permissions_recursive(path: &Path) -> Result<()> {
match path.parent() {
// Create parent directory
- Some(parent) => create_dir_with_permissions_recursive(parent)?,
+ Some(parent) => create_dir_recursive_with_permissions(parent, user_permissions)?,
None => {
// Reached the top of the tree but when creating directories only got NotFound for some
// reason
@@ -139,19 +159,19 @@ fn create_dir_with_permissions_recursive(path: &Path) -> Result<()> {
}
std::fs::create_dir(path).map_err(|e| Error::CreateDirFailed(path.display().to_string(), e))?;
- set_security_permissions(path)
+ set_security_permissions(path, user_permissions)
}
/// Recursively creates directories for the given path with permissions that give full access to
/// admins and read only access to authenticated users. If any of the directories already exist this
/// will not return an error, instead it will apply the permissions and if successful return Ok(()).
pub fn create_privileged_directory(path: &Path) -> Result<()> {
- create_dir_with_permissions_recursive(path)
+ create_dir_recursive_with_permissions(path, UserPermissions::read_only())
}
/// Sets security permissions for path such that admin has full ownership and access while
/// authenticated users only have read access.
-fn set_security_permissions(path: &Path) -> Result<()> {
+fn set_security_permissions(path: &Path, user_permissions: UserPermissions) -> Result<()> {
let wide_path = get_wide_str(path);
let security_information = Security::DACL_SECURITY_INFORMATION
| Security::PROTECTED_DACL_SECURITY_INFORMATION
@@ -216,7 +236,7 @@ fn set_security_permissions(path: &Path) -> Result<()> {
};
let authenticated_users_ea = EXPLICIT_ACCESS_W {
- grfAccessPermissions: GENERIC_READ,
+ grfAccessPermissions: user_permissions.flags(),
grfAccessMode: SET_ACCESS,
grfInheritance: NO_INHERITANCE | SUB_CONTAINERS_AND_OBJECTS_INHERIT,
Trustee: trustee,