{client,server}: enforce permissions on directories and files
This may become a warning rather than an action later, but for now let's make sure older installations that had incorrect permissions are taken care of.pull/48/head
parent
ee890ccaa7
commit
72dc14c49c
|
@ -1,4 +1,5 @@
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
use colored::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use shared::{ensure_dirs_exist, Cidr, IoErrorContext, Peer, CLIENT_DATA_PATH};
|
use shared::{ensure_dirs_exist, Cidr, IoErrorContext, Peer, CLIENT_DATA_PATH};
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -23,12 +24,18 @@ pub enum Contents {
|
||||||
|
|
||||||
impl DataStore {
|
impl DataStore {
|
||||||
pub(self) fn open_with_path<P: AsRef<Path>>(path: P, create: bool) -> Result<Self, Error> {
|
pub(self) fn open_with_path<P: AsRef<Path>>(path: P, create: bool) -> Result<Self, Error> {
|
||||||
|
let path = path.as_ref();
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.create(create)
|
.create(create)
|
||||||
.open(&path)
|
.open(path)
|
||||||
.with_path(&path)?;
|
.with_path(path)?;
|
||||||
|
|
||||||
|
if shared::chmod(&file, 0o600)? {
|
||||||
|
println!("{} updated permissions for {} to 0600.", "[!]".yellow(), path.display());
|
||||||
|
}
|
||||||
|
|
||||||
let mut json = String::new();
|
let mut json = String::new();
|
||||||
file.read_to_string(&mut json).with_path(path)?;
|
file.read_to_string(&mut json).with_path(path)?;
|
||||||
let contents = serde_json::from_str(&json).unwrap_or_else(|_| Contents::V1 {
|
let contents = serde_json::from_str(&json).unwrap_or_else(|_| Contents::V1 {
|
||||||
|
|
|
@ -114,6 +114,7 @@ pub struct ConfigFile {
|
||||||
impl ConfigFile {
|
impl ConfigFile {
|
||||||
pub fn write_to_path<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> {
|
pub fn write_to_path<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> {
|
||||||
let mut invitation_file = File::create(&path).with_path(&path)?;
|
let mut invitation_file = File::create(&path).with_path(&path)?;
|
||||||
|
shared::chmod(&invitation_file, 0o600)?;
|
||||||
invitation_file
|
invitation_file
|
||||||
.write_all(toml::to_string(self).unwrap().as_bytes())
|
.write_all(toml::to_string(self).unwrap().as_bytes())
|
||||||
.with_path(path)?;
|
.with_path(path)?;
|
||||||
|
@ -121,6 +122,11 @@ impl ConfigFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
|
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
|
||||||
|
let path = path.as_ref();
|
||||||
|
let file = File::open(path).with_path(path)?;
|
||||||
|
if shared::chmod(&file, 0o600)? {
|
||||||
|
println!("{} updated permissions for {} to 0600.", "[!]".yellow(), path.display());
|
||||||
|
}
|
||||||
Ok(toml::from_slice(&std::fs::read(&path).with_path(path)?)?)
|
Ok(toml::from_slice(&std::fs::read(&path).with_path(path)?)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{ensure_dirs_exist, Error, IoErrorContext, CLIENT_CONFIG_PATH};
|
use crate::{ensure_dirs_exist, Error, IoErrorContext, CLIENT_CONFIG_PATH};
|
||||||
|
use colored::*;
|
||||||
use indoc::writedoc;
|
use indoc::writedoc;
|
||||||
use ipnetwork::IpNetwork;
|
use ipnetwork::IpNetwork;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -58,12 +59,16 @@ impl InterfaceConfig {
|
||||||
comments: bool,
|
comments: bool,
|
||||||
mode: Option<u32>,
|
mode: Option<u32>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
let path = path.as_ref();
|
||||||
let mut target_file = OpenOptions::new()
|
let mut target_file = OpenOptions::new()
|
||||||
.create_new(true)
|
.create_new(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.open(&path)
|
.open(path)
|
||||||
.with_path(&path)?;
|
.with_path(path)?;
|
||||||
if let Some(val) = mode {
|
if let Some(val) = mode {
|
||||||
|
if crate::chmod(&target_file, 0o600)? {
|
||||||
|
println!("{} updated permissions for {} to 0600.", "[!]".yellow(), path.display());
|
||||||
|
}
|
||||||
let metadata = target_file.metadata()?;
|
let metadata = target_file.metadata()?;
|
||||||
let mut permissions = metadata.permissions();
|
let mut permissions = metadata.permissions();
|
||||||
permissions.set_mode(val);
|
permissions.set_mode(val);
|
||||||
|
@ -106,7 +111,12 @@ impl InterfaceConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_interface(interface: &InterfaceName) -> Result<Self, Error> {
|
pub fn from_interface(interface: &InterfaceName) -> Result<Self, Error> {
|
||||||
Self::from_file(Self::build_config_file_path(interface)?)
|
let path = Self::build_config_file_path(interface)?;
|
||||||
|
let file = File::open(&path).with_path(&path)?;
|
||||||
|
if crate::chmod(&file, 0o600)? {
|
||||||
|
println!("{} updated permissions for {} to 0600.", "[!]".yellow(), path.display());
|
||||||
|
}
|
||||||
|
Self::from_file(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_config_file_path(interface: &InterfaceName) -> Result<PathBuf, Error> {
|
fn build_config_file_path(interface: &InterfaceName) -> Result<PathBuf, Error> {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use colored::*;
|
||||||
use ipnetwork::IpNetwork;
|
use ipnetwork::IpNetwork;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use prompts::hostname_validator;
|
use prompts::hostname_validator;
|
||||||
|
@ -362,21 +363,37 @@ pub static WG_DIR: &str = "/etc/wireguard";
|
||||||
pub fn ensure_dirs_exist(dirs: &[&Path]) -> Result<(), Error> {
|
pub fn ensure_dirs_exist(dirs: &[&Path]) -> Result<(), Error> {
|
||||||
for dir in dirs {
|
for dir in dirs {
|
||||||
match fs::create_dir(dir) {
|
match fs::create_dir(dir) {
|
||||||
Ok(()) => {
|
|
||||||
let target_file = File::open(dir).with_path(dir)?;
|
|
||||||
let metadata = target_file.metadata().with_path(dir)?;
|
|
||||||
let mut permissions = metadata.permissions();
|
|
||||||
permissions.set_mode(0o700);
|
|
||||||
},
|
|
||||||
Err(e) if e.kind() != io::ErrorKind::AlreadyExists => {
|
Err(e) if e.kind() != io::ErrorKind::AlreadyExists => {
|
||||||
return Err(e.into());
|
return Err(e.into());
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {
|
||||||
|
let target_file = File::open(dir).with_path(dir)?;
|
||||||
|
if chmod(&target_file, 0o700)? {
|
||||||
|
println!("{} updated permissions for {} to 0700.", "[!]".yellow(), dir.display());
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates the permissions of a file or directory. Returns `Ok(true)` if
|
||||||
|
/// permissions had to be changed, `Ok(false)` if permissions were already
|
||||||
|
/// correct.
|
||||||
|
pub fn chmod(file: &File, mode: u32) -> Result<bool, Error> {
|
||||||
|
let metadata = file.metadata()?;
|
||||||
|
let mut permissions = metadata.permissions();
|
||||||
|
let updated = if permissions.mode() != mode {
|
||||||
|
permissions.set_mode(mode);
|
||||||
|
file.set_permissions(permissions)?;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(updated)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Reference in New Issue