diff options
author | Jan-Marek Glogowski <jan-marek.glogowski@extern.cib.de> | 2019-10-22 17:56:15 +0000 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2020-07-03 17:13:12 +0200 |
commit | b1d0d0cf866ac7235cd23ff862a8f2e9085148d8 (patch) | |
tree | e5cb49b7fad2b5b072e58ebc3a9071734d2270a0 /xmlsecurity | |
parent | 47c098e5760537e8c43a92c9dbe16ace3902a19d (diff) |
[API CHANGE] Move NSS profile handling into NSS service
While developing the patchset for tdf#127909, I broke the
certificate path dialog, because I wasn't aware, that the
NSSInitializer service has to use the same logic to auto-
select the users profile, then the dialog. So currently you
have to keep the complex service and dialog auto-select
logic in sync.
To prevent this error, this moves all the profile auto-selection
and enumeration into the NSSInitializer service. What I also
stumbled over is the particular lifecycle of the NSS library
initialization in the NSS service. This is just done, when the
first user calls some crypto function. As a result it's actually
possible to change the path setting without restarting
LibreOffice. But since the NSS deninitialization is run as an
atexit handler, this setting can't be changed after the init.
What is currently missing is any indication inside the dialog of
the currently active NSS setting in comparison to any later user
selection, if the user doesn't restart LibreOffice as requested.
Change-Id: I886962777958c363abeb0ec91fc8a35cbd39eb98
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97668
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Diffstat (limited to 'xmlsecurity')
-rw-r--r-- | xmlsecurity/source/xmlsec/nss/nssinitializer.cxx | 162 | ||||
-rw-r--r-- | xmlsecurity/source/xmlsec/nss/nssinitializer.hxx | 13 |
2 files changed, 141 insertions, 34 deletions
diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx index d64ea10a05a0..c43abe14569f 100644 --- a/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx +++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx @@ -21,6 +21,7 @@ #include <com/sun/star/mozilla/XMozillaBootstrap.hpp> #include <com/sun/star/xml/crypto/DigestID.hpp> #include <com/sun/star/xml/crypto/CipherID.hpp> +#include <com/sun/star/xml/crypto/NSSInitializer.hpp> #include <com/sun/star/uno/XComponentContext.hpp> #include <cppuhelper/supportsservice.hxx> #include <officecfg/Office/Common.hxx> @@ -33,6 +34,7 @@ #include <tools/diagnose_ex.h> #include <unotools/tempfile.hxx> #include <salhelper/singletonref.hxx> +#include <comphelper/sequence.hxx> #include <nss/nssinitializer.hxx> @@ -144,8 +146,35 @@ void deleteRootsModule() } } -OString getMozillaCurrentProfile( const css::uno::Reference< css::uno::XComponentContext > &rxContext ) +#endif + +bool lcl_pathExists(const OUString& sPath) { + if (sPath.isEmpty()) + return false; + + ::osl::DirectoryItem aPathItem; + OUString sURL; + osl::FileBase::getFileURLFromSystemPath(sPath, sURL); + if (::osl::FileBase::E_None == ::osl::DirectoryItem::get(sURL, aPathItem)) + { + ::osl::FileStatus aStatus = osl_FileStatus_Mask_Validate; + if (::osl::FileBase::E_None == aPathItem.getFileStatus(aStatus)) + return true; + } + + return false; +} + +} // namespace + +OUString ONSSInitializer::getMozillaCurrentProfile(const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool bSetActive) +{ + if (m_bIsNSSinitialized) + return m_sNSSPath; + if (bSetActive) + m_bIsNSSinitialized = true; + // first, try to get the profile from "MOZILLA_CERTIFICATE_FOLDER" const char* pEnv = getenv("MOZILLA_CERTIFICATE_FOLDER"); if (pEnv) @@ -153,30 +182,33 @@ OString getMozillaCurrentProfile( const css::uno::Reference< css::uno::XComponen SAL_INFO( "xmlsecurity.xmlsec", "Using Mozilla profile from MOZILLA_CERTIFICATE_FOLDER=" << pEnv); - return pEnv; + m_sNSSPath = OStringToOUString(pEnv, osl_getThreadTextEncoding()); } // second, try to get saved user-preference - try + if (m_sNSSPath.isEmpty()) { - OUString sUserSetCertPath = - officecfg::Office::Common::Security::Scripting::CertDir::get().value_or(OUString()); + try + { + OUString sUserSetCertPath = + officecfg::Office::Common::Security::Scripting::CertDir::get().value_or(OUString()); - if (!sUserSetCertPath.isEmpty()) + if (lcl_pathExists(sUserSetCertPath)) + { + SAL_INFO( + "xmlsecurity.xmlsec", + "Using Mozilla profile from /org.openoffice.Office.Common/" + "Security/Scripting/CertDir: " << sUserSetCertPath); + m_sNSSPath = sUserSetCertPath; + } + } + catch (const uno::Exception &) { - SAL_INFO( - "xmlsecurity.xmlsec", - "Using Mozilla profile from /org.openoffice.Office.Common/" - "Security/Scripting/CertDir: " << sUserSetCertPath); - return OUStringToOString(sUserSetCertPath, osl_getThreadTextEncoding()); + TOOLS_WARN_EXCEPTION("xmlsecurity.xmlsec", "getMozillaCurrentProfile:"); } } - catch (const uno::Exception &) - { - TOOLS_WARN_EXCEPTION("xmlsecurity.xmlsec", "getMozillaCurrentProfile:"); - } - // third, dig around to see if there's one available + // third, dig around to see if there's one default available mozilla::MozillaProductType productTypes[3] = { mozilla::MozillaProductType_Thunderbird, mozilla::MozillaProductType_Firefox, @@ -196,20 +228,95 @@ OString getMozillaCurrentProfile( const css::uno::Reference< css::uno::XComponen if (!profile.isEmpty()) { - OUString sProfilePath = xMozillaBootstrap->getProfilePath( productTypes[i], profile ); - SAL_INFO( - "xmlsecurity.xmlsec", - "Using Mozilla profile " << sProfilePath); - return OUStringToOString(sProfilePath, osl_getThreadTextEncoding()); + OUString sProfilePath = xMozillaBootstrap->getProfilePath(productTypes[i], profile); + if (m_sNSSPath.isEmpty()) + { + SAL_INFO("xmlsecurity.xmlsec", "Using Mozilla profile " << sProfilePath); + m_sNSSPath = sProfilePath; + } + break; } } } - SAL_INFO("xmlsecurity.xmlsec", "No Mozilla profile found"); - return OString(); + SAL_INFO_IF(m_sNSSPath.isEmpty(), "xmlsecurity.xmlsec", "No Mozilla profile found"); + return m_sNSSPath; } -#endif +css::uno::Sequence<css::xml::crypto::NSSProfile> SAL_CALL ONSSInitializer::getNSSProfiles() +{ + ONSSInitializer::getMozillaCurrentProfile(m_xContext); + + std::vector<xml::crypto::NSSProfile> aProfileList; + aProfileList.reserve(10); + + mozilla::MozillaProductType productTypes[3] = { + mozilla::MozillaProductType_Thunderbird, + mozilla::MozillaProductType_Firefox, + mozilla::MozillaProductType_Mozilla }; + + uno::Reference<uno::XInterface> xInstance = m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.mozilla.MozillaBootstrap", m_xContext); + OSL_ENSURE(xInstance.is(), "failed to create instance" ); + + uno::Reference<mozilla::XMozillaBootstrap> xMozillaBootstrap(xInstance,uno::UNO_QUERY); + + if (xMozillaBootstrap.is()) + { + for (int i=0; i<int(SAL_N_ELEMENTS(productTypes)); ++i) + { + uno::Sequence<OUString> aProductProfileList; + xMozillaBootstrap->getProfileList(productTypes[i], aProductProfileList); + for (const auto& sProfile : std::as_const(aProductProfileList)) + aProfileList.push_back({sProfile, xMozillaBootstrap->getProfilePath(productTypes[i], sProfile), productTypes[i]}); + } + } + + OUString sUserSelect; + try + { + sUserSelect = officecfg::Office::Common::Security::Scripting::CertDir::get().value_or(OUString());; + if (!lcl_pathExists(sUserSelect)) + sUserSelect = OUString(); + } + catch (const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.xmlsec", "getMozillaCurrentProfile:"); + } + aProfileList.push_back({"MANUAL", sUserSelect, mozilla::MozillaProductType_Default}); + + const char* pEnv = getenv("MOZILLA_CERTIFICATE_FOLDER"); + aProfileList.push_back({"MOZILLA_CERTIFICATE_FOLDER", + pEnv ? OStringToOUString(pEnv, osl_getThreadTextEncoding()) : OUString(), + mozilla::MozillaProductType_Default}); + + return comphelper::containerToSequence(aProfileList); +} + +bool ONSSInitializer::m_bIsNSSinitialized = false; +OUString ONSSInitializer::m_sNSSPath; + +OUString SAL_CALL ONSSInitializer::getNSSPath() +{ + ONSSInitializer::getMozillaCurrentProfile(m_xContext); + return m_sNSSPath; +}; + +sal_Bool SAL_CALL ONSSInitializer::getIsNSSinitialized() +{ + return m_bIsNSSinitialized; +} + +ONSSInitializer::ONSSInitializer(const css::uno::Reference< css::uno::XComponentContext > &rxContext) + : m_xContext(rxContext) +{ +} + +ONSSInitializer::ONSSInitializer() +{ +} + +namespace +{ //Older versions of Firefox (FF), for example FF2, and Thunderbird (TB) 2 write //the roots certificate module (libnssckbi.so), which they use, into the @@ -238,7 +345,7 @@ bool nsscrypto_initialize(css::uno::Reference<css::uno::XComponentContext> const OString sCertDir; #ifdef XMLSEC_CRYPTO_NSS - sCertDir = getMozillaCurrentProfile(rxContext); + sCertDir = OUStringToOString(ONSSInitializer::getMozillaCurrentProfile(rxContext, true), osl_getThreadTextEncoding()); #else (void) rxContext; #endif @@ -402,11 +509,6 @@ extern "C" void nsscrypto_finalize() (*getInitNSSPrivate())->reset(); } -ONSSInitializer::ONSSInitializer( - const css::uno::Reference< css::uno::XComponentContext > &rxContext) - :m_xContext( rxContext ) -{ -} ONSSInitializer::~ONSSInitializer() { diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx index 7e1b7ff50537..2dcd821c020d 100644 --- a/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx +++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx @@ -37,15 +37,22 @@ class ONSSInitializer : public cppu::WeakImplHelper { protected: css::uno::Reference< css::uno::XComponentContext > m_xContext; + static OUString m_sNSSPath; + static bool m_bIsNSSinitialized; - ONSSInitializer() - {} + ONSSInitializer(); public: explicit ONSSInitializer(const css::uno::Reference<css::uno::XComponentContext> &rxContext); virtual ~ONSSInitializer() override; static bool initNSS( const css::uno::Reference< css::uno::XComponentContext > &rxContext ); + static OUString getMozillaCurrentProfile(const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool bSetActive = false); + + /* XNSSInitializer */ + virtual OUString SAL_CALL getNSSPath() override; + virtual sal_Bool SAL_CALL getIsNSSinitialized() override; + virtual css::uno::Sequence<css::xml::crypto::NSSProfile> SAL_CALL getNSSProfiles() override; /* XDigestContextSupplier */ virtual css::uno::Reference< css::xml::crypto::XDigestContext > SAL_CALL getDigestContext( ::sal_Int32 nDigestID, const css::uno::Sequence< css::beans::NamedValue >& aParams ) override; @@ -55,9 +62,7 @@ public: /* XServiceInfo */ virtual OUString SAL_CALL getImplementationName() override; - virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; - virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; }; |