diff --git a/src/server.rs b/src/server.rs index 577cc67..e3af2c2 100644 --- a/src/server.rs +++ b/src/server.rs @@ -239,7 +239,7 @@ impl Server { } else if is_miss { status_not_found(&mut res); } else { - self.handle_copy(path, headers, &mut res).await? + self.handle_copy(path, &req, &mut res).await? } } "MOVE" => { @@ -248,7 +248,7 @@ impl Server { } else if is_miss { status_not_found(&mut res); } else { - self.handle_move(path, headers, &mut res).await? + self.handle_move(path, &req, &mut res).await? } } "LOCK" => { @@ -643,16 +643,10 @@ impl Server { Ok(()) } - async fn handle_copy( - &self, - path: &Path, - headers: &HeaderMap, - res: &mut Response, - ) -> BoxResult<()> { - let dest = match self.extract_dest(headers) { + async fn handle_copy(&self, path: &Path, req: &Request, res: &mut Response) -> BoxResult<()> { + let dest = match self.extract_dest(req, res) { Some(dest) => dest, None => { - *res.status_mut() = StatusCode::BAD_REQUEST; return Ok(()); } }; @@ -671,16 +665,10 @@ impl Server { Ok(()) } - async fn handle_move( - &self, - path: &Path, - headers: &HeaderMap, - res: &mut Response, - ) -> BoxResult<()> { - let dest = match self.extract_dest(headers) { + async fn handle_move(&self, path: &Path, req: &Request, res: &mut Response) -> BoxResult<()> { + let dest = match self.extract_dest(req, res) { Some(dest) => dest, None => { - *res.status_mut() = StatusCode::BAD_REQUEST; return Ok(()); } }; @@ -799,10 +787,43 @@ DATA = {} .unwrap_or_default() } - fn extract_dest(&self, headers: &HeaderMap) -> Option { + fn extract_dest(&self, req: &Request, res: &mut Response) -> Option { + let headers = req.headers(); + let dest_path = match self.extract_destination_header(headers) { + Some(dest) => dest, + None => { + *res.status_mut() = StatusCode::BAD_REQUEST; + return None; + } + }; + let authorization = headers.get(AUTHORIZATION); + let guard_type = self.args.auth.guard( + &dest_path, + req.method(), + authorization, + self.args.auth_method.clone(), + ); + if guard_type.is_reject() { + *res.status_mut() = StatusCode::FORBIDDEN; + *res.body_mut() = Body::from("Forbidden"); + return None; + } + + let dest = match self.extract_path(&dest_path) { + Some(dest) => dest, + None => { + *res.status_mut() = StatusCode::BAD_REQUEST; + return None; + } + }; + + Some(dest) + } + + fn extract_destination_header(&self, headers: &HeaderMap) -> Option { let dest = headers.get("Destination")?.to_str().ok()?; let uri: Uri = dest.parse().ok()?; - self.extract_path(uri.path()) + Some(uri.path().to_string()) } fn extract_path(&self, path: &str) -> Option { diff --git a/tests/auth.rs b/tests/auth.rs index c1fe0e7..fad9ecb 100644 --- a/tests/auth.rs +++ b/tests/auth.rs @@ -95,3 +95,29 @@ fn auth_basic( assert_eq!(resp.status(), 201); Ok(()) } + +#[rstest] +fn auth_webdav_move( + #[with(&["--auth", "/@user:pass@*", "--auth", "/dira@user3:pass3", "-A"])] server: TestServer, +) -> Result<(), Error> { + let origin_url = format!("{}dira/test.html", server.url()); + let new_url = format!("{}test2.html", server.url()); + let resp = fetch!(b"MOVE", &origin_url) + .header("Destination", &new_url) + .send_with_digest_auth("user3", "pass3")?; + assert_eq!(resp.status(), 403); + Ok(()) +} + +#[rstest] +fn auth_webdav_copy( + #[with(&["--auth", "/@user:pass@*", "--auth", "/dira@user3:pass3", "-A"])] server: TestServer, +) -> Result<(), Error> { + let origin_url = format!("{}dira/test.html", server.url()); + let new_url = format!("{}test2.html", server.url()); + let resp = fetch!(b"COPY", &origin_url) + .header("Destination", &new_url) + .send_with_digest_auth("user3", "pass3")?; + assert_eq!(resp.status(), 403); + Ok(()) +}