From 6f2e351beed5ae4bff12116659b9809db354b429 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Fri, 19 Sep 2025 09:49:10 +0200 Subject: [PATCH 1/7] ensure data directories have appropriate permissions --- src-tauri/src/bin/defguard-client.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src-tauri/src/bin/defguard-client.rs b/src-tauri/src/bin/defguard-client.rs index 3f0699db..dfee4697 100644 --- a/src-tauri/src/bin/defguard-client.rs +++ b/src-tauri/src/bin/defguard-client.rs @@ -3,7 +3,13 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -use std::{env, str::FromStr, sync::LazyLock}; +use std::{ + env, + fs::{set_permissions, Permissions}, + os::unix::fs::PermissionsExt, + str::FromStr, + sync::LazyLock, +}; #[cfg(target_os = "windows")] use defguard_client::utils::sync_connections; @@ -277,15 +283,22 @@ fn main() { app.run(|app_handle, event| match event { // Startup tasks RunEvent::Ready => { + // Ensure data directory has appropriate permissions (dg25-28) + let data_dir = app_handle + .path() + .app_data_dir() + .unwrap_or_else(|_| "UNDEFINED DATA DIRECTORY".into()); + if let Err(err) = set_permissions(&data_dir, Permissions::from_mode(0o700)) { + warn!( + "Failed to set permissions on data directory {}: {err}", + data_dir.display() + ); + } info!( "Application data (database file) will be stored in: {} and application logs in: {}. \ Logs of the background Defguard service responsible for managing VPN connections at the \ network level will be stored in: {}.", - // display the path to the app data directory, convert option to option<&str> - app_handle - .path() - .app_data_dir() - .unwrap_or_else(|_| "UNDEFINED DATA DIRECTORY".into()).display(), + data_dir.display(), app_handle .path() .app_log_dir() From 630a2d24d50f6c4a6c200682b8bff49ef215436f Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Fri, 19 Sep 2025 10:17:52 +0200 Subject: [PATCH 2/7] also set permissions for log directory --- src-tauri/src/bin/defguard-client.rs | 35 +++++++++++++++++----------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src-tauri/src/bin/defguard-client.rs b/src-tauri/src/bin/defguard-client.rs index dfee4697..dcddae92 100644 --- a/src-tauri/src/bin/defguard-client.rs +++ b/src-tauri/src/bin/defguard-client.rs @@ -283,26 +283,35 @@ fn main() { app.run(|app_handle, event| match event { // Startup tasks RunEvent::Ready => { - // Ensure data directory has appropriate permissions (dg25-28) let data_dir = app_handle .path() .app_data_dir() .unwrap_or_else(|_| "UNDEFINED DATA DIRECTORY".into()); - if let Err(err) = set_permissions(&data_dir, Permissions::from_mode(0o700)) { - warn!( - "Failed to set permissions on data directory {}: {err}", - data_dir.display() - ); - } + let log_dir = app_handle + .path() + .app_log_dir() + .unwrap_or_else(|_| "UNDEFINED LOG DIRECTORY".into()); + + // Ensure directories have appropriate permissions (dg25-28). + #[cfg(not(windows))] + { + if let Err(err) = set_permissions(&data_dir, Permissions::from_mode(0o700)) { + warn!( + "Failed to set permissions on data directory {}: {err}", + data_dir.display() + ); + } + if let Err(err) = set_permissions(&log_dir, Permissions::from_mode(0o700)) { + warn!( + "Failed to set permissions on log directory {}: {err}", + log_dir.display() + ); + } + } info!( - "Application data (database file) will be stored in: {} and application logs in: {}. \ + "Application data (database file) will be stored in: {data_dir:?} and application logs in: {log_dir:?}. \ Logs of the background Defguard service responsible for managing VPN connections at the \ network level will be stored in: {}.", - data_dir.display(), - app_handle - .path() - .app_log_dir() - .unwrap_or_else(|_| "UNDEFINED LOG DIRECTORY".into()).display(), service::config::DEFAULT_LOG_DIR ); tauri::async_runtime::block_on(startup(app_handle)); From b141790d1e2bab55b146b1e7da1cd6f8fb7ff5fe Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Fri, 19 Sep 2025 10:19:21 +0200 Subject: [PATCH 3/7] formatting --- src-tauri/src/bin/defguard-client.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src-tauri/src/bin/defguard-client.rs b/src-tauri/src/bin/defguard-client.rs index dcddae92..fe2fd05a 100644 --- a/src-tauri/src/bin/defguard-client.rs +++ b/src-tauri/src/bin/defguard-client.rs @@ -294,20 +294,20 @@ fn main() { // Ensure directories have appropriate permissions (dg25-28). #[cfg(not(windows))] - { - if let Err(err) = set_permissions(&data_dir, Permissions::from_mode(0o700)) { - warn!( - "Failed to set permissions on data directory {}: {err}", - data_dir.display() - ); - } - if let Err(err) = set_permissions(&log_dir, Permissions::from_mode(0o700)) { - warn!( - "Failed to set permissions on log directory {}: {err}", - log_dir.display() - ); - } + { + if let Err(err) = set_permissions(&data_dir, Permissions::from_mode(0o700)) { + warn!( + "Failed to set permissions on data directory {}: {err}", + data_dir.display() + ); + } + if let Err(err) = set_permissions(&log_dir, Permissions::from_mode(0o700)) { + warn!( + "Failed to set permissions on log directory {}: {err}", + log_dir.display() + ); } + } info!( "Application data (database file) will be stored in: {data_dir:?} and application logs in: {log_dir:?}. \ Logs of the background Defguard service responsible for managing VPN connections at the \ From 60933ceb714079ee9154c582a2f7112f638c1040 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Fri, 19 Sep 2025 10:48:57 +0200 Subject: [PATCH 4/7] set permissions for other files/directories --- src-tauri/src/app_config.rs | 4 ++++ src-tauri/src/bin/defguard-client.rs | 30 ++++------------------------ src-tauri/src/database/mod.rs | 9 ++++++++- src-tauri/src/lib.rs | 18 +++++++++++++++++ 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src-tauri/src/app_config.rs b/src-tauri/src/app_config.rs index d949d67f..bbc107d0 100644 --- a/src-tauri/src/app_config.rs +++ b/src-tauri/src/app_config.rs @@ -9,6 +9,8 @@ use struct_patch::Patch; use strum::{Display, EnumString}; use tauri::{AppHandle, Manager}; +use crate::set_perms; + static APP_CONFIG_FILE_NAME: &str = "config.json"; fn get_config_file_path(app: &AppHandle) -> PathBuf { @@ -19,7 +21,9 @@ fn get_config_file_path(app: &AppHandle) -> PathBuf { if !config_file_path.exists() { create_dir_all(&config_file_path).expect("Failed to create missing app data dir"); } + set_perms(&config_file_path, true); config_file_path.push(APP_CONFIG_FILE_NAME); + set_perms(&config_file_path, false); config_file_path } diff --git a/src-tauri/src/bin/defguard-client.rs b/src-tauri/src/bin/defguard-client.rs index fe2fd05a..862be75a 100644 --- a/src-tauri/src/bin/defguard-client.rs +++ b/src-tauri/src/bin/defguard-client.rs @@ -14,19 +14,10 @@ use std::{ #[cfg(target_os = "windows")] use defguard_client::utils::sync_connections; use defguard_client::{ - active_connections::close_all_connections, - app_config::AppConfig, - appstate::AppState, - commands::*, - database::{ + active_connections::close_all_connections, app_config::AppConfig, appstate::AppState, commands::*, database::{ models::{location_stats::LocationStats, tunnel::TunnelStats}, DB_POOL, - }, - periodic::run_periodic_tasks, - service, - tray::{configure_tray_icon, setup_tray, show_main_window}, - utils::load_log_targets, - VERSION, + }, periodic::run_periodic_tasks, service, set_perms, tray::{configure_tray_icon, setup_tray, show_main_window}, utils::load_log_targets, VERSION }; use log::{Level, LevelFilter}; #[cfg(target_os = "macos")] @@ -293,21 +284,8 @@ fn main() { .unwrap_or_else(|_| "UNDEFINED LOG DIRECTORY".into()); // Ensure directories have appropriate permissions (dg25-28). - #[cfg(not(windows))] - { - if let Err(err) = set_permissions(&data_dir, Permissions::from_mode(0o700)) { - warn!( - "Failed to set permissions on data directory {}: {err}", - data_dir.display() - ); - } - if let Err(err) = set_permissions(&log_dir, Permissions::from_mode(0o700)) { - warn!( - "Failed to set permissions on log directory {}: {err}", - log_dir.display() - ); - } - } + set_perms(&data_dir, true); + set_perms(&log_dir, true); info!( "Application data (database file) will be stored in: {data_dir:?} and application logs in: {log_dir:?}. \ Logs of the background Defguard service responsible for managing VPN connections at the \ diff --git a/src-tauri/src/database/mod.rs b/src-tauri/src/database/mod.rs index e2a03b6a..c74d9e7d 100644 --- a/src-tauri/src/database/mod.rs +++ b/src-tauri/src/database/mod.rs @@ -6,10 +6,15 @@ use std::{ str::FromStr, sync::LazyLock, }; +#[cfg(not(windows))] +use std::{ + fs::{set_permissions, Permissions}, + os::unix::fs::PermissionsExt, +}; use sqlx::sqlite::{SqliteAutoVacuum, SqliteConnectOptions, SqliteJournalMode, SqlitePool}; -use crate::{app_data_dir, error::Error}; +use crate::{app_data_dir, error::Error, set_perms}; const DB_NAME: &str = "defguard.db"; @@ -59,6 +64,7 @@ fn prepare_db_url() -> Result { app_dir.to_string_lossy() ); } + set_perms(&app_dir, true); let db_path = app_dir.join(DB_NAME); if db_path.exists() { debug!( @@ -77,6 +83,7 @@ fn prepare_db_url() -> Result { db_path.to_string_lossy() ); } + set_perms(&db_path, false); debug!( "Application's database file is located at: {}", db_path.to_string_lossy() diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index e57ddd2c..881d5151 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,6 +1,11 @@ // FIXME: actually refactor errors instead #![allow(clippy::result_large_err)] use std::{fmt, path::PathBuf}; +#[cfg(not(windows))] +use std::{ + fs::{set_permissions, Permissions}, + os::unix::fs::PermissionsExt, +}; use chrono::NaiveDateTime; use semver::Version; @@ -77,6 +82,19 @@ pub fn app_data_dir() -> Option { dirs_next::data_dir().map(|dir| dir.join(BUNDLE_IDENTIFIER)) } +/// Ensures path has appropriate permissions set (dg25-28): +/// - 700 for directories +/// - 600 for files +pub fn set_perms(path: &PathBuf, is_directory: bool) { + #[cfg(not(windows))] + { + let perms = if is_directory { 0o700 } else { 0o600 }; + if let Err(err) = set_permissions(path, Permissions::from_mode(perms)) { + warn!("Failed to set permissions on path {path:?}: {err}"); + } + } +} + /// Location type used in commands to check if we using tunnel or location #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub enum ConnectionType { From c7b79af39d634320b4d945f33a5c35b65916a3b8 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Fri, 19 Sep 2025 10:51:16 +0200 Subject: [PATCH 5/7] cargo fmt & clippy --- src-tauri/src/bin/defguard-client.rs | 21 ++++++++++++--------- src-tauri/src/database/mod.rs | 9 ++------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src-tauri/src/bin/defguard-client.rs b/src-tauri/src/bin/defguard-client.rs index 862be75a..8984f897 100644 --- a/src-tauri/src/bin/defguard-client.rs +++ b/src-tauri/src/bin/defguard-client.rs @@ -3,21 +3,24 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -use std::{ - env, - fs::{set_permissions, Permissions}, - os::unix::fs::PermissionsExt, - str::FromStr, - sync::LazyLock, -}; +use std::{env, str::FromStr, sync::LazyLock}; #[cfg(target_os = "windows")] use defguard_client::utils::sync_connections; use defguard_client::{ - active_connections::close_all_connections, app_config::AppConfig, appstate::AppState, commands::*, database::{ + active_connections::close_all_connections, + app_config::AppConfig, + appstate::AppState, + commands::*, + database::{ models::{location_stats::LocationStats, tunnel::TunnelStats}, DB_POOL, - }, periodic::run_periodic_tasks, service, set_perms, tray::{configure_tray_icon, setup_tray, show_main_window}, utils::load_log_targets, VERSION + }, + periodic::run_periodic_tasks, + service, set_perms, + tray::{configure_tray_icon, setup_tray, show_main_window}, + utils::load_log_targets, + VERSION, }; use log::{Level, LevelFilter}; #[cfg(target_os = "macos")] diff --git a/src-tauri/src/database/mod.rs b/src-tauri/src/database/mod.rs index c74d9e7d..b813f857 100644 --- a/src-tauri/src/database/mod.rs +++ b/src-tauri/src/database/mod.rs @@ -1,16 +1,9 @@ -pub mod models; - use std::{ env, fs::{create_dir_all, File}, str::FromStr, sync::LazyLock, }; -#[cfg(not(windows))] -use std::{ - fs::{set_permissions, Permissions}, - os::unix::fs::PermissionsExt, -}; use sqlx::sqlite::{SqliteAutoVacuum, SqliteConnectOptions, SqliteJournalMode, SqlitePool}; @@ -18,6 +11,8 @@ use crate::{app_data_dir, error::Error, set_perms}; const DB_NAME: &str = "defguard.db"; +pub mod models; + pub(crate) type DbPool = SqlitePool; pub static DB_POOL: LazyLock = LazyLock::new(|| { From ddd81e43b5fe4849286fe06ebae0bc66796d2d8f Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Fri, 19 Sep 2025 11:06:42 +0200 Subject: [PATCH 6/7] automatically determine if path is a directory --- src-tauri/src/app_config.rs | 4 ++-- src-tauri/src/bin/defguard-client.rs | 4 ++-- src-tauri/src/database/mod.rs | 4 ++-- src-tauri/src/lib.rs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src-tauri/src/app_config.rs b/src-tauri/src/app_config.rs index bbc107d0..1d46f1dc 100644 --- a/src-tauri/src/app_config.rs +++ b/src-tauri/src/app_config.rs @@ -21,9 +21,9 @@ fn get_config_file_path(app: &AppHandle) -> PathBuf { if !config_file_path.exists() { create_dir_all(&config_file_path).expect("Failed to create missing app data dir"); } - set_perms(&config_file_path, true); + set_perms(&config_file_path); config_file_path.push(APP_CONFIG_FILE_NAME); - set_perms(&config_file_path, false); + set_perms(&config_file_path); config_file_path } diff --git a/src-tauri/src/bin/defguard-client.rs b/src-tauri/src/bin/defguard-client.rs index 8984f897..a30eb8e0 100644 --- a/src-tauri/src/bin/defguard-client.rs +++ b/src-tauri/src/bin/defguard-client.rs @@ -287,8 +287,8 @@ fn main() { .unwrap_or_else(|_| "UNDEFINED LOG DIRECTORY".into()); // Ensure directories have appropriate permissions (dg25-28). - set_perms(&data_dir, true); - set_perms(&log_dir, true); + set_perms(&data_dir); + set_perms(&log_dir); info!( "Application data (database file) will be stored in: {data_dir:?} and application logs in: {log_dir:?}. \ Logs of the background Defguard service responsible for managing VPN connections at the \ diff --git a/src-tauri/src/database/mod.rs b/src-tauri/src/database/mod.rs index b813f857..847233ae 100644 --- a/src-tauri/src/database/mod.rs +++ b/src-tauri/src/database/mod.rs @@ -59,7 +59,7 @@ fn prepare_db_url() -> Result { app_dir.to_string_lossy() ); } - set_perms(&app_dir, true); + set_perms(&app_dir); let db_path = app_dir.join(DB_NAME); if db_path.exists() { debug!( @@ -78,7 +78,7 @@ fn prepare_db_url() -> Result { db_path.to_string_lossy() ); } - set_perms(&db_path, false); + set_perms(&db_path); debug!( "Application's database file is located at: {}", db_path.to_string_lossy() diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 881d5151..696873f0 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -85,10 +85,10 @@ pub fn app_data_dir() -> Option { /// Ensures path has appropriate permissions set (dg25-28): /// - 700 for directories /// - 600 for files -pub fn set_perms(path: &PathBuf, is_directory: bool) { +pub fn set_perms(path: &PathBuf) { #[cfg(not(windows))] { - let perms = if is_directory { 0o700 } else { 0o600 }; + let perms = if path.is_dir() { 0o700 } else { 0o600 }; if let Err(err) = set_permissions(path, Permissions::from_mode(perms)) { warn!("Failed to set permissions on path {path:?}: {err}"); } From 4ac08173735fea25e821e4496511a7cd60e835df Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Fri, 19 Sep 2025 12:10:32 +0200 Subject: [PATCH 7/7] nix flake update --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 31754b0a..b10558f0 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1756159630, - "narHash": "sha256-ohMvsjtSVdT/bruXf5ClBh8ZYXRmD4krmjKrXhEvwMg=", + "lastModified": 1758213207, + "narHash": "sha256-rqoqF0LEi+6ZT59tr+hTQlxVwrzQsET01U4uUdmqRtM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "84c256e42600cb0fdf25763b48d28df2f25a0c8b", + "rev": "f4b140d5b253f5e2a1ff4e5506edbf8267724bde", "type": "github" }, "original": { @@ -60,11 +60,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1756262090, - "narHash": "sha256-PQHSup4d0cVXxJ7mlHrrxBx1WVrmudKiNQgnNl5xRas=", + "lastModified": 1758249250, + "narHash": "sha256-bg228atm49IZ8koNOlT3bsrFKE9sFjq6vn6Tx8eVgpc=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "df7ea78aded79f195a92fc5423de96af2b8a85d1", + "rev": "e26a009e7edab102bd569dc041459deb6c0009f4", "type": "github" }, "original": {