diff options
| author | Sebastian Holmin <sebastian.holmin@mullvad.net> | 2025-04-09 13:47:36 +0200 |
|---|---|---|
| committer | Sebastian Holmin <sebastian.holmin@mullvad.net> | 2025-05-28 13:25:27 +0200 |
| commit | 23e7acba0f8afd4d238df067c836ae649fa80b84 (patch) | |
| tree | bd658b140a9f27066d1d7ae6788d84c3f4af2eef /mullvad-paths/src | |
| parent | c525c77d54f5c449f872094a804d77b7e85bfc55 (diff) | |
| download | mullvadvpn-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.rs | 9 | ||||
| -rw-r--r-- | mullvad-paths/src/lib.rs | 17 | ||||
| -rw-r--r-- | mullvad-paths/src/logs.rs | 16 | ||||
| -rw-r--r-- | mullvad-paths/src/settings.rs | 10 | ||||
| -rw-r--r-- | mullvad-paths/src/unix.rs | 30 | ||||
| -rw-r--r-- | mullvad-paths/src/windows.rs | 46 |
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, |
