Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / xmlsecurity / source / dialogs / digitalsignaturesdialog.cxx
blob0a306a008db052a666434bb551dcc439527d2bcd
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>
29 #include <comphelper/diagnose_ex.hxx>
31 #include <com/sun/star/embed/XStorage.hpp>
32 #include <com/sun/star/embed/ElementModes.hpp>
33 #include <com/sun/star/embed/StorageFormats.hpp>
34 #include <com/sun/star/container/XNameAccess.hpp>
35 #include <com/sun/star/lang/XComponent.hpp>
36 #include <com/sun/star/security/NoPasswordException.hpp>
37 #include <com/sun/star/lang/DisposedException.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/security/CertificateValidity.hpp>
40 #include <com/sun/star/packages/WrongPasswordException.hpp>
41 #include <com/sun/star/security/CertificateKind.hpp>
42 #include <com/sun/star/security/XDocumentDigitalSignatures.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/lok.hxx>
60 #include <comphelper/xmlsechelper.hxx>
61 #include <comphelper/processfactory.hxx>
63 #include <utility>
64 #include <vcl/weld.hxx>
65 #include <vcl/svapp.hxx>
66 #include <unotools/configitem.hxx>
68 #ifdef _WIN32
69 #include <o3tl/char16_t2wchar_t.hxx>
70 #include <systools/win32/comtools.hxx>
71 #include <Shlobj.h>
72 #endif
74 using namespace comphelper;
75 using namespace css::security;
76 using namespace css::uno;
77 using namespace css;
79 namespace
81 class SaveODFItem: public utl::ConfigItem
83 private:
84 sal_Int16 m_nODF;
86 virtual void ImplCommit() override;
88 public:
89 virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
90 SaveODFItem();
91 //See group ODF in Common.xcs
92 bool isLessODF1_2() const
94 return m_nODF < 3;
98 void SaveODFItem::ImplCommit() {}
99 void SaveODFItem::Notify( const css::uno::Sequence< OUString >& ) {}
101 SaveODFItem::SaveODFItem(): utl::ConfigItem("Office.Common/Save"), m_nODF(0)
103 OUString sDef("ODF/DefaultVersion");
104 Sequence< css::uno::Any > aValues = GetProperties( Sequence<OUString>(&sDef,1) );
105 if ( aValues.getLength() != 1)
106 throw uno::RuntimeException(
107 "[xmlsecurity] Could not open property Office.Common/Save/ODF/DefaultVersion",
108 nullptr);
110 sal_Int16 nTmp = 0;
111 if ( !(aValues[0] >>= nTmp) )
112 throw uno::RuntimeException(
113 "[xmlsecurity]SaveODFItem::SaveODFItem(): Wrong Type!",
114 nullptr );
116 m_nODF = nTmp;
120 DigitalSignaturesDialog::DigitalSignaturesDialog(
121 weld::Window* pParent,
122 const uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode,
123 bool bReadOnly, OUString sODFVersion, bool bHasDocumentSignature)
124 : GenericDialogController(pParent, "xmlsec/ui/digitalsignaturesdialog.ui", "DigitalSignaturesDialog")
125 , maSignatureManager(rxCtx, eMode)
126 , m_sODFVersion (std::move(sODFVersion))
127 , m_bHasDocumentSignature(bHasDocumentSignature)
128 , m_bWarningShowSignMacro(false)
129 , m_xHintDocFT(m_xBuilder->weld_label("dochint"))
130 , m_xHintBasicFT(m_xBuilder->weld_label("macrohint"))
131 , m_xHintPackageFT(m_xBuilder->weld_label("packagehint"))
132 , m_xSignaturesLB(m_xBuilder->weld_tree_view("signatures"))
133 , m_xSigsValidImg(m_xBuilder->weld_image("validimg"))
134 , m_xSigsValidFI(m_xBuilder->weld_label("validft"))
135 , m_xSigsInvalidImg(m_xBuilder->weld_image("invalidimg"))
136 , m_xSigsInvalidFI(m_xBuilder->weld_label("invalidft"))
137 , m_xSigsNotvalidatedImg(m_xBuilder->weld_image("notvalidatedimg"))
138 , m_xSigsNotvalidatedFI(m_xBuilder->weld_label("notvalidatedft"))
139 , m_xSigsOldSignatureImg(m_xBuilder->weld_image("oldsignatureimg"))
140 , m_xSigsOldSignatureFI(m_xBuilder->weld_label("oldsignatureft"))
141 , m_xAdESCompliantCB(m_xBuilder->weld_check_button("adescompliant"))
142 , m_xViewBtn(m_xBuilder->weld_button("view"))
143 , m_xAddBtn(m_xBuilder->weld_button("sign"))
144 , m_xRemoveBtn(m_xBuilder->weld_button("remove"))
145 , m_xStartCertMgrBtn(m_xBuilder->weld_button("start_certmanager"))
146 , m_xCloseBtn(m_xBuilder->weld_button("close"))
148 m_bAdESCompliant = !DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
150 auto nControlWidth = m_xSignaturesLB->get_approximate_digit_width() * 105;
151 m_xSignaturesLB->set_size_request(nControlWidth, m_xSignaturesLB->get_height_rows(10));
153 // Give the first column 6 percent, try to distribute the rest equally.
154 std::vector<int> aWidths;
155 aWidths.push_back(6*nControlWidth/100);
156 auto nColWidth = (nControlWidth - aWidths[0]) / 4;
157 aWidths.push_back(nColWidth);
158 aWidths.push_back(nColWidth);
159 aWidths.push_back(nColWidth);
160 m_xSignaturesLB->set_column_fixed_widths(aWidths);
162 mbVerifySignatures = true;
163 mbSignaturesChanged = false;
165 m_xSignaturesLB->connect_changed( LINK( this, DigitalSignaturesDialog, SignatureHighlightHdl ) );
166 m_xSignaturesLB->connect_row_activated( LINK( this, DigitalSignaturesDialog, SignatureSelectHdl ) );
168 m_xAdESCompliantCB->connect_toggled( LINK( this, DigitalSignaturesDialog, AdESCompliantCheckBoxHdl ) );
169 m_xAdESCompliantCB->set_active(m_bAdESCompliant);
171 m_xViewBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, ViewButtonHdl ) );
172 m_xViewBtn->set_sensitive(false);
174 m_xAddBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, AddButtonHdl ) );
175 if ( bReadOnly )
176 m_xAddBtn->set_sensitive(false);
178 m_xRemoveBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, RemoveButtonHdl ) );
179 m_xRemoveBtn->set_sensitive(false);
181 m_xStartCertMgrBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, CertMgrButtonHdl ) );
183 m_xCloseBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, OKButtonHdl) );
185 switch( maSignatureManager.getSignatureMode() )
187 case DocumentSignatureMode::Content:
188 m_xHintDocFT->show();
189 break;
190 case DocumentSignatureMode::Macros:
191 m_xHintBasicFT->show();
192 break;
193 case DocumentSignatureMode::Package:
194 m_xHintPackageFT->show();
195 break;
198 if (comphelper::LibreOfficeKit::isActive())
200 m_xAddBtn->hide();
201 m_xRemoveBtn->hide();
202 m_xStartCertMgrBtn->hide();
206 DigitalSignaturesDialog::~DigitalSignaturesDialog()
208 if (m_xViewer)
209 m_xViewer->response(RET_OK);
211 if (m_xInfoBox)
212 m_xInfoBox->response(RET_OK);
215 bool DigitalSignaturesDialog::Init()
217 bool bInit = maSignatureManager.init();
219 SAL_WARN_IF( !bInit, "xmlsecurity.dialogs", "Error initializing security context!" );
221 if ( bInit )
223 maSignatureManager.getSignatureHelper().SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog, StartVerifySignatureHdl ) );
226 return bInit;
229 void DigitalSignaturesDialog::SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore )
231 if (!rxStore.is())
233 // PDF supports AdES.
234 m_bAdESCompliant = true;
235 m_xAdESCompliantCB->set_active(m_bAdESCompliant);
236 return;
239 maSignatureManager.setStore(rxStore);
240 maSignatureManager.getSignatureHelper().SetStorage( maSignatureManager.getStore(), m_sODFVersion);
243 void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream )
245 maSignatureManager.setSignatureStream(rxStream);
248 bool DigitalSignaturesDialog::canAddRemove()
250 //FIXME: this func needs some cleanup, such as real split between
251 //'canAdd' and 'canRemove' case
252 bool ret = true;
254 uno::Reference<container::XNameAccess> xNameAccess = maSignatureManager.getStore();
255 if (xNameAccess.is() && xNameAccess->hasByName("[Content_Types].xml"))
256 // It's always possible to append an OOXML signature.
257 return ret;
259 if (!maSignatureManager.getStore().is())
260 // It's always possible to append a PDF signature.
261 return ret;
263 OSL_ASSERT(maSignatureManager.getStore().is());
264 bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
265 SaveODFItem item;
266 bool bSave1_1 = item.isLessODF1_2();
268 // see specification
269 //cvs: specs/www/appwide/security/Electronic_Signatures_and_Security.sxw
270 //Paragraph 'Behavior with regard to ODF 1.2'
271 //For both, macro and document
272 if ( (!bSave1_1 && bDoc1_1) || (bSave1_1 && bDoc1_1) )
274 //#4
275 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
276 VclMessageType::Warning, VclButtonsType::Ok,
277 XsResId(STR_XMLSECDLG_OLD_ODF_FORMAT)));
278 xBox->run();
279 ret = false;
282 //As of OOo 3.2 the document signature includes in macrosignatures.xml. That is
283 //adding a macro signature will break an existing document signature.
284 //The sfx2 will remove the documentsignature when the user adds a macro signature
285 if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Macros
286 && ret)
288 if (m_bHasDocumentSignature && !m_bWarningShowSignMacro)
290 //The warning says that the document signatures will be removed if the user
291 //continues. He can then either press 'OK' or 'NO'
292 //It the user presses 'Add' or 'Remove' several times then, then the warning
293 //is shown every time until the user presses 'OK'. From then on, the warning
294 //is not displayed anymore as long as the signatures dialog is alive.
295 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
296 VclMessageType::Question, VclButtonsType::YesNo,
297 XsResId(STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN)));
298 if (xBox->run() == RET_NO)
299 ret = false;
300 else
301 m_bWarningShowSignMacro = true;
305 return ret;
308 bool DigitalSignaturesDialog::canAdd()
310 return canAddRemove();
313 bool DigitalSignaturesDialog::canRemove()
315 bool bRet = true;
317 if ( maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content )
319 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
320 VclMessageType::Question, VclButtonsType::YesNo,
321 XsResId(STR_XMLSECDLG_QUERY_REALLYREMOVE)));
322 short nDlgRet = xBox->run();
323 bRet = ( nDlgRet == RET_YES );
326 return (bRet && canAddRemove());
329 void DigitalSignaturesDialog::beforeRun()
331 // Verify Signatures and add certificates to ListBox...
332 mbVerifySignatures = true;
333 ImplGetSignatureInformations(/*bUseTempStream=*/false, /*bCacheLastSignature=*/true);
334 ImplFillSignaturesBox();
336 // FIXME: Disable the "Use XAdES compliant signatures" checkbox if it is irrelevant. If it is
337 // enabled, set its initial state based on existing signatures, if any.
339 // If it is OOXML, the checkbox is irrelevant.
341 // How to find out here whether it is OOXML? I don't want to create a SignatureStreamHelper and
342 // check its nStorageFormat as that seems overly complicated and seems to have weird indirect
343 // consequences, as I noticed when I tried to use DocumentSignatureManager::IsXAdESRelevant()
344 // (which now is in #if 0).
346 if (!maSignatureManager.getCurrentSignatureInformations().empty())
348 // If the document has only SHA-1 signatures we probably want it to stay that way?
351 // Only verify once, content will not change.
352 // But for refreshing signature information, StartVerifySignatureHdl will be called after each add/remove
353 mbVerifySignatures = false;
356 short DigitalSignaturesDialog::run()
358 beforeRun();
359 return GenericDialogController::run();
362 IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureHighlightHdl, weld::TreeView&, void)
364 bool bSel = m_xSignaturesLB->get_selected_index() != -1;
365 m_xViewBtn->set_sensitive( bSel );
366 if ( m_xAddBtn->get_sensitive() ) // not read only
367 m_xRemoveBtn->set_sensitive( bSel );
370 IMPL_LINK_NOARG(DigitalSignaturesDialog, OKButtonHdl, weld::Button&, void)
372 if (mbSignaturesChanged)
373 maSignatureManager.write(m_bAdESCompliant);
375 m_xDialog->response(RET_OK);
378 IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureSelectHdl, weld::TreeView&, bool)
380 ImplShowSignaturesDetails();
381 return true;
384 IMPL_LINK_NOARG(DigitalSignaturesDialog, AdESCompliantCheckBoxHdl, weld::Toggleable&, void)
386 m_bAdESCompliant = m_xAdESCompliantCB->get_active();
389 IMPL_LINK_NOARG(DigitalSignaturesDialog, ViewButtonHdl, weld::Button&, void)
391 ImplShowSignaturesDetails();
394 IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, weld::Button&, void)
396 if( ! canAdd())
397 return;
400 std::vector<uno::Reference<xml::crypto::XXMLSecurityContext>> xSecContexts
402 maSignatureManager.getSecurityContext()
404 // Gpg signing is only possible with ODF >= 1.2 documents
405 if (DocumentSignatureHelper::CanSignWithGPG(maSignatureManager.getStore(), m_sODFVersion))
406 xSecContexts.push_back(maSignatureManager.getGpgSecurityContext());
408 CertificateChooser aChooser(m_xDialog.get(), std::move(xSecContexts), UserAction::Sign);
409 if (aChooser.run() == RET_OK)
411 sal_Int32 nSecurityId;
412 if (!maSignatureManager.add(aChooser.GetSelectedCertificates()[0], aChooser.GetSelectedSecurityContext(),
413 aChooser.GetDescription(), nSecurityId, m_bAdESCompliant))
414 return;
415 mbSignaturesChanged = true;
417 xml::crypto::SecurityOperationStatus nStatus = xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
419 if (maSignatureManager.getStore().is())
420 // In the PDF case the signature information is only available after parsing.
421 nStatus = maSignatureManager.getSignatureHelper().GetSignatureInformation( nSecurityId ).nStatus;
423 if ( nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED )
425 mbSignaturesChanged = true;
427 // Can't simply remember current information, need parsing for getting full information :(
428 // We need to verify the signatures again, otherwise the status in the signature information
429 // will not contain
430 // SecurityOperationStatus_OPERATION_SUCCEEDED
431 mbVerifySignatures = true;
432 ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
433 ImplFillSignaturesBox();
437 catch ( uno::Exception& )
439 TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "adding a signature!" );
440 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
441 VclMessageType::Error, VclButtonsType::Ok,
442 XsResId(STR_XMLSECDLG_SIGNING_FAILED)));
443 xBox->run();
444 // Don't keep invalid entries...
445 ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
446 ImplFillSignaturesBox();
450 IMPL_LINK_NOARG(DigitalSignaturesDialog, RemoveButtonHdl, weld::Button&, void)
452 if (!canRemove())
453 return;
454 int nEntry = m_xSignaturesLB->get_selected_index();
455 if (nEntry == -1)
456 return;
460 sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32();
461 maSignatureManager.remove(nSelected);
463 mbSignaturesChanged = true;
465 ImplFillSignaturesBox();
467 catch ( uno::Exception& )
469 TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "Exception while removing a signature!" );
470 // Don't keep invalid entries...
471 ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/true);
472 ImplFillSignaturesBox();
476 IMPL_LINK_NOARG(DigitalSignaturesDialog, CertMgrButtonHdl, weld::Button&, void)
478 #ifdef _WIN32
479 // FIXME: call GpgME::dirInfo("bindir") somewhere in
480 // SecurityEnvironmentGpg or whatnot
481 // FIXME: perhaps poke GpgME for uiserver, and hope it returns something useful?
482 static const std::u16string_view aGUIServers[] = { u"Gpg4win\\kleopatra.exe",
483 u"Gpg4win\\bin\\kleopatra.exe",
484 u"GNU\\GnuPG\\kleopatra.exe",
485 u"GNU\\GnuPG\\launch-gpa.exe",
486 u"GNU\\GnuPG\\gpa.exe",
487 u"GnuPG\\bin\\gpa.exe",
488 u"GNU\\GnuPG\\bin\\kleopatra.exe",
489 u"GNU\\GnuPG\\bin\\launch-gpa.exe",
490 u"GNU\\GnuPG\\bin\\gpa.exe",
492 static const OUString aPath = [] {
493 sal::systools::CoTaskMemAllocated<wchar_t> sPath;
494 HRESULT hr
495 = SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, KF_FLAG_DEFAULT, nullptr, &sPath);
496 if (SUCCEEDED(hr))
497 return OUString(o3tl::toU(sPath));
498 return OUString();
499 }();
500 if (aPath.isEmpty())
501 return;
502 #else
503 static const std::u16string_view aGUIServers[] = { u"kleopatra", u"seahorse", u"gpa", u"kgpg" };
504 const char* cPath = getenv("PATH");
505 if (!cPath)
506 return;
507 OUString aPath(cPath, strlen(cPath), osl_getThreadTextEncoding());
508 #endif
510 OUString sFoundGUIServer, sExecutable;
512 for ( auto const &rServer : aGUIServers )
514 osl::FileBase::RC searchError = osl::File::searchFileURL(OUString(rServer), aPath, sFoundGUIServer );
515 if (searchError == osl::FileBase::E_None)
517 osl::File::getSystemPathFromFileURL( sFoundGUIServer, sExecutable );
518 break;
523 if ( !sExecutable.isEmpty() )
525 uno::Reference< uno::XComponentContext > xContext =
526 ::comphelper::getProcessComponentContext();
527 uno::Reference< css::system::XSystemShellExecute > xSystemShell(
528 css::system::SystemShellExecute::create(xContext) );
530 xSystemShell->execute( sExecutable, OUString(),
531 css::system::SystemShellExecuteFlags::DEFAULTS );
533 else
535 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
536 VclMessageType::Info, VclButtonsType::Ok,
537 XsResId(STR_XMLSECDLG_NO_CERT_MANAGER)));
538 xInfoBox->run();
542 IMPL_LINK_NOARG(DigitalSignaturesDialog, StartVerifySignatureHdl, LinkParamNone*, bool)
544 return mbVerifySignatures;
547 void DigitalSignaturesDialog::ImplFillSignaturesBox()
549 m_xSignaturesLB->clear();
551 size_t nInfos = maSignatureManager.getCurrentSignatureInformations().size();
552 size_t nValidSigs = 0, nValidCerts = 0;
553 bool bAllNewSignatures = true;
554 bool bSomePartial = false;
556 if( nInfos )
558 for( size_t n = 0; n < nInfos; ++n )
560 DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm(
561 m_sODFVersion, maSignatureManager.getCurrentSignatureInformations()[n]);
562 std::vector< OUString > aElementsToBeVerified;
563 if (maSignatureManager.getStore().is())
564 aElementsToBeVerified = DocumentSignatureHelper::CreateElementList(maSignatureManager.getStore(), maSignatureManager.getSignatureMode(), mode);
566 const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[n];
567 uno::Reference< css::security::XCertificate > xCert = getCertificate(rInfo);
569 OUString aSubject;
570 OUString aIssuer;
571 OUString aDateTimeStr;
572 OUString aDescription;
573 OUString aType;
575 bool bCertValid = false;
576 if( xCert.is() )
578 //check the validity of the cert
579 try {
580 sal_Int32 certResult = getSecurityEnvironmentForCertificate(xCert)->verifyCertificate(xCert,
581 Sequence<uno::Reference<security::XCertificate> >());
583 bCertValid = certResult == css::security::CertificateValidity::VALID;
584 if ( bCertValid )
585 nValidCerts++;
587 } catch (css::uno::SecurityException& ) {
588 OSL_FAIL("Verification of certificate failed");
589 bCertValid = false;
592 aSubject = xmlsec::GetContentPart( xCert->getSubjectName(), xCert->getCertificateKind() );
593 aIssuer = xmlsec::GetContentPart( xCert->getIssuerName(), xCert->getCertificateKind() );
595 else if (!rInfo.ouGpgCertificate.isEmpty())
597 // In case we don't have the gpg key locally, get some data from the document
598 aIssuer = rInfo.ouGpgOwner;
601 aDateTimeStr = utl::GetDateTimeString( rInfo.stDateTime );
602 aDescription = rInfo.ouDescription;
604 // Decide type string.
605 if (maSignatureManager.getStore().is())
607 // OpenPGP
608 if (!rInfo.ouGpgCertificate.isEmpty())
609 aType = "OpenPGP";
610 // XML based: XAdES or not.
611 else if (rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->CertDigest.isEmpty())
612 aType = "XAdES";
613 else
614 aType = "XML-DSig";
616 else
618 // Assume PDF: PAdES or not.
619 if (rInfo.bHasSigningCertificate)
620 aType = "PAdES";
621 else
622 aType = "PDF";
625 bool bSigValid = rInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
627 if ( bSigValid )
629 if (maSignatureManager.getStore().is())
631 // ZIP based.
632 bSigValid = DocumentSignatureHelper::checkIfAllFilesAreSigned(
633 aElementsToBeVerified, rInfo, mode);
635 else
637 // Assume PDF.
638 bSigValid = !rInfo.bPartialDocumentSignature;
641 if( bSigValid )
642 nValidSigs++;
643 else
645 bSomePartial = true;
649 OUString sImage;
650 if (!bSigValid)
652 sImage = BMP_SIG_INVALID;
654 else if (!bCertValid)
656 sImage = BMP_SIG_NOT_VALIDATED;
658 //Check if the signature is a "old" document signature, that is, which was created
659 //by a version of OOo previous to 3.2
660 // If there is no storage, then it's pointless to check storage
661 // stream references.
662 else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content
663 && (maSignatureManager.getStore().is() && !DocumentSignatureHelper::isOOo3_2_Signature(
664 maSignatureManager.getCurrentSignatureInformations()[n])))
666 sImage = BMP_SIG_NOT_VALIDATED;
667 bAllNewSignatures = false;
669 else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content
670 && DocumentSignatureHelper::isOOo3_2_Signature(
671 maSignatureManager.getCurrentSignatureInformations()[n]))
673 sImage = BMP_SIG_VALID;
675 else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Macros)
677 sImage = BMP_SIG_VALID;
680 m_xSignaturesLB->insert(nullptr, n, nullptr, nullptr,
681 &sImage, nullptr, false, nullptr);
682 m_xSignaturesLB->set_text(n, aSubject, 1);
683 m_xSignaturesLB->set_text(n, aIssuer, 2);
684 m_xSignaturesLB->set_text(n, aDateTimeStr, 3);
685 m_xSignaturesLB->set_text(n, aDescription, 4);
686 m_xSignaturesLB->set_text(n, aType, 5);
687 m_xSignaturesLB->set_id(n, OUString::number(n)); // misuse user data as index
691 bool bAllSigsValid = (nValidSigs == nInfos);
692 bool bAllCertsValid = (nValidCerts == nInfos);
693 bool bShowValidState = nInfos && (bAllSigsValid && bAllCertsValid && bAllNewSignatures);
695 m_xSigsValidImg->set_visible( bShowValidState);
696 m_xSigsValidFI->set_visible( bShowValidState );
698 bool bShowInvalidState = nInfos && !bAllSigsValid;
700 m_xSigsInvalidImg->set_visible( bShowInvalidState && !bSomePartial);
701 m_xSigsInvalidFI->set_visible( bShowInvalidState && !bSomePartial);
703 bool bShowNotValidatedState = nInfos && bAllSigsValid && !bAllCertsValid;
705 m_xSigsNotvalidatedImg->set_visible(bShowNotValidatedState);
706 m_xSigsNotvalidatedFI->set_visible(bShowNotValidatedState);
708 //bAllNewSignatures is always true if we are not in document mode
709 bool bShowOldSignature = nInfos && bAllSigsValid && bAllCertsValid && !bAllNewSignatures;
710 m_xSigsOldSignatureImg->set_visible(bShowOldSignature || bSomePartial);
711 m_xSigsOldSignatureFI->set_visible(bShowOldSignature || bSomePartial);
713 SignatureHighlightHdl(*m_xSignaturesLB);
716 uno::Reference<security::XCertificate> DigitalSignaturesDialog::getCertificate(const SignatureInformation& rInfo)
718 uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureManager.getSecurityEnvironment();
719 uno::Reference<xml::crypto::XSecurityEnvironment> xGpgSecEnv = maSignatureManager.getGpgSecurityEnvironment();
720 uno::Reference<security::XCertificate> xCert;
722 //First we try to get the certificate which is embedded in the XML Signature
723 if (xSecEnv.is() && rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->X509Certificate.isEmpty())
724 xCert = xSecEnv->createCertificateFromAscii(rInfo.GetSigningCertificate()->X509Certificate);
725 else {
726 //There must be an embedded certificate because we use it to get the
727 //issuer name. We cannot use /Signature/KeyInfo/X509Data/X509IssuerName
728 //because it could be modified by an attacker. The issuer is displayed
729 //in the digital signature dialog.
730 //Comparing the X509IssuerName with the one from the X509Certificate in order
731 //to find out if the X509IssuerName was modified does not work. See #i62684
732 SAL_WARN( "xmlsecurity.dialogs", "Could not find embedded certificate!");
735 //In case there is no embedded certificate we try to get it from a local store
736 if (!xCert.is() && xSecEnv.is() && rInfo.GetSigningCertificate())
738 xCert = xSecEnv->getCertificate(rInfo.GetSigningCertificate()->X509IssuerName,
739 xmlsecurity::numericStringToBigInteger(rInfo.GetSigningCertificate()->X509SerialNumber));
741 if (!xCert.is() && xGpgSecEnv.is() && !rInfo.ouGpgKeyID.isEmpty())
742 xCert = xGpgSecEnv->getCertificate( rInfo.ouGpgKeyID, xmlsecurity::numericStringToBigInteger(u"") );
744 SAL_WARN_IF( !xCert.is(), "xmlsecurity.dialogs", "Certificate not found and can't be created!" );
746 return xCert;
749 uno::Reference<xml::crypto::XSecurityEnvironment> DigitalSignaturesDialog::getSecurityEnvironmentForCertificate(const uno::Reference<security::XCertificate>& xCert)
751 if (xCert->getCertificateKind() == CertificateKind_OPENPGP)
752 return maSignatureManager.getGpgSecurityEnvironment();
753 else if (xCert->getCertificateKind() == CertificateKind_X509)
754 return maSignatureManager.getSecurityEnvironment();
756 throw RuntimeException("Unknown certificate kind");
759 //If bUseTempStream is true then the temporary signature stream is used.
760 //Otherwise the real signature stream is used.
761 void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature)
763 maSignatureManager.read(bUseTempStream, bCacheLastSignature);
764 mbVerifySignatures = false;
767 void DigitalSignaturesDialog::ImplShowSignaturesDetails()
769 int nEntry = m_xSignaturesLB->get_selected_index();
770 if (nEntry == -1)
771 return;
773 sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32();
774 const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[ nSelected ];
775 uno::Reference<security::XCertificate> xCert = getCertificate(rInfo);
777 if ( xCert.is() )
779 if (m_xViewer)
780 m_xViewer->response(RET_OK);
782 uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = getSecurityEnvironmentForCertificate(xCert);
783 m_xViewer = std::make_shared<CertificateViewer>(m_xDialog.get(), xSecEnv, xCert, false, nullptr);
784 weld::DialogController::runAsync(m_xViewer, [this] (sal_Int32) { m_xViewer = nullptr; });
786 else
788 if (m_xInfoBox)
789 m_xInfoBox->response(RET_OK);
791 m_xInfoBox = std::shared_ptr<weld::MessageDialog>(Application::CreateMessageDialog(m_xDialog.get(),
792 VclMessageType::Info, VclButtonsType::Ok,
793 XsResId(STR_XMLSECDLG_NO_CERT_FOUND)));
794 m_xInfoBox->runAsync(m_xInfoBox, [this] (sal_Int32) { m_xInfoBox = nullptr; });
798 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */