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