Merge "Added support for Event creation in worker thread" into tizen
[platform/framework/native/appfw.git] / src / security / cert / FSecCert_X509CertificateStoreImpl.cpp
old mode 100755 (executable)
new mode 100644 (file)
index b787943..ca25fc4
@@ -1,5 +1,4 @@
 //
-// Open Service Platform
 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
 //
 // Licensed under the Apache License, Version 2.0 (the License);
@@ -27,6 +26,9 @@
 #include <FSecCertX509Certificate.h>
 #include <FBaseSysLog.h>
 #include <FBase_StringConverter.h>
+#include <FSec_AccessController.h>
+#include <FSec_AccessControlTypes.h>
+#include <FSecCert_CertServer.h>
 #include <FSecCert_CertService.h>
 #include <FSecCert_CertServiceProxy.h>
 #include <FSecCert_X509CertificateStoreImpl.h>
@@ -38,44 +40,85 @@ namespace Tizen { namespace Security { namespace Cert
 
 static const int _MAX_CERT_BUFFER_SIZE = 2048;
 
+int
+GetIndexFromCertType(int certType)
+{
+       int index = 0;
+       switch (certType)
+       {
+       case _CERT_TYPE_ROOT_CA:
+               index = 0;
+               break;
+
+       case _CERT_TYPE_ROOT_DOMAIN1:
+               index = 1;
+               break;
+
+       case _CERT_TYPE_ROOT_DOMAIN3:
+               index = 2;
+               break;
+
+       default:
+               SysTryReturn(NID_SEC_CERT, false, -1, E_INVALID_ARG, "[%s] Invalid certificate type.", GetErrorMessage(E_INVALID_ARG));
+               break;
+       }
+
+       return index;
+}
+
 _X509CertificateStoreImpl::_X509CertificateStoreImpl(void)
        : __certType(static_cast< int >(_CERT_TYPE_NOT_BOUNDED))
-       , __certificateStoreCtx(0)
+       , __curPos(0)
 {
        ClearLastResult();
 
+       memset(__context, 0, sizeof(__context));
+
        __pCertServiceProxy = _CertServiceProxy::GetInstance();
        SysTryReturnVoidResult(NID_SEC_CERT, __pCertServiceProxy != null, E_SYSTEM, "[E_SYSTEM] Failed to get certificate proxy instance.");
+
+       // restore root CA cert DB
+       __pCertServiceProxy->RestoreRootCaIntegrity();
+       ClearLastResult();
 }
 
 _X509CertificateStoreImpl::~_X509CertificateStoreImpl(void)
 {
-
-       if (__certificateStoreCtx != 0)
+       if ((__certType > _CERT_TYPE_NOT_BOUNDED) && (__certType < _CERT_TYPE_MAX))
        {
-               __pCertServiceProxy->CloseCertificateStore(__certificateStoreCtx);
+               __pCertServiceProxy->CloseCertificateStore(__certType);
        }
 }
 
 result
 _X509CertificateStoreImpl::GetName(String& name) const
 {
-       result r = __pCertServiceProxy->GetName();
-       if (!IsFailed(r))
-       {
-               name = L"CertServiceStore";
-       }
-
-       return r;
+       name = L"CertServiceStore";
+       return E_SUCCESS;
 }
 
 result
 _X509CertificateStoreImpl::SetCertificateSelector(const Tizen::Security::Cert::ICertificateSelector& selector)
 {
+       result r = E_SUCCESS;
+
+       int prevIndex = GetIndexFromCertType(__certType);
+       if (__certType == _CERT_TYPE_USER_CERT)
+       {
+               r = __pCertServiceProxy->CloseCertificateStore(__certType);
+               SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_SYSTEM, "Failed to close certificate store.");
+       }
+       else if (prevIndex > -1 && __context[prevIndex] != 0)
+       {
+               r = _CertServer::CloseCertificateStore(reinterpret_cast< CertificateStoreCtx >(__context[prevIndex]));
+               __context[prevIndex] = 0;
+               SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_SYSTEM, "Failed to close certificate store.");
+       }
+
        int count = 0;
+       __curPos = 0;
 
        CertificateType certType = (const_cast< ICertificateSelector& >(selector)).GetType();
-
        switch (certType)
        {
        case ROOT_CA:
@@ -92,49 +135,108 @@ _X509CertificateStoreImpl::SetCertificateSelector(const Tizen::Security::Cert::I
 
        case USER_CERT:
                __certType = _CERT_TYPE_USER_CERT;
-               break;
+               return __pCertServiceProxy->OpenCertificateStoreByType(static_cast< _CaCertType >(__certType), count);
 
        default:
                SysTryReturnResult(NID_SEC_CERT, false, E_INVALID_ARG, "Invalid certificate type.");
                break;
        }
 
-       if (__certificateStoreCtx != 0)
+       CertificateStoreCtx certList = null;
+       int index = GetIndexFromCertType(__certType);
+
+       if (__context[index] == 0)
        {
-               __pCertServiceProxy->CloseCertificateStore(__certificateStoreCtx);
-               __certificateStoreCtx = 0;
+               certList = _CertServer::OpenCertificateStoreByType(static_cast< _CaCertType >(__certType), &count);
+               r = GetLastResult();
+               SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_SYSTEM, "Failed to open certificate store.");
+               __context[index] = reinterpret_cast< int >(certList);
        }
 
-       return __pCertServiceProxy->OpenCertificateStoreByType(static_cast< _CaCertType >(__certType), count, __certificateStoreCtx);
+       return E_SUCCESS;
 }
 
 result
-_X509CertificateStoreImpl::GetCertificateCount(int& count) const
+_X509CertificateStoreImpl::GetCertificateCount(int& count)
 {
-       if (__certificateStoreCtx != 0)
+       result r = E_SUCCESS;
+
+       if (__certType == _CERT_TYPE_USER_CERT)
        {
-               return __pCertServiceProxy->GetCertificateCount(__certificateStoreCtx, count);
+               r = __pCertServiceProxy->GetCertificateCount(__certType, count);
        }
+       else
+       {
+               r = _AccessController::CheckUserPrivilege(_PRV_CERTIFICATE_READ);
+               SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
 
-       count = 0;
-       return E_SUCCESS;
-}
+               int index = GetIndexFromCertType(__certType);
+               SysTryReturnResult(NID_SEC_CERT, index > -1, E_SYSTEM, "Failed to open certificate store.");
+               count = _CertServer::GetCertificateCount(reinterpret_cast< CertificateStoreCtx >(__context[index]));
+       }
 
+       return r;
+}
 
 Tizen::Security::Cert::ICertificate*
-_X509CertificateStoreImpl::GetNextCertificateN(void) const
+_X509CertificateStoreImpl::GetNextCertificateN(void)
 {
        result r = E_SUCCESS;
        ByteBuffer certBuffer;
        byte certBytes[_MAX_CERT_BUFFER_SIZE] = {0, };
        int certLen = sizeof(certBytes);
+       int curPos = __curPos;
 
        ClearLastResult();
 
-       SysTryReturn(NID_SEC_CERT, __certificateStoreCtx != 0, null, E_SYSTEM, "[E_SYSTEM] Certificate list is empty, call SetCertificateSelector() function.");
+       if (__certType == _CERT_TYPE_USER_CERT)
+       {
+               r = __pCertServiceProxy->GetNextCertificate(__certType, curPos, certBytes, certLen);
+               SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, r, "[%s] Failed to get next root certificate.", GetErrorMessage(r));
+       }
+       else
+       {
+               r = _AccessController::CheckUserPrivilege(_PRV_CERTIFICATE_READ);
+               SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
+
+               _CertRootCaInfo* pRootCa = null;
+               _CertRootList* pTemp = null;
+               int count = 0;
+
+               int index = GetIndexFromCertType(__certType);
+               SysTryReturnResult(NID_SEC_CERT, index > -1, null, "Failed to open certificate store.");
+
+               CertificateStoreCtx certificateStoreCtx = reinterpret_cast< CertificateStoreCtx >(__context[index]);
+               SysTryReturn(NID_SEC_CERT, certificateStoreCtx != null, null, E_INVALID_ARG, "Invalid certificate store context.");
+
+               pRootCa = reinterpret_cast< _CertRootCaInfo* >(certificateStoreCtx);
+               SysTryReturn(NID_SEC_CERT, pRootCa->pRootList != null, null, E_OBJ_NOT_FOUND, "Certificate list is empty.");
+
+               pTemp = pRootCa->pRootList;
+
+               while (count != curPos)
+               {
+                       count++;
+                       SysTryReturn(NID_SEC_CERT, pTemp->pNext != null, null, E_OBJ_NOT_FOUND, "Certificate index not found.");
 
-       r = __pCertServiceProxy->GetNextCertificate(__certificateStoreCtx, certBytes, certLen);
-       SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, r, "[%s] Failed to get next root certificate.", GetErrorMessage(r));
+                       pTemp = pTemp->pNext;
+               }
+
+               pRootCa->pCurrRootList = pTemp;
+               if (certLen > static_cast< int >(pRootCa->pCurrRootList->length))
+               {
+                       memcpy(certBytes, pRootCa->pCurrRootList->certificate, pRootCa->pCurrRootList->length);
+                       certLen = pRootCa->pCurrRootList->length;
+               }
+               else
+               {
+                       memcpy(certBytes, pRootCa->pCurrRootList->certificate, certLen);
+               }
+
+               curPos++;
+       }
+
+       __curPos = curPos;
 
        r = certBuffer.Construct(certLen);
        SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, r, "[%s] Failed to allocate memory.", GetErrorMessage(r));
@@ -201,6 +303,9 @@ _X509CertificateStoreImpl::Insert(CertificateType certificateType, const Tizen::
        else
        {
                r = __pCertServiceProxy->InsertCaCertificate(static_cast< int >(certType), _CERT_X509, pBuffer, bufferLen);
+
+               UpdateCertStoreContext(certType);
+               SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to update cert store.", GetErrorMessage(r));
        }
 
        if (r == E_FILE_ALREADY_EXIST)
@@ -209,14 +314,11 @@ _X509CertificateStoreImpl::Insert(CertificateType certificateType, const Tizen::
        }
        SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to insert root certificate.", GetErrorMessage(r));
 
-       r = UpdateCertStoreContext();
-       SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to open certificate store context.", GetErrorMessage(r));
-       
        return r;
 }
 
 result
-_X509CertificateStoreImpl::InsertPkcs12(const String& filePath, const String& password)
+_X509CertificateStoreImpl::InsertPkcs12(const String& filePath, const String& password, bool checkPrivilege)
 {
        result r = E_SUCCESS;
        std::unique_ptr< char[] > pFilePath(_StringConverter::CopyToCharArrayN(filePath));
@@ -226,15 +328,13 @@ _X509CertificateStoreImpl::InsertPkcs12(const String& filePath, const String& pa
        SysTryReturnResult(NID_SEC_CERT, pFilePath != null, E_INVALID_ARG, "File path is invalid.");
 
        //password can be null
-       r = __pCertServiceProxy->InsertPkcs12Content(pFilePath.get(), pPassword.get());
+       r = __pCertServiceProxy->InsertPkcs12Content(pFilePath.get(), pPassword.get(), checkPrivilege);
        if (r == E_FILE_ALREADY_EXIST)
        {
                r = E_SUCCESS;
        }
        SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to insert pkcs 12 user certificate.", GetErrorMessage(r));
-       
-       r = UpdateCertStoreContext();
-       SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to open certificate store context.", GetErrorMessage(r));
+
        return r;
 }
 
@@ -281,8 +381,6 @@ _X509CertificateStoreImpl::Update(CertificateType certificateType, const Tizen::
        oldBufferLen = pOldEncodedData->GetRemaining();
        SysTryReturnResult(NID_SEC_CERT, oldBufferLen > 0, E_INVALID_ARG, "Input old certificate length is not positive.");
 
-       pOldEncodedData.reset(null);
-
        std::unique_ptr< ByteBuffer > pNewEncodedData(newCert.GetEncodedDataN());
        SysTryReturnResult(NID_SEC_CERT, pNewEncodedData != null, E_INVALID_ARG, "Failed to get encoded data on new input certificate.");
 
@@ -305,7 +403,7 @@ _X509CertificateStoreImpl::Update(CertificateType certificateType, const Tizen::
                _CertService::CloseCertificate(&certHandle);
                SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to find user certificates in store.", GetErrorMessage(r));
 
-               r = __pCertServiceProxy->RemoveUserCaCertificateByCertId(certId);
+               r = __pCertServiceProxy->RemoveUserCertChainByCertId(certId);
                SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to remove/update user certificates from store.", GetErrorMessage(r));
 
                r = __pCertServiceProxy->InsertUserCertChainPrivateKey(reinterpret_cast< char* >(pNewBuffer), newBufferLen, null, 0);
@@ -315,10 +413,10 @@ _X509CertificateStoreImpl::Update(CertificateType certificateType, const Tizen::
        {
                r = __pCertServiceProxy->UpdateCaCertificate(static_cast< int >(certType), pOldBuffer, oldBufferLen, pNewBuffer, newBufferLen);
                SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to update certificate.", GetErrorMessage(r));
-       }
 
-       r = UpdateCertStoreContext();
-       SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to open certificate store context.", GetErrorMessage(r));
+               UpdateCertStoreContext(certType);
+               SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to update cert store.", GetErrorMessage(r));
+       }
 
        return r;
 }
@@ -330,6 +428,7 @@ _X509CertificateStoreImpl::Remove(CertificateType certificateType, const Tizen::
        result r = E_SUCCESS;
        byte* pBuffer = null;
        int bufferLen = 0;
+
        _CaCertType certType = _CERT_TYPE_NOT_BOUNDED;
 
        switch (certificateType)
@@ -373,24 +472,51 @@ _X509CertificateStoreImpl::Remove(CertificateType certificateType, const Tizen::
                SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to open certificates.", GetErrorMessage(r));
 
                r = _CertService::GetUserCertificateId(certHandle, certId);
+
                _CertService::CloseCertificate(&certHandle);
                SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to find user certificates in store.", GetErrorMessage(r));
 
-               r = __pCertServiceProxy->RemoveUserCertificateByCertId(certId);
+               r = __pCertServiceProxy->RemoveUserCertChainByCertId(certId);
                SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to remove user certificates.", GetErrorMessage(r));
        }
        else
        {
                r = __pCertServiceProxy->RemoveCaCertificate(static_cast< int >(certType), pBuffer, bufferLen);
                SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to remove certificate.", GetErrorMessage(r));
+
+               UpdateCertStoreContext(certType);
+               SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to update cert store.", GetErrorMessage(r));
        }
-       
-       r = UpdateCertStoreContext();
-       SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to open certificate store context.", GetErrorMessage(r));
 
        return r;
+}
+
+result
+_X509CertificateStoreImpl::UpdateCertStoreContext(int type)
+{
+       result r = E_SUCCESS;
 
+       CertificateStoreCtx certList = null;
+       int index = GetIndexFromCertType(type);
+
+       int count = 0;
+
+       if (index > -1 && type == __certType)
+       {
+               if (__context[index] != 0)
+               {
+                       r = _CertServer::CloseCertificateStore(reinterpret_cast< CertificateStoreCtx >(__context[index]));
+                       TryReturnResult(!IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
+               }
+               certList = _CertServer::OpenCertificateStoreByType(static_cast< _CaCertType >(type), &count);
+               r = GetLastResult();
+               SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_SYSTEM, "Failed to open certificate store.");
+               __context[index] = reinterpret_cast< int >(certList);
+       }
+
+       return r;
 }
+
 _X509CertificateStoreImpl*
 _X509CertificateStoreImpl::GetInstance(X509CertificateStore& x509CertificateStore)
 {
@@ -403,22 +529,25 @@ _X509CertificateStoreImpl::GetInstance(const X509CertificateStore& x509Certifica
        return x509CertificateStore.__pX509CertificateStoreImpl;
 }
 
-result
-_X509CertificateStoreImpl::UpdateCertStoreContext(void)
+int
+InsertPkcs12Content(const char* pPath, const char* pPassword)
 {
        result r = E_SUCCESS;
-       int count =0;
+       _X509CertificateStoreImpl store;
+       String filePath;
+       String password;
 
-       if (__certificateStoreCtx != 0)
-       {
-               __pCertServiceProxy->CloseCertificateStore(__certificateStoreCtx);
-               r =  __pCertServiceProxy->OpenCertificateStoreByType(static_cast< _CaCertType >(__certType), count, __certificateStoreCtx);
-               SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to open certificate store context.", GetErrorMessage(r));
-       }
+       filePath.SetCapacity(strlen(pPath) + 1);
+       password.SetCapacity(strlen(pPassword) + 1);
 
-       return r;
-}
+       filePath.Format(strlen(pPath) + 1, L"%s", pPath);
+       password.Format(strlen(pPassword) + 1, L"%s", pPassword);
 
+       r = store.InsertPkcs12(filePath, password, false);
+       SysTryReturn(NID_SEC_CERT, !IsFailed(r), -1, r, "[%s] Failed to remove certificate.", GetErrorMessage(r));
+
+       return 0;
+}
 
 
-} } }       // Tizen::Security::Cert
+} } }     // Tizen::Security::Cert