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