2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file test_cases.cpp
19 * @author Jan Olszak (j.olszak@samsung.com)
20 * @author Rafal Krypa (r.krypa@samsung.com)
22 * @brief libprivilege-control test runer
33 #include <dpl/test/test_runner.h>
34 #include <dpl/test/test_runner_child.h>
35 #include <dpl/log/log.h>
36 #include <sys/types.h>
39 #include <sys/xattr.h>
40 #include <sys/smack.h>
41 #include <privilege-control.h>
45 #define SMACK_RULES_DIR "/etc/smack/accesses.d/"
46 #define SMACK_LOAD2 "/smack/load2"
47 #define TEST_APP_DIR "/etc/smack/test_privilege_control_DIR/app_dir"
48 #define TEST_NON_APP_DIR "/etc/smack/test_privilege_control_DIR/non_app_dir"
49 #define APPID_DIR "test_APP_ID_dir"
50 #define APPID_SHARED_DIR "test_APP_ID_shared_dir"
51 #define CANARY_LABEL "tiny_yellow_canary"
53 #define APP_ID "test_APP"
54 #define APP_SET_PRIV_PATH "/etc/smack/test_privilege_control_DIR/test_set_app_privilege/test_APP"
55 #define APP_SET_PRIV_PATH_REAL "/etc/smack/test_privilege_control_DIR/test_set_app_privilege/test_APP_REAL"
57 const char *PRIVS[] = { "WRT", "test_privilege_control_rules", NULL };
59 #define LIBPRIVILEGE_APP_GROUP_LIST "/usr/share/privilege-control/app_group_list"
60 #define LIBPRIVILEGE_TEST_DAC_FILE "/usr/share/privilege-control/test_privilege_control_rules.dac"
62 #define APP_TEST_APP_1 "test-application1"
63 #define APP_TEST_APP_2 "test-application_2"
64 #define APP_TEST_APP_3 "test-app-3"
65 #define APP_TEST_AV_1 "test-antivirus1"
66 #define APP_TEST_AV_2 "test-antivirus_2"
67 #define APP_TEST_AV_3 "test-av-3"
68 #define SMACK_APPS_LABELS_DATABASE "/opt/dbspace/.privilege_control_all_apps_id.db"
69 #define SMACK_AVS_LABELS_DATABASE "/opt/dbspace/.privilege_control_all_avs_id.db"
73 #define APP_USER_NAME "app"
74 #define APP_HOME_DIR "/opt/home/app"
76 // How many open file descriptors should ftw() function use?
77 #define FTW_MAX_FDS 16
79 // Rules from test_privilege_control_rules.smack
80 const std::vector< std::vector<std::string> > rules = {
81 { APP_ID, "test_book_1", "r" },
82 { APP_ID, "test_book_2", "w" },
83 { APP_ID, "test_book_3", "x" },
84 { APP_ID, "test_book_4", "rw" },
85 { APP_ID, "test_book_5", "rx" },
86 { APP_ID, "test_book_6", "wx" },
87 { APP_ID, "test_book_7", "rwx" },
88 { "test_subject_1", APP_ID, "r" },
89 { "test_subject_2", APP_ID, "w" },
90 { "test_subject_3", APP_ID, "x" },
91 { "test_subject_4", APP_ID, "rw" },
92 { "test_subject_5", APP_ID, "rx" },
93 { "test_subject_6", APP_ID, "wx" },
94 { "test_subject_7", APP_ID, "rwx" },
95 { APP_ID, APPID_SHARED_DIR, "rwxat"}};
100 const char* OSP_BLAHBLAH = "/usr/share/privilege-control/OSP_blahblah.smack";
101 const char* WRT_BLAHBLAH = "/usr/share/privilege-control/WGT_blahblah.smack";
102 const char* OTHER_BLAHBLAH = "/usr/share/privilege-control/blahblah.smack";
103 const char* OSP_BLAHBLAH_DAC = "/usr/share/privilege-control/OSP_blahblah.dac";
104 const char* WRT_BLAHBLAH_DAC = "/usr/share/privilege-control/WGT_blahblah.dac";
105 const char* OTHER_BLAHBLAH_DAC = "/usr/share/privilege-control/blahblah.dac";
106 const char* BLAHBLAH_FEATURE = "http://feature/blah/blahblah";
109 * Check if every rule is true.
110 * @return 1 if ALL rules in SMACK, 0 if ANY rule isn't
112 int test_have_all_accesses(const std::vector< std::vector<std::string> >& rules){
114 for(uint i =0; i<rules.size();++i ){
115 result = smack_have_access(rules[i][0].c_str(),rules[i][1].c_str(),rules[i][2].c_str());
123 * Check if every rule is true.
124 * @return 1 if ANY rule in SMACK, 0 if
126 int test_have_any_accesses(const std::vector< std::vector<std::string> >& rules){
128 for(uint i =0; i<rules.size();++i ){
129 result = smack_have_access(rules[i][0].c_str(),rules[i][1].c_str(),rules[i][2].c_str());
136 RUNNER_TEST_GROUP_INIT(libprivilegecontrol)
138 int nftw_remove_labels(const char *fpath, const struct stat *sb,
139 int typeflag, struct FTW *ftwbuf)
141 smack_lsetlabel(fpath, NULL, SMACK_LABEL_ACCESS);
142 smack_lsetlabel(fpath, NULL, SMACK_LABEL_EXEC);
143 smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
148 int nftw_set_labels_non_app_dir(const char *fpath, const struct stat *sb,
149 int typeflag, struct FTW *ftwbuf)
151 smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_ACCESS);
152 smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_EXEC);
153 smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
158 int nftw_check_labels_non_app_dir(const char *fpath, const struct stat *sb,
159 int typeflag, struct FTW *ftwbuf)
165 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
166 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
167 result = strcmp(CANARY_LABEL, label);
168 RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is overwritten");
171 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
172 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
173 result = strcmp(CANARY_LABEL, label);
174 RUNNER_ASSERT_MSG(result == 0, "EXEC label on " << fpath << " is overwritten");
177 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
178 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
179 RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
184 int nftw_check_labels_app_dir(const char *fpath, const struct stat *sb,
185 int typeflag, struct FTW *ftwbuf)
191 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
192 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
193 RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
194 result = strcmp(APPID_DIR, label);
195 RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
198 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
199 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
200 if (S_ISREG(sb->st_mode) && (sb->st_mode & S_IXUSR)) {
201 RUNNER_ASSERT_MSG(label != NULL, "EXEC label on " << fpath << " is not set");
202 result = strcmp(APPID_DIR, label);
203 RUNNER_ASSERT_MSG(result == 0, "EXEC label on executable file " << fpath << " is incorrect");
205 RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
208 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
209 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
210 RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
215 int nftw_check_labels_app_shared_dir(const char *fpath, const struct stat *sb,
216 int typeflag, struct FTW *ftwbuf)
222 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
223 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
224 RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
225 result = strcmp(APPID_SHARED_DIR, label);
226 RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
229 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
230 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
231 RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
234 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
235 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
236 if (S_ISDIR(sb->st_mode)) {
237 RUNNER_ASSERT_MSG(label != NULL, "TRANSMUTE label on " << fpath << " is not set");
238 result = strcmp("TRUE", label);
239 RUNNER_ASSERT_MSG(result == 0, "TRANSMUTE label on " << fpath << " is not set");
241 RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
246 int file_exists(const char* path)
248 FILE* file = fopen(path, "r");
256 void osp_blahblah_check(int line_no, const std::vector<std::string>& rules)
258 std::ifstream smack_file(OSP_BLAHBLAH);
259 RUNNER_ASSERT_MSG(smack_file, "Line: " << line_no << " Failed to create " << OSP_BLAHBLAH);
261 auto it = rules.begin();
263 while(std::getline(smack_file,line)) {
264 RUNNER_ASSERT_MSG(it != rules.end(), "Line: " << line_no << "Additional line in file: " << line);
265 RUNNER_ASSERT_MSG(*it == line, "Line: " << line_no << " " << *it << "!=" << line);
269 RUNNER_ASSERT_MSG(it == rules.end(), "Line: " << line_no << " Missing line in file: " << *it);
274 void osp_blahblah_dac_check(int line_no, const std::vector<unsigned>& gids)
276 std::ifstream dac_file(OSP_BLAHBLAH_DAC);
277 RUNNER_ASSERT_MSG(dac_file, "Line: " << line_no << " Failed to create " << OSP_BLAHBLAH_DAC);
279 auto it = gids.begin();
281 while(std::getline(dac_file,line)) {
282 std::istringstream is(line);
285 RUNNER_ASSERT_MSG(it != gids.end(), "Line: " << line_no << "Additional line in file: " << gid);
286 RUNNER_ASSERT_MSG(*it == gid, "Line: " << line_no << " " << *it << "!=" << gid);
290 RUNNER_ASSERT_MSG(it == gids.end(), "Line: " << line_no << " Missing line in file: " << *it);
295 void remove_smack_files()
298 unlink(OSP_BLAHBLAH);
299 unlink(WRT_BLAHBLAH);
300 unlink(OTHER_BLAHBLAH);
301 unlink(OSP_BLAHBLAH_DAC);
302 unlink(WRT_BLAHBLAH_DAC);
303 unlink(OTHER_BLAHBLAH_DAC);
306 int smack_file_name(const char* app_id, char** path)
308 if (asprintf(path, SMACK_RULES_DIR "/%s", app_id) == -1) {
309 RUNNER_ASSERT_MSG(false, "asprint failed");
316 int cleaning_smack_app_files (void)
321 smack_file_name(APP_TEST_APP_1, &path);
325 smack_file_name(APP_TEST_APP_2, &path);
329 smack_file_name(APP_TEST_APP_3, &path);
333 smack_file_name(APP_TEST_AV_1, &path);
337 smack_file_name(APP_TEST_AV_2, &path);
341 smack_file_name(APP_TEST_AV_3, &path);
348 int cleaning_smack_database_files (void)
353 unlink(SMACK_APPS_LABELS_DATABASE);
354 fd = open(SMACK_APPS_LABELS_DATABASE, O_RDWR | O_EXCL | O_CREAT, 0644);
360 unlink(SMACK_AVS_LABELS_DATABASE);
361 fd = open(SMACK_AVS_LABELS_DATABASE, O_RDWR | O_EXCL | O_CREAT, 0644);
371 * Test setting labels for all files and folders in given path.
373 RUNNER_TEST(privilege_control02_app_label_dir)
377 result = app_label_shared_dir(APP_ID, APP_ID, TEST_APP_DIR);
378 RUNNER_ASSERT_MSG(result != 0, "app_label_shared_dir(APP_ADD, APP_ID) == " << result);
380 result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
381 RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
383 result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
384 RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
386 result = app_label_dir(APPID_DIR, TEST_APP_DIR);
387 RUNNER_ASSERT_MSG(result == 0, "app_label_dir() failed");
389 result = nftw(TEST_APP_DIR, &nftw_check_labels_app_dir, FTW_MAX_FDS, FTW_PHYS);
390 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for app dir");
392 result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
393 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
396 RUNNER_TEST(privilege_control03_app_label_shared_dir)
400 result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
401 RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
403 result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
404 RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
406 result = app_label_shared_dir(APP_ID, APPID_SHARED_DIR, TEST_APP_DIR);
407 RUNNER_ASSERT_MSG(result == 0, "app_label_shared_dir() failed");
409 result = nftw(TEST_APP_DIR, &nftw_check_labels_app_shared_dir, FTW_MAX_FDS, FTW_PHYS);
410 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for shared app dir");
412 result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
413 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
418 * Add permisions from test_privilege_control_rules template
420 RUNNER_TEST(privilege_control04_add_permissions)
422 int result = app_add_permissions(APP_ID, PRIVS);
423 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
424 " Error adding app permissions. Errno: " << result);
426 // Check if the accesses are realy applied..
427 result = test_have_all_accesses(rules);
428 RUNNER_ASSERT_MSG(result==1, "Permissions not added.");
431 FILE *pFile = fopen(SMACK_RULES_DIR APP_ID, "rb");
432 RUNNER_ASSERT_MSG(pFile != NULL,
433 "SMACK file NOT created!. Errno: " << errno);
436 fseek(pFile, 0L, SEEK_END);
437 int smack_file_length = ftell(pFile);
438 RUNNER_ASSERT_MSG(smack_file_length>0,
439 "SMACK file empty, but privileges list was not empty.. Errno: " << errno);
447 * Revoke permissions from the list. Should be executed as privileged user.
449 RUNNER_CHILD_TEST(privilege_control06_revoke_permissions)
455 // Revoke permissions
456 result = app_revoke_permissions(APP_ID);
457 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
458 "Error revoking app permissions. Errno: " << result);
460 // Are all the permissions revoked?
461 result = test_have_all_accesses(rules);
462 RUNNER_ASSERT_MSG(result!=1, "Not all permisions revoked.");
464 smack_file_name(APP_ID, &path);
465 fd = open(path, O_RDONLY);
466 RUNNER_ASSERT_MSG(fd >= 0, "SMACK file deleted after app_revoke_permissions");
467 RUNNER_ASSERT_MSG(lseek(fd, 0, SEEK_END) == 0, "SMACK file not empty after app_revoke_permissions");
472 static void read_gids(std::set<unsigned> &set, const char* file_path)
474 FILE *f = fopen(file_path, "r");
475 RUNNER_ASSERT_MSG(f != NULL, "Unable to open file " << file_path);
477 while (fscanf(f, "%u\n", &gid) == 1) {
482 RUNNER_TEST(privilege_control05_add_shared_dir_readers)
485 #define TEST_OBJ "TEST_OBJECT"
486 #define TEST_OBJ_SOME_OTHER "TEST_OBJA"
487 #define test_string_01 "TEST_raz TEST_OBJECT r-x-- -----"
488 #define test_string_21 "TEST_trzy TEST_OBJA -wx--\n"
489 #define test_string_22 "TEST_trzy TEST_OBJECT r-x-- -----\n"
496 const char *app_labels_wrong[] = {"-TEST_raz", NULL};
497 const char *app_labels[] = {"TEST_raz", "TEST_dwa", "TEST_trzy", NULL};
498 const int READ_BUF_SIZE = 1000;
499 char buf[READ_BUF_SIZE];
501 struct smack_accesses * rules = NULL;
503 //test what happens when the label is not correct SMACK label
504 result = smack_accesses_new(&rules);
505 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS, "Error in smack_accesses_new. Error: " << result);
507 result = add_shared_dir_readers(TEST_OBJ,app_labels_wrong);
508 RUNNER_ASSERT_MSG(result == PC_ERR_INVALID_PARAM, "add_shared_dir_readers should fail here");
510 result = smack_have_access(app_labels_wrong[0],TEST_OBJ,"rx");
511 RUNNER_ASSERT_MSG(result != 1, "add_shared_dir_readers should not grant permission here");
513 smack_accesses_free(rules);
515 //ok, now the correct list of apps
516 result = smack_accesses_new(&rules);
517 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS, "Error in smack_accesses_new. Error: " << result);
519 for (i = 0; i < 3; i++) {
521 (void)app_uninstall(app_labels[i]);
522 result = app_install(app_labels[i]);
523 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS, "Error in app_install.");
525 asprintf(&path, SMACK_RULES_DIR "/%s", app_labels[i]);
526 fd = open(path, O_WRONLY, 0644);
527 RUNNER_ASSERT_MSG(fd != -1, "Error in opening file " << path);
530 result = smack_accesses_add(rules,app_labels[i],TEST_OBJ,"wt");
531 RUNNER_ASSERT_MSG(result == 0, "smack_accesses_add failed");
534 smack_accesses_free(rules);
535 result = smack_accesses_new(&rules);
536 result = smack_accesses_add(rules,app_labels[i],TEST_OBJ_SOME_OTHER,"wx");
537 RUNNER_ASSERT_MSG(result == 0, "smack_accesses_add failed");
539 result = smack_accesses_apply(rules);
540 RUNNER_ASSERT_MSG(fd != -1, "smack_accesses_apply failed");
542 result = smack_accesses_save(rules, fd);
543 RUNNER_ASSERT_MSG(fd != -1, "smack_accesses_apply failed");
550 smack_accesses_free(rules);
552 // THE TEST - accesses
554 result = add_shared_dir_readers(TEST_OBJ,app_labels);
555 RUNNER_ASSERT_MSG(result == 0, "add_shared_dir_readers failed");
557 result = smack_have_access(app_labels[0],TEST_OBJ,"rx");
558 RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
560 result = smack_have_access(app_labels[1],TEST_OBJ,"rx");
561 RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
563 result = smack_have_access(app_labels[2],TEST_OBJ,"rx");
564 RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
566 result = smack_have_access(app_labels[1],TEST_OBJ,"rwxt");
567 RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
569 result = smack_have_access(app_labels[2],TEST_OBJ_SOME_OTHER,"wx");
570 RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
573 //TEST the operations on empty files
575 asprintf(&path, SMACK_RULES_DIR "/%s", app_labels[0]);
576 file = fopen(path, "r");
578 RUNNER_ASSERT_MSG(file, "fopen failed, errno:" << errno);
580 fgets(buf, READ_BUF_SIZE, file);
581 result = strcmp(buf, test_string_01);
582 RUNNER_ASSERT_MSG( result!=0, "add_shared_dir_readers ERROR, file not formatted" << path );
587 //TEST the operations on non empty files
588 asprintf(&path, SMACK_RULES_DIR "/%s", app_labels[2]);
590 file = fopen(path, "r");
591 RUNNER_ASSERT_MSG(file, "fopen failed, errno:" << errno);
593 fgets(buf, READ_BUF_SIZE, file);
594 result = strcmp(buf, test_string_21);
595 RUNNER_ASSERT_MSG( result==0, "add_shared_dir_readers ERROR, file not formatted" );
597 fgets(buf, READ_BUF_SIZE, file);
598 result = strcmp(buf, test_string_22);
599 RUNNER_ASSERT_MSG( result==0, "add_shared_dir_readers ERROR, file not formatted" );
607 * Set APP privileges.
609 RUNNER_CHILD_TEST(privilege_control05_set_app_privilege)
614 smack_lsetlabel(APP_SET_PRIV_PATH_REAL, APP_ID, SMACK_LABEL_EXEC);
615 smack_lsetlabel(APP_SET_PRIV_PATH, APP_ID "_symlink", SMACK_LABEL_EXEC);
617 // Set APP privileges
618 result = set_app_privilege(APP_ID, NULL, APP_SET_PRIV_PATH);
619 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS, "Error in set_app_privilege. Error: " << result);
621 // Check if SMACK label really set
623 result = smack_new_label_from_self(&label);
624 RUNNER_ASSERT_MSG(result == 0, "Error getting current process label");
625 RUNNER_ASSERT_MSG(label != NULL, "Process label is not set");
626 result = strcmp(APP_ID, label);
627 RUNNER_ASSERT_MSG(result == 0, "Process label " << label << " is incorrect");
629 // Check if DAC privileges really set
630 RUNNER_ASSERT_MSG(getuid() == APP_UID, "Wrong UID");
631 RUNNER_ASSERT_MSG(getgid() == APP_GID, "Wrong GID");
633 result = strcmp(getenv("HOME"), APP_HOME_DIR);
634 RUNNER_ASSERT_MSG(result == 0, "Wrong HOME DIR");
636 result = strcmp(getenv("USER"), APP_USER_NAME);
637 RUNNER_ASSERT_MSG(result == 0, "Wrong user USER NAME");
639 std::set<unsigned> groups_check;
640 read_gids(groups_check, LIBPRIVILEGE_APP_GROUP_LIST);
641 read_gids(groups_check, LIBPRIVILEGE_TEST_DAC_FILE);
643 int groups_cnt = getgroups(0, NULL);
644 RUNNER_ASSERT_MSG(groups_cnt > 0, "Wrong number of supplementary groupsCnt");
645 gid_t *groups_list = (gid_t *) calloc(groups_cnt, sizeof(gid_t));
646 RUNNER_ASSERT_MSG(groups_list != NULL, "Memory allocation failed");
647 getgroups(groups_cnt, groups_list);
649 for (int i = 0; i < groups_cnt; ++i) {
650 if (groups_check.erase(groups_list[i]) == 0) {
651 // getgroups() may also return process' main group
652 if (groups_list[i] == getgid())
653 RUNNER_ASSERT_MSG(false, "Application belongs to unknown group (GID=" << groups_list[i] << ")");
656 std::string groups_left;
657 for (std::set<unsigned>::iterator it = groups_check.begin(); it != groups_check.end(); it++) {
658 groups_left.append(std::to_string(*it)).append(" ");
660 RUNNER_ASSERT_MSG(groups_check.empty(), "Application doesn't belong to some required groups: " << groups_left);
663 RUNNER_TEST(privilege_control08_app_give_access)
665 const char *subject = "lkjq345v34sfa";
666 const char *object = "lk9290f92lkjz";
667 smack_accesses *tmp = NULL;
669 RUNNER_ASSERT(0 == smack_accesses_new(&tmp));
671 std::unique_ptr<smack_accesses,std::function<void(smack_accesses*)>>
672 smack(tmp, smack_accesses_free);
674 RUNNER_ASSERT(0 == smack_accesses_add(smack.get(), subject, object, "r--a-"));
675 RUNNER_ASSERT(0 == smack_accesses_apply(smack.get()));
677 app_give_access(subject, object, "wt");
679 RUNNER_ASSERT(1 == smack_have_access(subject, object, "rwat"));
680 RUNNER_ASSERT(0 == smack_have_access(subject, object, "x"));
682 app_revoke_access(subject, object);
684 RUNNER_ASSERT(1 == smack_have_access(subject, object, "ra"));
685 RUNNER_ASSERT(0 == smack_have_access(subject, object, "w"));
686 RUNNER_ASSERT(0 == smack_have_access(subject, object, "x"));
687 RUNNER_ASSERT(0 == smack_have_access(subject, object, "t"));
689 RUNNER_ASSERT(0 == smack_accesses_add(smack.get(), subject, object, "-"));
690 RUNNER_ASSERT(0 == smack_accesses_apply(smack.get()));
694 * Add new API feature
696 RUNNER_TEST(privilege_control09_add_api_feature)
700 remove_smack_files();
703 // argument validation
704 result = add_api_feature(APP_TYPE_OSP, NULL, NULL, NULL, 0);
705 RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
707 result = add_api_feature(APP_TYPE_OSP,"" , NULL, NULL, 0);
708 RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
711 // already existing features
712 result = add_api_feature(APP_TYPE_OSP,"messaging" , NULL, NULL, 0);
713 RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
715 result = add_api_feature(APP_TYPE_OSP,"blahblah/messaging" , NULL, NULL, 0);
716 RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
718 result = add_api_feature(APP_TYPE_WGT,"blahblahblah/messaging" , NULL, NULL, 0);
719 RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
721 result = add_api_feature(APP_TYPE_OTHER,"blah/messaging" , NULL, NULL, 0);
722 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
726 result = add_api_feature(APP_TYPE_OSP,"blahblah" , NULL, NULL, 0);
727 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
729 result = add_api_feature(APP_TYPE_WGT,"blahblah" , NULL, NULL, 0);
730 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
732 result = add_api_feature(APP_TYPE_OTHER,"blahblah" , NULL, NULL, 0);
733 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
736 // smack files existence
737 result = file_exists(OSP_BLAHBLAH);
738 RUNNER_ASSERT(result == -1);
740 result = file_exists(WRT_BLAHBLAH);
741 RUNNER_ASSERT(result == -1);
743 result = file_exists(OTHER_BLAHBLAH);
744 RUNNER_ASSERT(result == -1);
748 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , { NULL }, NULL, 0);
749 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
750 result = file_exists(OSP_BLAHBLAH);
751 RUNNER_ASSERT(result == -1);
753 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "", NULL }, NULL, 0);
754 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
755 result = file_exists(OSP_BLAHBLAH);
756 RUNNER_ASSERT(result == 0);
757 remove_smack_files();
759 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ " \t\n", "\t \n", "\n\t ", NULL }, NULL, 0);
760 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
761 result = file_exists(OSP_BLAHBLAH);
762 RUNNER_ASSERT(result == 0);
763 remove_smack_files();
767 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "malformed", NULL }, NULL, 0);
768 RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
769 result = file_exists(OSP_BLAHBLAH);
770 RUNNER_ASSERT(result == -1);
772 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "malformed malformed", NULL }, NULL, 0);
773 RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
774 result = file_exists(OSP_BLAHBLAH);
775 RUNNER_ASSERT(result == -1);
777 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "-malformed malformed rwxat", NULL }, NULL, 0);
778 RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
779 result = file_exists(OSP_BLAHBLAH);
780 RUNNER_ASSERT(result == -1);
782 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "~/\"\\\ malformed rwxat", NULL }, NULL, 0);
783 RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
784 result = file_exists(OSP_BLAHBLAH);
785 RUNNER_ASSERT(result == -1);
787 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "subject object rwxat something else", NULL }, NULL, 0);
788 RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
789 result = file_exists(OSP_BLAHBLAH);
790 RUNNER_ASSERT(result == -1);
794 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "malformed malformed maaaaaalformed", NULL }, NULL, 0);
795 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
796 osp_blahblah_check(__LINE__, { "malformed malformed r--a-" });
797 remove_smack_files();
799 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "subject object foo", NULL }, NULL, 0);
800 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
801 osp_blahblah_check(__LINE__, { "subject object -----" });
802 remove_smack_files();
804 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){
805 "subject object\t rwxat",
807 "subject2\tobject2 txarw",
810 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
811 osp_blahblah_check(__LINE__, { "subject object rwxat", "subject2 object2 rwxat"});
812 remove_smack_files();
814 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){
815 "Sub::jE,ct object a-RwX",
817 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
818 osp_blahblah_check(__LINE__, { "Sub::jE,ct object rwxa-"});
819 remove_smack_files();
821 // TODO For now identical/complementary rules are not merged.
822 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){
823 "subject object rwxat",
825 "subject object txarw",
828 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
829 osp_blahblah_check(__LINE__, { "subject object rwxat", "subject object rwxat"});
830 remove_smack_files();
834 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){"a a a",NULL},(const gid_t[]){0,1,2},0);
835 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
836 osp_blahblah_check(__LINE__, { "a a ---a-"});
837 result = file_exists(OSP_BLAHBLAH_DAC);
838 RUNNER_ASSERT(result == -1);
839 remove_smack_files();
843 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){"a a a",NULL},(const gid_t[]){0,1,2},3);
844 printf("%d \n", result);
845 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
846 osp_blahblah_check(__LINE__, { "a a ---a-"});
847 osp_blahblah_dac_check(__LINE__, {0,1,2});
848 remove_smack_files();
850 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){"a a a",NULL},(const gid_t[]){0,1,2},1);
851 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
852 osp_blahblah_check(__LINE__, { "a a ---a-"});
853 osp_blahblah_dac_check(__LINE__, {0});
854 remove_smack_files();
856 result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){"a a a",NULL},(const gid_t[]){1,1,1},3);
857 RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
858 osp_blahblah_check(__LINE__, { "a a ---a-"});
859 osp_blahblah_dac_check(__LINE__, {1,1,1});
860 remove_smack_files();
864 * Check app_install function
866 RUNNER_TEST(privilege_control01_app_install)
872 smack_file_name(APP_ID, &path);
875 result = app_install(APP_ID);
876 RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
878 // checking if file really exists
879 fd = open(path, O_RDONLY);
880 RUNNER_ASSERT_MSG(fd >= 0, "File open failed: " << path << " : " << result << ". Errno: " << strerror(errno));
884 // try install second time app with the same ID - it should failed with -1 (Errno: File exists).
885 result = app_install(APP_ID);
886 RUNNER_ASSERT_MSG(result == -1, "app_install returned " << result <<". Errno: " << strerror(errno));
890 * Check app_install function
892 RUNNER_TEST(privilege_control07_app_uninstall)
898 smack_file_name(APP_ID, &path);
899 result = app_uninstall(APP_ID);
900 RUNNER_ASSERT_MSG(result == 0, "app_uninstall returned " << result <<". Errno: " << strerror(errno));
902 // checking if file really exists
903 smack_file_name(APP_ID, &path);
904 fd = open(path, O_RDONLY);
905 RUNNER_ASSERT_MSG(fd == -1, "SMACK file NOT deleted after app_uninstall");
911 * Check app_register_av function
912 * Notice that this test case may have no sense if previous would fail (privilege_control06_app_install)
914 RUNNER_TEST(privilege_control10_app_register_av)
917 //FILE* file_av = NULL;
918 //FILE* file_app = NULL;
925 //char label1[SMACK_LABEL_LEN +1];
926 //char label2[SMACK_LABEL_LEN +1];
927 //char acces_rights[6 +1];
928 //char row[2 * SMACK_LABEL_LEN + 20] //
929 const char* correct_antivirus1_rules = "test-antivirus1 test-application1 rwx--\n"
930 "test-antivirus1 test-application_2 rwx--\n"
931 "test-antivirus1 test-app-3 rwx--";
932 const char* correct_antivirus2_rules = "test-antivirus_2 test-application1 rwx--\n"
933 "test-antivirus_2 test-application_2 rwx--\n"
934 "test-antivirus_2 test-app-3 rwx--";
937 cleaning_smack_app_files();
938 cleaning_smack_database_files();
940 result = app_install(APP_TEST_APP_1);
941 RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
943 result = app_install(APP_TEST_APP_2);
944 RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
946 result = app_register_av(APP_TEST_AV_1);
947 RUNNER_ASSERT_MSG(result == 0, "app_register_av returned " << result <<". Errno: " << strerror(errno));
949 result = app_install(APP_TEST_APP_3);
950 RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
952 result = app_register_av(APP_TEST_AV_2);
953 RUNNER_ASSERT_MSG(result == 0, "app_register_av returned " << result <<". Errno: " << strerror(errno));
955 // checking rules for anti virus 1
956 // compare between file in /etc/smack/access.d/ and correct value (correct_antivirus1_rules).
957 len = strlen(correct_antivirus1_rules);
958 buff = (char *) malloc((len+1) * sizeof(char));
959 smack_file_name(APP_TEST_AV_1, &path);
960 fd = open(path, O_RDONLY);
962 RUNNER_ASSERT_MSG(fd > -1, "file open failed " << result <<". Errno: " << strerror(errno));
963 result = read(fd, buff, len);
967 RUNNER_ASSERT_MSG(result > -1, "read from file descriptor failed. Errno: " << strerror(errno));
968 result = strncmp(buff, correct_antivirus1_rules, len);
969 RUNNER_ASSERT_MSG(result == 0, "Rules do not match: " << result << "\n\"" << buff << "\"\n\"" << correct_antivirus1_rules << "\"\n" << len);
972 // checking rules for anti virus 2
973 len = strlen(correct_antivirus2_rules);
974 buff = (char *) malloc((len+1) * sizeof(char));
975 smack_file_name(APP_TEST_AV_2, &path);
976 fd = open(path, O_RDONLY);
978 RUNNER_ASSERT_MSG(fd > -1, "file open failed " << result <<". Errno: " << strerror(errno));
979 result = read(fd, buff, len);
983 RUNNER_ASSERT_MSG(result > -1, "read from file descriptor failed. Errno: " << strerror(errno));
984 result = strncmp(buff, correct_antivirus2_rules, len);
985 RUNNER_ASSERT_MSG(result == 0, "Rules do not match: " << result << "\n\"" << buff << "\"\n\"" << correct_antivirus1_rules << "\"\n" << len);
989 cleaning_smack_app_files();
990 cleaning_smack_database_files();