/* -*- 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 #include #include "xsecparser.hxx" #include "ooxmlsecparser.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 xInitialization(xReferenceResolvedListener, css::uno::UNO_QUERY); css::uno::Sequence args(5); args[0] <<= OUString::number(nSecurityId); args[1] <<= uno::Reference(static_cast(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 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( m_vInternalSignatureInformations.back().xReferenceResolvedListener.get()); if (pImpl) { css::uno::Reference 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 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 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& 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 lcl_getGraphicFromString(const OUString& rImage) { Sequence seq; comphelper::Base64::decode(seq, rImage); Reference< graphic::XGraphic > xGraphic; if( !seq.hasElements() ) return Reference(); 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()) { // ID attribute is for the date. isi.signatureInfor.ouPropertyId = ouPropertyId; } else { // 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; isetNextHandler(nullptr); } sal_Int32 nKeeperId = m_xSAXEventKeeper->addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY, false ); css::uno::Reference 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: */