mirror of
https://gitlab.com/pulsechaincom/lighthouse-pulse.git
synced 2025-01-05 10:32:20 +00:00
8600645f65
## Issue Addressed New lints for rust 1.65 ## Proposed Changes Notable change is the identification or parameters that are only used in recursion ## Additional Info na
145 lines
5.1 KiB
Rust
145 lines
5.1 KiB
Rust
use std::fs::File;
|
|
use std::io;
|
|
use std::io::Write;
|
|
use std::path::Path;
|
|
#[cfg(windows)]
|
|
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;
|
|
|
|
#[derive(Debug)]
|
|
pub enum Error {
|
|
/// The file could not be created
|
|
UnableToCreateFile(io::Error),
|
|
/// The file could not be copied
|
|
UnableToCopyFile(io::Error),
|
|
/// The file could not be opened
|
|
UnableToOpenFile(io::Error),
|
|
/// The file could not be renamed
|
|
UnableToRenameFile(io::Error),
|
|
/// Failed to set permissions
|
|
UnableToSetPermissions(io::Error),
|
|
/// Failed to retrieve file metadata
|
|
UnableToRetrieveMetadata(io::Error),
|
|
/// Failed to write bytes to file
|
|
UnableToWriteFile(io::Error),
|
|
/// Failed to obtain file path
|
|
UnableToObtainFilePath,
|
|
/// Failed to convert string to SID
|
|
UnableToConvertSID(u32),
|
|
/// Failed to retrieve ACL for file
|
|
UnableToRetrieveACL(u32),
|
|
/// Failed to enumerate ACL entries
|
|
UnableToEnumerateACLEntries(u32),
|
|
/// Failed to add new ACL entry
|
|
UnableToAddACLEntry(String),
|
|
/// Failed to remove ACL entry
|
|
UnableToRemoveACLEntry(String),
|
|
}
|
|
|
|
/// Creates a file with `600 (-rw-------)` permissions and writes the specified bytes to file.
|
|
pub fn create_with_600_perms<P: AsRef<Path>>(path: P, bytes: &[u8]) -> Result<(), Error> {
|
|
let path = path.as_ref();
|
|
let mut file = File::create(path).map_err(Error::UnableToCreateFile)?;
|
|
|
|
#[cfg(unix)]
|
|
{
|
|
use std::os::unix::fs::PermissionsExt;
|
|
let mut perm = file
|
|
.metadata()
|
|
.map_err(Error::UnableToRetrieveMetadata)?
|
|
.permissions();
|
|
perm.set_mode(0o600);
|
|
file.set_permissions(perm)
|
|
.map_err(Error::UnableToSetPermissions)?;
|
|
}
|
|
|
|
file.write_all(bytes).map_err(Error::UnableToWriteFile)?;
|
|
#[cfg(windows)]
|
|
{
|
|
restrict_file_permissions(path)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn restrict_file_permissions<P: AsRef<Path>>(path: P) -> Result<(), Error> {
|
|
#[cfg(unix)]
|
|
{
|
|
use std::os::unix::fs::PermissionsExt;
|
|
let file = File::open(path.as_ref()).map_err(Error::UnableToOpenFile)?;
|
|
let mut perm = file
|
|
.metadata()
|
|
.map_err(Error::UnableToRetrieveMetadata)?
|
|
.permissions();
|
|
perm.set_mode(0o600);
|
|
file.set_permissions(perm)
|
|
.map_err(Error::UnableToSetPermissions)?;
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
{
|
|
use winapi::um::winnt::PSID;
|
|
use windows_acl::acl::{AceType, ACL};
|
|
use windows_acl::helper::sid_to_string;
|
|
|
|
let path_str = path
|
|
.as_ref()
|
|
.to_str()
|
|
.ok_or(Error::UnableToObtainFilePath)?;
|
|
let mut acl = ACL::from_file_path(path_str, false).map_err(Error::UnableToRetrieveACL)?;
|
|
|
|
let owner_sid =
|
|
windows_acl::helper::string_to_sid(OWNER_SID_STR).map_err(Error::UnableToConvertSID)?;
|
|
|
|
let entries = acl.all().map_err(Error::UnableToEnumerateACLEntries)?;
|
|
|
|
// 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(|code| {
|
|
Error::UnableToAddACLEntry(format!(
|
|
"Failed to add ACL entry for SID {} error={}",
|
|
OWNER_SID_STR, code
|
|
))
|
|
})?;
|
|
// 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(|_| {
|
|
Error::UnableToRemoveACLEntry(format!(
|
|
"Failed to remove ACL entry for SID {}",
|
|
entry_sid_str
|
|
))
|
|
})?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|