From f078a9afa74f8608ee3f2a6e705159df15915c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Sun, 7 Nov 2021 00:49:31 +0300 Subject: [PATCH] fix(server): prevent serving an already expired file --- Cargo.lock | 24 ++++++++++++++++++++++++ Cargo.toml | 1 + src/file.rs | 7 ++++--- src/paste.rs | 2 +- src/server.rs | 1 + src/util.rs | 27 ++++++++++++++++++--------- 6 files changed, 49 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9bac1f1..7d0a1e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1000,6 +1000,29 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" +[[package]] +name = "lazy-regex" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919a16773ebf2de27e95fc58460110932e55bb0780e23aa51fa5a6b59c9e2b3d" +dependencies = [ + "lazy-regex-proc_macros", + "once_cell", + "regex", +] + +[[package]] +name = "lazy-regex-proc_macros" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fbe6bf0a04af51c07976625d5007e75ed9b8b955befc21c77b3947733496e36" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1528,6 +1551,7 @@ dependencies = [ "glob", "humantime", "infer", + "lazy-regex", "log", "mime", "petname", diff --git a/Cargo.toml b/Cargo.toml index 83e750d..a597fe3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ url = "2.2.2" mime = "0.3.16" regex = "1.5.4" serde_regex = "1.1.0" +lazy-regex = "2.2.1" humantime = "2.1.0" glob = "0.3.0" ring = "0.16.20" diff --git a/src/file.rs b/src/file.rs index e33d359..398573a 100644 --- a/src/file.rs +++ b/src/file.rs @@ -45,9 +45,10 @@ impl<'a> TryFrom<&'a Path> for Directory { impl Directory { /// Returns the file that matches the given checksum. pub fn get_file>(self, sha256sum: S) -> Option { - self.files - .into_iter() - .find(|file| file.sha256sum == sha256sum.as_ref()) + self.files.into_iter().find(|file| { + file.sha256sum == sha256sum.as_ref() + && !util::TIMESTAMP_EXTENSION_REGEX.is_match(&file.path.to_string_lossy()) + }) } } diff --git a/src/paste.rs b/src/paste.rs index c03c944..be31b74 100644 --- a/src/paste.rs +++ b/src/paste.rs @@ -177,7 +177,7 @@ impl Paste { let bytes = response.body().limit(payload_limit).await?.to_vec(); let bytes_checksum = util::sha256_digest(&*bytes)?; self.data = bytes; - if !config.paste.duplicate_files.unwrap_or(true) { + if !config.paste.duplicate_files.unwrap_or(true) && expiry_date.is_none() { if let Some(file) = Directory::try_from(config.server.upload_path.as_path())?.get_file(bytes_checksum) { diff --git a/src/server.rs b/src/server.rs index a734f74..0fb2ccb 100644 --- a/src/server.rs +++ b/src/server.rs @@ -106,6 +106,7 @@ async fn upload( } if paste_type != PasteType::Oneshot && paste_type != PasteType::RemoteFile + && expiry_date.is_none() && !config.paste.duplicate_files.unwrap_or(true) { let bytes_checksum = util::sha256_digest(&*bytes)?; diff --git a/src/util.rs b/src/util.rs index 9c265f6..12cedee 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,11 +1,15 @@ use actix_web::{error, Error as ActixError}; use glob::glob; +use lazy_regex::{lazy_regex, Lazy, Regex}; use ring::digest::{Context, SHA256}; use std::io::{BufReader, Read}; use std::path::PathBuf; use std::time::Duration; use std::time::{SystemTime, UNIX_EPOCH}; +/// Regex for matching the timestamp extension of a path. +pub static TIMESTAMP_EXTENSION_REGEX: Lazy = lazy_regex!(r#"\.[0-9]{10,}$"#); + /// Returns the system time as [`Duration`](Duration). pub fn get_system_time() -> Result { SystemTime::now() @@ -17,15 +21,20 @@ pub fn get_system_time() -> Result { /// /// The file extension is accepted as a timestamp that points to the expiry date. pub fn glob_match_file(mut path: PathBuf) -> Result { - if let Some(glob_path) = glob(&format!( - "{}.[0-9]*", - path.to_str() - .ok_or_else(|| error::ErrorInternalServerError( - "file name contains invalid characters" - ))?, - )) - .map_err(error::ErrorInternalServerError)? - .next() + path = PathBuf::from( + TIMESTAMP_EXTENSION_REGEX + .replacen( + path.to_str().ok_or_else(|| { + error::ErrorInternalServerError("path contains invalid characters") + })?, + 1, + "", + ) + .to_string(), + ); + if let Some(glob_path) = glob(&format!("{}.[0-9]*", path.to_string_lossy())) + .map_err(error::ErrorInternalServerError)? + .next() { let glob_path = glob_path.map_err(error::ErrorInternalServerError)?; if let Some(extension) = glob_path