Adjust AccessProvider api to current security-server.
[platform/core/test/security-tests.git] / tests / libsmack-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      Pawel Polawski (p.polawski@samsung.com)
20  * @author      Jan Olszak (j.olszak@samsung.com)
21  * @author      Zofia Abramowska (z.abramowska@samsung.com)
22  * @version     1.0
23  * @brief       libsmack test runner
24  */
25
26 #include <string>
27 #include <sstream>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <dpl/test/test_runner.h>
31 #include <dpl/test/test_runner_multiprocess.h>
32 #include <dpl/log/log.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/mman.h>
36 #include <sys/smack.h>
37 #include <sys/xattr.h>
38 #include <sys/socket.h>
39 #include <sys/un.h>
40 #include <sys/file.h>
41 #include <sys/wait.h>
42 #include "tests_common.h"
43 #include <access_provider.h>
44 #include "memory.h"
45
46 const char* const TEST_SUBJECT = "test_subject";
47 const char* const TEST_OBJECT = "test_object";
48 const char* const TEST_OBJECT_2 = "test_object_2";
49
50 const std::string testDir = "/opt/home/app/";
51 const std::vector<std::string> accessesBasic = { "r", "w", "x", "wx", "rx", "rw", "rwx", "rwxat" };
52
53 //This one define is required for sockaddr_un initialization
54 #define SOCK_PATH "/tmp/test-smack-socket"
55
56 int files_compare(int fd1, int fd2)
57 {
58     //for getting files sizes
59     struct stat fs1, fs2;
60
61     //handlers for mmap()
62     void *h1 = MAP_FAILED;
63     void *h2 = MAP_FAILED;
64
65     //getting files information
66     RUNNER_ASSERT_MSG_BT(fstat(fd1, &fs1) == 0, "fstat failed: " << strerror(errno));
67     RUNNER_ASSERT_MSG_BT(fstat(fd2, &fs2) == 0, "fstat failed: " << strerror(errno));
68
69     if (fs1.st_size != fs2.st_size) //if files are identical size will be the same
70         return -1;
71
72     //mapping files to process memory
73     RUNNER_ASSERT_MSG_BT((h1 = mmap(0, fs1.st_size, PROT_READ, MAP_SHARED, fd1, 0 )) != MAP_FAILED,
74             "mmap failed for fd=" << fd1 << " : " << strerror(errno));
75
76     if ((h2 = mmap(0, fs2.st_size, PROT_READ, MAP_SHARED, fd2, 0 )) == MAP_FAILED) {
77         munmap(h1, fs1.st_size);
78         RUNNER_ASSERT_MSG_BT(h2 != MAP_FAILED, "mmap failed for fd=" << fd2
79                                                 << " : " << strerror(errno));
80     }
81
82     int result = memcmp(h1, h2, fs1.st_size);
83     munmap(h1, fs1.st_size);
84     munmap(h2, fs2.st_size);
85
86     return result;
87 }
88
89 RUNNER_TEST_GROUP_INIT(libsmack)
90 /**
91  * Helper method to reset privileges at the begginning of tests.
92  */
93 void clean_up()
94 {
95     smack_revoke_subject(TEST_SUBJECT);
96 }
97
98 /**
99  * Checking if subject has any access to object
100  */
101 bool checkNoAccesses(const char *subject, const char *object)
102 {
103     int result;
104     for(const auto &perm : std::vector<std::string> () = {"r", "w", "a","t", "l"}) {
105         result = smack_have_access(subject, object, perm.c_str());
106         if (result == 1) {
107             return false;
108         }
109     }
110     return true;
111 }
112
113 void removeAccessesAll()
114 {
115     for(int i = 1; i <=3; i++)
116         //smack_revoke_subject will fail, when subject does not exist in kernel
117         //as this function is called at test beginning we cannot check return value
118         smack_revoke_subject(("test_subject_0" + std::to_string(i)).c_str());
119 }
120
121 /**
122  * Add a new access with smack_accesses_add_modify()
123  */
124 RUNNER_TEST_SMACK(smack_accesses_add_modify_test_1){
125     int result;
126
127     clean_up();
128
129     struct smack_accesses *rules = NULL;
130     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
131     SmackAccessesPtr rules_ptr(rules);
132
133     // THE TEST
134     result = smack_accesses_add_modify(rules,TEST_SUBJECT, TEST_OBJECT,"xr","");
135     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add modify by empty rules");
136     RUNNER_ASSERT_MSG_BT(smack_accesses_apply(rules_ptr.get()) == 0, "Unable to apply rules");
137
138     result = smack_have_access(TEST_SUBJECT, TEST_OBJECT,"xr");
139     RUNNER_ASSERT_MSG_BT(result == 1, "Rule modified (added 'xr'), but no change made.");
140
141     // CLEAN UP
142     clean_up();
143 }
144
145
146 /**
147  * Test if rules are applied in the right order, and modification works.
148  */
149 RUNNER_TEST_SMACK(smack_accesses_add_modify_test_2){
150     int result;
151     struct smack_accesses *rules = NULL;
152     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
153     SmackAccessesPtr rules_ptr(rules);
154
155     clean_up();
156
157     // THE TEST
158     result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,"r","");
159     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify rule.");
160
161     result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,"","r");
162     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify rule.");
163
164     RUNNER_ASSERT_MSG_BT(smack_accesses_apply(rules_ptr.get()) == 0, "Unable to apply rules");
165     RUNNER_ASSERT_MSG_BT(smack_have_access(TEST_SUBJECT, TEST_OBJECT,"r") == 0,
166             "Modification didn't work");
167
168     // CLEAN UP
169     clean_up();
170 }
171
172
173 /**
174  * Test if rules are applied in the right order, and modification works.
175  * Using different smack_accesses list to add and delete.
176  */
177 RUNNER_TEST_SMACK(smack_accesses_add_modify_test_3){
178     int result;
179     struct smack_accesses *rules = NULL;
180     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
181     SmackAccessesPtr rules_ptr(rules);
182
183     clean_up();
184
185     // THE TEST
186     // Add r privilage
187     result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,"r","");
188     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify rule.");
189     RUNNER_ASSERT_MSG_BT(smack_accesses_apply(rules_ptr.get()) == 0, "Unable to apply rules");
190     RUNNER_ASSERT_MSG_BT(smack_have_access(TEST_SUBJECT, TEST_OBJECT,"r") == 1,
191             "Adding privileges didn't work");
192
193     // Revoke r privilege
194     rules_ptr.release();
195     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
196     rules_ptr.reset(rules);
197     result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,"","r");
198     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify rule.");
199     RUNNER_ASSERT_MSG_BT(smack_accesses_apply(rules_ptr.get()) == 0, "Unable to apply rules");
200
201     result = smack_have_access(TEST_SUBJECT, TEST_OBJECT,"r");
202     RUNNER_ASSERT_MSG_BT(result == 0, "Modification didn't work, rule has still 'r' privileges.");
203
204     // CLEAN UP
205     clean_up();
206 }
207
208 /**
209  * Add a list of privileges and then revoke just ONE of them.
210  */
211 RUNNER_TEST_SMACK(smack_accesses_add_modify_test_4){
212     int result;
213     struct smack_accesses *rules = NULL;
214     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
215     SmackAccessesPtr rules_ptr(rules);
216
217     clean_up();
218
219     // THE TEST
220     result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,"rwxat","");
221     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify rule.");
222     RUNNER_ASSERT_MSG_BT(smack_accesses_apply(rules_ptr.get()) == 0, "Unable to apply rules");
223
224     result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,"","r");
225     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify rule.");
226     RUNNER_ASSERT_MSG_BT(smack_accesses_apply(rules_ptr.get()) == 0, "Unable to apply rules");
227
228     result = smack_have_access(TEST_SUBJECT, TEST_OBJECT,"awxt");
229     RUNNER_ASSERT_MSG_BT(result == 1, "Modification didn't work. Rule should have 'awxt' privileges.");
230     result = smack_have_access(TEST_SUBJECT, TEST_OBJECT,"r");
231     RUNNER_ASSERT_MSG_BT(result != 1, "Modification didn't work. Rule should NOT have 'r' privilege.");
232
233     // CLEAN UP
234     clean_up();
235 }
236
237 /**
238  * Add a list of privileges and then revoke just ONE of them.
239  * Without applying privileges in between those actions.
240  */
241 RUNNER_TEST_SMACK(smack_accesses_add_modify_test_5){
242     int result;
243     struct smack_accesses *rules = NULL;
244     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
245     SmackAccessesPtr rules_ptr(rules);
246
247     clean_up();
248
249     // THE TEST
250     result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,"rwxat","");
251     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify rule.");
252
253     result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,"","r");
254     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify rule.");
255     RUNNER_ASSERT_MSG_BT(smack_accesses_apply(rules_ptr.get()) == 0, "Unable to apply rules");
256
257     result = smack_have_access(TEST_SUBJECT, TEST_OBJECT,"awxt");
258     RUNNER_ASSERT_MSG_BT(result == 1, "Modification didn't work. Rule should have 'awxt' privileges.");
259     result = smack_have_access(TEST_SUBJECT, TEST_OBJECT,"r");
260     RUNNER_ASSERT_MSG_BT(result != 1, "Modification didn't work. Rule should NOT have 'r' privilege.");
261
262     // CLEAN UP
263     clean_up();
264 }
265
266
267 /**
268  * Add a list of privileges and then revoke just TWO of them.
269  */
270 RUNNER_TEST_SMACK(smack_accesses_add_modify_test_6){
271     int result;
272     struct smack_accesses *rules = NULL;
273     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
274     SmackAccessesPtr rules_ptr(rules);
275
276     clean_up();
277
278     // THE TEST
279     result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,"rwt","");
280     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify rule.");
281     RUNNER_ASSERT_MSG_BT(smack_accesses_apply(rules_ptr.get()) == 0, "Unable to apply rules");
282
283     result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,"ax","rt");
284     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify rule.");
285     RUNNER_ASSERT_MSG_BT(smack_accesses_apply(rules_ptr.get()) == 0, "Unable to apply rules");
286
287     result = smack_have_access(TEST_SUBJECT, TEST_OBJECT,"wax");
288     RUNNER_ASSERT_MSG_BT(result == 1, "Modification didn't work. Rule should have 'wax' privileges.");
289     result = smack_have_access(TEST_SUBJECT, TEST_OBJECT,"r");
290     RUNNER_ASSERT_MSG_BT(result != 1, "Modification didn't work. Rule should NOT have 'r' privilege.");
291
292     // CLEAN UP
293     clean_up();
294 }
295
296 /**
297  * Run smack_accesses_add_modify with the same accesses_add and accesses_del.
298  */
299 RUNNER_TEST_SMACK(smack_accesses_add_modify_test_7){
300     unsigned int i;
301     int result;
302
303     struct smack_accesses *rules = NULL;
304
305     for (i = 0; i < accessesBasic.size(); ++i) {
306         RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
307         SmackAccessesPtr rules_ptr(rules);
308
309         result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,
310                 accessesBasic[i].c_str(), accessesBasic[i].c_str());
311         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify accesses instance");
312         RUNNER_ASSERT_MSG_BT(smack_accesses_apply(rules_ptr.get()) == 0, "Unable to apply rules");
313
314         RUNNER_ASSERT_MSG_BT(checkNoAccesses(TEST_SUBJECT, TEST_OBJECT),
315             " Error while checking smack access. Accesses exist.");
316
317         // CLEAN UP
318         clean_up();
319     }
320 }
321
322 /**
323  * Revoke subject with previously added rules and revoke it again.
324  */
325 RUNNER_TEST_SMACK(smack_revoke_subject_test_1){
326     unsigned int i;
327     int result;
328
329     struct smack_accesses *rules = NULL;
330
331     for (i = 0; i < accessesBasic.size(); ++i) {
332         // Creating and adding rules with TEST_OBJECT and TEST_OBJECT_2
333         RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
334         SmackAccessesPtr rules_ptr(rules);
335
336         result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,
337                 accessesBasic[i].c_str(),"");
338         result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT_2,
339                 accessesBasic[i].c_str(),"");
340         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify accesses instance");
341         RUNNER_ASSERT_MSG_BT(smack_accesses_apply(rules_ptr.get()) == 0, "Unable to apply rules");
342         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT,accessesBasic[i].c_str());
343         RUNNER_ASSERT_MSG_BT(result == 1, "Modification didn't work. "
344                 "Rule " << accessesBasic[i].c_str() << " does not exist.");
345         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT_2,accessesBasic[i].c_str());
346         RUNNER_ASSERT_MSG_BT(result == 1, "Modification didn't work. "
347                 "Rule " << accessesBasic[i].c_str() << " does not exist.");
348
349         // Revoking subject
350         result = smack_revoke_subject(TEST_SUBJECT);
351         RUNNER_ASSERT_MSG_BT(result == 0, "Revoking subject didn't work.");
352
353         RUNNER_ASSERT_MSG_BT(checkNoAccesses(TEST_SUBJECT, TEST_OBJECT),
354             " Revoke didn't work. Accesses exist.");
355         RUNNER_ASSERT_MSG_BT(checkNoAccesses(TEST_SUBJECT, TEST_OBJECT_2),
356             " Revoke didn't work. Accesses exist.");
357
358
359         // Revoking subject again
360         result = smack_revoke_subject(TEST_SUBJECT);
361         RUNNER_ASSERT_MSG_BT(result == 0, "Revoking subject didn't work.");
362
363         RUNNER_ASSERT_MSG_BT(checkNoAccesses(TEST_SUBJECT, TEST_OBJECT),
364             " Revoke didn't work. Accesses exist.");
365         RUNNER_ASSERT_MSG_BT(checkNoAccesses(TEST_SUBJECT, TEST_OBJECT_2),
366             " Revoke didn't work. Accesses exist.");
367
368     }
369 }
370
371 /**
372  * Clearing accesses
373  */
374 RUNNER_TEST_SMACK(smack_accesses_clear_test_1){
375     unsigned int i;
376     int result;
377
378     struct smack_accesses *rules = NULL;
379
380     for (i = 0; i < accessesBasic.size(); ++i) {
381         // Creating and adding rules with TEST_OBJECT and TEST_OBJECT_2
382         RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
383         SmackAccessesPtr rules_ptr(rules);
384         result = smack_accesses_add(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,
385                 accessesBasic[i].c_str());
386         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify accesses instance");
387         result = smack_accesses_add(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT_2,
388                 accessesBasic[i].c_str());
389         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify accesses instance");
390         RUNNER_ASSERT_MSG_BT(smack_accesses_apply(rules_ptr.get()) == 0, "Unable to apply rules");
391
392         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT,accessesBasic[i].c_str());
393         RUNNER_ASSERT_MSG_BT(result == 1, "Modification didn't work. Rule "
394                 << accessesBasic[i].c_str() << " does not exist.");
395         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT_2,accessesBasic[i].c_str());
396         RUNNER_ASSERT_MSG_BT(result == 1, "Modification didn't work. Rule "
397                 << accessesBasic[i].c_str() << " does not exist.");
398
399         // Creating and clearing rules with TEST_OBJECT
400         rules_ptr.release();
401         RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
402         rules_ptr.reset(rules);
403         result = smack_accesses_add(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,
404                 accessesBasic[i].c_str());
405         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify accesses instance");
406         result = smack_accesses_clear(rules_ptr.get());
407         RUNNER_ASSERT_MSG_BT(result == 0, "Clearing rules didn't work.");
408
409         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT,accessesBasic[i].c_str());
410         RUNNER_ASSERT_MSG_BT(result == 0, "Clearing rules didn't work. Rule "
411                 << accessesBasic[i].c_str() << " does exist.");
412         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT_2,accessesBasic[i].c_str());
413         RUNNER_ASSERT_MSG_BT(result == 1, "Clearing rules didn't work. Rule "
414                 << accessesBasic[i].c_str() << " does not exist.");
415
416         // Creating and clearing rules with TEST_OBJECT
417         rules_ptr.release();
418         RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
419         rules_ptr.reset(rules);
420
421         result = smack_accesses_add(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT_2,
422                 accessesBasic[i].c_str());
423         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify accesses instance");
424         result = smack_accesses_clear(rules_ptr.get());
425         RUNNER_ASSERT_MSG_BT(result == 0, "Clearing rules didn't work.");
426
427         RUNNER_ASSERT_MSG_BT(checkNoAccesses(TEST_SUBJECT, TEST_OBJECT),
428             " Clear didn't work. Accesses exist.");
429         RUNNER_ASSERT_MSG_BT(checkNoAccesses(TEST_SUBJECT, TEST_OBJECT_2),
430             " Clear didn't work. Accesses exist.");
431     }
432 }
433
434 RUNNER_TEST(smack01_storing_and_restoring_rules)
435 {
436     /*
437      * author: Pawel Polawski
438      * test: smack_accesses_new, smack_accesses_add, smack_accesses_add_modify, smack_accesses_add_from_file,
439      *       smack_accesses_free, smack_accesses_save
440      * description: This test case will create structure holding SMACK rules and add new one to it. Next rules will be
441      *              stored and restored from file.
442      * expect: Rules created and stored in file should be identical to predefined template.
443      */
444
445     struct smack_accesses *rules = NULL;        //rules prepared in this test case
446     struct smack_accesses *import_test = NULL;  //rules imported from file
447
448     int result;             //result of each operation to be tested by RUNNER_ASSERT
449     int fd, tmp, sample;    //file descripptors for save / restore rules tests
450
451     //int smack_accesses_new(struct smack_accesses **accesses);
452     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
453     SmackAccessesPtr rules_ptr(rules);
454     RUNNER_ASSERT_BT(smack_accesses_new(&import_test) == 0);
455     SmackAccessesPtr import_ptr(import_test);
456
457     //opening files
458     fd = open("/tmp/smack01_rules", O_RDWR | O_CREAT | O_TRUNC, 0644);  //for export prepared rules
459     RUNNER_ASSERT_MSG_BT(fd >= 0, "Unable to create /tmp/smack01_rules");
460     FdUniquePtr fd_ptr(&fd);
461     tmp = open("/tmp/smack01_tmp", O_RDWR | O_CREAT | O_TRUNC, 0644);   //for import rules exported before
462     RUNNER_ASSERT_MSG_BT(fd >= 0, "Unable to create /tmp/smack01_tmp");
463     FdUniquePtr tmp_ptr(&tmp);
464     sample = open("/etc/smack/test_smack_rules", O_RDONLY, 0644);             //reference preinstalled rules
465     RUNNER_ASSERT_MSG_BT(sample >= 0, "Unable to open /etc/smack/test_smack_rules");
466     FdUniquePtr sample_ptr(&sample);
467
468     result = smack_accesses_add(rules_ptr.get(), "writer", "book", "rw");
469     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add smack rules");
470     result = smack_accesses_add(rules_ptr.get(), "reader", "book", "wx");
471     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add smack rules");
472
473     result = smack_accesses_add_modify(rules_ptr.get(), "reader", "book", "r", "wx");
474     RUNNER_ASSERT_MSG_BT(0 == result, "Unable to modify smack rules");
475
476     result = smack_accesses_save(rules_ptr.get(), fd);
477     RUNNER_ASSERT_MSG_BT(0 == result, "Unable to save smack_accesses instance in file");
478
479     result = lseek(fd, 0, SEEK_SET);
480     RUNNER_ASSERT_MSG_BT(result == 0, "lseek() error");
481     result = smack_accesses_add_from_file(import_ptr.get(), fd);
482     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to import rules from file");
483
484     result = smack_accesses_save(import_ptr.get(), tmp);
485     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to save smack_accesses instance in file");
486
487     //comparing rules saved in file, restored from it and stored one more time
488     result = files_compare(fd, tmp);
489     RUNNER_ASSERT_MSG_BT(result == 0, "No match in stored and restored rules");
490
491     //comparing rules stored in file with reference preinstalled rules
492     result = files_compare(tmp, sample);
493     RUNNER_ASSERT_MSG_BT(result == 0, "No match in stored rules and pattern file");
494 }
495
496 RUNNER_TEST_SMACK(smack02_aplying_rules_into_kernel)
497 {
498     /*
499      * author: Pawel Polawski
500      * test: smack_accesses_apply, smack_have_access, smack_revoke_subject, smack_accesses_clear, smack_accesses_new,
501      *       smack_accesses_add, smack_accesses_free
502      * description: In this test case aplying rules to kernel will be tested. After that function for test
503      *              accesses will be used.
504      * expect: In case of correct rules access should be granted.
505      */
506
507     //CAP_MAC_ADMIN needed for process to be able to change rules in kernel (apllying, removing)
508
509     struct smack_accesses *rules = NULL;        //rules prepared in this test case
510     int result;                                 //for storing functions results
511
512     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
513     SmackAccessesPtr rules_ptr(rules);
514
515     //adding test rules to struct
516     result = smack_accesses_add(rules_ptr.get(), "writer", "book", "rwx");
517     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add smack rules");
518     result = smack_accesses_add(rules_ptr.get(), "reader", "book", "r");
519     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add smack rules");
520     result = smack_accesses_add(rules_ptr.get(), "spy", "book", "rwx");
521     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add smack rules");
522
523     result = smack_accesses_apply(rules_ptr.get());       //applying rules to kernel
524     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to apply rules into kernel");
525
526     //should have access - rule exist
527     result = smack_have_access("spy", "book", "rwx");
528     RUNNER_ASSERT_MSG_BT(result == 1, "Error while checking Smack access");
529     //should have no access - wrong rule, should be "r" only
530     result = smack_have_access("reader", "book", "rwx");
531     RUNNER_ASSERT_MSG_BT(result == 0, "Error while checking Smack access");
532     //should fail - rule not exist
533     result = smack_have_access("s02badsubjectlabel", "book", "rwx");
534     RUNNER_ASSERT_MSG_BT(result == -1, "Error while checking Smack access");
535
536     //this subject do not exist in kernel rules
537     result = smack_revoke_subject("s02nonexistinglabel");
538     RUNNER_ASSERT_MSG_BT(result == 0, "Error in removing not existing subject from kernel");
539     result = smack_revoke_subject("spy");       //this subject exist in kernel rules
540     RUNNER_ASSERT_MSG_BT(result == 0, "Error in removing existing subject from kernel");
541
542     //testing access after revoke_subject() from kernel
543     result = smack_have_access("spy", "book", "rwx");
544     //now spy should have no access
545     RUNNER_ASSERT_MSG_BT(result == 0, "Error in acces aplied to kernel");
546
547     //for create new rule as a consequence of use accesses_clear() below
548     result = smack_accesses_add(rules_ptr.get(), "s02subjectlabel", "book", "rwx");
549     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add smack rules");
550
551     //"spy" removed before by using smack_revoke_subject()
552     result = smack_accesses_clear(rules_ptr.get());
553     RUNNER_ASSERT_MSG_BT(result == 0, "Error in clearing rules in kernel");
554
555     //testing acces after acces_clear()
556     result = smack_have_access("writer", "book", "rwx");
557     //now writer also should have no access
558     RUNNER_ASSERT_MSG_BT(result == 0, "Error in acces aplied to kernel");
559
560 }
561
562 //pairs of rules for test with mixed cases, different length and mixed order
563 std::vector< std::vector<std::string> > correct_rules = {
564     { "reader1",  "-",                "------" },
565     { "reader2",  "--------",         "------" },
566     { "reader3",  "RwXaTl",           "rwxatl" },
567     { "reader4",  "RrrXXXXTTT",       "r-x-t-" },
568     { "reader5",  "-r-w-a-t-",        "rw-at-" },
569     { "reader6",  "",                 "------" },
570     { "reader7",  "xa--Rt---W--L",    "rwxatl" },
571 };
572
573 RUNNER_TEST_SMACK(smack03_mixed_rule_string_add)
574 {
575     /*
576      * author: Pawel Polawski
577      * test: smack_have_access, smack_accesses_new, smack_accesses_add, smack_accesses_apply, smack_accesses_free
578      * description: In thist test case rules based on mixed string are added to kernel.
579      *              Strings are presented above and contains lower / upper case alpha, numbers and special signs.
580      * expect: Rules should be parsed correct and aplied to kernel.
581      */
582
583     //In thist test case mixed string are used as rules applied to kernel, next they are
584     //readed and compared with correct form of rules
585
586     struct smack_accesses *rules = NULL;        //rules prepared in this test case
587     int result;                                 //for storing functions results
588     int expected;
589
590     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
591     SmackAccessesPtr rules_ptr(rules);
592
593     //adding test rules with mixed string
594     for (auto rule=correct_rules.begin(); rule != correct_rules.end(); ++rule) {
595         //using mixed rules from table
596         result = smack_accesses_add(rules_ptr.get(),
597                                     (*rule)[0].c_str(),
598                                     "book",
599                                     (*rule)[1].c_str());
600         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add smack rules");
601     }
602
603     //clearing
604     //FIXME: Using clear() here can cover error in accesses_apply() function
605     //result = smack_accesses_clear(rules);
606     //RUNNER_ASSERT_MSG_BT(result == 0, "Error in clearing rules in kernel");
607
608     //applying rules to kernel
609     result = smack_accesses_apply(rules_ptr.get());
610     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to apply rules into kernel");
611
612     //checking accesses using normal rules
613     for (auto rule=correct_rules.begin(); rule != correct_rules.end(); ++rule) {
614         if ((*rule)[2] == "------")
615             expected = 0;
616         else
617             expected = 1;
618         //using normal rules from table
619         result = smack_have_access((*rule)[0].c_str(),
620                                    "book",
621                                    (*rule)[2].c_str());
622         RUNNER_ASSERT_MSG_BT(result == expected, "Error while checking Smack access");
623     }
624 }
625
626 RUNNER_TEST_SMACK(smack04_mixed_rule_string_have_access)
627 {
628     /*
629      * author: Pawel Polawski
630      * test: smack_have_access
631      * description: In this test case we testing aplied before SMACK rules and comparing them using mixed strings.
632      * expect: Subjects should have accesses to the objects.
633      */
634
635     //In this test case we checking previous aplied rules but for compare mixed strings are used
636
637     int result;
638     int expected;
639
640     //rules were added in previous RUNNER_TEST section
641     //checking accesses using mixed rules
642     for (auto rule=correct_rules.begin(); rule != correct_rules.end(); ++rule) {
643         if ((*rule)[2] == "------")
644             expected = 0;
645         else
646             expected = 1;
647         //using mixed rules from table
648         result = smack_have_access((*rule)[0].c_str(),
649                                    "book",
650                                    (*rule)[1].c_str());
651         RUNNER_ASSERT_MSG_BT(result == expected, "Error while checking Smack access");
652     }
653 }
654
655 //RUNNER_TEST(smackXX_accesses_add_modify)
656 //{
657 //IDEAS FOR TESTS
658 // - what if we want to apply rule that is already in kernel?
659 // - tests for smack_accesses_add_modify() + smack_have_access() (check if add_modify sets the proper rule)
660 // - smack_accesses_add_modify("subject", "object", "rwx", "rwx") should create empty rule
661 //}
662
663 RUNNER_TEST_SMACK(smack05_self_label)
664 {
665     /*
666      * author: Pawel Polawski
667      * test: smack_set_label_for_self, smack_new_label_from_self
668      * description: In this test case process test it own default label. Next label is changed
669      *              and tested one more time if change was successfull.
670      * expect: Proces should have default "-" label and can change it to the oter one.
671      */
672
673     //In this test case process will manipulate it own label
674
675     char *label = NULL;
676     int result;
677     int fd;
678
679     const int B_SIZE = 8;
680     char buff[B_SIZE];
681
682     const char *def_rule = "_";
683
684     result = smack_new_label_from_self(&label);
685     RUNNER_ASSERT_MSG_BT(result >= 0, "Error in getting self label");
686     //comparing this label with default one "_"
687     result = strcmp(label, def_rule);
688     free(label);
689     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong default process label");
690
691     //comparing this rule with received from /proc/self/attr/current
692     fd = open("/proc/self/attr/current", O_RDONLY, 0644);
693     RUNNER_ASSERT_MSG_BT(fd >= 0, "Unable to open /proc/self/attr/current");
694     FdUniquePtr fd_ptr(&fd);
695     result = read(fd, buff, B_SIZE);
696     RUNNER_ASSERT_MSG_BT(result >= 0, "Error in reading from file /proc/self/attr/current");
697     result = strncmp(buff, def_rule, result);
698     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong default process rule");
699
700     //now time for setting labels:
701
702     result = smack_set_label_for_self("cola");
703     RUNNER_ASSERT_MSG_BT(result == 0, "Error in setting self label");
704
705     //checking new label using smack function
706     result = smack_new_label_from_self(&label);
707     RUNNER_ASSERT_MSG_BT(result >= 0, "Error in getting self label");
708     result = strcmp(label, "cola");
709     free(label);
710     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong process label");
711
712     //checking new label using /proc/self/attr/current
713     result = lseek(fd, 0, SEEK_SET);    //going to the file beginning
714     RUNNER_ASSERT_MSG_BT(result == 0, "lseek() error");
715     result = read(fd, buff, B_SIZE);
716     RUNNER_ASSERT_MSG_BT(result >= 0, "Error in reading from file /proc/self/attr/current");
717     result = strncmp(buff, "cola", result);
718     RUNNER_ASSERT_MSG_BT(result == 0, "Proces rule in /proc/self/attr/current other than set");
719 }
720
721 //RUNNER_TEST(smackXX_parent_child_label)
722 //{
723 //In this test case parent process and child labels will be tested
724 //Parent will fork and check child's label. First fork will be with default "_" parent label,
725 //second one witch changed label.
726 //}
727
728 //bellow function is from libsmack.c witch changed name
729 const char *xattr(enum smack_label_type type)
730 {
731     switch (type) {
732         case SMACK_LABEL_ACCESS:
733             return "security.SMACK64";
734         case SMACK_LABEL_EXEC:
735             return "security.SMACK64EXEC";
736         case SMACK_LABEL_MMAP:
737             return "security.SMACK64MMAP";
738         case SMACK_LABEL_TRANSMUTE:
739             return "security.SMACK64TRANSMUTE";
740         case SMACK_LABEL_IPIN:
741             return "security.SMACK64IPIN";
742         case SMACK_LABEL_IPOUT:
743             return "security.SMACK64IPOUT";
744         default:
745             /*  Should not reach this point */
746             return NULL;
747     }
748 }
749
750 //TODO: In bellow RUNNER_TEST add  lget / lset functions to be testet the same way as normal get / set
751 RUNNER_TEST(smack06_get_set_label)
752 {
753     /*
754      * author: Pawel Polawski
755      * test: smack_getlabel, smack_setlabel
756      * description: In this test case file label is tested using SMACK API functions and system xattr functions.
757      *              Functions tested here is used for normal files.
758      * expect: Function should return default label, and the new one after change it.
759      */
760
761     //In this test case will be tested setting and getting file label
762     //If file is symbolic link functions should follow it
763
764     //SMACK xattr from libsmack.c:
765     //
766     //case SMACK_LABEL_ACCESS:
767     //    return "security.SMACK64";
768     //case SMACK_LABEL_EXEC:
769     //    return "security.SMACK64EXEC";
770     //case SMACK_LABEL_MMAP:
771     //    return "security.SMACK64MMAP";
772     //case SMACK_LABEL_TRANSMUTE:
773     //    return "security.SMACK64TRANSMUTE";
774     //case SMACK_LABEL_IPIN:
775     //    return "security.SMACK64IPIN";
776     //case SMACK_LABEL_IPOUT:
777     //    return "security.SMACK64IPOUT";
778
779     int result;
780     char *label = NULL;
781
782     char buff[SMACK_LABEL_LEN+1];
783     const char* s06testlabel = "s06testlabel";
784     const char *file_path = "/etc/smack/test_smack_rules";
785
786     //preparing environment by restoring default "_" label
787     result = smack_setlabel(file_path, "_", SMACK_LABEL_ACCESS);
788     RUNNER_ASSERT_MSG_BT(result == 0, "Error in setting ACCESS label for file");
789
790     result = smack_getlabel(file_path, &label, SMACK_LABEL_ACCESS);
791     RUNNER_ASSERT_MSG_BT(result == 0, "Error in getting smack ACCESS label from file");
792     //get label, should be default "_"
793     result = strcmp(label, "_");
794     free(label);
795     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong file default label");
796
797     //get label using xattr function
798     result = getxattr(file_path, xattr(SMACK_LABEL_ACCESS), buff, SMACK_LABEL_LEN);
799     RUNNER_ASSERT_MSG_BT(result > 0, "Error in getting xattr from file");
800     //check label, should match the one readed by smack function
801     result = strncmp(buff, "_", result);
802     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong file default label");
803
804     result = smack_setlabel(file_path, s06testlabel, SMACK_LABEL_ACCESS);
805     RUNNER_ASSERT_MSG_BT(result == 0, "Error in setting ACCESS label for file");
806
807     //get label using smack function
808     result = smack_getlabel(file_path, &label, SMACK_LABEL_ACCESS);
809     RUNNER_ASSERT_MSG_BT(result == 0, "Error in getting smack ACCESS label from file");
810     //get label, should be default s06testlabel
811     result = strcmp(label, s06testlabel);
812     free(label);
813     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong file label");
814
815     //get label using xattr function
816     result = getxattr(file_path, xattr(SMACK_LABEL_ACCESS), buff, SMACK_LABEL_LEN);
817     RUNNER_ASSERT_MSG_BT(result > 0, "Error in getting xattr from file");
818     //check label, should match the one readed by smack function
819     result = strncmp(buff, s06testlabel, result);
820     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong file label");
821 }
822
823 //RUNNER_TEST(smackXX_get_label_exec)
824 //{
825 //In this test case EXEC label will be tested
826 //by setting this type of label, reading it and testing executed binary exit status
827 //}
828
829 RUNNER_TEST(smack07_l_get_set_label)
830 {
831     /*
832      * author: Pawel Polawski
833      * test: smack_lgetlabel, smack_lsetlabel, smack_getlabel
834      * description: Functions tested here are similar to one from previous test case. The difference
835      *              is that in case of symbolic link they follows it and operates on file pointed by it.
836      * expect: All label manipulations should affect file pointed by symbolic link.
837      */
838
839     int result;
840     char *label = NULL;
841
842     char buff[SMACK_LABEL_LEN+1];
843     const char* s07testlabel1 = "s07testlabel1";
844     const char* s07testlabel2 = "s07testlabel2";
845
846     const char *file_path = "/etc/smack/test_smack_rules_lnk";
847
848     //preparing environment by restoring default "_" label
849     result = smack_lsetlabel(file_path, "_", SMACK_LABEL_ACCESS);
850     RUNNER_ASSERT_MSG_BT(result == 0, "Error in setting ACCESS label for file");
851     result = smack_setlabel(file_path, "_", SMACK_LABEL_ACCESS);
852     RUNNER_ASSERT_MSG_BT(result == 0, "Error in setting ACCESS label for file");
853
854     result = smack_lgetlabel(file_path, &label, SMACK_LABEL_ACCESS);
855     RUNNER_ASSERT_MSG_BT(result == 0, "Error in getting smack ACCESS label from file");
856     //get label of symbolic link, should be default "_"
857     result = strcmp(label, "_");
858     free(label);
859     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong file default label");
860
861     //get label using xattr function
862     result = lgetxattr(file_path, xattr(SMACK_LABEL_ACCESS), buff, SMACK_LABEL_LEN);
863     RUNNER_ASSERT_MSG_BT(result > 0, "Error in getting xattr from file");
864     //check label, should match the one readed by smack function
865     result = strncmp(buff, "_", result);
866     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong file default label");
867
868     result = smack_lsetlabel(file_path, s07testlabel1, SMACK_LABEL_ACCESS);
869     RUNNER_ASSERT_MSG_BT(result == 0, "Error in setting ACCESS label for file");
870     //and set label for file pointed by link
871     result = smack_setlabel(file_path, s07testlabel2, SMACK_LABEL_ACCESS);
872     RUNNER_ASSERT_MSG_BT(result == 0, "Error in setting ACCESS label for file");
873
874     //get label using smack function
875     result = smack_lgetlabel(file_path, &label, SMACK_LABEL_ACCESS);
876     RUNNER_ASSERT_MSG_BT(result == 0, "Error in getting smack ACCESS label from file");
877     //check label, should be s07testlabel1
878     result = strcmp(label, s07testlabel1);
879     free(label);
880     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong file label");
881
882     //get label using xattr function
883     result = lgetxattr(file_path, xattr(SMACK_LABEL_ACCESS), buff, SMACK_LABEL_LEN);
884     RUNNER_ASSERT_MSG_BT(result > 0, "Error in getting xattr from file");
885     //check label, should match the one readed by smack function
886     result = strncmp(buff, s07testlabel1, result);
887     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong file label");
888
889     //now similar to above, but folowing symbolic link set before to s07testlabel2
890     result = smack_getlabel(file_path, &label, SMACK_LABEL_ACCESS);
891     RUNNER_ASSERT_MSG_BT(result == 0, "Error gettin label of file pointed by symbolic link");
892     //now label should be s07testlabel2 for file instead of s07testlabel1 set for link
893     result = strcmp(label, s07testlabel2);
894     free(label);
895     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong label of file pointed by symbolic link");
896
897     //get label using xattr function
898     result = getxattr(file_path, xattr(SMACK_LABEL_ACCESS), buff, SMACK_LABEL_LEN);
899     RUNNER_ASSERT_MSG_BT(result > 0, "Error in getting xattr from file");
900     //check label, should match the one readed by smack function
901     result = strncmp(buff, s07testlabel2, result);
902     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong file label");
903 }
904
905 RUNNER_TEST(smack08_f_get_set_label)
906 {
907     /*
908      * author: Pawel Polawski
909      * test: smack_fgetlabel, smack_fsetlabel
910      * description: This test case is similar to test case smack06 above. The difference
911      *              is that argument is file descriptor instead of file path.
912      *              Function not follow symbolic link and operates directly on it.
913      * expect: All label manipulations should affect symbolic link itself.
914      */
915
916     int result;
917     char *label = NULL;
918
919     char buff[SMACK_LABEL_LEN+1];
920     const char* s08testlabel = "s08testlabel";
921
922     int fd;
923     const char *file_path = "/etc/smack/test_smack_rules";
924
925     fd = open(file_path, O_RDWR, 0644);             //reference preinstalled rules
926     RUNNER_ASSERT_MSG_BT(fd >= 0, "Unable to open /etc/smack/test_smack_rules");
927     FdUniquePtr fd_ptr(&fd);
928
929     //preparing environment by restoring default "_" label
930     result = smack_fsetlabel(fd, "_", SMACK_LABEL_ACCESS);
931     RUNNER_ASSERT_MSG_BT(result == 0, "Error in setting ACCESS label for file");
932
933     result = smack_fgetlabel(fd, &label, SMACK_LABEL_ACCESS);
934     RUNNER_ASSERT_MSG_BT(result == 0, "Error in getting smack ACCESS label from file");
935     //check label, should be "_"
936     result = strcmp(label, "_");
937     free(label);
938     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong file default label");
939
940     //get label using xattr function
941     result = fgetxattr(fd, xattr(SMACK_LABEL_ACCESS), buff, SMACK_LABEL_LEN);
942     RUNNER_ASSERT_MSG_BT(result > 0, "Error in getting xattr from file");
943     //check label, should match the one readed by smack function
944     result = strncmp(buff, "_", result);
945     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong file default label");
946
947     result = smack_fsetlabel(fd, s08testlabel, SMACK_LABEL_ACCESS);
948     RUNNER_ASSERT_MSG_BT(result == 0, "Error in setting ACCESS label for file");
949
950     //get label using smack function
951     result = smack_fgetlabel(fd, &label, SMACK_LABEL_ACCESS);
952     RUNNER_ASSERT_MSG_BT(result == 0, "Error in getting smack ACCESS label from file");
953     //check label, should be s08testlabel
954     result = strcmp(label, s08testlabel);
955     free(label);
956     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong file label");
957
958     //get label using xattr function
959     result = fgetxattr(fd, xattr(SMACK_LABEL_ACCESS), buff, SMACK_LABEL_LEN);
960     RUNNER_ASSERT_MSG_BT(result > 0, "Error in getting xattr from file");
961     //check label, should match the one readed by smack function
962     result = strncmp(buff, s08testlabel, result);
963     RUNNER_ASSERT_MSG_BT(result == 0, "Wrong file label");
964 }
965
966 RUNNER_TEST_SMACK(smack10_adding_removing_rules)
967 {
968     unsigned int i;
969     int result;
970
971     struct smack_accesses *rules = NULL;
972
973     for (i = 0; i < accessesBasic.size(); ++i)
974     {
975         // Creating rules
976         RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
977         SmackAccessesPtr rules_ptr(rules);
978
979         // Adding accesses
980         result = smack_accesses_add(rules_ptr.get(), TEST_SUBJECT, TEST_OBJECT, accessesBasic[i].c_str());
981         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add modify rulesBasic. Result: " << result);
982
983         // Applying rules
984         result = smack_accesses_apply(rules_ptr.get());
985         RUNNER_ASSERT_MSG_BT(result == 0, "Error while applying accesses. Result: " << result);
986
987         // Checking if accesses were created
988         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT, accessesBasic[i].c_str());
989         RUNNER_ASSERT_MSG_BT(result == 1,
990             " Error while checking smack access. Result: " << result);
991
992         // Deleting all rules
993         clean_up();
994     }
995
996     for (i = 0; i < 3; ++i)
997     {
998         // --- Creating rules (r or w or x)
999         RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
1000         SmackAccessesPtr rules_ptr(rules);
1001
1002         // Adding accesses
1003         result = smack_accesses_add(rules_ptr.get(), TEST_SUBJECT, TEST_OBJECT, accessesBasic[i].c_str());
1004         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add rulesBasic. Result: " << result);
1005
1006         // Applying rules
1007         result = smack_accesses_apply(rules_ptr.get());
1008         RUNNER_ASSERT_MSG_BT(result == 0, "Error while applying accesses. Result: " << result);
1009         // Checking if accesses were created
1010         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT, accessesBasic[i].c_str());
1011         RUNNER_ASSERT_MSG_BT(result == 1,
1012             " Error while checking smack access. Result: " << result);
1013
1014         // Checking if wrong accesses were not created
1015         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT, accessesBasic[i + 3].c_str());
1016         RUNNER_ASSERT_MSG_BT(result == 0,
1017             " Error while checking smack access. Result: " << result);
1018
1019         // --- Modifying accesses (r for wx or w for rx or x for rw)
1020         result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,
1021                 accessesBasic[i + 3].c_str(),accessesBasic[i].c_str());
1022         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add modify rulesBasic. Result: " << result);
1023
1024         // Applying rules
1025         result = smack_accesses_apply(rules_ptr.get());
1026         RUNNER_ASSERT_MSG_BT(result == 0, "Error while applying accesses. Result: " << result);
1027
1028         // Checking if accesses were created
1029         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT, accessesBasic[i + 3].c_str());
1030         RUNNER_ASSERT_MSG_BT(result == 1,
1031             " Error while checking smack access. Result: " << result);
1032
1033         // Checking if wrong accesses were not created
1034         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT, accessesBasic[i].c_str());
1035         RUNNER_ASSERT_MSG_BT(result == 0,
1036             " Error while checking smack access. Result: " << result);
1037
1038         rules_ptr.release();
1039         // --- Creating complementary rules (r or w or x)
1040         RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
1041         rules_ptr.reset(rules);
1042
1043         // Adding accesses
1044         result = smack_accesses_add(rules_ptr.get(), TEST_SUBJECT, TEST_OBJECT,
1045                 accessesBasic[i].c_str());
1046         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add rulesBasic. Result: " << result);
1047
1048         // Checking if accesses were created
1049         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT, accessesBasic[i + 3].c_str());
1050         RUNNER_ASSERT_MSG_BT(result == 1,
1051             " Error while checking smack access. Result: " << result);
1052
1053         // Applying rules
1054         result = smack_accesses_apply(rules_ptr.get());
1055         RUNNER_ASSERT_MSG_BT(result == 0, "Error while applying accesses. Result: " << result);
1056
1057         // Checking if accesses were created
1058         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT, accessesBasic[i].c_str());
1059         RUNNER_ASSERT_MSG_BT(result == 1,
1060             " Error while checking smack access. Result: " << result);
1061
1062         // --- Modifying accesses (adding rwx and removing r or w or x)
1063         result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,"rwx",
1064                 accessesBasic[i].c_str());
1065         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add modify rulesBasic. Result: " << result);
1066
1067         // Applying rules
1068         result = smack_accesses_apply(rules_ptr.get());
1069         RUNNER_ASSERT_MSG_BT(result == 0, "Error while applying accesses. Result: " << result);
1070
1071         // Checking if accesses were created
1072         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT, accessesBasic[i + 3].c_str());
1073         RUNNER_ASSERT_MSG_BT(result == 1,
1074             " Error while checking smack access. Result: " << result);
1075
1076         // Checking if wrong accesses were not created
1077         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT, accessesBasic[i].c_str());
1078         RUNNER_ASSERT_MSG_BT(result == 0,
1079             " Error while checking smack access. Result: " << result);
1080
1081         // --- Adding crossing accesses (rx or rw or wx)
1082         result = smack_accesses_add_modify(rules_ptr.get(),TEST_SUBJECT, TEST_OBJECT,
1083                 accessesBasic[3 + ((i + 1) % 3)].c_str(),"");
1084         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add modify rulesBasic. Result: " << result);
1085
1086         // Applying rules
1087         result = smack_accesses_apply(rules_ptr.get());
1088         RUNNER_ASSERT_MSG_BT(result == 0, "Error while applying accesses. Result: " << result);
1089
1090         // Checking if accesses were created
1091         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT,
1092                 accessesBasic[3 + ((i + 1) % 3)].c_str());
1093         RUNNER_ASSERT_MSG_BT(result == 1,
1094             " Error while checking smack access. Result: " << result);
1095
1096         result = smack_have_access(TEST_SUBJECT, TEST_OBJECT, "rwx");
1097         RUNNER_ASSERT_MSG_BT(result == 1,
1098             " Error while checking smack access. Result: " << result);
1099
1100         // Deleting all rules
1101         result = smack_accesses_add_modify(rules,TEST_SUBJECT, TEST_OBJECT,"","rwx");
1102         RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add modify rulesBasic. Result: " << result);
1103
1104         result = smack_accesses_apply(rules_ptr.get());
1105         RUNNER_ASSERT_MSG_BT(result == 0, "Error while checking smack access. Result: " << result);
1106
1107         // Deleting all rules
1108         clean_up();
1109     }
1110 }
1111
1112 RUNNER_TEST_SMACK(smack11_saving_loading_rules)
1113 {
1114     int result;
1115     int fd;
1116
1117     struct smack_accesses *rules = NULL;
1118
1119     // Pre-cleanup
1120     removeAccessesAll();
1121
1122     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
1123     SmackAccessesPtr rules_ptr(rules);
1124
1125     // Loading file with rwxat rules - test_smack_rules_full
1126     fd = open("/etc/smack/test_smack_rules_full", O_RDONLY, 0644);
1127     RUNNER_ASSERT_MSG_BT(fd >= 0, "Unable to open /etc/smack/test_smack_rules_full");
1128
1129     // Adding rules from file
1130     result = smack_accesses_add_from_file(rules_ptr.get(), fd);
1131     close(fd);
1132     RUNNER_ASSERT_MSG_BT(result == 0, "Error importing accesses from file");
1133
1134     // Applying rules
1135     result = smack_accesses_apply(rules_ptr.get());
1136     RUNNER_ASSERT_MSG_BT(result == 0, "Error while applying accesses. Result: " << result);
1137
1138     // Checking rules
1139     result = smack_have_access("test_subject_01", "test_object_02", "rwxat");
1140     RUNNER_ASSERT_MSG_BT(result == 1,
1141         " Error while checking smack accesses.");
1142     result = smack_have_access("test_subject_01", "test_object_03", "rwxat");
1143     RUNNER_ASSERT_MSG_BT(result == 1,
1144         " Error while checking smack accesses.");
1145     result = smack_have_access("test_subject_02", "test_object_01", "rwxat");
1146     RUNNER_ASSERT_MSG_BT(result == 1,
1147         " Error while checking smack accesses.");
1148     result = smack_have_access("test_subject_02", "test_object_02", "rwxat");
1149     RUNNER_ASSERT_MSG_BT(result == 1,
1150         " Error while checking smack accesses.");
1151     result = smack_have_access("test_subject_02", "test_object_03", "rwxat");
1152     RUNNER_ASSERT_MSG_BT(result == 1,
1153         " Error while checking smack accesses.");
1154     result = smack_have_access("test_subject_03", "test_object_01", "rwxat");
1155     RUNNER_ASSERT_MSG_BT(result == 1,
1156         " Error while checking smack accesses.");
1157     result = smack_have_access("test_subject_03", "test_object_02", "rwxat");
1158     RUNNER_ASSERT_MSG_BT(result == 1,
1159         " Error while checking smack accesses.");
1160     result = smack_have_access("test_subject_03", "test_object_03", "rwxat");
1161     RUNNER_ASSERT_MSG_BT(result == 1,
1162         " Error while checking smack accesses.");
1163
1164     // Removing rules
1165     removeAccessesAll();
1166
1167     // Creating rules
1168     rules_ptr.release();
1169     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
1170     rules_ptr.reset(rules);
1171
1172     // Loading file with partial wrong rules - test_smack_rules2
1173     fd = open("/etc/smack/test_smack_rules2", O_RDONLY, 0644);
1174     RUNNER_ASSERT_MSG_BT(fd >= 0, "Unable to open /etc/smack/test_smack_rules2");
1175
1176     // Adding rules from file
1177     result = smack_accesses_add_from_file(rules_ptr.get(), fd);
1178     close(fd);
1179     RUNNER_ASSERT_MSG_BT(result == 0, "Error importing accesses from file");
1180
1181     // Applying rules
1182     result = smack_accesses_apply(rules_ptr.get());
1183     RUNNER_ASSERT_MSG_BT(result == 0, "Error while applying accesses. Result: " << result);
1184
1185     // Checking rules
1186     RUNNER_ASSERT_MSG_BT(checkNoAccesses("test_subject_01", "test_object_01"),
1187         " Error while checking smack access loaded from /etc/smack/test_smack_rules2. Accesses exist.");
1188     result = smack_have_access("test_subject_01", "test_object_02", "rwatl");
1189     RUNNER_ASSERT_MSG_BT(result == 1,
1190         " Error while checking smack access loaded from /etc/smack/test_smack_rules2. Result: " << result );
1191     result = smack_have_access("test_subject_01", "test_object_03", "wat");
1192     RUNNER_ASSERT_MSG_BT(result == 1,
1193         " Error while checking smack access loaded from /etc/smack/test_smack_rules2. Result: " << result );
1194     RUNNER_ASSERT_MSG_BT(checkNoAccesses("test_subject_02", "test_object_01"),
1195         " Error while checking smack access loaded from /etc/smack/test_smack_rules2. Accesses exist.");
1196     result = smack_have_access("test_subject_02", "test_object_02", "wa-lt");
1197     RUNNER_ASSERT_MSG_BT(result == 1,
1198         " Error while checking smack access loaded from /etc/smack/test_smack_rules2. Result: " << result );
1199     result = smack_have_access("test_subject_02", "test_object_03", "wr");
1200     RUNNER_ASSERT_MSG_BT(result == 1,
1201         " Error while checking smack access loaded from /etc/smack/test_smack_rules2. Result: " << result );
1202     result = smack_have_access("test_subject_03", "test_object_01", "a");
1203     RUNNER_ASSERT_MSG_BT(result == 1,
1204         " Error while checking smack access loaded from /etc/smack/test_smack_rules2. Result: " << result );
1205     result = smack_have_access("test_subject_03", "test_object_02", "rwat");
1206     RUNNER_ASSERT_MSG_BT(result == 1,
1207         " Error while checking smack access loaded from /etc/smack/test_smack_rules2. Result: " << result );
1208     result = smack_have_access("test_subject_03", "test_object_03", "w---l-");
1209     RUNNER_ASSERT_MSG_BT(result == 1,
1210         " Error while checking smack access loaded from /etc/smack/test_smack_rules2. Result: " << result );
1211
1212     // Removing rules
1213     removeAccessesAll();
1214
1215     // Creating rules
1216     rules_ptr.release();
1217     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
1218     rules_ptr.reset(rules);
1219
1220     // Loading file with partial wrong rules - test_smack_rules3
1221     fd = open("/etc/smack/test_smack_rules3", O_RDONLY, 0644);
1222     RUNNER_ASSERT_MSG_BT(fd >= 0, "Unable to open /etc/smack/test_smack_rules3");
1223
1224     // Adding rules from file
1225     result = smack_accesses_add_from_file(rules_ptr.get(), fd);
1226     close(fd);
1227     RUNNER_ASSERT_MSG_BT(result != 0, "Accesses were loaded from file");
1228
1229     // Removing rules
1230     removeAccessesAll();
1231
1232     // Creating rules
1233     rules_ptr.release();
1234     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
1235     rules_ptr.reset(rules);
1236
1237     // Loading file with partial wrong rules - test_smack_rules4
1238     fd = open("/etc/smack/test_smack_rules4", O_RDONLY, 0644);
1239     RUNNER_ASSERT_MSG_BT(fd >= 0, "Unable to open /etc/smack/test_smack_rules4");
1240
1241     // Adding rules from file
1242     result = smack_accesses_add_from_file(rules_ptr.get(), fd);
1243     close(fd);
1244     RUNNER_ASSERT_MSG_BT(result != 0, "Accesses were loaded from file");
1245
1246     // Removing rules
1247     removeAccessesAll();
1248 }
1249
1250 //int smack_new_label_from_socket(int fd, char **label);
1251
1252
1253 static void smack_set_another_label_for_self(void)
1254 {
1255     static int number = time(NULL);
1256
1257     number++;
1258     std::string smack_label("s" + std::to_string(number));
1259
1260     int result = smack_set_label_for_self(smack_label.c_str());
1261     RUNNER_ASSERT_MSG_BT(result == 0, "smack_set_label_for_self(" << smack_label << ") failed");
1262 }
1263
1264 static void smack_unix_sock_server(int sock)
1265 {
1266     int fd, result;
1267     char *label;
1268
1269     alarm(2);
1270     fd = accept(sock, NULL, NULL);
1271     alarm(0);
1272     RUNNER_ASSERT_BT(fd >= 0);
1273     FdUniquePtr fd_ptr(&fd);
1274
1275     result = smack_new_label_from_self(&label);
1276     RUNNER_ASSERT_MSG_BT(result >= 0, "smack_new_label_from_self() failed");
1277     CStringPtr label_ptr(label);
1278     result = write(fd, label, strlen(label));
1279     RUNNER_ASSERT_MSG_BT(result == (int)strlen(label), "write() failed");
1280
1281 }
1282
1283 RUNNER_MULTIPROCESS_TEST_SMACK(smack09_new_label_from_socket)
1284 {
1285     int pid;
1286     struct sockaddr_un sockaddr = {AF_UNIX, SOCK_PATH};
1287     unlink(SOCK_PATH);
1288     smack_set_another_label_for_self();
1289     pid = fork();
1290     RUNNER_ASSERT_MSG_BT(pid >= 0, "Fork failed");
1291     if (!pid) { /* child process, server */
1292         int sock, result;
1293
1294
1295         sock = socket(AF_UNIX, SOCK_STREAM, 0);
1296         RUNNER_ASSERT_MSG_BT(sock >= 0, "socket failed: " << strerror(errno));
1297         SockUniquePtr sock_ptr(&sock);
1298         result = bind(sock, (struct sockaddr*) &sockaddr, sizeof(struct sockaddr_un));
1299         RUNNER_ASSERT_MSG_BT(result == 0, "bind failed: " << strerror(errno));
1300         result = listen(sock, 1);
1301         RUNNER_ASSERT_MSG_BT(result == 0, "listen failed: " << strerror(errno));
1302         smack_unix_sock_server(sock);
1303
1304         pid = fork();
1305         RUNNER_ASSERT_MSG_BT(pid >= 0, "Fork failed");
1306         /*  Test if socket label was unaffected by fork() */
1307         smack_unix_sock_server(sock);
1308         if (!pid) {
1309             usleep (100);
1310             smack_set_another_label_for_self();
1311             smack_unix_sock_server(sock);
1312         }
1313
1314         exit(0);
1315     } else { /* parent process, client */
1316         sleep(1); /* Give server some time to setup listening socket */
1317         for (int i = 0; i < 4; ++i) {
1318             int sock, result;
1319             char smack_label1[SMACK_LABEL_LEN + 1];
1320             char *smack_label2;
1321
1322             sock = socket(AF_UNIX, SOCK_STREAM, 0);
1323             RUNNER_ASSERT_MSG_BT(sock >= 0, "socket failed: " << strerror(errno));
1324             SockUniquePtr sock_ptr(&sock);
1325             result = connect(sock, (struct sockaddr*) &sockaddr, sizeof(struct sockaddr_un));
1326             RUNNER_ASSERT_MSG_BT(result == 0, "connect failed: " << strerror(errno));
1327             alarm(2);
1328             result = read(sock, smack_label1, SMACK_LABEL_LEN);
1329             alarm(0);
1330             RUNNER_ASSERT_MSG_BT(result >= 0, "read failed: " << strerror(errno));
1331             smack_label1[result] = '\0';
1332             result = smack_new_label_from_socket(sock, &smack_label2);
1333             SmackLabelPtr label2_ptr(smack_label2);
1334             RUNNER_ASSERT_MSG_BT(result >= 0, "smack_label_from_socket failed");
1335             result = strcmp(smack_label1, label2_ptr.get());
1336             if (i < 3)
1337                 RUNNER_ASSERT_MSG_BT(result == 0, "smack labels differ: '" << smack_label1
1338                         << "' != '" << smack_label2 << "' i == " << i);
1339             else
1340                 RUNNER_ASSERT_MSG_BT(result != 0, "smack labels do not differ: '" << smack_label1
1341                         << "' != '" << smack_label2 << "' i == " << i);
1342         }
1343     }
1344 }
1345
1346 void createFileWithLabel(const std::string &filePath, const std::string &fileLabel)
1347 {
1348     //create temporary file and set label for it
1349     mode_t systemMask;
1350
1351     unlink(filePath.c_str());
1352     //allow to create file with 777 rights
1353     systemMask = umask(0000);
1354     int fd = open(filePath.c_str(), O_RDWR | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
1355     //restore system mask
1356     umask(systemMask);
1357     RUNNER_ASSERT_MSG_BT(fd > -1, "Unable to create file for tests: " << strerror(errno));
1358
1359     //for descriptor protection
1360     FdUniquePtr fd_ptr(&fd);
1361
1362     //change owner and group to user APP
1363     int ret = chown(filePath.c_str(), APP_UID, APP_GID);
1364     RUNNER_ASSERT_MSG_BT(ret == 0, "Unable to change file owner: " << strerror(errno));
1365
1366     //set smack label on file
1367     ret = smack_setlabel(filePath.c_str(), fileLabel.c_str(), SMACK_LABEL_ACCESS);
1368     RUNNER_ASSERT_MSG_BT(ret == 0, "Unable to set label for file: " << ret);
1369
1370     char *label = NULL;
1371     ret = smack_getlabel(filePath.c_str(), &label, SMACK_LABEL_ACCESS);
1372     RUNNER_ASSERT_MSG_BT(ret == 0, "Unable to get label from file");
1373     std::string label_str(label ? label : "");
1374     free(label);
1375     RUNNER_ASSERT_MSG_BT(label_str == fileLabel, "File label not match set label");
1376 }
1377
1378 void prepareEnvironment(const std::string &subject, const std::string &object, const std::string &access)
1379 {
1380     const std::string ruleAll = "x";
1381
1382     SecurityServer::AccessProvider provider(subject);
1383     provider.addObjectRule("User", ruleAll);
1384     provider.addObjectRule(object, access);
1385     provider.applyAndSwithToUser(APP_UID, APP_GID);
1386 }
1387
1388 //- Add "l" rule to system
1389 //
1390 //Should be able to add "l" rule to system
1391 RUNNER_CHILD_TEST_SMACK(smack13_0_checking_laccess_mode_enabled_on_device)
1392 {
1393     std::string selfLabel = "smack13_0";
1394     std::string filename = "smack13_0_file";
1395
1396     //function inside checks if rule exist after add it
1397     SecurityServer::AccessProvider provider(selfLabel);
1398     provider.addObjectRule(filename, "l");
1399     provider.apply();
1400
1401     int ret = smack_have_access(selfLabel.c_str(), filename.c_str(), "l");
1402     RUNNER_ASSERT_MSG_BT(ret == 1, "Error in adding laccess rule - l");
1403 }
1404
1405 //- Create file
1406 //- Set label for file and self
1407 //- Drop privileges
1408 //
1409 //Should have no access due to missing SMACK rule
1410 RUNNER_CHILD_TEST_SMACK(smack13_1_checking_laccess_mode)
1411 {
1412     std::string selfLabel = "smack13_1";
1413     std::string filename = "smack13_1_file";
1414     std::string filePath = testDir + filename;
1415
1416     createFileWithLabel(filePath, filename);
1417     int fd = open(filePath.c_str(), O_RDWR, 0);
1418     FdUniquePtr fd_ptr(&fd);
1419
1420     SecurityServer::AccessProvider provider(selfLabel);
1421     provider.applyAndSwithToUser(APP_UID, APP_GID);
1422
1423     int ret = flock(fd, LOCK_EX | LOCK_NB);
1424     RUNNER_ASSERT_MSG_BT(ret < 0, "Error, able to lock file: " << strerror(errno));
1425     ret = flock(fd, LOCK_UN | LOCK_NB);
1426     RUNNER_ASSERT_MSG_BT(ret < 0, "Error, able to lock file: " << strerror(errno));
1427     ret = flock(fd, LOCK_SH | LOCK_NB);
1428     RUNNER_ASSERT_MSG_BT(ret < 0, "Error, able to lock file: " << strerror(errno));
1429 }
1430
1431 //- Create file
1432 //- Set label for file and self
1433 //- Add SMACK rule "l"
1434 //- Drop privileges
1435 //
1436 //Should be able to lock file even without "w" rule
1437 RUNNER_CHILD_TEST_SMACK(smack13_2_checking_laccess_mode_with_l_rule)
1438 {
1439     std::string selfLabel = "smack13_2";
1440     std::string filename = "smack13_2_file";
1441     std::string filePath = testDir + filename;
1442
1443     createFileWithLabel(filePath, filename);
1444     int fd = open(filePath.c_str(), O_RDWR, 0);
1445     FdUniquePtr fd_ptr(&fd);
1446
1447     prepareEnvironment(selfLabel, filename, "l");
1448
1449     int ret = flock(fd, LOCK_EX | LOCK_NB);
1450     RUNNER_ASSERT_MSG_BT(ret == 0, "Error, unable to exclusive lock file: " << strerror(errno));
1451     ret = flock(fd, LOCK_UN | LOCK_NB);
1452     RUNNER_ASSERT_MSG_BT(ret == 0, "Error, unable to unlock file: " << strerror(errno));
1453     ret = flock(fd, LOCK_SH | LOCK_NB);
1454     RUNNER_ASSERT_MSG_BT(ret == 0, "Error, unable to shared lock file: " << strerror(errno));
1455 }
1456
1457 //- Create file
1458 //- Set label for file and self
1459 //- Add SMACK rule "w"
1460 //- Drop privileges
1461 //
1462 //Should be able to lock file even without "l" rule
1463 RUNNER_CHILD_TEST_SMACK(smack13_3_checking_laccess_mode_with_w_rule)
1464 {
1465     std::string selfLabel = "smack13_3";
1466     std::string filename = "smack13_3_file";
1467     std::string filePath = testDir + filename;
1468
1469     createFileWithLabel(filePath, filename);
1470     int fd = open(filePath.c_str(), O_RDWR, 0);
1471     FdUniquePtr fd_ptr(&fd);
1472
1473     prepareEnvironment(selfLabel, filename, "w");
1474
1475     int ret = flock(fd, LOCK_EX | LOCK_NB);
1476     RUNNER_ASSERT_MSG_BT(ret == 0, "Error, unable to exclusive lock file: " << strerror(errno));
1477     ret = flock(fd, LOCK_UN | LOCK_NB);
1478     RUNNER_ASSERT_MSG_BT(ret == 0, "Error, unable to unlock file: " << strerror(errno));
1479     ret = flock(fd, LOCK_SH | LOCK_NB);
1480     RUNNER_ASSERT_MSG_BT(ret == 0, "Error, unable to shared lock file: " << strerror(errno));
1481 }
1482
1483 //- Create file
1484 //- Set label for file and self
1485 //- Add SMACK rule "rw"
1486 //- Drop privileges
1487 //- Lock file (shared lock)
1488 //- Spawn child process
1489 //- Child tries to lock file (shared)
1490 //
1491 //Child should be able to lock file due to shared lock
1492 RUNNER_MULTIPROCESS_TEST_SMACK(smack13_4_0_checking_laccess_mode_w_rule_child)
1493 {
1494     std::string selfLabel = "smack13_4_0";
1495     std::string filename = "smack13_4_0_file";
1496     std::string filePath = testDir + filename;
1497
1498     createFileWithLabel(filePath, filename);
1499     int fd = open(filePath.c_str(), O_RDWR);
1500     FdUniquePtr fd_ptr(&fd);
1501     int ret = flock(fd, LOCK_SH | LOCK_NB);
1502     RUNNER_ASSERT_MSG_BT(ret == 0, "Error, unable to shared lock file: " << strerror(errno));
1503
1504     pid_t pid = fork();
1505     if (pid == 0) {
1506         //child process
1507         prepareEnvironment(selfLabel, filename, "rw");
1508
1509         int child_fd = open(filePath.c_str(), O_RDWR);
1510         RUNNER_ASSERT_MSG_BT(child_fd > -1, "Unable to open created file: " << strerror(errno));
1511         //for descriptor protection
1512         FdUniquePtr child_fd_ptr(&child_fd);
1513
1514         ret = flock(child_fd, LOCK_SH | LOCK_NB);
1515         RUNNER_ASSERT_MSG_BT(ret == 0, "Error, unable to lock file with shared lock: "
1516                           << strerror(errno));
1517     }
1518 }
1519
1520 //- Create file
1521 //- Set label for file and self
1522 //- Add SMACK rule "l"
1523 //- Drop privileges
1524 //- Lock file (shared lock)
1525 //- Spawn child process
1526 //- Child tries to lock file (shared)
1527 //
1528 //Child should be able to lock file due to shared lock
1529 RUNNER_MULTIPROCESS_TEST_SMACK(smack13_4_1_checking_laccess_mode_l_rule_child)
1530 {
1531     std::string selfLabel = "smack13_4_1";
1532     std::string filename = "smack13_4_1_file";
1533     std::string filePath = testDir + filename;
1534
1535     createFileWithLabel(filePath, filename);
1536     int fd = open(filePath.c_str(), O_RDWR);
1537     FdUniquePtr fd_str(&fd);
1538     int ret = flock(fd, LOCK_SH | LOCK_NB);
1539     RUNNER_ASSERT_MSG_BT(ret == 0, "Error, unable to shared lock file: " << strerror(errno));
1540
1541     pid_t pid = fork();
1542     if (pid == 0) {
1543         //child process
1544         //"r" is only for open in O_RDONLY mode
1545         prepareEnvironment(selfLabel, filename, "rl");
1546
1547         int child_fd = open(filePath.c_str(), O_RDONLY, 0);
1548         RUNNER_ASSERT_MSG_BT(child_fd > -1, "Unable to open created file: " << strerror(errno));
1549         //for descriptor protection
1550         FdUniquePtr child_fd_ptr(&child_fd);
1551
1552         ret = flock(child_fd, LOCK_SH | LOCK_NB);
1553         RUNNER_ASSERT_MSG_BT(ret == 0, "Error, unable to lock file with shared lock: "
1554                           << strerror(errno));
1555     }
1556 }
1557
1558 //- Create file
1559 //- Set label for file and self
1560 //- Add SMACK rule "rw"
1561 //- Drop privileges
1562 //- Lock file (exclusive lock)
1563 //- Spawn child process
1564 //- Child tries to lock file (exclusive / shared)
1565 //
1566 //Child should not be able to lock file due to exclusive lock
1567 RUNNER_MULTIPROCESS_TEST_SMACK(smack13_4_2_checking_laccess_mode_w_rule_child)
1568 {
1569     std::string selfLabel = "smack13_4_2";
1570     std::string filename = "smack13_4_2_file";
1571     std::string filePath = testDir + filename;
1572
1573     createFileWithLabel(filePath, filename);
1574     int fd = open(filePath.c_str(), O_RDWR);
1575     FdUniquePtr fd_ptr(&fd);
1576     int ret = flock(fd, LOCK_EX | LOCK_NB);
1577     RUNNER_ASSERT_MSG_BT(ret == 0, "Error, unable to exclusive lock file: " << strerror(errno));
1578
1579     pid_t pid = fork();
1580     if (pid == 0) {
1581         //child process
1582         prepareEnvironment(selfLabel, filename, "rw");
1583
1584         int child_fd = open(filePath.c_str(), O_RDWR, 0);
1585         RUNNER_ASSERT_MSG_BT(child_fd > -1, "Unable to open created file: " << strerror(errno));
1586         //for descriptor protection
1587         FdUniquePtr child_fd_ptr(&child_fd);
1588
1589         ret = flock(child_fd, LOCK_EX | LOCK_NB);
1590         RUNNER_ASSERT_MSG_BT(ret < 0, "Error, able to lock file with exclusive lock");
1591     }
1592 }
1593
1594 //- Create file
1595 //- Set label for file and self
1596 //- Add SMACK rule "l"
1597 //- Drop privileges
1598 //- Lock file (exclusive lock)
1599 //- Spawn child process
1600 //- Child tries to lock file (exclusive / shared)
1601 //
1602 //Child should not be able to lock file due to exclusive lock
1603 RUNNER_MULTIPROCESS_TEST_SMACK(smack13_4_3_checking_laccess_mode_l_rule_child)
1604 {
1605     std::string selfLabel = "smack13_4_3";
1606     std::string filename = "smack13_4_3_file";
1607     std::string filePath = testDir + filename;
1608
1609     createFileWithLabel(filePath, filename);
1610     int fd = open(filePath.c_str(), O_RDWR, 0);
1611     FdUniquePtr fd_ptr(&fd);
1612     int ret = flock(fd, LOCK_EX | LOCK_NB);
1613     RUNNER_ASSERT_MSG_BT(ret == 0, "Error, unable to exclusive lock file: " << strerror(errno));
1614
1615     pid_t pid = fork();
1616     if (pid == 0) {
1617         //child process
1618         //"r" is only for open in O_RDONLY mode
1619         prepareEnvironment(selfLabel, filename, "rl");
1620
1621         int child_fd = open(filePath.c_str(), O_RDONLY, 0);
1622         RUNNER_ASSERT_MSG_BT(child_fd > -1, "Unable to open created file: " << strerror(errno));
1623         //for descriptor protection
1624         FdUniquePtr child_fd_ptr(&child_fd);
1625
1626         ret = flock(child_fd, LOCK_EX | LOCK_NB);
1627         RUNNER_ASSERT_MSG_BT(ret < 0, "Error, able to lock file with eclusive lock");
1628     }
1629 }
1630
1631
1632 /////////////////////////////////////////
1633 //////NOSMACK ENVIRONMENT TESTS//////////
1634 /////////////////////////////////////////
1635
1636 /**
1637  * NOSMACK version of smack02 test. Functions, that should return error instead of success:
1638  * - smack_accesses_apply
1639  * - smack_have_access
1640  * - smack_revoke_subject
1641  * - smack_acceesses_clear
1642  *
1643  * Tests smack03, smack04, smack10, smack_accesses_clear, smack_revoke_subject all use functions
1644  * tested in smack02 test. Results from those functions (smack_have_access, smack_accesses_apply,
1645  * smack_accesses_clear, smack_revoke_subject) would be the same as in this test. Tests mentioned
1646  * above doesn't make much sense on NOSMACK environment when test smack02 exists and passes
1647  * correctly, thus those tests are are not implemented.
1648  */
1649 RUNNER_TEST_NOSMACK(smack02_aplying_rules_into_kernel_nosmack)
1650 {
1651
1652     smack_accesses *rules = NULL;
1653     int result;
1654
1655     //init rules
1656     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
1657     //pass rules to unique_ptr
1658     SmackAccessesPtr rules_ptr(rules);
1659
1660     //adding test rules to struct (same as SMACK version of smack02 test)
1661     result = smack_accesses_add(rules_ptr.get(), "writer", "book", "rwx");
1662     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add smack rules");
1663     result = smack_accesses_add(rules_ptr.get(), "reader", "book", "r");
1664     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add smack rules");
1665     result = smack_accesses_add(rules_ptr.get(), "spy", "book", "rwx");
1666     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add smack rules");
1667
1668     //applying rules to kernel (should fail)
1669     result = smack_accesses_apply(rules_ptr.get());
1670     RUNNER_ASSERT_MSG_BT(result == -1, "Unable to apply rules into kernel");
1671
1672     //calls from SMACK version of this test - all should fail because of SMACK being turned off
1673     result = smack_have_access("spy", "book", "rwx");
1674     RUNNER_ASSERT_MSG_BT(result == -1, "smack_have_access should return error (SMACK is off)");
1675     result = smack_have_access("reader", "book", "rwx");
1676     RUNNER_ASSERT_MSG_BT(result == -1, "smack_have_access should return error (SMACK is off)");
1677     result = smack_have_access("s02badsubjectlabel", "book", "rwx");
1678     RUNNER_ASSERT_MSG_BT(result == -1, "smack_have_access should return error (SMACK is off)");
1679
1680     //testing subject revoking - should return error (no accesses applied = no subjects to revoke)
1681     result = smack_revoke_subject("s02nonexistinglabel");
1682     RUNNER_ASSERT_MSG_BT(result == -1, "smack_revoke_subject error - subject doesn't exist.");
1683     result = smack_revoke_subject("spy");
1684     RUNNER_ASSERT_MSG_BT(result == -1, "smack_revoke_subject error - subject doesn't exist.");
1685
1686     //after revoking smack_have_access still should return error
1687     result = smack_have_access("spy", "book", "rwx");
1688     RUNNER_ASSERT_MSG_BT(result == -1, "smack_have_access should return error (SMACK is off).");
1689
1690     result = smack_accesses_add(rules_ptr.get(), "s02subjectlabel", "book", "rwx");
1691     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to add smack rules");
1692
1693     //smack_accesses_clear should return error aswell
1694     result = smack_accesses_clear(rules_ptr.get());
1695     RUNNER_ASSERT_MSG_BT(result == -1, "Clearing rules should return error - no SMACK on system.");
1696
1697     result = smack_have_access("writer", "book", "rwx");
1698     RUNNER_ASSERT_MSG_BT(result == -1, "smack_have_access should return error (SMACK is off).");
1699 }
1700
1701 /**
1702  * NOSMACK version of smack11 test. Tests functions:
1703  * - smack_accesses_add_from_file
1704  *
1705  * Since other SMACK functions were tested in smack02 test, the only function needed to be checked
1706  * is applying rules loaded from file.
1707  */
1708 RUNNER_TEST_NOSMACK(smack03_saving_loading_rules_nosmack)
1709 {
1710     int result;
1711     int fd;
1712
1713     smack_accesses* tmp = NULL;
1714
1715     RUNNER_ASSERT_BT(smack_accesses_new(&tmp) == 0);
1716     SmackAccessesPtr rules(tmp);
1717
1718     //open file with rules
1719     fd = open("/etc/smack/test_smack_rules_full", O_RDONLY, 0644);
1720     RUNNER_ASSERT_MSG_BT(fd >= 0,
1721             "Unable to open /etc/smack/test_smack_rules_full. Errno: " << strerror(errno));
1722
1723     //load accesses from file
1724     result = smack_accesses_add_from_file(rules.get(), fd);
1725     close(fd);
1726     RUNNER_ASSERT_MSG_BT(result == 0, "Error while importing accesses from file. Result: " << result);
1727 }
1728
1729 /**
1730  * NOSMACK version of smack05 test. Tests if functions getting, or
1731  * setting self label work correctly (that is, return error).
1732  */
1733 RUNNER_TEST_NOSMACK(smack04_self_label_nosmack)
1734 {
1735     char* label = NULL;
1736     int result;
1737     int fd;
1738
1739     char buff[SMACK_LABEL_LEN+1];
1740
1741     //smack_new_label_from_self should fail
1742     result = smack_new_label_from_self(&label);
1743     RUNNER_ASSERT_MSG_BT(result == -1, "new_label_from_self should return error (SMACK is off).");
1744     RUNNER_ASSERT_MSG_BT(label == NULL, "new_label_from_self shouldn't allocate memory to label.");
1745     //We don't need to remember about freeing label - smack_new_label_from_self must return NULL
1746     //label if it's working properly.
1747
1748     // /proc/self/attr/current shouldn't keep any rules inside
1749     fd = open("/proc/self/attr/current", O_RDONLY, 0644);   //file exists, so it should open
1750     RUNNER_ASSERT_MSG_BT(fd >= 0, "/proc/self/attr/current failed to open.");
1751     FdUniquePtr fd_ptr(&fd);
1752
1753     result = read(fd, buff, SMACK_LABEL_LEN);   //however reading it should return error
1754     RUNNER_ASSERT_MSG_BT(result < 0, "Reading /proc/self/attr/current should return error.");
1755
1756     //setting label for self should fail
1757     result = smack_set_label_for_self("s04testlabel");
1758     RUNNER_ASSERT_MSG_BT(result == -1, "set_label_for_self should return error (SMACK is off).");
1759
1760     //getting previously set label should also fail
1761     result = smack_new_label_from_self(&label);
1762     RUNNER_ASSERT_MSG_BT(result == -1, "new_label_from_self should return error (SMACK is off).");
1763     RUNNER_ASSERT_MSG_BT(label == NULL, "new_label_from_self shouldn't allocate memory to label.");
1764
1765     // /proc/self/attr/current still shouldn't keep any rules inside
1766     result = lseek(fd, 0, SEEK_SET);    //going to the file beginning
1767     RUNNER_ASSERT_MSG_BT(result == 0, "lseek() error.");
1768
1769     result = read(fd, buff, SMACK_LABEL_LEN);   //however it should return error
1770     RUNNER_ASSERT_MSG_BT(result < 0, "Reading /proc/self/attr/current should return error.");
1771 }
1772
1773 /**
1774  * NOSMACK version of smack_accesses_add_modify_x tests.
1775  *
1776  * Because all smack_accesses_add_modify tests are basically the same (all use smack_accesses_apply
1777  * and smack_have_access, which return -1 when SMACK is turned off), it makes much more sense to
1778  * write one test which will create rules using smack_accesses_add_modify and then check if
1779  * smack_accesses_apply and smack_have_access indeed return -1 when SMACK is turned off.
1780  */
1781 RUNNER_TEST_NOSMACK(smack05_accesses_add_modify_nosmack)
1782 {
1783     int result;
1784     smack_accesses* rules = NULL;
1785
1786     RUNNER_ASSERT_BT(smack_accesses_new(&rules) == 0);
1787
1788     SmackAccessesPtr rules_ptr(rules);
1789
1790     //Not doing clean_up() every RUNNER_ASSERT_MSG - what clean_up does is just a creation of new
1791     //rule struct and removal of currenctly added and applied rules. clean_up() must be done only
1792     //after smack_accesses_apply().
1793     result = smack_accesses_add_modify(rules_ptr.get(), TEST_SUBJECT, TEST_OBJECT, "rwx", "");
1794     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify rule. Result: " << result);
1795
1796     result = smack_accesses_add_modify(rules_ptr.get(), TEST_SUBJECT, TEST_OBJECT, "rwx", "");
1797     RUNNER_ASSERT_MSG_BT(result == 0, "Unable to modify rule. Result: " << result);
1798
1799     result = smack_accesses_apply(rules_ptr.get());
1800     RUNNER_ASSERT_MSG_BT(result == -1,
1801             "smack_accesses_apply should return error (SMACK is off). Result: " << result);
1802
1803     result = smack_have_access(TEST_SUBJECT, TEST_OBJECT, "rwx");
1804     if(result != -1) {
1805         clean_up();
1806         RUNNER_ASSERT_MSG_BT(false,
1807                 "smack_have_access should return error (SMACK is off). Result: " << result);
1808     }
1809
1810     clean_up();
1811 }
1812
1813 /**
1814  * NOSMACK version of smack09 test.
1815  *
1816  * This test checks if smack_new_label_from_socket reacts correctly. Since label should be
1817  * acquired from getsockopt, and it should fail, we must only set up socket and call
1818  * smack_new_label_from_socket. It should return error.
1819  */
1820 RUNNER_MULTIPROCESS_TEST_NOSMACK(smack09_new_label_from_socket_nosmack)
1821 {
1822     int pid;
1823     struct sockaddr_un sockaddr = {AF_UNIX, SOCK_PATH};
1824     unlink(SOCK_PATH);
1825     char* smack_label;
1826
1827     pid = fork();
1828     RUNNER_ASSERT_MSG_BT(pid >= 0, "Fork failed");
1829     if (!pid) { //child (server)
1830         int sock, result;
1831         int fd;
1832
1833         //Create new socket
1834         sock = socket(AF_UNIX, SOCK_STREAM, 0);
1835         RUNNER_ASSERT_MSG_BT(sock >= 0, "socket failed: " << strerror(errno));
1836         SockUniquePtr sock_ptr(&sock);
1837
1838         //Bind it to sockaddr
1839         result = bind(sock, (struct sockaddr*) &sockaddr, sizeof(struct sockaddr_un));
1840         RUNNER_ASSERT_MSG_BT(result == 0, "bind failed: " << strerror(errno));
1841
1842         //Prepare for listening
1843         result = listen(sock, 1);
1844         RUNNER_ASSERT_MSG_BT(result == 0, "listen failed: " << strerror(errno));
1845
1846         //Accept client
1847         alarm(2);
1848         fd = accept(sock, NULL, NULL);
1849         alarm(0);
1850         RUNNER_ASSERT_MSG_BT(fd >= 0, "Failed when accepting connection from client.");
1851         FdUniquePtr fd_ptr(&fd);
1852
1853         //wait for smack_new_label_from_socket execution
1854         usleep(200);
1855
1856         //Close server
1857         exit(0);
1858     }
1859     else { //parent (client)
1860         //Wait a little bit until server is set up
1861         sleep(1);
1862         int sock, result;
1863
1864         //Create socket
1865         sock = socket(AF_UNIX, SOCK_STREAM, 0);
1866         SockUniquePtr sock_ptr(&sock);
1867         RUNNER_ASSERT_MSG_BT(sock >= 0, "socket failed: " << strerror(errno));
1868
1869         //Connect to sockaddr
1870         result = connect(sock, (struct sockaddr*) &sockaddr,
1871                 sizeof(struct sockaddr_un));
1872         RUNNER_ASSERT_MSG_BT(result == 0, "connect failed: " << strerror(errno));
1873
1874         //Try getting label, should fail beacuse getsockopt won't get anything
1875         result = smack_new_label_from_socket(sock, &smack_label);
1876         RUNNER_ASSERT_MSG_BT(result == -1, "smack_new_label_from_socket should fail.");
1877     }
1878 }