Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added option restrict-upload-dir #858

Merged
merged 32 commits into from
Sep 20, 2022

Conversation

jonasdiemer
Copy link
Contributor

To fix #842

@svenstaro
Copy link
Owner

Cool, before I do a proper review, could you add a test to check that other directories are now indeed forbidden?

@jonasdiemer
Copy link
Contributor Author

Sure, let me have a look into testing in Rust :)

@svenstaro
Copy link
Owner

You can take a look at the other tests concerning the upload. It should be somewhat straight forward. Just remember: If you messed up and the test doesn't pick it up, this is a security issue so we need to be really careful here. :)

@jonasdiemer
Copy link
Contributor Author

@svenstaro thanks for the suggestion. Fixed an issue (running tests is actually helpful :)) and added a test similar to existing one uploading_files_is_prevented.

Copy link
Owner

@svenstaro svenstaro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good stuff! This will probably require a few rounds of reviews until we get there but i think for your first foray into Rust this is already looking pretty good.

tests/upload_files.rs Outdated Show resolved Hide resolved
tests/upload_files.rs Outdated Show resolved Hide resolved
tests/upload_files.rs Show resolved Hide resolved
src/file_upload.rs Outdated Show resolved Hide resolved
src/args.rs Outdated Show resolved Hide resolved
@jonasdiemer
Copy link
Contributor Author

jonasdiemer commented Aug 3, 2022

Reworked the solution to use PathBuf and with this also fixed subdirectories not working.

Edit: improved (hopefully) the style a bit using iter().any().

@svenstaro I'd appreciate some feedback (esp. on improving the style). Thanks again! :)

@jonasdiemer jonasdiemer requested a review from svenstaro August 3, 2022 12:53
src/file_upload.rs Outdated Show resolved Hide resolved
src/file_upload.rs Outdated Show resolved Hide resolved
src/args.rs Outdated Show resolved Hide resolved
tests/upload_files.rs Outdated Show resolved Hide resolved
tests/upload_files.rs Show resolved Hide resolved
@svenstaro
Copy link
Owner

I'd be happy to merge as-is. Please update the README.md with the new output of miniserve --help and fix the formatting issue and we're good to merge.

src/config.rs Outdated Show resolved Hide resolved
Copy link
Owner

@svenstaro svenstaro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found a few tiny things but once we have that, we're good to go. Great job so far!

src/file_upload.rs Outdated Show resolved Hide resolved
src/args.rs Outdated
/// Allowed upload directories (together with -u)
///
/// If this is set, uploads are only allowed into the provided directories.
#[clap(long, requires = "file-upload", value_hint = ValueHint::FilePath)]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you like, you can choose a short letter for this as well as it'd be annoying to write it out many times otherwise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd go for 'A' (as in allowed...), but I am wondering if we might just want to re-purpose -u...

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean something like -u alone would allow for uploading everywhere and then -u /tmp/lol would allow uploading only to that dir? If that's what you're thinking, I appreciate the conciseness but I can't help but wonder whether that wouldn't make -u pretty hard to parse (is it even still possible?) and somewhat confusing to users perhaps. Thoughts?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-A is a fine choice, I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean something like -u alone would allow for uploading everywhere and then -u /tmp/lol would allow uploading only to that dir? If that's what you're thinking, I appreciate the conciseness but I can't help but wonder whether that wouldn't make -u pretty hard to parse (is it even still possible?) and somewhat confusing to users perhaps. Thoughts?

Exactly, that was my thinking (after seeing so many command line shorts already taken ;)). Not sure about the parsing, though, I'd give it a try...

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it parse this correctly? -u --some-other-flag? Would it try to parse the stuff behind -u as a PathBuf?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just tried -u --verbose and it worked as expected (i.e. verbose output and allowed_upload_dir == Some([]) (i.e. it would allow uploads everywhere)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just committed a version that uses -u to define allowed directories. @svenstaro, please check it out and let me know what you think (I am also fine to use the previous version with -A as a shortcut).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the -u with min_values. Makes more sense. Might want to try how it does in windows shell. It should work in bash because we've to use ./-path when a file starts with - (e.g. touch ./-h) otherwise it'll be parsed as cli argument.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, I cannot try on Windows.

Directories starting with - would also need the ./ prefix, which doesn't work with my implementation (yet) - will have a look.

tests/upload_files.rs Outdated Show resolved Hide resolved
tests/upload_files.rs Outdated Show resolved Hide resolved
Copy link
Owner

@svenstaro svenstaro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, I think we're almost there now. Only some tiny stuff now. I'd like to put this into the next miniserve release, too! Do you have some time to finish it up soon so we can land it with the release?

tests/upload_files.rs Outdated Show resolved Hide resolved
src/args.rs Outdated
/// Allowed upload directories (together with -u)
///
/// If this is set, uploads are only allowed into the provided directories.
#[clap(long, requires = "file-upload", value_hint = ValueHint::FilePath)]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-A is a fine choice, I think.

@jonasdiemer
Copy link
Contributor Author

Hey, I think we're almost there now. Only some tiny stuff now. I'd like to put this into the next miniserve release, too! Do you have some time to finish it up soon so we can land it with the release?

Except for the decision for using -u or -A (and some cleanup in case we go with -u), it should be ready.

@svenstaro
Copy link
Owner

Please run cargo fmt to fix CI.

@jonasdiemer jonasdiemer requested a review from svenstaro August 17, 2022 08:32
@jonasdiemer
Copy link
Contributor Author

Fixed formatting and also sanitized paths so that specification of `-u ./some_dir' also works.

@svenstaro
Copy link
Owner

There's a small lint to fix there.

@jonasdiemer
Copy link
Contributor Author

Looks like CICD on Windows fails, might have to do with the tests that include a dash in the directory name. Unfortunately, I don't have a windows machine to test on...

@Atreyagaurav
Copy link
Contributor

I also don't have a Windows machine to build miniserve to test, but I made a colleague try to make a directory named "-h" and it was a success (I tried both with "New Folder" button and mkdir in cmd. cd -h & cd ./-hworked fine, but dir ./-h gave Invalid switch - "h".

I don't know if it's a good idea, but we might be able to use cfg to only test that on Linux? At least for now...

@svenstaro
Copy link
Owner

I'd be fine if we don't run that test on Windows.

@jonasdiemer
Copy link
Contributor Author

jonasdiemer commented Aug 30, 2022

As CI has test cases 3+4 failing, I am not sure it's related to the dot. Rather, it could be related to sub-directories (and possibly different path separator for Windows). I've pushed another commit that tries to fix the paths for windows, let's see if it passes CI. Suggestions welcome (struggling a bit as a noob without access to the target platform).

@jonasdiemer jonasdiemer reopened this Aug 30, 2022
fn uploading_files_to_allowed_dir_works(
#[case] server: TestServer,
#[case] upload_dirs: Vec<&str>,
Copy link
Owner

@svenstaro svenstaro Aug 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it work if you take these as Path or OsPath? That might be a better way that just works in Windows as well.

tests/upload_files.rs Outdated Show resolved Hide resolved
@svenstaro
Copy link
Owner

It seems like there's a conflict with the recent QR stuff merge. Could you rebase?

@jonasdiemer
Copy link
Contributor Author

Rebase done, still need to fix the failing test for windows platform.

Comment on lines 120 to 129
#[case(server(&["-u", "someDir"]), vec!["someDir".to_string()])]
#[case(server(&["-u", "./-someDir"]), vec!["./-someDir".to_string()])]
#[case(server(&["-u", if cfg!(windows) {r"someDir\some_sub_dir"} else {"someDir/some_sub_dir"}]),
vec!["someDir/some_sub_dir".to_string()])]
#[case(server(&["-u", if cfg!(windows) {r"someDir\some_sub_dir"} else {"someDir/some_sub_dir"},
"-u", if cfg!(windows) {r"someDir\some_other_dir"} else {"someDir/some_other_dir"}]),
vec!["someDir/some_sub_dir".to_string(), "someDir/some_other_dir".to_string()])]
fn uploading_files_to_allowed_dir_works(
#[case] server: TestServer,
#[case] upload_dirs: Vec<String>,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't really understand why you can't use a std::path::Path here as it will take care of the conversion for you on the operating systems. Wouldn't that be more convenient?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was thinking the same, but thought I'd stick first with they way other tests (see e.g. l. 179) handled it. Since that didn't work in this case (CI still failing), I will try the approach with std::path::Path.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably change other tests as well. :)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it still doesn't work, I'd also be ok with you simply disabling the failing test cases on Windows.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, and kind of hard to make progress without access to a windows machine. Not sure I'll find time to setup something (e.g. on Azure/CodeSpaces)...

@svenstaro, I don't know how I would disable a test-case for a specific platform. Could you give me a pointer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also noticed, that the feature doesn't work on windows with subdirectories (likely due to \ vs /) - found out by running miniserve.exe from publish_release action on an old windows laptop. Pushed a fix, waiting for Action workflow to verify.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I found a solution - latest commit passes CI on all platforms.

I assume the warning (the following packages contain code that will be rejected by a future version of Rust: winapi v0.2.8) has nothing to do with my PR.

From my perspective, the PR should be ready to merge now - please let me know if I overlooked something.

Re the 500 errors, I might have a stab at that if time permits.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, the error handling was easier to fix than I thought - fixed it (also for the case when overwrite_files is not set, i.e. DuplicateFileError).

@svenstaro
Copy link
Owner

At last! Outstanding work getting it to this state. It took a while but I hope you appreciate that for security stuff we need to go the extra mile. :)

@svenstaro svenstaro merged commit 5a68df1 into svenstaro:master Sep 20, 2022
@jonasdiemer
Copy link
Contributor Author

Thanks a lot for your guidance (and patience), I leaned a lot and it was fun!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

set upload folder
3 participants