f3ac8e31e4510bb4c03712a83fce7e9f37d92c71
[platform/framework/native/installer.git] / src / XmlHandler / PrivilegeHandler.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  * @file                PrivilegeHandler.cpp
19  * @brief               This is the implementation for the PrivilegeHandler class.
20  */
21
22 #include <stdlib.h>
23
24 #include <FBaseString.h>
25 #include <FBaseLog.h>
26 #include <FSecCryptoAesCipher.h>
27 #include <FSecCryptoSha1Hash.h>
28 #include <FBase_StringConverter.h>
29 #include <FBaseInternalTypes.h>
30 #include <FSec_AccessControlTypes.h>
31 #include <FIoDatabase.h>
32 #include <FIoDbEnumerator.h>
33
34 #include "InstallerDefs.h"
35 #include "PrivilegeHandler.h"
36 #include "InstallerUtil.h"
37
38 using namespace Tizen::App;
39 using namespace Tizen::Base;
40 using namespace Tizen::Base::Collection;
41 using namespace Tizen::Base::Utility;
42 using namespace Tizen::Security;
43 using namespace Tizen::Security::Crypto;
44 using namespace Tizen::Text;
45 using namespace Tizen::Io;
46
47
48 result
49 PrivilegeHandler::PickExternalPrivilege(const IList& fullPrivilegeList, IList& normalPrivilegeList, IList& externalPrivilegeList)
50 {
51         result r = E_SUCCESS;
52         String externalPrivilege;
53         ArrayList privilegeList;
54         Database privilegeDb;
55         DbEnumerator* pDbEnum;
56
57         r = privilegeDb.Construct(EXTERNAL_PRIVILEGE_DB_NAME, "r");
58         TryReturnResultTag(OSP_INSTALLER, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
59
60
61         pDbEnum = privilegeDb.QueryN(L"SELECT PRIVILEGE_ID FROM PrivilegeInfo");
62         TryReturnResultTag(OSP_INSTALLER, pDbEnum != null, E_DATABASE, E_DATABASE, "[E_DATABASE] Privilege database error.");
63
64         AppLog("------------------------------------------");
65         AppLog("External Privilege");
66         AppLog("------------------------------------------");
67
68         while (pDbEnum->MoveNext() == E_SUCCESS)
69         {
70                 r = pDbEnum->GetStringAt(0, externalPrivilege);
71                 TryReturnResultTag(OSP_INSTALLER, r == E_SUCCESS, E_DATABASE, E_DATABASE, "[E_DATABASE] Privilege database error.");
72
73                 AppLog("%ls", externalPrivilege.GetPointer());
74                 privilegeList.Add(new String(externalPrivilege));
75         }
76         delete pDbEnum;
77
78         IEnumerator* pEnum = fullPrivilegeList.GetEnumeratorN();
79         while(pEnum->MoveNext() == E_SUCCESS)
80         {
81                 String* tempString = static_cast<String*>(pEnum->GetCurrent());
82
83                 if (privilegeList.Contains(*tempString))
84                 {
85                         externalPrivilegeList.Add(new String(*tempString));
86                 }
87                 else
88                 {
89                         normalPrivilegeList.Add(new String(*tempString));
90                 }
91         }
92
93         delete pEnum;
94         privilegeList.RemoveAll(true);
95         return r;
96 }
97
98 result
99 PrivilegeHandler::GenerateCipherPrivilege(const AppId& appId, const IList& privilegeList, String& encryptedPrivileges, String& checksum, IList& stringPrivilegeList)
100 {
101         result r = E_SUCCESS;
102         byte* pBitwisePrivilege = null;
103         int count = 0;
104         ArrayList normalPrivilegeList;
105
106         encryptedPrivileges.Clear();
107         checksum.Clear();
108         normalPrivilegeList.Construct();
109
110         count = privilegeList.GetCount();
111         if (count == 0)
112         {
113                 goto CATCH;
114         }
115
116         r = PickExternalPrivilege(privilegeList, normalPrivilegeList, stringPrivilegeList);
117         if (r == E_SUCCESS)
118         {
119                 pBitwisePrivilege = PackPrivilegeN(normalPrivilegeList);
120                 TryReturnResultTag(OSP_INSTALLER, pBitwisePrivilege != null, GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
121         }
122         else
123         {
124                 AppLog("Working with normal PrivilegeDb.");
125                 pBitwisePrivilege = PackPrivilegeN(privilegeList);
126                 TryReturnResultTag(OSP_INSTALLER, pBitwisePrivilege != null, GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
127         }
128
129         r = GetEncryptedBitwise(pBitwisePrivilege, encryptedPrivileges);
130         TryCatchTag(OSP_INSTALLER, r == E_SUCCESS, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
131
132         r = GetChecksum(appId, pBitwisePrivilege, checksum);
133         TryCatchTag(OSP_INSTALLER, r == E_SUCCESS, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
134
135         // fall through
136
137 CATCH:
138
139         if (pBitwisePrivilege)
140         {
141                 free(pBitwisePrivilege);
142         }
143
144         normalPrivilegeList.RemoveAll(true);
145         return r;
146 }
147
148 result
149 PrivilegeHandler::GenerateCipherPrivilege(const AppId& appId, const IList& privilegeList, int visibilityLevel, String& encryptedPrivileges, String& checksum, IList& stringPrivilegeList)
150 {
151         result r = E_SUCCESS;
152         byte* pBitwisePrivilege = null;
153         int count = 0;
154         ArrayList normalPrivilegeList;
155
156         encryptedPrivileges.Clear();
157         checksum.Clear();
158         normalPrivilegeList.Construct();
159
160         count = privilegeList.GetCount();
161         if (count == 0)
162         {
163                 goto CATCH;
164         }
165
166         r = PickExternalPrivilege(privilegeList, normalPrivilegeList, stringPrivilegeList);
167         if (r == E_SUCCESS)
168         {
169                 r = PackPrivilegeN(normalPrivilegeList, visibilityLevel, &pBitwisePrivilege);
170                 TryReturnResultTag(OSP_INSTALLER, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
171         }
172         else
173         {
174                 AppLog("Working with normal PrivilegeDb.");
175                 r = PackPrivilegeN(privilegeList, visibilityLevel, &pBitwisePrivilege);
176                 TryReturnResultTag(OSP_INSTALLER, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
177         }
178
179         r = GetEncryptedBitwise(pBitwisePrivilege, encryptedPrivileges);
180         TryCatchTag(OSP_INSTALLER, r == E_SUCCESS, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
181
182         r = GetChecksum(appId, pBitwisePrivilege, checksum);
183         TryCatchTag(OSP_INSTALLER, r == E_SUCCESS, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
184
185         // fall through
186
187 CATCH:
188
189         if (pBitwisePrivilege)
190         {
191                 free(pBitwisePrivilege);
192         }
193
194         normalPrivilegeList.RemoveAll(true);
195         return r;
196 }
197
198 byte*
199 PrivilegeHandler::PackPrivilegeN(const IList& privilegeList)
200 {
201         result r = E_SUCCESS;
202         int index = 0;
203         int privilegeEnum = 0;
204         int position = 0;
205         bool validStringFlag = false;
206         bool resultFlag = true;
207         byte privilegeBit = 0;
208         byte* pResult = null;
209         byte* pBitwisePrivilege = null;
210         IEnumerator* pEnum = null;
211
212         ClearLastResult();
213
214         pResult = (byte*) malloc(sizeof(byte) * MAX_BITWISE_PRIV_SIZE);
215         TryReturnResultTag(OSP_INSTALLER, pResult != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
216
217         memset(pResult, 0, MAX_BITWISE_PRIV_SIZE);
218
219         pEnum = privilegeList.GetEnumeratorN();
220         TryCatch(pEnum != null, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
221
222         while (pEnum->MoveNext() == E_SUCCESS)
223         {
224                 validStringFlag = false;
225                 String privilegeURI = L"http://tizen.org/privilege/";
226
227                 String* pTempString = (String*) pEnum->GetCurrent();
228
229                 if ((pTempString->GetLength()) < (privilegeURI.GetLength()))
230                 {
231                         AppLogExceptionTag(OSP_INSTALLER, "[E_INVALID_ARG] Invalid privilege string (Length error): [%ls]", pTempString->GetPointer());
232                         resultFlag = false;
233                         continue;
234                 }
235
236                 String uriString;
237                 pTempString->SubString(0, privilegeURI.GetLength(), uriString);
238
239                 if (!(uriString.Equals(privilegeURI, true)))
240                 {
241                         AppLogExceptionTag(OSP_INSTALLER, "[E_INVALID_ARG] Invalid privilege string (URI error): [%ls]", pTempString->GetPointer());
242                         resultFlag = false;
243                         continue;
244                 }
245
246                 String privilegeString;
247                 pTempString->SubString(privilegeURI.GetLength(), pTempString->GetLength()-privilegeURI.GetLength(), privilegeString);
248
249                 for (index = 0; index < _MAX_PRIVILEGE_ENUM; index++)
250                 {
251                         if (wcscmp(privilegeListTable[index].privilegeString, privilegeString.GetPointer()) == 0)
252                         {
253                                 validStringFlag = true;
254                                 privilegeEnum = static_cast< int >(privilegeListTable[index].privilege);
255
256                                 position = privilegeEnum / _BITS_IN_BYTE;
257                                 privilegeBit = (byte) (privilegeEnum % _BITS_IN_BYTE);
258                                 pResult[position] = pResult[position] | (1 << privilegeBit);
259                                 break;
260                         }
261                 }
262
263                 if (validStringFlag == false)
264                 {
265                         AppLogExceptionTag(OSP_INSTALLER, "[E_INVALID_ARG] Invalid privilege string: [%ls]", pTempString->GetPointer());
266                         resultFlag = false;
267                 }
268         }
269
270         TryCatchTag(OSP_INSTALLER, resultFlag == true, r = E_INVALID_ARG, "[E_INVALID_ARG] One of privilege string is invalid.");
271
272         pBitwisePrivilege = pResult;
273
274         delete pEnum;
275
276         return pBitwisePrivilege;
277
278 CATCH:
279
280         delete pEnum;
281         free(pResult);
282
283         SetLastResult(r);
284
285         return null;
286 }
287
288 result
289 PrivilegeHandler::PackPrivilegeN(const IList& privilegeList, int visibilityLevel, byte** ppBitwisePrivilege)
290 {
291         result r = E_SUCCESS;
292         int index = 0;
293         int privilegeEnum = 0;
294         int position = 0;
295         bool validStringFlag = false;
296         bool validLevelFlag = true;
297         bool resultFlag = true;
298         bool resultLevelFlag = true;
299         byte privilegeBit = 0;
300         byte* pResult = null;
301         IEnumerator* pEnum = null;
302
303         ClearLastResult();
304
305         pResult = (byte*) malloc(sizeof(byte) * MAX_BITWISE_PRIV_SIZE);
306         TryReturnResultTag(OSP_INSTALLER, pResult != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
307
308         memset(pResult, 0, MAX_BITWISE_PRIV_SIZE);
309
310         pEnum = privilegeList.GetEnumeratorN();
311         TryCatchTag(OSP_INSTALLER, pEnum != null, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
312
313         while (pEnum->MoveNext() == E_SUCCESS)
314         {
315                 validStringFlag = false;
316                 validLevelFlag = true;
317
318                 String privilegeURI = L"http://tizen.org/privilege/";
319
320                 String* pTempString = (String*) pEnum->GetCurrent();
321
322                 if ((pTempString->GetLength()) < (privilegeURI.GetLength()))
323                 {
324                         AppLogExceptionTag(OSP_INSTALLER, "[E_INVALID_ARG] Invalid privilege string (Length error): [%ls]", pTempString->GetPointer());
325                         resultFlag = false;
326                         continue;
327                 }
328
329                 String uriString;
330                 pTempString->SubString(0, privilegeURI.GetLength(), uriString);
331
332                 if (!(uriString.Equals(privilegeURI, true)))
333                 {
334                         AppLogExceptionTag(OSP_INSTALLER, "[E_INVALID_ARG] Invalid privilege string (URI error): [%ls]", pTempString->GetPointer());
335                         resultFlag = false;
336                         continue;
337                 }
338
339                 String privilegeString;
340                 pTempString->SubString(privilegeURI.GetLength(), pTempString->GetLength()-privilegeURI.GetLength(), privilegeString);
341
342                 for (index = 0; index < _MAX_PRIVILEGE_ENUM; index++)
343                 {
344                         if (wcscmp(privilegeListTable[index].privilegeString, privilegeString.GetPointer()) == 0)
345                         {
346                                 validStringFlag = true;
347                                 privilegeEnum = static_cast< int >(privilegeListTable[index].privilege);
348
349                                 if (visibilityLevel != _API_VISIBILITY_NONE)
350                                 {
351                                         if (visibilityLevelListTable[privilegeEnum][_PRV_API_VER_2_0] > visibilityLevel)
352                                         {
353                                                 validLevelFlag = false;
354                                                 break;
355                                         }
356                                 }
357
358                                 position = privilegeEnum / _BITS_IN_BYTE;
359                                 privilegeBit = (byte) (privilegeEnum % _BITS_IN_BYTE);
360                                 pResult[position] = pResult[position] | (1 << privilegeBit);
361                                 break;
362                         }
363                 }
364
365                 if (validStringFlag == false)
366                 {
367                         AppLogExceptionTag(OSP_INSTALLER, "[E_INVALID_ARG] Invalid privilege string: [%ls]", pTempString->GetPointer());
368                         resultFlag = false;
369                 }
370
371                 if (validLevelFlag == false)
372                 {
373                         AppLogExceptionTag(OSP_INSTALLER, "[E_ILLEGAL_ACCESS] The application does not have the privilege level to register [%ls]", pTempString->GetPointer());
374                         resultLevelFlag = false;
375                 }
376         }
377
378         TryCatchTag(OSP_INSTALLER, resultLevelFlag == true, r = E_ILLEGAL_ACCESS, "[E_ILLEGAL_ACCESS] Unauthorized privileges are detected.");
379         TryCatchTag(OSP_INSTALLER, resultFlag == true, r = E_INVALID_ARG, "[E_INVALID_ARG] Unsupported privilege strings are detected.");
380
381         *ppBitwisePrivilege = pResult;
382
383         delete pEnum;
384
385         return r;
386
387 CATCH:
388
389         delete pEnum;
390         free(pResult);
391
392         return r;
393 }
394
395
396 result
397 PrivilegeHandler::GetEncryptedBitwise(byte* pBitwisePrivilege, String& encryptedPrivileges)
398 {
399         result r = E_SUCCESS;
400         ByteBuffer* pTempBitwisePrivilege = null;
401
402         pTempBitwisePrivilege = new (std::nothrow) ByteBuffer();
403         TryReturnResultTag(OSP_INSTALLER, pTempBitwisePrivilege != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation is failed.");
404
405         r = pTempBitwisePrivilege->Construct(MAX_BITWISE_PRIV_SIZE);
406         TryCatchTag(OSP_INSTALLER, r == E_SUCCESS, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
407
408         r = pTempBitwisePrivilege->SetArray(pBitwisePrivilege, 0, MAX_BITWISE_PRIV_SIZE);
409         TryCatchTag(OSP_INSTALLER, r == E_SUCCESS, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
410         pTempBitwisePrivilege->Flip();
411
412         r = StringUtil::EncodeToBase64String(*pTempBitwisePrivilege, encryptedPrivileges);
413         TryCatchTag(OSP_INSTALLER, r == E_SUCCESS, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
414
415         // fall through
416
417 CATCH:
418
419         delete pTempBitwisePrivilege;
420
421         return r;
422 }
423
424 result
425 PrivilegeHandler::GetChecksum(AppId appId, byte* pBitwisePrivilege, String& checksum)
426 {
427         result r = E_SUCCESS;
428         byte tempChecksumString[MAX_BITWISE_PRIV_SIZE + MAX_APP_ID_SIZE];
429
430         ByteBuffer input;
431         IHash* pHash = null;
432         ByteBuffer* pChecksumByteBuffer = null;
433
434         std::unique_ptr<char[]> pAppId(null);
435         pAppId.reset(_StringConverter::CopyToCharArrayN(appId));
436         TryCatchTag(OSP_INSTALLER, pAppId != null, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
437
438         memcpy(tempChecksumString, pAppId.get(), MAX_APP_ID_SIZE);
439         memcpy(tempChecksumString + MAX_APP_ID_SIZE, pBitwisePrivilege, MAX_BITWISE_PRIV_SIZE);
440
441         r = input.Construct(MAX_APP_ID_SIZE + MAX_BITWISE_PRIV_SIZE);
442         TryCatchTag(OSP_INSTALLER, r == E_SUCCESS, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
443
444         r = input.SetArray(tempChecksumString, 0, MAX_APP_ID_SIZE + MAX_BITWISE_PRIV_SIZE);
445         TryCatchTag(OSP_INSTALLER, r == E_SUCCESS, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
446         input.Flip();
447
448         pHash = new (std::nothrow) Sha1Hash();
449         TryCatchTag(OSP_INSTALLER, pHash != null, r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation is failed.");
450
451         pChecksumByteBuffer = pHash->GetHashN(input);
452         TryCatchTag(OSP_INSTALLER, pChecksumByteBuffer != null, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
453
454         r = StringUtil::EncodeToBase64String(*pChecksumByteBuffer, checksum);
455         TryCatchTag(OSP_INSTALLER, r == E_SUCCESS, r = E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
456
457         // fall through
458
459 CATCH:
460
461         delete pHash;
462         delete pChecksumByteBuffer;
463
464         return r;
465 }