LibreOffice Module xmlsecurity (master) 1
digitalsignaturesdialog.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <rtl/ustring.hxx>
21#include <sal/config.h>
22
23#include <string_view>
24
27#include <certificateviewer.hxx>
28#include <biginteger.hxx>
32#include <officecfg/Office/Common.hxx>
33
34#include <com/sun/star/embed/XStorage.hpp>
35#include <com/sun/star/embed/ElementModes.hpp>
36#include <com/sun/star/embed/StorageFormats.hpp>
37#include <com/sun/star/container/XNameAccess.hpp>
38#include <com/sun/star/lang/XComponent.hpp>
39#include <com/sun/star/security/NoPasswordException.hpp>
40#include <com/sun/star/lang/DisposedException.hpp>
41#include <com/sun/star/beans/XPropertySet.hpp>
42#include <com/sun/star/security/CertificateValidity.hpp>
43#include <com/sun/star/packages/WrongPasswordException.hpp>
44#include <com/sun/star/security/CertificateKind.hpp>
45#include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
46#include <com/sun/star/system/SystemShellExecute.hpp>
47#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
48#include <com/sun/star/system/SystemShellExecuteException.hpp>
49
50#include <osl/file.hxx>
51#include <rtl/ustrbuf.hxx>
52#include <rtl/uri.hxx>
53#include <sal/log.hxx>
54
55#include <tools/date.hxx>
56#include <tools/time.hxx>
57#include <unotools/datetime.hxx>
58
59#include <bitmaps.hlst>
60#include <strings.hrc>
61#include <resourcemanager.hxx>
62#include <comphelper/lok.hxx>
65
66#include <utility>
67#include <vcl/weld.hxx>
68#include <vcl/svapp.hxx>
70
71#ifdef _WIN32
73#include <systools/win32/comtools.hxx>
74#include <Shlobj.h>
75#endif
76
77using namespace comphelper;
78using namespace css::security;
79using namespace css::uno;
80using namespace css;
81
82namespace
83{
84 class SaveODFItem: public utl::ConfigItem
85 {
86 private:
87 virtual void ImplCommit() override;
88
89 public:
90 virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
91 SaveODFItem();
92 };
93
94 void SaveODFItem::ImplCommit() {}
95 void SaveODFItem::Notify( const css::uno::Sequence< OUString >& ) {}
96
97 SaveODFItem::SaveODFItem(): utl::ConfigItem("Office.Common/Save")
98 {
99 OUString sDef("ODF/DefaultVersion");
100 Sequence< css::uno::Any > aValues = GetProperties( Sequence<OUString>(&sDef,1) );
101 if ( aValues.getLength() != 1)
102 throw uno::RuntimeException(
103 "[xmlsecurity] Could not open property Office.Common/Save/ODF/DefaultVersion",
104 nullptr);
105
106 sal_Int16 nTmp = 0;
107 if ( !(aValues[0] >>= nTmp) )
108 throw uno::RuntimeException(
109 "[xmlsecurity]SaveODFItem::SaveODFItem(): Wrong Type!",
110 nullptr );
111 }
112
113 std::vector<std::u16string_view>& GetGUIServers()
114 {
115
116#ifdef _WIN32
117 static std::vector<std::u16string_view> aGUIServers
118 = { u"Gpg4win\\kleopatra.exe",
119 u"Gpg4win\\bin\\kleopatra.exe",
120 u"GNU\\GnuPG\\kleopatra.exe",
121 u"GNU\\GnuPG\\launch-gpa.exe",
122 u"GNU\\GnuPG\\gpa.exe",
123 u"GnuPG\\bin\\gpa.exe",
124 u"GNU\\GnuPG\\bin\\kleopatra.exe",
125 u"GNU\\GnuPG\\bin\\launch-gpa.exe",
126 u"GNU\\GnuPG\\bin\\gpa.exe",
127 officecfg::Office::Common::Security::Scripting::CertMgrPath::get() };
128#else
129 static std::vector<std::u16string_view> aGUIServers
130 = { u"kleopatra", u"seahorse", u"gpa", u"kgpg",
131 officecfg::Office::Common::Security::Scripting::CertMgrPath::get() };
132#endif
133 return aGUIServers;
134 }
135
136}
137
139 weld::Window* pParent,
140 const uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode,
141 bool bReadOnly, OUString sODFVersion, bool bHasDocumentSignature)
142 : GenericDialogController(pParent, "xmlsec/ui/digitalsignaturesdialog.ui", "DigitalSignaturesDialog")
143 , maSignatureManager(rxCtx, eMode)
144 , m_sODFVersion (std::move(sODFVersion))
145 , m_bHasDocumentSignature(bHasDocumentSignature)
146 , m_bWarningShowSignMacro(false)
147 , m_xHintDocFT(m_xBuilder->weld_label("dochint"))
148 , m_xHintBasicFT(m_xBuilder->weld_label("macrohint"))
149 , m_xHintPackageFT(m_xBuilder->weld_label("packagehint"))
150 , m_xSignaturesLB(m_xBuilder->weld_tree_view("signatures"))
151 , m_xSigsValidImg(m_xBuilder->weld_image("validimg"))
152 , m_xSigsValidFI(m_xBuilder->weld_label("validft"))
153 , m_xSigsInvalidImg(m_xBuilder->weld_image("invalidimg"))
154 , m_xSigsInvalidFI(m_xBuilder->weld_label("invalidft"))
155 , m_xSigsNotvalidatedImg(m_xBuilder->weld_image("notvalidatedimg"))
156 , m_xSigsNotvalidatedFI(m_xBuilder->weld_label("notvalidatedft"))
157 , m_xSigsOldSignatureImg(m_xBuilder->weld_image("oldsignatureimg"))
158 , m_xSigsOldSignatureFI(m_xBuilder->weld_label("oldsignatureft"))
159 , m_xAdESCompliantCB(m_xBuilder->weld_check_button("adescompliant"))
160 , m_xViewBtn(m_xBuilder->weld_button("view"))
161 , m_xAddBtn(m_xBuilder->weld_button("sign"))
162 , m_xRemoveBtn(m_xBuilder->weld_button("remove"))
163 , m_xStartCertMgrBtn(m_xBuilder->weld_button("start_certmanager"))
164 , m_xCloseBtn(m_xBuilder->weld_button("close"))
165{
167
168 auto nControlWidth = m_xSignaturesLB->get_approximate_digit_width() * 105;
169 m_xSignaturesLB->set_size_request(nControlWidth, m_xSignaturesLB->get_height_rows(10));
170
171 // Give the first column 6 percent, try to distribute the rest equally.
172 std::vector<int> aWidths;
173 aWidths.push_back(6*nControlWidth/100);
174 auto nColWidth = (nControlWidth - aWidths[0]) / 4;
175 aWidths.push_back(nColWidth);
176 aWidths.push_back(nColWidth);
177 aWidths.push_back(nColWidth);
178 m_xSignaturesLB->set_column_fixed_widths(aWidths);
179
180 mbVerifySignatures = true;
181 mbSignaturesChanged = false;
182
183 m_xSignaturesLB->connect_changed( LINK( this, DigitalSignaturesDialog, SignatureHighlightHdl ) );
184 m_xSignaturesLB->connect_row_activated( LINK( this, DigitalSignaturesDialog, SignatureSelectHdl ) );
185
186 m_xAdESCompliantCB->connect_toggled( LINK( this, DigitalSignaturesDialog, AdESCompliantCheckBoxHdl ) );
188
189 m_xViewBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, ViewButtonHdl ) );
190 m_xViewBtn->set_sensitive(false);
191
192 m_xAddBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, AddButtonHdl ) );
193 if ( bReadOnly )
194 m_xAddBtn->set_sensitive(false);
195
196 m_xRemoveBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, RemoveButtonHdl ) );
197 m_xRemoveBtn->set_sensitive(false);
198
199 m_xStartCertMgrBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, CertMgrButtonHdl ) );
200
201 m_xCloseBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, OKButtonHdl) );
202
204 {
206 m_xHintDocFT->show();
207 break;
209 m_xHintBasicFT->show();
210 break;
212 m_xHintPackageFT->show();
213 break;
214 }
215
217 {
218 m_xAddBtn->hide();
219 m_xRemoveBtn->hide();
220 m_xStartCertMgrBtn->hide();
221 }
222
224 {
225 m_xStartCertMgrBtn->set_sensitive(false);
226 }
227}
228
230{
231 if (m_xViewer)
232 m_xViewer->response(RET_OK);
233
234 if (m_xInfoBox)
235 m_xInfoBox->response(RET_OK);
236}
237
239{
240 bool bInit = maSignatureManager.init();
241
242 SAL_WARN_IF( !bInit, "xmlsecurity.dialogs", "Error initializing security context!" );
243
244 if ( bInit )
245 {
247 }
248
249 return bInit;
250}
251
252void DigitalSignaturesDialog::SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore )
253{
254 if (!rxStore.is())
255 {
256 // PDF supports AdES.
257 m_bAdESCompliant = true;
259 return;
260 }
261
264}
265
266void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream )
267{
269}
270
272{
273 //FIXME: this func needs some cleanup, such as real split between
274 //'canAdd' and 'canRemove' case
275 bool ret = true;
276
277 uno::Reference<container::XNameAccess> xNameAccess = maSignatureManager.getStore();
278 if (xNameAccess.is() && xNameAccess->hasByName("[Content_Types].xml"))
279 // It's always possible to append an OOXML signature.
280 return ret;
281
282 if (!maSignatureManager.getStore().is())
283 // It's always possible to append a PDF signature.
284 return ret;
285
286 OSL_ASSERT(maSignatureManager.getStore().is());
288 SaveODFItem item;
289
290 // see specification
291 //cvs: specs/www/appwide/security/Electronic_Signatures_and_Security.sxw
292 //Paragraph 'Behavior with regard to ODF 1.2'
293 //For both, macro and document
294 if ( bDoc1_1 )
295 {
296 //#4
297 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
298 VclMessageType::Warning, VclButtonsType::Ok,
299 XsResId(STR_XMLSECDLG_OLD_ODF_FORMAT)));
300 xBox->run();
301 ret = false;
302 }
303
304 //As of OOo 3.2 the document signature includes in macrosignatures.xml. That is
305 //adding a macro signature will break an existing document signature.
306 //The sfx2 will remove the documentsignature when the user adds a macro signature
308 && ret)
309 {
311 {
312 //The warning says that the document signatures will be removed if the user
313 //continues. He can then either press 'OK' or 'NO'
314 //It the user presses 'Add' or 'Remove' several times then, then the warning
315 //is shown every time until the user presses 'OK'. From then on, the warning
316 //is not displayed anymore as long as the signatures dialog is alive.
317 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
318 m_xDialog.get(), VclMessageType::Question, VclButtonsType::YesNo,
319 XsResId(STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN)));
320 if (xBox->run() == RET_NO)
321 ret = false;
322 else
324 }
325 }
326 return ret;
327}
328
330
332{
333 bool bRet = true;
334
336 {
337 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
338 VclMessageType::Question, VclButtonsType::YesNo,
339 XsResId(STR_XMLSECDLG_QUERY_REALLYREMOVE)));
340 short nDlgRet = xBox->run();
341 bRet = ( nDlgRet == RET_YES );
342 }
343
344 return (bRet && canAddRemove());
345}
346
348{
349 // Verify Signatures and add certificates to ListBox...
350 mbVerifySignatures = true;
351 ImplGetSignatureInformations(/*bUseTempStream=*/false, /*bCacheLastSignature=*/true);
353
354 // FIXME: Disable the "Use XAdES compliant signatures" checkbox if it is irrelevant. If it is
355 // enabled, set its initial state based on existing signatures, if any.
356
357 // If it is OOXML, the checkbox is irrelevant.
358
359 // How to find out here whether it is OOXML? I don't want to create a SignatureStreamHelper and
360 // check its nStorageFormat as that seems overly complicated and seems to have weird indirect
361 // consequences, as I noticed when I tried to use DocumentSignatureManager::IsXAdESRelevant()
362 // (which now is in #if 0).
363
365 {
366 // If the document has only SHA-1 signatures we probably want it to stay that way?
367 }
368
369 // Only verify once, content will not change.
370 // But for refreshing signature information, StartVerifySignatureHdl will be called after each add/remove
371 mbVerifySignatures = false;
372}
373
375{
376 beforeRun();
377 return GenericDialogController::run();
378}
379
381{
382 bool bSel = m_xSignaturesLB->get_selected_index() != -1;
383 m_xViewBtn->set_sensitive( bSel );
384 if ( m_xAddBtn->get_sensitive() ) // not read only
385 m_xRemoveBtn->set_sensitive( bSel );
386}
387
389{
390 if (mbSignaturesChanged)
391 maSignatureManager.write(m_bAdESCompliant);
392
393 m_xDialog->response(RET_OK);
394}
395
397{
398 ImplShowSignaturesDetails();
399 return true;
400}
401
403{
404 m_bAdESCompliant = m_xAdESCompliantCB->get_active();
405}
406
408{
409 ImplShowSignaturesDetails();
410}
411
413{
414 if( ! canAdd())
415 return;
416 try
417 {
418 std::vector<uno::Reference<xml::crypto::XXMLSecurityContext>> xSecContexts
419 {
420 maSignatureManager.getSecurityContext()
421 };
422 // Gpg signing is only possible with ODF >= 1.2 documents
423 if (DocumentSignatureHelper::CanSignWithGPG(maSignatureManager.getStore(), m_sODFVersion))
424 xSecContexts.push_back(maSignatureManager.getGpgSecurityContext());
425
426 CertificateChooser aChooser(m_xDialog.get(), std::move(xSecContexts), UserAction::Sign);
427 if (aChooser.run() == RET_OK)
428 {
429 sal_Int32 nSecurityId;
430 if (!maSignatureManager.add(aChooser.GetSelectedCertificates()[0], aChooser.GetSelectedSecurityContext(),
431 aChooser.GetDescription(), nSecurityId, m_bAdESCompliant))
432 return;
433 mbSignaturesChanged = true;
434
435 xml::crypto::SecurityOperationStatus nStatus = xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
436
437 if (maSignatureManager.getStore().is())
438 // In the PDF case the signature information is only available after parsing.
439 nStatus = maSignatureManager.getSignatureHelper().GetSignatureInformation( nSecurityId ).nStatus;
440
441 if ( nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED )
442 {
443 mbSignaturesChanged = true;
444
445 // Can't simply remember current information, need parsing for getting full information :(
446 // We need to verify the signatures again, otherwise the status in the signature information
447 // will not contain
448 // SecurityOperationStatus_OPERATION_SUCCEEDED
449 mbVerifySignatures = true;
450 ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
451 ImplFillSignaturesBox();
452 }
453 }
454 }
455 catch ( uno::Exception& )
456 {
457 TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "adding a signature!" );
458 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
459 VclMessageType::Error, VclButtonsType::Ok,
460 XsResId(STR_XMLSECDLG_SIGNING_FAILED)));
461 xBox->run();
462 // Don't keep invalid entries...
463 ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
464 ImplFillSignaturesBox();
465 }
466}
467
469{
470 if (!canRemove())
471 return;
472 int nEntry = m_xSignaturesLB->get_selected_index();
473 if (nEntry == -1)
474 return;
475
476 try
477 {
478 sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32();
479 maSignatureManager.remove(nSelected);
480
481 mbSignaturesChanged = true;
482
483 ImplFillSignaturesBox();
484 }
485 catch ( uno::Exception& )
486 {
487 TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "Exception while removing a signature!" );
488 // Don't keep invalid entries...
489 ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/true);
490 ImplFillSignaturesBox();
491 }
492}
493
495{
496#ifdef _WIN32
497 aPath = []
498 {
499 sal::systools::CoTaskMemAllocated<wchar_t> sPath;
500 HRESULT hr
501 = SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, KF_FLAG_DEFAULT, nullptr, &sPath);
502 if (SUCCEEDED(hr))
503 return OUString(o3tl::toU(sPath));
504 return OUString();
505 }();
506 if (aPath.isEmpty())
507 return false;
508#else
509 const char* cPath = getenv("PATH");
510 if (!cPath)
511 return false;
512 aPath = OUString(cPath, strlen(cPath), osl_getThreadTextEncoding());
513#endif
514 return (!aPath.isEmpty());
515}
516
517void DigitalSignaturesDialog::GetCertificateManager(OUString& aPath, OUString& sExecutable,
518 OUString& sFoundGUIServer)
519{
520 GetGUIServers().pop_back();
521 GetGUIServers().push_back(officecfg::Office::Common::Security::Scripting::CertMgrPath::get());
522
523 for (auto it = GetGUIServers().rbegin(); it != GetGUIServers().rend(); ++it)
524 {
525 const auto& rServer = *it;
526
527 if (rServer.empty())
528 continue;
529
530 bool bValidSetMgr = (it == GetGUIServers().rbegin() && rServer.size() > 0);
531 sal_Int32 nLastBackslashIndex = -1;
532
533 if (bValidSetMgr)
534 {
535#ifdef _WIN32
536 nLastBackslashIndex = rServer.find_last_of('\\');
537#else
538 nLastBackslashIndex = rServer.find_last_of('/');
539#endif
540 }
541
542 osl::FileBase::RC searchError = osl::File::searchFileURL(
543 OUString(bValidSetMgr ? rServer.substr(nLastBackslashIndex + 1) : rServer), aPath,
544 sFoundGUIServer);
545 if (searchError == osl::FileBase::E_None)
546 {
547 osl::File::getSystemPathFromFileURL(sFoundGUIServer, sExecutable);
548 if (it != GetGUIServers().rbegin())
549 {
550 std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
552 officecfg::Office::Common::Security::Scripting::CertMgrPath::set(sExecutable,
553 pBatch);
554 pBatch->commit();
555 }
556
557 break;
558 }
559 }
560}
561
563{
564 OUString aPath, sFoundGUIServer, sExecutable;
565 if (!GetPathAllOS(aPath))
566 return false;
567 GetCertificateManager(aPath, sExecutable, sFoundGUIServer);
568 return (!sExecutable.isEmpty());
569}
570
572{
573 OUString aPath, sFoundGUIServer, sExecutable;
574 if (!GetPathAllOS(aPath))
575 return;
576
577 GetCertificateManager(aPath, sExecutable, sFoundGUIServer);
578
579 if (!sExecutable.isEmpty())
580 {
581 uno::Reference<uno::XComponentContext> xContext
582 = ::comphelper::getProcessComponentContext();
583 uno::Reference<css::system::XSystemShellExecute> xSystemShell(
584 css::system::SystemShellExecute::create(xContext));
585
586 xSystemShell->execute(sExecutable, OUString(),
587 css::system::SystemShellExecuteFlags::DEFAULTS);
588 }
589
590 OUString sDialogText = (sExecutable.isEmpty() ?
591 XsResId(STR_XMLSECDLG_NO_CERT_MANAGER) : XsResId(STR_XMLSECDLG_OPENED_CRTMGR) + sExecutable);
592
593 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(
594 m_xDialog.get(), VclMessageType::Info, VclButtonsType::Ok,
595 sDialogText));
596 xInfoBox->run();
597}
598
600{
601 return mbVerifySignatures;
602}
603
605{
606 m_xSignaturesLB->clear();
607
609 size_t nValidSigs = 0, nValidCerts = 0;
610 bool bAllNewSignatures = true;
611 bool bSomePartial = false;
612
613 if( nInfos )
614 {
615 for( size_t n = 0; n < nInfos; ++n )
616 {
619 std::vector< OUString > aElementsToBeVerified;
620 if (maSignatureManager.getStore().is())
622
624 uno::Reference< css::security::XCertificate > xCert = getCertificate(rInfo);
625
626 OUString aSubject;
627 OUString aIssuer;
628 OUString aDateTimeStr;
629 OUString aDescription;
630 OUString aType;
631
632 bool bCertValid = false;
633 if( xCert.is() )
634 {
635 //check the validity of the cert
636 try {
637 sal_Int32 certResult = getSecurityEnvironmentForCertificate(xCert)->verifyCertificate(xCert,
638 Sequence<uno::Reference<security::XCertificate> >());
639
640 bCertValid = certResult == css::security::CertificateValidity::VALID;
641 if ( bCertValid )
642 nValidCerts++;
643
644 } catch (css::uno::SecurityException& ) {
645 OSL_FAIL("Verification of certificate failed");
646 bCertValid = false;
647 }
648
649 aSubject = xmlsec::GetContentPart( xCert->getSubjectName(), xCert->getCertificateKind() );
650 aIssuer = xmlsec::GetContentPart( xCert->getIssuerName(), xCert->getCertificateKind() );
651 }
652 else if (!rInfo.ouGpgCertificate.isEmpty())
653 {
654 // In case we don't have the gpg key locally, get some data from the document
655 aIssuer = rInfo.ouGpgOwner;
656 }
657
658 aDateTimeStr = utl::GetDateTimeString( rInfo.stDateTime );
659 aDescription = rInfo.ouDescription;
660
661 // Decide type string.
662 if (maSignatureManager.getStore().is())
663 {
664 // OpenPGP
665 if (!rInfo.ouGpgCertificate.isEmpty())
666 aType = "OpenPGP";
667 // XML based: XAdES or not.
668 else if (rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->CertDigest.isEmpty())
669 aType = "XAdES";
670 else
671 aType = "XML-DSig";
672 }
673 else
674 {
675 // Assume PDF: PAdES or not.
676 if (rInfo.bHasSigningCertificate)
677 aType = "PAdES";
678 else
679 aType = "PDF";
680 }
681
682 bool bSigValid = rInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
683
684 if ( bSigValid )
685 {
686 if (maSignatureManager.getStore().is())
687 {
688 // ZIP based.
690 aElementsToBeVerified, rInfo, mode);
691 }
692 else
693 {
694 // Assume PDF.
695 bSigValid = !rInfo.bPartialDocumentSignature;
696 }
697
698 if( bSigValid )
699 nValidSigs++;
700 else
701 {
702 bSomePartial = true;
703 }
704 }
705
706 OUString sImage;
707 if (!bSigValid)
708 {
709 sImage = BMP_SIG_INVALID;
710 }
711 else if (!bCertValid)
712 {
713 sImage = BMP_SIG_NOT_VALIDATED;
714 }
715 //Check if the signature is a "old" document signature, that is, which was created
716 //by a version of OOo previous to 3.2
717 // If there is no storage, then it's pointless to check storage
718 // stream references.
722 {
723 sImage = BMP_SIG_NOT_VALIDATED;
724 bAllNewSignatures = false;
725 }
729 {
730 sImage = BMP_SIG_VALID;
731 }
733 {
734 sImage = BMP_SIG_VALID;
735 }
736
737 m_xSignaturesLB->insert(nullptr, n, nullptr, nullptr,
738 &sImage, nullptr, false, nullptr);
739 m_xSignaturesLB->set_text(n, aSubject, 1);
740 m_xSignaturesLB->set_text(n, aIssuer, 2);
741 m_xSignaturesLB->set_text(n, aDateTimeStr, 3);
742 m_xSignaturesLB->set_text(n, aDescription, 4);
743 m_xSignaturesLB->set_text(n, aType, 5);
744 m_xSignaturesLB->set_id(n, OUString::number(n)); // misuse user data as index
745 }
746 }
747
748 bool bAllSigsValid = (nValidSigs == nInfos);
749 bool bAllCertsValid = (nValidCerts == nInfos);
750 bool bShowValidState = nInfos && (bAllSigsValid && bAllCertsValid && bAllNewSignatures);
751
752 m_xSigsValidImg->set_visible( bShowValidState);
753 m_xSigsValidFI->set_visible( bShowValidState );
754
755 bool bShowInvalidState = nInfos && !bAllSigsValid;
756
757 m_xSigsInvalidImg->set_visible( bShowInvalidState && !bSomePartial);
758 m_xSigsInvalidFI->set_visible( bShowInvalidState && !bSomePartial);
759
760 bool bShowNotValidatedState = nInfos && bAllSigsValid && !bAllCertsValid;
761
762 m_xSigsNotvalidatedImg->set_visible(bShowNotValidatedState);
763 m_xSigsNotvalidatedFI->set_visible(bShowNotValidatedState);
764
765 //bAllNewSignatures is always true if we are not in document mode
766 bool bShowOldSignature = nInfos && bAllSigsValid && bAllCertsValid && !bAllNewSignatures;
767 m_xSigsOldSignatureImg->set_visible(bShowOldSignature || bSomePartial);
768 m_xSigsOldSignatureFI->set_visible(bShowOldSignature || bSomePartial);
769
770 SignatureHighlightHdl(*m_xSignaturesLB);
771}
772
773uno::Reference<security::XCertificate> DigitalSignaturesDialog::getCertificate(const SignatureInformation& rInfo)
774{
775 uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureManager.getSecurityEnvironment();
776 uno::Reference<xml::crypto::XSecurityEnvironment> xGpgSecEnv = maSignatureManager.getGpgSecurityEnvironment();
777 uno::Reference<security::XCertificate> xCert;
778
779 //First we try to get the certificate which is embedded in the XML Signature
780 if (xSecEnv.is() && rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->X509Certificate.isEmpty())
781 xCert = xSecEnv->createCertificateFromAscii(rInfo.GetSigningCertificate()->X509Certificate);
782 else {
783 //There must be an embedded certificate because we use it to get the
784 //issuer name. We cannot use /Signature/KeyInfo/X509Data/X509IssuerName
785 //because it could be modified by an attacker. The issuer is displayed
786 //in the digital signature dialog.
787 //Comparing the X509IssuerName with the one from the X509Certificate in order
788 //to find out if the X509IssuerName was modified does not work. See #i62684
789 SAL_WARN( "xmlsecurity.dialogs", "Could not find embedded certificate!");
790 }
791
792 //In case there is no embedded certificate we try to get it from a local store
793 if (!xCert.is() && xSecEnv.is() && rInfo.GetSigningCertificate())
794 {
795 xCert = xSecEnv->getCertificate(rInfo.GetSigningCertificate()->X509IssuerName,
797 }
798 if (!xCert.is() && xGpgSecEnv.is() && !rInfo.ouGpgKeyID.isEmpty())
799 xCert = xGpgSecEnv->getCertificate( rInfo.ouGpgKeyID, xmlsecurity::numericStringToBigInteger(u"") );
800
801 SAL_WARN_IF( !xCert.is(), "xmlsecurity.dialogs", "Certificate not found and can't be created!" );
802
803 return xCert;
804}
805
806uno::Reference<xml::crypto::XSecurityEnvironment> DigitalSignaturesDialog::getSecurityEnvironmentForCertificate(const uno::Reference<security::XCertificate>& xCert)
807{
808 if (xCert->getCertificateKind() == CertificateKind_OPENPGP)
810 else if (xCert->getCertificateKind() == CertificateKind_X509)
812
813 throw RuntimeException("Unknown certificate kind");
814}
815
816//If bUseTempStream is true then the temporary signature stream is used.
817//Otherwise the real signature stream is used.
818void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature)
819{
820 maSignatureManager.read(bUseTempStream, bCacheLastSignature);
821 mbVerifySignatures = false;
822}
823
825{
826 int nEntry = m_xSignaturesLB->get_selected_index();
827 if (nEntry == -1)
828 return;
829
830 sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32();
832 uno::Reference<security::XCertificate> xCert = getCertificate(rInfo);
833
834 if ( xCert.is() )
835 {
836 if (m_xViewer)
837 m_xViewer->response(RET_OK);
838
839 uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = getSecurityEnvironmentForCertificate(xCert);
840 m_xViewer = std::make_shared<CertificateViewer>(m_xDialog.get(), xSecEnv, xCert, false, nullptr);
841 weld::DialogController::runAsync(m_xViewer, [this] (sal_Int32) { m_xViewer = nullptr; });
842 }
843 else
844 {
845 if (m_xInfoBox)
846 m_xInfoBox->response(RET_OK);
847
848 m_xInfoBox = std::shared_ptr<weld::MessageDialog>(Application::CreateMessageDialog(m_xDialog.get(),
849 VclMessageType::Info, VclButtonsType::Ok,
850 XsResId(STR_XMLSECDLG_NO_CERT_FOUND)));
851 m_xInfoBox->runAsync(m_xInfoBox, [this] (sal_Int32) { m_xInfoBox = nullptr; });
852 }
853}
854
855/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XExecutableDialog > m_xDialog
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
css::uno::Reference< css::xml::crypto::XXMLSecurityContext > GetSelectedSecurityContext() const
OUString GetDescription() const
Gets the description string provided when selecting the certificate.
css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > GetSelectedCertificates()
short run() override
std::unique_ptr< weld::TreeView > m_xSignaturesLB
std::unique_ptr< weld::Button > m_xCloseBtn
std::unique_ptr< weld::Label > m_xHintDocFT
std::unique_ptr< weld::Label > m_xSigsInvalidFI
std::unique_ptr< weld::Button > m_xRemoveBtn
std::shared_ptr< weld::MessageDialog > m_xInfoBox
std::shared_ptr< CertificateViewer > m_xViewer
DigitalSignaturesDialog(weld::Window *pParent, const css::uno::Reference< css::uno::XComponentContext > &rxCtx, DocumentSignatureMode eMode, bool bReadOnly, OUString sODFVersion, bool bHasDocumentSignature)
std::unique_ptr< weld::CheckButton > m_xAdESCompliantCB
std::unique_ptr< weld::Label > m_xSigsValidFI
std::unique_ptr< weld::Label > m_xHintBasicFT
css::uno::Reference< css::security::XCertificate > getCertificate(const SignatureInformation &rInfo)
std::unique_ptr< weld::Label > m_xHintPackageFT
std::unique_ptr< weld::Image > m_xSigsInvalidImg
void GetCertificateManager(OUString &aPath, OUString &sExecutable, OUString &sFoundGUIServer)
virtual ~DigitalSignaturesDialog() override
bool GetPathAllOS(OUString &aPath)
std::unique_ptr< weld::Image > m_xSigsValidImg
void SetStorage(const css::uno::Reference< css::embed::XStorage > &rxStore)
std::unique_ptr< weld::Image > m_xSigsNotvalidatedImg
std::unique_ptr< weld::Image > m_xSigsOldSignatureImg
void ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature)
void SetSignatureStream(const css::uno::Reference< css::io::XStream > &rxStream)
std::unique_ptr< weld::Button > m_xViewBtn
DocumentSignatureManager maSignatureManager
std::unique_ptr< weld::Label > m_xSigsNotvalidatedFI
std::unique_ptr< weld::Button > m_xAddBtn
std::unique_ptr< weld::Button > m_xStartCertMgrBtn
std::unique_ptr< weld::Label > m_xSigsOldSignatureFI
css::uno::Reference< css::xml::crypto::XSecurityEnvironment > getSecurityEnvironmentForCertificate(const css::uno::Reference< css::security::XCertificate > &xCert)
DocumentSignatureMode getSignatureMode() const
bool init()
Attempts to initialize the platform-specific crypto.
css::uno::Reference< css::xml::crypto::XSecurityEnvironment > getGpgSecurityEnvironment()
SignatureInformations & getCurrentSignatureInformations()
void setSignatureStream(const css::uno::Reference< css::io::XStream > &xSignatureStream)
XMLSignatureHelper & getSignatureHelper()
void setStore(const css::uno::Reference< css::embed::XStorage > &xStore)
const css::uno::Reference< css::embed::XStorage > & getStore() const
void read(bool bUseTempStream, bool bCacheLastSignature=true)
Read signatures from either a temp stream or the real storage.
css::uno::Reference< css::xml::crypto::XSecurityEnvironment > getSecurityEnvironment()
Get the security environment.
void SetStartVerifySignatureHdl(const Link< LinkParamNone *, bool > &rLink)
void SetStorage(const css::uno::Reference< css::embed::XStorage > &rxStorage, std::u16string_view sODFVersion)
static std::shared_ptr< ConfigurationChanges > create()
virtual void Notify(const css::uno::Sequence< OUString > &aPropertyNames)=0
virtual void ImplCommit()=0
static bool runAsync(const std::shared_ptr< DialogController > &rController, const std::function< void(sal_Int32)> &)
std::shared_ptr< weld::Dialog > m_xDialog
#define TOOLS_WARN_EXCEPTION(area, stream)
IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureHighlightHdl, weld::TreeView &, void)
DocumentSignatureAlgorithm
float u
bool bReadOnly
Mode eMode
sal_Int64 n
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
bool checkIfAllFilesAreSigned(const ::std::vector< OUString > &sElementList, const SignatureInformation &sigInfo, const DocumentSignatureAlgorithm alg)
bool CanSignWithGPG(const css::uno::Reference< css::embed::XStorage > &rxStore, std::u16string_view sOdfVersion)
DocumentSignatureAlgorithm getDocumentAlgorithm(std::u16string_view sODFVersion, const SignatureInformation &sigInfo)
bool isOOo3_2_Signature(const SignatureInformation &sigInfo)
std::vector< OUString > CreateElementList(const css::uno::Reference< css::embed::XStorage > &rxStore, DocumentSignatureMode eMode, const DocumentSignatureAlgorithm mode)
bool isODFPre_1_2(std::u16string_view sODFVersion)
OUString GetDateTimeString(const css::util::DateTime &_rDT)
Sequence< sal_Int8 > numericStringToBigInteger(std::u16string_view numeral)
Definition: biginteger.cxx:32
ConversionMode mode
OUString XsResId(TranslateId aId)
return hr
css::xml::crypto::SecurityOperationStatus nStatus
X509CertInfo const * GetSigningCertificate() const
css::util::DateTime stDateTime
RET_OK
RET_NO
RET_YES