diff options
Diffstat (limited to 'xmlsecurity/source/helper/xsecverify.cxx')
-rw-r--r-- | xmlsecurity/source/helper/xsecverify.cxx | 537 |
1 files changed, 537 insertions, 0 deletions
diff --git a/xmlsecurity/source/helper/xsecverify.cxx b/xmlsecurity/source/helper/xsecverify.cxx new file mode 100644 index 000000000..c826971b1 --- /dev/null +++ b/xmlsecurity/source/helper/xsecverify.cxx @@ -0,0 +1,537 @@ +/* -*- 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 . + */ + +#include <config_gpgme.h> + +#include <xsecctl.hxx> +#include "xsecparser.hxx" +#include "ooxmlsecparser.hxx" +#include <framework/signatureverifierimpl.hxx> +#include <framework/saxeventkeeperimpl.hxx> +#include <gpg/xmlsignature_gpgimpl.hxx> +#include <gpg/SEInitializer.hxx> + +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/xml/crypto/sax/XKeyCollector.hpp> +#include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp> +#include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp> +#include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp> +#include <com/sun/star/xml/crypto/XSEInitializer.hpp> +#include <com/sun/star/graphic/GraphicProvider.hpp> +#include <com/sun/star/embed/StorageFormats.hpp> +#include <sal/log.hxx> +#include <unotools/datetime.hxx> +#include <comphelper/base64.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/seqstream.hxx> + +namespace com::sun::star::graphic { class XGraphic; } + +using namespace css; +using namespace css::uno; +using namespace css::beans; + +/* protected: for signature verify */ +css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > XSecController::prepareSignatureToRead( + sal_Int32 nSecurityId) +{ + if ( m_eStatusOfSecurityComponents != InitializationState::INITIALIZED ) + { + return nullptr; + } + + sal_Int32 nIdOfSignatureElementCollector; + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener; + + nIdOfSignatureElementCollector = + m_xSAXEventKeeper->addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY, false); + + m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId); + + /* + * create a SignatureVerifier + */ + xReferenceResolvedListener = new SignatureVerifierImpl; + + css::uno::Reference<css::lang::XInitialization> xInitialization(xReferenceResolvedListener, css::uno::UNO_QUERY); + + css::uno::Sequence<css::uno::Any> args(5); + args[0] <<= OUString::number(nSecurityId); + args[1] <<= uno::Reference<xml::crypto::sax::XSecuritySAXEventKeeper>(static_cast<cppu::OWeakObject*>(m_xSAXEventKeeper.get()), uno::UNO_QUERY); + args[2] <<= OUString::number(nIdOfSignatureElementCollector); + args[3] <<= m_xSecurityContext; + args[4] <<= m_xXMLSignature; + xInitialization->initialize(args); + + css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultBroadcaster > + signatureVerifyResultBroadcaster(xReferenceResolvedListener, css::uno::UNO_QUERY); + + signatureVerifyResultBroadcaster->addSignatureVerifyResultListener( this ); + + m_xSAXEventKeeper->addReferenceResolvedListener( + nIdOfSignatureElementCollector, + xReferenceResolvedListener); + + css::uno::Reference<css::xml::crypto::sax::XKeyCollector> keyCollector (xReferenceResolvedListener, css::uno::UNO_QUERY); + keyCollector->setKeyId(0); + + return xReferenceResolvedListener; +} + +void XSecController::addSignature() +{ + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener; + sal_Int32 nSignatureId = 0; + + + if (m_bVerifyCurrentSignature) + { + chainOn(); + xReferenceResolvedListener = prepareSignatureToRead( m_nReservedSignatureId ); + m_bVerifyCurrentSignature = false; + nSignatureId = m_nReservedSignatureId; + } + + InternalSignatureInformation isi( nSignatureId, xReferenceResolvedListener ); + m_vInternalSignatureInformations.push_back( isi ); +} + +void XSecController::setSignatureMethod(svl::crypto::SignatureMethodAlgorithm eAlgorithmID) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + m_vInternalSignatureInformations.back().signatureInfor.eAlgorithmID = eAlgorithmID; +} + +void XSecController::switchGpgSignature() +{ +#if HAVE_FEATURE_GPGME + // swap signature verifier for the Gpg one + m_xXMLSignature.set(new XMLSignature_GpgImpl()); + if (!m_vInternalSignatureInformations.empty()) + { + SignatureVerifierImpl* pImpl= + dynamic_cast<SignatureVerifierImpl*>( + m_vInternalSignatureInformations.back().xReferenceResolvedListener.get()); + if (pImpl) + { + css::uno::Reference<css::xml::crypto::XSEInitializer> xGpgSEInitializer( + new SEInitializerGpg()); + pImpl->updateSignature(new XMLSignature_GpgImpl(), + xGpgSEInitializer->createSecurityContext(OUString())); + } + } +#else + (void) this; +#endif +} + +void XSecController::addReference( const OUString& ouUri, sal_Int32 nDigestID, const OUString& ouType ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::addReference: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.addReference(SignatureReferenceType::SAMEDOCUMENT, nDigestID, ouUri, -1, ouType ); +} + +void XSecController::addStreamReference( + const OUString& ouUri, + bool isBinary, + sal_Int32 nDigestID ) +{ + SignatureReferenceType type = (isBinary?SignatureReferenceType::BINARYSTREAM:SignatureReferenceType::XMLSTREAM); + + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::addStreamReference: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + + if ( isi.xReferenceResolvedListener.is() ) + { + /* + * get the input stream + */ + css::uno::Reference< css::io::XInputStream > xObjectInputStream + = getObjectInputStream( ouUri ); + + if ( xObjectInputStream.is() ) + { + css::uno::Reference<css::xml::crypto::XUriBinding> xUriBinding + (isi.xReferenceResolvedListener, css::uno::UNO_QUERY); + xUriBinding->setUriBinding(ouUri, xObjectInputStream); + } + } + + isi.addReference(type, nDigestID, ouUri, -1, OUString()); +} + +void XSecController::setReferenceCount() const +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setReferenceCount: no signature"); + return; + } + const InternalSignatureInformation &isi = + m_vInternalSignatureInformations.back(); + + if ( isi.xReferenceResolvedListener.is() ) + { + const SignatureReferenceInformations &refInfors = isi.signatureInfor.vSignatureReferenceInfors; + + int refNum = refInfors.size(); + sal_Int32 referenceCount = 0; + + for(int i=0 ; i<refNum; ++i) + { + if (refInfors[i].nType == SignatureReferenceType::SAMEDOCUMENT ) + /* + * same-document reference + */ + { + referenceCount++; + } + } + + css::uno::Reference<css::xml::crypto::sax::XReferenceCollector> xReferenceCollector + (isi.xReferenceResolvedListener, css::uno::UNO_QUERY); + xReferenceCollector->setReferenceCount( referenceCount ); + } +} + +void XSecController::setX509IssuerName( OUString const & ouX509IssuerName ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setX509IssuerName: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouX509IssuerName = ouX509IssuerName; +} + +void XSecController::setX509SerialNumber( OUString const & ouX509SerialNumber ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setX509SerialNumber: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouX509SerialNumber = ouX509SerialNumber; +} + +void XSecController::setX509Certificate( OUString const & ouX509Certificate ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setX509Certificate: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouX509Certificate = ouX509Certificate; +} + +void XSecController::setSignatureValue( OUString const & ouSignatureValue ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setSignatureValue: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouSignatureValue = ouSignatureValue; +} + +void XSecController::setDigestValue( sal_Int32 nDigestID, OUString const & ouDigestValue ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setDigestValue: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + if (isi.signatureInfor.vSignatureReferenceInfors.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setDigestValue: no signature reference"); + return; + } + SignatureReferenceInformation &reference = + isi.signatureInfor.vSignatureReferenceInfors.back(); + reference.nDigestID = nDigestID; + reference.ouDigestValue = ouDigestValue; +} + +void XSecController::setGpgKeyID( OUString const & ouKeyID ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setGpgKeyID: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouGpgKeyID = ouKeyID; +} + +void XSecController::setGpgCertificate( OUString const & ouGpgCert ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setGpgCertificate: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouGpgCertificate = ouGpgCert; +} + +void XSecController::setGpgOwner( OUString const & ouGpgOwner ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setGpgOwner: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouGpgOwner = ouGpgOwner; +} + +void XSecController::setDate( OUString const & ouDate ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setDate: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + (void)utl::ISO8601parseDateTime( ouDate, isi.signatureInfor.stDateTime); + isi.signatureInfor.ouDateTime = ouDate; +} + +void XSecController::setDescription(const OUString& rDescription) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.ouDescription = rDescription; +} + +void XSecController::setSignatureBytes(const uno::Sequence<sal_Int8>& rBytes) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.aSignatureBytes = rBytes; +} + +void XSecController::setCertDigest(const OUString& rCertDigest) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.ouCertDigest = rCertDigest; +} + +namespace { +Reference<css::graphic::XGraphic> lcl_getGraphicFromString(const OUString& rImage) +{ + Sequence<sal_Int8> seq; + comphelper::Base64::decode(seq, rImage); + + Reference< graphic::XGraphic > xGraphic; + if( !seq.hasElements() ) + return Reference<css::graphic::XGraphic>(); + + Reference< graphic::XGraphicProvider > xGraphicProvider( + graphic::GraphicProvider::create(comphelper::getProcessComponentContext()) ); + Reference< io::XInputStream > xInputStream( new ::comphelper::SequenceInputStream( seq ) ); + + Sequence< PropertyValue > aArgs( 1 ); + aArgs[ 0 ].Name = "InputStream"; + aArgs[ 0 ].Value <<= xInputStream; + xGraphic = xGraphicProvider->queryGraphic(aArgs); + + return xGraphic; +} +} + +void XSecController::setValidSignatureImage(const OUString& rValidSigImg) +{ + if (m_vInternalSignatureInformations.empty() || rValidSigImg.isEmpty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.aValidSignatureImage = lcl_getGraphicFromString(rValidSigImg); +} + +void XSecController::setInvalidSignatureImage(const OUString& rInvalidSigImg) +{ + if (m_vInternalSignatureInformations.empty() || rInvalidSigImg.isEmpty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.aInvalidSignatureImage = lcl_getGraphicFromString(rInvalidSigImg); +} + +void XSecController::setSignatureLineId(const OUString& rSignatureLineId) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.ouSignatureLineId = rSignatureLineId; +} + +void XSecController::addEncapsulatedX509Certificate(const OUString& rEncapsulatedX509Certificate) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + if (rEncapsulatedX509Certificate.isEmpty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.maEncapsulatedX509Certificates.insert(rEncapsulatedX509Certificate); +} + +void XSecController::setId( OUString const & ouId ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setId: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouSignatureId = ouId; +} + +void XSecController::setPropertyId( OUString const & ouPropertyId ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setPropertyId: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + + if (isi.signatureInfor.ouPropertyId.isEmpty()) + { + // <SignatureProperty> ID attribute is for the date. + isi.signatureInfor.ouPropertyId = ouPropertyId; + } + else + { + // <SignatureProperty> ID attribute is for the description. + isi.signatureInfor.ouDescriptionPropertyId = ouPropertyId; + } +} + +/* public: for signature verify */ +void XSecController::collectToVerify( const OUString& referenceId ) +{ + /* SAL_WARN_IF( !m_xSAXEventKeeper.is(), "xmlsecurity", "the SAXEventKeeper is NULL" ); */ + + if ( m_eStatusOfSecurityComponents == InitializationState::INITIALIZED ) + /* + * if all security components are ready, verify the signature. + */ + { + bool bJustChainingOn = false; + css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler; + + int i,j; + int sigNum = m_vInternalSignatureInformations.size(); + + for (i=0; i<sigNum; ++i) + { + InternalSignatureInformation& isi = m_vInternalSignatureInformations[i]; + SignatureReferenceInformations& vReferenceInfors = isi.signatureInfor.vSignatureReferenceInfors; + int refNum = vReferenceInfors.size(); + + for (j=0; j<refNum; ++j) + { + SignatureReferenceInformation &refInfor = vReferenceInfors[j]; + + if (refInfor.ouURI == referenceId) + { + if (chainOn()) + { + bJustChainingOn = true; + xHandler = m_xSAXEventKeeper->setNextHandler(nullptr); + } + + sal_Int32 nKeeperId = m_xSAXEventKeeper->addSecurityElementCollector( + css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY, false ); + + css::uno::Reference<css::xml::crypto::sax::XReferenceCollector> xReferenceCollector + ( isi.xReferenceResolvedListener, css::uno::UNO_QUERY ); + + m_xSAXEventKeeper->setSecurityId(nKeeperId, isi.signatureInfor.nSecurityId); + m_xSAXEventKeeper->addReferenceResolvedListener( nKeeperId, isi.xReferenceResolvedListener); + xReferenceCollector->setReferenceId( nKeeperId ); + + isi.vKeeperIds[j] = nKeeperId; + break; + } + } + } + + if ( bJustChainingOn ) + { + m_xSAXEventKeeper->setNextHandler(xHandler); + } + } +} + +void XSecController::addSignature( sal_Int32 nSignatureId ) +{ + SAL_WARN_IF( !m_xSecParser.is(), "xmlsecurity.helper", "No XSecParser initialized" ); + + m_nReservedSignatureId = nSignatureId; + m_bVerifyCurrentSignature = true; +} + +css::uno::Reference< css::xml::sax::XDocumentHandler > const & XSecController::createSignatureReader(XMLSignatureHelper& rXMLSignatureHelper, sal_Int32 nType) +{ + if (nType == embed::StorageFormats::OFOPXML) + m_xSecParser = new OOXMLSecParser(rXMLSignatureHelper, this); + else + m_xSecParser = new XSecParser(rXMLSignatureHelper, this); + css::uno::Reference< css::lang::XInitialization > xInitialization(m_xSecParser, uno::UNO_QUERY); + + setSAXChainConnector(xInitialization); + + return m_xSecParser; +} + +void XSecController::releaseSignatureReader() +{ + clearSAXChainConnector( ); + m_xSecParser.clear(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |