disable crc32 checks when handling aes encrypted data
This commit is contained in:
parent
852ab625fb
commit
12260f5623
3 changed files with 21 additions and 15 deletions
|
@ -51,7 +51,7 @@ All of these are enabled by default.
|
||||||
MSRV
|
MSRV
|
||||||
----
|
----
|
||||||
|
|
||||||
Our current Minimum Supported Rust Version is **1.36.0**. When adding features,
|
Our current Minimum Supported Rust Version is **1.42.0**. When adding features,
|
||||||
we will follow these guidelines:
|
we will follow these guidelines:
|
||||||
|
|
||||||
- We will always support the latest four minor Rust versions. This gives you a 6
|
- We will always support the latest four minor Rust versions. This gives you a 6
|
||||||
|
|
16
src/crc32.rs
16
src/crc32.rs
|
@ -10,15 +10,19 @@ pub struct Crc32Reader<R> {
|
||||||
inner: R,
|
inner: R,
|
||||||
hasher: Hasher,
|
hasher: Hasher,
|
||||||
check: u32,
|
check: u32,
|
||||||
|
/// Signals if `inner` stores aes encrypted data.
|
||||||
|
/// AE-2 encrypted data doesn't use crc and sets the value to 0.
|
||||||
|
aes_encrypted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> Crc32Reader<R> {
|
impl<R> Crc32Reader<R> {
|
||||||
/// Get a new Crc32Reader which check the inner reader against checksum.
|
/// Get a new Crc32Reader which check the inner reader against checksum.
|
||||||
pub fn new(inner: R, checksum: u32) -> Crc32Reader<R> {
|
pub fn new(inner: R, checksum: u32, aes_encrypted: bool) -> Crc32Reader<R> {
|
||||||
Crc32Reader {
|
Crc32Reader {
|
||||||
inner,
|
inner,
|
||||||
hasher: Hasher::new(),
|
hasher: Hasher::new(),
|
||||||
check: checksum,
|
check: checksum,
|
||||||
|
aes_encrypted,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +38,7 @@ impl<R> Crc32Reader<R> {
|
||||||
impl<R: Read> Read for Crc32Reader<R> {
|
impl<R: Read> Read for Crc32Reader<R> {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
let count = match self.inner.read(buf) {
|
let count = match self.inner.read(buf) {
|
||||||
Ok(0) if !buf.is_empty() && !self.check_matches() => {
|
Ok(0) if !buf.is_empty() && !self.check_matches() && !self.aes_encrypted => {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, "Invalid checksum"))
|
return Err(io::Error::new(io::ErrorKind::Other, "Invalid checksum"))
|
||||||
}
|
}
|
||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
|
@ -55,10 +59,10 @@ mod test {
|
||||||
let data: &[u8] = b"";
|
let data: &[u8] = b"";
|
||||||
let mut buf = [0; 1];
|
let mut buf = [0; 1];
|
||||||
|
|
||||||
let mut reader = Crc32Reader::new(data, 0);
|
let mut reader = Crc32Reader::new(data, 0, false);
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
||||||
|
|
||||||
let mut reader = Crc32Reader::new(data, 1);
|
let mut reader = Crc32Reader::new(data, 1, false);
|
||||||
assert!(reader
|
assert!(reader
|
||||||
.read(&mut buf)
|
.read(&mut buf)
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
|
@ -71,7 +75,7 @@ mod test {
|
||||||
let data: &[u8] = b"1234";
|
let data: &[u8] = b"1234";
|
||||||
let mut buf = [0; 1];
|
let mut buf = [0; 1];
|
||||||
|
|
||||||
let mut reader = Crc32Reader::new(data, 0x9be3e0a3);
|
let mut reader = Crc32Reader::new(data, 0x9be3e0a3, false);
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 1);
|
assert_eq!(reader.read(&mut buf).unwrap(), 1);
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 1);
|
assert_eq!(reader.read(&mut buf).unwrap(), 1);
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 1);
|
assert_eq!(reader.read(&mut buf).unwrap(), 1);
|
||||||
|
@ -86,7 +90,7 @@ mod test {
|
||||||
let data: &[u8] = b"1234";
|
let data: &[u8] = b"1234";
|
||||||
let mut buf = [0; 5];
|
let mut buf = [0; 5];
|
||||||
|
|
||||||
let mut reader = Crc32Reader::new(data, 0x9be3e0a3);
|
let mut reader = Crc32Reader::new(data, 0x9be3e0a3, false);
|
||||||
assert_eq!(reader.read(&mut buf[..0]).unwrap(), 0);
|
assert_eq!(reader.read(&mut buf[..0]).unwrap(), 0);
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 4);
|
assert_eq!(reader.read(&mut buf).unwrap(), 4);
|
||||||
}
|
}
|
||||||
|
|
18
src/read.rs
18
src/read.rs
|
@ -1,6 +1,6 @@
|
||||||
//! Types for reading ZIP archives
|
//! Types for reading ZIP archives
|
||||||
|
|
||||||
use crate::aes::{AesReaderValid, AesReader};
|
use crate::aes::{AesReader, AesReaderValid};
|
||||||
use crate::compression::CompressionMethod;
|
use crate::compression::CompressionMethod;
|
||||||
use crate::cp437::FromCp437;
|
use crate::cp437::FromCp437;
|
||||||
use crate::crc32::Crc32Reader;
|
use crate::crc32::Crc32Reader;
|
||||||
|
@ -205,8 +205,11 @@ fn make_reader<'a>(
|
||||||
crc32: u32,
|
crc32: u32,
|
||||||
reader: CryptoReader<'a>,
|
reader: CryptoReader<'a>,
|
||||||
) -> ZipFileReader<'a> {
|
) -> ZipFileReader<'a> {
|
||||||
|
let aes_encrypted = matches!(reader, CryptoReader::Aes(_));
|
||||||
match compression_method {
|
match compression_method {
|
||||||
CompressionMethod::Stored => ZipFileReader::Stored(Crc32Reader::new(reader, crc32)),
|
CompressionMethod::Stored => {
|
||||||
|
ZipFileReader::Stored(Crc32Reader::new(reader, crc32, aes_encrypted))
|
||||||
|
}
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "deflate",
|
feature = "deflate",
|
||||||
feature = "deflate-miniz",
|
feature = "deflate-miniz",
|
||||||
|
@ -214,12 +217,12 @@ fn make_reader<'a>(
|
||||||
))]
|
))]
|
||||||
CompressionMethod::Deflated => {
|
CompressionMethod::Deflated => {
|
||||||
let deflate_reader = DeflateDecoder::new(reader);
|
let deflate_reader = DeflateDecoder::new(reader);
|
||||||
ZipFileReader::Deflated(Crc32Reader::new(deflate_reader, crc32))
|
ZipFileReader::Deflated(Crc32Reader::new(deflate_reader, crc32, aes_encrypted))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "bzip2")]
|
#[cfg(feature = "bzip2")]
|
||||||
CompressionMethod::Bzip2 => {
|
CompressionMethod::Bzip2 => {
|
||||||
let bzip2_reader = BzDecoder::new(reader);
|
let bzip2_reader = BzDecoder::new(reader);
|
||||||
ZipFileReader::Bzip2(Crc32Reader::new(bzip2_reader, crc32))
|
ZipFileReader::Bzip2(Crc32Reader::new(bzip2_reader, crc32, aes_encrypted))
|
||||||
}
|
}
|
||||||
_ => panic!("Compression method not supported"),
|
_ => panic!("Compression method not supported"),
|
||||||
}
|
}
|
||||||
|
@ -514,7 +517,7 @@ impl<R: Read + io::Seek> ZipArchive<R> {
|
||||||
limit_reader,
|
limit_reader,
|
||||||
password,
|
password,
|
||||||
data.aes_mode,
|
data.aes_mode,
|
||||||
data.compressed_size
|
data.compressed_size,
|
||||||
) {
|
) {
|
||||||
Ok(Ok(crypto_reader)) => Ok(Ok(ZipFile {
|
Ok(Ok(crypto_reader)) => Ok(Ok(ZipFile {
|
||||||
crypto_reader: Some(crypto_reader),
|
crypto_reader: Some(crypto_reader),
|
||||||
|
@ -610,13 +613,12 @@ pub(crate) fn central_header_to_zip_file<R: Read + io::Seek>(
|
||||||
large_file: false,
|
large_file: false,
|
||||||
aes_mode: None,
|
aes_mode: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
match parse_extra_field(&mut result) {
|
match parse_extra_field(&mut result) {
|
||||||
Ok(..) | Err(ZipError::Io(..)) => {}
|
Ok(..) | Err(ZipError::Io(..)) => {}
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let aes_enabled = result.compression_method == CompressionMethod::AES;
|
let aes_enabled = result.compression_method == CompressionMethod::AES;
|
||||||
if aes_enabled && result.aes_mode.is_none() {
|
if aes_enabled && result.aes_mode.is_none() {
|
||||||
return Err(ZipError::InvalidArchive(
|
return Err(ZipError::InvalidArchive(
|
||||||
|
|
Loading…
Add table
Reference in a new issue