🐛 Use file permissions to forbid access to ptth_server.toml

main
_ 2020-11-19 01:45:42 +00:00
parent 563465c85b
commit 5378e66e39
6 changed files with 55 additions and 13 deletions

View File

@ -29,6 +29,7 @@ reqwest = { version = "0.10.8", features = ["stream"] }
rmp-serde = "0.14.4"
serde = {version = "1.0.117", features = ["derive"]}
structopt = "0.3.20"
# thiserror = "1.0.22"
tokio = { version = "0.2.22", features = ["full"] }
tracing = "0.1.21"
tracing-futures = "0.2.4"

View File

@ -21,7 +21,7 @@ async fn main () -> Result <(), Box <dyn Error>> {
.init ()
;
let config_file = ptth::load_toml::load ("config/ptth_relay.toml");
let config_file = ptth::load_toml::load_public ("config/ptth_relay.toml");
info! ("ptth_relay Git version: {:?}", ptth::git_version::GIT_VERSION);

View File

@ -7,19 +7,48 @@ use std::{
use serde::de::DeserializeOwned;
pub fn load <
pub const CONFIG_PERMISSIONS_MODE: u32 = 33152;
fn load_inner <
T: DeserializeOwned
> (
mut f: File
) -> T {
let mut buffer = vec! [0u8; 4096];
let bytes_read = f.read (&mut buffer).unwrap_or_else (|_| panic! ("Can't read config"));
buffer.truncate (bytes_read);
let config_s = String::from_utf8 (buffer).unwrap_or_else (|_| panic! ("Can't parse config as UTF-8"));
toml::from_str (&config_s).unwrap_or_else (|e| panic! ("Can't parse config as TOML: {}", e))
}
/// For files that contain public-viewable information
pub fn load_public <
T: DeserializeOwned,
P: AsRef <Path> + Debug
> (
config_file_path: P
) -> T {
let mut f = File::open (&config_file_path).unwrap_or_else (|_| panic! ("Can't open {:?}", config_file_path));
let mut buffer = vec! [0u8; 4096];
let bytes_read = f.read (&mut buffer).unwrap_or_else (|_| panic! ("Can't read {:?}", config_file_path));
buffer.truncate (bytes_read);
{
let config_s = String::from_utf8 (buffer).unwrap_or_else (|_| panic! ("Can't parse {:?} as UTF-8", config_file_path));
toml::from_str (&config_s).unwrap_or_else (|e| panic! ("Can't parse {:?} as TOML: {}", config_file_path, e))
}
load_inner (f)
}
/// For files that may contain secrets and should have permissions or other
/// safeties checked
pub fn load <
T: DeserializeOwned,
P: AsRef <Path> + Debug
> (
config_file_path: P
) -> T {
use std::os::unix::fs::PermissionsExt;
let mut f = File::open (&config_file_path).unwrap_or_else (|_| panic! ("Can't open {:?}", config_file_path));
let mode = f.metadata ().unwrap ().permissions ().mode ();
assert_eq! (mode, CONFIG_PERMISSIONS_MODE, "Config file has bad permissions mode, it should be octal 0600");
load_inner (f)
}

View File

@ -500,7 +500,8 @@ async fn handle_all (req: Request <Body>, state: Arc <RelayState>)
servers: Vec <ServerEntry <'a>>,
}
let names = state.list_servers ().await;
let mut names = state.list_servers ().await;
names.sort ();
//println! ("Found {} servers", names.len ());

View File

@ -501,8 +501,7 @@ async fn internal_serve_all (
let path_s = percent_decode (encoded_path.as_bytes ()).decode_utf8 ().unwrap ();
let path = Path::new (&*path_s);
let mut full_path = PathBuf::from (root);
full_path.push (path);
let full_path = root.join (path);
debug! ("full_path = {:?}", full_path);
@ -531,7 +530,14 @@ async fn internal_serve_all (
})
}
else if let Ok (mut file) = File::open (&full_path).await {
use std::os::unix::fs::PermissionsExt;
let file_md = file.metadata ().await.unwrap ();
if file_md.permissions ().mode () == crate::load_toml::CONFIG_PERMISSIONS_MODE
{
return Forbidden;
}
let file_len = file_md.len ();
let range_header = headers.get ("range").map (|v| std::str::from_utf8 (v).ok ()).flatten ();

View File

@ -76,3 +76,8 @@ what happens.
I might have to build a client that imitates this behavior, since it's hard
to control.
## Server won't work on Windows
This is because I use Unix-specific file permissions to protect the server
config.