1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
67 #include <o3tl/char16_t2wchar_t.hxx>
72 using namespace comphelper
;
73 using namespace css::security
;
74 using namespace css::uno
;
79 class SaveODFItem
: public utl::ConfigItem
84 virtual void ImplCommit() override
;
87 virtual void Notify( const css::uno::Sequence
< OUString
>& aPropertyNames
) override
;
89 //See group ODF in Common.xcs
90 bool isLessODF1_2() const
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",
109 if ( !(aValues
[0] >>= nTmp
) )
110 throw uno::RuntimeException(
111 "[xmlsecurity]SaveODFItem::SaveODFItem(): Wrong Type!",
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
) );
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();
188 case DocumentSignatureMode::Macros
:
189 m_xHintBasicFT
->show();
191 case DocumentSignatureMode::Package
:
192 m_xHintPackageFT
->show();
197 DigitalSignaturesDialog::~DigitalSignaturesDialog()
201 bool DigitalSignaturesDialog::Init()
203 bool bInit
= maSignatureManager
.init();
205 SAL_WARN_IF( !bInit
, "xmlsecurity.dialogs", "Error initializing security context!" );
209 maSignatureManager
.getSignatureHelper().SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog
, StartVerifySignatureHdl
) );
215 void DigitalSignaturesDialog::SetStorage( const css::uno::Reference
< css::embed::XStorage
>& rxStore
)
219 // PDF supports AdES.
220 m_bAdESCompliant
= true;
221 m_xAdESCompliantCB
->set_active(m_bAdESCompliant
);
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
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.
245 if (!maSignatureManager
.getStore().is())
246 // It's always possible to append a PDF signature.
249 OSL_ASSERT(maSignatureManager
.getStore().is());
250 bool bDoc1_1
= DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion
);
252 bool bSave1_1
= item
.isLessODF1_2();
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
) )
261 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_xDialog
.get(),
262 VclMessageType::Warning
, VclButtonsType::Ok
,
263 XsResId(STR_XMLSECDLG_OLD_ODF_FORMAT
)));
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
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
)
287 m_bWarningShowSignMacro
= true;
294 bool DigitalSignaturesDialog::canAdd()
296 return canAddRemove();
299 bool DigitalSignaturesDialog::canRemove()
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();
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)
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
))
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
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
)));
424 // Don't keep invalid entries...
425 ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
426 ImplFillSignaturesBox();
430 IMPL_LINK_NOARG(DigitalSignaturesDialog
, RemoveButtonHdl
, weld::Button
&, void)
434 int nEntry
= m_xSignaturesLB
->get_selected_index();
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)
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
= [] {
474 PWSTR sPath
= nullptr;
476 = SHGetKnownFolderPath(FOLDERID_ProgramFilesX86
, KF_FLAG_DEFAULT
, nullptr, &sPath
);
479 sRet
= o3tl::toU(sPath
);
480 CoTaskMemFree(sPath
);
487 static const std::u16string_view aGUIServers
[] = { u
"kleopatra", u
"seahorse", u
"gpa", u
"kgpg" };
488 const char* cPath
= getenv("PATH");
491 OUString
aPath(cPath
, strlen(cPath
), osl_getThreadTextEncoding());
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
);
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
);
519 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(m_xDialog
.get(),
520 VclMessageType::Info
, VclButtonsType::Ok
,
521 XsResId(STR_XMLSECDLG_NO_CERT_MANAGER
)));
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;
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
);
555 OUString aDateTimeStr
;
556 OUString aDescription
;
559 bool bCertValid
= false;
562 //check the validity of the cert
564 sal_Int32 certResult
= getSecurityEnvironmentForCertificate(xCert
)->verifyCertificate(xCert
,
565 Sequence
<uno::Reference
<security::XCertificate
> >());
567 bCertValid
= certResult
== css::security::CertificateValidity::VALID
;
571 } catch (css::uno::SecurityException
& ) {
572 OSL_FAIL("Verification of certificate failed");
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())
592 if (!rInfo
.ouGpgCertificate
.isEmpty())
594 // XML based: XAdES or not.
595 else if (rInfo
.GetSigningCertificate() && !rInfo
.GetSigningCertificate()->CertDigest
.isEmpty())
602 // Assume PDF: PAdES or not.
603 if (rInfo
.bHasSigningCertificate
)
609 bool bSigValid
= rInfo
.nStatus
== css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED
;
613 if (maSignatureManager
.getStore().is())
616 bSigValid
= DocumentSignatureHelper::checkIfAllFilesAreSigned(
617 aElementsToBeVerified
, rInfo
, mode
);
622 bSigValid
= !rInfo
.bPartialDocumentSignature
;
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
);
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!" );
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();
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
);
763 uno::Reference
<xml::crypto::XSecurityEnvironment
> xSecEnv
= getSecurityEnvironmentForCertificate(xCert
);
764 CertificateViewer
aViewer(m_xDialog
.get(), xSecEnv
, xCert
, false, nullptr);
769 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(m_xDialog
.get(),
770 VclMessageType::Info
, VclButtonsType::Ok
,
771 XsResId(STR_XMLSECDLG_NO_CERT_FOUND
)));
776 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */