Add privacy check method
[platform/framework/native/appfw.git] / src / security / FSec_AccessController.cpp
index cd41a20..a7d1390 100644 (file)
 #include <FBaseSysLog.h>
 #include <FBaseString.h>
 #include <FBaseColArrayList.h>
+#include <FBase_StringConverter.h>
 #include <FIoFile.h>
 #include <FIo_IpcClient.h>
+#include <privacy_checker_client.h>
 #include "FSec_AccessController.h"
 #include "FSec_PrivilegeManager.h"
 #include "FSec_PrivilegeManagerMessage.h"
 #include "FSec_PrivilegeInfo.h"
 
+
 using namespace Tizen::App;
 using namespace Tizen::App::Package;
 using namespace Tizen::Base;
@@ -50,6 +53,12 @@ namespace Tizen { namespace Security
 
 _PrivilegeManager* _AccessController::__pPrivilegeManager = null;
 
+static std::unique_ptr<String> pEncryptedPrivileges(null);
+static std::unique_ptr<String> pChecksum(null);
+static std::unique_ptr<String> pEncryptedVisibility(null);
+static std::unique_ptr<String> pVisibilityChecksum(null);
+static std::unique_ptr<ArrayList> pPrivilegeList(null);
+
 _AccessController::_AccessController(void)
 {
 
@@ -57,11 +66,14 @@ _AccessController::_AccessController(void)
 
 _AccessController::~_AccessController(void)
 {
-
+       if (pPrivilegeList != null)
+       {
+               pPrivilegeList->RemoveAll(true);
+       }
 }
 
 result
-_AccessController::CheckSystemPrivilege(const AppId& appId, _Privilege privilege)
+_AccessController::CheckSystemPrivilege(const PackageId& packageId, _Privilege privilege)
 {
        result r = E_SUCCESS;
 
@@ -72,23 +84,159 @@ _AccessController::CheckSystemPrivilege(const AppId& appId, _Privilege privilege
        String appType;
        String webAppType(L"wgt");
 
-       SysLog(NID_SEC, "Enter.");
        SysTryReturnResult(NID_SEC, privilege < _MAX_PRIVILEGE_ENUM, E_INVALID_ARG, "The privilege enumerator is invalid");
 
-       appId.SubString(0, MAX_APP_ID_SIZE, subAppId);
+       packageId.SubString(0, MAX_APP_ID_SIZE, subAppId);
 
        r = infoImpl.Construct(subAppId);
-       if (r == E_APP_NOT_INSTALLED)
+       SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "An unexpected system error occurred.");
+
+       appType = infoImpl.GetAppType();
+       if (appType.Equals(webAppType, true))
+       {
+               return E_SUCCESS;
+       }
+
+       if (__pPrivilegeManager == null)
+       {
+               __pPrivilegeManager = _PrivilegeManager::GetInstance();
+       }
+       SysTryReturnResult(NID_SEC, __pPrivilegeManager != null, E_SYSTEM, "An unexpected system error occurred.");
+
+       pPrivilegeInfo.reset(__pPrivilegeManager->RetrievePrivilegeInfoN(subAppId));
+       r = GetLastResult();
+
+       if (r == E_SUCCESS)
        {
-               SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The package information does not exist.");
-               r = E_DATA_NOT_FOUND;
+               // nothing to do.
+       }
+       else if (r == E_DATA_NOT_FOUND)
+       {
+               SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
                goto CATCH;
        }
+       else
+       {
+               SysLogException(NID_SEC, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
+               return E_SYSTEM;
+       }
+
+       ret = pPrivilegeInfo->HasPrivilege(privilege);
+       if (!ret)
+       {
+               r = E_PRIVILEGE_DENIED;
+               goto CATCH;
+       }
+
+       r = CheckPrivacy(packageId, privilege);
+       SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
+
+       return r;
+
+CATCH:
+
+       SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
+
+       _AppManagerImpl* pAppManagerImpl = _AppManagerImpl::GetInstance();
+       pAppManagerImpl->TerminateApplications(packageId);
+
+       return r;
+}
+
+result
+_AccessController::CheckSystemPrivilege(const PackageId& packageId, _Privilege privilege1, _Privilege privilege2)
+{
+       result r = E_SUCCESS;
+
+       bool ret = false;
+       std::unique_ptr<_PrivilegeInfo> pPrivilegeInfo(null);
+       String subAppId;
+       _PackageInfoImpl infoImpl;
+       String appType;
+       String webAppType(L"wgt");
+
+       SysTryReturnResult(NID_SEC, privilege1 < _MAX_PRIVILEGE_ENUM, E_INVALID_ARG, "The privilege enumerator is invalid");
+       SysTryReturnResult(NID_SEC, privilege2 < _MAX_PRIVILEGE_ENUM, E_INVALID_ARG, "The privilege enumerator is invalid");
+
+       packageId.SubString(0, MAX_APP_ID_SIZE, subAppId);
+
+       r = infoImpl.Construct(subAppId);
+       SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "An unexpected system error occurred.");
 
        appType = infoImpl.GetAppType();
+       if (appType.Equals(webAppType, true))
+       {
+               return E_SUCCESS;
+       }
+
+       if (__pPrivilegeManager == null)
+       {
+               __pPrivilegeManager = _PrivilegeManager::GetInstance();
+       }
+       SysTryReturnResult(NID_SEC, __pPrivilegeManager != null, E_SYSTEM, "An unexpected system error occurred.");
+
+       pPrivilegeInfo.reset(__pPrivilegeManager->RetrievePrivilegeInfoN(subAppId));
        r = GetLastResult();
+
+       if (r == E_SUCCESS)
+       {
+               // nothing to do.
+       }
+       else if (r == E_DATA_NOT_FOUND)
+       {
+               SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
+               goto CATCH;
+       }
+       else
+       {
+               SysLogException(NID_SEC, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
+               return E_SYSTEM;
+       }
+
+       ret = pPrivilegeInfo->HasPrivilegeEx(privilege1);
+       if (!ret)
+       {
+               ret = pPrivilegeInfo->HasPrivilege(privilege2);
+               if (!ret)
+               {
+                       r = E_PRIVILEGE_DENIED;
+                       goto CATCH;
+               }
+       }
+
+       r = CheckPrivacy(packageId, privilege2);
+       SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
+
+       return r;
+
+CATCH:
+
+       SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
+
+       _AppManagerImpl* pAppManagerImpl = _AppManagerImpl::GetInstance();
+       pAppManagerImpl->TerminateApplications(packageId);
+
+       return r;
+}
+
+result
+_AccessController::CheckPrivilege(const PackageId& packageId, const String& privilege)
+{
+       result r = E_SUCCESS;
+
+       bool ret = false;
+       std::unique_ptr<_PrivilegeInfo> pPrivilegeInfo(null);
+       String subAppId;
+       _PackageInfoImpl infoImpl;
+       String appType;
+       String webAppType(L"wgt");
+
+       packageId.SubString(0, MAX_APP_ID_SIZE, subAppId);
+
+       r = infoImpl.Construct(subAppId);
        SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "An unexpected system error occurred.");
 
+       appType = infoImpl.GetAppType();
        if (appType.Equals(webAppType, true))
        {
                return E_SUCCESS;
@@ -125,25 +273,21 @@ _AccessController::CheckSystemPrivilege(const AppId& appId, _Privilege privilege
                goto CATCH;
        }
 
-       SysLog(NID_SEC, "Exit.");
+       r = CheckPrivacy(packageId, privilege);
+       SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
+
        return r;
 
 CATCH:
 
        SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
-       SysLog(NID_SEC, "Exit.");
 
        _AppManagerImpl* pAppManagerImpl = _AppManagerImpl::GetInstance();
-       pAppManagerImpl->TerminateApplications(appId);
+       pAppManagerImpl->TerminateApplications(packageId);
 
        return r;
 }
 
-static std::unique_ptr<String> pEncryptedPrivileges(null);
-static std::unique_ptr<String> pChecksum(null);
-static std::unique_ptr<String> pEncryptedVisibility(null);
-static std::unique_ptr<String> pVisibilityChecksum(null);
-
 void
 _AccessController::Initialize(void)
 {
@@ -153,8 +297,6 @@ _AccessController::Initialize(void)
        std::unique_ptr<IPC::Message> pCipherPrivilegeMessage(null);
        std::unique_ptr<IPC::Message> pCipherVisibilityMessage(null);
 
-       SysLog(NID_SEC, "Enter");
-
        r = ipcClient.Construct(L"osp.security.ipcserver.privilegemanager", null);
        SysTryReturnVoidResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "Failed to construct the instance of IPC.");
 
@@ -164,7 +306,12 @@ _AccessController::Initialize(void)
        pChecksum.reset(new (std::nothrow) String());
        SysTryReturnVoidResult(NID_SEC, pChecksum != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
 
-       pCipherPrivilegeMessage.reset(new (std::nothrow) PrivilegeManagerMsg_retrieve(pEncryptedPrivileges.get(), pChecksum.get(), &r));
+       pPrivilegeList.reset(new ArrayList());
+       SysTryReturnVoidResult(NID_SEC, pPrivilegeList != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
+
+       pPrivilegeList->Construct();
+
+       pCipherPrivilegeMessage.reset(new (std::nothrow) PrivilegeManagerMsg_retrieve(pEncryptedPrivileges.get(), pChecksum.get(), pPrivilegeList.get(), &r));
        SysTryReturnVoidResult(NID_SEC, pCipherPrivilegeMessage != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
 
        ipcResult = ipcClient.SendRequest(pCipherPrivilegeMessage.get());
@@ -186,7 +333,6 @@ _AccessController::Initialize(void)
 
        isConstructed = true;
 
-    SysLog(NID_SEC, "Exit");
        return;
 }
 
@@ -198,17 +344,96 @@ _AccessController::CheckUserPrivilege(_Privilege privilege)
 
        bool ret = false;
 
-       _AppType appType = _APP_TYPE_UI_APP;
        _PrivilegeInfo privilegeInfo;
 
-       SysLog(NID_SEC, "Enter.");
        ClearLastResult();
 
        SysTryReturnResult(NID_SEC, privilege < _MAX_PRIVILEGE_ENUM, E_INVALID_ARG, "The privilege enumerator is invalid");
        //SysAssertf(privilegeLevelListTable[privilege][_PRV_API_VER_2_0] == _PRV_LEVEL_USER, "System-level privilege is passed to CheckUserPrivilege.");
 
-       appType = _AppInfo::GetAppType();
-       const PackageId& packageId = _AppInfo::GetPackageId();
+       int appType = _AppInfo::GetAppType();
+       PackageId packageId = _AppInfo::GetPackageId();
+       packageId[0] = packageId[0];
+
+       if ((appType & _APP_TYPE_WEB_APP) != _APP_TYPE_WEB_APP)
+       {
+           if (isConstructed != true)
+           {
+               pthread_once(&onceBlock, Initialize);
+               r = GetLastResult();
+               if (IsFailed(r))
+               {
+                       if (r == E_DATA_NOT_FOUND)
+                       {
+                               SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
+                               goto CATCH;
+                       }
+                       else
+                       {
+                               onceBlock = PTHREAD_ONCE_INIT;
+                                       SysLogException(NID_SEC, r, "[%s] Propagated.", GetErrorMessage(r));
+                       }
+                               return r;
+               }
+           }
+
+               if ((pEncryptedPrivileges != null) && (pChecksum != null) && (pEncryptedVisibility != null) && (pVisibilityChecksum != null))
+               {
+                       r = privilegeInfo.Construct(packageId, *(pEncryptedPrivileges.get()), *(pChecksum.get()), *(pEncryptedVisibility.get()), *(pVisibilityChecksum.get()), pPrivilegeList.get());
+                       SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "An unexpected system error occurred. %ls", packageId.GetPointer());
+
+                       SysLog(NID_SEC, "%ls is in the cache [client]", privilegeInfo.GetAppId().GetPointer());
+               }
+               else
+               {
+                       SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
+                       r =  E_DATA_NOT_FOUND;
+                       goto CATCH;
+               }
+
+               ret = privilegeInfo.HasPrivilege(privilege);
+               if (!ret)
+               {
+                       r = E_PRIVILEGE_DENIED;
+                       goto CATCH;
+               }
+       }
+
+       r = CheckPrivacy(packageId, privilege);
+       SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
+
+       return r;
+
+CATCH:
+
+       SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
+
+       _AppManagerImpl* pAppManagerImpl = _AppManagerImpl::GetInstance();
+       pAppManagerImpl->TerminateApplications(packageId);
+
+       return r;
+
+}
+
+result
+_AccessController::CheckUserPrivilege(_Privilege privilege1, _Privilege privilege2)
+{
+       result r = E_SUCCESS;
+       static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
+
+       bool ret = false;
+
+       _PrivilegeInfo privilegeInfo;
+
+       ClearLastResult();
+
+       SysTryReturnResult(NID_SEC, privilege1 < _MAX_PRIVILEGE_ENUM, E_INVALID_ARG, "The privilege enumerator is invalid");
+       SysTryReturnResult(NID_SEC, privilege2 < _MAX_PRIVILEGE_ENUM, E_INVALID_ARG, "The privilege enumerator is invalid");
+       //SysAssertf(privilegeLevelListTable[privilege][_PRV_API_VER_2_0] == _PRV_LEVEL_USER, "System-level privilege is passed to CheckUserPrivilege.");
+
+       int appType = _AppInfo::GetAppType();
+       PackageId packageId = _AppInfo::GetPackageId();
+       packageId[0] = packageId[0];
 
        if ((appType & _APP_TYPE_WEB_APP) != _APP_TYPE_WEB_APP)
        {
@@ -234,7 +459,91 @@ _AccessController::CheckUserPrivilege(_Privilege privilege)
 
                if ((pEncryptedPrivileges != null) && (pChecksum != null) && (pEncryptedVisibility != null) && (pVisibilityChecksum != null))
                {
-                       r = privilegeInfo.Construct(packageId, *(pEncryptedPrivileges.get()), *(pChecksum.get()), *(pEncryptedVisibility.get()), *(pVisibilityChecksum.get()));
+                       r = privilegeInfo.Construct(packageId, *(pEncryptedPrivileges.get()), *(pChecksum.get()), *(pEncryptedVisibility.get()), *(pVisibilityChecksum.get()), pPrivilegeList.get());
+                       SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "An unexpected system error occurred. %ls", packageId.GetPointer());
+
+                       SysLog(NID_SEC, "%ls is in the cache [client]", privilegeInfo.GetAppId().GetPointer());
+               }
+               else
+               {
+                       SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
+                       r =  E_DATA_NOT_FOUND;
+                       goto CATCH;
+               }
+
+               ret = privilegeInfo.HasPrivilegeEx(privilege1);
+               if (!ret)
+               {
+                       ret = privilegeInfo.HasPrivilege(privilege2);
+                       if (!ret)
+                       {
+                               r = E_PRIVILEGE_DENIED;
+                               goto CATCH;
+                       }
+               }
+       }
+
+       r = CheckPrivacy(packageId, privilege2);
+       SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
+
+       return r;
+
+CATCH:
+
+       SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
+
+       _AppManagerImpl* pAppManagerImpl = _AppManagerImpl::GetInstance();
+       pAppManagerImpl->TerminateApplications(packageId);
+
+       return r;
+
+}
+
+
+result
+_AccessController::CheckPrivilege(const String& privilege)
+{
+       result r = E_SUCCESS;
+       static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
+
+       bool ret = false;
+
+       _PrivilegeInfo privilegeInfo;
+
+       ClearLastResult();
+
+       int appType = _AppInfo::GetAppType();
+       PackageId packageId = _AppInfo::GetPackageId();
+       packageId[0] = packageId[0];
+
+       if ((appType & _APP_TYPE_WEB_APP) != _APP_TYPE_WEB_APP)
+       {
+               if (isConstructed != true)
+               {
+                       pthread_once(&onceBlock, Initialize);
+                       r = GetLastResult();
+                       if (IsFailed(r))
+                       {
+                               if (r == E_DATA_NOT_FOUND)
+                               {
+                                       SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
+                                       goto CATCH;
+                               }
+                               else
+                               {
+                                       onceBlock = PTHREAD_ONCE_INIT;
+                                       SysLogException(NID_SEC, r, "[%s] Propagated.", GetErrorMessage(r));
+                               }
+                               return r;
+                       }
+               }
+
+               std::unique_ptr<IEnumerator> pEnum(null);
+               pEnum.reset(pPrivilegeList->GetEnumeratorN());
+
+               if ((pEncryptedPrivileges != null) && (pChecksum != null) && (pEncryptedVisibility != null) && (pVisibilityChecksum != null))
+               {
+                       r = privilegeInfo.Construct(packageId, *(pEncryptedPrivileges.get()), *(pChecksum.get()), *(pEncryptedVisibility.get()), *(pVisibilityChecksum.get()), pPrivilegeList.get());
                        SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "An unexpected system error occurred. %ls", packageId.GetPointer());
 
                        SysLog(NID_SEC, "%ls is in the cache [client]", privilegeInfo.GetAppId().GetPointer());
@@ -252,21 +561,78 @@ _AccessController::CheckUserPrivilege(_Privilege privilege)
                        r = E_PRIVILEGE_DENIED;
                        goto CATCH;
                }
+
        }
 
-       SysLog(NID_SEC, "Exit.");
+       r = CheckPrivacy(packageId, privilege);
+       SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
+
        return r;
 
 CATCH:
 
        SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
-       SysLog(NID_SEC, "Exit.");
 
        _AppManagerImpl* pAppManagerImpl = _AppManagerImpl::GetInstance();
        pAppManagerImpl->TerminateApplications(packageId);
 
        return r;
+}
+
+result
+_AccessController::CheckPrivacy(const PackageId & packageId, _Privilege privilege)
+{
+       result r = E_SUCCESS;
+       int ret = PRIV_MGR_ERROR_SUCCESS;
+
+       if (privacyListTable[privilege][_PRV_API_VER_2_0] != true)
+       {
+               return r;
+       }
+
+       std::unique_ptr<char[]> pPackageId(null);
+       pPackageId.reset(_StringConverter::CopyToCharArrayN(packageId));
+       SysTryReturnResult(NID_SEC, pPackageId != null, E_SYSTEM, "An unexpected system error occurred.");
 
+       std::unique_ptr<char[]> pPrivilegeId(null);
+       String privilegeId(L"http://tizen.org/privilege/");
+       privilegeId.Append(privilegeListTable[privilege].privilegeString);
+
+       pPrivilegeId.reset(_StringConverter::CopyToCharArrayN(privilegeId));
+       SysTryReturnResult(NID_SEC, pPrivilegeId != null, E_SYSTEM, "An unexpected system error occurred.");
+
+       ret = privacy_checker_check_package_by_privilege(pPackageId.get(), pPrivilegeId.get());
+       if (ret != PRIV_MGR_ERROR_SUCCESS)
+       {
+               r = E_USER_NOT_CONSENTED;
+               SysLog(NID_SEC, "Result : FALSE [Privacy]");
+       }
+
+       return r;
+}
+
+result
+_AccessController::CheckPrivacy(const PackageId & packageId, const String& privilege)
+{
+       result r = E_SUCCESS;
+       int ret = PRIV_MGR_ERROR_SUCCESS;
+
+       std::unique_ptr<char[]> pPackageId(null);
+       pPackageId.reset(_StringConverter::CopyToCharArrayN(packageId));
+       SysTryReturnResult(NID_SEC, pPackageId != null, E_SYSTEM, "An unexpected system error occurred.");
+
+       std::unique_ptr<char[]> pPrivilegeId(null);
+       pPrivilegeId.reset(_StringConverter::CopyToCharArrayN(privilege));
+       SysTryReturnResult(NID_SEC, pPrivilegeId != null, E_SYSTEM, "An unexpected system error occurred.");
+
+       ret = privacy_checker_check_package_by_privilege(pPackageId.get(), pPrivilegeId.get());
+       if (ret != PRIV_MGR_ERROR_SUCCESS)
+       {
+               r = E_USER_NOT_CONSENTED;
+               SysLog(NID_SEC, "Result : FALSE [Privacy]");
+       }
+
+       return r;
 }
 
 }} //Tizen::Security