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/XReferenceCollector.hpp>
34 #include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp>
35 #include <com/sun/star/xml/crypto/XSEInitializer.hpp>
36 #include <com/sun/star/graphic/GraphicProvider.hpp>
37 #include <com/sun/star/embed/StorageFormats.hpp>
38 #include <sal/log.hxx>
39 #include <unotools/datetime.hxx>
40 #include <comphelper/base64.hxx>
41 #include <comphelper/processfactory.hxx>
42 #include <comphelper/seqstream.hxx>
44 namespace com::sun::star::graphic
{ class XGraphic
; }
47 using namespace css::uno
;
48 using namespace css::beans
;
49 namespace cssu
= com::sun::star::uno
;
50 namespace cssl
= com::sun::star::lang
;
51 namespace cssxc
= com::sun::star::xml::crypto
;
52 namespace cssxs
= com::sun::star::xml::sax
;
54 /* protected: for signature verify */
55 cssu::Reference
< cssxc::sax::XReferenceResolvedListener
> XSecController::prepareSignatureToRead(
56 sal_Int32 nSecurityId
)
58 if ( m_eStatusOfSecurityComponents
!= InitializationState::INITIALIZED
)
63 sal_Int32 nIdOfSignatureElementCollector
;
64 cssu::Reference
< cssxc::sax::XReferenceResolvedListener
> xReferenceResolvedListener
;
66 nIdOfSignatureElementCollector
=
67 m_xSAXEventKeeper
->addSecurityElementCollector( cssxc::sax::ElementMarkPriority_BEFOREMODIFY
, false);
69 m_xSAXEventKeeper
->setSecurityId(nIdOfSignatureElementCollector
, nSecurityId
);
72 * create a SignatureVerifier
74 xReferenceResolvedListener
= new SignatureVerifierImpl
;
76 cssu::Reference
<cssl::XInitialization
> xInitialization(xReferenceResolvedListener
, cssu::UNO_QUERY
);
78 cssu::Sequence
<cssu::Any
> args(5);
79 args
[0] <<= OUString::number(nSecurityId
);
80 args
[1] <<= uno::Reference
<xml::crypto::sax::XSecuritySAXEventKeeper
>(static_cast<cppu::OWeakObject
*>(m_xSAXEventKeeper
.get()), uno::UNO_QUERY
);
81 args
[2] <<= OUString::number(nIdOfSignatureElementCollector
);
82 args
[3] <<= m_xSecurityContext
;
83 args
[4] <<= m_xXMLSignature
;
84 xInitialization
->initialize(args
);
86 cssu::Reference
< cssxc::sax::XSignatureVerifyResultBroadcaster
>
87 signatureVerifyResultBroadcaster(xReferenceResolvedListener
, cssu::UNO_QUERY
);
89 signatureVerifyResultBroadcaster
->addSignatureVerifyResultListener( this );
91 m_xSAXEventKeeper
->addReferenceResolvedListener(
92 nIdOfSignatureElementCollector
,
93 xReferenceResolvedListener
);
95 cssu::Reference
<cssxc::sax::XKeyCollector
> keyCollector (xReferenceResolvedListener
, cssu::UNO_QUERY
);
96 keyCollector
->setKeyId(0);
98 return xReferenceResolvedListener
;
101 void XSecController::addSignature()
103 cssu::Reference
< cssxc::sax::XReferenceResolvedListener
> xReferenceResolvedListener
;
104 sal_Int32 nSignatureId
= 0;
107 if (m_bVerifyCurrentSignature
)
110 xReferenceResolvedListener
= prepareSignatureToRead( m_nReservedSignatureId
);
111 m_bVerifyCurrentSignature
= false;
112 nSignatureId
= m_nReservedSignatureId
;
115 InternalSignatureInformation
isi( nSignatureId
, xReferenceResolvedListener
);
116 m_vInternalSignatureInformations
.push_back( isi
);
119 void XSecController::setSignatureMethod(svl::crypto::SignatureMethodAlgorithm eAlgorithmID
)
121 if (m_vInternalSignatureInformations
.empty())
124 m_vInternalSignatureInformations
.back().signatureInfor
.eAlgorithmID
= eAlgorithmID
;
127 void XSecController::switchGpgSignature()
129 #if HAVE_FEATURE_GPGME
130 // swap signature verifier for the Gpg one
131 m_xXMLSignature
.set(new XMLSignature_GpgImpl());
132 if (!m_vInternalSignatureInformations
.empty())
134 SignatureVerifierImpl
* pImpl
=
135 dynamic_cast<SignatureVerifierImpl
*>(
136 m_vInternalSignatureInformations
.back().xReferenceResolvedListener
.get());
139 css::uno::Reference
<css::xml::crypto::XSEInitializer
> xGpgSEInitializer(
140 new SEInitializerGpg());
141 pImpl
->updateSignature(new XMLSignature_GpgImpl(),
142 xGpgSEInitializer
->createSecurityContext(OUString()));
150 void XSecController::addReference( const OUString
& ouUri
, sal_Int32 nDigestID
, const OUString
& ouType
)
152 if (m_vInternalSignatureInformations
.empty())
154 SAL_INFO("xmlsecurity.helper","XSecController::addReference: no signature");
157 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
158 isi
.addReference(SignatureReferenceType::SAMEDOCUMENT
, nDigestID
, ouUri
, -1, ouType
);
161 void XSecController::addStreamReference(
162 const OUString
& ouUri
,
164 sal_Int32 nDigestID
)
166 SignatureReferenceType type
= (isBinary
?SignatureReferenceType::BINARYSTREAM
:SignatureReferenceType::XMLSTREAM
);
168 if (m_vInternalSignatureInformations
.empty())
170 SAL_INFO("xmlsecurity.helper","XSecController::addStreamReference: no signature");
173 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
175 if ( isi
.xReferenceResolvedListener
.is() )
178 * get the input stream
180 cssu::Reference
< css::io::XInputStream
> xObjectInputStream
181 = getObjectInputStream( ouUri
);
183 if ( xObjectInputStream
.is() )
185 cssu::Reference
<cssxc::XUriBinding
> xUriBinding
186 (isi
.xReferenceResolvedListener
, cssu::UNO_QUERY
);
187 xUriBinding
->setUriBinding(ouUri
, xObjectInputStream
);
191 isi
.addReference(type
, nDigestID
, ouUri
, -1, OUString());
194 void XSecController::setReferenceCount() const
196 if (m_vInternalSignatureInformations
.empty())
198 SAL_INFO("xmlsecurity.helper","XSecController::setReferenceCount: no signature");
201 const InternalSignatureInformation
&isi
=
202 m_vInternalSignatureInformations
.back();
204 if ( isi
.xReferenceResolvedListener
.is() )
206 const SignatureReferenceInformations
&refInfors
= isi
.signatureInfor
.vSignatureReferenceInfors
;
208 int refNum
= refInfors
.size();
209 sal_Int32 referenceCount
= 0;
211 for(int i
=0 ; i
<refNum
; ++i
)
213 if (refInfors
[i
].nType
== SignatureReferenceType::SAMEDOCUMENT
)
215 * same-document reference
222 cssu::Reference
<cssxc::sax::XReferenceCollector
> xReferenceCollector
223 (isi
.xReferenceResolvedListener
, cssu::UNO_QUERY
);
224 xReferenceCollector
->setReferenceCount( referenceCount
);
228 void XSecController::setX509IssuerName( OUString
const & ouX509IssuerName
)
230 if (m_vInternalSignatureInformations
.empty())
232 SAL_INFO("xmlsecurity.helper","XSecController::setX509IssuerName: no signature");
235 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
236 isi
.signatureInfor
.ouX509IssuerName
= ouX509IssuerName
;
239 void XSecController::setX509SerialNumber( OUString
const & ouX509SerialNumber
)
241 if (m_vInternalSignatureInformations
.empty())
243 SAL_INFO("xmlsecurity.helper","XSecController::setX509SerialNumber: no signature");
246 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
247 isi
.signatureInfor
.ouX509SerialNumber
= ouX509SerialNumber
;
250 void XSecController::setX509Certificate( OUString
const & ouX509Certificate
)
252 if (m_vInternalSignatureInformations
.empty())
254 SAL_INFO("xmlsecurity.helper","XSecController::setX509Certificate: no signature");
257 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
258 isi
.signatureInfor
.ouX509Certificate
= ouX509Certificate
;
261 void XSecController::setSignatureValue( OUString
const & ouSignatureValue
)
263 if (m_vInternalSignatureInformations
.empty())
265 SAL_INFO("xmlsecurity.helper","XSecController::setSignatureValue: no signature");
268 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
269 isi
.signatureInfor
.ouSignatureValue
= ouSignatureValue
;
272 void XSecController::setDigestValue( sal_Int32 nDigestID
, OUString
const & ouDigestValue
)
274 if (m_vInternalSignatureInformations
.empty())
276 SAL_INFO("xmlsecurity.helper","XSecController::setDigestValue: no signature");
279 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
280 if (isi
.signatureInfor
.vSignatureReferenceInfors
.empty())
282 SAL_INFO("xmlsecurity.helper","XSecController::setDigestValue: no signature reference");
285 SignatureReferenceInformation
&reference
=
286 isi
.signatureInfor
.vSignatureReferenceInfors
.back();
287 reference
.nDigestID
= nDigestID
;
288 reference
.ouDigestValue
= ouDigestValue
;
291 void XSecController::setGpgKeyID( OUString
const & ouKeyID
)
293 if (m_vInternalSignatureInformations
.empty())
295 SAL_INFO("xmlsecurity.helper","XSecController::setGpgKeyID: no signature");
298 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
299 isi
.signatureInfor
.ouGpgKeyID
= ouKeyID
;
302 void XSecController::setGpgCertificate( OUString
const & ouGpgCert
)
304 if (m_vInternalSignatureInformations
.empty())
306 SAL_INFO("xmlsecurity.helper","XSecController::setGpgCertificate: no signature");
309 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
310 isi
.signatureInfor
.ouGpgCertificate
= ouGpgCert
;
313 void XSecController::setGpgOwner( OUString
const & ouGpgOwner
)
315 if (m_vInternalSignatureInformations
.empty())
317 SAL_INFO("xmlsecurity.helper","XSecController::setGpgOwner: no signature");
320 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
321 isi
.signatureInfor
.ouGpgOwner
= ouGpgOwner
;
324 void XSecController::setDate( OUString
const & ouDate
)
326 if (m_vInternalSignatureInformations
.empty())
328 SAL_INFO("xmlsecurity.helper","XSecController::setDate: no signature");
331 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
332 (void)utl::ISO8601parseDateTime( ouDate
, isi
.signatureInfor
.stDateTime
);
333 isi
.signatureInfor
.ouDateTime
= ouDate
;
336 void XSecController::setDescription(const OUString
& rDescription
)
338 if (m_vInternalSignatureInformations
.empty())
341 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
342 rInformation
.signatureInfor
.ouDescription
= rDescription
;
345 void XSecController::setSignatureBytes(const uno::Sequence
<sal_Int8
>& rBytes
)
347 if (m_vInternalSignatureInformations
.empty())
350 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
351 rInformation
.signatureInfor
.aSignatureBytes
= rBytes
;
354 void XSecController::setCertDigest(const OUString
& rCertDigest
)
356 if (m_vInternalSignatureInformations
.empty())
359 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
360 rInformation
.signatureInfor
.ouCertDigest
= rCertDigest
;
364 Reference
<css::graphic::XGraphic
> lcl_getGraphicFromString(const OUString
& rImage
)
366 Sequence
<sal_Int8
> seq
;
367 comphelper::Base64::decode(seq
, rImage
);
369 Reference
< graphic::XGraphic
> xGraphic
;
370 if( !seq
.hasElements() )
371 return Reference
<css::graphic::XGraphic
>();
373 Reference
< graphic::XGraphicProvider
> xGraphicProvider(
374 graphic::GraphicProvider::create(comphelper::getProcessComponentContext()) );
375 Reference
< io::XInputStream
> xInputStream( new ::comphelper::SequenceInputStream( seq
) );
377 Sequence
< PropertyValue
> aArgs( 1 );
378 aArgs
[ 0 ].Name
= "InputStream";
379 aArgs
[ 0 ].Value
<<= xInputStream
;
380 xGraphic
= xGraphicProvider
->queryGraphic(aArgs
);
386 void XSecController::setValidSignatureImage(const OUString
& rValidSigImg
)
388 if (m_vInternalSignatureInformations
.empty() || rValidSigImg
.isEmpty())
391 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
392 rInformation
.signatureInfor
.aValidSignatureImage
= lcl_getGraphicFromString(rValidSigImg
);
395 void XSecController::setInvalidSignatureImage(const OUString
& rInvalidSigImg
)
397 if (m_vInternalSignatureInformations
.empty() || rInvalidSigImg
.isEmpty())
400 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
401 rInformation
.signatureInfor
.aInvalidSignatureImage
= lcl_getGraphicFromString(rInvalidSigImg
);
404 void XSecController::setSignatureLineId(const OUString
& rSignatureLineId
)
406 if (m_vInternalSignatureInformations
.empty())
409 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
410 rInformation
.signatureInfor
.ouSignatureLineId
= rSignatureLineId
;
413 void XSecController::addEncapsulatedX509Certificate(const OUString
& rEncapsulatedX509Certificate
)
415 if (m_vInternalSignatureInformations
.empty())
418 if (rEncapsulatedX509Certificate
.isEmpty())
421 InternalSignatureInformation
& rInformation
= m_vInternalSignatureInformations
.back();
422 rInformation
.signatureInfor
.maEncapsulatedX509Certificates
.insert(rEncapsulatedX509Certificate
);
425 void XSecController::setId( OUString
const & ouId
)
427 if (m_vInternalSignatureInformations
.empty())
429 SAL_INFO("xmlsecurity.helper","XSecController::setId: no signature");
432 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
433 isi
.signatureInfor
.ouSignatureId
= ouId
;
436 void XSecController::setPropertyId( OUString
const & ouPropertyId
)
438 if (m_vInternalSignatureInformations
.empty())
440 SAL_INFO("xmlsecurity.helper","XSecController::setPropertyId: no signature");
443 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
.back();
445 if (isi
.signatureInfor
.ouPropertyId
.isEmpty())
447 // <SignatureProperty> ID attribute is for the date.
448 isi
.signatureInfor
.ouPropertyId
= ouPropertyId
;
452 // <SignatureProperty> ID attribute is for the description.
453 isi
.signatureInfor
.ouDescriptionPropertyId
= ouPropertyId
;
457 /* public: for signature verify */
458 void XSecController::collectToVerify( const OUString
& referenceId
)
460 /* SAL_WARN_IF( !m_xSAXEventKeeper.is(), "xmlsecurity", "the SAXEventKeeper is NULL" ); */
462 if ( m_eStatusOfSecurityComponents
== InitializationState::INITIALIZED
)
464 * if all security components are ready, verify the signature.
467 bool bJustChainingOn
= false;
468 cssu::Reference
< cssxs::XDocumentHandler
> xHandler
;
471 int sigNum
= m_vInternalSignatureInformations
.size();
473 for (i
=0; i
<sigNum
; ++i
)
475 InternalSignatureInformation
& isi
= m_vInternalSignatureInformations
[i
];
476 SignatureReferenceInformations
& vReferenceInfors
= isi
.signatureInfor
.vSignatureReferenceInfors
;
477 int refNum
= vReferenceInfors
.size();
479 for (j
=0; j
<refNum
; ++j
)
481 SignatureReferenceInformation
&refInfor
= vReferenceInfors
[j
];
483 if (refInfor
.ouURI
== referenceId
)
487 bJustChainingOn
= true;
488 xHandler
= m_xSAXEventKeeper
->setNextHandler(nullptr);
491 sal_Int32 nKeeperId
= m_xSAXEventKeeper
->addSecurityElementCollector(
492 cssxc::sax::ElementMarkPriority_BEFOREMODIFY
, false );
494 cssu::Reference
<cssxc::sax::XReferenceCollector
> xReferenceCollector
495 ( isi
.xReferenceResolvedListener
, cssu::UNO_QUERY
);
497 m_xSAXEventKeeper
->setSecurityId(nKeeperId
, isi
.signatureInfor
.nSecurityId
);
498 m_xSAXEventKeeper
->addReferenceResolvedListener( nKeeperId
, isi
.xReferenceResolvedListener
);
499 xReferenceCollector
->setReferenceId( nKeeperId
);
501 isi
.vKeeperIds
[j
] = nKeeperId
;
507 if ( bJustChainingOn
)
509 cssu::Reference
< cssxs::XDocumentHandler
> xSEKHandler(static_cast<cppu::OWeakObject
*>(m_xSAXEventKeeper
.get()), cssu::UNO_QUERY
);
510 m_xSAXEventKeeper
->setNextHandler(xHandler
);
515 void XSecController::addSignature( sal_Int32 nSignatureId
)
517 SAL_WARN_IF( !m_xSecParser
.is(), "xmlsecurity.helper", "No XSecParser initialized" );
519 m_nReservedSignatureId
= nSignatureId
;
520 m_bVerifyCurrentSignature
= true;
523 cssu::Reference
< cssxs::XDocumentHandler
> const & XSecController::createSignatureReader(XMLSignatureHelper
& rXMLSignatureHelper
, sal_Int32 nType
)
525 if (nType
== embed::StorageFormats::OFOPXML
)
526 m_xSecParser
= new OOXMLSecParser(rXMLSignatureHelper
, this);
528 m_xSecParser
= new XSecParser(rXMLSignatureHelper
, this);
529 cssu::Reference
< cssl::XInitialization
> xInitialization(m_xSecParser
, uno::UNO_QUERY
);
531 setSAXChainConnector(xInitialization
);
536 void XSecController::releaseSignatureReader()
538 clearSAXChainConnector( );
539 m_xSecParser
.clear();
542 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */