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