Bump version to 5.0-14
[LibreOffice.git] / xmlsecurity / source / dialogs / digitalsignaturesdialog.cxx
blob14bc8bd959e021638def2ca5f03db9fc24b0ba1f
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 <xmlsecurity/digitalsignaturesdialog.hxx>
21 #include <xmlsecurity/certificatechooser.hxx>
22 #include <xmlsecurity/certificateviewer.hxx>
23 #include <xmlsecurity/biginteger.hxx>
24 #include <sax/tools/converter.hxx>
26 #include <com/sun/star/embed/XStorage.hpp>
27 #include <com/sun/star/embed/ElementModes.hpp>
28 #include <com/sun/star/io/XSeekable.hpp>
29 #include <com/sun/star/io/XTruncate.hpp>
30 #include <com/sun/star/io/TempFile.hpp>
31 #include <com/sun/star/embed/XTransactedObject.hpp>
32 #include <com/sun/star/container/XNameAccess.hpp>
33 #include <com/sun/star/lang/XComponent.hpp>
34 #include <com/sun/star/security/NoPasswordException.hpp>
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/security/CertificateValidity.hpp>
38 #include <com/sun/star/packages/WrongPasswordException.hpp>
39 #include <com/sun/star/security/SerialNumberAdapter.hpp>
40 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
41 #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
42 #include <com/sun/star/packages/manifest/ManifestReader.hpp>
45 #include <rtl/ustrbuf.hxx>
46 #include <rtl/uri.hxx>
48 #include <tools/date.hxx>
49 #include <tools/time.hxx>
50 #include <svtools/treelistentry.hxx>
52 #include "dialogs.hrc"
53 #include "digitalsignaturesdialog.hrc"
54 #include "helpids.hrc"
55 #include "resourcemanager.hxx"
57 #include <vcl/layout.hxx>
58 #include <unotools/configitem.hxx>
60 using namespace css::security;
61 using namespace css::uno;
62 using namespace css;
64 namespace
66 class SaveODFItem: public utl::ConfigItem
68 private:
69 sal_Int16 m_nODF;
71 virtual void ImplCommit() SAL_OVERRIDE;
73 public:
74 virtual void Notify( const ::com::sun::star::uno::Sequence< OUString >& aPropertyNames ) SAL_OVERRIDE;
75 SaveODFItem();
76 //See group ODF in Common.xcs
77 bool isLessODF1_2()
79 return m_nODF < 3;
83 void SaveODFItem::ImplCommit() {}
84 void SaveODFItem::Notify( const ::com::sun::star::uno::Sequence< OUString >& ) {}
86 SaveODFItem::SaveODFItem(): utl::ConfigItem(OUString(
87 "Office.Common/Save")), m_nODF(0)
89 OUString sDef("ODF/DefaultVersion");
90 Sequence< css::uno::Any > aValues = GetProperties( Sequence<OUString>(&sDef,1) );
91 if ( aValues.getLength() == 1)
93 sal_Int16 nTmp = 0;
94 if ( aValues[0] >>= nTmp )
95 m_nODF = nTmp;
96 else
97 throw uno::RuntimeException(
98 OUString("[xmlsecurity]SaveODFItem::SaveODFItem(): Wrong Type!"),
99 0 );
102 else
103 throw uno::RuntimeException(
104 OUString("[xmlsecurity] Could not open property Office.Common/Save/ODF/DefaultVersion"),
109 /* Using the zip storage, we cannot get the properties "MediaType" and "IsEncrypted"
110 We use the manifest to find out if a file is xml and if it is encrypted.
111 The parameter is an encoded uri. However, the manifest contains paths. Therefore
112 the path is encoded as uri, so they can be compared.
114 bool DigitalSignaturesDialog::isXML(const OUString& rURI )
116 OSL_ASSERT(mxStore.is());
118 bool bIsXML = false;
119 bool bPropsAvailable = false;
120 const OUString sPropFullPath("FullPath");
121 const OUString sPropMediaType("MediaType");
122 const OUString sPropDigest("Digest");
124 for (int i = 0; i < m_manifest.getLength(); i++)
126 const Sequence< css::beans::PropertyValue >& entry = m_manifest[i];
127 OUString sPath, sMediaType;
128 bool bEncrypted = false;
129 for (int j = 0; j < entry.getLength(); j++)
131 const css::beans::PropertyValue & prop = entry[j];
133 if (prop.Name.equals( sPropFullPath ) )
134 prop.Value >>= sPath;
135 else if (prop.Name.equals( sPropMediaType ) )
136 prop.Value >>= sMediaType;
137 else if (prop.Name.equals( sPropDigest ) )
138 bEncrypted = true;
140 if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI, sPath))
142 bIsXML = sMediaType == "text/xml" && ! bEncrypted;
143 bPropsAvailable = true;
144 break;
147 if (!bPropsAvailable)
149 //This would be the case for at least mimetype, META-INF/manifest.xml
150 //META-INF/macrosignatures.xml.
151 //Files can only be encrypted if they are in the manifest.xml.
152 //That is, the current file cannot be encrypted, otherwise bPropsAvailable
153 //would be true.
154 OUString aXMLExt( "XML" );
155 sal_Int32 nSep = rURI.lastIndexOf( '.' );
156 if ( nSep != (-1) )
158 OUString aExt = rURI.copy( nSep+1 );
159 if (aExt.equalsIgnoreAsciiCase(aXMLExt ))
160 bIsXML = true;
163 return bIsXML;
166 DigitalSignaturesDialog::DigitalSignaturesDialog(
167 vcl::Window* pParent,
168 uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode,
169 bool bReadOnly, const OUString& sODFVersion, bool bHasDocumentSignature)
170 : ModalDialog(pParent, "DigitalSignaturesDialog", "xmlsec/ui/digitalsignaturesdialog.ui")
171 , mxCtx(rxCtx)
172 , maSignatureHelper(rxCtx)
173 , meSignatureMode(eMode)
174 , m_sODFVersion (sODFVersion)
175 , m_bHasDocumentSignature(bHasDocumentSignature)
176 , m_bWarningShowSignMacro(false)
178 get(m_pHintDocFT, "dochint");
179 get(m_pHintBasicFT, "macrohint");
180 get(m_pHintPackageFT, "packagehint");
181 get(m_pViewBtn, "view");
182 get(m_pAddBtn, "sign");
183 get(m_pRemoveBtn, "remove");
184 get(m_pCloseBtn, "close");
185 get(m_pSigsValidImg, "validimg");
186 get(m_pSigsValidFI, "validft");
187 get(m_pSigsInvalidImg, "invalidimg");
188 get(m_pSigsInvalidFI, "invalidft");
189 get(m_pSigsNotvalidatedImg, "notvalidatedimg");
190 get(m_pSigsNotvalidatedFI, "notvalidatedft");
191 get(m_pSigsOldSignatureImg, "oldsignatureimg");
192 get(m_pSigsOldSignatureFI, "oldsignatureft");
194 Size aControlSize(275, 109);
195 const long nControlWidth = aControlSize.Width();
196 aControlSize = LogicToPixel(aControlSize, MAP_APPFONT);
197 SvSimpleTableContainer *pSignatures = get<SvSimpleTableContainer>("signatures");
198 pSignatures->set_width_request(aControlSize.Width());
199 pSignatures->set_height_request(aControlSize.Height());
201 m_pSignaturesLB = VclPtr<SvSimpleTable>::Create(*pSignatures);
202 // #i48253# the tablistbox needs its own unique id
203 m_pSignaturesLB->Window::SetUniqueId( HID_XMLSEC_TREE_SIGNATURESDLG );
204 static long aTabs[] = { 4, 0, 6*nControlWidth/100, 36*nControlWidth/100, 74*nControlWidth/100 };
205 m_pSignaturesLB->SetTabs(aTabs);
207 m_pSignaturesLB->InsertHeaderEntry("\t" + get<FixedText>("signed")->GetText() + "\t"
208 + get<FixedText>("issued")->GetText() + "\t" + get<FixedText>("date")->GetText());
210 mbVerifySignatures = true;
211 mbSignaturesChanged = false;
213 m_pSignaturesLB->SetSelectHdl( LINK( this, DigitalSignaturesDialog, SignatureHighlightHdl ) );
214 m_pSignaturesLB->SetDoubleClickHdl( LINK( this, DigitalSignaturesDialog, SignatureSelectHdl ) );
216 m_pViewBtn->SetClickHdl( LINK( this, DigitalSignaturesDialog, ViewButtonHdl ) );
217 m_pViewBtn->Disable();
219 m_pAddBtn->SetClickHdl( LINK( this, DigitalSignaturesDialog, AddButtonHdl ) );
220 if ( bReadOnly )
221 m_pAddBtn->Disable();
223 m_pRemoveBtn->SetClickHdl( LINK( this, DigitalSignaturesDialog, RemoveButtonHdl ) );
224 m_pRemoveBtn->Disable();
226 m_pCloseBtn->SetClickHdl( LINK( this, DigitalSignaturesDialog, OKButtonHdl) );
228 switch( meSignatureMode )
230 case SignatureModeDocumentContent: m_pHintDocFT->Show(); break;
231 case SignatureModeMacros: m_pHintBasicFT->Show(); break;
232 case SignatureModePackage: m_pHintPackageFT->Show(); break;
236 DigitalSignaturesDialog::~DigitalSignaturesDialog()
238 disposeOnce();
241 void DigitalSignaturesDialog::dispose()
243 m_pSignaturesLB.disposeAndClear();
244 m_pHintDocFT.clear();
245 m_pHintBasicFT.clear();
246 m_pHintPackageFT.clear();
247 m_pSigsValidImg.clear();
248 m_pSigsValidFI.clear();
249 m_pSigsInvalidImg.clear();
250 m_pSigsInvalidFI.clear();
251 m_pSigsNotvalidatedImg.clear();
252 m_pSigsNotvalidatedFI.clear();
253 m_pSigsOldSignatureImg.clear();
254 m_pSigsOldSignatureFI.clear();
255 m_pViewBtn.clear();
256 m_pAddBtn.clear();
257 m_pRemoveBtn.clear();
258 m_pCloseBtn.clear();
259 ModalDialog::dispose();
262 bool DigitalSignaturesDialog::Init()
264 bool bInit = maSignatureHelper.Init();
266 DBG_ASSERT( bInit, "Error initializing security context!" );
268 if ( bInit )
270 maSignatureHelper.SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog, StartVerifySignatureHdl ) );
273 return bInit;
276 void DigitalSignaturesDialog::SetStorage( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rxStore )
278 mxStore = rxStore;
279 maSignatureHelper.SetStorage( mxStore, m_sODFVersion);
281 Reference < css::packages::manifest::XManifestReader > xReader =
282 css::packages::manifest::ManifestReader::create(mxCtx);
284 //Get the manifest.xml
285 Reference < css::embed::XStorage > xSubStore(rxStore->openStorageElement(
286 "META-INF", css::embed::ElementModes::READ), UNO_QUERY_THROW);
288 Reference< css::io::XInputStream > xStream(
289 xSubStore->openStreamElement("manifest.xml", css::embed::ElementModes::READ),
290 UNO_QUERY_THROW);
292 m_manifest = xReader->readManifestSequence(xStream);
295 void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream )
297 mxSignatureStream = rxStream;
300 bool DigitalSignaturesDialog::canAddRemove()
302 //m56
303 bool ret = true;
304 OSL_ASSERT(mxStore.is());
305 bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
306 SaveODFItem item;
307 bool bSave1_1 = item.isLessODF1_2();
309 // see specification
310 //cvs: specs/www/appwide/security/Electronic_Signatures_and_Security.sxw
311 //Paragraph 'Behavior with regard to ODF 1.2'
312 //For both, macro and document
313 if ( (!bSave1_1 && bDoc1_1) || (bSave1_1 && bDoc1_1) )
315 //#4
316 ScopedVclPtrInstance< MessageDialog > err(nullptr, XMLSEC_RES(STR_XMLSECDLG_OLD_ODF_FORMAT));
317 err->Execute();
318 ret = false;
321 //As of OOo 3.2 the document signature includes in macrosignatures.xml. That is
322 //adding a macro signature will break an existing document signature.
323 //The sfx2 will remove the documentsignature when the user adds a macro signature
324 if (meSignatureMode == SignatureModeMacros
325 && ret)
327 if (m_bHasDocumentSignature && !m_bWarningShowSignMacro)
329 //The warning says that the document signatures will be removed if the user
330 //continues. He can then either press 'OK' or 'NO'
331 //It the user presses 'Add' or 'Remove' several times then, then the warning
332 //is shown every time until the user presses 'OK'. From then on, the warning
333 //is not displayed anymore as long as the signatures dialog is alive.
334 if (ScopedVclPtr<MessageDialog>::Create(
335 nullptr, XMLSEC_RES(STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN), VCL_MESSAGE_QUESTION, VCL_BUTTONS_YES_NO)->Execute() == RET_NO)
336 ret = false;
337 else
338 m_bWarningShowSignMacro = true;
342 return ret;
345 bool DigitalSignaturesDialog::canAdd()
347 if (canAddRemove())
348 return true;
349 return false;
352 bool DigitalSignaturesDialog::canRemove()
354 if (canAddRemove())
355 return true;
356 return false;
359 short DigitalSignaturesDialog::Execute()
361 // Verify Signatures and add certificates to ListBox...
362 mbVerifySignatures = true;
363 ImplGetSignatureInformations(false);
364 ImplFillSignaturesBox();
366 // Only verify once, content will not change.
367 // But for refreshing signature information, StartVerifySignatureHdl will be called after each add/remove
368 mbVerifySignatures = false;
370 return Dialog::Execute();
373 IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureHighlightHdl)
375 bool bSel = m_pSignaturesLB->FirstSelected();
376 m_pViewBtn->Enable( bSel );
377 if ( m_pAddBtn->IsEnabled() ) // not read only
378 m_pRemoveBtn->Enable( bSel );
380 return 0;
383 IMPL_LINK_NOARG(DigitalSignaturesDialog, OKButtonHdl)
385 // Export all other signatures...
386 SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
387 embed::ElementModes::WRITE|embed::ElementModes::TRUNCATE, false );
388 uno::Reference< io::XOutputStream > xOutputStream(
389 aStreamHelper.xSignatureStream, uno::UNO_QUERY );
390 uno::Reference< com::sun::star::xml::sax::XWriter> xSaxWriter =
391 maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
393 uno::Reference< xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, UNO_QUERY_THROW);
394 size_t nInfos = maCurrentSignatureInformations.size();
395 for( size_t n = 0 ; n < nInfos ; ++n )
396 XMLSignatureHelper::ExportSignature(
397 xDocumentHandler, maCurrentSignatureInformations[ n ] );
399 XMLSignatureHelper::CloseDocumentHandler( xDocumentHandler);
401 // If stream was not provided, we are responsible for committing it....
402 if ( !mxSignatureStream.is() )
404 uno::Reference< embed::XTransactedObject > xTrans(
405 aStreamHelper.xSignatureStorage, uno::UNO_QUERY );
406 xTrans->commit();
409 EndDialog(RET_OK);
410 return 0;
413 IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureSelectHdl)
415 ImplShowSignaturesDetails();
416 return 0;
419 IMPL_LINK_NOARG(DigitalSignaturesDialog, ViewButtonHdl)
421 ImplShowSignaturesDetails();
422 return 0;
425 IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl)
427 if( ! canAdd())
428 return 0;
431 uno::Reference<com::sun::star::xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureHelper.GetSecurityEnvironment();
433 uno::Reference<com::sun::star::security::XSerialNumberAdapter> xSerialNumberAdapter =
434 ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
435 ScopedVclPtrInstance< CertificateChooser > aChooser( this, mxCtx, xSecEnv, maCurrentSignatureInformations );
436 if ( aChooser->Execute() == RET_OK )
438 uno::Reference< ::com::sun::star::security::XCertificate > xCert = aChooser->GetSelectedCertificate();
439 if ( !xCert.is() )
441 SAL_WARN( "xmlsecurity.dialogs", "no certificate selected" );
442 return -1;
444 OUString aCertSerial = xSerialNumberAdapter->toString( xCert->getSerialNumber() );
445 if ( aCertSerial.isEmpty() )
447 OSL_FAIL( "Error in Certificate, problem with serial number!" );
448 return -1;
451 maSignatureHelper.StartMission();
453 sal_Int32 nSecurityId = maSignatureHelper.GetNewSecurityId();
455 OUStringBuffer aStrBuffer;
456 ::sax::Converter::encodeBase64(aStrBuffer, xCert->getEncoded());
458 maSignatureHelper.SetX509Certificate( nSecurityId,
459 xCert->getIssuerName(), aCertSerial,
460 aStrBuffer.makeStringAndClear());
462 std::vector< OUString > aElements =
463 DocumentSignatureHelper::CreateElementList(
464 mxStore, meSignatureMode, OOo3_2Document);
466 sal_Int32 nElements = aElements.size();
467 for ( sal_Int32 n = 0; n < nElements; n++ )
469 bool bBinaryMode = !isXML(aElements[n]);
470 maSignatureHelper.AddForSigning( nSecurityId, aElements[n], aElements[n], bBinaryMode );
473 maSignatureHelper.SetDateTime( nSecurityId, Date( Date::SYSTEM ), tools::Time( tools::Time::SYSTEM ) );
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 an will 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 = ImplOpenSignatureStream(
481 css::embed::ElementModes::WRITE|css::embed::ElementModes::TRUNCATE, true);
482 Reference< css::io::XOutputStream > xOutputStream(
483 aStreamHelper.xSignatureStream, UNO_QUERY_THROW);
484 Reference< css::xml::sax::XWriter> xSaxWriter =
485 maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
487 // Export old signatures...
488 uno::Reference< xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, UNO_QUERY_THROW);
489 size_t nInfos = maCurrentSignatureInformations.size();
490 for ( size_t n = 0; n < nInfos; n++ )
491 XMLSignatureHelper::ExportSignature( xDocumentHandler, maCurrentSignatureInformations[n]);
493 // Create a new one...
494 maSignatureHelper.CreateAndWriteSignature( xDocumentHandler );
496 // That's it...
497 XMLSignatureHelper::CloseDocumentHandler( xDocumentHandler);
499 maSignatureHelper.EndMission();
501 aStreamHelper = SignatureStreamHelper(); // release objects...
503 mbSignaturesChanged = true;
505 sal_Int32 nStatus = maSignatureHelper.GetSignatureInformation( nSecurityId ).nStatus;
507 if ( nStatus == ::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED )
509 mbSignaturesChanged = true;
511 // Can't simply remember current information, need parsing for getting full information :(
512 // We need to verify the signatures again, otherwise the status in the signature information
513 // will not contain
514 // SecurityOperationStatus_OPERATION_SUCCEEDED
515 mbVerifySignatures = true;
516 ImplGetSignatureInformations(true);
517 ImplFillSignaturesBox();
521 catch ( uno::Exception& )
523 OSL_FAIL( "Exception while adding a signature!" );
524 // Don't keep invalid entries...
525 ImplGetSignatureInformations(true);
526 ImplFillSignaturesBox();
529 return 0;
532 IMPL_LINK_NOARG(DigitalSignaturesDialog, RemoveButtonHdl)
534 if (!canRemove())
535 return 0;
536 if( m_pSignaturesLB->FirstSelected() )
540 sal_uInt16 nSelected = (sal_uInt16) reinterpret_cast<sal_uIntPtr>( m_pSignaturesLB->FirstSelected()->GetUserData() );
541 maCurrentSignatureInformations.erase( maCurrentSignatureInformations.begin()+nSelected );
543 // Export all other signatures...
544 SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
545 css::embed::ElementModes::WRITE | css::embed::ElementModes::TRUNCATE, true);
546 Reference< css::io::XOutputStream > xOutputStream(
547 aStreamHelper.xSignatureStream, UNO_QUERY_THROW);
548 Reference< css::xml::sax::XWriter> xSaxWriter =
549 maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
551 uno::Reference< xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, UNO_QUERY_THROW);
552 size_t nInfos = maCurrentSignatureInformations.size();
553 for( size_t n = 0 ; n < nInfos ; ++n )
554 XMLSignatureHelper::ExportSignature( xDocumentHandler, maCurrentSignatureInformations[ n ] );
556 XMLSignatureHelper::CloseDocumentHandler( xDocumentHandler);
558 mbSignaturesChanged = true;
560 aStreamHelper = SignatureStreamHelper(); // release objects...
562 ImplFillSignaturesBox();
564 catch ( uno::Exception& )
566 OSL_FAIL( "Exception while removing a signature!" );
567 // Don't keep invalid entries...
568 ImplGetSignatureInformations(true);
569 ImplFillSignaturesBox();
573 return 0;
576 IMPL_LINK_NOARG(DigitalSignaturesDialog, StartVerifySignatureHdl)
578 return mbVerifySignatures ? 1 : 0;
581 void DigitalSignaturesDialog::ImplFillSignaturesBox()
583 m_pSignaturesLB->Clear();
585 uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment > xSecEnv = maSignatureHelper.GetSecurityEnvironment();
586 uno::Reference<com::sun::star::security::XSerialNumberAdapter> xSerialNumberAdapter =
587 ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
589 uno::Reference< ::com::sun::star::security::XCertificate > xCert;
591 size_t nInfos = maCurrentSignatureInformations.size();
592 size_t nValidSigs = 0, nValidCerts = 0;
593 bool bAllNewSignatures = true;
595 if( nInfos )
597 for( size_t n = 0; n < nInfos; ++n )
599 DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm(
600 m_sODFVersion, maCurrentSignatureInformations[n]);
601 std::vector< OUString > aElementsToBeVerified =
602 DocumentSignatureHelper::CreateElementList(
603 mxStore, meSignatureMode, mode);
605 const SignatureInformation& rInfo = maCurrentSignatureInformations[n];
606 //First we try to get the certificate which is embedded in the XML Signature
607 if (!rInfo.ouX509Certificate.isEmpty())
608 xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate);
609 else {
610 //There must be an embedded certificate because we use it to get the
611 //issuer name. We cannot use /Signature/KeyInfo/X509Data/X509IssuerName
612 //because it could be modified by an attacker. The issuer is displayed
613 //in the digital signature dialog.
614 //Comparing the X509IssuerName with the one from the X509Certificate in order
615 //to find out if the X509IssuerName was modified does not work. See #i62684
616 DBG_ASSERT(false, "Could not find embedded certificate!");
619 //In case there is no embedded certificate we try to get it from a local store
620 //Todo: This probably could be removed, see above.
621 if (!xCert.is())
622 xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xSerialNumberAdapter->toSequence( rInfo.ouX509SerialNumber ) );
624 DBG_ASSERT( xCert.is(), "Certificate not found and can't be created!" );
626 OUString aSubject;
627 OUString aIssuer;
628 OUString aDateTimeStr;
630 bool bSigValid = false;
631 bool bCertValid = false;
632 if( xCert.is() )
634 //check the validity of the cert
635 try {
636 sal_Int32 certResult = xSecEnv->verifyCertificate(xCert,
637 Sequence<css::uno::Reference<css::security::XCertificate> >());
639 bCertValid = certResult == css::security::CertificateValidity::VALID;
640 if ( bCertValid )
641 nValidCerts++;
643 } catch (css::uno::SecurityException& ) {
644 OSL_FAIL("Verification of certificate failed");
645 bCertValid = false;
648 aSubject = XmlSec::GetContentPart( xCert->getSubjectName() );
649 aIssuer = XmlSec::GetContentPart( xCert->getIssuerName() );
650 // String with date and time information (#i20172#)
651 aDateTimeStr = XmlSec::GetDateTimeString( rInfo.stDateTime );
653 bSigValid = ( rInfo.nStatus == ::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED );
655 if ( bSigValid )
657 bSigValid = DocumentSignatureHelper::checkIfAllFilesAreSigned(
658 aElementsToBeVerified, rInfo, mode);
660 if( bSigValid )
661 nValidSigs++;
664 Image aImage;
665 if (!bSigValid)
667 aImage = m_pSigsInvalidImg->GetImage();
669 else if (bSigValid && !bCertValid)
671 aImage = m_pSigsNotvalidatedImg->GetImage();
673 //Check if the signature is a "old" document signature, that is, which was created
674 //by an version of OOo previous to 3.2
675 else if (meSignatureMode == SignatureModeDocumentContent
676 && bSigValid && bCertValid && !DocumentSignatureHelper::isOOo3_2_Signature(
677 maCurrentSignatureInformations[n]))
679 aImage = m_pSigsNotvalidatedImg->GetImage();
680 bAllNewSignatures &= false;
682 else if (meSignatureMode == SignatureModeDocumentContent
683 && bSigValid && bCertValid && DocumentSignatureHelper::isOOo3_2_Signature(
684 maCurrentSignatureInformations[n]))
686 aImage = m_pSigsValidImg->GetImage();
688 else if (meSignatureMode == SignatureModeMacros
689 && bSigValid && bCertValid)
691 aImage = m_pSigsValidImg->GetImage();
694 SvTreeListEntry* pEntry = m_pSignaturesLB->InsertEntry( OUString(), aImage, aImage );
695 m_pSignaturesLB->SetEntryText( aSubject, pEntry, 1 );
696 m_pSignaturesLB->SetEntryText( aIssuer, pEntry, 2 );
697 m_pSignaturesLB->SetEntryText( aDateTimeStr, pEntry, 3 );
698 pEntry->SetUserData( reinterpret_cast<void*>(n) ); // missuse user data as index
702 bool bAllSigsValid = (nValidSigs == nInfos);
703 bool bAllCertsValid = (nValidCerts == nInfos);
704 bool bShowValidState = nInfos && (bAllSigsValid && bAllCertsValid && bAllNewSignatures);
706 m_pSigsValidImg->Show( bShowValidState);
707 m_pSigsValidFI->Show( bShowValidState );
709 bool bShowInvalidState = nInfos && !bAllSigsValid;
711 m_pSigsInvalidImg->Show( bShowInvalidState );
712 m_pSigsInvalidFI->Show( bShowInvalidState );
714 bool bShowNotValidatedState = nInfos && bAllSigsValid && !bAllCertsValid;
716 m_pSigsNotvalidatedImg->Show(bShowNotValidatedState);
717 m_pSigsNotvalidatedFI->Show(bShowNotValidatedState);
719 //bAllNewSignatures is always true if we are not in document mode
720 bool bShowOldSignature = nInfos && bAllSigsValid && bAllCertsValid && !bAllNewSignatures;
721 m_pSigsOldSignatureImg->Show(bShowOldSignature);
722 m_pSigsOldSignatureFI->Show(bShowOldSignature);
724 SignatureHighlightHdl( NULL );
727 //If bUseTempStream is true then the temporary signature stream is used.
728 //Otherwise the real signature stream is used.
729 void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream)
731 maCurrentSignatureInformations.clear();
733 maSignatureHelper.StartMission();
735 SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
736 css::embed::ElementModes::READ, bUseTempStream);
737 if ( aStreamHelper.xSignatureStream.is() )
739 uno::Reference< io::XInputStream > xInputStream( aStreamHelper.xSignatureStream, uno::UNO_QUERY );
740 maSignatureHelper.ReadAndVerifySignature( xInputStream );
742 maSignatureHelper.EndMission();
744 maCurrentSignatureInformations = maSignatureHelper.GetSignatureInformations();
746 mbVerifySignatures = false;
749 void DigitalSignaturesDialog::ImplShowSignaturesDetails()
751 if( m_pSignaturesLB->FirstSelected() )
753 sal_uInt16 nSelected = (sal_uInt16) reinterpret_cast<sal_uIntPtr>( m_pSignaturesLB->FirstSelected()->GetUserData() );
754 const SignatureInformation& rInfo = maCurrentSignatureInformations[ nSelected ];
755 css::uno::Reference<css::xml::crypto::XSecurityEnvironment > xSecEnv =
756 maSignatureHelper.GetSecurityEnvironment();
757 css::uno::Reference<com::sun::star::security::XSerialNumberAdapter> xSerialNumberAdapter =
758 ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
759 // Use Certificate from doc, not from key store
760 uno::Reference< css::security::XCertificate > xCert;
761 if (!rInfo.ouX509Certificate.isEmpty())
762 xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate);
763 //fallback if no certificate is embedded, get if from store
764 if (!xCert.is())
765 xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xSerialNumberAdapter->toSequence( rInfo.ouX509SerialNumber ) );
767 DBG_ASSERT( xCert.is(), "Error getting cCertificate!" );
768 if ( xCert.is() )
770 ScopedVclPtrInstance< CertificateViewer > aViewer( this, maSignatureHelper.GetSecurityEnvironment(), xCert, false );
771 aViewer->Execute();
776 //If bTempStream is true, then a temporary stream is return. If it is false then, the actual
777 //signature stream is used.
778 //Every time the user presses Add a new temporary stream is created.
779 //We keep the temporary stream as member because ImplGetSignatureInformations
780 //will later access the stream to create DocumentSignatureInformation objects
781 //which are stored in maCurrentSignatureInformations.
782 SignatureStreamHelper DigitalSignaturesDialog::ImplOpenSignatureStream(
783 sal_Int32 nStreamOpenMode, bool bTempStream)
785 SignatureStreamHelper aHelper;
786 if (bTempStream)
788 if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE)
790 //We write always into a new temporary stream.
791 mxTempSignatureStream = Reference < css::io::XStream >(css::io::TempFile::create(mxCtx), UNO_QUERY_THROW);
792 aHelper.xSignatureStream = mxTempSignatureStream;
794 else
796 //When we read from the temp stream, then we must have previously
797 //created one.
798 OSL_ASSERT(mxTempSignatureStream.is());
800 aHelper.xSignatureStream = mxTempSignatureStream;
802 else
804 //No temporary stream
805 if (!mxSignatureStream.is())
807 //We may not have a dedicated stream for writing the signature
808 //So we take one directly from the storage
809 //Or DocumentDigitalSignatures::showDocumentContentSignatures was called,
810 //in which case Add/Remove is not allowed. This is done, for example, if the
811 //document is readonly
812 aHelper = DocumentSignatureHelper::OpenSignatureStream(
813 mxStore, nStreamOpenMode, meSignatureMode );
815 else
817 aHelper.xSignatureStream = mxSignatureStream;
821 if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE)
823 css::uno::Reference < css::io::XTruncate > xTruncate(
824 aHelper.xSignatureStream, UNO_QUERY_THROW);
825 DBG_ASSERT( xTruncate.is(), "ImplOpenSignatureStream - Stream does not support xTruncate!" );
826 xTruncate->truncate();
828 else if ( bTempStream || mxSignatureStream.is())
830 //In case we read the signature stream from the storage directly,
831 //which is the case when DocumentDigitalSignatures::showDocumentContentSignatures
832 //then XSeakable is not supported
833 css::uno::Reference < css::io::XSeekable > xSeek(
834 aHelper.xSignatureStream, UNO_QUERY_THROW);
835 DBG_ASSERT( xSeek.is(), "ImplOpenSignatureStream - Stream does not support xSeekable!" );
836 xSeek->seek( 0 );
839 return aHelper;
842 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */