+//
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <unique_ptr.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <error.h>
+#include <memory.h>
+#include <new>
+#include <sys/stat.h>
+#include <assert.h>
+#include <dirent.h>
+#include <FBaseByteBuffer.h>
+#include <FBaseResult.h>
+#include <FBaseSysLog.h>
+#include <FBaseRt_EventDispatcher.h>
+#include <FIo_IpcServer.h>
+#include <FSec_AccessController.h>
+#include <FSec_AccessControlTypes.h>
+#include <FApp_AppInfo.h>
+#include <CertificateServiceStub.h>
+#include <FSecCert_CertMgrMessages.h>
+#include <FSecCert_CertServer.h>
+
+using namespace Tizen::Base;
+using namespace Tizen::Base::Collection;
+using namespace Tizen::Base::Runtime;
+using namespace Tizen::App;
+using namespace Tizen::Io;
+
+namespace Tizen { namespace Security { namespace Cert
+{
+
+_CertServiceStub::_CertServiceStub(void)
+ : __pIpcServer(null)
+ , __context(0)
+ , __refCount(0)
+{
+}
+
+_CertServiceStub::~_CertServiceStub(void)
+{
+ if (__pIpcServer != null)
+ {
+ __pIpcServer->Stop();
+ delete __pIpcServer;
+ }
+}
+
+result
+_CertServiceStub::Construct(void)
+{
+ result r = E_SUCCESS;
+
+ std::unique_ptr< _IpcServer > pIpcServer(new (std::nothrow) _IpcServer());
+ TryReturnResult(pIpcServer != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
+
+ r = pIpcServer->Construct(L"osp.security.ipcserver.certmanager", *this);
+ TryReturnResult(!IsFailed(r), r, r, "[%s] Failed to create IPC server(%s)", GetErrorMessage(r), "CertService");
+
+ __pIpcServer = pIpcServer.release();
+
+ // It was replaced into the script due to N_SE-53394 (mk-cert-db.sh)
+ // _CertServer::InitializeDb();
+
+ return r;
+}
+
+bool
+_CertServiceStub::OnUpdateRootCa(int type, Tizen::Io::_IpcBuffer certOldBufferIpc, Tizen::Io::_IpcBuffer certNewBufferIpc, result* pRet)
+{
+ *pRet = _AccessController::CheckSystemPrivilege(__pIpcServer->GetClientPackageId(), _PRV_CERTIFICATE_WRITE);
+ TryCatchResult(!IsFailed(*pRet), *pRet = E_PRIVILEGE_DENIED, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
+
+ *pRet = _CertServer::UpdateCaCertificate(static_cast< _CaCertType >(type), static_cast< char* >(certOldBufferIpc.pBuffer), certOldBufferIpc.size,
+ static_cast< char* >(certNewBufferIpc.pBuffer), certNewBufferIpc.size);
+
+CATCH:
+ return true;
+}
+
+bool
+_CertServiceStub::OnRemoveRootCa(int type, Tizen::Io::_IpcBuffer certBufferIpc, int bufLen, result* pRet)
+{
+ *pRet = _AccessController::CheckSystemPrivilege(__pIpcServer->GetClientPackageId(), _PRV_CERTIFICATE_WRITE);
+ TryCatchResult(!IsFailed(*pRet), *pRet = E_PRIVILEGE_DENIED, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
+
+ *pRet = _CertServer::RemoveCaCertificate(static_cast< _CaCertType >(type), static_cast< char* >(certBufferIpc.pBuffer), bufLen);
+
+CATCH:
+ return true;
+}
+
+bool
+_CertServiceStub::OnInsertCaCertificate(int type, int format, Tizen::Io::_IpcBuffer pCert, long certLen, result* pRet)
+{
+ *pRet = _AccessController::CheckSystemPrivilege(__pIpcServer->GetClientPackageId(), _PRV_CERTIFICATE_WRITE);
+ TryCatchResult(!IsFailed(*pRet), *pRet = E_PRIVILEGE_DENIED, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
+
+ *pRet = _CertServer::InsertCaCertificate(static_cast< _CaCertType >(type), static_cast< _CertFormat >(format), static_cast< byte* >(pCert.pBuffer), certLen);
+
+CATCH:
+ return true;
+}
+
+bool
+_CertServiceStub::OnInsertUserCaCertificate(int format, Tizen::Io::_IpcBuffer pCert, int certLen, result* pRet)
+{
+ *pRet = _CertServer::InsertUserCaCertificate(static_cast< _CertFormat >(format), static_cast< char* >(pCert.pBuffer), certLen);
+
+ return true;
+}
+
+bool
+_CertServiceStub::OnInstallUserRootCertificate(Tizen::Io::_IpcBuffer filePath, result* pRet)
+{
+ *pRet = _CertServer::InsertUserCaCertificate(static_cast< byte* >(filePath.pBuffer));
+
+ return true;
+}
+
+//User Certificate APIs
+bool
+_CertServiceStub::OnInsertUserCertChainPrivateKey(Tizen::Io::_IpcBuffer certChainBufferIpc, int certSize, Tizen::Io::_IpcBuffer privateKeyBufferIpc, int userPriKeyLen, result* pRet)
+{
+ result r = E_SUCCESS;
+
+ *pRet = _AccessController::CheckSystemPrivilege(__pIpcServer->GetClientPackageId(), _PRV_CERTIFICATE_WRITE);
+ TryCatchResult(!IsFailed(*pRet), *pRet = E_PRIVILEGE_DENIED, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
+
+ *pRet = _CertServer::InsertUserCertChainPrivateKey(static_cast< char* >(certChainBufferIpc.pBuffer), certSize, static_cast< char* >(privateKeyBufferIpc.pBuffer), userPriKeyLen);
+
+ r = UpdateCertStoreContext();
+ TryCatchResult(!IsFailed(r), , r, "[%s] Failed to update certificate store context.", GetErrorMessage(r), "_CertServer");
+
+CATCH:
+ return true;
+}
+
+bool
+_CertServiceStub::OnInsertCertificateChainWithPrivateKey(Tizen::Io::_IpcBuffer certChainPrivateKeyBufferIpc, int certChainPrivateKeyLength, result* pRet)
+{
+ *pRet = _CertServer::InsertCertificateChainWithPrivateKey(static_cast< char* >(certChainPrivateKeyBufferIpc.pBuffer), certChainPrivateKeyLength);
+
+ return true;
+}
+
+bool
+_CertServiceStub::OnInstallPkcs12Content(Tizen::Io::_IpcBuffer pkcs12FilePath, Tizen::Io::_IpcBuffer pkcs12ImportPassword, bool checkPrivilege, result* pRet)
+{
+ result r = E_SUCCESS;
+
+ if (checkPrivilege == true)
+ {
+ *pRet = _AccessController::CheckSystemPrivilege(__pIpcServer->GetClientPackageId(), _PRV_CERTIFICATE_WRITE);
+ TryCatchResult(!IsFailed(*pRet), *pRet = E_PRIVILEGE_DENIED, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
+ }
+
+ *pRet = _CertServer::InsertPkcs12Content(static_cast< char* >(pkcs12FilePath.pBuffer), static_cast< char* >(pkcs12ImportPassword.pBuffer));
+
+ r = UpdateCertStoreContext();
+ TryCatchResult(!IsFailed(r), , r, "[%s] Failed to update certificate store context.", GetErrorMessage(r), "_CertServer");
+
+CATCH:
+ return true;
+}
+
+bool
+_CertServiceStub::OnDeleteUserCertChainByCertId(int certId, result* pRet)
+{
+ result r = E_SUCCESS;
+
+ *pRet = _CertServer::RemoveUserCertChainByCertId(certId);
+
+ r = UpdateCertStoreContext();
+ TryCatchResult(!IsFailed(r), , r, "[%s] Failed to update certificate store context.", GetErrorMessage(r), "_CertServer");
+
+CATCH:
+ return true;
+}
+
+bool
+_CertServiceStub::OnUninstallUserRootCertificateByCertId(int certId, result* pRet)
+{
+ *pRet = _AccessController::CheckSystemPrivilege(__pIpcServer->GetClientPackageId(), _PRV_CERTIFICATE_WRITE);
+ TryCatchResult(!IsFailed(*pRet), *pRet = E_PRIVILEGE_DENIED, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
+
+ *pRet = _CertServer::RemoveUserCaCertificateByCertId(certId);
+
+CATCH:
+ return true;
+}
+
+bool
+_CertServiceStub::OnGetUserCertChainByIssuerAndSubjectNameN(Tizen::Io::_IpcBuffer issuerBufferIpc, int issuerNameLen, Tizen::Io::_IpcBuffer subjectBufferIpc, int subNameLen, _CertificateListInfo* pCertList, result* pRet)
+{
+ _CertificateListInfo* pCertListIpc = null;
+
+ *pRet = _CertServer::GetUserCertChainByIssuerAndSubjectNameN(static_cast< char* >(issuerBufferIpc.pBuffer), issuerNameLen, static_cast< char* >(subjectBufferIpc.pBuffer), subNameLen, pCertListIpc);
+
+ if (pCertListIpc != null)
+ {
+ std::unique_ptr< _CertificateListInfo > pCertListAuto(pCertListIpc);
+
+ pCertList->certFileId = pCertListIpc->certFileId;
+
+ pCertList->format = pCertListIpc->format;
+ pCertList->certType = pCertListIpc->certType;
+ pCertList->length = pCertListIpc->length;
+ pCertList->priKeyLen = pCertListIpc->priKeyLen;
+
+ memcpy(pCertList->certificate, pCertListIpc->certificate, _MAX_CERTIFICATE_SIZE);
+ memcpy(pCertList->privatekey, pCertListIpc->privatekey, _MAX_CERT_PRIVATE_KEY_SIZE);
+
+ pCertList->pNext = pCertListIpc->pNext;
+ }
+ else
+ {
+ memset(pCertList, 0, sizeof(*pCertList));
+ }
+
+ return true;
+}
+
+bool
+_CertServiceStub::OnGetUserCertificateByCertIdN(int certId, int encodingType, _CertInfo* pUserCertificateList, result* pRet)
+{
+ _CertInfo* pUserCertificateInfoIpc = null;
+
+ *pRet = _CertServer::GetUserCertificateByCertIdN(certId, static_cast< _CertEncodingType >(encodingType), pUserCertificateInfoIpc);
+
+ if (pUserCertificateInfoIpc != null)
+ {
+ std::unique_ptr< _CertInfo > pCertInfoAuto(pUserCertificateInfoIpc);
+
+ pUserCertificateList->certId = pUserCertificateInfoIpc->certId;
+ pUserCertificateList->certFormat = pUserCertificateInfoIpc->certFormat;
+ pUserCertificateList->certType = pUserCertificateInfoIpc->certType;
+ pUserCertificateList->certLength = pUserCertificateInfoIpc->certLength;
+ pUserCertificateList->privateKeyLen = pUserCertificateInfoIpc->privateKeyLen;
+
+ memcpy(pUserCertificateList->certificate, pUserCertificateInfoIpc->certificate, _MAX_CERTIFICATE_SIZE);
+ memcpy(pUserCertificateList->privatekey, pUserCertificateInfoIpc->privatekey, _MAX_CERT_PRIVATE_KEY_SIZE);
+ }
+ else
+ {
+ memset(pUserCertificateList, 0, sizeof(*pUserCertificateList));
+ }
+ return true;
+}
+
+bool
+_CertServiceStub::OnGetUserCertFieldInfoByCertId(int certId, _CertFieldInfos* pCertInfoBufferIpc, result* pRet)
+{
+ _CertFieldInfos certInfo;
+
+ *pRet = _CertServer::GetUserCertFieldInfoByCertId(certId, &certInfo);
+
+ if (!IsFailed(*pRet))
+ {
+ pCertInfoBufferIpc->certType = certInfo.certType;
+ pCertInfoBufferIpc->certFileId = certInfo.certFileId;
+
+ memcpy(pCertInfoBufferIpc->serialNo, certInfo.serialNo, _MAX_SERIAL_NUMBER_SIZE + 1);
+ memcpy(pCertInfoBufferIpc->sigAlgorithm, certInfo.sigAlgorithm, _MAX_CERT_ALGORITHM_SIZE + 1);
+ memcpy(pCertInfoBufferIpc->validityFrom, certInfo.validityFrom, _MAX_CERT_VALIDITY_SIZE + 1);
+ memcpy(pCertInfoBufferIpc->validityTo, certInfo.validityTo, _MAX_CERT_VALIDITY_SIZE + 1);
+ memcpy(pCertInfoBufferIpc->subjectName, certInfo.subjectName, _MAX_ISSUER_SUBJECT_NAME_SIZE + 1);
+ memcpy(pCertInfoBufferIpc->issuerName, certInfo.issuerName, _MAX_ISSUER_SUBJECT_NAME_SIZE + 1);
+ memcpy(pCertInfoBufferIpc->fingerPrint, certInfo.fingerPrint, _MAX_CERT_FINGERPRINT_SIZE + 1);
+
+ pCertInfoBufferIpc->fingerPrintLen = certInfo.fingerPrintLen;
+
+ memcpy(pCertInfoBufferIpc->publicKey, certInfo.publicKey, _MAX_CERT_PUBLIC_KEY_SIZE + 1);
+ memcpy(static_cast< void* >(pCertInfoBufferIpc->certTypeFormat), static_cast< const void* >(certInfo.certTypeFormat), _MAX_CERT_TYPE_SIZE + 1);
+
+ pCertInfoBufferIpc->certVersion = certInfo.certVersion;
+
+ memcpy(pCertInfoBufferIpc->certTitle, certInfo.certTitle, _MAX_ISSUER_SUBJECT_NAME_SIZE + 1);
+ memcpy(pCertInfoBufferIpc->certSubTitle, certInfo.certSubTitle, _MAX_ISSUER_SUBJECT_NAME_SIZE + 1);
+
+ }
+ else
+ {
+ memset(pCertInfoBufferIpc, 0, sizeof(*pCertInfoBufferIpc));
+ }
+ return true;
+}
+
+
+bool
+_CertServiceStub::OnGetName(result* pRet)
+{
+ *pRet = _AccessController::CheckSystemPrivilege(__pIpcServer->GetClientPackageId(), _PRV_CERTIFICATE_READ);
+ TryCatchResult(!IsFailed(*pRet), *pRet = E_PRIVILEGE_DENIED, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
+
+ *pRet = E_SUCCESS;
+
+CATCH:
+ return true;
+}
+
+bool
+_CertServiceStub::OnCloseCertificateStore(int type, result* pRet)
+{
+ *pRet = _AccessController::CheckSystemPrivilege(__pIpcServer->GetClientPackageId(), _PRV_CERTIFICATE_READ);
+ TryCatchResult(!IsFailed(*pRet), *pRet = E_PRIVILEGE_DENIED, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
+
+ TryCatchResult(type == _CERT_TYPE_USER_CERT, *pRet = E_SYSTEM, E_SYSTEM, "The cert is not user cert.");
+
+ if (__refCount > 0)
+ {
+ __refCount -= 1;
+
+ if (__refCount == 0 && __context != 0)
+ {
+ *pRet = _CertServer::CloseCertificateStore(reinterpret_cast< CertificateStoreCtx >(__context));
+ __context = 0;
+ }
+ }
+
+ *pRet = E_SUCCESS;
+
+CATCH:
+ return true;
+}
+
+bool
+_CertServiceStub::OnOpenCertificateStoreByType(int type, int* pCount, result* pRet)
+{
+ void* pCertList = null;
+
+ *pRet = _AccessController::CheckSystemPrivilege(__pIpcServer->GetClientPackageId(), _PRV_CERTIFICATE_READ);
+ TryCatchResult(!IsFailed(*pRet), *pRet = E_PRIVILEGE_DENIED, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
+
+ TryCatchResult(type == _CERT_TYPE_USER_CERT, *pRet = E_SYSTEM, E_SYSTEM, "The cert is not user cert.");
+
+ if (__context == 0)
+ {
+ *pCount = 0;
+ pCertList = _CertServer::OpenCertificateStoreByType(static_cast< _CaCertType >(type), pCount);
+
+ __context = reinterpret_cast< int >(pCertList);
+ }
+ else
+ {
+ *pCount = _CertServer::GetCertificateCount(reinterpret_cast< CertificateStoreCtx >(__context));
+ }
+
+ __refCount += 1;
+
+ *pRet = E_SUCCESS;
+
+CATCH:
+ return true;
+}
+
+bool
+_CertServiceStub::OnGetCertificateCount(int type, int* pCertCount, result* pRet)
+{
+ *pRet = _AccessController::CheckSystemPrivilege(__pIpcServer->GetClientPackageId(), _PRV_CERTIFICATE_READ);
+ TryCatchResult(!IsFailed(*pRet), *pRet = E_PRIVILEGE_DENIED, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
+
+ TryCatchResult(type == _CERT_TYPE_USER_CERT, *pRet = E_SYSTEM, E_SYSTEM, "The cert is not user cert.");
+
+ *pCertCount = _CertServer::GetCertificateCount(reinterpret_cast< CertificateStoreCtx >(__context));
+
+ *pRet = E_SUCCESS;
+
+CATCH:
+ return true;
+}
+
+bool
+_CertServiceStub::OnGetNextCertificate(int type, int curPos, int length, Tizen::Base::ByteBuffer* pCertBufferIpc, int* pNewPos, result* pRet)
+{
+ char* pBuffer = null;
+
+ *pRet = _AccessController::CheckSystemPrivilege(__pIpcServer->GetClientPackageId(), _PRV_CERTIFICATE_READ);
+ TryCatchResult(!IsFailed(*pRet), *pRet = E_PRIVILEGE_DENIED, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
+
+ TryCatchResult(type == _CERT_TYPE_USER_CERT, *pRet = E_SYSTEM, E_SYSTEM, "The cert is not user cert.");
+
+ pBuffer = new (std::nothrow) char[length];
+ TryCatchResult(pBuffer, *pRet = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]Allocation failed");
+
+ *pRet = _CertServer::GetNextCertificate(reinterpret_cast< CertificateStoreCtx >(__context), curPos, pBuffer, &length);
+ *pNewPos = curPos;
+
+CATCH:
+ if (!IsFailed(*pRet))
+ {
+ pCertBufferIpc->Construct(length);
+ pCertBufferIpc->SetArray(reinterpret_cast<const byte*>(pBuffer), 0, length);
+ pCertBufferIpc->Flip();
+ }
+ else
+ {
+ SysLog(NID_SEC_CERT, "GetNextCertificate failed");
+ }
+ delete[] pBuffer;
+
+ return true;
+}
+
+bool
+_CertServiceStub::OnRestoreRootCaIntegrity(void)
+{
+ _CertServer::RestoreRootCaIntegrity();
+ ClearLastResult();
+ return true;
+}
+
+result
+_CertServiceStub::UpdateCertStoreContext(void)
+{
+ result r = E_SUCCESS;
+ CertificateStoreCtx certList = null;
+
+ int count = 0;
+
+ if (__refCount > 0)
+ {
+ if (__context != 0)
+ {
+ r = _CertServer::CloseCertificateStore(reinterpret_cast< CertificateStoreCtx >(__context));
+ TryReturnResult(!IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
+ __context = NULL;
+ }
+ certList = _CertServer::OpenCertificateStoreByType(_CERT_TYPE_USER_CERT, &count);
+ r = GetLastResult();
+ SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_SYSTEM, "Failed to open certificate store.");
+ __context = reinterpret_cast< int >(certList);
+
+ }
+ return r;
+}
+
+void
+_CertServiceStub::OnIpcRequestReceived(_IpcServer& server, const IPC::Message& message)
+{
+ IPC_BEGIN_MESSAGE_MAP(_CertServiceStub, message)
+ IPC_MESSAGE_HANDLER_EX(CertServer_GetName, &server, OnGetName)
+ IPC_MESSAGE_HANDLER_EX(CertServer_CloseCertificateStore, &server, OnCloseCertificateStore)
+ IPC_MESSAGE_HANDLER_EX(CertServer_OpenCertificateStoreByType, &server, OnOpenCertificateStoreByType)
+ IPC_MESSAGE_HANDLER_EX(CertServer_GetCertificateCount, &server, OnGetCertificateCount)
+ IPC_MESSAGE_HANDLER_EX(CertServer_GetNextCertificate, &server, OnGetNextCertificate)
+ IPC_MESSAGE_HANDLER_EX(CertServer_UpdateRootCa, &server, OnUpdateRootCa)
+ IPC_MESSAGE_HANDLER_EX(CertServer_RemoveRootCa, &server, OnRemoveRootCa)
+ IPC_MESSAGE_HANDLER_EX(CertServer_UninstallUserRootCertificateByCertId, &server, OnUninstallUserRootCertificateByCertId)
+ IPC_MESSAGE_HANDLER_EX(CertServer_InsertCaCertificate, &server, OnInsertCaCertificate)
+ IPC_MESSAGE_HANDLER_EX(CertServer_InsertUserCaCertificate, &server, OnInsertUserCaCertificate)
+ IPC_MESSAGE_HANDLER_EX(CertServer_InstallUserRootCertificate, &server, OnInstallUserRootCertificate)
+
+ //User Certificates API
+ IPC_MESSAGE_HANDLER_EX(CertServer_InsertUserCertChainPrivateKey, &server, OnInsertUserCertChainPrivateKey)
+ IPC_MESSAGE_HANDLER_EX(CertServer_InsertCertificateChainWithPrivateKey, &server, OnInsertCertificateChainWithPrivateKey)
+ IPC_MESSAGE_HANDLER_EX(CertServer_InstallPkcs12Content, &server, OnInstallPkcs12Content)
+ IPC_MESSAGE_HANDLER_EX(CertServer_DeleteUserCertChainByCertId, &server, OnDeleteUserCertChainByCertId)
+ IPC_MESSAGE_HANDLER_EX(CertServer_GetUserCertChainByIssuerAndSubjectNameN, &server, OnGetUserCertChainByIssuerAndSubjectNameN)
+ IPC_MESSAGE_HANDLER_EX(CertServer_GetUserCertificateByCertIdN, &server, OnGetUserCertificateByCertIdN)
+ IPC_MESSAGE_HANDLER_EX(CertServer_GetUserCertFieldInfoByCertId, &server, OnGetUserCertFieldInfoByCertId)
+
+ IPC_MESSAGE_HANDLER_EX(CertServer_RestoreRootCaIntegrity, &server, OnRestoreRootCaIntegrity)
+
+ IPC_END_MESSAGE_MAP_EX();
+}
+
+
+void
+_CertServiceStub::OnIpcServerStarted(const _IpcServer& server)
+{
+
+}
+
+void
+_CertServiceStub::OnIpcServerStopped(const _IpcServer& server)
+{
+
+}
+
+void
+_CertServiceStub::OnIpcClientConnected(const _IpcServer& server, int clientId)
+{
+
+}
+
+void
+_CertServiceStub::OnIpcClientDisconnected(const _IpcServer& server, int clientId)
+{
+
+}
+
+} } }