fix(server): prevent serving an already expired file

This commit is contained in:
Orhun Parmaksız 2021-11-07 00:49:31 +03:00
parent 3eee294bd9
commit f078a9afa7
No known key found for this signature in database
GPG key ID: F83424824B3E4B90
6 changed files with 49 additions and 13 deletions

24
Cargo.lock generated
View file

@ -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",

View file

@ -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"

View file

@ -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<S: AsRef<str>>(self, sha256sum: S) -> Option<File> {
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())
})
}
}

View file

@ -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)
{

View file

@ -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)?;

View file

@ -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<Regex> = lazy_regex!(r#"\.[0-9]{10,}$"#);
/// Returns the system time as [`Duration`](Duration).
pub fn get_system_time() -> Result<Duration, ActixError> {
SystemTime::now()
@ -17,15 +21,20 @@ pub fn get_system_time() -> Result<Duration, ActixError> {
///
/// The file extension is accepted as a timestamp that points to the expiry date.
pub fn glob_match_file(mut path: PathBuf) -> Result<PathBuf, ActixError> {
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