diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/readme.rs | 22 | ||||
-rw-r--r-- | tests/upload_files.rs | 91 |
2 files changed, 101 insertions, 12 deletions
diff --git a/tests/readme.rs b/tests/readme.rs index 56a3afd..3fcbe29 100644 --- a/tests/readme.rs +++ b/tests/readme.rs @@ -64,7 +64,11 @@ fn show_root_readme_contents( case("readme.md"), case("README.md"), case("README.MD"), - case("ReAdMe.Md") + case("ReAdMe.Md"), + case("Readme.txt"), + case("README.txt"), + case("README"), + case("ReAdMe") )] fn show_nested_readme_contents( #[with(&["--readme"])] server: TestServer, @@ -113,13 +117,11 @@ fn assert_readme_contents(parsed_dom: &Document, filename: &str) { .find(Attr("id", "readme-contents")) .next() .is_some()); - assert!( - parsed_dom - .find(Attr("id", "readme-contents")) - .next() - .unwrap() - .text() - .trim() - == format!("Contents of {}", filename) - ); + assert!(parsed_dom + .find(Attr("id", "readme-contents")) + .next() + .unwrap() + .text() + .trim() + .contains(&format!("Contents of {}", filename))); } diff --git a/tests/upload_files.rs b/tests/upload_files.rs index 71fcbc4..196f3cd 100644 --- a/tests/upload_files.rs +++ b/tests/upload_files.rs @@ -6,6 +6,8 @@ use reqwest::blocking::{multipart, Client}; use rstest::rstest; use select::document::Document; use select::predicate::{Attr, Text}; +use std::fs::create_dir_all; +use std::path::Path; #[rstest] fn uploading_files_works(#[with(&["-u"])] server: TestServer) -> Result<(), Error> { @@ -72,7 +74,7 @@ fn uploading_files_is_prevented(server: TestServer) -> Result<(), Error> { .error_for_status() .is_err()); - // After uploading, check whether the uploaded file is now getting listed. + // After uploading, check whether the uploaded file is NOT getting listed. let body = reqwest::blocking::get(server.url())?; let parsed = Document::from_read(body)?; assert!(!parsed.find(Text).any(|x| x.text() == test_file_name)); @@ -80,6 +82,92 @@ fn uploading_files_is_prevented(server: TestServer) -> Result<(), Error> { Ok(()) } +/// This test runs the server with --allowed-upload-dir argument and +/// checks that file upload to a different directory is actually prevented. +#[rstest] +#[case(server_no_stderr(&["-u", "someDir"]))] +#[case(server_no_stderr(&["-u", "someDir/some_sub_dir"]))] +fn uploading_files_is_restricted(#[case] server: TestServer) -> Result<(), Error> { + let test_file_name = "uploaded test file.txt"; + + // Then try to upload file to root directory (which is not the --allowed-upload-dir) + let form = multipart::Form::new(); + let part = multipart::Part::text("this should not be uploaded") + .file_name(test_file_name) + .mime_str("text/plain")?; + let form = form.part("file_to_upload", part); + + let client = Client::new(); + // Ensure uploading fails and returns an error + assert_eq!( + 403, + client + .post(server.url().join("/upload?path=/")?) + .multipart(form) + .send()? + .status() + ); + + // After uploading, check whether the uploaded file is NOT getting listed. + let body = reqwest::blocking::get(server.url())?; + let parsed = Document::from_read(body)?; + assert!(!parsed.find(Text).any(|x| x.text() == test_file_name)); + + Ok(()) +} + +/// This tests that we can upload files to the directory specified by --allow-upload-dir +#[rstest] +#[case(server(&["-u", "someDir"]), vec!["someDir"])] +#[case(server(&["-u", "./-someDir"]), vec!["./-someDir"])] +#[case(server(&["-u", Path::new("someDir/some_sub_dir").to_str().unwrap()]), + vec!["someDir/some_sub_dir"])] +#[case(server(&["-u", Path::new("someDir/some_sub_dir").to_str().unwrap(), + "-u", Path::new("someDir/some_other_dir").to_str().unwrap()]), + vec!["someDir/some_sub_dir", "someDir/some_other_dir"])] +fn uploading_files_to_allowed_dir_works( + #[case] server: TestServer, + #[case] upload_dirs: Vec<&str>, +) -> Result<(), Error> { + let test_file_name = "uploaded test file.txt"; + + for upload_dir in upload_dirs { + // Create test directory + create_dir_all(server.path().join(Path::new(upload_dir))).unwrap(); + + // Before uploading, check whether the uploaded file does not yet exist. + let body = reqwest::blocking::get(server.url().join(upload_dir)?)?.error_for_status()?; + let parsed = Document::from_read(body)?; + assert!(parsed.find(Text).all(|x| x.text() != test_file_name)); + + // Perform the actual upload. + let upload_action = parsed + .find(Attr("id", "file_submit")) + .next() + .expect("Couldn't find element with id=file_submit") + .attr("action") + .expect("Upload form doesn't have action attribute"); + let form = multipart::Form::new(); + let part = multipart::Part::text("this should be uploaded") + .file_name(test_file_name) + .mime_str("text/plain")?; + let form = form.part("file_to_upload", part); + + let client = Client::new(); + client + .post(server.url().join(upload_action)?) + .multipart(form) + .send()? + .error_for_status()?; + + // After uploading, check whether the uploaded file is now getting listed. + let body = reqwest::blocking::get(server.url().join(upload_dir)?)?; + let parsed = Document::from_read(body)?; + assert!(parsed.find(Text).any(|x| x.text() == test_file_name)); + } + Ok(()) +} + /// Test for path traversal vulnerability (CWE-22) in both path parameter of query string and in /// file name (Content-Disposition) /// @@ -98,7 +186,6 @@ fn prevent_path_traversal_attacks( #[case] expected: &str, ) -> Result<(), Error> { // Create test directories - use std::fs::create_dir_all; create_dir_all(server.path().join("foo")).unwrap(); if !cfg!(windows) { for dir in &["C:/foo/C:", r"C:\foo", r"\foo"] { |