sync with master
[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
51 namespace Tizen { namespace Security
52 {
53
54 AccessController::AccessController(void)
55 {
56
57 }
58
59 AccessController::~AccessController(void)
60 {
61
62 }
63
64 static _PrivilegeInfo privilegeInfo;
65
66
67 void
68 AccessController::Initialize(void)
69 {
70         result r = E_SUCCESS;
71         result ipcResult = E_SUCCESS;
72
73         std::unique_ptr<String> pEncryptedPrivileges(null);
74         std::unique_ptr<String> pChecksum(null);
75         std::unique_ptr<String> pEncryptedVisibility(null);
76         std::unique_ptr<String> pVisibilityChecksum(null);
77
78         std::unique_ptr<IPC::Message> pCipherPrivilegeMessage(null);
79         std::unique_ptr<IPC::Message> pCipherVisibilityMessage(null);
80         std::unique_ptr<ArrayList> pPrivilegeList(null);
81
82         r = ipcClient.Construct(L"osp.security.ipcserver.privilegemanager", null);
83         SysTryReturnVoidResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "Failed to construct the instance of IPC.");
84
85         pEncryptedPrivileges.reset(new (std::nothrow) String());
86         SysTryReturnVoidResult(NID_SEC, pEncryptedPrivileges != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
87
88         pChecksum.reset(new (std::nothrow) String());
89         SysTryReturnVoidResult(NID_SEC, pChecksum != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
90
91         pPrivilegeList.reset(new ArrayList());
92         SysTryReturnVoidResult(NID_SEC, pPrivilegeList != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
93
94         pPrivilegeList->Construct();
95
96         pCipherPrivilegeMessage.reset(new (std::nothrow) PrivilegeManagerMsg_retrieve(pEncryptedPrivileges.get(), pChecksum.get(), pPrivilegeList.get(), &r));
97         SysTryReturnVoidResult(NID_SEC, pCipherPrivilegeMessage != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
98
99         ipcResult = ipcClient.SendRequest(pCipherPrivilegeMessage.get());
100         SysTryReturnVoidResult(NID_SEC, ipcResult == E_SUCCESS, E_SYSTEM, "Failed to send IPC message.");
101         SysTryReturnVoidResult(NID_SEC, r == E_SUCCESS, r, "Failed to retrieve privilege information");
102
103         pEncryptedVisibility.reset(new (std::nothrow) String());
104         SysTryReturnVoidResult(NID_SEC, pEncryptedVisibility != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
105
106         pVisibilityChecksum.reset(new (std::nothrow) String());
107         SysTryReturnVoidResult(NID_SEC, pVisibilityChecksum != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
108
109         pCipherVisibilityMessage.reset(new (std::nothrow) PrivilegeManagerMsg_retrieveEx(pEncryptedVisibility.get(), pVisibilityChecksum.get(), &r));
110         SysTryReturnVoidResult(NID_SEC, pCipherVisibilityMessage != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
111
112         ipcResult = ipcClient.SendRequest(pCipherVisibilityMessage.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         PackageId packageId = _AppInfo::GetPackageId();
117         packageId[0] = packageId[0];
118
119         r = privilegeInfo.Construct(packageId, *(pEncryptedPrivileges.get()), *(pChecksum.get()), *(pEncryptedVisibility.get()), *(pVisibilityChecksum.get()), pPrivilegeList.get());
120         SysTryReturnVoidResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "An unexpected system error occurred.");
121
122         pPrivilegeList->RemoveAll(true);
123         isConstructed = true;
124         return;
125 }
126
127 result
128 AccessController::CheckPrivilege(int privilege)
129 {
130         result r = E_SUCCESS;
131         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
132
133         bool ret = false;
134
135         ClearLastResult();
136
137         SysTryReturnResult(NID_SEC, privilege < _MAX_PRIVILEGE_ENUM, E_INVALID_ARG, "The privilege enumerator is invalid");
138
139         if (!isConstructed)
140         {
141                 pthread_once(&onceBlock, Initialize);
142                 r = GetLastResult();
143                 if (IsFailed(r))
144                 {
145                         if (r == E_DATA_NOT_FOUND)
146                         {
147                                 SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
148                                 goto CATCH;
149                         }
150                         else
151                         {
152                                 onceBlock = PTHREAD_ONCE_INIT;
153                                 SysLogException(NID_SEC, r, "[%s] Propagated.", GetErrorMessage(r));
154                         }
155                         return r;
156                 }
157         }
158
159         if (privilegeInfo.GetAppId().IsEmpty())
160         {
161                 SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
162                 r = E_DATA_NOT_FOUND;
163                 goto CATCH;
164         }
165         else
166         {
167                 SysLog(NID_SEC, "%ls is in the cache [client]", privilegeInfo.GetAppId().GetPointer());
168         }
169
170         ret = privilegeInfo.HasPrivilege(static_cast< _Privilege >(privilege));
171         if (!ret)
172         {
173                 r = E_PRIVILEGE_DENIED;
174                 goto CATCH;
175         }
176
177         return r;
178
179 CATCH:
180
181         SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
182         return r;
183 }
184
185 result
186 AccessController::CheckPrivilege(const String& privilege)
187 {
188         result r = E_SUCCESS;
189         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
190
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         return r;
234
235 CATCH:
236
237         SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
238         return r;
239 }
240
241 _PrivilegeManager* AccessController::__pPrivilegeManager = null;
242
243 result
244 AccessController::CheckPrivilege(const PackageId& packageId, const String& privilege)
245 {
246         result r = E_SUCCESS;
247
248         bool ret = false;
249         std::unique_ptr<_PrivilegeInfo> pPrivilegeInfo(null);
250         String subAppId;
251         _PackageInfoImpl infoImpl;
252         String appType;
253         String webAppType(L"wgt");
254
255         r = _AccessController::CheckUserPrivilege(_PRV_PRIVILEGEMANAGER_READ);
256         SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
257
258         packageId.SubString(0, MAX_APP_ID_SIZE, subAppId);
259
260         r = infoImpl.Construct(subAppId);
261         SysTryReturnResult(NID_SEC, r == E_SUCCESS, E_SYSTEM, "An unexpected system error occurred.");
262
263         appType = infoImpl.GetAppType();
264         if (appType.Equals(webAppType, true))
265         {
266                 return E_SUCCESS;
267         }
268
269         if (__pPrivilegeManager == null)
270         {
271                 __pPrivilegeManager = _PrivilegeManager::GetInstance();
272         }
273         SysTryReturnResult(NID_SEC, __pPrivilegeManager != null, E_SYSTEM, "An unexpected system error occurred.");
274
275         pPrivilegeInfo.reset(__pPrivilegeManager->RetrievePrivilegeInfoN(subAppId));
276         r = GetLastResult();
277
278         if (r == E_SUCCESS)
279         {
280                 // nothing to do.
281         }
282         else if (r == E_DATA_NOT_FOUND)
283         {
284                 SysLogException(NID_SEC, E_DATA_NOT_FOUND, "[E_DATA_NOT_FOUND] The privilege information does not exist.");
285                 goto CATCH;
286         }
287         else
288         {
289                 SysLogException(NID_SEC, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
290                 return E_SYSTEM;
291         }
292
293         ret = pPrivilegeInfo->HasPrivilege(privilege);
294         if (!ret)
295         {
296                 r = E_PRIVILEGE_DENIED;
297                 goto CATCH;
298         }
299
300         return r;
301
302 CATCH:
303
304         SysLogException(NID_SEC,  r, "[E_PRIVILEGE_DENIED] The application does not have the privilege to call this method.");
305         return r;
306 }
307
308 }} //Tizen::Security