Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / xmlsecurity / source / dialogs / digitalsignaturesdialog.cxx
blob5c1c7daf2785c5d3cd7993f6c1ec97966aa75e14
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 <digitalsignaturesdialog.hxx>
21 #include <certificatechooser.hxx>
22 #include <certificateviewer.hxx>
23 #include <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/embed/StorageFormats.hpp>
29 #include <com/sun/star/container/XNameAccess.hpp>
30 #include <com/sun/star/lang/XComponent.hpp>
31 #include <com/sun/star/security/NoPasswordException.hpp>
32 #include <com/sun/star/lang/DisposedException.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/security/CertificateValidity.hpp>
35 #include <com/sun/star/packages/WrongPasswordException.hpp>
36 #include <com/sun/star/security/CertificateKind.hpp>
37 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
38 #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
39 #include <com/sun/star/system/SystemShellExecute.hpp>
40 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
41 #include <com/sun/star/system/SystemShellExecuteException.hpp>
43 #include <osl/file.hxx>
44 #include <rtl/ustrbuf.hxx>
45 #include <rtl/uri.hxx>
46 #include <sal/log.hxx>
48 #include <tools/date.hxx>
49 #include <tools/time.hxx>
50 #include <unotools/datetime.hxx>
52 #include <bitmaps.hlst>
53 #include <strings.hrc>
54 #include <resourcemanager.hxx>
55 #include <comphelper/xmlsechelper.hxx>
56 #include <comphelper/processfactory.hxx>
58 #include <vcl/weld.hxx>
59 #include <vcl/svapp.hxx>
60 #include <unotools/configitem.hxx>
62 #ifdef _WIN32
63 #include <o3tl/char16_t2wchar_t.hxx>
64 #include <prewin.h>
65 #include <Shlobj.h>
66 #endif
68 using namespace comphelper;
69 using namespace css::security;
70 using namespace css::uno;
71 using namespace css;
73 namespace
75 class SaveODFItem: public utl::ConfigItem
77 private:
78 sal_Int16 m_nODF;
80 virtual void ImplCommit() override;
82 public:
83 virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
84 SaveODFItem();
85 //See group ODF in Common.xcs
86 bool isLessODF1_2() const
88 return m_nODF < 3;
92 void SaveODFItem::ImplCommit() {}
93 void SaveODFItem::Notify( const css::uno::Sequence< OUString >& ) {}
95 SaveODFItem::SaveODFItem(): utl::ConfigItem("Office.Common/Save"), m_nODF(0)
97 OUString sDef("ODF/DefaultVersion");
98 Sequence< css::uno::Any > aValues = GetProperties( Sequence<OUString>(&sDef,1) );
99 if ( aValues.getLength() != 1)
100 throw uno::RuntimeException(
101 "[xmlsecurity] Could not open property Office.Common/Save/ODF/DefaultVersion",
102 nullptr);
104 sal_Int16 nTmp = 0;
105 if ( !(aValues[0] >>= nTmp) )
106 throw uno::RuntimeException(
107 "[xmlsecurity]SaveODFItem::SaveODFItem(): Wrong Type!",
108 nullptr );
110 m_nODF = nTmp;
114 DigitalSignaturesDialog::DigitalSignaturesDialog(
115 weld::Window* pParent,
116 const uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode,
117 bool bReadOnly, const OUString& sODFVersion, bool bHasDocumentSignature)
118 : GenericDialogController(pParent, "xmlsec/ui/digitalsignaturesdialog.ui", "DigitalSignaturesDialog")
119 , maSignatureManager(rxCtx, eMode)
120 , m_sODFVersion (sODFVersion)
121 , m_bHasDocumentSignature(bHasDocumentSignature)
122 , m_bWarningShowSignMacro(false)
123 , m_xHintDocFT(m_xBuilder->weld_label("dochint"))
124 , m_xHintBasicFT(m_xBuilder->weld_label("macrohint"))
125 , m_xHintPackageFT(m_xBuilder->weld_label("packagehint"))
126 , m_xSignaturesLB(m_xBuilder->weld_tree_view("signatures"))
127 , m_xSigsValidImg(m_xBuilder->weld_image("validimg"))
128 , m_xSigsValidFI(m_xBuilder->weld_label("validft"))
129 , m_xSigsInvalidImg(m_xBuilder->weld_image("invalidimg"))
130 , m_xSigsInvalidFI(m_xBuilder->weld_label("invalidft"))
131 , m_xSigsNotvalidatedImg(m_xBuilder->weld_image("notvalidatedimg"))
132 , m_xSigsNotvalidatedFI(m_xBuilder->weld_label("notvalidatedft"))
133 , m_xSigsOldSignatureImg(m_xBuilder->weld_image("oldsignatureimg"))
134 , m_xSigsOldSignatureFI(m_xBuilder->weld_label("oldsignatureft"))
135 , m_xAdESCompliantCB(m_xBuilder->weld_check_button("adescompliant"))
136 , m_xViewBtn(m_xBuilder->weld_button("view"))
137 , m_xAddBtn(m_xBuilder->weld_button("sign"))
138 , m_xRemoveBtn(m_xBuilder->weld_button("remove"))
139 , m_xStartCertMgrBtn(m_xBuilder->weld_button("start_certmanager"))
140 , m_xCloseBtn(m_xBuilder->weld_button("close"))
142 m_bAdESCompliant = !DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
144 auto nControlWidth = m_xSignaturesLB->get_approximate_digit_width() * 105;
145 m_xSignaturesLB->set_size_request(nControlWidth, m_xSignaturesLB->get_height_rows(10));
147 // Give the first column 6 percent, try to distribute the rest equally.
148 std::vector<int> aWidths;
149 aWidths.push_back(6*nControlWidth/100);
150 auto nColWidth = (nControlWidth - aWidths[0]) / 4;
151 aWidths.push_back(nColWidth);
152 aWidths.push_back(nColWidth);
153 aWidths.push_back(nColWidth);
154 m_xSignaturesLB->set_column_fixed_widths(aWidths);
156 mbVerifySignatures = true;
157 mbSignaturesChanged = false;
159 m_xSignaturesLB->connect_changed( LINK( this, DigitalSignaturesDialog, SignatureHighlightHdl ) );
160 m_xSignaturesLB->connect_row_activated( LINK( this, DigitalSignaturesDialog, SignatureSelectHdl ) );
162 m_xAdESCompliantCB->connect_toggled( LINK( this, DigitalSignaturesDialog, AdESCompliantCheckBoxHdl ) );
163 m_xAdESCompliantCB->set_active(m_bAdESCompliant);
165 m_xViewBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, ViewButtonHdl ) );
166 m_xViewBtn->set_sensitive(false);
168 m_xAddBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, AddButtonHdl ) );
169 if ( bReadOnly )
170 m_xAddBtn->set_sensitive(false);
172 m_xRemoveBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, RemoveButtonHdl ) );
173 m_xRemoveBtn->set_sensitive(false);
175 m_xStartCertMgrBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, CertMgrButtonHdl ) );
177 m_xCloseBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, OKButtonHdl) );
179 switch( maSignatureManager.getSignatureMode() )
181 case DocumentSignatureMode::Content:
182 m_xHintDocFT->show();
183 break;
184 case DocumentSignatureMode::Macros:
185 m_xHintBasicFT->show();
186 break;
187 case DocumentSignatureMode::Package:
188 m_xHintPackageFT->show();
189 break;
193 DigitalSignaturesDialog::~DigitalSignaturesDialog()
197 bool DigitalSignaturesDialog::Init()
199 bool bInit = maSignatureManager.init();
201 SAL_WARN_IF( !bInit, "xmlsecurity.dialogs", "Error initializing security context!" );
203 if ( bInit )
205 maSignatureManager.getSignatureHelper().SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog, StartVerifySignatureHdl ) );
208 return bInit;
211 void DigitalSignaturesDialog::SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore )
213 if (!rxStore.is())
215 // PDF supports AdES.
216 m_bAdESCompliant = true;
217 m_xAdESCompliantCB->set_active(m_bAdESCompliant);
218 return;
221 maSignatureManager.setStore(rxStore);
222 maSignatureManager.getSignatureHelper().SetStorage( maSignatureManager.getStore(), m_sODFVersion);
225 void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream )
227 maSignatureManager.setSignatureStream(rxStream);
230 bool DigitalSignaturesDialog::canAddRemove()
232 //FIXME: this func needs some cleanup, such as real split between
233 //'canAdd' and 'canRemove' case
234 bool ret = true;
236 uno::Reference<container::XNameAccess> xNameAccess = maSignatureManager.getStore();
237 if (xNameAccess.is() && xNameAccess->hasByName("[Content_Types].xml"))
238 // It's always possible to append an OOXML signature.
239 return ret;
241 if (!maSignatureManager.getStore().is())
242 // It's always possible to append a PDF signature.
243 return ret;
245 OSL_ASSERT(maSignatureManager.getStore().is());
246 bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
247 SaveODFItem item;
248 bool bSave1_1 = item.isLessODF1_2();
250 // see specification
251 //cvs: specs/www/appwide/security/Electronic_Signatures_and_Security.sxw
252 //Paragraph 'Behavior with regard to ODF 1.2'
253 //For both, macro and document
254 if ( (!bSave1_1 && bDoc1_1) || (bSave1_1 && bDoc1_1) )
256 //#4
257 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
258 VclMessageType::Warning, VclButtonsType::Ok,
259 XsResId(STR_XMLSECDLG_OLD_ODF_FORMAT)));
260 xBox->run();
261 ret = false;
264 //As of OOo 3.2 the document signature includes in macrosignatures.xml. That is
265 //adding a macro signature will break an existing document signature.
266 //The sfx2 will remove the documentsignature when the user adds a macro signature
267 if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Macros
268 && ret)
270 if (m_bHasDocumentSignature && !m_bWarningShowSignMacro)
272 //The warning says that the document signatures will be removed if the user
273 //continues. He can then either press 'OK' or 'NO'
274 //It the user presses 'Add' or 'Remove' several times then, then the warning
275 //is shown every time until the user presses 'OK'. From then on, the warning
276 //is not displayed anymore as long as the signatures dialog is alive.
277 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
278 VclMessageType::Question, VclButtonsType::YesNo,
279 XsResId(STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN)));
280 if (xBox->run() == RET_NO)
281 ret = false;
282 else
283 m_bWarningShowSignMacro = true;
287 return ret;
290 bool DigitalSignaturesDialog::canAdd()
292 return canAddRemove();
295 bool DigitalSignaturesDialog::canRemove()
297 bool bRet = true;
299 if ( maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content )
301 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
302 VclMessageType::Question, VclButtonsType::YesNo,
303 XsResId(STR_XMLSECDLG_QUERY_REALLYREMOVE)));
304 short nDlgRet = xBox->run();
305 bRet = ( nDlgRet == RET_YES );
308 return (bRet && canAddRemove());
311 short DigitalSignaturesDialog::run()
313 // Verify Signatures and add certificates to ListBox...
314 mbVerifySignatures = true;
315 ImplGetSignatureInformations(/*bUseTempStream=*/false, /*bCacheLastSignature=*/true);
316 ImplFillSignaturesBox();
318 // FIXME: Disable the "Use XAdES compliant signatures" checkbox if it is irrelevant. If it is
319 // enabled, set its initial state based on existing signatures, if any.
321 // If it is OOXML, the checkbox is irrelevant.
323 // How to find out here whether it is OOXML? I don't want to create a SignatureStreamHelper and
324 // check its nStorageFormat as that seems overly complicated and seems to have weird indirect
325 // consequences, as I noticed when I tried to use DocumentSignatureManager::IsXAdESRelevant()
326 // (which now is in #if 0).
328 if (!maSignatureManager.getCurrentSignatureInformations().empty())
330 // If the document has only SHA-1 signatures we probably want it to stay that way?
333 // Only verify once, content will not change.
334 // But for refreshing signature information, StartVerifySignatureHdl will be called after each add/remove
335 mbVerifySignatures = false;
337 return GenericDialogController::run();
340 IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureHighlightHdl, weld::TreeView&, void)
342 bool bSel = m_xSignaturesLB->get_selected_index() != -1;
343 m_xViewBtn->set_sensitive( bSel );
344 if ( m_xAddBtn->get_sensitive() ) // not read only
345 m_xRemoveBtn->set_sensitive( bSel );
348 IMPL_LINK_NOARG(DigitalSignaturesDialog, OKButtonHdl, weld::Button&, void)
350 if (mbSignaturesChanged)
351 maSignatureManager.write(m_bAdESCompliant);
353 m_xDialog->response(RET_OK);
356 IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureSelectHdl, weld::TreeView&, bool)
358 ImplShowSignaturesDetails();
359 return true;
362 IMPL_LINK_NOARG(DigitalSignaturesDialog, AdESCompliantCheckBoxHdl, weld::ToggleButton&, void)
364 m_bAdESCompliant = m_xAdESCompliantCB->get_active();
367 IMPL_LINK_NOARG(DigitalSignaturesDialog, ViewButtonHdl, weld::Button&, void)
369 ImplShowSignaturesDetails();
372 IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, weld::Button&, void)
374 if( ! canAdd())
375 return;
378 std::vector<uno::Reference<xml::crypto::XXMLSecurityContext>> xSecContexts;
379 xSecContexts.push_back(maSignatureManager.getSecurityContext());
380 // Gpg signing is only possible with ODF >= 1.2 documents
381 if (DocumentSignatureHelper::CanSignWithGPG(maSignatureManager.getStore(), m_sODFVersion))
382 xSecContexts.push_back(maSignatureManager.getGpgSecurityContext());
384 CertificateChooser aChooser(m_xDialog.get(), xSecContexts, UserAction::Sign);
385 if (aChooser.run() == RET_OK)
387 sal_Int32 nSecurityId;
388 if (!maSignatureManager.add(aChooser.GetSelectedCertificates()[0], aChooser.GetSelectedSecurityContext(),
389 aChooser.GetDescription(), nSecurityId, m_bAdESCompliant))
390 return;
391 mbSignaturesChanged = true;
393 xml::crypto::SecurityOperationStatus nStatus = xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
395 if (maSignatureManager.getStore().is())
396 // In the PDF case the signature information is only available after parsing.
397 nStatus = maSignatureManager.getSignatureHelper().GetSignatureInformation( nSecurityId ).nStatus;
399 if ( nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED )
401 mbSignaturesChanged = true;
403 // Can't simply remember current information, need parsing for getting full information :(
404 // We need to verify the signatures again, otherwise the status in the signature information
405 // will not contain
406 // SecurityOperationStatus_OPERATION_SUCCEEDED
407 mbVerifySignatures = true;
408 ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
409 ImplFillSignaturesBox();
413 catch ( uno::Exception& )
415 OSL_FAIL( "Exception while adding a signature!" );
416 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
417 VclMessageType::Error, VclButtonsType::Ok,
418 XsResId(STR_XMLSECDLG_SIGNING_FAILED)));
419 xBox->run();
420 // Don't keep invalid entries...
421 ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
422 ImplFillSignaturesBox();
426 IMPL_LINK_NOARG(DigitalSignaturesDialog, RemoveButtonHdl, weld::Button&, void)
428 if (!canRemove())
429 return;
430 int nEntry = m_xSignaturesLB->get_selected_index();
431 if (nEntry != -1)
435 sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32();
436 maSignatureManager.remove(nSelected);
438 mbSignaturesChanged = true;
440 ImplFillSignaturesBox();
442 catch ( uno::Exception& )
444 OSL_FAIL( "Exception while removing a signature!" );
445 // Don't keep invalid entries...
446 ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/true);
447 ImplFillSignaturesBox();
452 IMPL_LINK_NOARG(DigitalSignaturesDialog, CertMgrButtonHdl, weld::Button&, void)
454 #ifdef _WIN32
455 // FIXME: call GpgME::dirInfo("bindir") somewhere in
456 // SecurityEnvironmentGpg or whatnot
457 // FIXME: perhaps poke GpgME for uiserver, and hope it returns something useful?
458 static const OUStringLiteral aGUIServers[] = { "Gpg4win\\kleopatra.exe",
459 "Gpg4win\\bin\\kleopatra.exe",
460 "GNU\\GnuPG\\kleopatra.exe",
461 "GNU\\GnuPG\\launch-gpa.exe",
462 "GNU\\GnuPG\\gpa.exe",
463 "GnuPG\\bin\\gpa.exe",
464 "GNU\\GnuPG\\bin\\kleopatra.exe",
465 "GNU\\GnuPG\\bin\\launch-gpa.exe",
466 "GNU\\GnuPG\\bin\\gpa.exe",
468 static const OUString aPath = [] {
469 OUString sRet;
470 PWSTR sPath = nullptr;
471 HRESULT hr
472 = SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, KF_FLAG_DEFAULT, nullptr, &sPath);
473 if (SUCCEEDED(hr))
475 sRet = o3tl::toU(sPath);
476 CoTaskMemFree(sPath);
478 return sRet;
479 }();
480 if (aPath.isEmpty())
481 return;
482 #else
483 static const OUStringLiteral aGUIServers[] = { "kleopatra", "seahorse", "gpa", "kgpg" };
484 const char* cPath = getenv("PATH");
485 if (!cPath)
486 return;
487 OUString aPath(cPath, strlen(cPath), osl_getThreadTextEncoding());
488 #endif
490 OUString sFoundGUIServer, sExecutable;
492 for ( auto const &rServer : aGUIServers )
494 osl::FileBase::RC searchError = osl::File::searchFileURL(rServer, aPath, sFoundGUIServer );
495 if (searchError == osl::FileBase::E_None)
497 osl::File::getSystemPathFromFileURL( sFoundGUIServer, sExecutable );
498 break;
503 if ( !sExecutable.isEmpty() )
505 uno::Reference< uno::XComponentContext > xContext =
506 ::comphelper::getProcessComponentContext();
507 uno::Reference< css::system::XSystemShellExecute > xSystemShell(
508 css::system::SystemShellExecute::create(xContext) );
510 xSystemShell->execute( sExecutable, OUString(),
511 css::system::SystemShellExecuteFlags::DEFAULTS );
513 else
515 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
516 VclMessageType::Info, VclButtonsType::Ok,
517 XsResId(STR_XMLSECDLG_NO_CERT_MANAGER)));
518 xInfoBox->run();
522 IMPL_LINK_NOARG(DigitalSignaturesDialog, StartVerifySignatureHdl, LinkParamNone*, bool)
524 return mbVerifySignatures;
527 void DigitalSignaturesDialog::ImplFillSignaturesBox()
529 m_xSignaturesLB->clear();
531 size_t nInfos = maSignatureManager.getCurrentSignatureInformations().size();
532 size_t nValidSigs = 0, nValidCerts = 0;
533 bool bAllNewSignatures = true;
535 if( nInfos )
537 for( size_t n = 0; n < nInfos; ++n )
539 DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm(
540 m_sODFVersion, maSignatureManager.getCurrentSignatureInformations()[n]);
541 std::vector< OUString > aElementsToBeVerified;
542 if (maSignatureManager.getStore().is())
543 aElementsToBeVerified = DocumentSignatureHelper::CreateElementList(maSignatureManager.getStore(), maSignatureManager.getSignatureMode(), mode);
545 const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[n];
546 uno::Reference< css::security::XCertificate > xCert = getCertificate(rInfo);
548 OUString aSubject;
549 OUString aIssuer;
550 OUString aDateTimeStr;
551 OUString aDescription;
552 OUString aType;
554 bool bCertValid = false;
555 if( xCert.is() )
557 //check the validity of the cert
558 try {
559 sal_Int32 certResult = getSecurityEnvironmentForCertificate(xCert)->verifyCertificate(xCert,
560 Sequence<uno::Reference<security::XCertificate> >());
562 bCertValid = certResult == css::security::CertificateValidity::VALID;
563 if ( bCertValid )
564 nValidCerts++;
566 } catch (css::uno::SecurityException& ) {
567 OSL_FAIL("Verification of certificate failed");
568 bCertValid = false;
571 aSubject = xmlsec::GetContentPart( xCert->getSubjectName() );
572 aIssuer = xmlsec::GetContentPart( xCert->getIssuerName() );
574 else if (!rInfo.ouGpgCertificate.isEmpty())
576 // In case we don't have the gpg key locally, get some data from the document
577 aIssuer = rInfo.ouGpgOwner;
580 aDateTimeStr = utl::GetDateTimeString( rInfo.stDateTime );
581 aDescription = rInfo.ouDescription;
583 // Decide type string.
584 if (maSignatureManager.getStore().is())
586 // OpenPGP
587 if (!rInfo.ouGpgCertificate.isEmpty())
588 aType = "OpenPGP";
589 // XML based: XAdES or not.
590 else if (!rInfo.ouCertDigest.isEmpty())
591 aType = "XAdES";
592 else
593 aType = "XML-DSig";
595 else
597 // Assume PDF: PAdES or not.
598 if (rInfo.bHasSigningCertificate)
599 aType = "PAdES";
600 else
601 aType = "PDF";
604 bool bSigValid = rInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
606 if ( bSigValid )
608 bSigValid = DocumentSignatureHelper::checkIfAllFilesAreSigned(
609 aElementsToBeVerified, rInfo, mode);
611 if( bSigValid )
612 nValidSigs++;
615 OUString sImage;
616 if (!bSigValid)
618 sImage = BMP_SIG_INVALID;
620 else if (!bCertValid)
622 sImage = BMP_SIG_NOT_VALIDATED;
624 //Check if the signature is a "old" document signature, that is, which was created
625 //by a version of OOo previous to 3.2
626 // If there is no storage, then it's pointless to check storage
627 // stream references.
628 else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content
629 && (maSignatureManager.getStore().is() && !DocumentSignatureHelper::isOOo3_2_Signature(
630 maSignatureManager.getCurrentSignatureInformations()[n])))
632 sImage = BMP_SIG_NOT_VALIDATED;
633 bAllNewSignatures = false;
635 else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content
636 && DocumentSignatureHelper::isOOo3_2_Signature(
637 maSignatureManager.getCurrentSignatureInformations()[n]))
639 sImage = BMP_SIG_VALID;
641 else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Macros)
643 sImage = BMP_SIG_VALID;
646 m_xSignaturesLB->insert(nullptr, n, nullptr, nullptr,
647 &sImage, nullptr, nullptr, false, nullptr);
648 m_xSignaturesLB->set_text(n, aSubject, 1);
649 m_xSignaturesLB->set_text(n, aIssuer, 2);
650 m_xSignaturesLB->set_text(n, aDateTimeStr, 3);
651 m_xSignaturesLB->set_text(n, aDescription, 4);
652 m_xSignaturesLB->set_text(n, aType, 5);
653 m_xSignaturesLB->set_id(n, OUString::number(n)); // misuse user data as index
657 bool bAllSigsValid = (nValidSigs == nInfos);
658 bool bAllCertsValid = (nValidCerts == nInfos);
659 bool bShowValidState = nInfos && (bAllSigsValid && bAllCertsValid && bAllNewSignatures);
661 m_xSigsValidImg->set_visible( bShowValidState);
662 m_xSigsValidFI->set_visible( bShowValidState );
664 bool bShowInvalidState = nInfos && !bAllSigsValid;
666 m_xSigsInvalidImg->set_visible( bShowInvalidState );
667 m_xSigsInvalidFI->set_visible( bShowInvalidState );
669 bool bShowNotValidatedState = nInfos && bAllSigsValid && !bAllCertsValid;
671 m_xSigsNotvalidatedImg->set_visible(bShowNotValidatedState);
672 m_xSigsNotvalidatedFI->set_visible(bShowNotValidatedState);
674 //bAllNewSignatures is always true if we are not in document mode
675 bool bShowOldSignature = nInfos && bAllSigsValid && bAllCertsValid && !bAllNewSignatures;
676 m_xSigsOldSignatureImg->set_visible(bShowOldSignature);
677 m_xSigsOldSignatureFI->set_visible(bShowOldSignature);
679 SignatureHighlightHdl(*m_xSignaturesLB);
682 uno::Reference<security::XCertificate> DigitalSignaturesDialog::getCertificate(const SignatureInformation& rInfo)
684 uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureManager.getSecurityEnvironment();
685 uno::Reference<xml::crypto::XSecurityEnvironment> xGpgSecEnv = maSignatureManager.getGpgSecurityEnvironment();
686 uno::Reference<security::XCertificate> xCert;
688 //First we try to get the certificate which is embedded in the XML Signature
689 if (xSecEnv.is() && !rInfo.ouX509Certificate.isEmpty())
690 xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate);
691 else {
692 //There must be an embedded certificate because we use it to get the
693 //issuer name. We cannot use /Signature/KeyInfo/X509Data/X509IssuerName
694 //because it could be modified by an attacker. The issuer is displayed
695 //in the digital signature dialog.
696 //Comparing the X509IssuerName with the one from the X509Certificate in order
697 //to find out if the X509IssuerName was modified does not work. See #i62684
698 SAL_WARN( "xmlsecurity.dialogs", "Could not find embedded certificate!");
701 //In case there is no embedded certificate we try to get it from a local store
702 if (!xCert.is() && xSecEnv.is())
703 xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xmlsecurity::numericStringToBigInteger( rInfo.ouX509SerialNumber ) );
704 if (!xCert.is() && xGpgSecEnv.is())
705 xCert = xGpgSecEnv->getCertificate( rInfo.ouGpgKeyID, xmlsecurity::numericStringToBigInteger("") );
707 SAL_WARN_IF( !xCert.is(), "xmlsecurity.dialogs", "Certificate not found and can't be created!" );
709 return xCert;
712 uno::Reference<xml::crypto::XSecurityEnvironment> DigitalSignaturesDialog::getSecurityEnvironmentForCertificate(const uno::Reference<security::XCertificate>& xCert)
714 if (xCert->getCertificateKind() == CertificateKind_OPENPGP)
715 return maSignatureManager.getGpgSecurityEnvironment();
716 else if (xCert->getCertificateKind() == CertificateKind_X509)
717 return maSignatureManager.getSecurityEnvironment();
719 throw RuntimeException("Unknown certificate kind");
722 //If bUseTempStream is true then the temporary signature stream is used.
723 //Otherwise the real signature stream is used.
724 void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature)
726 maSignatureManager.read(bUseTempStream, bCacheLastSignature);
727 mbVerifySignatures = false;
730 void DigitalSignaturesDialog::ImplShowSignaturesDetails()
732 int nEntry = m_xSignaturesLB->get_selected_index();
733 if (nEntry != -1)
735 sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32();
736 const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[ nSelected ];
737 uno::Reference<security::XCertificate> xCert = getCertificate(rInfo);
739 if ( xCert.is() )
741 uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = getSecurityEnvironmentForCertificate(xCert);
742 CertificateViewer aViewer(m_xDialog.get(), xSecEnv, xCert, false, nullptr);
743 aViewer.run();
745 else
747 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
748 VclMessageType::Info, VclButtonsType::Ok,
749 XsResId(STR_XMLSECDLG_NO_CERT_FOUND)));
750 xInfoBox->run();
755 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */