From 6be36b8e51830e69f66510193096e79e59c74474 Mon Sep 17 00:00:00 2001 From: sigoden Date: Mon, 5 Jun 2023 11:40:31 +0800 Subject: [PATCH] fix: webdav only see public folder even logging in (#231) --- src/auth.rs | 20 ++++++++------------ src/server.rs | 14 ++++++++++---- tests/auth.rs | 12 ++++++++++++ 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index 70cbd10..dbeda89 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -80,8 +80,8 @@ impl AccessControl { Ok(Self { users, anony }) } - pub fn valid(&self) -> bool { - !self.users.is_empty() || self.anony.is_some() + pub fn exist(&self) -> bool { + !self.users.is_empty() } pub fn guard( @@ -257,18 +257,14 @@ pub enum AuthMethod { } impl AuthMethod { - pub fn www_auth(&self, stale: bool) -> Result { + pub fn www_auth(&self) -> Result { match self { AuthMethod::Basic => Ok(format!("Basic realm=\"{REALM}\"")), - AuthMethod::Digest => { - let str_stale = if stale { "stale=true," } else { "" }; - Ok(format!( - "Digest realm=\"{}\",nonce=\"{}\",{}qop=\"auth\"", - REALM, - create_nonce()?, - str_stale - )) - } + AuthMethod::Digest => Ok(format!( + "Digest realm=\"{}\",nonce=\"{}\",qop=\"auth\"", + REALM, + create_nonce()?, + )), } } diff --git a/src/server.rs b/src/server.rs index 980b901..dba58b0 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,6 +1,6 @@ #![allow(clippy::too_many_arguments)] -use crate::auth::AccessPaths; +use crate::auth::{AccessPaths, AccessPerm}; use crate::streamer::Streamer; use crate::utils::{ decode_uri, encode_uri, get_file_mtime_and_mode, get_file_name, glob, try_get_file_name, @@ -340,6 +340,12 @@ impl Server { method => match method.as_str() { "PROPFIND" => { if is_dir { + let access_paths = if access_paths.perm().indexonly() { + // see https://github.com/sigoden/dufs/issues/229 + AccessPaths::new(AccessPerm::ReadOnly) + } else { + access_paths + }; self.handle_propfind_dir(path, headers, access_paths, &mut res) .await?; } else if is_file { @@ -759,7 +765,7 @@ impl Server { uri_prefix: self.args.uri_prefix.clone(), allow_upload: self.args.allow_upload, allow_delete: self.args.allow_delete, - auth: self.args.auth.valid(), + auth: self.args.auth.exist(), user, editable, }; @@ -974,7 +980,7 @@ impl Server { allow_search: self.args.allow_search, allow_archive: self.args.allow_archive, dir_exists: exist, - auth: self.args.auth.valid(), + auth: self.args.auth.exist(), user, paths, }; @@ -999,7 +1005,7 @@ impl Server { } fn auth_reject(&self, res: &mut Response) -> Result<()> { - let value = self.args.auth_method.www_auth(false)?; + let value = self.args.auth_method.www_auth()?; set_webdav_headers(res); res.headers_mut().insert(WWW_AUTHENTICATE, value.parse()?); // set 401 to make the browser pop up the login box diff --git a/tests/auth.rs b/tests/auth.rs index 6a0cbde..0111cfd 100644 --- a/tests/auth.rs +++ b/tests/auth.rs @@ -201,3 +201,15 @@ fn auth_partial_index( ); Ok(()) } + +#[rstest] +fn no_auth_propfind_dir( + #[with(&["--auth", "user:pass@/:rw", "--auth", "@/dir-assets", "-A"])] server: TestServer, +) -> Result<(), Error> { + let resp = fetch!(b"PROPFIND", server.url()).send()?; + assert_eq!(resp.status(), 207); + let body = resp.text()?; + assert!(body.contains("/dir-assets/")); + assert!(body.contains("/dir1/")); + Ok(()) +}