aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven-Hendrik Haase <svenstaro@gmail.com>2022-05-18 04:45:37 +0000
committerSven-Hendrik Haase <svenstaro@gmail.com>2022-05-18 04:45:37 +0000
commit46c64a983927aaa7e7a752bc0643e8c9c43e23ec (patch)
tree02519193e2ab5e52ef24fbb530e08c188b502b66 /src
parentRun clippy only on nightly (diff)
downloadminiserve-46c64a983927aaa7e7a752bc0643e8c9c43e23ec.tar.gz
miniserve-46c64a983927aaa7e7a752bc0643e8c9c43e23ec.zip
Fix security issue with --no-symlinks
Even with --no-symlinks specified, if a direct path to a symlink had been entered, it would be resolved. This fixes that behavior and improves tests to ensure this behavior.
Diffstat (limited to 'src')
-rw-r--r--src/args.rs4
-rw-r--r--src/main.rs19
2 files changed, 21 insertions, 2 deletions
diff --git a/src/args.rs b/src/args.rs
index 7667bee..757fd22 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -75,7 +75,7 @@ pub struct CliArgs {
#[clap(long = "random-route", conflicts_with("route-prefix"))]
pub random_route: bool,
- /// Do not follow symbolic links
+ /// Hide symlinks in listing and prevent them from being followed
#[clap(short = 'P', long = "no-symlinks")]
pub no_symlinks: bool,
@@ -160,7 +160,7 @@ pub struct CliArgs {
)]
pub header: Vec<HeaderMap>,
- /// Show symlink info
+ /// Visualize symlinks in directory listing
#[clap(short = 'l', long = "show-symlink-info")]
pub show_symlink_info: bool,
diff --git a/src/main.rs b/src/main.rs
index de10d7d..9d3f9ac 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -304,6 +304,8 @@ fn configure_header(conf: &MiniserveConfig) -> middleware::DefaultHeaders {
}
/// Configures the Actix application
+///
+/// This is where we configure the app to serve an index file, the file listing, or a single file.
fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) {
let files_service = || {
let files = actix_files::Files::new("", &conf.path);
@@ -332,11 +334,28 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) {
true => files.use_hidden_files(),
false => files,
};
+
+ let base_path = conf.path.clone();
+ let symlinks_may_be_followed = !conf.no_symlinks;
files
.show_files_listing()
.files_listing_renderer(listing::directory_listing)
.prefer_utf8(true)
.redirect_to_slash_directory()
+ .path_filter(move |path, _| {
+ // Only allow symlinks to be followed in case conf.no_symlinks is false.
+ let path_is_symlink = base_path
+ .join(path)
+ .symlink_metadata()
+ .map(|m| m.file_type().is_symlink())
+ .unwrap_or(false);
+
+ if path_is_symlink {
+ symlinks_may_be_followed
+ } else {
+ true
+ }
+ })
};
if !conf.path.is_file() {