package: ZipPackage: add additional check for entries STORED with
... data descriptor; only allow it for encrypted ODF entries, which requires reading the manifest first. Change-Id: If36d31a4cb93e7af78f48be3ed899ad9d9bb28f0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171911 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
This commit is contained in:
parent
d9841ab378
commit
32cad89592
3 changed files with 37 additions and 0 deletions
|
@ -104,6 +104,7 @@ class ZipPackage final : public cppu::WeakImplHelper
|
|||
|
||||
bool isLocalFile() const;
|
||||
|
||||
void checkZipEntriesWithDD();
|
||||
void parseManifest();
|
||||
void parseContentType();
|
||||
void getZipFileContents();
|
||||
|
|
|
@ -1018,6 +1018,7 @@ sal_uInt64 ZipFile::readLOC(ZipEntry &rEntry)
|
|||
// Unfortunately every encrypted ODF package entry hits this,
|
||||
// because ODF requires deflated entry with value STORED and OOo/LO
|
||||
// has always written compressed streams with data descriptor.
|
||||
// So it is checked later in ZipPackage::checkZipEntriesWithDD()
|
||||
if (nLocMethod == STORED)
|
||||
{
|
||||
SAL_INFO("package", "LOC STORED with data descriptor: \"" << rEntry.sPath << "\"");
|
||||
|
@ -1389,6 +1390,11 @@ sal_Int32 ZipFile::readCEN()
|
|||
if (o3tl::checked_multiply<sal_Int64>(aEntry.nOffset, -1, aEntry.nOffset))
|
||||
throw ZipException(u"Integer-overflow"_ustr);
|
||||
|
||||
if (aEntry.nMethod == STORED && aEntry.nCompressedSize != aEntry.nSize)
|
||||
{
|
||||
throw ZipException(u"entry STORED with inconsistent size"_ustr);
|
||||
}
|
||||
|
||||
aMemGrabber.skipBytes(nCommentLen);
|
||||
|
||||
// unfortunately readLOC is required now to check the consistency
|
||||
|
|
|
@ -165,6 +165,31 @@ bool ZipPackage::isLocalFile() const
|
|||
return comphelper::isFileUrl(m_aURL);
|
||||
}
|
||||
|
||||
// note: don't check for StorageFormats::ZIP, it breaks signing!
|
||||
void ZipPackage::checkZipEntriesWithDD()
|
||||
{
|
||||
if (!m_bForceRecovery)
|
||||
{
|
||||
ZipEnumeration entries{m_pZipFile->entries()};
|
||||
while (entries.hasMoreElements())
|
||||
{
|
||||
ZipEntry const& rEntry{*entries.nextElement()};
|
||||
if ((rEntry.nFlag & 0x08) != 0 && rEntry.nMethod == STORED)
|
||||
{
|
||||
uno::Reference<XPropertySet> xStream;
|
||||
getByHierarchicalName(rEntry.sPath) >>= xStream;
|
||||
if (!xStream->getPropertyValue("WasEncrypted").get<bool>())
|
||||
{
|
||||
SAL_INFO("package", "entry STORED with data descriptor but not encrypted: \"" << rEntry.sPath << "\"");
|
||||
throw ZipIOException(
|
||||
THROW_WHERE
|
||||
"entry STORED with data descriptor but not encrypted");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ZipPackage::parseManifest()
|
||||
{
|
||||
if ( m_nFormat != embed::StorageFormats::PACKAGE )
|
||||
|
@ -419,6 +444,8 @@ void ZipPackage::parseManifest()
|
|||
bManifestParsed = true;
|
||||
}
|
||||
|
||||
checkZipEntriesWithDD(); // check before removing entries!
|
||||
|
||||
// now hide the manifest.xml file from user
|
||||
xMetaInfFolder->removeByName( sManifest );
|
||||
}
|
||||
|
@ -665,7 +692,10 @@ void ZipPackage::getZipFileContents()
|
|||
if ( m_nFormat == embed::StorageFormats::PACKAGE )
|
||||
parseManifest();
|
||||
else if ( m_nFormat == embed::StorageFormats::OFOPXML )
|
||||
{
|
||||
parseContentType();
|
||||
checkZipEntriesWithDD();
|
||||
}
|
||||
}
|
||||
|
||||
void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments )
|
||||
|
|
Loading…
Reference in a new issue