02493830cfab3f07e6fea7e27f999dde79e0d1e3
[platform/framework/native/appfw.git] / src / security / FSecAccessController.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file        FSecAccessController.cpp
19  * @brief       This is the implementation for the AccessController class.
20  */
21
22 #include <unique_ptr.h>
23 #include <FAppTypes.h>
24 #include <FAppApplication.h>
25 #include <FApp_AppInfo.h>
26 #include <FApp_AppManagerImpl.h>
27 #include <FAppPkg_PackageInfoImpl.h>
28 #include <FBaseSysLog.h>
29 #include <FBaseString.h>
30 #include <FBaseColArrayList.h>
31 #include <FIoFile.h>
32 #include <FIo_IpcClient.h>
33 #include <FSecAccessController.h>
34 #include <FSec_AccessController.h>
35 #include "FSec_AccessControlTypes.h"
36 #include "FSec_PrivilegeManager.h"
37 #include "FSec_PrivilegeManagerMessage.h"
38 #include "FSec_PrivilegeInfo.h"
39
40
41 using namespace Tizen::App;
42 using namespace Tizen::App::Package;
43 using namespace Tizen::Base;
44 using namespace Tizen::Base::Collection;
45 using namespace Tizen::Io;
46
47 static bool isConstructed = false;
48 static std::unique_ptr<_IpcClient> pIpcClient(null);
49 static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
50 static pthread_once_t ipcOnceBlock = PTHREAD_ONCE_INIT;
51
52 namespace Tizen { namespace Security
53 {
54
55 AccessController::AccessController(void)
56 {
57
58 }
59
60 AccessController::~AccessController(void)
61 {
62
63 }
64
65 static _PrivilegeInfo privilegeInfo;
66
67
68 void
69 AccessController::InitIpcClient(void)
70 {
71         std::unique_ptr<_IpcClient> pLocalIpcClient(new (std::nothrow) _IpcClient);
72         SysTryReturnVoidResult(NID_SEC, pLocalIpcClient != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
73
74         result r = pLocalIpcClient->Construct(L"osp.security.ipcserver.privilegemanager", null);
75         SysTryReturnVoidResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "Failed to construct the instance of IPC.");
76
77         pIpcClient = std::move(pLocalIpcClient);
78         return;
79 }
80
81 void
82 AccessController::Initialize(void)
83 {
84         result r = E_SUCCESS;
85
86         if (pIpcClient == null)
87     {
88         pthread_once(&ipcOnceBlock, InitIpcClient);
89         r = GetLastResult();
90         if (IsFailed(r))
91         {
92                 ipcOnceBlock = PTHREAD_ONCE_INIT;
93                         SysLogException(NID_SEC, r, "[%s] Propagated.", GetErrorMessage(r));
94                         return;
95         }
96     }
97
98     std::unique_ptr<String> pEncryptedPrivileges(new (std::nothrow) String());
99         SysTryReturnVoidResult(NID_SEC, pEncryptedPrivileges != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
100
101         std::unique_ptr<String> pChecksum(new (std::nothrow) String());
102         SysTryReturnVoidResult(NID_SEC, pChecksum != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
103
104         std::unique_ptr<ArrayList> pPrivilegeList(new ArrayList());
105         SysTryReturnVoidResult(NID_SEC, pPrivilegeList != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
106
107         pPrivilegeList->Construct();
108
109         std::unique_ptr<IPC::Message> pCipherPrivilegeMessage(new (std::nothrow) PrivilegeManagerMsg_retrieve(pEncryptedPrivileges.get(), pChecksum.get(), pPrivilegeList.get(), &r));
110         SysTryReturnVoidResult(NID_SEC, pCipherPrivilegeMessage != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
111
112         result ipcResult = pIpcClient->SendRequest(pCipherPrivilegeMessage.get());
113         SysTryReturnVoidResult(NID_SEC, ipcResult == E_SUCCESS, E_SYSTEM, "Failed to send IPC message.");
114         SysTryReturnVoidResult(NID_SEC, r == E_SUCCESS, r, "Failed to retrieve privilege information");
115
116         std::unique_ptr<String> pEncryptedVisibility(new (std::nothrow) String());
117         SysTryReturnVoidResult(NID_SEC, pEncryptedVisibility != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
118
119         std::unique_ptr<String> pVisibilityChecksum(new (std::nothrow) String());
120         SysTryReturnVoidResult(NID_SEC, pVisibilityChecksum != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
121
122         std::unique_ptr<IPC::Message> pCipherVisibilityMessage(new (std::nothrow) PrivilegeManagerMsg_retrieveEx(pEncryptedVisibility.get(), pVisibilityChecksum.get(), &r));
123         SysTryReturnVoidResult(NID_SEC, pCipherVisibilityMessage != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
124
125         ipcResult = pIpcClient->SendRequest(pCipherVisibilityMessage.get());
126         SysTryReturnVoidResult(NID_SEC, ipcResult == E_SUCCESS, E_SYSTEM, "Failed to send IPC message.");
127         SysTryReturnVoidResult(NID_SEC, r == E_SUCCESS, r, "Failed to retrieve privilege information");
128
129         PackageId packageId = _AppInfo::GetPackageId();
130         packageId[0] = packageId[0];
131
132         r = privilegeInfo.Construct(packageId, *(pEncryptedPrivileges.get()), *(pChecksum.get()), *(pEncryptedVisibility.get()), *(pVisibilityChecksum.get()), pPrivilegeList.get());
133         SysTryReturnVoidResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "An unexpected system error occurred.");
134
135         pPrivilegeList->RemoveAll(true);
136         isConstructed = true;
137
138         return;
139 }
140
141 result
142 AccessController::CheckPrivilege(int privilege)
143 {
144         result r = E_SUCCESS;
145         bool ret = false;
146         ClearLastResult();
147
148         SysTryReturnResult(NID_SEC, (privilege >= 0) && (privilege < _MAX_PRIVILEGE_ENUM), E_INVALID_ARG, "The privilege enumerator is invalid");
149
150         if (!isConstructed)
151         {
152                 pthread_once(&onceBlock, Initialize);
153                 r = GetLastResult();
154                 if (IsFailed(r))
155                 {
156                         if (r == E_DATA_NOT_FOUND)
157                         {
158                                 SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
159                                 goto CATCH;
160                         }
161                         else
162                         {
163                                 onceBlock = PTHREAD_ONCE_INIT;
164                                 SysLogException(NID_SEC, r, "[%s] Propagated.", GetErrorMessage(r));
165                         }
166                         return r;
167                 }
168         }
169
170         if (privilegeInfo.GetAppId().IsEmpty())
171         {
172                 SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
173                 r = E_DATA_NOT_FOUND;
174                 goto CATCH;
175         }
176         else
177         {
178                 SysLog(NID_SEC, "%ls is in the cache [client]", privilegeInfo.GetAppId().GetPointer());
179         }
180
181         ret = privilegeInfo.HasPrivilege(static_cast< _Privilege >(privilege));
182         if (!ret)
183         {
184                 r = E_PRIVILEGE_DENIED;
185                 goto CATCH;
186         }
187
188         r = _AccessController::CheckPrivacy(privilegeInfo.GetAppId(), static_cast< _Privilege >(privilege));
189         SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
190
191         return r;
192
193 CATCH:
194
195         SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
196         return r;
197 }
198
199 result
200 AccessController::CheckPrivilege(const String& privilege)
201 {
202         result r = E_SUCCESS;
203         bool ret = false;
204         ClearLastResult();
205
206         if (!isConstructed)
207         {
208                 pthread_once(&onceBlock, Initialize);
209                 r = GetLastResult();
210                 if (IsFailed(r))
211                 {
212                         if (r == E_DATA_NOT_FOUND)
213                         {
214                                 SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
215                                 goto CATCH;
216                         }
217                         else
218                         {
219                                 onceBlock = PTHREAD_ONCE_INIT;
220                                 SysLogException(NID_SEC, r, "[%s] Propagated.", GetErrorMessage(r));
221                         }
222                         return r;
223                 }
224         }
225
226         if (privilegeInfo.GetAppId().IsEmpty())
227         {
228                 SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
229                 r = E_DATA_NOT_FOUND;
230                 goto CATCH;
231         }
232         else
233         {
234                 SysLog(NID_SEC, "%ls is in the cache [client]", privilegeInfo.GetAppId().GetPointer());
235         }
236
237         ret = privilegeInfo.HasPrivilege(privilege);
238         if (!ret)
239         {
240                 r = E_PRIVILEGE_DENIED;
241                 goto CATCH;
242         }
243
244         r = _AccessController::CheckPrivacy(privilegeInfo.GetAppId(), privilege);
245         SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
246
247         return r;
248
249 CATCH:
250
251         SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
252         return r;
253 }
254
255 _PrivilegeManager* AccessController::__pPrivilegeManager = null;
256
257 result
258 AccessController::CheckPrivilege(const PackageId& packageId, const String& privilege)
259 {
260         bool ret = false;
261         result r = _AccessController::CheckUserPrivilege(_PRV_PRIVILEGEMANAGER_READ);
262         SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
263
264         String subAppId;
265         packageId.SubString(0, MAX_APP_ID_SIZE, subAppId);
266
267         _PackageInfoImpl infoImpl;
268         r = infoImpl.Construct(packageId);
269         SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "An unexpected system error occurred.");
270
271         String appType;
272         String webAppType(L"wgt");
273         String cAppType(L"rpm");
274         appType = infoImpl.GetAppType();
275         if (appType.Equals(webAppType, true))
276         {
277                 return E_SUCCESS;
278         }
279         else if (appType.Equals(cAppType, true))
280         {
281                 r = _AccessController::CheckPrivacy(packageId, privilege);
282                 SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
283
284                 return r;
285         }
286
287         if (__pPrivilegeManager == null)
288         {
289                 __pPrivilegeManager = _PrivilegeManager::GetInstance();
290         }
291         SysTryReturnResult(NID_SEC, __pPrivilegeManager != null, E_SYSTEM, "An unexpected system error occurred.");
292
293         std::unique_ptr<_PrivilegeInfo> pPrivilegeInfo(__pPrivilegeManager->RetrievePrivilegeInfoN(subAppId));
294         r = GetLastResult();
295
296         if (r == E_SUCCESS)
297         {
298                 // nothing to do.
299         }
300         else if (r == E_DATA_NOT_FOUND)
301         {
302                 SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
303                 goto CATCH;
304         }
305         else
306         {
307                 SysLogException(NID_SEC, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
308                 return E_SYSTEM;
309         }
310
311         ret = pPrivilegeInfo->HasPrivilege(privilege);
312         if (!ret)
313         {
314                 r = E_PRIVILEGE_DENIED;
315                 goto CATCH;
316         }
317
318         r = _AccessController::CheckPrivacy(packageId, privilege);
319         SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
320
321         return r;
322
323 CATCH:
324
325         SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
326         return r;
327 }
328
329 }} //Tizen::Security