diff options
Diffstat (limited to 'xmlsecurity/source')
-rw-r--r-- | xmlsecurity/source/component/documentdigitalsignatures.cxx | 2 | ||||
-rw-r--r-- | xmlsecurity/source/dialogs/certificatechooser.cxx | 3 | ||||
-rw-r--r-- | xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx | 77 | ||||
-rw-r--r-- | xmlsecurity/source/helper/xmlsignaturehelper.cxx | 68 | ||||
-rw-r--r-- | xmlsecurity/source/xmlsec/nss/ciphercontext.cxx | 5 | ||||
-rw-r--r-- | xmlsecurity/source/xmlsec/saxhelper.cxx | 15 |
6 files changed, 153 insertions, 17 deletions
diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx index 4ad63b36ed..c1768c0e95 100644 --- a/xmlsecurity/source/component/documentdigitalsignatures.cxx +++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx @@ -709,7 +709,7 @@ DocumentDigitalSignatures::chooseCertificatesImpl(std::map<OUString, OUString>& xSecContexts.push_back(aSignatureManager.getGpgSecurityContext()); } - CertificateChooser* aChooser = CertificateChooser::getInstance(Application::GetFrameWeld(mxParentWindow), std::move(xSecContexts), eAction); + std::unique_ptr<CertificateChooser> aChooser = CertificateChooser::getInstance(Application::GetFrameWeld(mxParentWindow), std::move(xSecContexts), eAction); if (aChooser->run() != RET_OK) return { Reference< css::security::XCertificate >(nullptr) }; diff --git a/xmlsecurity/source/dialogs/certificatechooser.cxx b/xmlsecurity/source/dialogs/certificatechooser.cxx index 9dba3e9e90..7305490933 100644 --- a/xmlsecurity/source/dialogs/certificatechooser.cxx +++ b/xmlsecurity/source/dialogs/certificatechooser.cxx @@ -56,7 +56,6 @@ CertificateChooser::CertificateChooser(weld::Window* _pParent, { auto nControlWidth = m_xCertLB->get_approximate_digit_width() * 105; m_xCertLB->set_size_request(nControlWidth, m_xCertLB->get_height_rows(12)); - m_xCertLB->make_sorted(); m_xCertLB->connect_changed( LINK( this, CertificateChooser, CertificateHighlightHdl ) ); m_xCertLB->connect_row_activated( LINK( this, CertificateChooser, CertificateSelectHdl ) ); @@ -136,6 +135,7 @@ void CertificateChooser::ImplInitialize(bool mbSearch) return; m_xCertLB->clear(); + m_xCertLB->make_unsorted(); m_xCertLB->freeze(); SvtUserOptions aUserOpts; @@ -257,6 +257,7 @@ void CertificateChooser::ImplInitialize(bool mbSearch) m_xCertLB->thaw(); m_xCertLB->unselect_all(); + m_xCertLB->make_sorted(); if (oSelectRow) { diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx index 3cd13c6060..8349a58a31 100644 --- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx +++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx @@ -74,6 +74,10 @@ #include <Shlobj.h> #endif +#if defined MACOSX +#include <sys/stat.h> +#endif + using namespace comphelper; using namespace css::security; using namespace css::uno; @@ -121,6 +125,12 @@ namespace u"GNU\\GnuPG\\bin\\kleopatra.exe", u"GNU\\GnuPG\\bin\\launch-gpa.exe", u"GNU\\GnuPG\\bin\\gpa.exe"}; +#elif defined MACOSX + constexpr std::u16string_view aGUIServers[] + = { u"/Applications/GPG Keychain.app", + u"/Applications/Trusted Key Manager.app", // tdf#147291 + u"/Applications/SCinterface/scManager.app", // tdf#147291 + u"/System/Applications/Utilities/Keychain Access.app"}; #else constexpr std::u16string_view aGUIServers[] = { u"kleopatra", u"seahorse", u"gpa", u"kgpg"}; @@ -154,26 +164,55 @@ void GetCertificateManager(OUString& sExecutable) OUString aCetMgrConfig = officecfg::Office::Common::Security::Scripting::CertMgrPath::get(); if (!aCetMgrConfig.isEmpty()) { + if (aCetMgrConfig.indexOf('/') != -1 #ifdef _WIN32 - sal_Int32 nLastBackslashIndex = aCetMgrConfig.lastIndexOf('\\'); -#else - sal_Int32 nLastBackslashIndex = aCetMgrConfig.lastIndexOf('/'); + || aCetMgrConfig.indexOf('\\') != -1 #endif + ) + { + sExecutable = aCetMgrConfig; + return; + } osl::FileBase::RC searchError = osl::File::searchFileURL( - aCetMgrConfig.copy(0, nLastBackslashIndex + 1), aPath, + aCetMgrConfig, aPath, aFoundGUIServer); if (searchError == osl::FileBase::E_None) + { + osl::File::getSystemPathFromFileURL(aFoundGUIServer, sExecutable); return; + } } for (const auto& rServer: aGUIServers) { - osl::FileBase::RC searchError = osl::File::searchFileURL( - OUString(rServer), aPath, - aFoundGUIServer); - if (searchError == osl::FileBase::E_None) + bool bSetCertMgrPath = false; + +#ifdef MACOSX + // On macOS, the list of default certificate manager applications + // includes absolute paths so check if the path exists and is a + // directory + if (rServer.starts_with('/')) + { + OString aSysPath = OUString(rServer).toUtf8(); + if (struct stat st; stat(aSysPath.getStr(), &st) == 0 && S_ISDIR(st.st_mode)) + { + bSetCertMgrPath = true; + sExecutable = rServer; + } + } +#endif + + if (!bSetCertMgrPath) + { + osl::FileBase::RC searchError = osl::File::searchFileURL( + OUString(rServer), aPath, + aFoundGUIServer); + if (searchError == osl::FileBase::E_None && osl::File::getSystemPathFromFileURL(aFoundGUIServer, sExecutable) == osl::FileBase::E_None) + bSetCertMgrPath = true; + } + + if (bSetCertMgrPath) { - osl::File::getSystemPathFromFileURL(aFoundGUIServer, sExecutable); std::shared_ptr<comphelper::ConfigurationChanges> pBatch( comphelper::ConfigurationChanges::create()); officecfg::Office::Common::Security::Scripting::CertMgrPath::set(sExecutable, @@ -470,7 +509,7 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, weld::Button&, void) if (DocumentSignatureHelper::CanSignWithGPG(maSignatureManager.getStore(), m_sODFVersion)) xSecContexts.push_back(maSignatureManager.getGpgSecurityContext()); - CertificateChooser* aChooser = CertificateChooser::getInstance(m_xDialog.get(), std::move(xSecContexts), UserAction::Sign); + std::unique_ptr<CertificateChooser> aChooser = CertificateChooser::getInstance(m_xDialog.get(), std::move(xSecContexts), UserAction::Sign); if (aChooser->run() == RET_OK) { sal_Int32 nSecurityId; @@ -551,8 +590,22 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, CertMgrButtonHdl, weld::Button&, void) uno::Reference<css::system::XSystemShellExecute> xSystemShell( css::system::SystemShellExecute::create(xContext)); - xSystemShell->execute(sExecutable, OUString(), - css::system::SystemShellExecuteFlags::DEFAULTS); + try + { + xSystemShell->execute(sExecutable, OUString(), + css::system::SystemShellExecuteFlags::DEFAULTS); + } + catch (...) + { + // Related tdf#159307 fix uncloseable windows due to uncaught exception + // XSystemShellExecute::execute() throws an exception for a variety + // of common error conditions such as files or directories that + // are non-existent or non-executable. Failure to catch such + // exceptions would cause the document window to be uncloseable + // and the application to be unquittable. + TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "executable failed!" ); + sExecutable = OUString(); + } } OUString sDialogText = (sExecutable.isEmpty() ? diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx index 0b5825b125..3b13f79f33 100644 --- a/xmlsecurity/source/helper/xmlsignaturehelper.cxx +++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx @@ -22,6 +22,7 @@ #include <documentsignaturehelper.hxx> #include <xsecctl.hxx> #include <biginteger.hxx> +#include <certificate.hxx> #include <UriBindingHelper.hxx> @@ -702,7 +703,72 @@ XMLSignatureHelper::CheckAndUpdateSignatureInformation( } if (CheckX509Data(xSecEnv, temp, certs, tempResult)) { - datas.emplace_back(tempResult); + if (rInfo.maEncapsulatedX509Certificates.empty()) // optional, XAdES + { + datas.emplace_back(tempResult); + } + else + { + // check for consistency between X509Data and EncapsulatedX509Certificate + // (LO produces just the signing certificate in X509Data and + // the entire chain in EncapsulatedX509Certificate so in this case + // using EncapsulatedX509Certificate yields additional intermediate + // certificates that may help in verifying) + std::vector<SignatureInformation::X509CertInfo> encapsulatedCertInfos; + for (OUString const& it : rInfo.maEncapsulatedX509Certificates) + { + encapsulatedCertInfos.emplace_back(); + encapsulatedCertInfos.back().X509Certificate = it; + } + std::vector<uno::Reference<security::XCertificate>> encapsulatedCerts; + SignatureInformation::X509Data encapsulatedResult; + if (CheckX509Data(xSecEnv, encapsulatedCertInfos, encapsulatedCerts, encapsulatedResult)) + { + auto const pXCertificate(dynamic_cast<xmlsecurity::Certificate*>(certs.back().get())); + auto const pECertificate(dynamic_cast<xmlsecurity::Certificate*>(encapsulatedCerts.back().get())); + assert(pXCertificate && pECertificate); // was just created by CheckX509Data + if (pXCertificate->getSHA256Thumbprint() == pECertificate->getSHA256Thumbprint()) + { + // both are chains - take the longer one + if (encapsulatedCerts.size() < certs.size()) + { + datas.emplace_back(tempResult); + } + else + { +#if 0 + // extra info needed in testSigningMultipleTimes_ODT + // ... but with it, it fails with BROKEN signature? + // fails even on the first signature, because somehow + // the xd:SigningCertificate element was signed + // containing only one certificate, but in the final + // file it contains all 3 certificates due to this here. + for (size_t i = 0; i < encapsulatedResult.size(); ++i) + { + encapsulatedResult[i].X509IssuerName = encapsulatedCerts[i]->getIssuerName(); + encapsulatedResult[i].X509SerialNumber = xmlsecurity::bigIntegerToNumericString(encapsulatedCerts[i]->getSerialNumber()); + encapsulatedResult[i].X509Subject = encapsulatedCerts[i]->getSubjectName(); + auto const pCertificate(dynamic_cast<xmlsecurity::Certificate*>(encapsulatedCerts[i].get())); + assert(pCertificate); // this was just created by CheckX509Data + OUStringBuffer aBuffer; + comphelper::Base64::encode(aBuffer, pCertificate->getSHA256Thumbprint()); + encapsulatedResult[i].CertDigest = aBuffer.makeStringAndClear(); + } + datas.emplace_back(encapsulatedResult); +#else + // keep the X509Data stuff in datas but return the + // longer EncapsulatedX509Certificate chain + datas.emplace_back(tempResult); +#endif + certs = encapsulatedCerts; // overwrite this seems easier + } + } + else + { + SAL_WARN("xmlsecurity.comp", "X509Data and EncapsulatedX509Certificate contain different certificates"); + } + } + } } // rInfo is a copy, update the original diff --git a/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx b/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx index c3bbfdb0f2..e5f2a89d11 100644 --- a/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx +++ b/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx @@ -326,7 +326,10 @@ uno::Sequence< ::sal_Int8 > SAL_CALL OCipherContext::finalizeCipherContextAndDis if ( nPaddingSize > 1 ) { rtlRandomPool aRandomPool = rtl_random_createPool(); - rtl_random_getBytes( aRandomPool, pLastBlock + nOldLastBlockLen, nPaddingSize - 1 ); + if (rtl_random_getBytes(aRandomPool, pLastBlock + nOldLastBlockLen, nPaddingSize - 1) != rtl_Random_E_None) + { + throw uno::RuntimeException("rtl_random_getBytes failed"); + } rtl_random_destroyPool ( aRandomPool ); } pLastBlock[m_aLastBlock.getLength() - 1] = static_cast< sal_Int8 >( nPaddingSize ); diff --git a/xmlsecurity/source/xmlsec/saxhelper.cxx b/xmlsecurity/source/xmlsec/saxhelper.cxx index ff576db496..0d39584894 100644 --- a/xmlsecurity/source/xmlsec/saxhelper.cxx +++ b/xmlsecurity/source/xmlsec/saxhelper.cxx @@ -118,11 +118,24 @@ SAXHelper::SAXHelper( ) * compile error: * xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS ; */ +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4996) +#endif xmlSubstituteEntitiesDefault(0) ; - #ifndef XMLSEC_NO_XSLT xmlIndentTreeOutput = 1 ; #endif /* XMLSEC_NO_XSLT */ +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif m_pParserCtxt = xmlNewParserCtxt() ; |