]> OzVa Git service - ozva-cloud/commitdiff
feat: check permission on move/copy destination (#93)
authorsigoden <sigoden@gmail.com>
Mon, 4 Jul 2022 15:25:05 +0000 (23:25 +0800)
committerGitHub <noreply@github.com>
Mon, 4 Jul 2022 15:25:05 +0000 (23:25 +0800)
src/server.rs
tests/auth.rs

index 577cc67ee5d6a3c971503344fc62212b322936a5..e3af2c2c45e8c91ef9e2cdf3ca95c1a17f83860e 100644 (file)
@@ -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<HeaderValue>,
-        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<HeaderValue>,
-        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<HeaderValue>) -> Option<PathBuf> {
+    fn extract_dest(&self, req: &Request, res: &mut Response) -> Option<PathBuf> {
+        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<HeaderValue>) -> Option<String> {
         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<PathBuf> {
index c1fe0e7bbf4fdb8d280063c21d8dabc5549709fc..fad9ecb37e9ba7906a1f95e334830912ad08352c 100644 (file)
@@ -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(())
+}