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": { diff --git a/src-tauri/src/app_config.rs b/src-tauri/src/app_config.rs index d949d67f..1d46f1dc 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); config_file_path.push(APP_CONFIG_FILE_NAME); + 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 3f0699db..a30eb8e0 100644 --- a/src-tauri/src/bin/defguard-client.rs +++ b/src-tauri/src/bin/defguard-client.rs @@ -17,7 +17,7 @@ use defguard_client::{ DB_POOL, }, periodic::run_periodic_tasks, - service, + service, set_perms, tray::{configure_tray_icon, setup_tray, show_main_window}, utils::load_log_targets, VERSION, @@ -277,19 +277,22 @@ fn main() { app.run(|app_handle, event| match event { // Startup tasks RunEvent::Ready => { + let data_dir = app_handle + .path() + .app_data_dir() + .unwrap_or_else(|_| "UNDEFINED DATA DIRECTORY".into()); + let log_dir = app_handle + .path() + .app_log_dir() + .unwrap_or_else(|_| "UNDEFINED LOG DIRECTORY".into()); + + // Ensure directories have appropriate permissions (dg25-28). + set_perms(&data_dir); + set_perms(&log_dir); 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: {}.", - // 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(), - 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)); diff --git a/src-tauri/src/database/mod.rs b/src-tauri/src/database/mod.rs index e2a03b6a..847233ae 100644 --- a/src-tauri/src/database/mod.rs +++ b/src-tauri/src/database/mod.rs @@ -1,5 +1,3 @@ -pub mod models; - use std::{ env, fs::{create_dir_all, File}, @@ -9,10 +7,12 @@ use std::{ 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"; +pub mod models; + pub(crate) type DbPool = SqlitePool; pub static DB_POOL: LazyLock = LazyLock::new(|| { @@ -59,6 +59,7 @@ fn prepare_db_url() -> Result { app_dir.to_string_lossy() ); } + set_perms(&app_dir); let db_path = app_dir.join(DB_NAME); if db_path.exists() { debug!( @@ -77,6 +78,7 @@ fn prepare_db_url() -> Result { db_path.to_string_lossy() ); } + 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 e57ddd2c..696873f0 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) { + #[cfg(not(windows))] + { + 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}"); + } + } +} + /// Location type used in commands to check if we using tunnel or location #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub enum ConnectionType {