Validate tarball components

This commit is contained in:
Eelco Dolstra 2019-12-13 18:11:37 +01:00
parent 4581159e3f
commit 5a6d6da7ae
5 changed files with 27 additions and 5 deletions

View file

@ -11,7 +11,10 @@ pub extern "C" fn unpack_tarfile(
source: foreign::Source, source: foreign::Source,
dest_dir: &str, dest_dir: &str,
) -> CBox<Result<(), error::CppException>> { ) -> CBox<Result<(), error::CppException>> {
CBox::new(util::tarfile::unpack_tarfile(source, dest_dir).map_err(|err| err.into())) CBox::new(
util::tarfile::unpack_tarfile(source, std::path::Path::new(dest_dir))
.map_err(|err| err.into()),
)
} }
#[no_mangle] #[no_mangle]

View file

@ -23,6 +23,7 @@ pub enum Error {
HttpError(hyper::error::Error), HttpError(hyper::error::Error),
Misc(String), Misc(String),
Foreign(CppException), Foreign(CppException),
BadTarFileMemberName(String),
} }
impl From<std::io::Error> for Error { impl From<std::io::Error> for Error {
@ -64,6 +65,9 @@ impl fmt::Display for Error {
Error::HttpError(err) => write!(f, "HTTP error: {}", err), Error::HttpError(err) => write!(f, "HTTP error: {}", err),
Error::Foreign(_) => write!(f, "<C++ exception>"), // FIXME Error::Foreign(_) => write!(f, "<C++ exception>"), // FIXME
Error::Misc(s) => write!(f, "{}", s), Error::Misc(s) => write!(f, "{}", s),
Error::BadTarFileMemberName(s) => {
write!(f, "tar archive contains illegal file name '{}'", s)
}
} }
} }
} }

View file

@ -2,18 +2,28 @@ use crate::{foreign::Source, Error};
use std::fs; use std::fs;
use std::io; use std::io;
use std::os::unix::fs::OpenOptionsExt; use std::os::unix::fs::OpenOptionsExt;
use std::path::Path; use std::path::{Component, Path};
use tar::Archive; use tar::Archive;
pub fn unpack_tarfile(source: Source, dest_dir: &str) -> Result<(), Error> { pub fn unpack_tarfile(source: Source, dest_dir: &Path) -> Result<(), Error> {
let dest_dir = Path::new(dest_dir); fs::create_dir_all(dest_dir)?;
let mut tar = Archive::new(source); let mut tar = Archive::new(source);
for file in tar.entries()? { for file in tar.entries()? {
let mut file = file?; let mut file = file?;
let dest_file = dest_dir.join(file.path()?); let path = file.path()?;
for i in path.components() {
if let Component::Prefix(_) | Component::RootDir | Component::ParentDir = i {
return Err(Error::BadTarFileMemberName(
file.path()?.to_str().unwrap().to_string(),
));
}
}
let dest_file = dest_dir.join(path);
fs::create_dir_all(dest_file.parent().unwrap())?; fs::create_dir_all(dest_file.parent().unwrap())?;

BIN
tests/bad.tar.xz Normal file

Binary file not shown.

View file

@ -35,3 +35,8 @@ test_tarball() {
test_tarball '' cat test_tarball '' cat
test_tarball .xz xz test_tarball .xz xz
test_tarball .gz gzip test_tarball .gz gzip
rm -rf $TEST_ROOT/tmp
mkdir -p $TEST_ROOT/tmp
(! TMPDIR=$TEST_ROOT/tmp XDG_RUNTIME_DIR=$TEST_ROOT/tmp nix-env -f file://$(pwd)/bad.tar.xz -qa --out-path)
(! [ -e $TEST_ROOT/tmp/bad ])