summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-06-09 16:08:51 +0200
committerDavid Lönnhager <david.l@mullvad.net>2020-06-09 16:08:51 +0200
commitdeaf23daa2e3aa2a3ece934481d105e0e46c99bc (patch)
treebaec8efc2d1fc9768d1cc76b240e894577bcd017
parent6b888626d14939f9c61583716363bfbb00182dad (diff)
parentf81f0d6bd22ef0bf33f577856d72e3ab6c81ce52 (diff)
downloadmullvadvpn-deaf23daa2e3aa2a3ece934481d105e0e46c99bc.tar.xz
mullvadvpn-deaf23daa2e3aa2a3ece934481d105e0e46c99bc.zip
Merge branch 'win-pipe-permissions'
-rw-r--r--Cargo.lock1
-rw-r--r--talpid-ipc/Cargo.toml3
-rw-r--r--talpid-ipc/src/lib.rs6
-rw-r--r--talpid-ipc/src/win.rs175
4 files changed, 184 insertions, 1 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 12e09896f3..df894cd109 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2877,6 +2877,7 @@ dependencies = [
"serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
diff --git a/talpid-ipc/Cargo.toml b/talpid-ipc/Cargo.toml
index 31ad7ca753..0a15db0f48 100644
--- a/talpid-ipc/Cargo.toml
+++ b/talpid-ipc/Cargo.toml
@@ -21,6 +21,9 @@ futures = "0.1"
jsonrpc-client-core = { git = "https://github.com/mullvad/jsonrpc-client-rs", rev = "68aac55b" }
jsonrpc-client-ipc = { git = "https://github.com/mullvad/jsonrpc-client-rs", rev = "68aac55b" }
+[target.'cfg(windows)'.dependencies]
+winapi = { version = "0.3", features = ["accctrl", "aclapi", "securitybaseapi", "winbase", "winerror", "winnt"] }
+
[dev-dependencies]
assert_matches = "1.0"
env_logger = "0.7"
diff --git a/talpid-ipc/src/lib.rs b/talpid-ipc/src/lib.rs
index 83ddd03991..2ab6d506c3 100644
--- a/talpid-ipc/src/lib.rs
+++ b/talpid-ipc/src/lib.rs
@@ -6,9 +6,11 @@ use std::{io, thread};
use jsonrpc_core::{MetaIoHandler, Metadata};
use jsonrpc_ipc_server::{MetaExtractor, NoopExtractor, SecurityAttributes, Server, ServerBuilder};
-
use std::fmt;
+#[cfg(windows)]
+mod win;
+
/// An Id created by the Ipc server that the client can use to connect to it
pub type IpcServerId = String;
@@ -78,6 +80,8 @@ impl IpcServer {
fs::set_permissions(&path, PermissionsExt::from_mode(0o766))
.map_err(Error::PermissionsError)?;
}
+ #[cfg(windows)]
+ win::deny_network_access(path).map_err(Error::PermissionsError)?;
Ok(server)
}
diff --git a/talpid-ipc/src/win.rs b/talpid-ipc/src/win.rs
new file mode 100644
index 0000000000..a555a652f9
--- /dev/null
+++ b/talpid-ipc/src/win.rs
@@ -0,0 +1,175 @@
+#![cfg(windows)]
+use std::{ffi::OsStr, io, os::windows::ffi::OsStrExt, ptr};
+use winapi::{
+ shared::{minwindef::DWORD, winerror::ERROR_SUCCESS},
+ um::{
+ accctrl::*,
+ aclapi::{SetEntriesInAclW, SetSecurityInfo},
+ fileapi::{CreateFileW, OPEN_EXISTING},
+ handleapi::{CloseHandle, INVALID_HANDLE_VALUE},
+ securitybaseapi::{AllocateAndInitializeSid, FreeSid},
+ winbase::LocalFree,
+ winnt::*,
+ },
+};
+
+struct Sid {
+ sid_ptr: PSID,
+}
+
+impl Sid {
+ pub fn new(authority: PSID_IDENTIFIER_AUTHORITY, relative_id: DWORD) -> Result<Sid, io::Error> {
+ let mut sid = Sid {
+ sid_ptr: ptr::null_mut(),
+ };
+
+ let result = unsafe {
+ AllocateAndInitializeSid(
+ authority,
+ 1,
+ relative_id,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ &mut sid.sid_ptr as *mut _,
+ )
+ };
+ if result != 0 {
+ Ok(sid)
+ } else {
+ Err(io::Error::last_os_error())
+ }
+ }
+
+ pub fn as_ptr(&self) -> PSID {
+ self.sid_ptr
+ }
+}
+
+impl Drop for Sid {
+ fn drop(&mut self) {
+ unsafe { FreeSid(self.sid_ptr) };
+ }
+}
+
+struct WinHandle(HANDLE);
+
+impl WinHandle {
+ pub fn get_raw(&self) -> HANDLE {
+ self.0
+ }
+}
+
+impl Drop for WinHandle {
+ fn drop(&mut self) {
+ unsafe { CloseHandle(self.0) };
+ }
+}
+
+pub fn deny_network_access<T: AsRef<OsStr>>(ipc_path: T) -> Result<(), io::Error> {
+ let ipc_w: Vec<_> = ipc_path.as_ref().encode_wide().collect();
+
+ let pipe_handle = unsafe {
+ CreateFileW(
+ ipc_w.as_ptr(),
+ GENERIC_WRITE | WRITE_DAC,
+ 0,
+ ptr::null_mut(),
+ OPEN_EXISTING,
+ 0,
+ ptr::null_mut(),
+ )
+ };
+
+ if pipe_handle == INVALID_HANDLE_VALUE {
+ return Err(io::Error::last_os_error());
+ }
+
+ let pipe_handle = WinHandle(pipe_handle);
+
+ let network_sid = Sid::new(
+ SECURITY_NT_AUTHORITY.as_mut_ptr() as *mut _,
+ SECURITY_NETWORK_RID,
+ )?;
+
+ let mut network_access: EXPLICIT_ACCESS_W = unsafe { std::mem::zeroed() };
+ network_access.grfAccessPermissions = GENERIC_READ | GENERIC_WRITE;
+ network_access.grfAccessMode = DENY_ACCESS;
+ network_access.grfInheritance = NO_INHERITANCE;
+ network_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+ network_access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+ network_access.Trustee.ptstrName = network_sid.as_ptr() as *mut _;
+
+ let network_svc_sid = Sid::new(
+ SECURITY_NT_AUTHORITY.as_mut_ptr() as *mut _,
+ SECURITY_NETWORK_SERVICE_RID,
+ )?;
+
+ let mut network_svc_access: EXPLICIT_ACCESS_W = unsafe { std::mem::zeroed() };
+ network_svc_access.grfAccessPermissions = GENERIC_READ | GENERIC_WRITE;
+ network_svc_access.grfAccessMode = DENY_ACCESS;
+ network_svc_access.grfInheritance = NO_INHERITANCE;
+ network_svc_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+ network_svc_access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+ network_svc_access.Trustee.ptstrName = network_svc_sid.as_ptr() as *mut _;
+
+ let everyone_sid = Sid::new(
+ SECURITY_WORLD_SID_AUTHORITY.as_mut_ptr() as *mut _,
+ SECURITY_WORLD_RID,
+ )?;
+
+ let mut world_access: EXPLICIT_ACCESS_W = unsafe { std::mem::zeroed() };
+ world_access.grfAccessPermissions = GENERIC_READ | GENERIC_WRITE;
+ world_access.grfAccessMode = SET_ACCESS;
+ world_access.grfInheritance = NO_INHERITANCE;
+ world_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+ world_access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+ world_access.Trustee.ptstrName = everyone_sid.as_ptr() as *mut _;
+
+ let mut ace_entries = vec![network_access, network_svc_access, world_access];
+
+ let mut new_dacl: PACL = unsafe { std::mem::zeroed() };
+ let result = unsafe {
+ SetEntriesInAclW(
+ ace_entries.len() as u32,
+ ace_entries.as_mut_ptr(),
+ ptr::null_mut(),
+ &mut new_dacl as *mut PACL,
+ )
+ };
+ if result != ERROR_SUCCESS {
+ // A non-zero error code in WinError.h
+ return Err(io::Error::new(
+ io::ErrorKind::Other,
+ format!("SetEntriesInAclW failed: {}", result),
+ ));
+ }
+
+ let result = unsafe {
+ SetSecurityInfo(
+ pipe_handle.get_raw(),
+ SE_KERNEL_OBJECT,
+ DACL_SECURITY_INFORMATION,
+ ptr::null_mut(),
+ ptr::null_mut(),
+ new_dacl as *mut ACL,
+ ptr::null_mut(),
+ )
+ };
+
+ unsafe { LocalFree(new_dacl as *mut _) };
+
+ if result != ERROR_SUCCESS {
+ // A non-zero error code in WinError.h
+ return Err(io::Error::new(
+ io::ErrorKind::Other,
+ format!("SetSecurityInfo failed: {}", result),
+ ));
+ }
+
+ Ok(())
+}