Can extract only a part of TAR file

This commit is contained in:
Pierre HUBERT 2022-03-27 14:27:53 +02:00
parent 2f50690fef
commit c100d87145

View File

@ -128,6 +128,13 @@ async fn replace_files(args: web::Data<Args>, req: HttpRequest, mut payload: Mul
return Err(ErrorUnauthorized("Invalid update token!")); 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(); let mut new_files = Vec::new();
// iterate over multipart stream // iterate over multipart stream
@ -144,12 +151,19 @@ async fn replace_files(args: web::Data<Args>, req: HttpRequest, mut payload: Mul
.map_err(|_| ErrorInternalServerError("Failed to parse TAR archive!"))? { .map_err(|_| ErrorInternalServerError("Failed to parse TAR archive!"))? {
let mut file = entry?; let mut file = entry?;
let inner_path = file.header().path()?; let inner_path = file.header().path()?;
let inner_path_str = inner_path.to_string_lossy();
if inner_path.is_absolute() { if !inner_path_str.starts_with(base_uri) {
return Err(ErrorInternalServerError("Cowardly refusing to unpack absolute file!")); 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; continue;
} }
@ -177,7 +191,10 @@ async fn replace_files(args: web::Data<Args>, req: HttpRequest, mut payload: Mul
// Apply new files // Apply new files
for file in new_files { for file in new_files {
std::fs::create_dir_all(file.path.parent().unwrap())?; 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()) Ok(HttpResponse::Ok().into())