Compare commits

...
Author SHA1 Message Date
Ian 9cbb31e15c Create the Windows data folder with its ACL instead of setting it after 2026-10-22 18:11:08 -04:00
2 changed files with 24 additions and 9 deletions

No files matched your search

+1 -1
View File
@@ -125,7 +125,7 @@ schannel = "0.1.29"
tokio = { version = "1.53.1", features = ["net"] } tokio = { version = "1.53.1", features = ["net"] }
tracing-appender = "0.2.5" tracing-appender = "0.2.5"
tray-icon = { version = "0.26.1", default-features = false } tray-icon = { version = "0.26.1", default-features = false }
windows = { version = "0.62", features = ["Win32_Foundation", "Win32_Security", "Win32_Security_Authorization", "Win32_Security_Cryptography", "Win32_System_Com", "Win32_System_Console", "Win32_System_Environment", "Win32_System_JobObjects", "Win32_System_Threading", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] } windows = { version = "0.62", features = ["Win32_Foundation", "Win32_Security", "Win32_Security_Authorization", "Win32_Security_Cryptography", "Win32_Storage_FileSystem", "Win32_System_Com", "Win32_System_Console", "Win32_System_Environment", "Win32_System_JobObjects", "Win32_System_Threading", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] }
windows-registry = "0.6.1" windows-registry = "0.6.1"
windows-service = "0.8.0" windows-service = "0.8.0"
+23 -8
View File
@@ -11,6 +11,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
use tracing::warn; use tracing::warn;
use windows::Win32::Security::Authorization::{GetNamedSecurityInfoW, SE_FILE_OBJECT}; use windows::Win32::Security::Authorization::{GetNamedSecurityInfoW, SE_FILE_OBJECT};
use windows::Win32::Security::*; use windows::Win32::Security::*;
use windows::Win32::Storage::FileSystem::CreateDirectoryW;
use windows_registry::Type; use windows_registry::Type;
/// SYSTEM and admins write, users only read, so no one else can plant a CA for node. /// SYSTEM and admins write, users only read, so no one else can plant a CA for node.
@@ -65,25 +66,39 @@ pub fn load_or_create_ca(
Ok(ca) Ok(ca)
} }
/// Created on first use, its owner and ACL reset every time. One a user made first, or a link, /// Created on first use with its ACL, which is reset every time. One a user made first, or a link,
/// is replaced: its owner could grant itself access again, and a link would redirect our writes. /// is replaced: its owner could grant itself access again, and a link would redirect our writes.
pub(super) fn secure_data_dir() -> io::Result<PathBuf> { pub(super) fn secure_data_dir() -> io::Result<PathBuf> {
let dir = data_dir(); let dir = data_dir();
match std::fs::symlink_metadata(&dir) { let exists = match std::fs::symlink_metadata(&dir) {
Ok(meta) if meta.file_type().is_symlink() => std::fs::remove_dir(&dir)?, Ok(meta) if meta.file_type().is_symlink() => {
std::fs::remove_dir(&dir)?;
false
}
Ok(_) if !owned_by_admins(&dir)? => { Ok(_) if !owned_by_admins(&dir)? => {
warn!(dir = %dir.display(), "replacing a data folder not created by an admin"); warn!(dir = %dir.display(), "replacing a data folder not created by an admin");
std::fs::remove_dir_all(&dir)? std::fs::remove_dir_all(&dir)?;
false
} }
_ => {} Ok(_) => true,
} Err(_) => false,
std::fs::create_dir_all(&dir)?; };
let info = OWNER_SECURITY_INFORMATION let info = OWNER_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION
| PROTECTED_DACL_SECURITY_INFORMATION; | PROTECTED_DACL_SECURITY_INFORMATION;
let path = HSTRING::from(dir.as_path()); let path = HSTRING::from(dir.as_path());
let acl = security_descriptor(DATA_DIR_ACL)?; let acl = security_descriptor(DATA_DIR_ACL)?;
unsafe { SetFileSecurityW(&path, info, PSECURITY_DESCRIPTOR(acl.0)).ok()? }; if exists {
unsafe { SetFileSecurityW(&path, info, PSECURITY_DESCRIPTOR(acl.0)).ok()? };
} else {
let attributes = SECURITY_ATTRIBUTES {
nLength: size_of::<SECURITY_ATTRIBUTES>() as u32,
lpSecurityDescriptor: acl.0,
bInheritHandle: false.into(),
};
// Never inherits ProgramData's ACL, which lets users add files; fails if it was recreated.
unsafe { CreateDirectoryW(&path, Some(&attributes))? };
}
Ok(dir) Ok(dir)
} }