include/sfx2/objsh.hxx | 10 + include/sfx2/strings.hrc | 1 sfx2/source/doc/guisaveas.cxx | 7 - sfx2/source/doc/objserv.cxx | 81 ++++++++++--- xmlsecurity/source/component/documentdigitalsignatures.cxx | 8 + 5 files changed, 86 insertions(+), 21 deletions(-)
New commits: commit 46722dbaa7795074e3c5043a76ae3f3a7782491e Author: TokieSan <elto...@aucegypt.edu> AuthorDate: Tue Jun 6 21:51:42 2023 +0300 Commit: Thorsten Behrens <thorsten.behr...@allotropia.de> CommitDate: Sun Jun 18 22:03:43 2023 +0200 tdf#155665 Adding option to remember signatures for each save Added the option in digital signatures dialog to remember used signature. Implemented ResignDocument function in objserv.cxx to resign after every save in case the option to remember signature is on. Added a new dialog box that checks whether there is a need to remember the signature. Change-Id: Ia7dbcc952044e9542e3fe6cd84b5d6633fcd1461 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152687 Reviewed-by: Heiko Tietze <heiko.tie...@documentfoundation.org> Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de> Tested-by: Thorsten Behrens <thorsten.behr...@allotropia.de> diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx index b29fb43d77e4..15533c2954ca 100644 --- a/include/sfx2/objsh.hxx +++ b/include/sfx2/objsh.hxx @@ -190,6 +190,7 @@ private: // sal_False := new object bool bIsInGenerateThumbnail; //optimize thumbnail generate and store procedure to improve odt saving performance, i120030 bool mbAvoidRecentDocs; ///< Avoid adding to the recent documents list, if not necessary. + bool bRememberSignature; // Do we want to remember the signature. enum TriState {undefined, yes, no}; TriState mbContinueImportOnFilterExceptions = undefined; // try to import as much as possible @@ -199,6 +200,8 @@ private: SAL_DLLPRIVATE void UpdateTime_Impl(const css::uno::Reference< css::document::XDocumentProperties> & i_xDocProps); + css::uno::Sequence< css::security::DocumentSignatureInformation > rSignatureInfosRemembered; + SAL_DLLPRIVATE bool SaveTo_Impl(SfxMedium &rMedium, const SfxItemSet* pSet ); protected: @@ -350,13 +353,14 @@ public: void AfterSigning(bool bSignSuccess, bool bSignScriptingContent); bool HasValidSignatures() const; SignatureState GetDocumentSignatureState(); - void SignDocumentContent(weld::Window* pDialogParent); + bool SignDocumentContent(weld::Window* pDialogParent); css::uno::Sequence<css::security::DocumentSignatureInformation> GetDocumentSignatureInformation( bool bScriptingContent, const css::uno::Reference<css::security::XDocumentDigitalSignatures>& xSigner = css::uno::Reference<css::security::XDocumentDigitalSignatures>()); bool SignDocumentContentUsingCertificate(const css::uno::Reference<css::security::XCertificate>& xCertificate); + bool ResignDocument(css::uno::Sequence< css::security::DocumentSignatureInformation >& rSignaturesInfo); void SignSignatureLine(weld::Window* pDialogParent, const OUString& aSignatureLineId, const css::uno::Reference<css::security::XCertificate>& xCert, @@ -364,7 +368,7 @@ public: const css::uno::Reference<css::graphic::XGraphic>& xInvalidGraphic, const OUString& aComment); SignatureState GetScriptingSignatureState(); - void SignScriptingContent(weld::Window* pDialogParent); + bool SignScriptingContent(weld::Window* pDialogParent); DECL_DLLPRIVATE_LINK(SignDocumentHandler, weld::Button&, void); virtual std::shared_ptr<SfxDocumentInfoDialog> CreateDocumentInfoDialog(weld::Window* pParent, const SfxItemSet& rItemSet); @@ -458,6 +462,8 @@ public: /// Don't add to the recent documents - it's an expensive operation, sometimes it is not wanted. bool IsAvoidRecentDocs() const { return mbAvoidRecentDocs; } + bool IsRememberingSignature() const { return bRememberSignature; } + /// Don't add to the recent documents - it's an expensive operation, sometimes it is not wanted. void AvoidRecentDocs(bool bAvoid) { mbAvoidRecentDocs = bAvoid; } diff --git a/include/sfx2/strings.hrc b/include/sfx2/strings.hrc index bd2c0b5d5630..3ccc50cb0947 100644 --- a/include/sfx2/strings.hrc +++ b/include/sfx2/strings.hrc @@ -149,6 +149,7 @@ #define RID_SVXSTR_XMLSEC_QUERY_LOSINGSIGNATURE NC_("RID_SVXSTR_XMLSEC_QUERY_LOSINGSIGNATURE", "Saving will remove all existing signatures.\nDo you want to continue saving the document?") #define RID_SVXSTR_XMLSEC_QUERY_SAVEBEFORESIGN NC_("RID_SVXSTR_XMLSEC_QUERY_SAVEBEFORESIGN", "The document has to be saved before it can be signed.\nDo you want to save the document?") #define STR_QUERY_CANCELCHECKOUT NC_("STR_QUERY_CANCELCHECKOUT", "This will discard all changes on the server since check-out.\nDo you want to proceed?") +#define STR_QUERY_REMEMBERSIGNATURE NC_("STR_QUERY_REMEMBERSIGNATURE", "Do you want to remember that signature for each save?") #define STR_INFO_WRONGDOCFORMAT NC_("STR_INFO_WRONGDOCFORMAT", "This document must be saved in OpenDocument file format before it can be digitally signed.") #define RID_XMLSEC_DOCUMENTSIGNED NC_("RID_XMLSEC_DOCUMENTSIGNED", " (Signed)") #define STR_EMBEDDED_TITLE NC_("STR_EMBEDDED_TITLE", " (Embedded document)") diff --git a/sfx2/source/doc/guisaveas.cxx b/sfx2/source/doc/guisaveas.cxx index b6d4ce61d8a6..272d68fedac6 100644 --- a/sfx2/source/doc/guisaveas.cxx +++ b/sfx2/source/doc/guisaveas.cxx @@ -1487,11 +1487,14 @@ bool SfxStoringHelper::GUIStoreModel( const uno::Reference< frame::XModel >& xMo if (!comphelper::LibreOfficeKit::isActive() && !( m_nStoreMode & EXPORT_REQUESTED ) ) { + SfxObjectShell* pDocShell = SfxViewShell::Current()->GetObjectShell(); + // if it is no export, warn user that the signature will be removed - if ( SignatureState::OK == nDocumentSignatureState + if ( !pDocShell->IsRememberingSignature() + && (SignatureState::OK == nDocumentSignatureState || SignatureState::INVALID == nDocumentSignatureState || SignatureState::NOTVALIDATED == nDocumentSignatureState - || SignatureState::PARTIAL_OK == nDocumentSignatureState) + || SignatureState::PARTIAL_OK == nDocumentSignatureState) ) { std::unique_ptr<weld::MessageDialog> xMessageBox(Application::CreateMessageDialog(SfxStoringHelper::GetModelWindow(xModel), VclMessageType::Question, VclButtonsType::YesNo, SfxResId(RID_SVXSTR_XMLSEC_QUERY_LOSINGSIGNATURE))); diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx index 78c4fd01f667..f321cbfc74a7 100644 --- a/sfx2/source/doc/objserv.cxx +++ b/sfx2/source/doc/objserv.cxx @@ -532,6 +532,8 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq) sal_uInt16 nId = rReq.GetSlot(); + bool bHaveWeSigned = false; + if( SID_SIGNATURE == nId || SID_MACRO_SIGNATURE == nId ) { if ( QueryHiddenInformation( HiddenWarningFact::WhenSigning, nullptr ) == RET_YES ) @@ -541,7 +543,8 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq) uno::Reference<security::XCertificate> xCertificate = GetSignPDFCertificate(); if (xCertificate.is()) { - SignDocumentContentUsingCertificate(xCertificate); + + bHaveWeSigned |= SignDocumentContentUsingCertificate(xCertificate); // Reload to show how the PDF actually looks like after signing. This also // changes "finish signing" on the infobar back to "sign document" as a side @@ -568,14 +571,31 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq) } else { - SignDocumentContent(pDialogParent); + bHaveWeSigned |= SignDocumentContent(pDialogParent); } } else { - SignScriptingContent(pDialogParent); + bHaveWeSigned |= SignScriptingContent(pDialogParent); } } + + if ( bHaveWeSigned && HasValidSignatures() ) + { + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog( pDialogParent, + VclMessageType::Question, VclButtonsType::YesNo, SfxResId(STR_QUERY_REMEMBERSIGNATURE))); + if (xBox->run() == RET_YES) + { + rSignatureInfosRemembered = GetDocumentSignatureInformation(false); + bRememberSignature = true; + } + else + { + rSignatureInfosRemembered = uno::Sequence< security::DocumentSignatureInformation >(); + bRememberSignature = false; + } + } + return; } @@ -1207,6 +1227,9 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq) } } + if (nId == SID_SAVEDOC && bRememberSignature && rSignatureInfosRemembered.hasElements()) + ResignDocument(rSignatureInfosRemembered); + rReq.SetReturnValue( SfxBoolItem(0, nErrorCode == ERRCODE_NONE ) ); ResetError(); @@ -1527,9 +1550,10 @@ void SfxObjectShell::GetState_Impl(SfxItemSet &rSet) aInfobarType = InfobarType::DANGER; break; case SignatureState::INVALID: - sMessage = SfxResId(STR_SIGNATURE_INVALID); + // If we are remembering the certificates, it should be kept as valid + sMessage = SfxResId(bRememberSignature ? STR_SIGNATURE_OK : STR_SIGNATURE_INVALID); // Warning only, I've tried Danger and it looked too scary - aInfobarType = InfobarType::WARNING; + aInfobarType = ( bRememberSignature ? InfobarType::INFO : InfobarType::WARNING ); break; case SignatureState::NOTVALIDATED: sMessage = SfxResId(STR_SIGNATURE_NOTVALIDATED); @@ -1880,11 +1904,15 @@ bool SfxObjectShell::PrepareForSigning(weld::Window* pDialogParent) if (nVersion >= SvtSaveOptions::ODFSVER_012) { OUString sQuestion(bHasSign ? SfxResId(STR_XMLSEC_QUERY_SAVESIGNEDBEFORESIGN) : SfxResId(RID_SVXSTR_XMLSEC_QUERY_SAVEBEFORESIGN)); - std::unique_ptr<weld::MessageDialog> xQuestion(Application::CreateMessageDialog(pDialogParent, - VclMessageType::Question, VclButtonsType::YesNo, sQuestion)); + std::unique_ptr<weld::MessageDialog> xQuestion; + if (!bRememberSignature) + { + xQuestion = std::unique_ptr<weld::MessageDialog>(Application::CreateMessageDialog(pDialogParent, + VclMessageType::Question, VclButtonsType::YesNo, sQuestion)); + } - if (xQuestion->run() == RET_YES) + if ( bRememberSignature || ( xQuestion != nullptr && xQuestion->run() == RET_YES ) ) { sal_uInt16 nId = SID_SAVEDOC; if ( !GetMedium() || GetMedium()->GetName().isEmpty() ) @@ -1932,7 +1960,7 @@ bool SfxObjectShell::PrepareForSigning(weld::Window* pDialogParent) // the document is not modified currently, so it can not become modified after signing pImpl->m_bAllowModifiedBackAfterSigning = false; - if ( IsEnableSetModified() ) + if ( IsEnableSetModified() || /*bRememberSignature == */true ) { EnableSetModified( false ); pImpl->m_bAllowModifiedBackAfterSigning = true; @@ -1968,7 +1996,7 @@ void SfxObjectShell::AfterSigning(bool bSignSuccess, bool bSignScriptingContent) if ( bSignSuccess ) RecheckSignature(bSignScriptingContent); - if ( pImpl->m_bAllowModifiedBackAfterSigning ) + if ( pImpl->m_bAllowModifiedBackAfterSigning || /* bRememberSignature ==*/ true ) EnableSetModified(); } @@ -2041,17 +2069,36 @@ SignatureState SfxObjectShell::GetDocumentSignatureState() return ImplGetSignatureState(); } -void SfxObjectShell::SignDocumentContent(weld::Window* pDialogParent) +bool SfxObjectShell::SignDocumentContent(weld::Window* pDialogParent) { if (!PrepareForSigning(pDialogParent)) - return; + return false; if (CheckIsReadonly(false, pDialogParent)) - return; + return false; bool bSignSuccess = GetMedium()->SignContents_Impl(pDialogParent, false, HasValidSignatures()); AfterSigning(bSignSuccess, false); + + return bSignSuccess; +} + +bool SfxObjectShell::ResignDocument(uno::Sequence< security::DocumentSignatureInformation >& rSignaturesInfo) +{ + bool bSignSuccess = true; + + // This should be at most one element, automatic iteration to avoid pointing issues in case no signs + for (auto & rInfo : rSignaturesInfo) + { + auto xCert = rInfo.Signer; + if (xCert.is()) + { + bSignSuccess &= SignDocumentContentUsingCertificate(xCert); + } + } + + return bSignSuccess; } bool SfxObjectShell::SignDocumentContentUsingCertificate(const Reference<XCertificate>& xCertificate) @@ -2162,17 +2209,19 @@ SignatureState SfxObjectShell::GetScriptingSignatureState() return ImplGetSignatureState( true ); } -void SfxObjectShell::SignScriptingContent(weld::Window* pDialogParent) +bool SfxObjectShell::SignScriptingContent(weld::Window* pDialogParent) { if (!PrepareForSigning(pDialogParent)) - return; + return false; if (CheckIsReadonly(true, pDialogParent)) - return; + return false; bool bSignSuccess = GetMedium()->SignContents_Impl(pDialogParent, true, HasValidSignatures()); AfterSigning(bSignSuccess, true); + + return bSignSuccess; } const uno::Sequence<sal_Int8>& SfxObjectShell::getUnoTunnelId() diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx index 990fa5dea739..0fd029fc2d81 100644 --- a/xmlsecurity/source/component/documentdigitalsignatures.cxx +++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx @@ -869,7 +869,13 @@ bool DocumentDigitalSignatures::signWithCertificateImpl( aSignatureManager.setSignatureStream(xStream); aSignatureManager.setModel(xModel); - Reference<XXMLSecurityContext> xSecurityContext = aSignatureManager.getSecurityContext(); + Reference<XXMLSecurityContext> xSecurityContext; + Reference<XServiceInfo> xServiceInfo(xCertificate, UNO_QUERY); + if (xServiceInfo->getImplementationName() + == "com.sun.star.xml.security.gpg.XCertificate_GpgImpl") + xSecurityContext = aSignatureManager.getGpgSecurityContext(); + else + xSecurityContext = aSignatureManager.getSecurityContext(); sal_Int32 nSecurityId;