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