[Libreoffice-commits] core.git: xmlsecurity/Library_xsec_xmlsec.mk xmlsecurity/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Mon Dec 31 21:07:15 UTC 2018


 xmlsecurity/Library_xsec_xmlsec.mk                            |    1 
 xmlsecurity/source/xmlsec/nss/nssinitializer.cxx              |  131 +++++++++-
 xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx |   56 ++--
 xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx     |   23 -
 xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx     |    2 
 5 files changed, 162 insertions(+), 51 deletions(-)

New commits:
commit 87eec1b90b6ecd83455f09168430c23f73c25c86
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon Dec 31 12:14:19 2018 +0100
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Mon Dec 31 22:06:51 2018 +0100

    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 at gmail.com>

diff --git a/xmlsecurity/Library_xsec_xmlsec.mk b/xmlsecurity/Library_xsec_xmlsec.mk
index 27972a2c87bc..f067e14d85f2 100644
--- a/xmlsecurity/Library_xsec_xmlsec.mk
+++ b/xmlsecurity/Library_xsec_xmlsec.mk
@@ -40,6 +40,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 847bdc61e4a6..b76684f6075e 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>
@@ -440,15 +441,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;
@@ -838,12 +858,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);
@@ -870,42 +888,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


More information about the Libreoffice-commits mailing list