xmlsecurity/Library_xmlsecurity.mk | 1 xmlsecurity/qa/unit/signing/data/bad.odt |binary xmlsecurity/qa/unit/signing/data/good.odt |binary xmlsecurity/qa/unit/signing/signing.cxx | 34 + xmlsecurity/source/helper/ooxmlsecexporter.cxx | 504 +++++++++++++++++++++++++ xmlsecurity/source/helper/ooxmlsecexporter.hxx | 37 + xmlsecurity/source/helper/xsecctl.cxx | 365 ------------------ 7 files changed, 579 insertions(+), 362 deletions(-)
New commits: commit 27fc89cce931039f8f585c10b8ee41023c777b5e Author: Miklos Vajna <vmik...@collabora.co.uk> Date: Fri Mar 11 17:09:02 2016 +0100 xmlsecurity: extract OOXML export code into its own class It was odd that import code had its own OOXMLSecParser, but export code was buried in the controller. Change-Id: Ie1964bf9c54a8b779981e8d72bf4810090cf960c diff --git a/xmlsecurity/Library_xmlsecurity.mk b/xmlsecurity/Library_xmlsecurity.mk index c594ec9..1997010 100644 --- a/xmlsecurity/Library_xmlsecurity.mk +++ b/xmlsecurity/Library_xmlsecurity.mk @@ -56,6 +56,7 @@ $(eval $(call gb_Library_add_exception_objects,xmlsecurity,\ xmlsecurity/source/helper/documentsignaturehelper \ xmlsecurity/source/helper/documentsignaturemanager \ xmlsecurity/source/helper/ooxmlsecparser \ + xmlsecurity/source/helper/ooxmlsecexporter \ xmlsecurity/source/helper/xmlsignaturehelper2 \ xmlsecurity/source/helper/xmlsignaturehelper \ xmlsecurity/source/helper/xsecctl \ diff --git a/xmlsecurity/source/helper/ooxmlsecexporter.cxx b/xmlsecurity/source/helper/ooxmlsecexporter.cxx new file mode 100644 index 0000000..d88d542 --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecexporter.cxx @@ -0,0 +1,504 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "ooxmlsecexporter.hxx" + +#include <algorithm> + +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XHierarchicalStorageAccess.hpp> +#include <com/sun/star/beans/StringPair.hpp> + +#include <comphelper/ofopxmlhelper.hxx> +#include <config_global.h> +#include <o3tl/make_unique.hxx> +#include <rtl/ref.hxx> +#include <unotools/datetime.hxx> +#include <xmloff/attrlist.hxx> + +#include <xsecctl.hxx> + +using namespace com::sun::star; + +struct OOXMLSecExporter::Impl +{ + const uno::Reference<uno::XComponentContext>& m_xComponentContext; + const uno::Reference<embed::XStorage>& m_xRootStorage; + const uno::Reference<xml::sax::XDocumentHandler>& m_xDocumentHandler; + const SignatureInformation& m_rInformation; + OUString m_aSignatureTimeValue; + + Impl(const uno::Reference<uno::XComponentContext>& xComponentContext, + const uno::Reference<embed::XStorage>& xRootStorage, + const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler, + const SignatureInformation& rInformation) + : m_xComponentContext(xComponentContext) + , m_xRootStorage(xRootStorage) + , m_xDocumentHandler(xDocumentHandler) + , m_rInformation(rInformation) + { + } + + /// Should we intentionally not sign this stream? + static bool isOOXMLBlacklist(const OUString& rStreamName); + /// Should we intentionally not sign this relation type? + static bool isOOXMLRelationBlacklist(const OUString& rRelationName); + + void writeSignedInfo(); + void writeCanonicalizationMethod(); + void writeCanonicalizationTransform(); + void writeDigestMethod(); + void writeSignatureMethod(); + void writeSignedInfoReferences(); + void writeSignatureValue(); + void writeKeyInfo(); + void writePackageObject(); + void writeManifest(); + void writeRelationshipTransform(const OUString& rURI); + /// Writes <SignatureProperties> inside idPackageObject. + void writePackageObjectSignatureProperties(); + /// Writes a single <Reference> inside <Manifest>. + void writeManifestReference(const SignatureReferenceInformation& rReference); + void writeOfficeObject(); + /// Writes <SignatureInfoV1>. + void writeSignatureInfo(); + void writePackageSignature(); + void writeSignedProperties(); +}; + +bool OOXMLSecExporter::Impl::isOOXMLBlacklist(const OUString& rStreamName) +{ +#if !HAVE_BROKEN_STATIC_INITILIZER_LIST + static +#endif + const std::initializer_list<OUStringLiteral> vBlacklist = + { + OUStringLiteral("/%5BContent_Types%5D.xml"), + OUStringLiteral("/docProps/app.xml"), + OUStringLiteral("/docProps/core.xml"), + // Don't attempt to sign other signatures for now. + OUStringLiteral("/_xmlsignatures") + }; + // Just check the prefix, as we don't care about the content type part of the stream name. + return std::find_if(vBlacklist.begin(), vBlacklist.end(), [&](const OUStringLiteral& rLiteral) + { + return rStreamName.startsWith(rLiteral); + }) != vBlacklist.end(); +} + +bool OOXMLSecExporter::Impl::isOOXMLRelationBlacklist(const OUString& rRelationName) +{ +#if !HAVE_BROKEN_STATIC_INITILIZER_LIST + static +#endif + const std::initializer_list<OUStringLiteral> vBlacklist = + { + OUStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"), + OUStringLiteral("http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"), + OUStringLiteral("http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin") + }; + return std::find(vBlacklist.begin(), vBlacklist.end(), rRelationName) != vBlacklist.end(); +} + +void OOXMLSecExporter::Impl::writeSignedInfo() +{ + m_xDocumentHandler->startElement(TAG_SIGNEDINFO, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + + writeCanonicalizationMethod(); + writeSignatureMethod(); + writeSignedInfoReferences(); + + m_xDocumentHandler->endElement(TAG_SIGNEDINFO); +} + +void OOXMLSecExporter::Impl::writeCanonicalizationMethod() +{ + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_ALGORITHM, ALGO_C14N); + m_xDocumentHandler->startElement(TAG_CANONICALIZATIONMETHOD, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + m_xDocumentHandler->endElement(TAG_CANONICALIZATIONMETHOD); + +} + +void OOXMLSecExporter::Impl::writeCanonicalizationTransform() +{ + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_ALGORITHM, ALGO_C14N); + m_xDocumentHandler->startElement(TAG_TRANSFORM, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + m_xDocumentHandler->endElement(TAG_TRANSFORM); + +} + +void OOXMLSecExporter::Impl::writeDigestMethod() +{ + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_ALGORITHM, ALGO_XMLDSIGSHA256); + m_xDocumentHandler->startElement(TAG_DIGESTMETHOD, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + m_xDocumentHandler->endElement(TAG_DIGESTMETHOD); +} + +void OOXMLSecExporter::Impl::writeSignatureMethod() +{ + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_ALGORITHM, ALGO_RSASHA256); + m_xDocumentHandler->startElement(TAG_SIGNATUREMETHOD, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + m_xDocumentHandler->endElement(TAG_SIGNATUREMETHOD); +} + +void OOXMLSecExporter::Impl::writeSignedInfoReferences() +{ + const SignatureReferenceInformations& rReferences = m_rInformation.vSignatureReferenceInfors; + for (const SignatureReferenceInformation& rReference : rReferences) + { + if (rReference.nType == SignatureReferenceType::SAMEDOCUMENT) + { + { + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + if (rReference.ouURI != "idSignedProperties") + pAttributeList->AddAttribute("Type", "http://www.w3.org/2000/09/xmldsig#Object"); + else + pAttributeList->AddAttribute("Type", "http://uri.etsi.org/01903#SignedProperties"); + pAttributeList->AddAttribute(ATTR_URI, CHAR_FRAGMENT + rReference.ouURI); + m_xDocumentHandler->startElement(TAG_REFERENCE, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + } + if (rReference.ouURI == "idSignedProperties") + { + m_xDocumentHandler->startElement(TAG_TRANSFORMS, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + writeCanonicalizationTransform(); + m_xDocumentHandler->endElement(TAG_TRANSFORMS); + } + + writeDigestMethod(); + m_xDocumentHandler->startElement(TAG_DIGESTVALUE, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters(rReference.ouDigestValue); + m_xDocumentHandler->endElement(TAG_DIGESTVALUE); + m_xDocumentHandler->endElement(TAG_REFERENCE); + } + } +} + +void OOXMLSecExporter::Impl::writeSignatureValue() +{ + m_xDocumentHandler->startElement(TAG_SIGNATUREVALUE, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouSignatureValue); + m_xDocumentHandler->endElement(TAG_SIGNATUREVALUE); +} + +void OOXMLSecExporter::Impl::writeKeyInfo() +{ + m_xDocumentHandler->startElement(TAG_KEYINFO, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->startElement(TAG_X509DATA, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->startElement(TAG_X509CERTIFICATE, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouX509Certificate); + m_xDocumentHandler->endElement(TAG_X509CERTIFICATE); + m_xDocumentHandler->endElement(TAG_X509DATA); + m_xDocumentHandler->endElement(TAG_KEYINFO); +} + +void OOXMLSecExporter::Impl::writePackageObject() +{ + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_ID, "idPackageObject"); + m_xDocumentHandler->startElement(TAG_OBJECT, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + + writeManifest(); + writePackageObjectSignatureProperties(); + + m_xDocumentHandler->endElement(TAG_OBJECT); +} + +void OOXMLSecExporter::Impl::writeManifest() +{ + m_xDocumentHandler->startElement(TAG_MANIFEST, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + const SignatureReferenceInformations& rReferences = m_rInformation.vSignatureReferenceInfors; + for (const SignatureReferenceInformation& rReference : rReferences) + { + if (rReference.nType != SignatureReferenceType::SAMEDOCUMENT) + { + if (OOXMLSecExporter::Impl::isOOXMLBlacklist(rReference.ouURI)) + continue; + + writeManifestReference(rReference); + } + } + m_xDocumentHandler->endElement(TAG_MANIFEST); +} + +void OOXMLSecExporter::Impl::writeRelationshipTransform(const OUString& rURI) +{ + uno::Reference<embed::XHierarchicalStorageAccess> xHierarchicalStorageAccess(m_xRootStorage, uno::UNO_QUERY); + uno::Reference<io::XInputStream> xRelStream(xHierarchicalStorageAccess->openStreamElementByHierarchicalName(rURI, embed::ElementModes::READ), uno::UNO_QUERY); + { + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_ALGORITHM, ALGO_RELATIONSHIP); + m_xDocumentHandler->startElement(TAG_TRANSFORM, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + } + + uno::Sequence< uno::Sequence<beans::StringPair> > aRelationsInfo = comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(xRelStream, rURI, m_xComponentContext); + for (const uno::Sequence<beans::StringPair>& rPairs : aRelationsInfo) + { + OUString aId; + OUString aType; + for (const beans::StringPair& rPair : rPairs) + { + if (rPair.First == "Id") + aId = rPair.Second; + else if (rPair.First == "Type") + aType = rPair.Second; + } + + if (OOXMLSecExporter::Impl::isOOXMLRelationBlacklist(aType)) + continue; + + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_XMLNS ":" NSTAG_MDSSI, NS_MDSSI); + pAttributeList->AddAttribute(ATTR_SOURCEID, aId); + m_xDocumentHandler->startElement(NSTAG_MDSSI ":" TAG_RELATIONSHIPREFERENCE, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + m_xDocumentHandler->endElement(NSTAG_MDSSI ":" TAG_RELATIONSHIPREFERENCE); + } + + m_xDocumentHandler->endElement(TAG_TRANSFORM); +} + +void OOXMLSecExporter::Impl::writePackageObjectSignatureProperties() +{ + m_xDocumentHandler->startElement(TAG_SIGNATUREPROPERTIES, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + { + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_ID, "idSignatureTime"); + pAttributeList->AddAttribute(ATTR_TARGET, "#idPackageSignature"); + m_xDocumentHandler->startElement(TAG_SIGNATUREPROPERTY, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + } + { + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_XMLNS ":" NSTAG_MDSSI, NS_MDSSI); + m_xDocumentHandler->startElement(NSTAG_MDSSI ":" TAG_SIGNATURETIME, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + } + m_xDocumentHandler->startElement(NSTAG_MDSSI ":" TAG_FORMAT, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("YYYY-MM-DDThh:mm:ssTZD"); + m_xDocumentHandler->endElement(NSTAG_MDSSI ":" TAG_FORMAT); + + m_xDocumentHandler->startElement(NSTAG_MDSSI ":" TAG_VALUE, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + if (!m_rInformation.ouDateTime.isEmpty()) + m_aSignatureTimeValue = m_rInformation.ouDateTime; + else + { + m_aSignatureTimeValue = utl::toISO8601(m_rInformation.stDateTime); + // Ignore sub-seconds. + sal_Int32 nCommaPos = m_aSignatureTimeValue.indexOf(','); + if (nCommaPos != -1) + { + m_aSignatureTimeValue = m_aSignatureTimeValue.copy(0, nCommaPos); + m_aSignatureTimeValue += "Z"; + } + } + m_xDocumentHandler->characters(m_aSignatureTimeValue); + m_xDocumentHandler->endElement(NSTAG_MDSSI ":" TAG_VALUE); + + m_xDocumentHandler->endElement(NSTAG_MDSSI ":" TAG_SIGNATURETIME); + m_xDocumentHandler->endElement(TAG_SIGNATUREPROPERTY); + m_xDocumentHandler->endElement(TAG_SIGNATUREPROPERTIES); +} + +void OOXMLSecExporter::Impl::writeManifestReference(const SignatureReferenceInformation& rReference) +{ + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_URI, rReference.ouURI); + m_xDocumentHandler->startElement(TAG_REFERENCE, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + + // Transforms + if (rReference.ouURI.endsWith("?ContentType=application/vnd.openxmlformats-package.relationships+xml")) + { + OUString aURI = rReference.ouURI; + // Ignore leading slash. + if (aURI.startsWith("/")) + aURI = aURI.copy(1); + // Ignore query part of the URI. + sal_Int32 nQueryPos = aURI.indexOf('?'); + if (nQueryPos != -1) + aURI = aURI.copy(0, nQueryPos); + + m_xDocumentHandler->startElement(TAG_TRANSFORMS, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + + writeRelationshipTransform(aURI); + writeCanonicalizationTransform(); + + m_xDocumentHandler->endElement(TAG_TRANSFORMS); + } + + writeDigestMethod(); + m_xDocumentHandler->startElement(TAG_DIGESTVALUE, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters(rReference.ouDigestValue); + m_xDocumentHandler->endElement(TAG_DIGESTVALUE); + m_xDocumentHandler->endElement(TAG_REFERENCE); +} + +void OOXMLSecExporter::Impl::writeOfficeObject() +{ + { + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_ID, "idOfficeObject"); + m_xDocumentHandler->startElement(TAG_OBJECT, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + } + m_xDocumentHandler->startElement(TAG_SIGNATUREPROPERTIES, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + { + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_ID, "idOfficeV1Details"); + pAttributeList->AddAttribute(ATTR_TARGET, "#idPackageSignature"); + m_xDocumentHandler->startElement(TAG_SIGNATUREPROPERTY, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + } + writeSignatureInfo(); + m_xDocumentHandler->endElement(TAG_SIGNATUREPROPERTY); + m_xDocumentHandler->endElement(TAG_SIGNATUREPROPERTIES); + m_xDocumentHandler->endElement(TAG_OBJECT); +} + +void OOXMLSecExporter::Impl::writeSignatureInfo() +{ + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_XMLNS, "http://schemas.microsoft.com/office/2006/digsig"); + m_xDocumentHandler->startElement("SignatureInfoV1", uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + + m_xDocumentHandler->startElement("SetupId", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->endElement("SetupId"); + m_xDocumentHandler->startElement("SignatureText", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->endElement("SignatureText"); + m_xDocumentHandler->startElement("SignatureImage", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->endElement("SignatureImage"); + m_xDocumentHandler->startElement("SignatureComments", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouDescription); + m_xDocumentHandler->endElement("SignatureComments"); + // Just hardcode something valid according to [MS-OFFCRYPTO]. + m_xDocumentHandler->startElement("WindowsVersion", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("6.1"); + m_xDocumentHandler->endElement("WindowsVersion"); + m_xDocumentHandler->startElement("OfficeVersion", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("16.0"); + m_xDocumentHandler->endElement("OfficeVersion"); + m_xDocumentHandler->startElement("ApplicationVersion", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("16.0"); + m_xDocumentHandler->endElement("ApplicationVersion"); + m_xDocumentHandler->startElement("Monitors", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("1"); + m_xDocumentHandler->endElement("Monitors"); + m_xDocumentHandler->startElement("HorizontalResolution", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("1280"); + m_xDocumentHandler->endElement("HorizontalResolution"); + m_xDocumentHandler->startElement("VerticalResolution", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("800"); + m_xDocumentHandler->endElement("VerticalResolution"); + m_xDocumentHandler->startElement("ColorDepth", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("32"); + m_xDocumentHandler->endElement("ColorDepth"); + m_xDocumentHandler->startElement("SignatureProviderId", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("{00000000-0000-0000-0000-000000000000}"); + m_xDocumentHandler->endElement("SignatureProviderId"); + m_xDocumentHandler->startElement("SignatureProviderUrl", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->endElement("SignatureProviderUrl"); + m_xDocumentHandler->startElement("SignatureProviderDetails", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("9"); // This is what MSO 2016 writes, though [MS-OFFCRYPTO] doesn't document what the value means. + m_xDocumentHandler->endElement("SignatureProviderDetails"); + m_xDocumentHandler->startElement("SignatureType", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("1"); + m_xDocumentHandler->endElement("SignatureType"); + + m_xDocumentHandler->endElement("SignatureInfoV1"); +} + +void OOXMLSecExporter::Impl::writePackageSignature() +{ + m_xDocumentHandler->startElement(TAG_OBJECT, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + { + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_XMLNS ":" NSTAG_XD, NS_XD); + pAttributeList->AddAttribute(ATTR_TARGET, "#idPackageSignature"); + m_xDocumentHandler->startElement(NSTAG_XD ":" TAG_QUALIFYINGPROPERTIES, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + } + + // FIXME why does this part crash NSS when MOZILLA_CERTIFICATE_FOLDER is not set? + static bool bTest = getenv("LO_TESTNAME"); + if (!bTest) + writeSignedProperties(); + + m_xDocumentHandler->endElement(NSTAG_XD ":" TAG_QUALIFYINGPROPERTIES); + m_xDocumentHandler->endElement(TAG_OBJECT); +} + +void OOXMLSecExporter::Impl::writeSignedProperties() +{ + { + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_ID, "idSignedProperties"); + m_xDocumentHandler->startElement(NSTAG_XD ":" TAG_SIGNEDPROPERTIES, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + } + + m_xDocumentHandler->startElement("xd:SignedSignatureProperties", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->startElement("xd:SigningTime", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters(m_aSignatureTimeValue); + m_xDocumentHandler->endElement("xd:SigningTime"); + m_xDocumentHandler->startElement("xd:SigningCertificate", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->startElement("xd:Cert", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->startElement("xd:CertDigest", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + writeDigestMethod(); + + m_xDocumentHandler->startElement("DigestValue", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + assert(!m_rInformation.ouCertDigest.isEmpty()); + m_xDocumentHandler->characters(m_rInformation.ouCertDigest); + m_xDocumentHandler->endElement("DigestValue"); + + m_xDocumentHandler->endElement("xd:CertDigest"); + m_xDocumentHandler->startElement("xd:IssuerSerial", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->startElement("X509IssuerName", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouX509IssuerName); + m_xDocumentHandler->endElement("X509IssuerName"); + m_xDocumentHandler->startElement("X509SerialNumber", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouX509SerialNumber); + m_xDocumentHandler->endElement("X509SerialNumber"); + m_xDocumentHandler->endElement("xd:IssuerSerial"); + m_xDocumentHandler->endElement("xd:Cert"); + m_xDocumentHandler->endElement("xd:SigningCertificate"); + m_xDocumentHandler->startElement("xd:SignaturePolicyIdentifier", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->startElement("xd:SignaturePolicyImplied", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->endElement("xd:SignaturePolicyImplied"); + m_xDocumentHandler->endElement("xd:SignaturePolicyIdentifier"); + m_xDocumentHandler->endElement("xd:SignedSignatureProperties"); + + m_xDocumentHandler->endElement(NSTAG_XD ":" TAG_SIGNEDPROPERTIES); +} + +OOXMLSecExporter::OOXMLSecExporter(const uno::Reference<uno::XComponentContext>& xComponentContext, + const uno::Reference<embed::XStorage>& xRootStorage, + const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler, + const SignatureInformation& rInformation) + : m_pImpl(o3tl::make_unique<Impl>(xComponentContext, xRootStorage, xDocumentHandler, rInformation)) +{ +} + +OOXMLSecExporter::~OOXMLSecExporter() +{ +} + +void OOXMLSecExporter::writeSignature() +{ + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute(ATTR_XMLNS, NS_XMLDSIG); + pAttributeList->AddAttribute(ATTR_ID, "idPackageSignature"); + m_pImpl->m_xDocumentHandler->startElement(TAG_SIGNATURE, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); + + m_pImpl->writeSignedInfo(); + m_pImpl->writeSignatureValue(); + m_pImpl->writeKeyInfo(); + m_pImpl->writePackageObject(); + m_pImpl->writeOfficeObject(); + m_pImpl->writePackageSignature(); + + m_pImpl->m_xDocumentHandler->endElement(TAG_SIGNATURE); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/ooxmlsecexporter.hxx b/xmlsecurity/source/helper/ooxmlsecexporter.hxx new file mode 100644 index 0000000..3b3d04e --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecexporter.hxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_HELPER_OOXMLSECEXPORTER_HXX +#define INCLUDED_XMLSECURITY_SOURCE_HELPER_OOXMLSECEXPORTER_HXX + +#include <memory> + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <xmlsecurity/sigstruct.hxx> + +/// Writes a single OOXML digital signature. +class OOXMLSecExporter +{ + struct Impl; + std::unique_ptr<Impl> m_pImpl; + +public: + OOXMLSecExporter(const css::uno::Reference<css::uno::XComponentContext>& xComponentContext, + const css::uno::Reference<css::embed::XStorage>& xRootStorage, + const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler, + const SignatureInformation& rInformation); + ~OOXMLSecExporter(); + void writeSignature(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecctl.cxx b/xmlsecurity/source/helper/xsecctl.cxx index 676e60d..f0271b8 100644 --- a/xmlsecurity/source/helper/xsecctl.cxx +++ b/xmlsecurity/source/helper/xsecctl.cxx @@ -39,6 +39,7 @@ #include <unotools/datetime.hxx> #include <comphelper/ofopxmlhelper.hxx> #include <sax/tools/converter.hxx> +#include <ooxmlsecexporter.hxx> namespace cssu = com::sun::star::uno; namespace cssl = com::sun::star::lang; @@ -854,370 +855,10 @@ void XSecController::exportSignature( xDocumentHandler->endElement( tag_Signature ); } -/// Should we intentionally not sign this stream? -static bool lcl_isOOXMLBlacklist(const OUString& rStreamName) -{ -#if !HAVE_BROKEN_STATIC_INITILIZER_LIST - static -#endif - const std::initializer_list<OUStringLiteral> vBlacklist = - { - OUStringLiteral("/%5BContent_Types%5D.xml"), - OUStringLiteral("/docProps/app.xml"), - OUStringLiteral("/docProps/core.xml"), - // Don't attempt to sign other signatures for now. - OUStringLiteral("/_xmlsignatures") - }; - // Just check the prefix, as we don't care about the content type part of the stream name. - return std::find_if(vBlacklist.begin(), vBlacklist.end(), [&](const OUStringLiteral& rLiteral) { return rStreamName.startsWith(rLiteral); }) != vBlacklist.end(); -} - -/// Should we intentionally not sign this relation type? -static bool lcl_isOOXMLRelationBlacklist(const OUString& rRelationName) -{ -#if !HAVE_BROKEN_STATIC_INITILIZER_LIST - static -#endif - const std::initializer_list<OUStringLiteral> vBlacklist = - { - OUStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"), - OUStringLiteral("http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"), - OUStringLiteral("http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin") - }; - return std::find(vBlacklist.begin(), vBlacklist.end(), rRelationName) != vBlacklist.end(); -} - void XSecController::exportOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler, const SignatureInformation& rInformation) { - uno::Reference<embed::XHierarchicalStorageAccess> xHierarchicalStorageAccess(xRootStorage, uno::UNO_QUERY); - - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_XMLNS, NS_XMLDSIG); - pAttributeList->AddAttribute(ATTR_ID, "idPackageSignature"); - xDocumentHandler->startElement(TAG_SIGNATURE, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - xDocumentHandler->startElement(TAG_SIGNEDINFO, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_ALGORITHM, ALGO_C14N); - xDocumentHandler->startElement(TAG_CANONICALIZATIONMETHOD, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - xDocumentHandler->endElement(TAG_CANONICALIZATIONMETHOD); - } - - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_ALGORITHM, ALGO_RSASHA256); - xDocumentHandler->startElement(TAG_SIGNATUREMETHOD, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - xDocumentHandler->endElement(TAG_SIGNATUREMETHOD); - } - - const SignatureReferenceInformations& rReferences = rInformation.vSignatureReferenceInfors; - for (const SignatureReferenceInformation& rReference : rReferences) - { - if (rReference.nType == SignatureReferenceType::SAMEDOCUMENT) - { - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - if (rReference.ouURI != "idSignedProperties") - pAttributeList->AddAttribute("Type", "http://www.w3.org/2000/09/xmldsig#Object"); - else - pAttributeList->AddAttribute("Type", "http://uri.etsi.org/01903#SignedProperties"); - pAttributeList->AddAttribute(ATTR_URI, CHAR_FRAGMENT + rReference.ouURI); - xDocumentHandler->startElement(TAG_REFERENCE, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - if (rReference.ouURI == "idSignedProperties") - { - xDocumentHandler->startElement(TAG_TRANSFORMS, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_ALGORITHM, ALGO_C14N); - xDocumentHandler->startElement(TAG_TRANSFORM, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - xDocumentHandler->endElement(TAG_TRANSFORM); - xDocumentHandler->endElement(TAG_TRANSFORMS); - } - - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_ALGORITHM, ALGO_XMLDSIGSHA256); - xDocumentHandler->startElement(TAG_DIGESTMETHOD, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - xDocumentHandler->endElement(TAG_DIGESTMETHOD); - } - xDocumentHandler->startElement(TAG_DIGESTVALUE, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters(rReference.ouDigestValue); - xDocumentHandler->endElement(TAG_DIGESTVALUE); - xDocumentHandler->endElement(TAG_REFERENCE); - } - } - - xDocumentHandler->endElement(TAG_SIGNEDINFO); - - xDocumentHandler->startElement(TAG_SIGNATUREVALUE, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters(rInformation.ouSignatureValue); - xDocumentHandler->endElement(TAG_SIGNATUREVALUE); - - xDocumentHandler->startElement(TAG_KEYINFO, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->startElement(TAG_X509DATA, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->startElement(TAG_X509CERTIFICATE, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters(rInformation.ouX509Certificate); - xDocumentHandler->endElement(TAG_X509CERTIFICATE); - xDocumentHandler->endElement(TAG_X509DATA); - xDocumentHandler->endElement(TAG_KEYINFO); - - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_ID, "idPackageObject"); - xDocumentHandler->startElement(TAG_OBJECT, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - xDocumentHandler->startElement(TAG_MANIFEST, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - for (const SignatureReferenceInformation& rReference : rReferences) - { - if (rReference.nType != SignatureReferenceType::SAMEDOCUMENT) - { - if (lcl_isOOXMLBlacklist(rReference.ouURI)) - continue; - - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_URI, rReference.ouURI); - xDocumentHandler->startElement(TAG_REFERENCE, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - - // Transforms - if (rReference.ouURI.endsWith("?ContentType=application/vnd.openxmlformats-package.relationships+xml")) - { - OUString aURI = rReference.ouURI; - // Ignore leading slash. - if (aURI.startsWith("/")) - aURI = aURI.copy(1); - // Ignore query part of the URI. - sal_Int32 nQueryPos = aURI.indexOf('?'); - if (nQueryPos != -1) - aURI = aURI.copy(0, nQueryPos); - - uno::Reference<io::XInputStream> xRelStream(xHierarchicalStorageAccess->openStreamElementByHierarchicalName(aURI, embed::ElementModes::READ), uno::UNO_QUERY); - xDocumentHandler->startElement(TAG_TRANSFORMS, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_ALGORITHM, ALGO_RELATIONSHIP); - xDocumentHandler->startElement(TAG_TRANSFORM, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - - uno::Sequence< uno::Sequence<beans::StringPair> > aRelationsInfo = comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(xRelStream, aURI, mxCtx); - for (const uno::Sequence<beans::StringPair>& rPairs : aRelationsInfo) - { - OUString aId; - OUString aType; - for (const beans::StringPair& rPair : rPairs) - { - if (rPair.First == "Id") - aId = rPair.Second; - else if (rPair.First == "Type") - aType = rPair.Second; - } - - if (lcl_isOOXMLRelationBlacklist(aType)) - continue; - - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_XMLNS ":" NSTAG_MDSSI, NS_MDSSI); - pAttributeList->AddAttribute(ATTR_SOURCEID, aId); - xDocumentHandler->startElement(NSTAG_MDSSI ":" TAG_RELATIONSHIPREFERENCE, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - xDocumentHandler->endElement(NSTAG_MDSSI ":" TAG_RELATIONSHIPREFERENCE); - } - - xDocumentHandler->endElement(TAG_TRANSFORM); - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_ALGORITHM, ALGO_C14N); - xDocumentHandler->startElement(TAG_TRANSFORM, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - xDocumentHandler->endElement(TAG_TRANSFORM); - xDocumentHandler->endElement(TAG_TRANSFORMS); - } - - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_ALGORITHM, ALGO_XMLDSIGSHA256); - xDocumentHandler->startElement(TAG_DIGESTMETHOD, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - xDocumentHandler->endElement(TAG_DIGESTMETHOD); - } - xDocumentHandler->startElement(TAG_DIGESTVALUE, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters(rReference.ouDigestValue); - xDocumentHandler->endElement(TAG_DIGESTVALUE); - xDocumentHandler->endElement(TAG_REFERENCE); - } - } - xDocumentHandler->endElement(TAG_MANIFEST); - - // SignatureProperties - xDocumentHandler->startElement(TAG_SIGNATUREPROPERTIES, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_ID, "idSignatureTime"); - pAttributeList->AddAttribute(ATTR_TARGET, "#idPackageSignature"); - xDocumentHandler->startElement(TAG_SIGNATUREPROPERTY, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_XMLNS ":" NSTAG_MDSSI, NS_MDSSI); - xDocumentHandler->startElement(NSTAG_MDSSI ":" TAG_SIGNATURETIME, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - xDocumentHandler->startElement(NSTAG_MDSSI ":" TAG_FORMAT, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters("YYYY-MM-DDThh:mm:ssTZD"); - xDocumentHandler->endElement(NSTAG_MDSSI ":" TAG_FORMAT); - - xDocumentHandler->startElement(NSTAG_MDSSI ":" TAG_VALUE, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - OUString aSignatureTimeValue; - if (!rInformation.ouDateTime.isEmpty()) - aSignatureTimeValue = rInformation.ouDateTime; - else - { - aSignatureTimeValue = utl::toISO8601(rInformation.stDateTime); - // Ignore sub-seconds. - sal_Int32 nCommaPos = aSignatureTimeValue.indexOf(','); - if (nCommaPos != -1) - { - aSignatureTimeValue = aSignatureTimeValue.copy(0, nCommaPos); - aSignatureTimeValue += "Z"; - } - } - xDocumentHandler->characters(aSignatureTimeValue); - xDocumentHandler->endElement(NSTAG_MDSSI ":" TAG_VALUE); - - xDocumentHandler->endElement(NSTAG_MDSSI ":" TAG_SIGNATURETIME); - xDocumentHandler->endElement(TAG_SIGNATUREPROPERTY); - xDocumentHandler->endElement(TAG_SIGNATUREPROPERTIES); - - xDocumentHandler->endElement(TAG_OBJECT); - - // idOfficeObject - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_ID, "idOfficeObject"); - xDocumentHandler->startElement(TAG_OBJECT, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - xDocumentHandler->startElement(TAG_SIGNATUREPROPERTIES, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_ID, "idOfficeV1Details"); - pAttributeList->AddAttribute(ATTR_TARGET, "#idPackageSignature"); - xDocumentHandler->startElement(TAG_SIGNATUREPROPERTY, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_XMLNS, "http://schemas.microsoft.com/office/2006/digsig"); - xDocumentHandler->startElement("SignatureInfoV1", uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - xDocumentHandler->startElement("SetupId", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->endElement("SetupId"); - xDocumentHandler->startElement("SignatureText", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->endElement("SignatureText"); - xDocumentHandler->startElement("SignatureImage", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->endElement("SignatureImage"); - xDocumentHandler->startElement("SignatureComments", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters(rInformation.ouDescription); - xDocumentHandler->endElement("SignatureComments"); - // Just hardcode something valid according to [MS-OFFCRYPTO]. - xDocumentHandler->startElement("WindowsVersion", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters("6.1"); - xDocumentHandler->endElement("WindowsVersion"); - xDocumentHandler->startElement("OfficeVersion", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters("16.0"); - xDocumentHandler->endElement("OfficeVersion"); - xDocumentHandler->startElement("ApplicationVersion", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters("16.0"); - xDocumentHandler->endElement("ApplicationVersion"); - xDocumentHandler->startElement("Monitors", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters("1"); - xDocumentHandler->endElement("Monitors"); - xDocumentHandler->startElement("HorizontalResolution", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters("1280"); - xDocumentHandler->endElement("HorizontalResolution"); - xDocumentHandler->startElement("VerticalResolution", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters("800"); - xDocumentHandler->endElement("VerticalResolution"); - xDocumentHandler->startElement("ColorDepth", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters("32"); - xDocumentHandler->endElement("ColorDepth"); - xDocumentHandler->startElement("SignatureProviderId", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters("{00000000-0000-0000-0000-000000000000}"); - xDocumentHandler->endElement("SignatureProviderId"); - xDocumentHandler->startElement("SignatureProviderUrl", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->endElement("SignatureProviderUrl"); - xDocumentHandler->startElement("SignatureProviderDetails", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters("9"); // This is what MSO 2016 writes, though [MS-OFFCRYPTO] doesn't document what the value means. - xDocumentHandler->endElement("SignatureProviderDetails"); - xDocumentHandler->startElement("SignatureType", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters("1"); - xDocumentHandler->endElement("SignatureType"); - xDocumentHandler->endElement("SignatureInfoV1"); - xDocumentHandler->endElement(TAG_SIGNATUREPROPERTY); - xDocumentHandler->endElement(TAG_SIGNATUREPROPERTIES); - xDocumentHandler->endElement(TAG_OBJECT); - - xDocumentHandler->startElement(TAG_OBJECT, uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_XMLNS ":" NSTAG_XD, NS_XD); - pAttributeList->AddAttribute(ATTR_TARGET, "#idPackageSignature"); - xDocumentHandler->startElement(NSTAG_XD ":" TAG_QUALIFYINGPROPERTIES, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - - // FIXME why does this part crash NSS when MOZILLA_CERTIFICATE_FOLDER is not set? - static bool bTest = getenv("LO_TESTNAME"); - if (!bTest) - { - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_ID, "idSignedProperties"); - xDocumentHandler->startElement(NSTAG_XD ":" TAG_SIGNEDPROPERTIES, uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - - xDocumentHandler->startElement("xd:SignedSignatureProperties", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->startElement("xd:SigningTime", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters(aSignatureTimeValue); - xDocumentHandler->endElement("xd:SigningTime"); - xDocumentHandler->startElement("xd:SigningCertificate", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->startElement("xd:Cert", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->startElement("xd:CertDigest", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - { - rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); - pAttributeList->AddAttribute(ATTR_ALGORITHM, ALGO_XMLDSIGSHA256); - xDocumentHandler->startElement("DigestMethod", uno::Reference<xml::sax::XAttributeList>(pAttributeList.get())); - } - xDocumentHandler->endElement("DigestMethod"); - xDocumentHandler->startElement("DigestValue", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - - assert(!rInformation.ouCertDigest.isEmpty()); - xDocumentHandler->characters(rInformation.ouCertDigest); - - xDocumentHandler->endElement("DigestValue"); - xDocumentHandler->endElement("xd:CertDigest"); - xDocumentHandler->startElement("xd:IssuerSerial", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->startElement("X509IssuerName", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters(rInformation.ouX509IssuerName); - xDocumentHandler->endElement("X509IssuerName"); - xDocumentHandler->startElement("X509SerialNumber", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->characters(rInformation.ouX509SerialNumber); - xDocumentHandler->endElement("X509SerialNumber"); - xDocumentHandler->endElement("xd:IssuerSerial"); - xDocumentHandler->endElement("xd:Cert"); - xDocumentHandler->endElement("xd:SigningCertificate"); - xDocumentHandler->startElement("xd:SignaturePolicyIdentifier", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->startElement("xd:SignaturePolicyImplied", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); - xDocumentHandler->endElement("xd:SignaturePolicyImplied"); - xDocumentHandler->endElement("xd:SignaturePolicyIdentifier"); - xDocumentHandler->endElement("xd:SignedSignatureProperties"); - - xDocumentHandler->endElement(NSTAG_XD ":" TAG_SIGNEDPROPERTIES); - } - xDocumentHandler->endElement(NSTAG_XD ":" TAG_QUALIFYINGPROPERTIES); - xDocumentHandler->endElement(TAG_OBJECT); - - xDocumentHandler->endElement(TAG_SIGNATURE); + OOXMLSecExporter aExporter(mxCtx, xRootStorage, xDocumentHandler, rInformation); + aExporter.writeSignature(); } SignatureInformation XSecController::getSignatureInformation( sal_Int32 nSecurityId ) const commit 6c11778ee6919b0f16acb17a896f65d4021f3089 Author: Miklos Vajna <vmik...@collabora.co.uk> Date: Fri Mar 11 14:53:13 2016 +0100 CppunitTest_xmlsecurity_signing: add ODF verification testcases Change-Id: I08734b7841fc83b327ebbf5c8ae43f7969e94e12 diff --git a/xmlsecurity/qa/unit/signing/data/bad.odt b/xmlsecurity/qa/unit/signing/data/bad.odt new file mode 100644 index 0000000..75c39d5 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/bad.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/good.odt b/xmlsecurity/qa/unit/signing/data/good.odt new file mode 100644 index 0000000..8c6019d Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/good.odt differ diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx index b576b3b..2ee8e33 100644 --- a/xmlsecurity/qa/unit/signing/signing.cxx +++ b/xmlsecurity/qa/unit/signing/signing.cxx @@ -61,6 +61,10 @@ public: virtual void tearDown() override; void testDescription(); + /// Test a typical ODF where all streams are signed. + void testODFGood(); + /// Test a typical broken ODF signature where one stream is corrupted. + void testODFBroken(); /// Test a typical OOXML where a number of (but not all) streams are signed. void testOOXMLPartial(); /// Test a typical broken OOXML signature where one stream is corrupted. @@ -75,6 +79,9 @@ public: CPPUNIT_TEST_SUITE(SigningTest); CPPUNIT_TEST(testDescription); + CPPUNIT_TEST(testODFGood); + CPPUNIT_TEST(testODFBroken); + CPPUNIT_TEST(testODFBroken); CPPUNIT_TEST(testOOXMLPartial); CPPUNIT_TEST(testOOXMLBroken); CPPUNIT_TEST(testOOXMLDescription); @@ -301,6 +308,33 @@ void SigningTest::testOOXMLRemoveAll() })); } +void SigningTest::testODFGood() +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "good.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + // We expect NOTVALIDATED in case the root CA is not imported on the system, and OK otherwise, so accept both. + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number( + static_cast<std::underlying_type<SignatureState>::type>(nActual)) + .getStr()), + (nActual == SignatureState::NOTVALIDATED + || nActual == SignatureState::PARTIAL_OK)); +} + +void SigningTest::testODFBroken() +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN), static_cast<int>(pObjectShell->GetDocumentSignatureState())); +} + void SigningTest::testOOXMLPartial() { createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.docx"); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits