]> OzVa Git service - ozva-cloud/commitdiff
fix: guard req and destination path (#359)
authorsigoden <sigoden@gmail.com>
Tue, 6 Feb 2024 09:23:18 +0000 (17:23 +0800)
committerGitHub <noreply@github.com>
Tue, 6 Feb 2024 09:23:18 +0000 (17:23 +0800)
src/server.rs
tests/assets.rs

index 965da88febb4ba4fc24d074bb43c8d0c4cae490d..4ef237b54bccb46e02f8492207e9a63070b0f590 100644 (file)
@@ -71,7 +71,7 @@ pub struct Server {
 
 impl Server {
     pub fn init(args: Args, running: Arc<AtomicBool>) -> Result<Self> {
-        let assets_prefix = format!("{}__dufs_v{}_", args.uri_prefix, env!("CARGO_PKG_VERSION"));
+        let assets_prefix = format!("{}__dufs_v{}_/", args.uri_prefix, env!("CARGO_PKG_VERSION"));
         let single_file_req_paths = if args.path_is_file {
             vec![
                 args.uri_prefix.to_string(),
@@ -144,6 +144,10 @@ impl Server {
         let headers = req.headers();
         let method = req.method().clone();
 
+        if guard_path(req_path, &mut res) {
+            return Ok(res);
+        }
+
         if method == Method::GET && self.handle_assets(req_path, headers, &mut res).await? {
             return Ok(res);
         }
@@ -713,7 +717,12 @@ impl Server {
             match self.args.assets.as_ref() {
                 Some(assets_path) => {
                     let path = assets_path.join(name);
-                    self.handle_send_file(&path, headers, false, res).await?;
+                    if path.exists() {
+                        self.handle_send_file(&path, headers, false, res).await?;
+                    } else {
+                        status_not_found(res);
+                        return Ok(true);
+                    }
                 }
                 None => match name {
                     "index.js" => {
@@ -1153,7 +1162,10 @@ impl Server {
 
     fn extract_dest(&self, req: &Request, res: &mut Response) -> Option<PathBuf> {
         let headers = req.headers();
-        let dest_path = match self.extract_destination_header(headers) {
+        let dest_path = match self
+            .extract_destination_header(headers)
+            .and_then(|dest| self.resolve_path(&dest))
+        {
             Some(dest) => dest,
             None => {
                 *res.status_mut() = StatusCode::BAD_REQUEST;
@@ -1161,19 +1173,15 @@ impl Server {
             }
         };
 
-        let relative_path = match self.resolve_path(&dest_path) {
-            Some(v) => v,
-            None => {
-                *res.status_mut() = StatusCode::BAD_REQUEST;
-                return None;
-            }
-        };
+        if guard_path(&dest_path, res) {
+            return None;
+        }
 
         let authorization = headers.get(AUTHORIZATION);
         let guard = self
             .args
             .auth
-            .guard(&relative_path, req.method(), authorization);
+            .guard(&dest_path, req.method(), authorization);
 
         match guard {
             (_, Some(_)) => {}
@@ -1183,7 +1191,7 @@ impl Server {
             }
         };
 
-        let dest = match self.join_path(&relative_path) {
+        let dest = match self.join_path(&dest_path) {
             Some(dest) => dest,
             None => {
                 *res.status_mut() = StatusCode::BAD_REQUEST;
@@ -1690,3 +1698,12 @@ fn parse_upload_offset(headers: &HeaderMap<HeaderValue>, size: u64) -> Result<Op
     let (start, _) = parse_range(value, size).ok_or_else(err)?;
     Ok(Some(start))
 }
+
+fn guard_path(path: &str, res: &mut Response) -> bool {
+    let path = Path::new(path);
+    if path.components().any(|v| v.as_os_str() == "..") {
+        status_bad_request(res, "");
+        return true;
+    }
+    false
+}
index ea1821b51df56550f24d20303ac02d12dcc039e0..8482b2a61baf2fe2c318122a2c605bd237974c14 100644 (file)
@@ -11,10 +11,11 @@ use std::process::{Command, Stdio};
 fn assets(server: TestServer) -> Result<(), Error> {
     let ver = env!("CARGO_PKG_VERSION");
     let resp = reqwest::blocking::get(server.url())?;
-    let index_js = format!("/__dufs_v{ver}_index.js");
-    let index_css = format!("/__dufs_v{ver}_index.css");
-    let favicon_ico = format!("/__dufs_v{ver}_favicon.ico");
+    let index_js = format!("/__dufs_v{ver}_/index.js");
+    let index_css = format!("/__dufs_v{ver}_/index.css");
+    let favicon_ico = format!("/__dufs_v{ver}_/favicon.ico");
     let text = resp.text()?;
+    println!("{text}");
     assert!(text.contains(&format!(r#"href="{index_css}""#)));
     assert!(text.contains(&format!(r#"href="{favicon_ico}""#)));
     assert!(text.contains(&format!(r#"src="{index_js}""#)));
@@ -24,7 +25,7 @@ fn assets(server: TestServer) -> Result<(), Error> {
 #[rstest]
 fn asset_js(server: TestServer) -> Result<(), Error> {
     let url = format!(
-        "{}__dufs_v{}_index.js",
+        "{}__dufs_v{}_/index.js",
         server.url(),
         env!("CARGO_PKG_VERSION")
     );
@@ -40,7 +41,7 @@ fn asset_js(server: TestServer) -> Result<(), Error> {
 #[rstest]
 fn asset_css(server: TestServer) -> Result<(), Error> {
     let url = format!(
-        "{}__dufs_v{}_index.css",
+        "{}__dufs_v{}_/index.css",
         server.url(),
         env!("CARGO_PKG_VERSION")
     );
@@ -56,7 +57,7 @@ fn asset_css(server: TestServer) -> Result<(), Error> {
 #[rstest]
 fn asset_ico(server: TestServer) -> Result<(), Error> {
     let url = format!(
-        "{}__dufs_v{}_favicon.ico",
+        "{}__dufs_v{}_/favicon.ico",
         server.url(),
         env!("CARGO_PKG_VERSION")
     );
@@ -70,9 +71,9 @@ fn asset_ico(server: TestServer) -> Result<(), Error> {
 fn assets_with_prefix(#[with(&["--path-prefix", "xyz"])] server: TestServer) -> Result<(), Error> {
     let ver = env!("CARGO_PKG_VERSION");
     let resp = reqwest::blocking::get(format!("{}xyz/", server.url()))?;
-    let index_js = format!("/xyz/__dufs_v{ver}_index.js");
-    let index_css = format!("/xyz/__dufs_v{ver}_index.css");
-    let favicon_ico = format!("/xyz/__dufs_v{ver}_favicon.ico");
+    let index_js = format!("/xyz/__dufs_v{ver}_/index.js");
+    let index_css = format!("/xyz/__dufs_v{ver}_/index.css");
+    let favicon_ico = format!("/xyz/__dufs_v{ver}_/favicon.ico");
     let text = resp.text()?;
     assert!(text.contains(&format!(r#"href="{index_css}""#)));
     assert!(text.contains(&format!(r#"href="{favicon_ico}""#)));
@@ -85,7 +86,7 @@ fn asset_js_with_prefix(
     #[with(&["--path-prefix", "xyz"])] server: TestServer,
 ) -> Result<(), Error> {
     let url = format!(
-        "{}xyz/__dufs_v{}_index.js",
+        "{}xyz/__dufs_v{}_/index.js",
         server.url(),
         env!("CARGO_PKG_VERSION")
     );
@@ -114,7 +115,7 @@ fn assets_override(tmpdir: TempDir, port: u16) -> Result<(), Error> {
     let url = format!("http://localhost:{port}");
     let resp = reqwest::blocking::get(&url)?;
     assert!(resp.text()?.starts_with(&format!(
-        "/__dufs_v{}_index.js;DATA",
+        "/__dufs_v{}_/index.js;DATA",
         env!("CARGO_PKG_VERSION")
     )));
     let resp = reqwest::blocking::get(&url)?;