Fix file upload

Add a flag for new files so we can skip the exists check when seeing if
the new file is within the base directory.
This commit is contained in:
Cameron Cordes
2023-04-03 08:41:03 -04:00
parent 7863990c68
commit 8bcd837038
2 changed files with 20 additions and 17 deletions

View File

@@ -137,6 +137,7 @@ pub fn is_image_or_video(path: &Path) -> bool {
pub fn is_valid_full_path<P: AsRef<Path> + Debug + AsRef<std::ffi::OsStr>>(
base: &P,
path: &P,
new_file: bool,
) -> Option<PathBuf> {
debug!("Base: {:?}. Path: {:?}", base, path);
@@ -150,7 +151,7 @@ pub fn is_valid_full_path<P: AsRef<Path> + Debug + AsRef<std::ffi::OsStr>>(
path
};
match is_path_above_base_dir(base, &mut path) {
match is_path_above_base_dir(base, &mut path, new_file) {
Ok(path) => Some(path),
Err(e) => {
error!("{}", e);
@@ -162,6 +163,7 @@ pub fn is_valid_full_path<P: AsRef<Path> + Debug + AsRef<std::ffi::OsStr>>(
fn is_path_above_base_dir<P: AsRef<Path> + Debug>(
base: P,
full_path: &mut PathBuf,
new_file: bool,
) -> anyhow::Result<PathBuf> {
full_path
.absolutize()
@@ -169,7 +171,7 @@ fn is_path_above_base_dir<P: AsRef<Path> + Debug>(
.map_or_else(
|e| Err(anyhow!(e)),
|p| {
if p.starts_with(base) && p.exists() {
if p.starts_with(base) && (new_file || p.exists()) {
Ok(p.into_owned())
} else if !p.exists() {
Err(anyhow!("Path does not exist: {:?}", p))
@@ -196,7 +198,7 @@ impl RealFileSystem {
impl FileSystemAccess for RealFileSystem {
fn get_files_for_path(&self, path: &str) -> anyhow::Result<Vec<PathBuf>> {
is_valid_full_path(&PathBuf::from(&self.base_path), &PathBuf::from(path))
is_valid_full_path(&PathBuf::from(&self.base_path), &PathBuf::from(path), false)
.map(|path| {
debug!("Valid path: {:?}", path);
list_files(&path).unwrap_or_default()
@@ -457,23 +459,23 @@ mod tests {
#[test]
fn directory_traversal_test() {
let base = env::temp_dir();
assert_eq!(None, is_valid_full_path(&base, &PathBuf::from("../")));
assert_eq!(None, is_valid_full_path(&base, &PathBuf::from("..")));
assert_eq!(None, is_valid_full_path(&base, &PathBuf::from("../"), false));
assert_eq!(None, is_valid_full_path(&base, &PathBuf::from(".."), false));
assert_eq!(
None,
is_valid_full_path(&base, &PathBuf::from("fake/../../../"))
is_valid_full_path(&base, &PathBuf::from("fake/../../../"), false)
);
assert_eq!(
None,
is_valid_full_path(&base, &PathBuf::from("../../../etc/passwd"))
is_valid_full_path(&base, &PathBuf::from("../../../etc/passwd"), false)
);
assert_eq!(
None,
is_valid_full_path(&base, &PathBuf::from("..//etc/passwd"))
is_valid_full_path(&base, &PathBuf::from("..//etc/passwd"), false)
);
assert_eq!(
None,
is_valid_full_path(&base, &PathBuf::from("../../etc/passwd"))
is_valid_full_path(&base, &PathBuf::from("../../etc/passwd"), false)
);
}
@@ -484,7 +486,7 @@ mod tests {
test_file.push("test.png");
File::create(test_file).unwrap();
assert!(is_valid_full_path(&base, &PathBuf::from("test.png")).is_some());
assert!(is_valid_full_path(&base, &PathBuf::from("test.png"), false).is_some());
}
#[test]
@@ -495,7 +497,7 @@ mod tests {
let mut test_file = PathBuf::from(&base);
test_file.push(path);
assert_eq!(None, is_valid_full_path(&base, &test_file));
assert_eq!(None, is_valid_full_path(&base, &test_file, false));
}
#[test]
@@ -505,11 +507,11 @@ mod tests {
test_file.push("test.png");
File::create(&test_file).unwrap();
assert!(is_valid_full_path(&base, &test_file).is_some());
assert!(is_valid_full_path(&base, &test_file, false).is_some());
assert_eq!(
Some(PathBuf::from("/tmp/test.png")),
is_valid_full_path(&base, &PathBuf::from("/tmp/test.png"))
is_valid_full_path(&base, &PathBuf::from("/tmp/test.png"), false)
);
}