Skip to content

Commit

Permalink
Restrict file permissions on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
Thoralf-M committed Sep 21, 2023
1 parent 610dc50 commit a47054f
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
30 changes: 30 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@ serde_json = { version = "1.0.107", default-features = false }
thiserror = { version = "1.0.48", default-features = false }
tokio = { version = "1.32.0", default-features = false, features = ["fs"] }
zeroize = { version = "1.6.0", default-features = false }

[target.'cfg(target_os = "windows")'.dependencies]
windows-acl = { version = "0.3.0", default-features = false }
winapi = { version = "0.3.9", default-features = false }
82 changes: 82 additions & 0 deletions cli/src/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,88 @@ async fn write_mnemonic_to_file(path: &str, mnemonic: &str) -> Result<(), Error>
let mut file = open_options.open(path).await?;
file.write_all(format!("{mnemonic}\n").as_bytes()).await?;

#[cfg(windows)]
restrict_file_permissions(path)?;

Ok(())
}

// Slightly modified from https://github.com/sile/sloggers/blob/master/src/permissions.rs
#[cfg(windows)]
pub fn restrict_file_permissions<P: AsRef<Path>>(path: P) -> std::io::Result<()> {
use winapi::um::winnt::{FILE_GENERIC_READ, FILE_GENERIC_WRITE, STANDARD_RIGHTS_ALL};

/// This is the security identifier in Windows for the owner of a file. See:
/// - https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/security-identifiers-in-windows#well-known-sids-all-versions-of-windows
#[cfg(windows)]
const OWNER_SID_STR: &str = "S-1-3-4";
/// We don't need any of the `AceFlags` listed here:
/// - https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header
#[cfg(windows)]
const OWNER_ACL_ENTRY_FLAGS: u8 = 0;
/// Generic Rights:
/// - https://docs.microsoft.com/en-us/windows/win32/fileio/file-security-and-access-rights
/// Individual Read/Write/Execute Permissions (referenced in generic rights link):
/// - https://docs.microsoft.com/en-us/windows/win32/wmisdk/file-and-directory-access-rights-constants
/// STANDARD_RIGHTS_ALL
/// - https://docs.microsoft.com/en-us/windows/win32/secauthz/access-mask
#[cfg(windows)]
const OWNER_ACL_ENTRY_MASK: u32 = FILE_GENERIC_READ | FILE_GENERIC_WRITE | STANDARD_RIGHTS_ALL;

use std::io;

use winapi::um::winnt::PSID;
use windows_acl::{
acl::{AceType, ACL},
helper::sid_to_string,
};

let path_str = path
.as_ref()
.to_str()
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Unable to open file path.".to_string()))?;

let mut acl = ACL::from_file_path(path_str, false)
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Unable to retrieve ACL: {:?}", e)))?;

let owner_sid = windows_acl::helper::string_to_sid(OWNER_SID_STR)
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Unable to convert SID: {:?}", e)))?;

let entries = acl.all().map_err(|e| {
io::Error::new(
io::ErrorKind::Other,
format!("Unable to enumerate ACL entries: {:?}", e),
)
})?;

// Add single entry for file owner.
acl.add_entry(
owner_sid.as_ptr() as PSID,
AceType::AccessAllow,
OWNER_ACL_ENTRY_FLAGS,
OWNER_ACL_ENTRY_MASK,
)
.map_err(|e| {
io::Error::new(
io::ErrorKind::Other,
format!("Failed to add ACL entry for SID {} error={}", OWNER_SID_STR, e),
)
})?;
// Remove all AccessAllow entries from the file that aren't the owner_sid.
for entry in &entries {
if let Some(ref entry_sid) = entry.sid {
let entry_sid_str = sid_to_string(entry_sid.as_ptr() as PSID).unwrap_or_else(|_| "BadFormat".to_string());
if entry_sid_str != OWNER_SID_STR {
acl.remove(entry_sid.as_ptr() as PSID, Some(AceType::AccessAllow), None)
.map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
format!("Failed to remove ACL entry for SID {}", entry_sid_str),
)
})?;
}
}
}
Ok(())
}

Expand Down

0 comments on commit a47054f

Please sign in to comment.