1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_gpgme.h>
22 #include <xsecctl.hxx>
23 #include "xsecparser.hxx"
24 #include "ooxmlsecparser.hxx"
25 #include <framework/signatureverifierimpl.hxx>
26 #include <framework/saxeventkeeperimpl.hxx>
27 #include <gpg/xmlsignature_gpgimpl.hxx>
28 #include <gpg/SEInitializer.hxx>
30 #include <com/sun/star/uno/Sequence.hxx>
31 #include <com/sun/star/xml/crypto/sax/XKeyCollector.hpp>
32 #include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
33 #include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp>
34 #include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp>
35 #include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp>
36 #include <com/sun/star/xml/crypto/XSEInitializer.hpp>
37 #include <com/sun/star/graphic/XGraphic.hpp>
38 #include <com/sun/star/graphic/GraphicProvider.hpp>
39 #include <com/sun/star/xml/sax/SAXParseException.hpp>
40 #include <com/sun/star/embed/StorageFormats.hpp>
41 #include <sal/log.hxx>
42 #include <unotools/datetime.hxx>
43 #include <comphelper/base64.hxx>
44 #include <comphelper/processfactory.hxx>
45 #include <comphelper/sequence.hxx>
46 #include <comphelper/seqstream.hxx>
49 using namespace css::uno
;
50 using namespace css::beans
;
51 namespace cssu
= com::sun::star::uno
;
52 namespace cssl
= com::sun::star::lang
;
53 namespace cssxc
= com::sun::star::xml::crypto
;
54 namespace cssxs
= com::sun::star::xml::sax
;
56 /* protected: for signature verify */
57 cssu::Reference
< cssxc::sax::XReferenceResolvedListener
> XSecController::prepareSignatureToRead(
58 sal_Int32 nSecurityId
)
60 if ( m_eStatusOfSecurityComponents
!= InitializationState::INITIALIZED
)
65 sal_Int32 nIdOfSignatureElementCollector
;
66 cssu::Reference
< cssxc::sax::XReferenceResolvedListener
> xReferenceResolvedListener
;
68 nIdOfSignatureElementCollector
=
69 m_xSAXEventKeeper
->addSecurityElementCollector( cssxc::sax::ElementMarkPriority_BEFOREMODIFY
, false);
71 m_xSAXEventKeeper
->setSecurityId(nIdOfSignatureElementCollector
, nSecurityId
);
74 * create a SignatureVerifier
76 xReferenceResolvedListener
= new SignatureVerifierImpl
;
78 cssu::Reference
<cssl::XInitialization
> xInitialization(xReferenceResolvedListener
, cssu::UNO_QUERY
);
80 cssu::Sequence
<cssu::Any
> args(5);
81 args
[0] <<= OUString::number(nSecurityId
);
82 args
[1] <<= uno::Reference
<xml::crypto::sax::XSecuritySAXEventKeeper
>(static_cast<cppu::OWeakObject
*>(m_xSAXEventKeeper
.get()), uno::UNO_QUERY
);
83 args
[2] <<= OUString::number(nIdOfSignatureElementCollector
);
84 args
[3] <<= m_xSecurityContext
;
85 args
[4] <<= m_xXMLSignature
;
86 xInitialization
->initialize(args
);
88 cssu::Reference
< cssxc::sax::XSignatureVerifyResultBroadcaster
>
89 signatureVerifyResultBroadcaster(xReferenceResolvedListener
, cssu::UNO_QUERY
);
91 signatureVerifyResultBroadcaster
->addSignatureVerifyResultListener( this );
93 m_xSAXEventKeeper
->addReferenceResolvedListener(
94 nIdOfSignatureElementCollector
,
95 xReferenceResolvedListener
);
97 cssu::Reference
<cssxc::sax::XKeyCollector
> keyCollector (xReferenceResolvedListener
, cssu::UNO_QUERY
);
98 keyCollector
->setKeyId(0);
100 return xReferenceResolvedListener
;
103 void XSecController::addSignature()
105 cssu::Reference
< cssxc::sax::XReferenceResolvedListener
> xReferenceResolvedListener
= nullptr;
106 sal_Int32 nSignatureId
= 0;
109 if (m_bVerifyCurrentSignature
)
112 xReferenceResolvedListener
= prepareSignatureToRead( m_nReservedSignatureId
);
113 m_bVerifyCurrentSignature
= false;
114 nSignatureId
= m_nReservedSignatureId
;
117 InternalSignatureInformation
isi( nSignatureId
, xReferenceResolvedListener
);
118 m_vInternalSignatureInformations
.push_back( isi
);
121 void XSecController::switchGpgSignature()
123 #if HAVE_FEATURE_GPGME
124 // swap signature verifier for the Gpg one
125 m_xXMLSignature
.set(new XMLSignature_GpgImpl());
126 if (!m_vInternalSignatureInformations
.empty())
128 SignatureVerifierImpl
* pImpl
=
129 dynamic_cast<SignatureVerifierImpl
*>(
130 m_vInternalSignatureInformations
.back().xReferenceResolvedListener
.get());
133 css::uno::Reference
<css::xml::crypto::XSEInitializer
> xGpgSEInitializer(
134 new SEInitializerGpg());
135 pImpl
->updateSignature(new XMLSignature_GpgImpl(),
136 xGpgSEInitializer
->createSecurityContext(OUString()));
144 void XSecController::addReference( const OUString
& ouUri
, sal_Int32 nDigestID
)
146 if (m_vInternalSignatureInformations
.empty())
148 SAL_INFO("xmlsecurity.helper","XSecController::addReference: no signature");
151 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
152 isi
.addReference(SignatureReferenceType::SAMEDOCUMENT
, nDigestID
, ouUri
, -1 );
155 void XSecController::addStreamReference(
156 const OUString
& ouUri
,
158 sal_Int32 nDigestID
)
160 SignatureReferenceType type
= (isBinary
?SignatureReferenceType::BINARYSTREAM
:SignatureReferenceType::XMLSTREAM
);
162 if (m_vInternalSignatureInformations
.empty())
164 SAL_INFO("xmlsecurity.helper","XSecController::addStreamReference: no signature");
167 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
169 if ( isi
.xReferenceResolvedListener
.is() )
172 * get the input stream
174 cssu::Reference
< css::io::XInputStream
> xObjectInputStream
175 = getObjectInputStream( ouUri
);
177 if ( xObjectInputStream
.is() )
179 cssu::Reference
<cssxc::XUriBinding
> xUriBinding
180 (isi
.xReferenceResolvedListener
, cssu::UNO_QUERY
);
181 xUriBinding
->setUriBinding(ouUri
, xObjectInputStream
);
185 isi
.addReference(type
, nDigestID
, ouUri
, -1);
188 void XSecController::setReferenceCount() const
190 if (m_vInternalSignatureInformations
.empty())
192 SAL_INFO("xmlsecurity.helper","XSecController::setReferenceCount: no signature");
195 const InternalSignatureInformation
&isi
=
196 m_vInternalSignatureInformations
.back();
198 if ( isi
.xReferenceResolvedListener
.is() )
200 const SignatureReferenceInformations
&refInfors
= isi
.signatureInfor
.vSignatureReferenceInfors
;
202 int refNum
= refInfors
.size();
203 sal_Int32 referenceCount
= 0;
205 for(int i
=0 ; i
<refNum
; ++i
)
207 if (refInfors
[i
].nType
== SignatureReferenceType::SAMEDOCUMENT
)
209 * same-document reference
216 cssu::Reference
<cssxc::sax::XReferenceCollector
> xReferenceCollector
217 (isi
.xReferenceResolvedListener
, cssu::UNO_QUERY
);
218 xReferenceCollector
->setReferenceCount( referenceCount
);
222 void XSecController::setX509IssuerName( OUString
const & ouX509IssuerName
)
224 if (m_vInternalSignatureInformations
.empty())
226 SAL_INFO("xmlsecurity.helper","XSecController::setX509IssuerName: no signature");
229 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
230 isi
.signatureInfor
.ouX509IssuerName
= ouX509IssuerName
;
233 void XSecController::setX509SerialNumber( OUString
const & ouX509SerialNumber
)
235 if (m_vInternalSignatureInformations
.empty())
237 SAL_INFO("xmlsecurity.helper","XSecController::setX509SerialNumber: no signature");
240 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
241 isi
.signatureInfor
.ouX509SerialNumber
= ouX509SerialNumber
;
244 void XSecController::setX509Certificate( OUString
const & ouX509Certificate
)
246 if (m_vInternalSignatureInformations
.empty())
248 SAL_INFO("xmlsecurity.helper","XSecController::setX509Certificate: no signature");
251 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
252 isi
.signatureInfor
.ouX509Certificate
= ouX509Certificate
;
255 void XSecController::setSignatureValue( OUString
const & ouSignatureValue
)
257 if (m_vInternalSignatureInformations
.empty())
259 SAL_INFO("xmlsecurity.helper","XSecController::setSignatureValue: no signature");
262 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
263 isi
.signatureInfor
.ouSignatureValue
= ouSignatureValue
;
266 void XSecController::setDigestValue( sal_Int32 nDigestID
, OUString
const & ouDigestValue
)
268 if (m_vInternalSignatureInformations
.empty())
270 SAL_INFO("xmlsecurity.helper","XSecController::setDigestValue: no signature");
273 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
274 if (isi
.signatureInfor
.vSignatureReferenceInfors
.empty())
276 SAL_INFO("xmlsecurity.helper","XSecController::setDigestValue: no signature reference");
279 SignatureReferenceInformation
&reference
=
280 isi
.signatureInfor
.vSignatureReferenceInfors
.back();
281 reference
.nDigestID
= nDigestID
;
282 reference
.ouDigestValue
= ouDigestValue
;
285 void XSecController::setGpgKeyID( OUString
const & ouKeyID
)
287 if (m_vInternalSignatureInformations
.empty())
289 SAL_INFO("xmlsecurity.helper","XSecController::setGpgKeyID: no signature");
292 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
293 isi
.signatureInfor
.ouGpgKeyID
= ouKeyID
;
296 void XSecController::setGpgCertificate( OUString
const & ouGpgCert
)
298 if (m_vInternalSignatureInformations
.empty())
300 SAL_INFO("xmlsecurity.helper","XSecController::setGpgCertificate: no signature");
303 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
304 isi
.signatureInfor
.ouGpgCertificate
= ouGpgCert
;
307 void XSecController::setGpgOwner( OUString
const & ouGpgOwner
)
309 if (m_vInternalSignatureInformations
.empty())
311 SAL_INFO("xmlsecurity.helper","XSecController::setGpgOwner: no signature");
314 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
315 isi
.signatureInfor
.ouGpgOwner
= ouGpgOwner
;
318 void XSecController::setDate( OUString
const & ouDate
)
320 if (m_vInternalSignatureInformations
.empty())
322 SAL_INFO("xmlsecurity.helper","XSecController::setDate: no signature");
325 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
326 (void)utl::ISO8601parseDateTime( ouDate
, isi
.signatureInfor
.stDateTime
);
327 isi
.signatureInfor
.ouDateTime
= ouDate
;
330 void XSecController::setDescription(const OUString
& rDescription
)
332 if (m_vInternalSignatureInformations
.empty())
335 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
336 rInformation
.signatureInfor
.ouDescription
= rDescription
;
339 void XSecController::setSignatureBytes(const uno::Sequence
<sal_Int8
>& rBytes
)
341 if (m_vInternalSignatureInformations
.empty())
344 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
345 rInformation
.signatureInfor
.aSignatureBytes
= rBytes
;
348 void XSecController::setCertDigest(const OUString
& rCertDigest
)
350 if (m_vInternalSignatureInformations
.empty())
353 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
354 rInformation
.signatureInfor
.ouCertDigest
= rCertDigest
;
358 Reference
<css::graphic::XGraphic
> lcl_getGraphicFromString(const OUString
& rImage
)
360 Sequence
<sal_Int8
> seq
;
361 comphelper::Base64::decode(seq
, rImage
);
363 Reference
< graphic::XGraphic
> xGraphic
;
364 if( !seq
.hasElements() )
365 return Reference
<css::graphic::XGraphic
>();
367 Reference
< graphic::XGraphicProvider
> xGraphicProvider(
368 graphic::GraphicProvider::create(comphelper::getProcessComponentContext()) );
369 Reference
< io::XInputStream
> xInputStream( new ::comphelper::SequenceInputStream( seq
) );
371 Sequence
< PropertyValue
> aArgs( 1 );
372 aArgs
[ 0 ].Name
= "InputStream";
373 aArgs
[ 0 ].Value
<<= xInputStream
;
374 xGraphic
= xGraphicProvider
->queryGraphic(aArgs
);
380 void XSecController::setValidSignatureImage(const OUString
& rValidSigImg
)
382 if (m_vInternalSignatureInformations
.empty() || rValidSigImg
.isEmpty())
385 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
386 rInformation
.signatureInfor
.aValidSignatureImage
= lcl_getGraphicFromString(rValidSigImg
);
389 void XSecController::setInvalidSignatureImage(const OUString
& rInvalidSigImg
)
391 if (m_vInternalSignatureInformations
.empty() || rInvalidSigImg
.isEmpty())
394 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
395 rInformation
.signatureInfor
.aInvalidSignatureImage
= lcl_getGraphicFromString(rInvalidSigImg
);
398 void XSecController::setSignatureLineId(const OUString
& rSignatureLineId
)
400 if (m_vInternalSignatureInformations
.empty())
403 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
404 rInformation
.signatureInfor
.ouSignatureLineId
= rSignatureLineId
;
407 void XSecController::addEncapsulatedX509Certificate(const OUString
& rEncapsulatedX509Certificate
)
409 if (m_vInternalSignatureInformations
.empty())
412 if (rEncapsulatedX509Certificate
.isEmpty())
415 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
416 rInformation
.signatureInfor
.maEncapsulatedX509Certificates
.insert(rEncapsulatedX509Certificate
);
419 void XSecController::setId( OUString
const & ouId
)
421 if (m_vInternalSignatureInformations
.empty())
423 SAL_INFO("xmlsecurity.helper","XSecController::setId: no signature");
426 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
427 isi
.signatureInfor
.ouSignatureId
= ouId
;
430 void XSecController::setPropertyId( OUString
const & ouPropertyId
)
432 if (m_vInternalSignatureInformations
.empty())
434 SAL_INFO("xmlsecurity.helper","XSecController::setPropertyId: no signature");
437 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
439 if (isi
.signatureInfor
.ouPropertyId
.isEmpty())
441 // <SignatureProperty> ID attribute is for the date.
442 isi
.signatureInfor
.ouPropertyId
= ouPropertyId
;
446 // <SignatureProperty> ID attribute is for the description.
447 isi
.signatureInfor
.ouDescriptionPropertyId
= ouPropertyId
;
451 /* public: for signature verify */
452 void XSecController::collectToVerify( const OUString
& referenceId
)
454 /* SAL_WARN_IF( !m_xSAXEventKeeper.is(), "xmlsecurity", "the SAXEventKeeper is NULL" ); */
456 if ( m_eStatusOfSecurityComponents
== InitializationState::INITIALIZED
)
458 * if all security components are ready, verify the signature.
461 bool bJustChainingOn
= false;
462 cssu::Reference
< cssxs::XDocumentHandler
> xHandler
= nullptr;
465 int sigNum
= m_vInternalSignatureInformations
.size();
467 for (i
=0; i
<sigNum
; ++i
)
469 InternalSignatureInformation
& isi
= m_vInternalSignatureInformations
[i
];
470 SignatureReferenceInformations
& vReferenceInfors
= isi
.signatureInfor
.vSignatureReferenceInfors
;
471 int refNum
= vReferenceInfors
.size();
473 for (j
=0; j
<refNum
; ++j
)
475 SignatureReferenceInformation
&refInfor
= vReferenceInfors
[j
];
477 if (refInfor
.ouURI
== referenceId
)
481 bJustChainingOn
= true;
482 xHandler
= m_xSAXEventKeeper
->setNextHandler(nullptr);
485 sal_Int32 nKeeperId
= m_xSAXEventKeeper
->addSecurityElementCollector(
486 cssxc::sax::ElementMarkPriority_BEFOREMODIFY
, false );
488 cssu::Reference
<cssxc::sax::XReferenceCollector
> xReferenceCollector
489 ( isi
.xReferenceResolvedListener
, cssu::UNO_QUERY
);
491 m_xSAXEventKeeper
->setSecurityId(nKeeperId
, isi
.signatureInfor
.nSecurityId
);
492 m_xSAXEventKeeper
->addReferenceResolvedListener( nKeeperId
, isi
.xReferenceResolvedListener
);
493 xReferenceCollector
->setReferenceId( nKeeperId
);
495 isi
.vKeeperIds
[j
] = nKeeperId
;
501 if ( bJustChainingOn
)
503 cssu::Reference
< cssxs::XDocumentHandler
> xSEKHandler(static_cast<cppu::OWeakObject
*>(m_xSAXEventKeeper
.get()), cssu::UNO_QUERY
);
504 m_xSAXEventKeeper
->setNextHandler(xHandler
);
509 void XSecController::addSignature( sal_Int32 nSignatureId
)
511 SAL_WARN_IF( !m_xSecParser
.is(), "xmlsecurity.helper", "No XSecParser initialized" );
513 m_nReservedSignatureId
= nSignatureId
;
514 m_bVerifyCurrentSignature
= true;
517 cssu::Reference
< cssxs::XDocumentHandler
> const & XSecController::createSignatureReader(XMLSignatureHelper
& rXMLSignatureHelper
, sal_Int32 nType
)
519 if (nType
== embed::StorageFormats::OFOPXML
)
520 m_xSecParser
= new OOXMLSecParser(rXMLSignatureHelper
, this);
522 m_xSecParser
= new XSecParser(rXMLSignatureHelper
, this);
523 cssu::Reference
< cssl::XInitialization
> xInitialization(m_xSecParser
, uno::UNO_QUERY
);
525 setSAXChainConnector(xInitialization
);
530 void XSecController::releaseSignatureReader()
532 clearSAXChainConnector( );
533 m_xSecParser
.clear();
536 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */