Add test for libprivilege-control / perm_add_additional_rules.
[platform/core/test/security-tests.git] / tests / libprivilege-control-tests / libprivilege-control_test_common.cpp
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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  * @file    libprivilege-control-test.cpp
18  * @author  Jan Olszak (j.olszak@samsung.com)
19  * @author  Lukasz Wojciechowski (l.wojciechow@partner.samsung.com)
20  * @version 1.0
21  * @brief   Main file for libprivilege-control unit tests.
22  */
23
24 #include <fcntl.h>
25 #include <fstream>
26 #include <set>
27 #include <string>
28 #include <string.h>
29 #include <sys/sendfile.h>
30 #include <sys/smack.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <vector>
34
35 #include <libprivilege-control_test_common.h>
36 #include <tests_common.h>
37 #include "common/duplicates.h"
38
39 #define CANARY_LABEL             "tiny_yellow_canary"
40
41 const char *PRIVS[] = { "WRT", "test_privilege_control_rules", NULL };
42 const char *PRIVS2[] = { "test_privilege_control_rules2", NULL };
43 const char *PRIVS2_NO_R[] = { "test_privilege_control_rules2_no_r", NULL };
44 const char *PRIVS2_R[] = { "test_privilege_control_rules2_r", NULL };
45 const char *PRIVS2_R_AND_NO_R[] = { "test_privilege_control_rules2_r", "test_privilege_control_rules2_no_r", NULL };
46
47 const char *PRIVS_WGT[] = { "test_privilege_control_rules_wgt", NULL };
48 const char *PRIVS_OSP[] = { "test_privilege_control_rules_osp", NULL };
49 const char *PRIVS_EFL[] = { "test_privilege_control_rules_efl", NULL };
50
51 const char* PRIV_APPSETTING[] {"org.tizen.privilege.appsetting", NULL};
52
53 const char* PRIVS_AV[] = { "org.tizen.privilege.antivirus", NULL };
54
55 bool DBBackup::backupfile(const std::string& src, const std::string& dst)
56 {
57     int fdsrc = TEMP_FAILURE_RETRY(open(src.c_str(), O_RDONLY));
58     if (fdsrc == -1)
59         return false;
60     FDUniquePtr FdPtrSrc(&fdsrc, closeFdPtr);
61
62     struct stat stat_source;
63     if (fstat(fdsrc, &stat_source) == -1)
64         return false;
65
66     int fddst = TEMP_FAILURE_RETRY(open(dst.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644));
67     if (fddst == -1)
68         return false;
69     FDUniquePtr FdPtrDst(&fddst, closeFdPtr);
70
71     if (sendfile(fddst, fdsrc, 0, stat_source.st_size) == -1)
72         return false;
73
74     return true;
75 }
76
77 bool DBBackup::restorefile(const std::string& src, const std::string& dst)
78 {
79     if (rename(src.c_str(), dst.c_str()) == -1)
80         return false;
81
82     return true;
83 }
84
85 DBBackup::DBBackup()
86 {
87     RUNNER_ASSERT_MSG_BT(backupfile(RDB_PATH, RDB_PATH_BACKUP),
88                          "libprivilege DB backup failed. Errno: " << strerror(errno));
89 }
90
91 DBBackup::~DBBackup()
92 {
93     if (!restorefile(RDB_PATH_BACKUP, RDB_PATH)) {
94
95         std::string fatal_error =
96             "\n\n"
97             "!!!                                                                !!!\n"
98             "!!!        FATAL ERROR - libprivilege DB restoring failed.         !!!\n"
99             "!!!        libprivilege-control tests are not valid.               !!!\n"
100             "!!!        Reinstall libprivilege-control package.                 !!!\n"
101             "!!!                                                                !!!\n";
102
103         if (std::uncaught_exception()) // don't throw!
104             std::cerr << fatal_error << std::flush;
105         else
106             RUNNER_ASSERT_MSG_BT(false, fatal_error);
107     }
108 }
109
110 /**
111  * Check if every rule is true.
112  * @return 1 if ALL rules in SMACK, 0 if ANY rule isn't, -1 on failure
113  */
114 int test_have_all_accesses(const rules_t &rules)
115 {
116     int result = 1;
117     for (uint i = 0; i < rules.size(); ++i) {
118         int access = smack_have_access(rules[i][0].c_str(),rules[i][1].c_str(),rules[i][2].c_str());
119         if (access < 0)
120             return -1;
121         if (access == 0)
122             result = 0;
123     }
124     return result;
125 }
126
127 /**
128  * Check if every rule is true.
129  * @return 1 if ANY rule in SMACK, 0 if NO rule in SMACK, -1 on failure
130  */
131 int test_have_any_accesses(const rules_t &rules)
132 {
133     int result = 0;
134     for (uint i = 0; i < rules.size(); ++i) {
135         int access = smack_have_access(rules[i][0].c_str(),rules[i][1].c_str(),rules[i][2].c_str());
136         if (access < 0)
137             return -1;
138         if (access > 0)
139             result = 1;
140     }
141     return result;
142 }
143
144 /**
145  * NOSMACK version of test_have_accesses functions.
146  *
147  * This will be used in many tests. Checks if for every rule smack_have_access returns error.
148  * If for any of rules smack_have_access will return something different than error, this result
149  * is being returned to caller.
150  */
151 int test_have_nosmack_accesses(const rules_t &rules)
152 {
153     int result;
154     for (uint i = 0; i < rules.size(); ++i) {
155         result = smack_have_access(rules[i][0].c_str(),rules[i][1].c_str(),rules[i][2].c_str());
156         if (result != -1)
157             return result;
158     }
159     return -1;
160 }
161
162 bool check_all_accesses(bool smack, const rules_t &rules)
163 {
164     if (smack)
165         return test_have_all_accesses(rules) == 1;
166     else
167         return test_have_nosmack_accesses(rules) == -1;
168 }
169
170 bool check_no_accesses(bool smack, const rules_t &rules)
171 {
172     if (smack)
173         return test_have_any_accesses(rules) == 0;
174     else
175         return test_have_nosmack_accesses(rules) == -1;
176 }
177
178 void read_gids(std::set<unsigned> &set, const char *file_path)
179 {
180     FILE *f = fopen(file_path, "r");
181     RUNNER_ASSERT_MSG_BT(f != NULL, "Unable to open file " << file_path);
182     unsigned gid;
183     while (fscanf(f, "%u\n", &gid) == 1) {
184         set.insert(gid);
185     }
186     fclose(f);
187 }
188
189 void check_groups(const char *dac_file)
190 {
191     std::set<unsigned> groups_check;
192     read_gids(groups_check, LIBPRIVILEGE_APP_GROUP_LIST);
193     read_gids(groups_check, dac_file);
194
195     int groups_cnt = getgroups(0, NULL);
196     RUNNER_ASSERT_MSG_BT(groups_cnt > 0, "Wrong number of supplementary groupsCnt");
197     gid_t *groups_list = (gid_t*) calloc(groups_cnt, sizeof(gid_t));
198     RUNNER_ASSERT_MSG_BT(groups_list != NULL, "Memory allocation failed");
199     RUNNER_ASSERT_BT(-1 != getgroups(groups_cnt, groups_list));
200
201     for (int i = 0; i < groups_cnt; ++i) {
202         //getgroups() can return multiple number of the same group
203         //they are returned in sequence, so we will given number when last
204         //element of this number is reached
205         if ((i < groups_cnt - 1) && (groups_list[i + 1] == groups_list[i]))
206             continue;
207         if (groups_check.erase(groups_list[i]) == 0) {
208             // getgroups() may also return process' main group
209             if (groups_list[i] != getgid())
210                 RUNNER_ASSERT_MSG_BT(false, "Application belongs to unknown group (GID=" << groups_list[i] << ")");
211         }
212     }
213     free(groups_list);
214     std::string groups_left;
215     for (std::set<unsigned>::iterator it = groups_check.begin(); it != groups_check.end(); it++) {
216         groups_left.append(std::to_string(*it)).append(" ");
217     }
218     RUNNER_ASSERT_MSG_BT(groups_check.empty(), "Application doesn't belong to some required groups: " << groups_left);
219 }
220
221 int file_exists(const char *path)
222 {
223     FILE *file = fopen(path, "r");
224     if (file) {
225         fclose(file);
226         return 0;
227     }
228     return -1;
229 }
230
231 void check_app_installed(int line_no, const char *app_path)
232 {
233     RUNNER_ASSERT_MSG_BT(file_exists(app_path) == 0, "Line: " << line_no <<
234             " App not installed: " << app_path);
235 }
236
237 int nftw_remove_labels(const char *fpath, const struct stat* /*sb*/,
238                        int /*typeflag*/, struct FTW* /*ftwbuf*/)
239 {
240     smack_lsetlabel(fpath, NULL, SMACK_LABEL_ACCESS);
241     smack_lsetlabel(fpath, NULL, SMACK_LABEL_EXEC);
242     smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
243
244     return 0;
245 }
246
247 int nftw_check_labels_app_dir(const char *fpath, const struct stat *sb,
248                                int /*typeflag*/, struct FTW* /*ftwbuf*/)
249 {
250     int result;
251     CStringPtr labelPtr;
252     char* label = NULL;
253
254     /* ACCESS */
255     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
256     labelPtr.reset(label);
257     RUNNER_ASSERT_MSG_BT(result == 0, "Could not get label for the path");
258     RUNNER_ASSERT_MSG_BT(labelPtr.get() != NULL, "ACCESS label on " << fpath << " is not set");
259     result = strcmp(APPID_DIR, labelPtr.get());
260     RUNNER_ASSERT_MSG_BT(result == 0, "ACCESS label on " << fpath << " is incorrect");
261
262     /* EXEC */
263     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
264     labelPtr.reset(label);
265     RUNNER_ASSERT_MSG_BT(result == 0, "Could not get label for the path");
266     if (S_ISREG(sb->st_mode) && (sb->st_mode & S_IXUSR)) {
267         RUNNER_ASSERT_MSG_BT(labelPtr.get() != NULL, "EXEC label on " << fpath << " is not set");
268         result = strcmp(APPID_DIR, labelPtr.get());
269         RUNNER_ASSERT_MSG_BT(result == 0, "EXEC label on executable file " << fpath << " is incorrect");
270     } else if (S_ISLNK(sb->st_mode)) {
271         struct stat buf;
272         char *target = realpath(fpath, NULL);
273         RUNNER_ASSERT_MSG_BT(0 == stat(target, &buf),"Stat failed for " << fpath);
274         free(target);
275         if (buf.st_mode != (buf.st_mode | S_IXUSR | S_IFREG)) {
276             RUNNER_ASSERT_MSG_BT(labelPtr.get() == NULL, "EXEC label on " << fpath << " is set");
277         } else {
278             RUNNER_ASSERT_MSG_BT(labelPtr.get() != NULL, "EXEC label on " << fpath << " is not set");
279             result = strcmp(APPID_DIR, labelPtr.get());
280             RUNNER_ASSERT_MSG_BT(result == 0, "EXEC label on link to executable file " << fpath << " is incorrect");
281         }
282     } else
283         RUNNER_ASSERT_MSG_BT(labelPtr.get() == NULL, "EXEC label on " << fpath << " is set");
284
285     /* TRANSMUTE */
286     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
287     labelPtr.reset(label);
288     RUNNER_ASSERT_MSG_BT(result == 0, "Could not get label for the path");
289     RUNNER_ASSERT_MSG_BT(labelPtr.get() == NULL, "TRANSMUTE label on " << fpath << " is set");
290
291     return 0;
292  }
293
294 int nftw_set_labels_non_app_dir(const char *fpath, const struct stat* /*sb*/,
295                                 int /*typeflag*/, struct FTW* /*ftwbuf*/)
296 {
297     smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_ACCESS);
298     smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_EXEC);
299     smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
300
301     return 0;
302 }
303
304 int nftw_check_labels_non_app_dir(const char *fpath, const struct stat* /*sb*/,
305                                   int /*typeflag*/, struct FTW* /*ftwbuf*/)
306 {
307     int result;
308     CStringPtr labelPtr;
309     char* label = NULL;
310
311     /* ACCESS */
312     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
313     labelPtr.reset(label);
314     RUNNER_ASSERT_MSG_BT(result == 0, "Could not get label for the path");
315     result = strcmp(CANARY_LABEL, labelPtr.get());
316     RUNNER_ASSERT_MSG_BT(result == 0, "ACCESS label on " << fpath << " is overwritten");
317
318     /* EXEC */
319     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
320     labelPtr.reset(label);
321     RUNNER_ASSERT_MSG_BT(result == 0, "Could not get label for the path");
322     result = strcmp(CANARY_LABEL, labelPtr.get());
323     RUNNER_ASSERT_MSG_BT(result == 0, "EXEC label on " << fpath << " is overwritten");
324
325     /* TRANSMUTE */
326     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
327     labelPtr.reset(label);
328     RUNNER_ASSERT_MSG_BT(result == 0, "Could not get label for the path");
329     RUNNER_ASSERT_MSG_BT(labelPtr.get() == NULL, "TRANSMUTE label on " << fpath << " is set");
330
331     return 0;
332 }
333
334 void check_app_has_permission(const char* app_id, const app_type_t app_type,
335                               const char *perm_list[], const int expected_result)
336 {
337     int result = PC_OPERATION_SUCCESS;
338     bool has_permission = false;
339
340     for (int i = 0; perm_list[i] != NULL; i++) {
341         result = perm_app_has_permission(app_id, app_type, perm_list[i], &has_permission);
342         RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
343                           "perm_app_has_permission failed with result: " << result);
344         RUNNER_ASSERT_MSG_BT(has_permission == expected_result,
345                           "Unexpected result, perm_app_has_permission returned: " << has_permission
346                           << ", expected: " << expected_result);
347     }
348 }
349 void checkOnlyAvAccess(const char *av_id, const char *app_id, const char *comment)
350 {
351     int result;
352     result = smack_have_access(av_id, app_id, "rwx");
353     RUNNER_ASSERT_MSG_BT(result == 1,
354         "Error while checking " << av_id << " rwx access to "
355         << app_id << " " << comment << " Result: " << result);
356     result = smack_have_access(av_id, app_id, "a");
357     RUNNER_ASSERT_MSG_BT(result == 0,
358         "Error while checking " << av_id << " a access to "
359         << app_id << " " << comment << " Result: " << result);
360     result = smack_have_access(av_id, app_id, "t");
361     RUNNER_ASSERT_MSG_BT(result == 0,
362         "Error while checking " << av_id << " t access to "
363         << app_id << " " << comment << " Result: " << result);
364 }
365
366 /**
367  * NOSMACK version of checkOnlyAvAccess function.
368  *
369  * Expects error instead of access granted/forbidden from smack_have_access.
370  */
371 void checkOnlyAvAccessNosmack(const char *av_id, const char *app_id, const char *comment)
372 {
373     int result;
374     result = smack_have_access(av_id, app_id, "rwx");
375     RUNNER_ASSERT_MSG_BT(result == -1,
376             "smack_have_access should return error (SMACK is off). Result: " << result
377             << " when testing " << comment);
378     result = smack_have_access(av_id, app_id, "a");
379     RUNNER_ASSERT_MSG_BT(result == -1,
380             "smack_have_access should return error (SMACK is off). Result: " << result
381             << " when testing " << comment);
382     result = smack_have_access(av_id, app_id, "t");
383     RUNNER_ASSERT_MSG_BT(result == -1,
384             "smack_have_access should return error (SMACK is off). Result: " << result
385             << " when testing " << comment);
386 }
387
388 void test_revoke_permissions(int line_no, const char* app_id, const rules_t &rules, bool smack)
389 {
390     int result;
391
392     // Cleanup
393     DB_BEGIN
394
395     result = perm_app_uninstall(app_id);
396     RUNNER_ASSERT_MSG_BT(result == 0, "Line: " << line_no <<
397             "perm_app_uninstall returned " << result);
398
399     // Close transaction to commit uninstallation before further actions
400     DB_END
401
402     DB_BEGIN
403
404     // Install test apps
405     result = perm_app_install(app_id);
406     RUNNER_ASSERT_MSG_BT(result == 0, "Line: " << line_no <<
407             "perm_app_install returned " << result);
408
409     // Close transaction to commit installation before further actions
410     DB_END
411
412     DB_BEGIN
413
414     // TEST:
415     // Revoke permissions
416     result = perm_app_revoke_permissions(app_id);
417     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS, "Line: " << line_no <<
418         "Error revoking app permissions. Result: " << result);
419
420     DB_END
421
422     // Are all the permissions revoked?
423     RUNNER_ASSERT_MSG_BT(check_no_accesses(smack, rules), "Line: " << line_no <<
424             "Not all permisions revoked.");
425
426     DB_BEGIN
427
428     // Cleanup - uninstall test apps
429     result = perm_app_uninstall(app_id);
430     RUNNER_ASSERT_MSG_BT(result == 0, "Line: " << line_no <<
431             "perm_app_uninstall returned " << result);
432
433     DB_END
434 }
435
436 void test_app_enable_permissions_efl(bool smack)
437 {
438     int result;
439
440     DB_BEGIN
441
442     // Prepare
443     result = perm_app_uninstall(EFL_APP_ID);
444     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
445             "perm_app_uninstall failed: " << result);
446     result = perm_app_install(EFL_APP_ID);
447     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
448             "perm_app_install failed: " << result);
449
450     // Register a permission:
451     result = perm_app_setup_permissions(EFL_APP_ID, APP_TYPE_EFL, PRIVS_EFL);
452     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
453         "Error registering app permissions. Result: " << result);
454
455     DB_END
456
457     RUNNER_ASSERT_MSG_BT(check_all_accesses(smack, {{EFL_APP_ID,"test_book_efl", "r"}}),
458             "SMACK accesses not granted for EFL_APP");
459
460     // Check if permission is assigned to app in db
461     check_app_has_permission(EFL_APP_ID, APP_TYPE_EFL, PRIVS_EFL, true);
462
463     DB_BEGIN
464
465     // Cleanup
466     result = perm_app_uninstall(EFL_APP_ID);
467     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
468             "perm_app_uninstall failed: " << result);
469
470     DB_END
471
472     // Check if permission is disabled in db
473     check_app_has_permission(EFL_APP_ID, APP_TYPE_EFL, PRIVS_EFL, false);
474 }
475
476 void test_app_disable_permissions_efl(bool smack)
477 {
478     int result;
479
480     DB_BEGIN
481
482     // Prepare
483     result = perm_app_uninstall(EFL_APP_ID);
484     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
485             "perm_app_uninstall failed: " << result);
486
487     result = perm_app_install(EFL_APP_ID);
488     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
489             "perm_app_install failed: " << result);
490
491     // Register a permission
492     result = perm_app_setup_permissions(EFL_APP_ID, APP_TYPE_EFL, PRIVS_EFL);
493     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
494         "Error registering app permissions. Result: " << result);
495
496     DB_END
497
498     RUNNER_ASSERT_MSG_BT(check_all_accesses(smack, {{EFL_APP_ID,"test_book_efl", "r"}}),
499             "SMACK accesses not granted for EFL_APP");
500
501     // Check if permission is assigned to app in db
502     check_app_has_permission(EFL_APP_ID, APP_TYPE_EFL, PRIVS_EFL, true);
503
504     DB_BEGIN
505
506     // Disable a permission
507     result = perm_app_disable_permissions(EFL_APP_ID, APP_TYPE_EFL, PRIVS_EFL);
508     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
509         "Error disabling app permissions. Result: " << result);
510
511     DB_END
512
513     RUNNER_ASSERT_MSG_BT(check_no_accesses(smack, {{EFL_APP_ID,"test_book_efl", "r"}}),
514             "SMACK accesses not disabled for EFL_APP");
515
516     // Check if permission is disabled in db
517     check_app_has_permission(EFL_APP_ID, APP_TYPE_EFL, PRIVS_EFL, false);
518
519     DB_BEGIN
520
521     // Cleanup
522     result = perm_app_uninstall(EFL_APP_ID);
523     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
524             "perm_app_uninstall failed: " << result);
525
526     DB_END
527 }
528
529 void test_app_disable_permissions(bool smack)
530 {
531     int result;
532
533     DB_BEGIN
534
535     // Prepare
536     result = perm_app_uninstall(WGT_APP_ID);
537     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
538             "perm_app_uninstall failed: " << result);
539
540     result = perm_app_install(WGT_APP_ID);
541     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
542             "perm_app_install failed: " << result);
543 /**
544  * Test - disable all granted permissions.
545  */
546
547     // Prepare permissions that we want to disable
548     result = perm_app_setup_permissions(WGT_APP_ID, APP_TYPE_WGT, PRIVS2);
549     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
550             " Error registering app permissions. Result: " << result);
551
552     DB_END
553
554     // Are all the permissions enabled?
555     RUNNER_ASSERT_MSG_BT(check_all_accesses(smack, rules2), "Not all permisions enabled.");
556
557     // Check if permissions are enabled in db
558     check_app_has_permission(WGT_APP_ID, APP_TYPE_WGT, PRIVS2, true);
559
560     DB_BEGIN
561
562     // Disable permissions
563     result = perm_app_disable_permissions(WGT_APP_ID, APP_TYPE_WGT, PRIVS2);
564     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
565             "Error disabling app permissions. Result: " << result);
566
567     DB_END
568
569     // Are all the permissions disabled?
570     RUNNER_ASSERT_MSG_BT(check_no_accesses(smack, rules2), "Not all permisions disabled.");
571
572     // Check if permission is disabled in db
573     check_app_has_permission(WGT_APP_ID, APP_TYPE_WGT, PRIVS2, false);
574
575 /**
576  * Test - disable some granted permissions leaving non complementary and then disabling those too.
577  */
578
579     DB_BEGIN
580
581     // Prepare permissions that will not be disabled
582     result = perm_app_setup_permissions(WGT_APP_ID, APP_TYPE_WGT, PRIVS);
583     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
584             " Error adding app first permissions. Result: " << result);
585
586     // Prepare permissions that we want to disable
587     result = perm_app_setup_permissions(WGT_APP_ID, APP_TYPE_WGT, PRIVS2);
588     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
589             " Error adding app second permissions. Result: " << result);
590
591     // Disable second permissions
592     result = perm_app_disable_permissions(WGT_APP_ID, APP_TYPE_WGT, PRIVS2);
593     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
594             "Error disabling app second permissions. Result: " << result);
595
596     DB_END
597
598     // Are all second permissions disabled?
599     RUNNER_ASSERT_MSG_BT(check_no_accesses(smack, rules2), "Not all first permisions disabled.");
600
601     // Are all first permissions not disabled?
602     RUNNER_ASSERT_MSG_BT(check_all_accesses(smack, rules_wgt2), "Some of second permissions disabled.");
603
604     // Check if second permission is disabled in db
605     check_app_has_permission(WGT_APP_ID, APP_TYPE_WGT, PRIVS2, false);
606     // Check if first permission is enabled in db
607     check_app_has_permission(WGT_APP_ID, APP_TYPE_WGT, PRIVS, true);
608
609     DB_BEGIN
610
611     // Disable first permissions
612     result = perm_app_disable_permissions(WGT_APP_ID, APP_TYPE_WGT, PRIVS);
613     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
614             "Error disabling app first permissions. Result: " << result);
615
616     DB_END
617
618     // Are all second permissions disabled?
619     RUNNER_ASSERT_MSG_BT(check_no_accesses(smack, rules_wgt2), "Not all second permisions disabled.");
620
621     // Check if permission is disabled in db
622     check_app_has_permission(WGT_APP_ID, APP_TYPE_WGT, PRIVS, false);
623
624 /**
625  * Test - disable only no r granted permissions.
626  */
627
628     DB_BEGIN
629
630     // Prepare permissions
631     result = perm_app_setup_permissions(WGT_APP_ID, APP_TYPE_WGT, PRIVS2_R);
632     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
633             " Error registering app r permissions. Result: " << result);
634
635     result = perm_app_setup_permissions(WGT_APP_ID, APP_TYPE_WGT, PRIVS2_NO_R);
636     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
637             " Error registering app no r permissions. Result: " << result);
638
639     // Disable same permissions without r
640     result = perm_app_disable_permissions(WGT_APP_ID, APP_TYPE_WGT, PRIVS2_NO_R);
641     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
642             "Error disabling app no r permissions. Result: " << result);
643
644     DB_END
645
646     // Is any r permissions disabled?
647     RUNNER_ASSERT_MSG_BT(check_all_accesses(smack, rules2_r), "Some of r permissions disabled.");
648     // Are all no r permissions disabled?
649     RUNNER_ASSERT_MSG_BT(check_no_accesses(smack, rules2_no_r), "Not all no r permissions disabled.");
650
651     // Check if second permission is enabled in db
652     check_app_has_permission(WGT_APP_ID, APP_TYPE_WGT, PRIVS2_R, true);
653     // Check if permission is disabled in db
654     check_app_has_permission(WGT_APP_ID, APP_TYPE_WGT, PRIVS2_NO_R, false);
655
656     DB_BEGIN
657
658     // Prepare permissions
659     result = perm_app_enable_permissions(WGT_APP_ID, APP_TYPE_WGT, PRIVS2_NO_R, 1);
660     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
661             " Error adding app no r permissions. Result: " << result);
662
663     DB_END
664
665     RUNNER_ASSERT_MSG_BT(check_all_accesses(smack, rules2_no_r), "Not all no r permissions enabled.");
666
667     DB_BEGIN
668
669     // Disable all permissions
670     result = perm_app_disable_permissions(WGT_APP_ID, APP_TYPE_WGT, PRIVS2_R);
671     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS,
672             "Error disabling app permissions. Result: " << result);
673
674     DB_END
675
676     RUNNER_ASSERT_MSG_BT(check_no_accesses(smack, rules2_r), "Not all r permissions disabled.");
677
678     // Check if permission is disabled in db
679     check_app_has_permission(WGT_APP_ID, APP_TYPE_WGT, PRIVS2_R, false);
680
681     DB_BEGIN
682
683     // Clean up after test:
684     result = perm_app_uninstall(WGT_APP_ID);
685     RUNNER_ASSERT_MSG_BT(result == PC_OPERATION_SUCCESS, "perm_app_uninstall returned " << result << ". Errno: " << strerror(errno));
686
687     DB_END
688 }
689
690 void test_appsettings_privilege(bool smack)
691 {
692     int ret;
693     CStringPtr app1DirLabelPtr;
694     CStringPtr app2DirLabelPtr;
695     char* label = NULL;
696
697     DB_BEGIN
698
699     (void)perm_app_uninstall(APP_TEST);
700     (void)perm_app_uninstall(APP_1);
701     (void)perm_app_uninstall(APP_2);
702
703     //install some app 1
704     ret = perm_app_install(APP_1);
705     RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS, "Error in perm_app_install." << ret);
706
707     mkdir(APP_1_DIR, S_IRWXU | S_IRGRP | S_IXGRP);
708
709     //register settings folder for app 1
710     ret = perm_app_setup_path(APP_1, APP_1_DIR, APP_PATH_SETTINGS_RW );
711     RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS, "Error in perm_app_setup_path: " << ret);
712
713     //install "app_test" and give it appsettings privilege
714     ret = perm_app_install(APP_TEST);
715     RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS, "Error in perm_app_install.");
716
717
718     ret = perm_app_setup_permissions(APP_TEST, APP_TYPE_OSP, PRIV_APPSETTING);
719     RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS,
720         " Error registering app permissions. Result: " << ret);
721
722     DB_END
723
724     //check if "app_test" has an RX access to the app "app_1"
725     RUNNER_ASSERT_MSG_BT(check_all_accesses(smack, {{APP_TEST, APP_1, "rx"}}), "access denied");
726
727     //check if "app_test" has an RWX access to a folder registered by "app_1"
728     ret = smack_getlabel(APP_1_DIR, &label, SMACK_LABEL_ACCESS );
729     app1DirLabelPtr.reset(label);
730     RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS,"smack_getlabel failed");
731     RUNNER_ASSERT_MSG_BT(check_all_accesses(smack, {{APP_TEST, app1DirLabelPtr.get(), "rwx"}}), "access denied to smack label: " << app1DirLabelPtr.get());
732
733
734     DB_BEGIN
735
736     //intstall another app: "app_2"
737     ret = perm_app_install(APP_2);
738     RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS, "Error in perm_app_install.");
739
740     mkdir(APP_2_DIR, S_IRWXU | S_IRGRP | S_IXGRP);
741     //register settings folder for that "app_2"
742     ret = perm_app_setup_path(APP_2, APP_2_DIR, APP_PATH_SETTINGS_RW );
743     RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS, "Error in perm_app_setup_path: " << ret);
744
745     DB_END
746
747     //check if "app_test" has an RX access to the app "app_2"
748     RUNNER_ASSERT_MSG_BT(check_all_accesses(smack, {{APP_TEST, APP_2, "rx"}}), "access denied");
749
750     //check if "app_test" has an RWX access to a folder registered by "app_2"
751     ret = smack_getlabel(APP_2_DIR, &label, SMACK_LABEL_ACCESS );
752     app2DirLabelPtr.reset(label);
753     RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS,"smack_getlabel failed");
754     RUNNER_ASSERT_MSG_BT(check_all_accesses(smack, {{APP_TEST, app2DirLabelPtr.get(), "rwx"}}), "access denies");
755
756     rmdir(APP_1_DIR);
757     rmdir(APP_2_DIR);
758
759     DB_BEGIN
760
761     (void)perm_app_uninstall(APP_TEST);
762     (void)perm_app_uninstall(APP_1);
763     (void)perm_app_uninstall(APP_2);
764
765     DB_END
766 }
767
768 // This function takes libprivilege additional smack_rules in same format as libprivilege,
769 // parses them in same way as libprivilege.
770 // If functions succeeds in parsing it returns true and fills rules parameter with parsed rules.
771 // If smack_rules cannot be parsed false is returned.
772 bool additional_rules_parse(const char** smack_rules, additional_rules& rules)
773 {
774     const size_t ACC_LEN = 6;
775     rules.clear();
776     for (int i = 0; smack_rules[i] != NULL ; ++i)
777     {
778         std::string line(smack_rules[i]);
779         additional_rule rule;
780
781         // Ignore empty lines
782         if (line.find_first_not_of(" \t\n") == std::string::npos)
783             continue;
784
785         // Split
786         std::stringstream(line) >> rule.subject >> rule.object >> rule.access;
787         // If last element is empty - split failed
788         if (rule.access.empty() || rule.object.length() > SMACK_LABEL_LEN ||
789             rule.subject.length() > SMACK_LABEL_LEN || rule.access.length() > ACC_LEN)
790             return false;
791         rule.reverse = false;
792
793         // Rearrange
794         if (is_wildcard(rule.subject))
795         {
796             rule.subject.swap(rule.object);
797             rule.reverse = true;
798         }
799
800         // Check validity of subject
801         if (!smack_label_is_valid(rule.subject))
802             return false;
803
804         rules.push_back(rule);
805     }
806     return true;
807 }
808
809 void restore_original_additional_rules(void)
810 {
811     std::ifstream file("/usr/share/privilege-control/ADDITIONAL_RULES.smack");
812     std::string line;
813     std::vector<const char*> rules;
814
815     while(std::getline(file, line))
816         rules.push_back(strdupa(line.c_str()));
817     rules.push_back(NULL);
818
819     perm_add_additional_rules(rules.data());
820 }