https://bugs.documentfoundation.org/show_bug.cgi?id=173500

            Bug ID: 173500
           Summary: ZipPackageFolder::LookForUnexpectedODF12Streams
                    rejects META-INF members even when declared in
                    manifest.xml, blocking ODF Extended Package use (e.g.
                    C2PA Manifest Store)
           Product: LibreOffice
           Version: 7.4.7.2 release
          Hardware: All
                OS: All
            Status: UNCONFIRMED
          Severity: normal
          Priority: medium
         Component: filters and storage
          Assignee: [email protected]
          Reporter: [email protected]

Description:
Problem:
Embedding any additional member in META-INF (for example a C2PA Manifest Store
at META-INF/content_credential.c2pa, as required by C2PA 2.4 section A.6.3) is
rejected by LibreOffice even when that member is explicitly declared in
META-INF/manifest.xml. This prevents legitimate ODF "Extended Package"
documents (ODF 1.3 Part 2, section 2.2.2, which explicitly permits additional
META-INF members beyond the ordinary Package class restriction in 2.2.1(E))
from opening.

Error:
com.sun.star.packages.zip.ZipIOException: Bad Zip File, IOException: there are
streams not referred in manifest.xml

This is thrown even when the member IS referred to in manifest.xml.

Affected extensions tested: ODT, ODS, ODP, ODG, OTT, OTS, OTP, OTG (tested in
LibreOffice 7.4.7).

Root cause:
package/source/zippackage/ZipPackageFolder.cxx,
ZipPackageFolder::LookForUnexpectedODF12Streams():

For streams located directly under META-INF/, the code only accepts the name
"manifest.xml" or any name containing the substring "signatures"
(case-sensitive):

    if ( rShortName != "manifest.xml"
      && rShortName.indexOf( "signatures" ) == -1 )
    {
        // a stream from META-INF with unexpected name
        bHasUnexpected = true;
    }

Unlike every other location checked by this same function (see the
IsFromManifest() check a few lines further down, which applies to streams
outside META-INF), this branch never consults whether the stream is declared in
META-INF/manifest.xml. So declaring the member in the manifest does not help;
the rejection is purely based on the hardcoded filename pattern.

Reproduction independent of any particular tool/format:
Starting from a real, valid ODF document, append one extra member under
META-INF/ with standard zip tooling:

  META-INF/probe.bin              -> fails to open
  META-INF/probe-signatures.bin   -> opens (name matches the "signatures"
substring)
  META-INF/probe-SIGNATURES.bin   -> fails (case-sensitive match)

This reproduces the failure without involving any C2PA library, confirming the
restriction is purely on the literal member name, not on manifest declaration,
encryption, or content.

Proposed fix (already implemented and tested locally):
Also accept a META-INF stream when ZipPackageStream::IsFromManifest() is true
(i.e. it was declared in META-INF/manifest.xml with a FullPath matching its
location) - this flag is set during ZipPackage::parseManifest(), before
LookForUnexpectedODF12Streams() runs, so the information is already available
at that point. This brings META-INF's handling in line with the trust model
already used for every other location in the same function, and matches the ODF
Extended Package class's explicit permission for extra META-INF members
declared in the manifest (ODF 1.3 Part 2, 2.2.2; the same distinction exists in
ODF 1.2 Part 3 and ODF 1.4 Part 2).

I have a patch (a 2-line functional change plus an updated comment) and a new
CppunitTest regression test (testMetaInfManifestDeclaredMember in
package/qa/cppunit/test_zippackage.cxx, with a minimal ODT fixture) verified
against the existing package2_test suite: 23/23 tests pass, no regressions.
I'll submit this to Gerrit referencing this bug number once one is assigned.

Note: this report only concerns the native ODF package loader's filename-based
rejection. It does not concern "wholesome" encrypted ODF packages, which are
checked separately, and it makes no claim about save-roundtrip preservation of
such members, which was not tested.

Steps to Reproduce:
1. Take a valid ODF document (e.g. a .odt file) that opens correctly.
2. Using standard zip tooling (not LibreOffice), add one extra member under
META-INF/, e.g. "META-INF/content_credential.c2pa" (or, to reproduce
independent of any C2PA implementation, any arbitrary file such as
"META-INF/probe.bin").
3. Declare that member in META-INF/manifest.xml with a <manifest:file-entry>
whose manifest:full-path matches it exactly.
4. Open the resulting file in LibreOffice.

Actual Results:
The document fails to open, with:
com.sun.star.packages.zip.ZipIOException: Bad Zip File, IOException: there are
streams not referred in manifest.xml

This happens even though the added member IS referred to in manifest.xml. The
rejection is based purely on the member's filename:
ZipPackageFolder::LookForUnexpectedODF12Streams only accepts "manifest.xml" or
names containing the substring "signatures" for anything under META-INF/, and
never checks whether the stream was declared in the manifest (unlike its
handling of streams everywhere else in the package).

Expected Results:
The document should open normally. ODF 1.3 Part 2, section 2.2.2 (the "Extended
Package" class) explicitly permits additional META-INF members beyond the
ordinary Package class restriction in 2.2.1(E), so a META-INF member that is
explicitly declared in META-INF/manifest.xml should not cause native rejection.


Reproducible: Always


User Profile Reset: Yes

Additional Info:
This report only concerns the native ODF package loader's filename-based
rejection under META-INF/. It does not concern "wholesome" encrypted ODF
packages, which are checked separately, and makes no claim about save-roundtrip
preservation of such members (not tested).

A candidate fix and CppunitTest regression test have already been written and
verified locally (built against upstream master, package2_test suite: 23/23
pass, no regressions). Will submit to Gerrit referencing this bug number.

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to