From c100d871451711b695c753dec73a3601a0002b4a Mon Sep 17 00:00:00 2001 From: Pierre Hubert Date: Sun, 27 Mar 2022 14:27:53 +0200 Subject: [PATCH] Can extract only a part of TAR file --- src/main.rs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index fa6c24b..17fddb1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -128,6 +128,13 @@ async fn replace_files(args: web::Data, req: HttpRequest, mut payload: Mul return Err(ErrorUnauthorized("Invalid update token!")); } + // Get base folder to keep from tar-file + let base_uri = match req.headers().get("BaseURI") { + None => "/", + Some(t) => t.to_str() + .map_err(|_| ErrorInternalServerError("Failed to parse base URI to keep!"))? + }; + let mut new_files = Vec::new(); // iterate over multipart stream @@ -144,12 +151,19 @@ async fn replace_files(args: web::Data, req: HttpRequest, mut payload: Mul .map_err(|_| ErrorInternalServerError("Failed to parse TAR archive!"))? { let mut file = entry?; let inner_path = file.header().path()?; + let inner_path_str = inner_path.to_string_lossy(); - if inner_path.is_absolute() { - return Err(ErrorInternalServerError("Cowardly refusing to unpack absolute file!")); + if !inner_path_str.starts_with(base_uri) { + continue; } - if inner_path.is_dir() || inner_path.to_string_lossy().ends_with("/") { + let mut inner_path_str = &inner_path_str[base_uri.len()..]; + if inner_path_str.starts_with("/") { + inner_path_str = &inner_path_str[1..]; + } + let inner_path = Path::new(inner_path_str); + + if inner_path.is_dir() || inner_path_str.ends_with("/") || inner_path_str.is_empty() { continue; } @@ -177,7 +191,10 @@ async fn replace_files(args: web::Data, req: HttpRequest, mut payload: Mul // Apply new files for file in new_files { std::fs::create_dir_all(file.path.parent().unwrap())?; - std::fs::write(file.path, file.bytes)?; + if let Err(e) = std::fs::write(&file.path, file.bytes) { + log::error!("Failed to write new file {:?} : {:?}", file.path, e); + return Err(ErrorInternalServerError("Failed to write a file!")); + } } Ok(HttpResponse::Ok().into())