summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2018-12-31 12:14:19 +0100
committerAndras Timar <andras.timar@collabora.com>2019-09-22 19:00:58 +0200
commit3787e1b78299ee88a17c242d0b30181286a753c4 (patch)
tree6cfd8218b7e038fcef00da8e37f803383a641b51
parent6fca83fab5a14745c3dc41eb8179d7ee0efd4e71 (diff)
NSS: create a temporary database instead of in-memory
When initializing for the in-memory database (NSS_NoDB_Init) the internal slot is read-only so a lot of actions (PK11_ImportCert) fails. Instead of that we create a new cert/key database inside the tmp directory and delete it on exit. This way there are no limitations and all the actions perform as expected. Change-Id: Iadec5dd8f3459be56ba57d077057eacf3e0797fc Reviewed-on: https://gerrit.libreoffice.org/65765 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> (cherry picked from commit 87eec1b90b6ecd83455f09168430c23f73c25c86)
-rw-r--r--xmlsecurity/Library_xsec_xmlsec.mk1
-rw-r--r--xmlsecurity/source/xmlsec/nss/nssinitializer.cxx131
-rw-r--r--xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx56
-rw-r--r--xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx23
-rw-r--r--xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx2
5 files changed, 162 insertions, 51 deletions
diff --git a/xmlsecurity/Library_xsec_xmlsec.mk b/xmlsecurity/Library_xsec_xmlsec.mk
index 8efb4911fbbb..1ddbb712b957 100644
--- a/xmlsecurity/Library_xsec_xmlsec.mk
+++ b/xmlsecurity/Library_xsec_xmlsec.mk
@@ -41,6 +41,7 @@ $(eval $(call gb_Library_use_libraries,xsec_xmlsec,\
svl \
tl \
xo \
+ utl \
))
ifeq ($(SYSTEM_XMLSEC),)
diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx
index 5d33268f741d..534c5bd7fc5c 100644
--- a/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx
+++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx
@@ -32,6 +32,8 @@
#include <osl/file.hxx>
#include <osl/thread.h>
#include <sal/log.hxx>
+#include <unotools/tempfile.hxx>
+#include <salhelper/singletonref.hxx>
#include "seinitializer_nssimpl.hxx"
@@ -40,6 +42,7 @@
#include "ciphercontext.hxx"
#include <memory>
+#include <vector>
#include <nspr.h>
#include <cert.h>
@@ -64,6 +67,97 @@ static void nsscrypto_finalize();
namespace
{
+class InitNSSPrivate
+{
+private:
+ std::unique_ptr<utl::TempFile> m_pTempFileDatabaseDirectory;
+
+ static void scanDirsAndFiles(OUString const & rDirURL, std::vector<OUString> & rDirs, std::vector<OUString> & rFiles)
+ {
+ if (rDirURL.isEmpty())
+ return;
+ osl::Directory aDirectory(rDirURL);
+
+ if (osl::FileBase::E_None != aDirectory.open())
+ return;
+
+ osl::DirectoryItem aDirectoryItem;
+
+ while (osl::FileBase::E_None == aDirectory.getNextItem(aDirectoryItem))
+ {
+ osl::FileStatus aFileStatus(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL | osl_FileStatus_Mask_FileName);
+
+ if (osl::FileBase::E_None == aDirectoryItem.getFileStatus(aFileStatus))
+ {
+ if (aFileStatus.isDirectory())
+ {
+ const OUString aFileName(aFileStatus.getFileName());
+ if (!aFileName.isEmpty())
+ rDirs.push_back(aFileName);
+ }
+ else if (aFileStatus.isRegular())
+ {
+ const OUString aFileName(aFileStatus.getFileName());
+ if (!aFileName.isEmpty())
+ rFiles.push_back(aFileName);
+
+ }
+ }
+ }
+ }
+
+ static bool deleteDirRecursively(OUString const & rDirURL)
+ {
+ std::vector<OUString> aDirs;
+ std::vector<OUString> aFiles;
+ bool bError(false);
+
+ scanDirsAndFiles(rDirURL, aDirs, aFiles);
+
+ for (const auto& sDir : aDirs)
+ {
+ const OUString aNewDirURL(rDirURL + "/" + sDir);
+ bError |= deleteDirRecursively(aNewDirURL);
+ }
+
+ for (const auto& sFile : aFiles)
+ {
+ OUString aNewFileURL(rDirURL + "/" + sFile);
+ bError |= (osl::FileBase::E_None != osl::File::remove(aNewFileURL));
+ }
+
+ bError |= (osl::FileBase::E_None != osl::Directory::remove(rDirURL));
+
+ return bError;
+ }
+
+public:
+ OUString getTempDatabasePath()
+ {
+ if (!m_pTempFileDatabaseDirectory)
+ {
+ m_pTempFileDatabaseDirectory.reset(new utl::TempFile(nullptr, true));
+ m_pTempFileDatabaseDirectory->EnableKillingFile();
+ }
+ return m_pTempFileDatabaseDirectory->GetFileName();
+ }
+
+ void reset()
+ {
+ if (m_pTempFileDatabaseDirectory)
+ {
+ deleteDirRecursively(m_pTempFileDatabaseDirectory->GetURL());
+ m_pTempFileDatabaseDirectory.reset();
+ }
+ }
+};
+
+salhelper::SingletonRef<InitNSSPrivate>* getInitNSSPrivate()
+{
+ static salhelper::SingletonRef<InitNSSPrivate> aInitNSSPrivate;
+ return &aInitNSSPrivate;
+}
+
bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool & out_nss_init );
struct InitNSSInitialize
@@ -230,7 +324,7 @@ OString getMozillaCurrentProfile( const css::uno::Reference< css::uno::XComponen
//return true - whole initialization was successful
//param out_nss_init = true: at least the NSS initialization (NSS_InitReadWrite
//was successful and therefore NSS_Shutdown should be called when terminating.
-bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool & out_nss_init )
+bool nsscrypto_initialize(css::uno::Reference<css::uno::XComponentContext> const & rxContext, bool & out_nss_init)
{
// this method must be called only once, no need for additional lock
OString sCertDir;
@@ -244,9 +338,9 @@ bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContex
PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ;
- bool bSuccess = true;
+ bool bSuccess = false;
// there might be no profile
- if ( !sCertDir.isEmpty() )
+ if (!sCertDir.isEmpty())
{
if (sCertDir.indexOf(':') == -1) //might be env var with explicit prefix
{
@@ -262,26 +356,31 @@ bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContex
sCertDir = "dbm:" + sCertDir;
}
}
- if( NSS_InitReadWrite( sCertDir.getStr() ) != SECSuccess )
+ if (NSS_InitReadWrite(sCertDir.getStr()) != SECSuccess)
{
SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with profile failed.");
int errlen = PR_GetErrorTextLength();
- if(errlen > 0)
+ if (errlen > 0)
{
std::unique_ptr<char[]> const error(new char[errlen + 1]);
PR_GetErrorText(error.get());
SAL_INFO("xmlsecurity.xmlsec", error.get());
}
- bSuccess = false;
+ }
+ else
+ {
+ bSuccess = true;
}
}
- if( sCertDir.isEmpty() || !bSuccess )
+ if (!bSuccess) // Try to create a database in temp dir
{
- SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS without profile.");
- if ( NSS_NoDB_Init(nullptr) != SECSuccess )
+ SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with a temporary profile.");
+ OUString rString = (*getInitNSSPrivate())->getTempDatabasePath();
+
+ if (NSS_InitReadWrite(rString.toUtf8().getStr()) != SECSuccess)
{
- SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS without profile failed.");
+ SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with a temporary profile.");
int errlen = PR_GetErrorTextLength();
if(errlen > 0)
{
@@ -289,7 +388,15 @@ bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContex
PR_GetErrorText(error.get());
SAL_INFO("xmlsecurity.xmlsec", error.get());
}
- return false ;
+ return false;
+ }
+ // Initialize and set empty password if needed
+ PK11SlotInfo* pSlot = PK11_GetInternalKeySlot();
+ if (pSlot)
+ {
+ if (PK11_NeedUserInit(pSlot))
+ PK11_InitPin(pSlot, nullptr, nullptr);
+ PK11_FreeSlot(pSlot);
}
}
out_nss_init = true;
@@ -383,6 +490,8 @@ extern "C" void nsscrypto_finalize()
}
PK11_LogoutAll();
(void)NSS_Shutdown();
+
+ (*getInitNSSPrivate())->reset();
}
ONSSInitializer::ONSSInitializer(
diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx
index 0da6276551af..b19ec766b5db 100644
--- a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx
+++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx
@@ -42,6 +42,7 @@
#include <comphelper/sequence.hxx>
#include "secerror.hxx"
+#include <prerror.h>
// added for password exception
#include <com/sun/star/security/NoPasswordException.hpp>
@@ -442,15 +443,34 @@ X509Certificate_NssImpl* SecurityEnvironment_NssImpl::createAndAddCertificateFro
if (!pCERTCertificate)
return nullptr;
- OString aTrustString = OUStringToOString(raString, RTL_TEXTENCODING_ASCII_US);
+ SECStatus aStatus;
+ OString aTrustString = OUStringToOString(raString, RTL_TEXTENCODING_ASCII_US);
CERTCertTrust aTrust;
- if (CERT_DecodeTrustString(&aTrust, aTrustString.getStr()) != SECSuccess)
+
+ aStatus = CERT_DecodeTrustString(&aTrust, aTrustString.getStr());
+
+ if (aStatus != SECSuccess)
+ return nullptr;
+
+ PK11SlotInfo* pSlot = PK11_GetInternalKeySlot();
+
+ if (!pSlot)
return nullptr;
- if (CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), pCERTCertificate, &aTrust) != SECSuccess)
+ aStatus = PK11_ImportCert(pSlot, pCERTCertificate, CK_INVALID_HANDLE, nullptr, PR_FALSE);
+
+ if (aStatus != SECSuccess)
return nullptr;
+ aStatus = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), pCERTCertificate, &aTrust);
+
+ if (aStatus != SECSuccess)
+ return nullptr;
+
+
+ PK11_FreeSlot(pSlot);
+
X509Certificate_NssImpl* pX509Certificate = new X509Certificate_NssImpl();
pX509Certificate->setCert(pCERTCertificate);
return pX509Certificate;
@@ -840,12 +860,10 @@ xmlSecKeysMngrPtr SecurityEnvironment_NssImpl::createKeysManager() {
// Adopt the private key of the signing certificate, if it has any.
if (auto pCertificate = dynamic_cast<X509Certificate_NssImpl*>(m_xSigningCertificate.get()))
{
- SECKEYPrivateKey* pPrivateKey = pCertificate->getPrivateKey();
- SECKEYPrivateKey* copy
- = pPrivateKey == nullptr ? nullptr : SECKEY_CopyPrivateKey(pPrivateKey);
- if (copy)
+ SECKEYPrivateKey* pPrivateKey = SECKEY_CopyPrivateKey(pCertificate->getPrivateKey());
+ if (pPrivateKey)
{
- xmlSecKeyDataPtr pKeyData = xmlSecNssPKIAdoptKey(copy, nullptr);
+ xmlSecKeyDataPtr pKeyData = xmlSecNssPKIAdoptKey(pPrivateKey, nullptr);
xmlSecKeyPtr pKey = xmlSecKeyCreate();
xmlSecKeySetValue(pKey, pKeyData);
xmlSecNssAppDefaultKeysMngrAdoptKey(pKeysMngr, pKey);
@@ -872,42 +890,40 @@ SECKEYPrivateKey* SecurityEnvironment_NssImpl::insertPrivateKey(css::uno::Sequen
if (!pSlot)
return nullptr;
- SECItem pDerPrivateKeyInfo;
- pDerPrivateKeyInfo.data = reinterpret_cast<unsigned char *>(const_cast<sal_Int8 *>(raPrivateKey.getConstArray()));
- pDerPrivateKeyInfo.len = raPrivateKey.getLength();
+ SECItem aDerPrivateKeyInfo;
+ aDerPrivateKeyInfo.data = reinterpret_cast<unsigned char *>(const_cast<sal_Int8 *>(raPrivateKey.getConstArray()));
+ aDerPrivateKeyInfo.len = raPrivateKey.getLength();
- const unsigned int aKeyUsage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
+ const unsigned int aKeyUsage = KU_ALL;
SECKEYPrivateKey* pPrivateKey = nullptr;
- bool bPermanent = false;
- bool bSensitive = false;
+ bool bPermanent = PR_FALSE;
+ bool bPrivate = PR_TRUE;
SECStatus nStatus = PK11_ImportDERPrivateKeyInfoAndReturnKey(
- pSlot, &pDerPrivateKeyInfo, nullptr, nullptr, bPermanent, bSensitive,
+ pSlot, &aDerPrivateKeyInfo, nullptr, nullptr, bPermanent, bPrivate,
aKeyUsage, &pPrivateKey, nullptr);
if (nStatus != SECSuccess)
return nullptr;
+ PK11_FreeSlot(pSlot);
+
return pPrivateKey;
}
uno::Reference<security::XCertificate> SecurityEnvironment_NssImpl::createDERCertificateWithPrivateKey(
Sequence<sal_Int8> const & raDERCertificate, Sequence<sal_Int8> const & raPrivateKey)
{
-
SECKEYPrivateKey* pPrivateKey = insertPrivateKey(raPrivateKey);
if (!pPrivateKey)
return uno::Reference<security::XCertificate>();
- X509Certificate_NssImpl* pX509Certificate = createAndAddCertificateFromPackage(raDERCertificate, "TCu,Cu,Tu");
-
+ X509Certificate_NssImpl* pX509Certificate = createAndAddCertificateFromPackage(raDERCertificate, "TCu,TCu,TCu");
if (!pX509Certificate)
return uno::Reference<security::XCertificate>();
- pX509Certificate->setCustomPrivateKey(pPrivateKey);
-
return pX509Certificate;
}
diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
index 35a3e841e6f4..180ef6558d38 100644
--- a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
+++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
@@ -46,8 +46,7 @@ using ::com::sun::star::security::XCertificate ;
using ::com::sun::star::util::DateTime ;
X509Certificate_NssImpl::X509Certificate_NssImpl() :
- m_pCert(nullptr),
- m_pPrivateKey(nullptr)
+ m_pCert(nullptr)
{
}
@@ -332,25 +331,13 @@ void X509Certificate_NssImpl::setRawCert( const Sequence< sal_Int8 >& rawCert )
m_pCert = cert ;
}
-void X509Certificate_NssImpl::setCustomPrivateKey(SECKEYPrivateKey* pPrivateKey)
-{
- m_pPrivateKey = pPrivateKey;
-}
-
SECKEYPrivateKey* X509Certificate_NssImpl::getPrivateKey()
{
- if (m_pPrivateKey)
- {
- return m_pPrivateKey;
- }
- else
+ if (m_pCert && m_pCert->slot)
{
- if (m_pCert && m_pCert->slot)
- {
- SECKEYPrivateKey* pPrivateKey = PK11_FindPrivateKeyFromCert(m_pCert->slot, m_pCert, nullptr);
- if (pPrivateKey)
- return pPrivateKey;
- }
+ SECKEYPrivateKey* pPrivateKey = PK11_FindPrivateKeyFromCert(m_pCert->slot, m_pCert, nullptr);
+ if (pPrivateKey)
+ return pPrivateKey;
}
return nullptr;
}
diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
index 64c76972bf83..cae1f7238739 100644
--- a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
+++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
@@ -41,7 +41,6 @@ class X509Certificate_NssImpl : public ::cppu::WeakImplHelper<
{
private:
CERTCertificate* m_pCert;
- SECKEYPrivateKey* m_pPrivateKey;
public:
X509Certificate_NssImpl() ;
@@ -97,7 +96,6 @@ class X509Certificate_NssImpl : public ::cppu::WeakImplHelper<
/// @throws css::uno::RuntimeException
void setRawCert( const css::uno::Sequence< sal_Int8 >& rawCert ) ;
- void setCustomPrivateKey(SECKEYPrivateKey* pPrivateKey);
SECKEYPrivateKey* getPrivateKey();
// XServiceInfo