e15f239ac81394cb6b88e9044778975f60e3595f
[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* BLAHBLAH_FEATURE = "http://feature/blah/blahblah";
104
105 /**
106  * Check if every rule is true.
107  * @return 1 if ALL rules in SMACK, 0 if ANY rule isn't
108  */
109 int test_have_all_accesses(const std::vector< std::vector<std::string> >& rules){
110     int result;
111     for(uint i =0; i<rules.size();++i ){
112         result = smack_have_access(rules[i][0].c_str(),rules[i][1].c_str(),rules[i][2].c_str());
113         if (result !=1)
114             return result;
115     }
116     return 1;
117 }
118
119 /**
120  * Check if every rule is true.
121  * @return 1 if ANY rule in SMACK, 0 if
122  */
123 int test_have_any_accesses(const std::vector< std::vector<std::string> >& rules){
124     int result;
125     for(uint i =0; i<rules.size();++i ){
126         result = smack_have_access(rules[i][0].c_str(),rules[i][1].c_str(),rules[i][2].c_str());
127         if (result ==1)
128             return 1;
129     }
130     return 0;
131 }
132
133 RUNNER_TEST_GROUP_INIT(libprivilegecontrol)
134
135 int nftw_remove_labels(const char *fpath, const struct stat *sb,
136                                 int typeflag, struct FTW *ftwbuf)
137 {
138         smack_lsetlabel(fpath, NULL, SMACK_LABEL_ACCESS);
139         smack_lsetlabel(fpath, NULL, SMACK_LABEL_EXEC);
140         smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
141
142         return 0;
143 }
144
145 int nftw_set_labels_non_app_dir(const char *fpath, const struct stat *sb,
146                                 int typeflag, struct FTW *ftwbuf)
147 {
148         smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_ACCESS);
149         smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_EXEC);
150         smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
151
152         return 0;
153 }
154
155 int nftw_check_labels_non_app_dir(const char *fpath, const struct stat *sb,
156                                 int typeflag, struct FTW *ftwbuf)
157 {
158     int result;
159     char* label;
160
161     /* ACCESS */
162     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
163     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
164     result = strcmp(CANARY_LABEL, label);
165     RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is overwritten");
166
167     /* EXEC */
168     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
169     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
170     result = strcmp(CANARY_LABEL, label);
171     RUNNER_ASSERT_MSG(result == 0, "EXEC label on " << fpath << " is overwritten");
172
173     /* TRANSMUTE */
174     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
175     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
176     RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
177
178     return 0;
179 }
180
181 int nftw_check_labels_app_dir(const char *fpath, const struct stat *sb,
182                                 int typeflag, struct FTW *ftwbuf)
183 {
184     int result;
185     char* label;
186
187     /* ACCESS */
188     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
189     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
190     RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
191     result = strcmp(APPID_DIR, label);
192     RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
193
194     /* EXEC */
195     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
196     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
197     if (S_ISREG(sb->st_mode) && (sb->st_mode & S_IXUSR)) {
198         RUNNER_ASSERT_MSG(label != NULL, "EXEC label on " << fpath << " is not set");
199         result = strcmp(APPID_DIR, label);
200         RUNNER_ASSERT_MSG(result == 0, "EXEC label on executable file " << fpath << " is incorrect");
201     } else
202         RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
203
204     /* TRANSMUTE */
205     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
206     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
207     RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
208
209     return 0;
210 }
211
212 int nftw_check_labels_app_shared_dir(const char *fpath, const struct stat *sb,
213                                 int typeflag, struct FTW *ftwbuf)
214 {
215     int result;
216     char* label;
217
218     /* ACCESS */
219     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
220     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
221     RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
222     result = strcmp(APPID_SHARED_DIR, label);
223     RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
224
225     /* EXEC */
226     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
227     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
228     RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
229
230     /* TRANSMUTE */
231     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
232     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
233     if (S_ISDIR(sb->st_mode)) {
234         RUNNER_ASSERT_MSG(label != NULL, "TRANSMUTE label on " << fpath << " is not set");
235         result = strcmp("TRUE", label);
236         RUNNER_ASSERT_MSG(result == 0, "TRANSMUTE label on " << fpath << " is not set");
237     } else
238         RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
239
240     return 0;
241 }
242
243 int file_exists(const char* path)
244 {
245     FILE* file = fopen(path, "r");
246     if (file) {
247         fclose(file);
248         return 0;
249     }
250     return -1;
251 }
252
253 void osp_blahblah_check(int line_no, const std::vector<std::string>& rules)
254 {
255     std::ifstream smack_file(OSP_BLAHBLAH);
256     RUNNER_ASSERT_MSG(smack_file, "Line: " << line_no << " Failed to create " << OSP_BLAHBLAH);
257
258     auto it = rules.begin();
259     std::string line;
260     while(std::getline(smack_file,line)) {
261         RUNNER_ASSERT_MSG(it != rules.end(), "Line: " << line_no << "Additional line in file: " << line);
262         RUNNER_ASSERT_MSG(*it == line, "Line: " << line_no << " " << *it << "!=" << line);
263         it++;
264     }
265
266     RUNNER_ASSERT_MSG(it == rules.end(), "Line: " << line_no << " Missing line in file: " << *it);
267
268     smack_file.close();
269 }
270
271 void remove_smack_files()
272 {
273     unlink(OSP_BLAHBLAH);
274     unlink(WRT_BLAHBLAH);
275     unlink(OTHER_BLAHBLAH);
276 }
277
278 int smack_file_name(const char* app_id, char** path)
279 {
280     if (asprintf(path, SMACK_RULES_DIR "/%s", app_id) == -1) {
281         RUNNER_ASSERT_MSG(false, "asprint failed");
282         *path = NULL;
283     }
284
285     return 0;
286 }
287
288 int cleaning_smack_app_files (void)
289 {
290     char *path = NULL;
291     int fd = -1;
292
293     smack_file_name(APP_TEST_APP_1, &path);
294     unlink(path);
295     free(path);
296
297     smack_file_name(APP_TEST_APP_2, &path);
298     unlink(path);
299     free(path);
300
301     smack_file_name(APP_TEST_APP_3, &path);
302     unlink(path);
303     free(path);
304
305     smack_file_name(APP_TEST_AV_1, &path);
306     unlink(path);
307     free(path);
308
309     smack_file_name(APP_TEST_AV_2, &path);
310     unlink(path);
311     free(path);
312
313     smack_file_name(APP_TEST_AV_3, &path);
314     unlink(path);
315     free(path);
316
317     return 0;
318 }
319
320 int cleaning_smack_database_files (void)
321 {
322     int fd = -1;
323
324     //clean app database
325     unlink(SMACK_APPS_LABELS_DATABASE);
326     fd = open(SMACK_APPS_LABELS_DATABASE, O_RDWR | O_EXCL | O_CREAT, 0644);
327     if (fd == -1) {
328         return -1;
329     }
330
331     //clean av database
332     unlink(SMACK_AVS_LABELS_DATABASE);
333     fd = open(SMACK_AVS_LABELS_DATABASE, O_RDWR | O_EXCL | O_CREAT, 0644);
334     if (fd == -1) {
335         return -1;
336     }
337
338     return 0;
339 }
340 } // namespace
341
342 /**
343  * Test setting labels for all files and folders in given path.
344  */
345 RUNNER_TEST(privilege_control02_app_label_dir)
346 {
347     int result;
348
349     result = app_label_shared_dir(APP_ID, APP_ID, TEST_APP_DIR);
350     RUNNER_ASSERT_MSG(result != 0, "app_label_shared_dir(APP_ADD, APP_ID) == " << result);
351
352     result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
353     RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
354
355     result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
356     RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
357
358     result = app_label_dir(APPID_DIR, TEST_APP_DIR);
359     RUNNER_ASSERT_MSG(result == 0, "app_label_dir() failed");
360
361     result = nftw(TEST_APP_DIR, &nftw_check_labels_app_dir, FTW_MAX_FDS, FTW_PHYS);
362     RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for app dir");
363
364     result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
365     RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
366 }
367
368 RUNNER_TEST(privilege_control03_app_label_shared_dir)
369 {
370     int result;
371
372     result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
373     RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
374
375     result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
376     RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
377
378     result = app_label_shared_dir(APP_ID, APPID_SHARED_DIR, TEST_APP_DIR);
379     RUNNER_ASSERT_MSG(result == 0, "app_label_shared_dir() failed");
380
381     result = nftw(TEST_APP_DIR, &nftw_check_labels_app_shared_dir, FTW_MAX_FDS, FTW_PHYS);
382     RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for shared app dir");
383
384     result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
385     RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
386 }
387
388
389 /**
390  * Add permisions from  test_privilege_control_rules template
391  */
392 RUNNER_TEST(privilege_control04_add_permissions)
393 {
394     int result = app_add_permissions(APP_ID, PRIVS);
395     RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
396             " Error adding app permissions. Errno: " << result);
397
398     // Check if the accesses are realy applied..
399     result = test_have_all_accesses(rules);
400     RUNNER_ASSERT_MSG(result==1, "Permissions not added.");
401
402     //// File exists?
403     FILE *pFile = fopen(SMACK_RULES_DIR APP_ID, "rb");
404     RUNNER_ASSERT_MSG(pFile != NULL,
405             "SMACK file NOT created!. Errno: " << errno);
406
407     //// Is it empty?
408     fseek(pFile, 0L, SEEK_END);
409     int smack_file_length = ftell(pFile);
410     RUNNER_ASSERT_MSG(smack_file_length>0,
411             "SMACK file empty, but privileges list was not empty.. Errno: " << errno);
412
413     if (pFile != NULL)
414         fclose(pFile);
415
416 }
417
418 /**
419  * Revoke permissions from the list. Should be executed as privileged user.
420  */
421 RUNNER_CHILD_TEST(privilege_control06_revoke_permissions)
422 {
423     int result;
424     char* path = NULL;
425     int fd;
426
427     // Revoke permissions
428     result = app_revoke_permissions(APP_ID);
429     RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
430             "Error revoking app permissions. Errno: " << result);
431
432     // Are all the permissions revoked?
433     result = test_have_all_accesses(rules);
434     RUNNER_ASSERT_MSG(result!=1, "Not all permisions revoked.");
435
436     smack_file_name(APP_ID, &path);
437     fd = open(path, O_RDONLY);
438     RUNNER_ASSERT_MSG(fd >= 0, "SMACK file deleted after app_revoke_permissions");
439     RUNNER_ASSERT_MSG(lseek(fd, 0, SEEK_END) == 0, "SMACK file not empty after app_revoke_permissions");
440     free(path);
441     close(fd);
442 }
443
444 static void read_gids(std::set<unsigned> &set, const char* file_path)
445 {
446         FILE *f = fopen(file_path, "r");
447         RUNNER_ASSERT_MSG(f != NULL, "Unable to open file " << file_path);
448         unsigned gid;
449         while (fscanf(f, "%u\n", &gid) == 1) {
450                 set.insert(gid);
451         }
452 }
453
454 RUNNER_TEST(privilege_control05_add_shared_dir_readers)
455 {
456
457 #define  TEST_OBJ "TEST_OBJECT"
458 #define  TEST_OBJ_SOME_OTHER "TEST_OBJA"
459 #define test_string_01 "TEST_raz TEST_OBJECT r-x-- -----"
460 #define test_string_21 "TEST_trzy TEST_OBJA -wx--\n"
461 #define test_string_22 "TEST_trzy TEST_OBJECT r-x-- -----\n"
462
463     int result;
464     int i;
465     int fd = -1;
466     char *path;
467     const char *app_labels[] = {"TEST_raz", "TEST_dwa", "TEST_trzy", ""};
468     const int READ_BUF_SIZE = 1000;
469     char buf[READ_BUF_SIZE];
470     FILE *file = NULL;
471     struct smack_accesses * rules = NULL;
472
473     result = smack_accesses_new(&rules);
474     RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS, "Error in smack_accesses_new. Error: " << result);
475
476     for (i = 0; i < 3; i++) {
477
478         (void)app_uninstall(app_labels[i]);
479         result = app_install(app_labels[i]);
480         RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS, "Error in app_install.");
481
482         asprintf(&path, SMACK_RULES_DIR "/%s", app_labels[i]);
483         fd = open(path, O_WRONLY, 0644);
484         RUNNER_ASSERT_MSG(fd != -1, "Error in opening file " << path);
485
486         if (i == 1) {
487                 result = smack_accesses_add(rules,app_labels[i],TEST_OBJ,"wt");
488                 RUNNER_ASSERT_MSG(result == 0, "smack_accesses_add failed");
489         }
490         if (i == 2) {
491                 smack_accesses_free(rules);
492                 result = smack_accesses_new(&rules);
493                 result = smack_accesses_add(rules,app_labels[i],TEST_OBJ_SOME_OTHER,"wx");
494                 RUNNER_ASSERT_MSG(result == 0, "smack_accesses_add failed");
495         }
496         result = smack_accesses_apply(rules);
497         RUNNER_ASSERT_MSG(fd != -1, "smack_accesses_apply failed");
498
499         result = smack_accesses_save(rules, fd);
500         RUNNER_ASSERT_MSG(fd != -1, "smack_accesses_apply failed");
501
502         free(path);
503         close(fd);
504
505     }
506
507     smack_accesses_free(rules);
508
509     // THE TEST - accesses
510
511     result = add_shared_dir_readers(TEST_OBJ,app_labels);
512     RUNNER_ASSERT_MSG(result == 0, "add_shared_dir_readers failed");
513
514     result = smack_have_access(app_labels[0],TEST_OBJ,"rx");
515     RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
516
517     result = smack_have_access(app_labels[1],TEST_OBJ,"rx");
518     RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
519
520     result = smack_have_access(app_labels[2],TEST_OBJ,"rx");
521     RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
522
523     result = smack_have_access(app_labels[1],TEST_OBJ,"rwxt");
524     RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
525
526     result = smack_have_access(app_labels[2],TEST_OBJ_SOME_OTHER,"wx");
527     RUNNER_ASSERT_MSG(result == 1, "add_shared_dir_readers ERROR");
528
529
530     //TEST the operations on empty files
531
532     asprintf(&path, SMACK_RULES_DIR "/%s", app_labels[0]);
533     file = fopen(path, "r");
534
535     RUNNER_ASSERT_MSG(file, "fopen failed, errno:" << errno);
536
537     fgets(buf, READ_BUF_SIZE, file);
538     result = strcmp(buf, test_string_01);
539     RUNNER_ASSERT_MSG( result!=0, "add_shared_dir_readers ERROR, file not formatted" << path );
540
541     free(path);
542     fclose(file);
543
544     //TEST the operations on non empty files
545     asprintf(&path, SMACK_RULES_DIR "/%s", app_labels[2]);
546     file = NULL;
547     file = fopen(path, "r");
548     RUNNER_ASSERT_MSG(file, "fopen failed, errno:" << errno);
549
550     fgets(buf, READ_BUF_SIZE, file);
551     result = strcmp(buf, test_string_21);
552     RUNNER_ASSERT_MSG( result==0, "add_shared_dir_readers ERROR, file not formatted" );
553
554     fgets(buf, READ_BUF_SIZE, file);
555     result = strcmp(buf, test_string_22);
556     RUNNER_ASSERT_MSG( result==0, "add_shared_dir_readers ERROR, file not formatted" );
557
558     free(path);
559     fclose(file);
560 }
561
562
563 /**
564  * Set APP privileges.
565  */
566 RUNNER_CHILD_TEST(privilege_control05_set_app_privilege)
567 {
568     int result;
569
570     // Preset exec label
571     smack_lsetlabel(APP_SET_PRIV_PATH_REAL, APP_ID, SMACK_LABEL_EXEC);
572     smack_lsetlabel(APP_SET_PRIV_PATH, APP_ID "_symlink", SMACK_LABEL_EXEC);
573
574     // Set APP privileges
575     result = set_app_privilege(APP_ID, NULL, APP_SET_PRIV_PATH);
576     RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS, "Error in set_app_privilege. Error: " << result);
577
578     // Check if SMACK label really set
579     char * label;
580     result = smack_new_label_from_self(&label);
581     RUNNER_ASSERT_MSG(result == 0, "Error getting current process label");
582     RUNNER_ASSERT_MSG(label != NULL, "Process label is not set");
583     result = strcmp(APP_ID, label);
584     RUNNER_ASSERT_MSG(result == 0, "Process label " << label << " is incorrect");
585
586     // Check if DAC privileges really set
587     RUNNER_ASSERT_MSG(getuid() == APP_UID, "Wrong UID");
588     RUNNER_ASSERT_MSG(getgid() == APP_GID, "Wrong GID");
589
590     result = strcmp(getenv("HOME"), APP_HOME_DIR);
591     RUNNER_ASSERT_MSG(result == 0, "Wrong HOME DIR");
592
593     result = strcmp(getenv("USER"), APP_USER_NAME);
594     RUNNER_ASSERT_MSG(result == 0, "Wrong user USER NAME");
595
596     std::set<unsigned> groups_check;
597     read_gids(groups_check, LIBPRIVILEGE_APP_GROUP_LIST);
598     read_gids(groups_check, LIBPRIVILEGE_TEST_DAC_FILE);
599
600     int groups_cnt = getgroups(0, NULL);
601     RUNNER_ASSERT_MSG(groups_cnt > 0, "Wrong number of supplementary groupsCnt");
602     gid_t *groups_list = (gid_t *) calloc(groups_cnt, sizeof(gid_t));
603     RUNNER_ASSERT_MSG(groups_list != NULL, "Memory allocation failed");
604     getgroups(groups_cnt, groups_list);
605
606     for (int i = 0; i < groups_cnt; ++i) {
607         if (groups_check.erase(groups_list[i]) == 0) {
608             // getgroups() may also return process' main group
609             if (groups_list[i] == getgid())
610                 RUNNER_ASSERT_MSG(false, "Application belongs to unknown group (GID=" << groups_list[i] << ")");
611         }
612     }
613     std::string groups_left;
614     for (std::set<unsigned>::iterator it = groups_check.begin(); it != groups_check.end(); it++) {
615         groups_left.append(std::to_string(*it)).append(" ");
616     }
617     RUNNER_ASSERT_MSG(groups_check.empty(), "Application doesn't belong to some required groups: " << groups_left);
618 }
619
620 RUNNER_TEST(privilege_control08_app_give_access)
621 {
622     const char *subject = "lkjq345v34sfa";
623     const char *object = "lk9290f92lkjz";
624     smack_accesses *tmp = NULL;
625
626     RUNNER_ASSERT(0 == smack_accesses_new(&tmp));
627
628     std::unique_ptr<smack_accesses,std::function<void(smack_accesses*)>>
629         smack(tmp, smack_accesses_free);
630
631     RUNNER_ASSERT(0 == smack_accesses_add(smack.get(), subject, object, "r--a-"));
632     RUNNER_ASSERT(0 == smack_accesses_apply(smack.get()));
633
634     app_give_access(subject, object, "wt");
635
636     RUNNER_ASSERT(1 == smack_have_access(subject, object, "rwat"));
637     RUNNER_ASSERT(0 == smack_have_access(subject, object, "x"));
638
639     app_revoke_access(subject, object);
640
641     RUNNER_ASSERT(1 == smack_have_access(subject, object, "ra"));
642     RUNNER_ASSERT(0 == smack_have_access(subject, object, "w"));
643     RUNNER_ASSERT(0 == smack_have_access(subject, object, "x"));
644     RUNNER_ASSERT(0 == smack_have_access(subject, object, "t"));
645
646     RUNNER_ASSERT(0 == smack_accesses_add(smack.get(), subject, object, "-"));
647     RUNNER_ASSERT(0 == smack_accesses_apply(smack.get()));
648 }
649
650 /**
651  * Add new API feature
652  */
653 RUNNER_TEST(privilege_control09_add_api_feature)
654 {
655     int result;
656
657     remove_smack_files();
658
659
660     // argument validation
661     result = add_api_feature(APP_TYPE_OSP, NULL, NULL, NULL);
662     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
663
664     result = add_api_feature(APP_TYPE_OSP,"" , NULL, NULL);
665     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
666
667
668     // already existing features
669     result = add_api_feature(APP_TYPE_OSP,"messaging" , NULL, NULL);
670     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
671
672     result = add_api_feature(APP_TYPE_OSP,"blahblah/messaging" , NULL, NULL);
673     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
674
675     result = add_api_feature(APP_TYPE_WGT,"blahblahblah/messaging" , NULL, NULL);
676     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
677
678     result = add_api_feature(APP_TYPE_OTHER,"blah/messaging" , NULL, NULL);
679     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
680
681
682     // empty features
683     result = add_api_feature(APP_TYPE_OSP,"blahblah" , NULL, NULL);
684     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
685
686     result = add_api_feature(APP_TYPE_WGT,"blahblah" , NULL, NULL);
687     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
688
689     result = add_api_feature(APP_TYPE_OTHER,"blahblah" , NULL, NULL);
690     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
691
692
693     // smack files existence
694     result = file_exists(OSP_BLAHBLAH);
695     RUNNER_ASSERT(result == -1);
696
697     result = file_exists(WRT_BLAHBLAH);
698     RUNNER_ASSERT(result == -1);
699
700     result = file_exists(OTHER_BLAHBLAH);
701     RUNNER_ASSERT(result == -1);
702
703
704     // empty rules
705     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , { NULL }, NULL);
706     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
707     result = file_exists(OSP_BLAHBLAH);
708     RUNNER_ASSERT(result == -1);
709
710     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "", NULL }, NULL);
711     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
712     result = file_exists(OSP_BLAHBLAH);
713     RUNNER_ASSERT(result == 0);
714     remove_smack_files();
715
716     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ " \t\n", "\t \n", "\n\t  ", NULL }, NULL);
717     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
718     result = file_exists(OSP_BLAHBLAH);
719     RUNNER_ASSERT(result == 0);
720     remove_smack_files();
721
722
723     // malformed rules
724     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "malformed", NULL }, NULL);
725     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
726     result = file_exists(OSP_BLAHBLAH);
727     RUNNER_ASSERT(result == -1);
728
729     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "malformed malformed", NULL }, NULL);
730     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
731     result = file_exists(OSP_BLAHBLAH);
732     RUNNER_ASSERT(result == -1);
733
734     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "-malformed malformed rwxat", NULL }, NULL);
735     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
736     result = file_exists(OSP_BLAHBLAH);
737     RUNNER_ASSERT(result == -1);
738
739     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "~/\"\\\ malformed rwxat", NULL }, NULL);
740     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
741     result = file_exists(OSP_BLAHBLAH);
742     RUNNER_ASSERT(result == -1);
743
744     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "subject object rwxat something else", NULL }, NULL);
745     RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
746     result = file_exists(OSP_BLAHBLAH);
747     RUNNER_ASSERT(result == -1);
748
749
750     // correct rules
751     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "malformed malformed maaaaaalformed", NULL }, NULL);
752     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
753     osp_blahblah_check(__LINE__, { "malformed malformed r--a-" });
754     remove_smack_files();
755
756     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "subject object foo", NULL }, NULL);
757     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
758     osp_blahblah_check(__LINE__, { "subject object -----" });
759     remove_smack_files();
760
761     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){
762         "subject    object\t rwxat",
763         " \t \n",
764         "subject2\tobject2 txarw",
765         "",
766         NULL }, NULL);
767     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
768     osp_blahblah_check(__LINE__, { "subject object rwxat", "subject2 object2 rwxat"});
769     remove_smack_files();
770
771     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){
772         "Sub::jE,ct object a-RwX",
773         NULL }, NULL);
774     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
775     osp_blahblah_check(__LINE__, { "Sub::jE,ct object rwxa-"});
776     remove_smack_files();
777
778     // TODO For now identical/complementary rules are not merged.
779     result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){
780         "subject object rwxat",
781         " \t \n",
782         "subject object txarw",
783         "",
784         NULL }, NULL);
785     RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
786     osp_blahblah_check(__LINE__, { "subject object rwxat", "subject object rwxat"});
787     remove_smack_files();
788
789
790     // TODO database group ids
791 }
792
793 /*
794  * Check app_install function
795  */
796 RUNNER_TEST(privilege_control01_app_install)
797 {
798     int result;
799     char *path = NULL;
800     int fd = -1;
801
802     smack_file_name(APP_ID, &path);
803     unlink(path);
804
805     result = app_install(APP_ID);
806     RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
807
808     // checking if file really exists
809     fd = open(path, O_RDONLY);
810     RUNNER_ASSERT_MSG(fd >= 0, "File open failed: " << path << " : " << result << ". Errno: " << strerror(errno));
811     close(fd);
812     free(path);
813
814     // try install second time app with the same ID - it should failed with -1 (Errno: File exists).
815     result = app_install(APP_ID);
816     RUNNER_ASSERT_MSG(result == -1, "app_install returned " << result <<". Errno: " << strerror(errno));
817 }
818
819 /*
820  * Check app_install function
821  */
822 RUNNER_TEST(privilege_control07_app_uninstall)
823 {
824     int result;
825     char *path = NULL;
826     int fd = -1;
827
828     smack_file_name(APP_ID, &path);
829     result = app_uninstall(APP_ID);
830     RUNNER_ASSERT_MSG(result == 0, "app_uninstall returned " << result <<". Errno: " << strerror(errno));
831
832     // checking if file really exists
833     smack_file_name(APP_ID, &path);
834     fd = open(path, O_RDONLY);
835     RUNNER_ASSERT_MSG(fd == -1, "SMACK file NOT deleted after app_uninstall");
836     close(fd);
837     free(path);
838 }
839
840 /*
841  * Check app_register_av function
842  * Notice that this test case may have no sense if previous would fail (privilege_control06_app_install)
843  */
844 RUNNER_TEST(privilege_control10_app_register_av)
845 {
846     int result;
847     //FILE* file_av = NULL;
848     //FILE* file_app = NULL;
849     //int fd_app = -1;
850     int fd  = -1;
851     char *path = NULL;
852     char *buff;
853     int len;
854     int i;
855     //char label1[SMACK_LABEL_LEN +1];
856     //char label2[SMACK_LABEL_LEN +1];
857     //char acces_rights[6 +1];
858     //char row[2 * SMACK_LABEL_LEN + 20] //
859     const char* correct_antivirus1_rules = "test-antivirus1 test-application1 rwx--\n"
860                                             "test-antivirus1 test-application_2 rwx--\n"
861                                             "test-antivirus1 test-app-3 rwx--";
862     const char* correct_antivirus2_rules = "test-antivirus_2 test-application1 rwx--\n"
863                                            "test-antivirus_2 test-application_2 rwx--\n"
864                                            "test-antivirus_2 test-app-3 rwx--";
865
866     // cleaning
867     cleaning_smack_app_files();
868     cleaning_smack_database_files();
869
870     result = app_install(APP_TEST_APP_1);
871     RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
872
873     result = app_install(APP_TEST_APP_2);
874     RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
875
876     result = app_register_av(APP_TEST_AV_1);
877     RUNNER_ASSERT_MSG(result == 0, "app_register_av returned " << result <<". Errno: " << strerror(errno));
878
879     result = app_install(APP_TEST_APP_3);
880     RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
881
882     result = app_register_av(APP_TEST_AV_2);
883     RUNNER_ASSERT_MSG(result == 0, "app_register_av returned " << result <<". Errno: " << strerror(errno));
884
885     // checking rules for anti virus 1
886     // compare between file in /etc/smack/access.d/ and correct value (correct_antivirus1_rules).
887     len = strlen(correct_antivirus1_rules);
888     buff = (char *) malloc((len+1) * sizeof(char));
889     smack_file_name(APP_TEST_AV_1, &path);
890     fd = open(path, O_RDONLY);
891     free(path);
892     RUNNER_ASSERT_MSG(fd > -1, "file open failed " << result <<". Errno: " << strerror(errno));
893     result = read(fd, buff, len);
894     close(fd);
895     fd = -1;
896     buff[len] = '\0';
897     RUNNER_ASSERT_MSG(result > -1, "read from file descriptor failed. Errno: " << strerror(errno));
898     result = strncmp(buff, correct_antivirus1_rules, len);
899     RUNNER_ASSERT_MSG(result == 0, "Rules do not match: " << result << "\n\"" << buff << "\"\n\"" << correct_antivirus1_rules << "\"\n" << len);
900     free(buff);
901
902     // checking rules for anti virus 2
903     len = strlen(correct_antivirus2_rules);
904     buff = (char *) malloc((len+1) * sizeof(char));
905     smack_file_name(APP_TEST_AV_2, &path);
906     fd = open(path, O_RDONLY);
907     free (path);
908     RUNNER_ASSERT_MSG(fd > -1, "file open failed " << result <<". Errno: " << strerror(errno));
909     result = read(fd, buff, len);
910     close (fd);
911     fd = -1;
912     buff[len] = '\0';
913     RUNNER_ASSERT_MSG(result > -1, "read from file descriptor failed. Errno: " << strerror(errno));
914     result = strncmp(buff, correct_antivirus2_rules, len);
915     RUNNER_ASSERT_MSG(result == 0, "Rules do not match: " << result << "\n\"" << buff << "\"\n\"" << correct_antivirus1_rules << "\"\n" << len);
916     free(buff);
917
918     // cleaning
919     cleaning_smack_app_files();
920     cleaning_smack_database_files();
921 }