Merge "Remove the memory leak on osp-security-service" into tizen_2.2
[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 <FBaseColArrayListT.h>
32 #include <FBaseColIEnumeratorT.h>
33 #include <FIoFile.h>
34 #include <FIo_IpcClient.h>
35 #include <FSecAccessController.h>
36 #include <FSec_AccessController.h>
37 #include "FSec_AccessControlTypes.h"
38 #include "FSec_PrivilegeManager.h"
39 #include "FSec_PrivilegeManagerMessage.h"
40 #include "FSec_PrivilegeInfo.h"
41
42
43 using namespace Tizen::App;
44 using namespace Tizen::App::Package;
45 using namespace Tizen::Base;
46 using namespace Tizen::Base::Collection;
47 using namespace Tizen::Io;
48
49 static bool isConstructed = false;
50 static std::unique_ptr<_IpcClient> pIpcClient(null);
51 static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
52 static pthread_once_t ipcOnceBlock = PTHREAD_ONCE_INIT;
53
54 namespace Tizen { namespace Security
55 {
56
57 AccessController::AccessController(void)
58 {
59
60 }
61
62 AccessController::~AccessController(void)
63 {
64
65 }
66
67 static _PrivilegeInfo privilegeInfo;
68
69
70 void
71 AccessController::InitIpcClient(void)
72 {
73         std::unique_ptr<_IpcClient> pLocalIpcClient(new (std::nothrow) _IpcClient);
74         SysTryReturnVoidResult(NID_SEC, pLocalIpcClient != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
75
76         result r = pLocalIpcClient->Construct(L"osp.security.ipcserver.privilegemanager", null);
77         SysTryReturnVoidResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "Failed to construct the instance of IPC.");
78
79         pIpcClient = std::move(pLocalIpcClient);
80         return;
81 }
82
83 void
84 AccessController::Initialize(void)
85 {
86         result r = E_SUCCESS;
87
88         if (pIpcClient == null)
89     {
90         pthread_once(&ipcOnceBlock, InitIpcClient);
91         r = GetLastResult();
92         if (IsFailed(r))
93         {
94                 ipcOnceBlock = PTHREAD_ONCE_INIT;
95                         SysLogException(NID_SEC, r, "[%s] Propagated.", GetErrorMessage(r));
96                         return;
97         }
98     }
99
100     std::unique_ptr<String> pEncryptedPrivileges(new (std::nothrow) String());
101         SysTryReturnVoidResult(NID_SEC, pEncryptedPrivileges != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
102
103         std::unique_ptr<String> pChecksum(new (std::nothrow) String());
104         SysTryReturnVoidResult(NID_SEC, pChecksum != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
105
106         std::unique_ptr< ArrayListT< String > > pPrivilegeListT(new ArrayListT< String >());
107         SysTryReturnVoidResult(NID_SEC, pPrivilegeListT != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
108
109         pPrivilegeListT->Construct();
110
111         std::unique_ptr<IPC::Message> pCipherPrivilegeMessage(new (std::nothrow) PrivilegeManagerMsg_retrieve(pEncryptedPrivileges.get(), pChecksum.get(), pPrivilegeListT.get(), &r));
112         SysTryReturnVoidResult(NID_SEC, pCipherPrivilegeMessage != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
113
114         result ipcResult = pIpcClient->SendRequest(pCipherPrivilegeMessage.get());
115         SysTryReturnVoidResult(NID_SEC, ipcResult == E_SUCCESS, E_SYSTEM, "Failed to send IPC message.");
116         SysTryReturnVoidResult(NID_SEC, r == E_SUCCESS, r, "Failed to retrieve privilege information");
117
118         std::unique_ptr<ArrayList> pPrivilegeList(new ArrayList());
119         SysTryReturnVoidResult(NID_SEC, pPrivilegeList != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
120
121         pPrivilegeList->Construct();
122
123         std::unique_ptr<IEnumeratorT< String > > pEnum(pPrivilegeListT->GetEnumeratorN());
124         while (pEnum->MoveNext() == E_SUCCESS)
125         {
126                 String tempString;
127                 pEnum->GetCurrent(tempString);
128                 pPrivilegeList->Add(new String(tempString));
129         }
130         pPrivilegeListT->RemoveAll();
131
132         std::unique_ptr<String> pEncryptedVisibility(new (std::nothrow) String());
133         SysTryReturnVoidResult(NID_SEC, pEncryptedVisibility != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
134
135         std::unique_ptr<String> pVisibilityChecksum(new (std::nothrow) String());
136         SysTryReturnVoidResult(NID_SEC, pVisibilityChecksum != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
137
138         std::unique_ptr<IPC::Message> pCipherVisibilityMessage(new (std::nothrow) PrivilegeManagerMsg_retrieveEx(pEncryptedVisibility.get(), pVisibilityChecksum.get(), &r));
139         SysTryReturnVoidResult(NID_SEC, pCipherVisibilityMessage != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
140
141         ipcResult = pIpcClient->SendRequest(pCipherVisibilityMessage.get());
142         SysTryReturnVoidResult(NID_SEC, ipcResult == E_SUCCESS, E_SYSTEM, "Failed to send IPC message.");
143         SysTryReturnVoidResult(NID_SEC, r == E_SUCCESS, r, "Failed to retrieve privilege information");
144
145         PackageId packageId = _AppInfo::GetPackageId();
146         packageId[0] = packageId[0];
147
148         r = privilegeInfo.Construct(packageId, *(pEncryptedPrivileges.get()), *(pChecksum.get()), *(pEncryptedVisibility.get()), *(pVisibilityChecksum.get()), pPrivilegeList.get());
149         SysTryReturnVoidResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "An unexpected system error occurred.");
150
151         pPrivilegeList->RemoveAll(true);
152         isConstructed = true;
153
154         return;
155 }
156
157 result
158 AccessController::CheckPrivilege(int privilege)
159 {
160         result r = E_SUCCESS;
161         bool ret = false;
162         ClearLastResult();
163
164         SysTryReturnResult(NID_SEC, (privilege >= 0) && (privilege < _MAX_PRIVILEGE_ENUM), E_INVALID_ARG, "The privilege enumerator is invalid");
165
166         if (!isConstructed)
167         {
168                 pthread_once(&onceBlock, Initialize);
169                 r = GetLastResult();
170                 if (IsFailed(r))
171                 {
172                         if (r == E_DATA_NOT_FOUND)
173                         {
174                                 SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
175                                 goto CATCH;
176                         }
177                         else
178                         {
179                                 onceBlock = PTHREAD_ONCE_INIT;
180                                 SysLogException(NID_SEC, r, "[%s] Propagated.", GetErrorMessage(r));
181                         }
182                         return r;
183                 }
184         }
185
186         if (privilegeInfo.GetAppId().IsEmpty())
187         {
188                 SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
189                 r = E_DATA_NOT_FOUND;
190                 goto CATCH;
191         }
192         else
193         {
194                 SysLog(NID_SEC, "%ls is in the cache [client]", privilegeInfo.GetAppId().GetPointer());
195         }
196
197         ret = privilegeInfo.HasPrivilege(static_cast< _Privilege >(privilege));
198         if (!ret)
199         {
200                 r = E_PRIVILEGE_DENIED;
201                 goto CATCH;
202         }
203
204         r = _AccessController::CheckPrivacy(privilegeInfo.GetAppId(), static_cast< _Privilege >(privilege));
205         SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
206
207         return r;
208
209 CATCH:
210
211         SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
212         return r;
213 }
214
215 result
216 AccessController::CheckPrivilege(const String& privilege)
217 {
218         result r = E_SUCCESS;
219         bool ret = false;
220         ClearLastResult();
221
222         if (!isConstructed)
223         {
224                 pthread_once(&onceBlock, Initialize);
225                 r = GetLastResult();
226                 if (IsFailed(r))
227                 {
228                         if (r == E_DATA_NOT_FOUND)
229                         {
230                                 SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
231                                 goto CATCH;
232                         }
233                         else
234                         {
235                                 onceBlock = PTHREAD_ONCE_INIT;
236                                 SysLogException(NID_SEC, r, "[%s] Propagated.", GetErrorMessage(r));
237                         }
238                         return r;
239                 }
240         }
241
242         if (privilegeInfo.GetAppId().IsEmpty())
243         {
244                 SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
245                 r = E_DATA_NOT_FOUND;
246                 goto CATCH;
247         }
248         else
249         {
250                 SysLog(NID_SEC, "%ls is in the cache [client]", privilegeInfo.GetAppId().GetPointer());
251         }
252
253         ret = privilegeInfo.HasPrivilege(privilege);
254         if (!ret)
255         {
256                 r = E_PRIVILEGE_DENIED;
257                 goto CATCH;
258         }
259
260         r = _AccessController::CheckPrivacy(privilegeInfo.GetAppId(), privilege);
261         SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
262
263         return r;
264
265 CATCH:
266
267         SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
268         return r;
269 }
270
271 _PrivilegeManager* AccessController::__pPrivilegeManager = null;
272
273 result
274 AccessController::CheckPrivilege(const PackageId& packageId, const String& privilege)
275 {
276         bool ret = false;
277         result r = _AccessController::CheckUserPrivilege(_PRV_PRIVILEGEMANAGER_READ);
278         SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
279
280         String subAppId;
281         packageId.SubString(0, MAX_APP_ID_SIZE, subAppId);
282
283         _PackageInfoImpl infoImpl;
284         r = infoImpl.Construct(packageId);
285         SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "An unexpected system error occurred.");
286
287         String appType;
288         String webAppType(L"wgt");
289         String cAppType(L"rpm");
290         appType = infoImpl.GetAppType();
291         if (appType.Equals(webAppType, true))
292         {
293                 return E_SUCCESS;
294         }
295         else if (appType.Equals(cAppType, true))
296         {
297                 r = _AccessController::CheckPrivacy(packageId, privilege);
298                 SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
299
300                 return r;
301         }
302
303         if (__pPrivilegeManager == null)
304         {
305                 __pPrivilegeManager = _PrivilegeManager::GetInstance();
306         }
307         SysTryReturnResult(NID_SEC, __pPrivilegeManager != null, E_SYSTEM, "An unexpected system error occurred.");
308
309         std::unique_ptr<_PrivilegeInfo> pPrivilegeInfo(__pPrivilegeManager->RetrievePrivilegeInfoN(subAppId));
310         r = GetLastResult();
311
312         if (r == E_SUCCESS)
313         {
314                 // nothing to do.
315         }
316         else if (r == E_DATA_NOT_FOUND)
317         {
318                 SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
319                 goto CATCH;
320         }
321         else
322         {
323                 SysLogException(NID_SEC, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
324                 return E_SYSTEM;
325         }
326
327         ret = pPrivilegeInfo->HasPrivilege(privilege);
328         if (!ret)
329         {
330                 r = E_PRIVILEGE_DENIED;
331                 goto CATCH;
332         }
333
334         r = _AccessController::CheckPrivacy(packageId, privilege);
335         SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_USER_NOT_CONSENTED, "The user blocks an application from calling the method.");
336
337         return r;
338
339 CATCH:
340
341         SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
342         return r;
343 }
344
345 }} //Tizen::Security