Skip to content

Commit

Permalink
Merge branch 'set-permissions-on-log-directory'
Browse files Browse the repository at this point in the history
  • Loading branch information
Jontified committed Nov 13, 2023
2 parents 73c8948 + 59126cf commit e676219
Show file tree
Hide file tree
Showing 11 changed files with 324 additions and 36 deletions.
2 changes: 2 additions & 0 deletions mullvad-nsis/include/mullvad-nsis.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ extern "C" {
/// the final null terminator.
Status get_system_local_appdata(uint16_t *buffer, uintptr_t *buffer_size);

Status create_privileged_directory(const uint16_t* path);

} // extern "C"
39 changes: 37 additions & 2 deletions mullvad-nsis/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
#![cfg(all(target_arch = "x86", target_os = "windows"))]

use std::{os::windows::ffi::OsStrExt, panic::UnwindSafe, ptr};
use std::{
ffi::OsString,
os::windows::ffi::{OsStrExt, OsStringExt},
panic::UnwindSafe,
path::Path,
ptr,
};

#[repr(C)]
pub enum Status {
Expand All @@ -11,6 +17,35 @@ pub enum Status {
Panic,
}

/// Max path size allowed
const MAX_PATH_SIZE: isize = 32_767;

/// SAFETY: path needs to be a windows path encoded as a string of u16 that terminates in 0 (two nul-bytes).
/// The string is also not allowed to be greater than `MAX_PATH_SIZE`.
#[no_mangle]
pub unsafe extern "C" fn create_privileged_directory(path: *const u16) -> Status {
catch_and_log_unwind(|| {
let mut i = 0;
// Calculate the length of the path by checking when the first u16 == 0
let len = loop {
if *(path.offset(i)) == 0 {
break i;
} else if i >= MAX_PATH_SIZE {
return Status::InvalidArguments;
}
i += 1;
};
let path = std::slice::from_raw_parts(path, len as usize);
let path = OsString::from_wide(path);
let path = Path::new(&path);

match mullvad_paths::windows::create_privileged_directory(path) {
Ok(()) => Status::Ok,
Err(_) => Status::OsError,
}
})
}

/// Writes the system's app data path into `buffer` when `Status::Ok` is returned.
/// If `buffer` is `null`, or if the buffer is too small, `InsufficientBufferSize`
/// is returned, and the required buffer size (in chars) is returned in `buffer_size`.
Expand Down Expand Up @@ -53,6 +88,6 @@ pub unsafe extern "C" fn get_system_local_appdata(
fn catch_and_log_unwind(func: impl FnOnce() -> Status + UnwindSafe) -> Status {
match std::panic::catch_unwind(func) {
Ok(status) => status,
Err(_error) => Status::Panic,
Err(_) => Status::Panic,
}
}
2 changes: 2 additions & 0 deletions mullvad-paths/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ workspace = true
features = [
"Win32_Foundation",
"Win32_Security",
"Win32_Security_Authorization",
"Win32_Storage_FileSystem",
"Win32_System_Com",
"Win32_System_ProcessStatus",
"Win32_System_SystemServices",
"Win32_System_Threading",
"Win32_UI_Shell",
"Win32_System_Memory",
]
4 changes: 3 additions & 1 deletion mullvad-paths/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ 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(not(target_os = "macos"))]
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
let permissions = None;
#[cfg(target_os = "macos")]
let permissions = Some(std::os::unix::fs::PermissionsExt::from_mode(0o755));
#[cfg(target_os = "windows")]
let permissions = true;
crate::create_and_return(get_cache_dir, permissions)
}

Expand Down
22 changes: 21 additions & 1 deletion mullvad-paths/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#![deny(rust_2018_idioms)]

use std::{fs, io, path::PathBuf};
#[cfg(not(target_os = "windows"))]
use std::fs;
use std::{io, path::PathBuf};

#[cfg(windows)]
use crate::windows::create_dir_recursive;

pub type Result<T> = std::result::Result<T, Error>;

Expand All @@ -20,6 +25,10 @@ pub enum Error {
#[error(display = "Missing %ALLUSERSPROFILE% environment variable")]
NoProgramDataDir,

#[cfg(windows)]
#[error(display = "Failed to create security attributes")]
GetSecurityAttributes(#[error(source)] io::Error),

#[cfg(all(windows, feature = "deduce-system-service"))]
#[error(display = "Failed to deduce system service directory")]
FailedToFindSystemServiceDir(#[error(source)] io::Error),
Expand All @@ -42,6 +51,7 @@ fn get_allusersprofile_dir() -> Result<PathBuf> {
}
}

#[cfg(not(target_os = "windows"))]
fn create_and_return(
dir_fn: fn() -> Result<PathBuf>,
permissions: Option<fs::Permissions>,
Expand All @@ -55,6 +65,16 @@ fn create_and_return(
Ok(dir)
}

#[cfg(windows)]
fn create_and_return(
dir_fn: fn() -> Result<PathBuf>,
set_security_permissions: bool,
) -> Result<PathBuf> {
let dir = dir_fn()?;
create_dir_recursive(&dir, set_security_permissions)?;
Ok(dir)
}

mod cache;
pub use crate::cache::{cache_dir, get_cache_dir, get_default_cache_dir};

Expand Down
12 changes: 8 additions & 4 deletions mullvad-paths/src/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ use std::{env, path::PathBuf};
/// one if that variable is unset.
pub fn log_dir() -> Result<PathBuf> {
#[cfg(unix)]
let permissions = Some(PermissionsExt::from_mode(0o755));
#[cfg(not(unix))]
let permissions = None;
crate::create_and_return(get_log_dir, permissions)
{
let permissions = Some(PermissionsExt::from_mode(0o755));
crate::create_and_return(get_log_dir, permissions)
}
#[cfg(target_os = "windows")]
{
crate::create_and_return(get_log_dir, true)
}
}

/// Get the logging directory, but don't try to create it.
Expand Down
10 changes: 9 additions & 1 deletion mullvad-paths/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@ 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> {
crate::create_and_return(get_settings_dir, None)
#[cfg(not(target_os = "windows"))]
{
crate::create_and_return(get_settings_dir, None)
}

#[cfg(target_os = "windows")]
{
crate::create_and_return(get_settings_dir, false)
}
}

fn get_settings_dir() -> Result<PathBuf> {
Expand Down
Loading

0 comments on commit e676219

Please sign in to comment.