Fixed tests for app_shared_dir_add_readers()
[platform/core/test/security-tests.git] / tests / libprivilege-control-tests / test_cases.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 /*
18  * @file        test_cases.cpp
19  * @author      Jan Olszak (j.olszak@samsung.com)
20  * @author      Rafal Krypa (r.krypa@samsung.com)
21  * @version     1.0
22  * @brief       libprivilege-control test runer
23  */
24
25 #include <string>
26 #include <stdio.h>
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <vector>
30 #include <errno.h>
31 #include <memory>
32 #include <ftw.h>
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>
37 #include <sys/stat.h>
38 #include <sys/mman.h>
39 #include <sys/xattr.h>
40 #include <sys/smack.h>
41 #include <privilege-control.h>
42 #include <fstream>
43
44
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"
52
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"
56
57 const char *PRIVS[] = { "WRT", "test_privilege_control_rules", NULL };
58
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"
61
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"
70
71 #define APP_GID 5000
72 #define APP_UID 5000
73 #define APP_USER_NAME "app"
74 #define APP_HOME_DIR "/opt/home/app"
75
76 // How many open file descriptors should ftw() function use?
77 #define FTW_MAX_FDS 16
78
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"}};
96
97
98 namespace {
99
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";
107
108 /**
109  * Check if every rule is true.
110  * @return 1 if ALL rules in SMACK, 0 if ANY rule isn't
111  */
112 int test_have_all_accesses(const std::vector< std::vector<std::string> >& rules){
113     int result;
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());
116         if (result !=1)
117             return result;
118     }
119     return 1;
120 }
121
122 /**
123  * Check if every rule is true.
124  * @return 1 if ANY rule in SMACK, 0 if
125  */
126 int test_have_any_accesses(const std::vector< std::vector<std::string> >& rules){
127     int result;
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());
130         if (result ==1)
131             return 1;
132     }
133     return 0;
134 }
135
136 RUNNER_TEST_GROUP_INIT(libprivilegecontrol)
137
138 int nftw_remove_labels(const char *fpath, const struct stat *sb,
139                                 int typeflag, struct FTW *ftwbuf)
140 {
141         smack_lsetlabel(fpath, NULL, SMACK_LABEL_ACCESS);
142         smack_lsetlabel(fpath, NULL, SMACK_LABEL_EXEC);
143         smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
144
145         return 0;
146 }
147
148 int nftw_set_labels_non_app_dir(const char *fpath, const struct stat *sb,
149                                 int typeflag, struct FTW *ftwbuf)
150 {
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);
154
155         return 0;
156 }
157
158 int nftw_check_labels_non_app_dir(const char *fpath, const struct stat *sb,
159                                 int typeflag, struct FTW *ftwbuf)
160 {
161     int result;
162     char* label;
163
164     /* ACCESS */
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");
169
170     /* EXEC */
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");
175
176     /* TRANSMUTE */
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");
180
181     return 0;
182 }
183
184 int nftw_check_labels_app_dir(const char *fpath, const struct stat *sb,
185                                 int typeflag, struct FTW *ftwbuf)
186 {
187     int result;
188     char* label;
189
190     /* ACCESS */
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");
196
197     /* EXEC */
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");
204     } else
205         RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
206
207     /* TRANSMUTE */
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");
211
212     return 0;
213 }
214
215 int nftw_check_labels_app_shared_dir(const char *fpath, const struct stat *sb,
216                                 int typeflag, struct FTW *ftwbuf)
217 {
218     int result;
219     char* label;
220
221     /* ACCESS */
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");
227
228     /* EXEC */
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");
232
233     /* TRANSMUTE */
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");
240     } else
241         RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
242
243     return 0;
244 }
245
246 int file_exists(const char* path)
247 {
248     FILE* file = fopen(path, "r");
249     if (file) {
250         fclose(file);
251         return 0;
252     }
253     return -1;
254 }
255
256 void osp_blahblah_check(int line_no, const std::vector<std::string>& rules)
257 {
258     std::ifstream smack_file(OSP_BLAHBLAH);
259     RUNNER_ASSERT_MSG(smack_file, "Line: " << line_no << " Failed to create " << OSP_BLAHBLAH);
260
261     auto it = rules.begin();
262     std::string line;
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);
266         it++;
267     }
268
269     RUNNER_ASSERT_MSG(it == rules.end(), "Line: " << line_no << " Missing line in file: " << *it);
270
271     smack_file.close();
272 }
273
274 void osp_blahblah_dac_check(int line_no, const std::vector<unsigned>& gids)
275 {
276         std::ifstream dac_file(OSP_BLAHBLAH_DAC);
277         RUNNER_ASSERT_MSG(dac_file, "Line: " << line_no << " Failed to create " << OSP_BLAHBLAH_DAC);
278
279         auto it = gids.begin();
280         std::string line;
281         while(std::getline(dac_file,line)) {
282                 std::istringstream is(line);
283                 unsigned gid;
284                 is >> gid;
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);
287                 it++;
288         }
289
290         RUNNER_ASSERT_MSG(it == gids.end(), "Line: " << line_no << " Missing line in file: " << *it);
291
292         dac_file.close();
293 }
294
295 void remove_smack_files()
296 {
297         // TODO array
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);
304 }
305
306 int smack_file_name(const char* app_id, char** path)
307 {
308     if (asprintf(path, SMACK_RULES_DIR "/%s", app_id) == -1) {
309         RUNNER_ASSERT_MSG(false, "asprint failed");
310         *path = NULL;
311     }
312
313     return 0;
314 }
315
316 int cleaning_smack_app_files (void)
317 {
318     char *path = NULL;
319     int fd = -1;
320
321     smack_file_name(APP_TEST_APP_1, &path);
322     unlink(path);
323     free(path);
324
325     smack_file_name(APP_TEST_APP_2, &path);
326     unlink(path);
327     free(path);
328
329     smack_file_name(APP_TEST_APP_3, &path);
330     unlink(path);
331     free(path);
332
333     smack_file_name(APP_TEST_AV_1, &path);
334     unlink(path);
335     free(path);
336
337     smack_file_name(APP_TEST_AV_2, &path);
338     unlink(path);
339     free(path);
340
341     smack_file_name(APP_TEST_AV_3, &path);
342     unlink(path);
343     free(path);
344
345     return 0;
346 }
347
348 int cleaning_smack_database_files (void)
349 {
350     int fd = -1;
351
352     //clean app database
353     unlink(SMACK_APPS_LABELS_DATABASE);
354     fd = open(SMACK_APPS_LABELS_DATABASE, O_RDWR | O_EXCL | O_CREAT, 0644);
355     if (fd == -1) {
356         return -1;
357     }
358
359     //clean av database
360     unlink(SMACK_AVS_LABELS_DATABASE);
361     fd = open(SMACK_AVS_LABELS_DATABASE, O_RDWR | O_EXCL | O_CREAT, 0644);
362     if (fd == -1) {
363         return -1;
364     }
365
366     return 0;
367 }
368 } // namespace
369
370 /**
371  * Test setting labels for all files and folders in given path.
372  */
373 RUNNER_TEST(privilege_control02_app_label_dir)
374 {
375     int result;
376
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);
379
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);
382
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);
385
386     result = app_label_dir(APPID_DIR, TEST_APP_DIR);
387     RUNNER_ASSERT_MSG(result == 0, "app_label_dir() failed");
388
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");
391
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");
394 }
395
396 RUNNER_TEST(privilege_control03_app_label_shared_dir)
397 {
398     int result;
399
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);
402
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);
405
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");
408
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");
411
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");
414 }
415
416
417 /**
418  * Add permisions from  test_privilege_control_rules template
419  */
420 RUNNER_TEST(privilege_control04_add_permissions)
421 {
422     int result = app_add_permissions(APP_ID, PRIVS);
423     RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
424             " Error adding app permissions. Errno: " << result);
425
426     // Check if the accesses are realy applied..
427     result = test_have_all_accesses(rules);
428     RUNNER_ASSERT_MSG(result==1, "Permissions not added.");
429
430     //// File exists?
431     FILE *pFile = fopen(SMACK_RULES_DIR APP_ID, "rb");
432     RUNNER_ASSERT_MSG(pFile != NULL,
433             "SMACK file NOT created!. Errno: " << errno);
434
435     //// Is it empty?
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);
440
441     if (pFile != NULL)
442         fclose(pFile);
443
444 }
445
446 /**
447  * Revoke permissions from the list. Should be executed as privileged user.
448  */
449 RUNNER_CHILD_TEST(privilege_control06_revoke_permissions)
450 {
451     int result;
452     char* path = NULL;
453     int fd;
454
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);
459
460     // Are all the permissions revoked?
461     result = test_have_all_accesses(rules);
462     RUNNER_ASSERT_MSG(result!=1, "Not all permisions revoked.");
463
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");
468     free(path);
469     close(fd);
470 }
471
472 static void read_gids(std::set<unsigned> &set, const char* file_path)
473 {
474         FILE *f = fopen(file_path, "r");
475         RUNNER_ASSERT_MSG(f != NULL, "Unable to open file " << file_path);
476         unsigned gid;
477         while (fscanf(f, "%u\n", &gid) == 1) {
478                 set.insert(gid);
479         }
480 }
481
482 RUNNER_TEST(privilege_control05_add_shared_dir_readers)
483 {
484
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"
490
491     int result;
492     int i;
493     int fd = -1;
494     char *path;
495
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];
500     FILE *file = NULL;
501     struct smack_accesses * rules = NULL;
502
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);
506
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");
509
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");
512
513     smack_accesses_free(rules);
514
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);
518
519     for (i = 0; i < 3; i++) {
520
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.");
524
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);
528
529         if (i == 1) {
530                 result = smack_accesses_add(rules,app_labels[i],TEST_OBJ,"wt");
531                 RUNNER_ASSERT_MSG(result == 0, "smack_accesses_add failed");
532         }
533         if (i == 2) {
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");
538         }
539         result = smack_accesses_apply(rules);
540         RUNNER_ASSERT_MSG(fd != -1, "smack_accesses_apply failed");
541
542         result = smack_accesses_save(rules, fd);
543         RUNNER_ASSERT_MSG(fd != -1, "smack_accesses_apply failed");
544
545         free(path);
546         close(fd);
547
548     }
549
550     smack_accesses_free(rules);
551
552     // THE TEST - accesses
553
554     result = add_shared_dir_readers(TEST_OBJ,app_labels);
555     RUNNER_ASSERT_MSG(result == 0, "add_shared_dir_readers failed");
556
557     result = smack_have_access(app_labels[0],TEST_OBJ,"rx");
558     RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
559
560     result = smack_have_access(app_labels[1],TEST_OBJ,"rx");
561     RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
562
563     result = smack_have_access(app_labels[2],TEST_OBJ,"rx");
564     RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
565
566     result = smack_have_access(app_labels[1],TEST_OBJ,"rwxt");
567     RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
568
569     result = smack_have_access(app_labels[2],TEST_OBJ_SOME_OTHER,"wx");
570     RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
571
572
573     //TEST the operations on empty files
574
575     asprintf(&path, SMACK_RULES_DIR "/%s", app_labels[0]);
576     file = fopen(path, "r");
577
578     RUNNER_ASSERT_MSG(file, "fopen failed, errno:" << errno);
579
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 );
583
584     free(path);
585     fclose(file);
586
587     //TEST the operations on non empty files
588     asprintf(&path, SMACK_RULES_DIR "/%s", app_labels[2]);
589     file = NULL;
590     file = fopen(path, "r");
591     RUNNER_ASSERT_MSG(file, "fopen failed, errno:" << errno);
592
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" );
596
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" );
600
601     free(path);
602     fclose(file);
603 }
604
605
606 /**
607  * Set APP privileges.
608  */
609 RUNNER_CHILD_TEST(privilege_control05_set_app_privilege)
610 {
611     int result;
612
613     // Preset exec label
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);
616
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);
620
621     // Check if SMACK label really set
622     char * label;
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");
628
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");
632
633     result = strcmp(getenv("HOME"), APP_HOME_DIR);
634     RUNNER_ASSERT_MSG(result == 0, "Wrong HOME DIR");
635
636     result = strcmp(getenv("USER"), APP_USER_NAME);
637     RUNNER_ASSERT_MSG(result == 0, "Wrong user USER NAME");
638
639     std::set<unsigned> groups_check;
640     read_gids(groups_check, LIBPRIVILEGE_APP_GROUP_LIST);
641     read_gids(groups_check, LIBPRIVILEGE_TEST_DAC_FILE);
642
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);
648
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] << ")");
654         }
655     }
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(" ");
659     }
660     RUNNER_ASSERT_MSG(groups_check.empty(), "Application doesn't belong to some required groups: " << groups_left);
661 }
662
663 RUNNER_TEST(privilege_control08_app_give_access)
664 {
665     const char *subject = "lkjq345v34sfa";
666     const char *object = "lk9290f92lkjz";
667     smack_accesses *tmp = NULL;
668
669     RUNNER_ASSERT(0 == smack_accesses_new(&tmp));
670
671     std::unique_ptr<smack_accesses,std::function<void(smack_accesses*)>>
672         smack(tmp, smack_accesses_free);
673
674     RUNNER_ASSERT(0 == smack_accesses_add(smack.get(), subject, object, "r--a-"));
675     RUNNER_ASSERT(0 == smack_accesses_apply(smack.get()));
676
677     app_give_access(subject, object, "wt");
678
679     RUNNER_ASSERT(1 == smack_have_access(subject, object, "rwat"));
680     RUNNER_ASSERT(0 == smack_have_access(subject, object, "x"));
681
682     app_revoke_access(subject, object);
683
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"));
688
689     RUNNER_ASSERT(0 == smack_accesses_add(smack.get(), subject, object, "-"));
690     RUNNER_ASSERT(0 == smack_accesses_apply(smack.get()));
691 }
692
693 /**
694  * Add new API feature
695  */
696 RUNNER_TEST(privilege_control09_add_api_feature)
697 {
698     int result;
699
700     remove_smack_files();
701
702
703     // argument validation
704     result = add_api_feature(APP_TYPE_OSP, NULL, NULL, NULL, 0);
705     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
706
707     result = add_api_feature(APP_TYPE_OSP,"" , NULL, NULL, 0);
708     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
709
710
711     // already existing features
712     result = add_api_feature(APP_TYPE_OSP,"messaging" , NULL, NULL, 0);
713     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
714
715     result = add_api_feature(APP_TYPE_OSP,"blahblah/messaging" , NULL, NULL, 0);
716     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
717
718     result = add_api_feature(APP_TYPE_WGT,"blahblahblah/messaging" , NULL, NULL, 0);
719     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
720
721     result = add_api_feature(APP_TYPE_OTHER,"blah/messaging" , NULL, NULL, 0);
722     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
723
724
725     // empty features
726     result = add_api_feature(APP_TYPE_OSP,"blahblah" , NULL, NULL, 0);
727     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
728
729     result = add_api_feature(APP_TYPE_WGT,"blahblah" , NULL, NULL, 0);
730     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
731
732     result = add_api_feature(APP_TYPE_OTHER,"blahblah" , NULL, NULL, 0);
733     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
734
735
736     // smack files existence
737     result = file_exists(OSP_BLAHBLAH);
738     RUNNER_ASSERT(result == -1);
739
740     result = file_exists(WRT_BLAHBLAH);
741     RUNNER_ASSERT(result == -1);
742
743     result = file_exists(OTHER_BLAHBLAH);
744     RUNNER_ASSERT(result == -1);
745
746
747     // empty rules
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);
752
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();
758
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();
764
765
766     // malformed rules
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);
771
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);
776
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);
781
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);
786
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);
791
792
793     // correct rules
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();
798
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();
803
804     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){
805         "subject    object\t rwxat",
806         " \t \n",
807         "subject2\tobject2 txarw",
808         "",
809         NULL }, NULL, 0);
810     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
811     osp_blahblah_check(__LINE__, { "subject object rwxat", "subject2 object2 rwxat"});
812     remove_smack_files();
813
814     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){
815         "Sub::jE,ct object a-RwX",
816         NULL }, NULL, 0);
817     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
818     osp_blahblah_check(__LINE__, { "Sub::jE,ct object rwxa-"});
819     remove_smack_files();
820
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",
824         " \t \n",
825         "subject object txarw",
826         "",
827         NULL }, NULL, 0);
828     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
829     osp_blahblah_check(__LINE__, { "subject object rwxat", "subject object rwxat"});
830     remove_smack_files();
831
832
833     // empty group ids
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();
840
841
842     // valid group ids
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();
849
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();
855
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();
861 }
862
863 /*
864  * Check app_install function
865  */
866 RUNNER_TEST(privilege_control01_app_install)
867 {
868     int result;
869     char *path = NULL;
870     int fd = -1;
871
872     smack_file_name(APP_ID, &path);
873     unlink(path);
874
875     result = app_install(APP_ID);
876     RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
877
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));
881     close(fd);
882     free(path);
883
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));
887 }
888
889 /*
890  * Check app_install function
891  */
892 RUNNER_TEST(privilege_control07_app_uninstall)
893 {
894     int result;
895     char *path = NULL;
896     int fd = -1;
897
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));
901
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");
906     close(fd);
907     free(path);
908 }
909
910 /*
911  * Check app_register_av function
912  * Notice that this test case may have no sense if previous would fail (privilege_control06_app_install)
913  */
914 RUNNER_TEST(privilege_control10_app_register_av)
915 {
916     int result;
917     //FILE* file_av = NULL;
918     //FILE* file_app = NULL;
919     //int fd_app = -1;
920     int fd  = -1;
921     char *path = NULL;
922     char *buff;
923     int len;
924     int i;
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--";
935
936     // cleaning
937     cleaning_smack_app_files();
938     cleaning_smack_database_files();
939
940     result = app_install(APP_TEST_APP_1);
941     RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
942
943     result = app_install(APP_TEST_APP_2);
944     RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
945
946     result = app_register_av(APP_TEST_AV_1);
947     RUNNER_ASSERT_MSG(result == 0, "app_register_av returned " << result <<". Errno: " << strerror(errno));
948
949     result = app_install(APP_TEST_APP_3);
950     RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
951
952     result = app_register_av(APP_TEST_AV_2);
953     RUNNER_ASSERT_MSG(result == 0, "app_register_av returned " << result <<". Errno: " << strerror(errno));
954
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);
961     free(path);
962     RUNNER_ASSERT_MSG(fd > -1, "file open failed " << result <<". Errno: " << strerror(errno));
963     result = read(fd, buff, len);
964     close(fd);
965     fd = -1;
966     buff[len] = '\0';
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);
970     free(buff);
971
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);
977     free (path);
978     RUNNER_ASSERT_MSG(fd > -1, "file open failed " << result <<". Errno: " << strerror(errno));
979     result = read(fd, buff, len);
980     close (fd);
981     fd = -1;
982     buff[len] = '\0';
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);
986     free(buff);
987
988     // cleaning
989     cleaning_smack_app_files();
990     cleaning_smack_database_files();
991 }