diff options
Diffstat (limited to '')
-rw-r--r-- | xmlsecurity/inc/xsecctl.hxx | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/xmlsecurity/inc/xsecctl.hxx b/xmlsecurity/inc/xsecctl.hxx new file mode 100644 index 000000000..adfd251b1 --- /dev/null +++ b/xmlsecurity/inc/xsecctl.hxx @@ -0,0 +1,408 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <svl/sigstruct.hxx> + +#include <com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeListener.hpp> +#include <com/sun/star/xml/crypto/sax/XSignatureCreationResultListener.hpp> +#include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultListener.hpp> + +#include <rtl/ref.hxx> +#include <cppuhelper/implbase.hxx> + +#include <vector> + +#include "UriBindingHelper.hxx" + +namespace com::sun::star::embed { class XStorage; } +namespace com::sun::star::graphic { class XGraphic; } +namespace com::sun::star::io { class XInputStream; } +namespace com::sun::star::lang { class XInitialization; } +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::xml::crypto { class XXMLSecurityContext; } +namespace com::sun::star::xml::crypto { class XXMLSignature; } +namespace com::sun::star::xml::crypto:: sax { class XReferenceResolvedListener; } +namespace com::sun::star::xml::sax { class XDocumentHandler; } + +inline constexpr OUStringLiteral NS_XMLDSIG = u"http://www.w3.org/2000/09/xmldsig#"; +inline constexpr OUStringLiteral NS_DC = u"http://purl.org/dc/elements/1.1/"; +inline constexpr OUStringLiteral NS_XD = u"http://uri.etsi.org/01903/v1.3.2#"; +inline constexpr OUStringLiteral NS_MDSSI = u"http://schemas.openxmlformats.org/package/2006/digital-signature"; +inline constexpr OUStringLiteral NS_LOEXT = u"urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"; + +inline constexpr OUStringLiteral ALGO_C14N = u"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; +inline constexpr OUStringLiteral ALGO_RSASHA1 = u"http://www.w3.org/2000/09/xmldsig#rsa-sha1"; +inline constexpr OUStringLiteral ALGO_RSASHA256 = u"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; +inline constexpr OUStringLiteral ALGO_RSASHA512 = u"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"; +inline constexpr OUStringLiteral ALGO_ECDSASHA1 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"; +inline constexpr OUStringLiteral ALGO_ECDSASHA256 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"; +inline constexpr OUStringLiteral ALGO_ECDSASHA512 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"; +inline constexpr OUStringLiteral ALGO_XMLDSIGSHA1 = u"http://www.w3.org/2000/09/xmldsig#sha1"; +inline constexpr OUStringLiteral ALGO_XMLDSIGSHA256 = u"http://www.w3.org/2001/04/xmlenc#sha256"; +inline constexpr OUStringLiteral ALGO_XMLDSIGSHA512 = u"http://www.w3.org/2001/04/xmlenc#sha512"; +inline constexpr OUStringLiteral ALGO_RELATIONSHIP = u"http://schemas.openxmlformats.org/package/2006/RelationshipTransform"; + +class XMLDocumentWrapper_XmlSecImpl; +class SAXEventKeeperImpl; +class XMLSignatureHelper; +namespace svl::crypto { enum class SignatureMethodAlgorithm; } + +class InternalSignatureInformation +{ +public: + SignatureInformation signatureInfor; + + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener; + + ::std::vector< sal_Int32 > vKeeperIds; + + InternalSignatureInformation( + sal_Int32 nId, + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > const & xListener) + :signatureInfor(nId) + { + xReferenceResolvedListener = xListener; + } + + void addReference( SignatureReferenceType type, sal_Int32 digestID, const OUString& uri, sal_Int32 keeperId, const OUString& rType ) + { + signatureInfor.vSignatureReferenceInfors.push_back( + SignatureReferenceInformation(type, digestID, uri, rType)); + vKeeperIds.push_back( keeperId ); + } +}; + +class XSecController final : public cppu::WeakImplHelper +< + css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener, + css::xml::crypto::sax::XSignatureCreationResultListener, + css::xml::crypto::sax::XSignatureVerifyResultListener +> +/****** XSecController.hxx/CLASS XSecController ******************************* + * + * NAME + * XSecController -- the xml security framework controller + * + * FUNCTION + * Controls the whole xml security framework to create signatures or to + * verify signatures. + * + ******************************************************************************/ +{ + friend class XSecParser; + friend class OOXMLSecParser; + +private: + css::uno::Reference< css::uno::XComponentContext> mxCtx; + + /* + * used to buffer SAX events + */ + rtl::Reference<XMLDocumentWrapper_XmlSecImpl> m_xXMLDocumentWrapper; + + /* + * the SAX events keeper + */ + rtl::Reference<SAXEventKeeperImpl> m_xSAXEventKeeper; + + /* + * the bridge component which creates/verifies signature + */ + css::uno::Reference< css::xml::crypto::XXMLSignature > m_xXMLSignature; + + /* + * the Security Context + */ + css::uno::Reference< css::xml::crypto::XXMLSecurityContext > m_xSecurityContext; + + /* + * the security id incrementer, in order to make any security id unique + * to the SAXEventKeeper. + * Because each XSecController has its own SAXEventKeeper, so this variable + * is not necessary to be static. + */ + sal_Int32 m_nNextSecurityId; + + /* + * Signature information + */ + std::vector< InternalSignatureInformation > m_vInternalSignatureInformations; + + /* + * the previous node on the SAX chain. + * The reason that use a Reference<XInterface> type variable + * is that the previous components are different when exporting + * and importing, and there is no other common interface they + * can provided. + */ + css::uno::Reference< css::uno::XInterface > m_xPreviousNodeOnSAXChain; + /* + * whether the previous node can provide an XInitialize interface, + * use this variable in order to typecast the XInterface to the + * correct interface type. + */ + bool m_bIsPreviousNodeInitializable; + + /* + * a flag representing whether the SAXEventKeeper is now on the + * SAX chain. + */ + bool m_bIsSAXEventKeeperConnected; + + /* + * a flag representing whether it is collecting some element, + * which means that the SAXEventKeeper can't be chained off the + * SAX chain. + */ + bool m_bIsCollectingElement; + + /* + * a flag representing whether the SAX event stream is blocking, + * which also means that the SAXEventKeeper can't be chained off + * the SAX chain. + */ + bool m_bIsBlocking; + + /* + * a flag representing the current status of security related + * components. + */ + + /* + * status of security related components + */ + enum class InitializationState { UNINITIALIZED, INITIALIZED, FAILTOINITIALIZED } m_eStatusOfSecurityComponents; + + /* + * a flag representing whether the SAXEventKeeper need to be + * on the SAX chain all the time. + * This flag is used to the situation when creating signature. + */ + bool m_bIsSAXEventKeeperSticky; + + /* + * the XSecParser which is used to parse the signature stream + */ + css::uno::Reference<css::xml::sax::XDocumentHandler> m_xSecParser; + + /* + * the caller assigned signature id for the next signature in the + * signature stream + */ + sal_Int32 m_nReservedSignatureId; + + /* + * representing whether to verify the current signature + */ + bool m_bVerifyCurrentSignature; + + /* + * An xUriBinding is provided to map Uris to XInputStream interfaces. + */ + rtl::Reference<UriBindingHelper> m_xUriBinding; + +private: + + /* + * Common methods + */ + void createXSecComponent( ); + int findSignatureInfor( sal_Int32 nSecurityId ) const; + bool chainOn(); + void chainOff(); + void checkChainingStatus(); + void initializeSAXChain(); + + css::uno::Reference< css::io::XInputStream > getObjectInputStream( const OUString& objectURL ); + + //sal_Int32 getFastPropertyIndex(sal_Int32 nHandle) const; + + /* + * For signature generation + */ + static OUString createId(); + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > prepareSignatureToWrite( + InternalSignatureInformation& signatureInfo, + sal_Int32 nStorageFormat, + bool bXAdESCompliantIfODF ); + + /* + * For signature verification + */ + void addSignature(); + /// Sets algorithm from <SignatureMethod Algorithm="...">. + void setSignatureMethod(svl::crypto::SignatureMethodAlgorithm eAlgorithmID); + void switchGpgSignature(); + bool haveReferenceForId(std::u16string_view rId) const; + void addReference( + const OUString& ouUri, + sal_Int32 nDigestID, + const OUString& ouType ); + void addStreamReference( + const OUString& ouUri, + bool isBinary, + sal_Int32 nDigestID ); + void setReferenceCount() const; + + void setX509Data( + std::vector<std::pair<OUString, OUString>> & rX509IssuerSerials, + std::vector<OUString> const& rX509Certificates); + void setX509CertDigest( + OUString const& rCertDigest, sal_Int32 const nReferenceDigestID, + std::u16string_view const& rX509IssuerName, std::u16string_view const& rX509SerialNumber); + + void setSignatureValue( OUString const & ouSignatureValue ); + void setDigestValue( sal_Int32 nDigestID, OUString const & ouDigestValue ); + void setGpgKeyID( OUString const & ouKeyID ); + void setGpgCertificate( OUString const & ouGpgCert ); + void setGpgOwner( OUString const & ouGpgOwner ); + + void setDate(OUString const& rId, OUString const& ouDate); + void setDescription(OUString const& rId, OUString const& rDescription); + void setValidSignatureImage(std::u16string_view rValidSigImg); + void setInvalidSignatureImage(std::u16string_view rInvalidSigImg); + void setSignatureLineId(const OUString& rSignatureLineId); + +public: + void setSignatureBytes(const css::uno::Sequence<sal_Int8>& rBytes); + +private: + void setId( OUString const & ouId ); + + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > prepareSignatureToRead( + sal_Int32 nSecurityId ); + +public: + explicit XSecController(const css::uno::Reference<css::uno::XComponentContext>& rxCtx); + virtual ~XSecController() override; + + sal_Int32 getNewSecurityId( ); + + void startMission(const rtl::Reference<UriBindingHelper>& xUriBinding, const css::uno::Reference<css::xml::crypto::XXMLSecurityContext>& xSecurityContext); + + void setSAXChainConnector(const css::uno::Reference< css::lang::XInitialization >& xInitialization); + + void clearSAXChainConnector(); + void endMission(); + + SignatureInformation getSignatureInformation( sal_Int32 nSecurityId ) const; + SignatureInformations getSignatureInformations() const; + /// only verify can figure out which X509Data is the signing certificate + void UpdateSignatureInformation(sal_Int32 nSecurityId, + std::vector<SignatureInformation::X509Data> && rDatas); + + static void exportSignature( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler, + const SignatureInformation& signatureInfo, + bool bXAdESCompliantIfODF ); + + + /* + * For signature generation + */ + void signAStream( sal_Int32 securityId, const OUString& uri, bool isBinary, bool bXAdESCompliantIfODF); + + + /** sets data that describes the certificate. + + It is absolutely necessary that the parameter ouX509IssuerName is set. It contains + the base64 encoded certificate, which is DER encoded. The XMLSec needs it to find + the private key. Although issuer name and certificate should be sufficient to identify + the certificate the implementation in XMLSec is broken, both for Windows and mozilla. + The reason is that they use functions to find the certificate which take as parameter + the DER encoded ASN.1 issuer name. The issuer name is a DName, where most attributes + are of type DirectoryName, which is a choice of 5 string types. This information is + not contained in the issuer string and while it is converted to the ASN.1 name the + conversion function must assume a particular type, which is often wrong. For example, + the Windows function CertStrToName will use a T.61 string if the string does not contain + special characters. So if the certificate uses simple characters but encodes the + issuer attributes in Utf8, then CertStrToName will use T.61. The resulting DER encoded + ASN.1 name now contains different bytes which indicate the string type. The functions + for finding the certificate apparently use memcmp - hence they fail to find the + certificate. + */ + void setX509Certificate( + sal_Int32 nSecurityId, + const OUString& ouX509IssuerName, + const OUString& ouX509SerialNumber, + const OUString& ouX509Cert, + const OUString& ouX509CertDigest, + svl::crypto::SignatureMethodAlgorithm eAlgorithmID); + + void addEncapsulatedX509Certificate(const OUString& rEncapsulatedX509Certificate); + + void setGpgCertificate( + sal_Int32 nSecurityId, + const OUString& ouCertDigest, + const OUString& ouCert, + const OUString& ouOwner); + + void setDate( + sal_Int32 nSecurityId, + const css::util::DateTime& rDateTime ); + void setDescription(sal_Int32 nSecurityId, const OUString& rDescription); + void setSignatureLineId(sal_Int32 nSecurityId, const OUString& rSignatureLineId); + void + setSignatureLineValidGraphic(sal_Int32 nSecurityId, + const css::uno::Reference<css::graphic::XGraphic>& xValidGraphic); + void setSignatureLineInvalidGraphic( + sal_Int32 nSecurityId, const css::uno::Reference<css::graphic::XGraphic>& xInvalidGraphic); + + bool WriteSignature( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler, + bool bXAdESCompliantIfODF); + + /* + * For signature verification + */ + void collectToVerify( std::u16string_view referenceId ); + void addSignature( sal_Int32 nSignatureId ); + css::uno::Reference< css::xml::sax::XDocumentHandler > const & createSignatureReader(XMLSignatureHelper& rXMLSignatureHelper, sal_Int32 nType = 0); + void releaseSignatureReader(); + +public: + /* Interface methods */ + + /* + * XSAXEventKeeperStatusChangeListener + */ + virtual void SAL_CALL blockingStatusChanged( sal_Bool isBlocking ) override; + virtual void SAL_CALL collectionStatusChanged( + sal_Bool isInsideCollectedElement ) override; + virtual void SAL_CALL bufferStatusChanged( sal_Bool isBufferEmpty ) override; + + /* + * XSignatureCreationResultListener + */ + virtual void SAL_CALL signatureCreated( sal_Int32 securityId, css::xml::crypto::SecurityOperationStatus nResult ) override; + + /* + * XSignatureVerifyResultListener + */ + virtual void SAL_CALL signatureVerified( sal_Int32 securityId, css::xml::crypto::SecurityOperationStatus nResult ) override; + + /// Writes XML elements inside a single OOXML signature's <Signature> element. + bool WriteOOXMLSignature(const css::uno::Reference<css::embed::XStorage>& xRootStorage, const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler); + /// Exports an OOXML signature, called by WriteOOXMLSignature(). + void exportOOXMLSignature(const css::uno::Reference<css::embed::XStorage>& xRootStorage, const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler, const SignatureInformation& rInformation); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |