tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / xmlsecurity / source / helper / documentsignaturemanager.cxx
blob2a4be54594f5fdb68c62b4d95d788e3146e35b1d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <documentsignaturemanager.hxx>
21 #include <config_gpgme.h>
23 #include <gpg/SEInitializer.hxx>
25 #include <com/sun/star/embed/StorageFormats.hpp>
26 #include <com/sun/star/embed/ElementModes.hpp>
27 #include <com/sun/star/embed/XStorage.hpp>
28 #include <com/sun/star/io/XTempFile.hpp>
29 #include <com/sun/star/io/XTruncate.hpp>
30 #include <com/sun/star/embed/XTransactedObject.hpp>
31 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
32 #include <com/sun/star/lang/XServiceInfo.hpp>
33 #include <com/sun/star/beans/PropertyValue.hpp>
34 #include <com/sun/star/packages/manifest/ManifestReader.hpp>
35 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
36 #include <com/sun/star/xml/sax/XWriter.hpp>
37 #include <com/sun/star/frame/XModel.hpp>
39 #include <comphelper/base64.hxx>
40 #include <comphelper/storagehelper.hxx>
41 #include <rtl/ustrbuf.hxx>
42 #include <sal/log.hxx>
43 #include <tools/datetime.hxx>
44 #include <o3tl/string_view.hxx>
45 #include <svl/cryptosign.hxx>
47 #include <certificate.hxx>
48 #include <biginteger.hxx>
50 #include <xmlsec/xmlsec_init.hxx>
52 #include <pdfsignaturehelper.hxx>
54 #include <memory>
56 using namespace css;
57 using namespace css::graphic;
58 using namespace css::uno;
60 /// RAII class to init / shut down libxmlsec.
61 class Xmlsec
63 public:
64 Xmlsec();
65 ~Xmlsec();
68 Xmlsec::Xmlsec() { initXmlSec(); }
70 Xmlsec::~Xmlsec() { deInitXmlSec(); }
72 namespace
74 /// Shared access to libxmlsec, to avoid double init.
75 struct XmlsecLibrary
77 static std::shared_ptr<Xmlsec>& get();
80 std::shared_ptr<Xmlsec>& XmlsecLibrary::get()
82 static std::shared_ptr<Xmlsec> pInstance = std::make_shared<Xmlsec>();
83 return pInstance;
87 DocumentSignatureManager::DocumentSignatureManager(
88 const uno::Reference<uno::XComponentContext>& xContext, DocumentSignatureMode eMode)
89 : mxContext(xContext)
90 , maSignatureHelper(xContext)
91 , meSignatureMode(eMode)
95 DocumentSignatureManager::~DocumentSignatureManager() { mpXmlsecLibrary.reset(); }
97 bool DocumentSignatureManager::init()
99 SAL_WARN_IF(mxSEInitializer.is(), "xmlsecurity.helper",
100 "DocumentSignatureManager::Init - mxSEInitializer already set!");
101 SAL_WARN_IF(mxSecurityContext.is(), "xmlsecurity.helper",
102 "DocumentSignatureManager::Init - mxSecurityContext already set!");
103 SAL_WARN_IF(mxGpgSEInitializer.is(), "xmlsecurity.helper",
104 "DocumentSignatureManager::Init - mxGpgSEInitializer already set!");
106 // xmlsec is needed by both services, so init before those
107 mpXmlsecLibrary = XmlsecLibrary::get();
109 mxSEInitializer = xml::crypto::SEInitializer::create(mxContext);
110 #if HAVE_FEATURE_GPGME
111 mxGpgSEInitializer.set(new SEInitializerGpg());
112 #endif
114 if (mxSEInitializer.is())
115 mxSecurityContext = mxSEInitializer->createSecurityContext(OUString());
117 #if HAVE_FEATURE_GPGME
118 if (mxGpgSEInitializer.is())
119 mxGpgSecurityContext = mxGpgSEInitializer->createSecurityContext(OUString());
121 return mxSecurityContext.is() || mxGpgSecurityContext.is();
122 #else
123 return mxSecurityContext.is();
124 #endif
127 PDFSignatureHelper& DocumentSignatureManager::getPDFSignatureHelper()
129 bool bInit = true;
130 if (!mxSecurityContext.is())
131 bInit = init();
133 SAL_WARN_IF(!bInit, "xmlsecurity.comp", "Error initializing security context!");
135 if (!mpPDFSignatureHelper)
136 mpPDFSignatureHelper = std::make_unique<PDFSignatureHelper>();
138 return *mpPDFSignatureHelper;
141 #if 0 // For some reason does not work
142 bool DocumentSignatureManager::IsXAdESRelevant()
144 if (mxStore.is())
146 // ZIP-based: ODF or OOXML.
147 maSignatureHelper.StartMission();
149 SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(embed::ElementModes::READ, /*bUseTempStream=*/true);
150 if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML)
152 maSignatureHelper.EndMission();
153 return false;
155 // FIXME: How to figure out if it is ODF 1.2?
156 maSignatureHelper.EndMission();
157 return true;
159 return false;
161 #endif
163 bool DocumentSignatureManager::readManifest()
165 // Check if manifest was already read
166 if (m_manifest.hasElements())
167 return true;
169 if (!mxContext.is())
170 return false;
172 if (!mxStore.is())
173 return false;
175 uno::Reference<packages::manifest::XManifestReader> xReader
176 = packages::manifest::ManifestReader::create(mxContext);
178 if (mxStore->hasByName(u"META-INF"_ustr))
180 //Get the manifest.xml
181 uno::Reference<embed::XStorage> xSubStore(
182 mxStore->openStorageElement(u"META-INF"_ustr, embed::ElementModes::READ),
183 UNO_SET_THROW);
185 uno::Reference<io::XInputStream> xStream(
186 xSubStore->openStreamElement(u"manifest.xml"_ustr, css::embed::ElementModes::READ),
187 UNO_QUERY_THROW);
189 m_manifest = xReader->readManifestSequence(xStream);
191 return true;
194 /* Using the zip storage, we cannot get the properties "MediaType" and "IsEncrypted"
195 We use the manifest to find out if a file is xml and if it is encrypted.
196 The parameter is an encoded uri. However, the manifest contains paths. Therefore
197 the path is encoded as uri, so they can be compared.
199 bool DocumentSignatureManager::isXML(std::u16string_view rURI)
201 SAL_WARN_IF(!mxStore.is(), "xmlsecurity.helper", "empty storage reference");
203 bool bIsXML = false;
204 bool bPropsAvailable = false;
205 static constexpr OUStringLiteral sPropFullPath(u"FullPath");
206 static constexpr OUStringLiteral sPropMediaType(u"MediaType");
207 static constexpr OUStringLiteral sPropDigest(u"Digest");
209 if (readManifest())
211 for (const uno::Sequence<beans::PropertyValue>& entry : m_manifest)
213 OUString sPath;
214 OUString sMediaType;
215 bool bEncrypted = false;
216 for (const beans::PropertyValue& prop : entry)
218 if (prop.Name == sPropFullPath)
219 prop.Value >>= sPath;
220 else if (prop.Name == sPropMediaType)
221 prop.Value >>= sMediaType;
222 else if (prop.Name == sPropDigest)
223 bEncrypted = true;
225 if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI, sPath))
227 bIsXML = sMediaType == "text/xml" && !bEncrypted;
228 bPropsAvailable = true;
229 break;
233 if (!bPropsAvailable)
235 //This would be the case for at least mimetype, META-INF/manifest.xml
236 //META-INF/macrosignatures.xml.
237 //Files can only be encrypted if they are in the manifest.xml.
238 //That is, the current file cannot be encrypted, otherwise bPropsAvailable
239 //would be true.
240 size_t nSep = rURI.rfind('.');
241 if (nSep != std::u16string_view::npos)
243 std::u16string_view aExt = rURI.substr(nSep + 1);
244 if (o3tl::equalsIgnoreAsciiCase(aExt, u"XML"))
245 bIsXML = true;
248 return bIsXML;
251 //If bTempStream is true, then a temporary stream is return. If it is false then, the actual
252 //signature stream is used.
253 //Every time the user presses Add a new temporary stream is created.
254 //We keep the temporary stream as member because ImplGetSignatureInformations
255 //will later access the stream to create DocumentSignatureInformation objects
256 //which are stored in maCurrentSignatureInformations.
257 SignatureStreamHelper DocumentSignatureManager::ImplOpenSignatureStream(sal_Int32 nStreamOpenMode,
258 bool bTempStream)
260 SignatureStreamHelper aHelper;
261 if (mxStore.is() && mxStore->hasByName(u"[Content_Types].xml"_ustr))
262 aHelper.nStorageFormat = embed::StorageFormats::OFOPXML;
264 if (bTempStream)
266 if (nStreamOpenMode & embed::ElementModes::TRUNCATE)
268 //We write always into a new temporary stream.
269 mxTempSignatureStream = new utl::TempFileFastService;
270 if (aHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
271 aHelper.xSignatureStream = mxTempSignatureStream;
272 else
274 mxTempSignatureStorage = comphelper::OStorageHelper::GetStorageOfFormatFromStream(
275 ZIP_STORAGE_FORMAT_STRING, mxTempSignatureStream);
276 aHelper.xSignatureStorage = mxTempSignatureStorage;
279 else
281 //When we read from the temp stream, then we must have previously
282 //created one.
283 SAL_WARN_IF(!mxTempSignatureStream.is(), "xmlsecurity.helper",
284 "empty temp. signature stream reference");
286 aHelper.xSignatureStream = mxTempSignatureStream;
287 if (aHelper.nStorageFormat == embed::StorageFormats::OFOPXML)
288 aHelper.xSignatureStorage = mxTempSignatureStorage;
290 else
292 //No temporary stream
293 if (!mxSignatureStream.is())
295 //We may not have a dedicated stream for writing the signature
296 //So we take one directly from the storage
297 //Or DocumentDigitalSignatures::showDocumentContentSignatures was called,
298 //in which case Add/Remove is not allowed. This is done, for example, if the
299 //document is readonly
300 aHelper = DocumentSignatureHelper::OpenSignatureStream(mxStore, nStreamOpenMode,
301 meSignatureMode);
303 else
305 aHelper.xSignatureStream = mxSignatureStream;
309 if (nStreamOpenMode & embed::ElementModes::TRUNCATE)
311 if (aHelper.xSignatureStream.is()
312 && aHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
314 uno::Reference<io::XTruncate> xTruncate(aHelper.xSignatureStream, uno::UNO_QUERY_THROW);
315 xTruncate->truncate();
318 else if (bTempStream || mxSignatureStream.is())
320 //In case we read the signature stream from the storage directly,
321 //which is the case when DocumentDigitalSignatures::showDocumentContentSignatures
322 //then XSeakable is not supported
323 uno::Reference<io::XSeekable> xSeek(aHelper.xSignatureStream, uno::UNO_QUERY_THROW);
324 xSeek->seek(0);
327 return aHelper;
330 bool DocumentSignatureManager::add(
331 svl::crypto::SigningContext& rSigningContext,
332 const uno::Reference<xml::crypto::XXMLSecurityContext>& xSecurityContext,
333 const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant,
334 const OUString& rSignatureLineId, const Reference<XGraphic>& xValidGraphic,
335 const Reference<XGraphic>& xInvalidGraphic)
337 uno::Reference<security::XCertificate> xCert = rSigningContext.m_xCertificate;
338 uno::Reference<lang::XServiceInfo> xServiceInfo(xSecurityContext, uno::UNO_QUERY);
339 if (!xCert.is()
340 && xServiceInfo->getImplementationName()
341 == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl")
343 SAL_WARN("xmlsecurity.helper", "no certificate selected");
344 return false;
347 // GPG or X509 key?
348 if (xServiceInfo->getImplementationName()
349 == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl")
351 // GPG keys only really have PGPKeyId and PGPKeyPacket
352 if (!mxStore.is())
354 SAL_WARN("xmlsecurity.helper", "cannot sign pdfs with GPG keys");
355 return false;
358 maSignatureHelper.StartMission(xSecurityContext);
360 nSecurityId = maSignatureHelper.GetNewSecurityId();
362 OUStringBuffer aStrBuffer;
363 comphelper::Base64::encode(aStrBuffer, xCert->getEncoded());
365 OUString aKeyId;
366 if (auto pCertificate = dynamic_cast<xmlsecurity::Certificate*>(xCert.get()))
368 OUStringBuffer aBuffer;
369 comphelper::Base64::encode(aBuffer, pCertificate->getSHA256Thumbprint());
370 aKeyId = aBuffer.makeStringAndClear();
372 else
373 SAL_WARN("xmlsecurity.helper",
374 "XCertificate implementation without an xmlsecurity::Certificate one");
376 maSignatureHelper.SetGpgCertificate(nSecurityId, aKeyId, aStrBuffer.makeStringAndClear(),
377 xCert->getIssuerName());
379 else
381 if (!mxStore.is())
383 // Something not ZIP based, try PDF.
384 nSecurityId = getPDFSignatureHelper().GetNewSecurityId();
385 getPDFSignatureHelper().SetX509Certificate(rSigningContext);
386 getPDFSignatureHelper().SetDescription(rDescription);
387 uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
388 if (!getPDFSignatureHelper().Sign(mxModel, xInputStream, bAdESCompliant))
390 if (rSigningContext.m_xCertificate.is())
392 SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::Sign() failed");
394 return false;
396 return true;
399 OUString aCertSerial = xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber());
400 if (aCertSerial.isEmpty())
402 SAL_WARN("xmlsecurity.helper", "Error in Certificate, problem with serial number!");
403 return false;
406 maSignatureHelper.StartMission(xSecurityContext);
408 nSecurityId = maSignatureHelper.GetNewSecurityId();
410 OUStringBuffer aStrBuffer;
411 comphelper::Base64::encode(aStrBuffer, xCert->getEncoded());
413 OUString aCertDigest;
414 svl::crypto::SignatureMethodAlgorithm eAlgorithmID
415 = svl::crypto::SignatureMethodAlgorithm::RSA;
416 if (auto pCertificate = dynamic_cast<xmlsecurity::Certificate*>(xCert.get()))
418 OUStringBuffer aBuffer;
419 comphelper::Base64::encode(aBuffer, pCertificate->getSHA256Thumbprint());
420 aCertDigest = aBuffer.makeStringAndClear();
422 eAlgorithmID = pCertificate->getSignatureMethodAlgorithm();
424 else
425 SAL_WARN("xmlsecurity.helper",
426 "XCertificate implementation without an xmlsecurity::Certificate one");
428 maSignatureHelper.SetX509Certificate(nSecurityId, xCert->getIssuerName(), aCertSerial,
429 aStrBuffer.makeStringAndClear(), aCertDigest,
430 eAlgorithmID);
433 const uno::Sequence<uno::Reference<security::XCertificate>> aCertPath
434 = xSecurityContext->getSecurityEnvironment()->buildCertificatePath(xCert);
436 OUStringBuffer aStrBuffer;
437 for (uno::Reference<security::XCertificate> const& rxCertificate : aCertPath)
439 comphelper::Base64::encode(aStrBuffer, rxCertificate->getEncoded());
440 OUString aString = aStrBuffer.makeStringAndClear();
441 maSignatureHelper.AddEncapsulatedX509Certificate(aString);
444 std::vector<OUString> aElements = DocumentSignatureHelper::CreateElementList(
445 mxStore, meSignatureMode, DocumentSignatureAlgorithm::OOo3_2);
447 if (mxScriptingSignatureStream.is())
449 aElements.emplace_back(
450 u"META-INF/"_ustr
451 + DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName());
452 std::sort(aElements.begin(), aElements.end());
455 DocumentSignatureHelper::AppendContentTypes(mxStore, aElements);
457 for (OUString const& rUri : aElements)
459 bool bBinaryMode = !isXML(rUri);
460 maSignatureHelper.AddForSigning(nSecurityId, rUri, bBinaryMode, bAdESCompliant);
463 maSignatureHelper.SetDateTime(nSecurityId, DateTime(DateTime::SYSTEM));
464 maSignatureHelper.SetDescription(nSecurityId, rDescription);
466 if (!rSignatureLineId.isEmpty())
467 maSignatureHelper.SetSignatureLineId(nSecurityId, rSignatureLineId);
469 if (xValidGraphic.is())
470 maSignatureHelper.SetSignatureLineValidGraphic(nSecurityId, xValidGraphic);
472 if (xInvalidGraphic.is())
473 maSignatureHelper.SetSignatureLineInvalidGraphic(nSecurityId, xInvalidGraphic);
475 // We open a signature stream in which the existing and the new
476 //signature is written. ImplGetSignatureInformation (later in this function) will
477 //then read the stream and fill maCurrentSignatureInformations. The final signature
478 //is written when the user presses OK. Then only maCurrentSignatureInformation and
479 //a sax writer are used to write the information.
480 SignatureStreamHelper aStreamHelper
481 = ImplOpenSignatureStream(embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, true);
483 if (aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
485 uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream,
486 uno::UNO_QUERY_THROW);
487 uno::Reference<xml::sax::XWriter> xSaxWriter
488 = maSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream);
490 // Export old signatures...
491 uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter,
492 uno::UNO_QUERY_THROW);
493 std::size_t nInfos = maCurrentSignatureInformations.size();
494 for (std::size_t n = 0; n < nInfos; n++)
495 XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n],
496 bAdESCompliant);
498 // Create a new one...
499 maSignatureHelper.CreateAndWriteSignature(xDocumentHandler, bAdESCompliant);
501 // That's it...
502 XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);
504 else
506 // OOXML
508 // Handle relations.
509 maSignatureHelper.EnsureSignaturesRelation(mxStore, /*bAdd=*/true);
510 // Old signatures + the new one.
511 int nSignatureCount = maCurrentSignatureInformations.size() + 1;
512 maSignatureHelper.ExportSignatureRelations(aStreamHelper.xSignatureStorage,
513 nSignatureCount);
515 // Export old signatures.
516 for (std::size_t i = 0; i < maCurrentSignatureInformations.size(); ++i)
517 maSignatureHelper.ExportOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage,
518 maCurrentSignatureInformations[i], i + 1);
520 // Create a new signature.
521 maSignatureHelper.CreateAndWriteOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage,
522 nSignatureCount);
524 // Flush objects.
525 uno::Reference<embed::XTransactedObject> xTransact(aStreamHelper.xSignatureStorage,
526 uno::UNO_QUERY);
527 xTransact->commit();
528 uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream,
529 uno::UNO_QUERY);
530 xOutputStream->closeOutput();
532 uno::Reference<io::XTempFile> xTempFile(aStreamHelper.xSignatureStream, uno::UNO_QUERY);
533 SAL_INFO("xmlsecurity.helper",
534 "DocumentSignatureManager::add temporary storage at " << xTempFile->getUri());
537 maSignatureHelper.EndMission();
538 return true;
541 void DocumentSignatureManager::remove(sal_uInt16 nPosition)
543 if (!mxStore.is())
545 // Something not ZIP based, try PDF.
546 uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
547 if (!PDFSignatureHelper::RemoveSignature(xInputStream, nPosition))
549 SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::RemoveSignature() failed");
550 return;
553 // Only erase when the removal was successful, it may fail for PDF.
554 // Also, erase the requested and all following signatures, as PDF signatures are always chained.
555 maCurrentSignatureInformations.erase(maCurrentSignatureInformations.begin() + nPosition,
556 maCurrentSignatureInformations.end());
557 return;
560 maCurrentSignatureInformations.erase(maCurrentSignatureInformations.begin() + nPosition);
562 // Export all other signatures...
563 SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
564 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, /*bTempStream=*/true);
566 if (aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
568 uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream,
569 uno::UNO_QUERY_THROW);
570 uno::Reference<xml::sax::XWriter> xSaxWriter
571 = maSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream);
573 uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter,
574 uno::UNO_QUERY_THROW);
575 std::size_t nInfos = maCurrentSignatureInformations.size();
576 for (std::size_t n = 0; n < nInfos; ++n)
577 XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n],
578 false /* ??? */);
580 XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);
582 else
584 // OOXML
586 // Handle relations.
587 int nSignatureCount = maCurrentSignatureInformations.size();
588 maSignatureHelper.ExportSignatureRelations(aStreamHelper.xSignatureStorage,
589 nSignatureCount);
591 // Export old signatures.
592 for (std::size_t i = 0; i < maCurrentSignatureInformations.size(); ++i)
593 maSignatureHelper.ExportOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage,
594 maCurrentSignatureInformations[i], i + 1);
596 // Flush objects.
597 uno::Reference<embed::XTransactedObject> xTransact(aStreamHelper.xSignatureStorage,
598 uno::UNO_QUERY);
599 xTransact->commit();
600 uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream,
601 uno::UNO_QUERY);
602 xOutputStream->closeOutput();
604 uno::Reference<io::XTempFile> xTempFile(aStreamHelper.xSignatureStream, uno::UNO_QUERY);
605 SAL_INFO("xmlsecurity.helper", "DocumentSignatureManager::remove: temporary storage is at "
606 << xTempFile->getUri());
610 void DocumentSignatureManager::read(bool bUseTempStream, bool bCacheLastSignature)
612 maCurrentSignatureInformations.clear();
614 if (mxStore.is())
616 // ZIP-based: ODF or OOXML.
617 maSignatureHelper.StartMission(mxSecurityContext);
619 SignatureStreamHelper aStreamHelper
620 = ImplOpenSignatureStream(embed::ElementModes::READ, bUseTempStream);
621 if (aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML
622 && aStreamHelper.xSignatureStream.is())
624 uno::Reference<io::XInputStream> xInputStream(aStreamHelper.xSignatureStream,
625 uno::UNO_QUERY);
626 maSignatureHelper.ReadAndVerifySignature(xInputStream);
628 else if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML
629 && aStreamHelper.xSignatureStorage.is())
630 maSignatureHelper.ReadAndVerifySignatureStorage(aStreamHelper.xSignatureStorage,
631 bCacheLastSignature);
632 maSignatureHelper.EndMission();
634 // this parses the XML independently from ImplVerifySignatures() - check
635 // certificates here too ...
636 for (auto const& it : maSignatureHelper.GetSignatureInformations())
638 if (!it.X509Datas.empty())
640 uno::Reference<xml::crypto::XSecurityEnvironment> const xSecEnv(
641 getSecurityEnvironment());
642 getSignatureHelper().CheckAndUpdateSignatureInformation(xSecEnv, it);
646 maCurrentSignatureInformations = maSignatureHelper.GetSignatureInformations();
648 else
650 // Something not ZIP based, try PDF.
651 uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
652 if (getPDFSignatureHelper().ReadAndVerifySignature(xInputStream))
653 maCurrentSignatureInformations = getPDFSignatureHelper().GetSignatureInformations();
657 void DocumentSignatureManager::write(bool bXAdESCompliantIfODF)
659 if (!mxStore.is())
661 // Something not ZIP based, assume PDF, which is written directly in add() already.
662 return;
665 // Export all other signatures...
666 SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
667 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, false);
669 if (aStreamHelper.xSignatureStream.is()
670 && aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
672 // ODF
673 uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream,
674 uno::UNO_QUERY);
675 uno::Reference<xml::sax::XWriter> xSaxWriter
676 = maSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream);
678 uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter,
679 uno::UNO_QUERY_THROW);
680 std::size_t nInfos = maCurrentSignatureInformations.size();
681 for (std::size_t n = 0; n < nInfos; ++n)
682 XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n],
683 bXAdESCompliantIfODF);
685 XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);
687 else if (aStreamHelper.xSignatureStorage.is()
688 && aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML)
690 // OOXML
691 std::size_t nSignatureCount = maCurrentSignatureInformations.size();
692 maSignatureHelper.ExportSignatureContentTypes(mxStore, nSignatureCount);
693 if (nSignatureCount > 0)
694 maSignatureHelper.ExportSignatureRelations(aStreamHelper.xSignatureStorage,
695 nSignatureCount);
696 else
698 // Removing all signatures: then need to remove the signature relation as well.
699 maSignatureHelper.EnsureSignaturesRelation(mxStore, /*bAdd=*/false);
700 // Also remove the whole signature sub-storage: release our read-write reference + remove the element.
701 aStreamHelper = SignatureStreamHelper();
702 mxStore->removeElement(u"_xmlsignatures"_ustr);
705 for (std::size_t i = 0; i < nSignatureCount; ++i)
706 maSignatureHelper.ExportOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage,
707 maCurrentSignatureInformations[i], i + 1);
710 // If stream was not provided, we are responsible for committing it...
711 if (!mxSignatureStream.is() && aStreamHelper.xSignatureStorage.is())
713 uno::Reference<embed::XTransactedObject> xTrans(aStreamHelper.xSignatureStorage,
714 uno::UNO_QUERY);
715 xTrans->commit();
719 uno::Reference<xml::crypto::XSecurityEnvironment> DocumentSignatureManager::getSecurityEnvironment()
721 return mxSecurityContext.is() ? mxSecurityContext->getSecurityEnvironment()
722 : uno::Reference<xml::crypto::XSecurityEnvironment>();
725 uno::Reference<xml::crypto::XSecurityEnvironment>
726 DocumentSignatureManager::getGpgSecurityEnvironment()
728 return mxGpgSecurityContext.is() ? mxGpgSecurityContext->getSecurityEnvironment()
729 : uno::Reference<xml::crypto::XSecurityEnvironment>();
732 uno::Reference<xml::crypto::XXMLSecurityContext> const&
733 DocumentSignatureManager::getSecurityContext() const
735 return mxSecurityContext;
738 uno::Reference<xml::crypto::XXMLSecurityContext> const&
739 DocumentSignatureManager::getGpgSecurityContext() const
741 return mxGpgSecurityContext;
744 void DocumentSignatureManager::setModel(const uno::Reference<frame::XModel>& xModel)
746 mxModel = xModel;
749 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */