nss: upgrade to release 3.73
[LibreOffice.git] / xmlsecurity / source / dialogs / digitalsignaturesdialog.cxx
blob818cd4862fff34311b47e4f653f01363f7727184
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 <sal/config.h>
22 #include <string_view>
24 #include <digitalsignaturesdialog.hxx>
25 #include <certificatechooser.hxx>
26 #include <certificateviewer.hxx>
27 #include <biginteger.hxx>
28 #include <sax/tools/converter.hxx>
30 #include <com/sun/star/embed/XStorage.hpp>
31 #include <com/sun/star/embed/ElementModes.hpp>
32 #include <com/sun/star/embed/StorageFormats.hpp>
33 #include <com/sun/star/container/XNameAccess.hpp>
34 #include <com/sun/star/lang/XComponent.hpp>
35 #include <com/sun/star/security/NoPasswordException.hpp>
36 #include <com/sun/star/lang/DisposedException.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/security/CertificateValidity.hpp>
39 #include <com/sun/star/packages/WrongPasswordException.hpp>
40 #include <com/sun/star/security/CertificateKind.hpp>
41 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
42 #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
43 #include <com/sun/star/system/SystemShellExecute.hpp>
44 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
45 #include <com/sun/star/system/SystemShellExecuteException.hpp>
47 #include <osl/file.hxx>
48 #include <rtl/ustrbuf.hxx>
49 #include <rtl/uri.hxx>
50 #include <sal/log.hxx>
52 #include <tools/date.hxx>
53 #include <tools/time.hxx>
54 #include <unotools/datetime.hxx>
56 #include <bitmaps.hlst>
57 #include <strings.hrc>
58 #include <resourcemanager.hxx>
59 #include <comphelper/xmlsechelper.hxx>
60 #include <comphelper/processfactory.hxx>
62 #include <vcl/weld.hxx>
63 #include <vcl/svapp.hxx>
64 #include <unotools/configitem.hxx>
66 #ifdef _WIN32
67 #include <o3tl/char16_t2wchar_t.hxx>
68 #include <prewin.h>
69 #include <Shlobj.h>
70 #endif
72 using namespace comphelper;
73 using namespace css::security;
74 using namespace css::uno;
75 using namespace css;
77 namespace
79 class SaveODFItem: public utl::ConfigItem
81 private:
82 sal_Int16 m_nODF;
84 virtual void ImplCommit() override;
86 public:
87 virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
88 SaveODFItem();
89 //See group ODF in Common.xcs
90 bool isLessODF1_2() const
92 return m_nODF < 3;
96 void SaveODFItem::ImplCommit() {}
97 void SaveODFItem::Notify( const css::uno::Sequence< OUString >& ) {}
99 SaveODFItem::SaveODFItem(): utl::ConfigItem("Office.Common/Save"), m_nODF(0)
101 OUString sDef("ODF/DefaultVersion");
102 Sequence< css::uno::Any > aValues = GetProperties( Sequence<OUString>(&sDef,1) );
103 if ( aValues.getLength() != 1)
104 throw uno::RuntimeException(
105 "[xmlsecurity] Could not open property Office.Common/Save/ODF/DefaultVersion",
106 nullptr);
108 sal_Int16 nTmp = 0;
109 if ( !(aValues[0] >>= nTmp) )
110 throw uno::RuntimeException(
111 "[xmlsecurity]SaveODFItem::SaveODFItem(): Wrong Type!",
112 nullptr );
114 m_nODF = nTmp;
118 DigitalSignaturesDialog::DigitalSignaturesDialog(
119 weld::Window* pParent,
120 const uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode,
121 bool bReadOnly, const OUString& sODFVersion, bool bHasDocumentSignature)
122 : GenericDialogController(pParent, "xmlsec/ui/digitalsignaturesdialog.ui", "DigitalSignaturesDialog")
123 , maSignatureManager(rxCtx, eMode)
124 , m_sODFVersion (sODFVersion)
125 , m_bHasDocumentSignature(bHasDocumentSignature)
126 , m_bWarningShowSignMacro(false)
127 , m_xHintDocFT(m_xBuilder->weld_label("dochint"))
128 , m_xHintBasicFT(m_xBuilder->weld_label("macrohint"))
129 , m_xHintPackageFT(m_xBuilder->weld_label("packagehint"))
130 , m_xSignaturesLB(m_xBuilder->weld_tree_view("signatures"))
131 , m_xSigsValidImg(m_xBuilder->weld_image("validimg"))
132 , m_xSigsValidFI(m_xBuilder->weld_label("validft"))
133 , m_xSigsInvalidImg(m_xBuilder->weld_image("invalidimg"))
134 , m_xSigsInvalidFI(m_xBuilder->weld_label("invalidft"))
135 , m_xSigsNotvalidatedImg(m_xBuilder->weld_image("notvalidatedimg"))
136 , m_xSigsNotvalidatedFI(m_xBuilder->weld_label("notvalidatedft"))
137 , m_xSigsOldSignatureImg(m_xBuilder->weld_image("oldsignatureimg"))
138 , m_xSigsOldSignatureFI(m_xBuilder->weld_label("oldsignatureft"))
139 , m_xAdESCompliantCB(m_xBuilder->weld_check_button("adescompliant"))
140 , m_xViewBtn(m_xBuilder->weld_button("view"))
141 , m_xAddBtn(m_xBuilder->weld_button("sign"))
142 , m_xRemoveBtn(m_xBuilder->weld_button("remove"))
143 , m_xStartCertMgrBtn(m_xBuilder->weld_button("start_certmanager"))
144 , m_xCloseBtn(m_xBuilder->weld_button("close"))
146 m_bAdESCompliant = !DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
148 auto nControlWidth = m_xSignaturesLB->get_approximate_digit_width() * 105;
149 m_xSignaturesLB->set_size_request(nControlWidth, m_xSignaturesLB->get_height_rows(10));
151 // Give the first column 6 percent, try to distribute the rest equally.
152 std::vector<int> aWidths;
153 aWidths.push_back(6*nControlWidth/100);
154 auto nColWidth = (nControlWidth - aWidths[0]) / 4;
155 aWidths.push_back(nColWidth);
156 aWidths.push_back(nColWidth);
157 aWidths.push_back(nColWidth);
158 m_xSignaturesLB->set_column_fixed_widths(aWidths);
160 mbVerifySignatures = true;
161 mbSignaturesChanged = false;
163 m_xSignaturesLB->connect_changed( LINK( this, DigitalSignaturesDialog, SignatureHighlightHdl ) );
164 m_xSignaturesLB->connect_row_activated( LINK( this, DigitalSignaturesDialog, SignatureSelectHdl ) );
166 m_xAdESCompliantCB->connect_toggled( LINK( this, DigitalSignaturesDialog, AdESCompliantCheckBoxHdl ) );
167 m_xAdESCompliantCB->set_active(m_bAdESCompliant);
169 m_xViewBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, ViewButtonHdl ) );
170 m_xViewBtn->set_sensitive(false);
172 m_xAddBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, AddButtonHdl ) );
173 if ( bReadOnly )
174 m_xAddBtn->set_sensitive(false);
176 m_xRemoveBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, RemoveButtonHdl ) );
177 m_xRemoveBtn->set_sensitive(false);
179 m_xStartCertMgrBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, CertMgrButtonHdl ) );
181 m_xCloseBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, OKButtonHdl) );
183 switch( maSignatureManager.getSignatureMode() )
185 case DocumentSignatureMode::Content:
186 m_xHintDocFT->show();
187 break;
188 case DocumentSignatureMode::Macros:
189 m_xHintBasicFT->show();
190 break;
191 case DocumentSignatureMode::Package:
192 m_xHintPackageFT->show();
193 break;
197 DigitalSignaturesDialog::~DigitalSignaturesDialog()
201 bool DigitalSignaturesDialog::Init()
203 bool bInit = maSignatureManager.init();
205 SAL_WARN_IF( !bInit, "xmlsecurity.dialogs", "Error initializing security context!" );
207 if ( bInit )
209 maSignatureManager.getSignatureHelper().SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog, StartVerifySignatureHdl ) );
212 return bInit;
215 void DigitalSignaturesDialog::SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore )
217 if (!rxStore.is())
219 // PDF supports AdES.
220 m_bAdESCompliant = true;
221 m_xAdESCompliantCB->set_active(m_bAdESCompliant);
222 return;
225 maSignatureManager.setStore(rxStore);
226 maSignatureManager.getSignatureHelper().SetStorage( maSignatureManager.getStore(), m_sODFVersion);
229 void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream )
231 maSignatureManager.setSignatureStream(rxStream);
234 bool DigitalSignaturesDialog::canAddRemove()
236 //FIXME: this func needs some cleanup, such as real split between
237 //'canAdd' and 'canRemove' case
238 bool ret = true;
240 uno::Reference<container::XNameAccess> xNameAccess = maSignatureManager.getStore();
241 if (xNameAccess.is() && xNameAccess->hasByName("[Content_Types].xml"))
242 // It's always possible to append an OOXML signature.
243 return ret;
245 if (!maSignatureManager.getStore().is())
246 // It's always possible to append a PDF signature.
247 return ret;
249 OSL_ASSERT(maSignatureManager.getStore().is());
250 bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
251 SaveODFItem item;
252 bool bSave1_1 = item.isLessODF1_2();
254 // see specification
255 //cvs: specs/www/appwide/security/Electronic_Signatures_and_Security.sxw
256 //Paragraph 'Behavior with regard to ODF 1.2'
257 //For both, macro and document
258 if ( (!bSave1_1 && bDoc1_1) || (bSave1_1 && bDoc1_1) )
260 //#4
261 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
262 VclMessageType::Warning, VclButtonsType::Ok,
263 XsResId(STR_XMLSECDLG_OLD_ODF_FORMAT)));
264 xBox->run();
265 ret = false;
268 //As of OOo 3.2 the document signature includes in macrosignatures.xml. That is
269 //adding a macro signature will break an existing document signature.
270 //The sfx2 will remove the documentsignature when the user adds a macro signature
271 if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Macros
272 && ret)
274 if (m_bHasDocumentSignature && !m_bWarningShowSignMacro)
276 //The warning says that the document signatures will be removed if the user
277 //continues. He can then either press 'OK' or 'NO'
278 //It the user presses 'Add' or 'Remove' several times then, then the warning
279 //is shown every time until the user presses 'OK'. From then on, the warning
280 //is not displayed anymore as long as the signatures dialog is alive.
281 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
282 VclMessageType::Question, VclButtonsType::YesNo,
283 XsResId(STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN)));
284 if (xBox->run() == RET_NO)
285 ret = false;
286 else
287 m_bWarningShowSignMacro = true;
291 return ret;
294 bool DigitalSignaturesDialog::canAdd()
296 return canAddRemove();
299 bool DigitalSignaturesDialog::canRemove()
301 bool bRet = true;
303 if ( maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content )
305 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
306 VclMessageType::Question, VclButtonsType::YesNo,
307 XsResId(STR_XMLSECDLG_QUERY_REALLYREMOVE)));
308 short nDlgRet = xBox->run();
309 bRet = ( nDlgRet == RET_YES );
312 return (bRet && canAddRemove());
315 short DigitalSignaturesDialog::run()
317 // Verify Signatures and add certificates to ListBox...
318 mbVerifySignatures = true;
319 ImplGetSignatureInformations(/*bUseTempStream=*/false, /*bCacheLastSignature=*/true);
320 ImplFillSignaturesBox();
322 // FIXME: Disable the "Use XAdES compliant signatures" checkbox if it is irrelevant. If it is
323 // enabled, set its initial state based on existing signatures, if any.
325 // If it is OOXML, the checkbox is irrelevant.
327 // How to find out here whether it is OOXML? I don't want to create a SignatureStreamHelper and
328 // check its nStorageFormat as that seems overly complicated and seems to have weird indirect
329 // consequences, as I noticed when I tried to use DocumentSignatureManager::IsXAdESRelevant()
330 // (which now is in #if 0).
332 if (!maSignatureManager.getCurrentSignatureInformations().empty())
334 // If the document has only SHA-1 signatures we probably want it to stay that way?
337 // Only verify once, content will not change.
338 // But for refreshing signature information, StartVerifySignatureHdl will be called after each add/remove
339 mbVerifySignatures = false;
341 return GenericDialogController::run();
344 IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureHighlightHdl, weld::TreeView&, void)
346 bool bSel = m_xSignaturesLB->get_selected_index() != -1;
347 m_xViewBtn->set_sensitive( bSel );
348 if ( m_xAddBtn->get_sensitive() ) // not read only
349 m_xRemoveBtn->set_sensitive( bSel );
352 IMPL_LINK_NOARG(DigitalSignaturesDialog, OKButtonHdl, weld::Button&, void)
354 if (mbSignaturesChanged)
355 maSignatureManager.write(m_bAdESCompliant);
357 m_xDialog->response(RET_OK);
360 IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureSelectHdl, weld::TreeView&, bool)
362 ImplShowSignaturesDetails();
363 return true;
366 IMPL_LINK_NOARG(DigitalSignaturesDialog, AdESCompliantCheckBoxHdl, weld::ToggleButton&, void)
368 m_bAdESCompliant = m_xAdESCompliantCB->get_active();
371 IMPL_LINK_NOARG(DigitalSignaturesDialog, ViewButtonHdl, weld::Button&, void)
373 ImplShowSignaturesDetails();
376 IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, weld::Button&, void)
378 if( ! canAdd())
379 return;
382 std::vector<uno::Reference<xml::crypto::XXMLSecurityContext>> xSecContexts;
383 xSecContexts.push_back(maSignatureManager.getSecurityContext());
384 // Gpg signing is only possible with ODF >= 1.2 documents
385 if (DocumentSignatureHelper::CanSignWithGPG(maSignatureManager.getStore(), m_sODFVersion))
386 xSecContexts.push_back(maSignatureManager.getGpgSecurityContext());
388 CertificateChooser aChooser(m_xDialog.get(), xSecContexts, UserAction::Sign);
389 if (aChooser.run() == RET_OK)
391 sal_Int32 nSecurityId;
392 if (!maSignatureManager.add(aChooser.GetSelectedCertificates()[0], aChooser.GetSelectedSecurityContext(),
393 aChooser.GetDescription(), nSecurityId, m_bAdESCompliant))
394 return;
395 mbSignaturesChanged = true;
397 xml::crypto::SecurityOperationStatus nStatus = xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
399 if (maSignatureManager.getStore().is())
400 // In the PDF case the signature information is only available after parsing.
401 nStatus = maSignatureManager.getSignatureHelper().GetSignatureInformation( nSecurityId ).nStatus;
403 if ( nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED )
405 mbSignaturesChanged = true;
407 // Can't simply remember current information, need parsing for getting full information :(
408 // We need to verify the signatures again, otherwise the status in the signature information
409 // will not contain
410 // SecurityOperationStatus_OPERATION_SUCCEEDED
411 mbVerifySignatures = true;
412 ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
413 ImplFillSignaturesBox();
417 catch ( uno::Exception& )
419 OSL_FAIL( "Exception while adding a signature!" );
420 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
421 VclMessageType::Error, VclButtonsType::Ok,
422 XsResId(STR_XMLSECDLG_SIGNING_FAILED)));
423 xBox->run();
424 // Don't keep invalid entries...
425 ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
426 ImplFillSignaturesBox();
430 IMPL_LINK_NOARG(DigitalSignaturesDialog, RemoveButtonHdl, weld::Button&, void)
432 if (!canRemove())
433 return;
434 int nEntry = m_xSignaturesLB->get_selected_index();
435 if (nEntry == -1)
436 return;
440 sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32();
441 maSignatureManager.remove(nSelected);
443 mbSignaturesChanged = true;
445 ImplFillSignaturesBox();
447 catch ( uno::Exception& )
449 OSL_FAIL( "Exception while removing a signature!" );
450 // Don't keep invalid entries...
451 ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/true);
452 ImplFillSignaturesBox();
456 IMPL_LINK_NOARG(DigitalSignaturesDialog, CertMgrButtonHdl, weld::Button&, void)
458 #ifdef _WIN32
459 // FIXME: call GpgME::dirInfo("bindir") somewhere in
460 // SecurityEnvironmentGpg or whatnot
461 // FIXME: perhaps poke GpgME for uiserver, and hope it returns something useful?
462 static const std::u16string_view aGUIServers[] = { u"Gpg4win\\kleopatra.exe",
463 u"Gpg4win\\bin\\kleopatra.exe",
464 u"GNU\\GnuPG\\kleopatra.exe",
465 u"GNU\\GnuPG\\launch-gpa.exe",
466 u"GNU\\GnuPG\\gpa.exe",
467 u"GnuPG\\bin\\gpa.exe",
468 u"GNU\\GnuPG\\bin\\kleopatra.exe",
469 u"GNU\\GnuPG\\bin\\launch-gpa.exe",
470 u"GNU\\GnuPG\\bin\\gpa.exe",
472 static const OUString aPath = [] {
473 OUString sRet;
474 PWSTR sPath = nullptr;
475 HRESULT hr
476 = SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, KF_FLAG_DEFAULT, nullptr, &sPath);
477 if (SUCCEEDED(hr))
479 sRet = o3tl::toU(sPath);
480 CoTaskMemFree(sPath);
482 return sRet;
483 }();
484 if (aPath.isEmpty())
485 return;
486 #else
487 static const std::u16string_view aGUIServers[] = { u"kleopatra", u"seahorse", u"gpa", u"kgpg" };
488 const char* cPath = getenv("PATH");
489 if (!cPath)
490 return;
491 OUString aPath(cPath, strlen(cPath), osl_getThreadTextEncoding());
492 #endif
494 OUString sFoundGUIServer, sExecutable;
496 for ( auto const &rServer : aGUIServers )
498 osl::FileBase::RC searchError = osl::File::searchFileURL(rServer, aPath, sFoundGUIServer );
499 if (searchError == osl::FileBase::E_None)
501 osl::File::getSystemPathFromFileURL( sFoundGUIServer, sExecutable );
502 break;
507 if ( !sExecutable.isEmpty() )
509 uno::Reference< uno::XComponentContext > xContext =
510 ::comphelper::getProcessComponentContext();
511 uno::Reference< css::system::XSystemShellExecute > xSystemShell(
512 css::system::SystemShellExecute::create(xContext) );
514 xSystemShell->execute( sExecutable, OUString(),
515 css::system::SystemShellExecuteFlags::DEFAULTS );
517 else
519 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
520 VclMessageType::Info, VclButtonsType::Ok,
521 XsResId(STR_XMLSECDLG_NO_CERT_MANAGER)));
522 xInfoBox->run();
526 IMPL_LINK_NOARG(DigitalSignaturesDialog, StartVerifySignatureHdl, LinkParamNone*, bool)
528 return mbVerifySignatures;
531 void DigitalSignaturesDialog::ImplFillSignaturesBox()
533 m_xSignaturesLB->clear();
535 size_t nInfos = maSignatureManager.getCurrentSignatureInformations().size();
536 size_t nValidSigs = 0, nValidCerts = 0;
537 bool bAllNewSignatures = true;
538 bool bSomePartial = false;
540 if( nInfos )
542 for( size_t n = 0; n < nInfos; ++n )
544 DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm(
545 m_sODFVersion, maSignatureManager.getCurrentSignatureInformations()[n]);
546 std::vector< OUString > aElementsToBeVerified;
547 if (maSignatureManager.getStore().is())
548 aElementsToBeVerified = DocumentSignatureHelper::CreateElementList(maSignatureManager.getStore(), maSignatureManager.getSignatureMode(), mode);
550 const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[n];
551 uno::Reference< css::security::XCertificate > xCert = getCertificate(rInfo);
553 OUString aSubject;
554 OUString aIssuer;
555 OUString aDateTimeStr;
556 OUString aDescription;
557 OUString aType;
559 bool bCertValid = false;
560 if( xCert.is() )
562 //check the validity of the cert
563 try {
564 sal_Int32 certResult = getSecurityEnvironmentForCertificate(xCert)->verifyCertificate(xCert,
565 Sequence<uno::Reference<security::XCertificate> >());
567 bCertValid = certResult == css::security::CertificateValidity::VALID;
568 if ( bCertValid )
569 nValidCerts++;
571 } catch (css::uno::SecurityException& ) {
572 OSL_FAIL("Verification of certificate failed");
573 bCertValid = false;
576 aSubject = xmlsec::GetContentPart( xCert->getSubjectName(), xCert->getCertificateKind() );
577 aIssuer = xmlsec::GetContentPart( xCert->getIssuerName(), xCert->getCertificateKind() );
579 else if (!rInfo.ouGpgCertificate.isEmpty())
581 // In case we don't have the gpg key locally, get some data from the document
582 aIssuer = rInfo.ouGpgOwner;
585 aDateTimeStr = utl::GetDateTimeString( rInfo.stDateTime );
586 aDescription = rInfo.ouDescription;
588 // Decide type string.
589 if (maSignatureManager.getStore().is())
591 // OpenPGP
592 if (!rInfo.ouGpgCertificate.isEmpty())
593 aType = "OpenPGP";
594 // XML based: XAdES or not.
595 else if (rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->CertDigest.isEmpty())
596 aType = "XAdES";
597 else
598 aType = "XML-DSig";
600 else
602 // Assume PDF: PAdES or not.
603 if (rInfo.bHasSigningCertificate)
604 aType = "PAdES";
605 else
606 aType = "PDF";
609 bool bSigValid = rInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
611 if ( bSigValid )
613 if (maSignatureManager.getStore().is())
615 // ZIP based.
616 bSigValid = DocumentSignatureHelper::checkIfAllFilesAreSigned(
617 aElementsToBeVerified, rInfo, mode);
619 else
621 // Assume PDF.
622 bSigValid = !rInfo.bPartialDocumentSignature;
625 if( bSigValid )
626 nValidSigs++;
627 else
629 bSomePartial = true;
633 OUString sImage;
634 if (!bSigValid)
636 sImage = BMP_SIG_INVALID;
638 else if (!bCertValid)
640 sImage = BMP_SIG_NOT_VALIDATED;
642 //Check if the signature is a "old" document signature, that is, which was created
643 //by a version of OOo previous to 3.2
644 // If there is no storage, then it's pointless to check storage
645 // stream references.
646 else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content
647 && (maSignatureManager.getStore().is() && !DocumentSignatureHelper::isOOo3_2_Signature(
648 maSignatureManager.getCurrentSignatureInformations()[n])))
650 sImage = BMP_SIG_NOT_VALIDATED;
651 bAllNewSignatures = false;
653 else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content
654 && DocumentSignatureHelper::isOOo3_2_Signature(
655 maSignatureManager.getCurrentSignatureInformations()[n]))
657 sImage = BMP_SIG_VALID;
659 else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Macros)
661 sImage = BMP_SIG_VALID;
664 m_xSignaturesLB->insert(nullptr, n, nullptr, nullptr,
665 &sImage, nullptr, false, nullptr);
666 m_xSignaturesLB->set_text(n, aSubject, 1);
667 m_xSignaturesLB->set_text(n, aIssuer, 2);
668 m_xSignaturesLB->set_text(n, aDateTimeStr, 3);
669 m_xSignaturesLB->set_text(n, aDescription, 4);
670 m_xSignaturesLB->set_text(n, aType, 5);
671 m_xSignaturesLB->set_id(n, OUString::number(n)); // misuse user data as index
675 bool bAllSigsValid = (nValidSigs == nInfos);
676 bool bAllCertsValid = (nValidCerts == nInfos);
677 bool bShowValidState = nInfos && (bAllSigsValid && bAllCertsValid && bAllNewSignatures);
679 m_xSigsValidImg->set_visible( bShowValidState);
680 m_xSigsValidFI->set_visible( bShowValidState );
682 bool bShowInvalidState = nInfos && !bAllSigsValid;
684 m_xSigsInvalidImg->set_visible( bShowInvalidState && !bSomePartial);
685 m_xSigsInvalidFI->set_visible( bShowInvalidState && !bSomePartial);
687 bool bShowNotValidatedState = nInfos && bAllSigsValid && !bAllCertsValid;
689 m_xSigsNotvalidatedImg->set_visible(bShowNotValidatedState);
690 m_xSigsNotvalidatedFI->set_visible(bShowNotValidatedState);
692 //bAllNewSignatures is always true if we are not in document mode
693 bool bShowOldSignature = nInfos && bAllSigsValid && bAllCertsValid && !bAllNewSignatures;
694 m_xSigsOldSignatureImg->set_visible(bShowOldSignature || bSomePartial);
695 m_xSigsOldSignatureFI->set_visible(bShowOldSignature || bSomePartial);
697 SignatureHighlightHdl(*m_xSignaturesLB);
700 uno::Reference<security::XCertificate> DigitalSignaturesDialog::getCertificate(const SignatureInformation& rInfo)
702 uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureManager.getSecurityEnvironment();
703 uno::Reference<xml::crypto::XSecurityEnvironment> xGpgSecEnv = maSignatureManager.getGpgSecurityEnvironment();
704 uno::Reference<security::XCertificate> xCert;
706 //First we try to get the certificate which is embedded in the XML Signature
707 if (xSecEnv.is() && rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->X509Certificate.isEmpty())
708 xCert = xSecEnv->createCertificateFromAscii(rInfo.GetSigningCertificate()->X509Certificate);
709 else {
710 //There must be an embedded certificate because we use it to get the
711 //issuer name. We cannot use /Signature/KeyInfo/X509Data/X509IssuerName
712 //because it could be modified by an attacker. The issuer is displayed
713 //in the digital signature dialog.
714 //Comparing the X509IssuerName with the one from the X509Certificate in order
715 //to find out if the X509IssuerName was modified does not work. See #i62684
716 SAL_WARN( "xmlsecurity.dialogs", "Could not find embedded certificate!");
719 //In case there is no embedded certificate we try to get it from a local store
720 if (!xCert.is() && xSecEnv.is() && rInfo.GetSigningCertificate())
722 xCert = xSecEnv->getCertificate(rInfo.GetSigningCertificate()->X509IssuerName,
723 xmlsecurity::numericStringToBigInteger(rInfo.GetSigningCertificate()->X509SerialNumber));
725 if (!xCert.is() && xGpgSecEnv.is() && !rInfo.ouGpgKeyID.isEmpty())
726 xCert = xGpgSecEnv->getCertificate( rInfo.ouGpgKeyID, xmlsecurity::numericStringToBigInteger("") );
728 SAL_WARN_IF( !xCert.is(), "xmlsecurity.dialogs", "Certificate not found and can't be created!" );
730 return xCert;
733 uno::Reference<xml::crypto::XSecurityEnvironment> DigitalSignaturesDialog::getSecurityEnvironmentForCertificate(const uno::Reference<security::XCertificate>& xCert)
735 if (xCert->getCertificateKind() == CertificateKind_OPENPGP)
736 return maSignatureManager.getGpgSecurityEnvironment();
737 else if (xCert->getCertificateKind() == CertificateKind_X509)
738 return maSignatureManager.getSecurityEnvironment();
740 throw RuntimeException("Unknown certificate kind");
743 //If bUseTempStream is true then the temporary signature stream is used.
744 //Otherwise the real signature stream is used.
745 void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature)
747 maSignatureManager.read(bUseTempStream, bCacheLastSignature);
748 mbVerifySignatures = false;
751 void DigitalSignaturesDialog::ImplShowSignaturesDetails()
753 int nEntry = m_xSignaturesLB->get_selected_index();
754 if (nEntry == -1)
755 return;
757 sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32();
758 const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[ nSelected ];
759 uno::Reference<security::XCertificate> xCert = getCertificate(rInfo);
761 if ( xCert.is() )
763 uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = getSecurityEnvironmentForCertificate(xCert);
764 CertificateViewer aViewer(m_xDialog.get(), xSecEnv, xCert, false, nullptr);
765 aViewer.run();
767 else
769 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
770 VclMessageType::Info, VclButtonsType::Ok,
771 XsResId(STR_XMLSECDLG_NO_CERT_FOUND)));
772 xInfoBox->run();
776 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */