summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2025-03-19 18:52:46 +0100
committerDavid Lönnhager <david.l@mullvad.net>2025-03-24 16:43:29 +0100
commit85a07b3c58a246497f738bcbf15d2ff5b7d1b577 (patch)
treefce8b0e47df3b4c166a246656153b6c1c020909e
parentbdaefa370f9a0464753690655b017a868872b69b (diff)
downloadmullvadvpn-85a07b3c58a246497f738bcbf15d2ff5b7d1b577.tar.xz
mullvadvpn-85a07b3c58a246497f738bcbf15d2ff5b7d1b577.zip
Add function for checking if file is owned by admin or system account
-rw-r--r--talpid-windows/Cargo.toml1
-rw-r--r--talpid-windows/src/fs.rs47
-rw-r--r--talpid-windows/src/lib.rs3
3 files changed, 51 insertions, 0 deletions
diff --git a/talpid-windows/Cargo.toml b/talpid-windows/Cargo.toml
index 0b9e1d2672..594e17f9ef 100644
--- a/talpid-windows/Cargo.toml
+++ b/talpid-windows/Cargo.toml
@@ -23,6 +23,7 @@ features = [
"Win32_Foundation",
"Win32_Globalization",
"Win32_Security",
+ "Win32_Security_Authorization",
"Win32_System_Diagnostics_ToolHelp",
"Win32_System_IO",
"Win32_Networking_WinSock",
diff --git a/talpid-windows/src/fs.rs b/talpid-windows/src/fs.rs
new file mode 100644
index 0000000000..eb78efa963
--- /dev/null
+++ b/talpid-windows/src/fs.rs
@@ -0,0 +1,47 @@
+use core::ffi::c_void;
+use std::io;
+use std::os::windows::io::AsRawHandle;
+use std::ptr;
+
+use windows_sys::Win32::{
+ Foundation::{LocalFree, ERROR_SUCCESS},
+ Security::{
+ Authorization::{GetSecurityInfo, SE_FILE_OBJECT},
+ IsWellKnownSid, WinBuiltinAdministratorsSid, WinLocalSystemSid, OWNER_SECURITY_INFORMATION,
+ SECURITY_DESCRIPTOR, SID,
+ },
+};
+
+/// Return whether a file handle is owned by either SYSTEM or the built-in administrators account
+pub fn is_admin_owned<T: AsRawHandle>(handle: T) -> io::Result<bool> {
+ let mut security_descriptor: *mut SECURITY_DESCRIPTOR = ptr::null_mut();
+ let mut owner: *mut SID = ptr::null_mut();
+
+ // SAFETY: `handle` is a valid handle
+ let result = unsafe {
+ GetSecurityInfo(
+ handle.as_raw_handle() as isize,
+ SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION,
+ (&mut owner) as *mut *mut SID as *mut *mut c_void,
+ ptr::null_mut(),
+ ptr::null_mut(),
+ ptr::null_mut(),
+ (&mut security_descriptor) as *mut *mut SECURITY_DESCRIPTOR as *mut *mut c_void,
+ )
+ };
+
+ if result != ERROR_SUCCESS {
+ return Err(io::Error::from_raw_os_error(result as i32));
+ }
+
+ // SAFETY: `owner` is valid since `security_descriptor` still is, and the well-known type is a valid argument
+ let is_system_owned = unsafe { IsWellKnownSid(owner as _, WinLocalSystemSid) != 0 };
+ // SAFETY: `owner` is valid since `security_descriptor` still is, and the well-known type is a valid argument
+ let is_admin_owned = unsafe { IsWellKnownSid(owner as _, WinBuiltinAdministratorsSid) != 0 };
+
+ // SAFETY: Since we no longer need the descriptor (or owner), it may be freed
+ unsafe { LocalFree(security_descriptor.cast()) };
+
+ Ok(is_system_owned || is_admin_owned)
+}
diff --git a/talpid-windows/src/lib.rs b/talpid-windows/src/lib.rs
index 53fa172ee0..92db769623 100644
--- a/talpid-windows/src/lib.rs
+++ b/talpid-windows/src/lib.rs
@@ -3,6 +3,9 @@
#![deny(missing_docs)]
#![cfg(windows)]
+/// File system
+pub mod fs;
+
/// I/O
pub mod io;