/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* 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 <utility>
#include <xsecctl.hxx>
#include <documentsignaturehelper.hxx>
#include <framework/saxeventkeeperimpl.hxx>
#include <xmlsec/xmldocumentwrapper_xmlsecimpl.hxx>
#if HAVE_FEATURE_GPGME
# include <gpg/xmlsignature_gpgimpl.hxx>
#endif
#include <com/sun/star/xml/crypto/sax/XMissionTaker.hpp>
#include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/xml/sax/XParser.hpp>
#include <com/sun/star/xml/crypto/XXMLSignature.hpp>
#include <comphelper/attributelist.hxx>
#include <rtl/ustrbuf.hxx>
#include <rtl/ref.hxx>
#include <sal/log.hxx>
#include <unotools/datetime.hxx>
#include "ooxmlsecexporter.hxx"
#include <UriBindingHelper.hxx>
using namespace com::sun::star;
namespace
{
const OUString & getDigestURI(sal_Int32 nID)
{
switch ( nID )
{
case css::xml::crypto::DigestID::SHA1:
return ALGO_XMLDSIGSHA1;
case css::xml::crypto::DigestID::SHA256:
return ALGO_XMLDSIGSHA256;
case css::xml::crypto::DigestID::SHA512:
return ALGO_XMLDSIGSHA512;
default :
return ALGO_XMLDSIGSHA1;
}
}
OUString getSignatureURI(svl::crypto::SignatureMethodAlgorithm eAlgorithm, sal_Int32 nDigestID)
{
OUString aRet;
if (eAlgorithm == svl::crypto::SignatureMethodAlgorithm::ECDSA)
{
switch (nDigestID)
{
case css::xml::crypto::DigestID::SHA1:
aRet = ALGO_ECDSASHA1;
break ;
case css::xml::crypto::DigestID::SHA256:
aRet = ALGO_ECDSASHA256;
break ;
case css::xml::crypto::DigestID::SHA512:
aRet = ALGO_ECDSASHA512;
break ;
default :
aRet = ALGO_ECDSASHA1;
break ;
}
}
if (!aRet.isEmpty())
return aRet;
switch (nDigestID)
{
case css::xml::crypto::DigestID::SHA1:
return ALGO_RSASHA1;
case css::xml::crypto::DigestID::SHA256:
return ALGO_RSASHA256;
case css::xml::crypto::DigestID::SHA512:
return ALGO_RSASHA512;
default :
return ALGO_RSASHA1;
}
}
}
XSecController::XSecController( css::uno::Reference<css::uno::XComponentContext> xCtx )
: mxCtx(std::move(xCtx))
, m_nNextSecurityId(1 )
, m_bIsPreviousNodeInitializable(false )
, m_bIsSAXEventKeeperConnected(false )
, m_bIsCollectingElement(false )
, m_bIsBlocking(false )
, m_eStatusOfSecurityComponents(InitializationState::UNINITIALIZED)
, m_bIsSAXEventKeeperSticky(false )
, m_nReservedSignatureId(0 )
, m_bVerifyCurrentSignature(false )
{
}
XSecController::~XSecController()
{
}
/*
* private methods
*/
int XSecController::findSignatureInfor( sal_Int32 nSecurityId) const
/****** XSecController/findSignatureInfor *************************************
*
* NAME
* findSignatureInfor - - find SignatureInformation struct for a particular
* signature
*
* SYNOPSIS
* index = findSignatureInfor ( nSecurityId ) ;
*
* INPUTS
* nSecurityId - the signature ' s id
*
* RESULT
* index - the index of the signature , or - 1 when no such signature
* existing
******************************************************************************/
{
int i;
int size = m_vInternalSignatureInformations.size();
for (i=0 ; i<size; ++i)
{
if (m_vInternalSignatureInformations[i].signatureInfor.nSecurityId == nSecurityId)
{
return i;
}
}
return -1 ;
}
void XSecController::createXSecComponent( )
/****** XSecController/createXSecComponent ************************************
*
* NAME
* bResult = createXSecComponent - - creates xml security components
*
* FUNCTION
* Creates xml security components , including :
* 1 . an xml signature bridge component
* 2 . an XMLDocumentWrapper component
* 3 . a SAXEventKeeper component
******************************************************************************/
{
/*
* marks all security components are not available .
*/
m_eStatusOfSecurityComponents = InitializationState::FAILTOINITIALIZED;
m_xXMLSignature = nullptr;
m_xXMLDocumentWrapper = nullptr;
m_xSAXEventKeeper = nullptr;
css::uno::Reference< css::lang::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() );
#if HAVE_FEATURE_GPGME
uno::Reference< lang::XServiceInfo > xServiceInfo( m_xSecurityContext, css::uno::UNO_QUERY );
if (xServiceInfo->getImplementationName() == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl" )
m_xXMLSignature.set(new XMLSignature_GpgImpl());
else // xmlsec or mscrypt
#endif
m_xXMLSignature.set(xMCF->createInstanceWithContext(u"com.sun.star.xml.crypto.XMLSignature" _ustr, mxCtx), css::uno::UNO_QUERY);
bool bSuccess = m_xXMLSignature.is();
if ( bSuccess )
/*
* XMLSignature created successfully .
*/
m_xXMLDocumentWrapper = new XMLDocumentWrapper_XmlSecImpl();
bSuccess &= m_xXMLDocumentWrapper.is();
if ( bSuccess )
m_xSAXEventKeeper = new SAXEventKeeperImpl();
bSuccess &= m_xSAXEventKeeper.is();
if (!bSuccess)
/*
* SAXEventKeeper created successfully .
*/
return ;
css::uno::Sequence <css::uno::Any> arg{ css::uno::Any(
uno::Reference<xml::wrapper::XXMLDocumentWrapper>(m_xXMLDocumentWrapper)) };
m_xSAXEventKeeper->initialize(arg);
css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >
xStatusChangeListener = this ;
m_xSAXEventKeeper->addSAXEventKeeperStatusChangeListener( xStatusChangeListener );
m_eStatusOfSecurityComponents = InitializationState::INITIALIZED;
}
bool XSecController::chainOn()
/****** XSecController/chainOn ************************************************
*
* NAME
* chainOn - - tries to connect the SAXEventKeeper with the SAX chain .
*
* SYNOPSIS
* bJustChainingOn = chainOn ( ) ;
*
* FUNCTION
* First , checks whether the SAXEventKeeper is on the SAX chain . If not ,
* creates xml security components , and chains the SAXEventKeeper into
* the SAX chain .
* Before being chained in , the SAXEventKeeper needs to receive all
* missed key SAX events , which can promise the DOM tree buffered by the
* SAXEventKeeper has the same structure with the original document .
*
* RESULT
* bJustChainingOn - whether the SAXEventKeeper is just chained into the
* SAX chain .
*
* NOTES
* Sometimes , the last key SAX event can ' t be transferred to the
* SAXEventKeeper together .
* For instance , at the time a referenced element is detected , the
* startElement event has already been reserved by the ElementStackKeeper .
* Meanwhile , an ElementCollector needs to be created before the
* SAXEventKeeper receives that startElement event .
* So for the SAXEventKeeper , it needs to receive all missed key SAX
* events except that startElement event , then adds a new
* ElementCollector , then receives that startElement event .
******************************************************************************/
{
bool rc = false ;
if (!m_bIsSAXEventKeeperSticky && !m_bIsSAXEventKeeperConnected)
{
if ( m_eStatusOfSecurityComponents == InitializationState::UNINITIALIZED )
{
createXSecComponent();
}
if ( m_eStatusOfSecurityComponents == InitializationState::INITIALIZED )
/*
* if all security components are ready , chains on the SAXEventKeeper
*/
{
/*
* disconnect the SAXEventKeeper with its current output handler ,
* to make sure no SAX event is forwarded during the connecting
* phase .
*/
m_xSAXEventKeeper->setNextHandler( nullptr );
css::uno::Reference< css::xml::sax::XDocumentHandler > xSEKHandler(m_xSAXEventKeeper);
/*
* connects the previous document handler on the SAX chain
*/
if ( m_xPreviousNodeOnSAXChain.is() )
{
if ( m_bIsPreviousNodeInitializable )
{
css::uno::Reference< css::lang::XInitialization > xInitialization
(m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY);
xInitialization->initialize({ css::uno::Any(xSEKHandler) });
}
else
{
css::uno::Reference< css::xml::sax::XParser > xParser
(m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY);
xParser->setDocumentHandler( xSEKHandler );
}
}
/*
* connects the next document handler on the SAX chain
*/
m_xSAXEventKeeper->setNextHandler(uno::Reference<xml::sax::XDocumentHandler>());
m_bIsSAXEventKeeperConnected = true ;
rc = true ;
}
}
return rc;
}
void XSecController::chainOff()
/****** XSecController/chainOff ***********************************************
*
* NAME
* chainOff - - disconnects the SAXEventKeeper from the SAX chain .
******************************************************************************/
{
if (m_bIsSAXEventKeeperSticky )
return ;
if (!m_bIsSAXEventKeeperConnected)
return ;
m_xSAXEventKeeper->setNextHandler( nullptr );
if ( m_xPreviousNodeOnSAXChain.is() )
{
if ( m_bIsPreviousNodeInitializable )
{
css::uno::Reference< css::lang::XInitialization > xInitialization
(m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY);
css::uno::Sequence<css::uno::Any> aArgs{ css::uno::Any(
uno::Reference<xml::sax::XDocumentHandler>()) };
xInitialization->initialize(aArgs);
}
else
{
css::uno::Reference< css::xml::sax::XParser > xParser(m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY);
xParser->setDocumentHandler(uno::Reference<xml::sax::XDocumentHandler>());
}
}
m_bIsSAXEventKeeperConnected = false ;
}
void XSecController::checkChainingStatus()
/****** XSecController/checkChainingStatus ************************************
*
* NAME
* checkChainingStatus - - connects or disconnects the SAXEventKeeper
* according to the current situation .
*
* SYNOPSIS
* checkChainingStatus ( ) ;
*
* FUNCTION
* The SAXEventKeeper is chained into the SAX chain , when :
* 1 . some element is being collected , or
* 2 . the SAX event stream is blocking .
* Otherwise , chain off the SAXEventKeeper .
******************************************************************************/
{
if ( m_bIsCollectingElement || m_bIsBlocking )
{
chainOn();
}
else
{
chainOff();
}
}
void XSecController::initializeSAXChain()
/****** XSecController/initializeSAXChain *************************************
*
* NAME
* initializeSAXChain - - initializes the SAX chain according to the
* current setting .
*
* FUNCTION
* Initializes the SAX chain , if the SAXEventKeeper is asked to be always
* on the SAX chain , chains it on . Otherwise , starts the
* ElementStackKeeper to reserve key SAX events .
******************************************************************************/
{
m_bIsSAXEventKeeperConnected = false ;
m_bIsCollectingElement = false ;
m_bIsBlocking = false ;
chainOff();
}
css::uno::Reference< css::io::XInputStream >
XSecController::getObjectInputStream( const OUString& objectURL )
/****** XSecController/getObjectInputStream ************************************
*
* NAME
* getObjectInputStream - - get a XInputStream interface from a SotStorage
*
* SYNOPSIS
* xInputStream = getObjectInputStream ( objectURL ) ;
*
* INPUTS
* objectURL - the object uri
*
* RESULT
* xInputStream - the XInputStream interface
******************************************************************************/
{
css::uno::Reference< css::io::XInputStream > xObjectInputStream;
SAL_WARN_IF( !m_xUriBinding.is(), "xmlsecurity.helper" , "Need XUriBinding!" );
xObjectInputStream = m_xUriBinding->getUriBinding(objectURL);
return xObjectInputStream;
}
/*
* public methods
*/
sal_Int32 XSecController::getNewSecurityId( )
{
sal_Int32 nId = m_nNextSecurityId;
m_nNextSecurityId++;
return nId;
}
void XSecController::startMission(const rtl::Reference<UriBindingHelper>& xUriBinding, const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& xSecurityContext )
/****** XSecController/startMission *******************************************
*
* NAME
* startMission - - starts a new security mission .
*
* FUNCTION
* get ready for a new mission .
*
* INPUTS
* xUriBinding - the Uri binding that provide maps between uris and
* XInputStreams
* xSecurityContext - the security context component which can provide
* cryptoken
******************************************************************************/
{
m_xUriBinding = xUriBinding;
m_eStatusOfSecurityComponents = InitializationState::UNINITIALIZED;
m_xSecurityContext = xSecurityContext;
m_vInternalSignatureInformations.clear();
m_bVerifyCurrentSignature = false ;
}
void XSecController::setSAXChainConnector(const css::uno::Reference< css::lang::XInitialization >& xInitialization)
/****** XSecController/setSAXChainConnector ***********************************
*
* NAME
* setSAXChainConnector - - configures the components which will
* collaborate with the SAXEventKeeper on the SAX chain .
*
* SYNOPSIS
* setSAXChainConnector ( xInitialization ) ;
*
* INPUTS
* xInitialization - the previous node on the SAX chain
******************************************************************************/
{
m_bIsPreviousNodeInitializable = true ;
m_xPreviousNodeOnSAXChain = xInitialization;
initializeSAXChain( );
}
void XSecController::clearSAXChainConnector()
/****** XSecController/clearSAXChainConnector *********************************
*
* NAME
* clearSAXChainConnector - - resets the collaborating components .
******************************************************************************/
{
chainOff();
m_xPreviousNodeOnSAXChain = nullptr;
}
void XSecController::endMission()
/****** XSecController/endMission *********************************************
*
* NAME
* endMission - - forces to end all missions
*
* FUNCTION
* Deletes all signature information and forces all missions to an end .
******************************************************************************/
{
sal_Int32 size = m_vInternalSignatureInformations.size();
for (int i=0 ; i<size; ++i)
{
if ( m_eStatusOfSecurityComponents == InitializationState::INITIALIZED )
/*
* ResolvedListener only exist when the security components are created .
*/
{
css::uno::Reference< css::xml::crypto::sax::XMissionTaker > xMissionTaker
( m_vInternalSignatureInformations[i].xReferenceResolvedListener, css::uno::UNO_QUERY );
/*
* asks the SignatureCreator / SignatureVerifier to release
* all resources it uses .
*/
xMissionTaker->endMission();
}
}
m_xUriBinding = nullptr;
m_xSecurityContext = nullptr;
/*
* free the status change listener reference to this object
*/
if (m_xSAXEventKeeper.is())
m_xSAXEventKeeper->addSAXEventKeeperStatusChangeListener( nullptr );
}
namespace
{
void writeUnsignedProperties(
const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler,
const SignatureInformation& signatureInfo)
{
{
rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList());
pAttributeList->AddAttribute(u"Id" _ustr, "idUnsignedProperties_" + signatureInfo.ouSignatureId);
xDocumentHandler->startElement(u"xd:UnsignedProperties" _ustr, uno::Reference<xml::sax::XAttributeList>(pAttributeList));
}
{
xDocumentHandler->startElement(u"xd:UnsignedSignatureProperties" _ustr, uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList()));
{
xDocumentHandler->startElement(u"xd:CertificateValues" _ustr, uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList()));
{
for (const auto & i: signatureInfo.maEncapsulatedX509Certificates)
{
xDocumentHandler->startElement(u"xd:EncapsulatedX509Certificate" _ustr, uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList()));
xDocumentHandler->characters(i);
xDocumentHandler->endElement(u"xd:EncapsulatedX509Certificate" _ustr);
}
}
xDocumentHandler->endElement(u"xd:CertificateValues" _ustr);
}
xDocumentHandler->endElement(u"xd:UnsignedSignatureProperties" _ustr);
}
xDocumentHandler->endElement(u"xd:UnsignedProperties" _ustr);
}
}
void XSecController::exportSignature(
const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler,
const SignatureInformation& signatureInfo,
bool bXAdESCompliantIfODF )
/****** XSecController/exportSignature ****************************************
*
* NAME
* exportSignature - - export a signature structure to an XDocumentHandler
*
* SYNOPSIS
* exportSignature ( xDocumentHandler , signatureInfo ) ;
*
* INPUTS
* xDocumentHandler - the document handler to receive the signature
* signatureInfo - signature to be exported
******************************************************************************/
{
const SignatureReferenceInformations& vReferenceInfors = signatureInfo.vSignatureReferenceInfors;
rtl::Reference<comphelper::AttributeList> pAttributeList;
/*
* Write Signature element
*/
pAttributeList = new comphelper::AttributeList();
pAttributeList->AddAttribute(
u"xmlns" _ustr,
NS_XMLDSIG);
if (!signatureInfo.ouSignatureId.isEmpty())
{
pAttributeList->AddAttribute(
u"Id" _ustr,
signatureInfo.ouSignatureId);
}
xDocumentHandler->startElement( u"Signature" _ustr, pAttributeList);
{
/* Write SignedInfo element */
xDocumentHandler->startElement(
u"SignedInfo" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
{
/* Write CanonicalizationMethod element */
pAttributeList = new comphelper::AttributeList();
pAttributeList->AddAttribute(
u"Algorithm" _ustr,
ALGO_C14N);
xDocumentHandler->startElement( u"CanonicalizationMethod" _ustr, pAttributeList );
xDocumentHandler->endElement( u"CanonicalizationMethod" _ustr );
/* Write SignatureMethod element */
pAttributeList = new comphelper::AttributeList();
// TODO: actually roundtrip this value from parsing documentsignatures.xml - entirely
// broken to assume this would in any way relate to the 1st reference's digest algo
// Assume that all Reference elements use the same DigestMethod:Algorithm, and that the
// SignatureMethod:Algorithm should be the corresponding one.
pAttributeList->AddAttribute(
u"Algorithm" _ustr,
getSignatureURI(signatureInfo.eAlgorithmID, vReferenceInfors[0 ].nDigestID));
xDocumentHandler->startElement( u"SignatureMethod" _ustr, pAttributeList );
xDocumentHandler->endElement( u"SignatureMethod" _ustr );
/* Write Reference element */
int j;
int refNum = vReferenceInfors.size();
for (j=0 ; j<refNum; ++j)
{
const SignatureReferenceInformation& refInfor = vReferenceInfors[j];
pAttributeList = new comphelper::AttributeList();
if ( refInfor.nType != SignatureReferenceType::SAMEDOCUMENT )
/*
* stream reference
*/
{
pAttributeList->AddAttribute(
u"URI" _ustr,
refInfor.ouURI);
}
else
/*
* same - document reference
*/
{
if (refInfor.ouURI.startsWith("idSignedProperties" ))
{
pAttributeList->AddAttribute(u"URI" _ustr, "#idSignedProperties_" + signatureInfo.ouSignatureId);
if (bXAdESCompliantIfODF && !refInfor.ouType.isEmpty())
{
// The reference which points to the SignedProperties
// shall have this specific type.
pAttributeList->AddAttribute(u"Type" _ustr, refInfor.ouType);
}
}
else
{
pAttributeList->AddAttribute(
u"URI" _ustr,
"#" + refInfor.ouURI);
}
}
xDocumentHandler->startElement( u"Reference" _ustr, pAttributeList );
{
/* Write Transforms element */
if (refInfor.nType == SignatureReferenceType::XMLSTREAM)
/*
* xml stream , so c14n transform is needed
*/
{
xDocumentHandler->startElement(
u"Transforms" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
{
pAttributeList = new comphelper::AttributeList();
pAttributeList->AddAttribute(
u"Algorithm" _ustr,
ALGO_C14N);
xDocumentHandler->startElement(
u"Transform" _ustr,
pAttributeList );
xDocumentHandler->endElement( u"Transform" _ustr );
}
xDocumentHandler->endElement( u"Transforms" _ustr );
}
/* Write DigestMethod element */
pAttributeList = new comphelper::AttributeList();
pAttributeList->AddAttribute(
u"Algorithm" _ustr,
getDigestURI(refInfor.nDigestID));
xDocumentHandler->startElement(
u"DigestMethod" _ustr,
pAttributeList );
xDocumentHandler->endElement( u"DigestMethod" _ustr );
/* Write DigestValue element */
xDocumentHandler->startElement(
u"DigestValue" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
xDocumentHandler->characters( refInfor.ouDigestValue );
xDocumentHandler->endElement( u"DigestValue" _ustr );
}
xDocumentHandler->endElement( u"Reference" _ustr );
}
}
xDocumentHandler->endElement( u"SignedInfo" _ustr );
/* Write SignatureValue element */
xDocumentHandler->startElement(
u"SignatureValue" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
xDocumentHandler->characters( signatureInfo.ouSignatureValue );
xDocumentHandler->endElement( u"SignatureValue" _ustr );
/* Write KeyInfo element */
xDocumentHandler->startElement(
u"KeyInfo" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
{
// GPG or X509 key?
if (!signatureInfo.ouGpgCertificate.isEmpty())
{
pAttributeList = new comphelper::AttributeList();
pAttributeList->AddAttribute(u"xmlns:loext" _ustr, NS_LOEXT);
/* Write PGPData element */
xDocumentHandler->startElement(
u"PGPData" _ustr,
pAttributeList);
{
/* Write keyid element */
xDocumentHandler->startElement(
u"PGPKeyID" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
xDocumentHandler->characters(signatureInfo.ouGpgKeyID);
xDocumentHandler->endElement( u"PGPKeyID" _ustr );
/* Write PGPKeyPacket element */
if (!signatureInfo.ouGpgCertificate.isEmpty())
{
xDocumentHandler->startElement(
u"PGPKeyPacket" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
xDocumentHandler->characters( signatureInfo.ouGpgCertificate );
xDocumentHandler->endElement( u"PGPKeyPacket" _ustr );
}
/* Write PGPOwner element */
xDocumentHandler->startElement(
u"loext:PGPOwner" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList >(new comphelper::AttributeList()));
xDocumentHandler->characters( signatureInfo.ouGpgOwner );
xDocumentHandler->endElement( u"loext:PGPOwner" _ustr );
}
xDocumentHandler->endElement( u"PGPData" _ustr );
}
else
{
assert(signatureInfo.GetSigningCertificate());
for (auto const & rData : signatureInfo.X509Datas)
{
/* Write X509Data element */
xDocumentHandler->startElement(
u"X509Data" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
{
for (auto const & it : rData)
{
/* Write X509IssuerSerial element */
xDocumentHandler->startElement(
u"X509IssuerSerial" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
{
/* Write X509IssuerName element */
xDocumentHandler->startElement(
u"X509IssuerName" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
xDocumentHandler->characters(it.X509IssuerName);
xDocumentHandler->endElement( u"X509IssuerName" _ustr );
/* Write X509SerialNumber element */
xDocumentHandler->startElement(
u"X509SerialNumber" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
xDocumentHandler->characters(it.X509SerialNumber);
xDocumentHandler->endElement( u"X509SerialNumber" _ustr );
}
xDocumentHandler->endElement( u"X509IssuerSerial" _ustr );
/* Write X509Certificate element */
if (!it.X509Certificate.isEmpty())
{
xDocumentHandler->startElement(
u"X509Certificate" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
xDocumentHandler->characters(it.X509Certificate);
xDocumentHandler->endElement( u"X509Certificate" _ustr );
}
}
}
xDocumentHandler->endElement( u"X509Data" _ustr );
}
}
}
xDocumentHandler->endElement( u"KeyInfo" _ustr );
OUString sDate;
/* Write Object element */
xDocumentHandler->startElement(
u"Object" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
{
/* Write SignatureProperties element */
xDocumentHandler->startElement(
u"SignatureProperties" _ustr,
css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList()));
{
/* Write SignatureProperty element */
pAttributeList = new comphelper::AttributeList();
pAttributeList->AddAttribute(
u"Id" _ustr,
signatureInfo.ouDateTimePropertyId);
pAttributeList->AddAttribute(
u"Target" _ustr,
"#" + signatureInfo.ouSignatureId);
xDocumentHandler->startElement(
u"SignatureProperty" _ustr,
pAttributeList);
{
/* Write timestamp element */
pAttributeList = new comphelper::AttributeList();
pAttributeList->AddAttribute(
u"xmlns:dc" _ustr,
NS_DC);
xDocumentHandler->startElement(
u"dc:date" _ustr,
pAttributeList);
OUStringBuffer buffer;
//If the xml signature was already contained in the document,
//then we use the original date and time string, rather than the
//converted one. This avoids writing a different string due to
//e.g. rounding issues and thus breaking the signature.
if (!signatureInfo.ouDateTime.isEmpty())
buffer = signatureInfo.ouDateTime;
else
{
buffer = utl::toISO8601(signatureInfo.stDateTime);
// xsd:dateTime must use period as separator for fractional seconds, while
// utl::toISO8601 uses comma (as allowed, and even recommended, by ISO8601).
buffer.replace(',' , '.' );
}
sDate = buffer.makeStringAndClear();
xDocumentHandler->characters( sDate );
xDocumentHandler->endElement(
u"dc:date" _ustr);
}
xDocumentHandler->endElement( u"SignatureProperty" _ustr );
}
// Write signature description.
if (!signatureInfo.ouDescription.isEmpty())
{
// SignatureProperty element.
pAttributeList = new comphelper::AttributeList();
pAttributeList->AddAttribute(u"Id" _ustr, signatureInfo.ouDescriptionPropertyId);
pAttributeList->AddAttribute(u"Target" _ustr, "#" + signatureInfo.ouSignatureId);
xDocumentHandler->startElement(u"SignatureProperty" _ustr, pAttributeList);
{
// Description element.
pAttributeList = new comphelper::AttributeList();
pAttributeList->AddAttribute(u"xmlns:dc" _ustr, NS_DC);
xDocumentHandler->startElement(u"dc:description" _ustr, pAttributeList);
xDocumentHandler->characters(signatureInfo.ouDescription);
xDocumentHandler->endElement(u"dc:description" _ustr);
}
xDocumentHandler->endElement(u"SignatureProperty" _ustr);
}
xDocumentHandler->endElement( u"SignatureProperties" _ustr );
}
xDocumentHandler->endElement( u"Object" _ustr );
// In XAdES, write another Object element for the QualifyingProperties
if (bXAdESCompliantIfODF)
{
pAttributeList = new comphelper::AttributeList();
pAttributeList->AddAttribute(u"xmlns:xd" _ustr, NS_XD);
xDocumentHandler->startElement(
u"Object" _ustr,
pAttributeList);
{
pAttributeList = new comphelper::AttributeList();
pAttributeList->AddAttribute(u"Target" _ustr, "#" + signatureInfo.ouSignatureId);
xDocumentHandler->startElement(
u"xd:QualifyingProperties" _ustr,
pAttributeList);
DocumentSignatureHelper::writeSignedProperties(xDocumentHandler, signatureInfo, sDate, true );
writeUnsignedProperties(xDocumentHandler, signatureInfo);
xDocumentHandler->endElement( u"xd:QualifyingProperties" _ustr );
}
xDocumentHandler->endElement( u"Object" _ustr );
}
}
xDocumentHandler->endElement( u"Signature" _ustr );
}
void XSecController::exportOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler, const SignatureInformation& rInformation)
{
OOXMLSecExporter aExporter(mxCtx, xRootStorage, xDocumentHandler, rInformation);
aExporter.writeSignature();
}
void XSecController::UpdateSignatureInformation(sal_Int32 const nSecurityId,
std::vector<SignatureInformation::X509Data> && rDatas)
{
int const nIndex = findSignatureInfor(nSecurityId);
assert(nIndex != -1 ); // nothing should touch this between parsing and verify
m_vInternalSignatureInformations[nIndex].signatureInfor.X509Datas = std::move(rDatas);
}
SignatureInformation XSecController::getSignatureInformation( sal_Int32 nSecurityId ) const
{
SignatureInformation aInf( 0 );
int nIndex = findSignatureInfor(nSecurityId);
SAL_WARN_IF( nIndex == -1 , "xmlsecurity.helper" , "getSignatureInformation - SecurityId is invalid!" );
if ( nIndex != -1 )
{
aInf = m_vInternalSignatureInformations[nIndex].signatureInfor;
}
return aInf;
}
SignatureInformations XSecController::getSignatureInformations() const
{
SignatureInformations vInfors;
int sigNum = m_vInternalSignatureInformations.size();
for (int i=0 ; i<sigNum; ++i)
{
SignatureInformation si = m_vInternalSignatureInformations[i].signatureInfor;
vInfors.push_back(si);
}
return vInfors;
}
/*
* XSAXEventKeeperStatusChangeListener
*/
void SAL_CALL XSecController::blockingStatusChanged( sal_Bool isBlocking )
{
m_bIsBlocking = isBlocking;
checkChainingStatus();
}
void SAL_CALL XSecController::collectionStatusChanged(
sal_Bool isInsideCollectedElement )
{
m_bIsCollectingElement = isInsideCollectedElement;
checkChainingStatus();
}
void SAL_CALL XSecController::bufferStatusChanged( sal_Bool /*isBufferEmpty*/)
{
}
/*
* XSignatureCreationResultListener
*/
void SAL_CALL XSecController::signatureCreated( sal_Int32 securityId, css::xml::crypto::SecurityOperationStatus nResult )
{
int index = findSignatureInfor(securityId);
assert(index != -1 && "Signature Not Found!" );
SignatureInformation& signatureInfor = m_vInternalSignatureInformations.at(index).signatureInfor;
signatureInfor.nStatus = nResult;
}
/*
* XSignatureVerifyResultListener
*/
void SAL_CALL XSecController::signatureVerified( sal_Int32 securityId, css::xml::crypto::SecurityOperationStatus nResult )
{
int index = findSignatureInfor(securityId);
assert(index != -1 && "Signature Not Found!" );
SignatureInformation& signatureInfor = m_vInternalSignatureInformations.at(index).signatureInfor;
signatureInfor.nStatus = nResult;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 in Prozent C=89 H=93 G=90
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet am 2026-09-28)
¤
*© Formatika GbR, Deutschland