Skip to content

Commit b434ecb

Browse files
authored
Merge pull request #297 from NordSecurity/msz/FILE-559-receiver-must-validate-paths-it-receives
Report file transfer error in case file subpath contains perent direc…
2 parents 0c0111f + e92e7b9 commit b434ecb

File tree

2 files changed

+48
-7
lines changed

2 files changed

+48
-7
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* Add `TransferDeffered` event indicating the connection to peer couldn't be establish at this time
1010
* Disallow downloading file for which any path component is larger than 250 characters
1111
* Fix ocassional missing of `TransferPaused` event when toggling libdrop on and off quickly
12+
* Report file transfer error in case file subpath contains perent directory `..`
1213

1314
---
1415
<br>

drop-transfer/src/ws/server/mod.rs

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use self::socket::{WebSocket, WsStream};
3636
use super::{events::FileEventTx, IncomingFileEventTx};
3737
use crate::{
3838
check,
39-
file::{self, FileToRecv},
39+
file::{self, FileSubPath, FileToRecv},
4040
protocol,
4141
quarantine::PathExt,
4242
service::State,
@@ -921,12 +921,7 @@ impl FileXferTask {
921921
guard: AliveGuard,
922922
) {
923923
let task = async {
924-
// Check file and dir names are shorter then MAX
925-
for name in self.file.subpath().iter() {
926-
if name.len() + MAX_FILE_SUFFIX_LEN > MAX_FILENAME_LENGTH {
927-
return Err(Error::FilenameTooLong);
928-
}
929-
}
924+
validate_subpath_for_download(self.file.subpath())?;
930925

931926
let emit_checksum_events = {
932927
if let Some(threshold) = state.config.checksum_events_size_threshold {
@@ -1185,3 +1180,48 @@ pub fn remove_temp_files<P, I>(
11851180
fn temp_file_name(transfer_id: uuid::Uuid, file_id: &FileId) -> String {
11861181
format!("{}-{file_id}.dropdl-part", transfer_id.as_simple(),)
11871182
}
1183+
1184+
/// Check file and dir names are shorter then MAX and contain illegal values
1185+
fn validate_subpath_for_download(subpath: &FileSubPath) -> crate::Result<()> {
1186+
const DISALLOWED: &[&str] = &[".."];
1187+
1188+
for name in subpath.iter() {
1189+
if name.len() + MAX_FILE_SUFFIX_LEN > MAX_FILENAME_LENGTH {
1190+
return Err(Error::FilenameTooLong);
1191+
}
1192+
1193+
if DISALLOWED.contains(&name.as_str()) {
1194+
return Err(Error::BadPath(
1195+
"File subpath contains disallowed element".into(),
1196+
));
1197+
}
1198+
}
1199+
1200+
Ok(())
1201+
}
1202+
1203+
#[cfg(test)]
1204+
mod tests {
1205+
use crate::file::FileSubPath;
1206+
1207+
#[test]
1208+
fn validate_subpath() {
1209+
let sp = FileSubPath::from_path("abc/dfg/hjk.txt").unwrap();
1210+
assert!(super::validate_subpath_for_download(&sp).is_ok());
1211+
1212+
let sp = FileSubPath::from_path("abc/../hjk.txt").unwrap();
1213+
assert!(matches!(
1214+
super::validate_subpath_for_download(&sp),
1215+
Err(crate::Error::BadPath(..))
1216+
));
1217+
1218+
let mut path = String::from("abc/");
1219+
path.extend(std::iter::repeat('x').take(251));
1220+
path.push_str("/hjk.txt");
1221+
let sp = FileSubPath::from_path(&path).unwrap();
1222+
assert!(matches!(
1223+
super::validate_subpath_for_download(&sp),
1224+
Err(crate::Error::FilenameTooLong)
1225+
));
1226+
}
1227+
}

0 commit comments

Comments
 (0)