e52010e2630c1d64251908a716c023a8f88db624
[platform/core/test/security-tests.git] / tests / libprivilege-control-tests / test_cases.cpp
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17 /*
18  * @file        test_cases.cpp
19  * @author      Jan Olszak (j.olszak@samsung.com)
20  * @author      Rafal Krypa (r.krypa@samsung.com)
21  * @version     1.0
22  * @brief       libprivilege-control test runer
23  */
24
25 #include <string>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <vector>
29 #include <errno.h>
30 #include <ftw.h>
31 #include <dpl/test/test_runner.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/xattr.h>
37 #include <sys/smack.h>
38 #include <privilege-control.h>
39
40
41 #define SMACK_RULES_DIR  "/etc/smack/accesses.d/"
42 #define TEST_APP_DIR "/etc/smack/test_privilege_control_DIR/app_dir"
43 #define TEST_NON_APP_DIR "/etc/smack/test_privilege_control_DIR/non_app_dir"
44 #define APPID_ADD  "test_APP_ID_add"
45 #define APPID_REVOKE  "test_APP_ID_revoke"
46 #define APPID_DIR  "test_APP_ID_dir"
47 #define APPID_SHARED_DIR  "test_APP_ID_shared_dir"
48 #define CANARY_LABEL "tiny_yellow_canary"
49
50 #define APP_SET_PRIV  "test_APP"
51 #define APP_SET_PRIV_PATH "/etc/smack/test_privilege_control_DIR/test_set_app_privilege/test_APP"
52
53 const char *PRIVS[] = { "WRT", "test_privilege_control_rules", NULL };
54
55 #define APP_GID 5000
56 #define APP_UID 5000
57 #define APP_USER_NAME "app"
58 #define APP_HOME_DIR "/opt/home/app"
59
60 // How many open file descriptors should ftw() function use?
61 #define FTW_MAX_FDS 16
62
63 // Rules from test_privilege_control_rules.smack
64 const std::vector< std::vector<std::string> > rulesAdd = {
65         { APPID_ADD, "test_book_1", "r" },
66         { APPID_ADD, "test_book_2", "w" },
67         { APPID_ADD, "test_book_3", "x" },
68         { APPID_ADD, "test_book_4", "rw" },
69         { APPID_ADD, "test_book_5", "rx" },
70         { APPID_ADD, "test_book_6", "wx" },
71         { APPID_ADD, "test_book_7", "rwx" },
72         { "test_subject_1", APPID_ADD, "r" },
73         { "test_subject_2", APPID_ADD, "w" },
74         { "test_subject_3", APPID_ADD, "x" },
75         { "test_subject_4", APPID_ADD, "rw" },
76         { "test_subject_5", APPID_ADD, "rx" },
77         { "test_subject_6", APPID_ADD, "wx" },
78         { "test_subject_7", APPID_ADD, "rwx" },
79         { APPID_ADD, APPID_SHARED_DIR, "rwxat"}};
80
81
82 // Rules from test_privilege_control_rules.smack
83 const std::vector< std::vector<std::string> > rulesRevoke = {
84         { APPID_REVOKE, "test_book_1", "r" },
85         { APPID_REVOKE, "test_book_2", "w" },
86         { APPID_REVOKE, "test_book_3", "x" },
87         { APPID_REVOKE, "test_book_4", "rw" },
88         { APPID_REVOKE, "test_book_5", "rx" },
89         { APPID_REVOKE, "test_book_6", "wx" },
90         { APPID_REVOKE, "test_book_7", "rwx" },
91         { "test_subject_1", APPID_REVOKE, "r" },
92         { "test_subject_2", APPID_REVOKE, "w" },
93         { "test_subject_3", APPID_REVOKE, "x" },
94         { "test_subject_4", APPID_REVOKE, "rw" },
95         { "test_subject_5", APPID_REVOKE, "rx" },
96         { "test_subject_6", APPID_REVOKE, "wx" },
97         { "test_subject_7", APPID_REVOKE, "rwx" }};
98
99 /**
100  * Check if every rule is true.
101  * @return 1 if ALL rules in SMACK, 0 if ANY rule isn't
102  */
103 int test_have_all_accesses(const std::vector< std::vector<std::string> >& rules){
104     int result;
105     for(uint i =0; i<rules.size();++i ){
106         result = smack_have_access(rules[i][0].c_str(),rules[i][1].c_str(),rules[i][2].c_str());
107         if (result !=1)
108             return result;
109     }
110     return 1;
111 }
112
113 /**
114  * Check if every rule is true.
115  * @return 1 if ANY rule in SMACK, 0 if
116  */
117 int test_have_any_accesses(const std::vector< std::vector<std::string> >& rules){
118     int result;
119     for(uint i =0; i<rules.size();++i ){
120         result = smack_have_access(rules[i][0].c_str(),rules[i][1].c_str(),rules[i][2].c_str());
121         if (result ==1)
122             return 1;
123     }
124     return 0;
125 }
126
127 RUNNER_TEST_GROUP_INIT(libprivilegecontrol)
128
129 static int nftw_remove_labels(const char *fpath, const struct stat *sb,
130                                 int typeflag, struct FTW *ftwbuf)
131 {
132         smack_lsetlabel(fpath, NULL, SMACK_LABEL_ACCESS);
133         smack_lsetlabel(fpath, NULL, SMACK_LABEL_EXEC);
134         smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
135
136         return 0;
137 }
138
139 static int nftw_set_labels_non_app_dir(const char *fpath, const struct stat *sb,
140                                 int typeflag, struct FTW *ftwbuf)
141 {
142         smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_ACCESS);
143         smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_EXEC);
144         smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
145
146         return 0;
147 }
148
149 static int nftw_check_labels_non_app_dir(const char *fpath, const struct stat *sb,
150                                 int typeflag, struct FTW *ftwbuf)
151 {
152     int result;
153     char* label;
154
155     /* ACCESS */
156     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
157     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
158     result = strcmp(CANARY_LABEL, label);
159     RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is overwritten");
160
161     /* EXEC */
162     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
163     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
164     result = strcmp(CANARY_LABEL, label);
165     RUNNER_ASSERT_MSG(result == 0, "EXEC label on " << fpath << " is overwritten");
166
167     /* TRANSMUTE */
168     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
169     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
170     RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
171
172     return 0;
173 }
174
175 static int nftw_check_labels_app_dir(const char *fpath, const struct stat *sb,
176                                 int typeflag, struct FTW *ftwbuf)
177 {
178     int result;
179     char* label;
180
181     /* ACCESS */
182     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
183     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
184     RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
185     result = strcmp(APPID_DIR, label);
186     RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
187
188     /* EXEC */
189     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
190     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
191     if (S_ISREG(sb->st_mode) && (sb->st_mode & S_IXUSR)) {
192         RUNNER_ASSERT_MSG(label != NULL, "EXEC label on " << fpath << " is not set");
193         result = strcmp(APPID_DIR, label);
194         RUNNER_ASSERT_MSG(result == 0, "EXEC label on executable file " << fpath << " is incorrect");
195     } else
196         RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
197
198     /* TRANSMUTE */
199     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
200     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
201     RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
202
203     return 0;
204 }
205
206 static int nftw_check_labels_app_shared_dir(const char *fpath, const struct stat *sb,
207                                 int typeflag, struct FTW *ftwbuf)
208 {
209     int result;
210     char* label;
211
212     /* ACCESS */
213     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
214     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
215     RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
216     result = strcmp(APPID_SHARED_DIR, label);
217     RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
218
219     /* EXEC */
220     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
221     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
222     RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
223
224     /* TRANSMUTE */
225     result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
226     RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
227     if (S_ISDIR(sb->st_mode)) {
228         RUNNER_ASSERT_MSG(label != NULL, "TRANSMUTE label on " << fpath << " is not set");
229         result = strcmp("TRUE", label);
230         RUNNER_ASSERT_MSG(result == 0, "TRANSMUTE label on " << fpath << " is not set");
231     } else
232         RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
233
234     return 0;
235 }
236
237 /**
238  * Test setting labels for all files and folders in given path.
239  */
240 RUNNER_TEST(privilege_control01_app_label_dir)
241 {
242     int result;
243
244     result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
245     RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
246
247     result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
248     RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
249
250     result = app_label_dir(APPID_DIR, TEST_APP_DIR);
251     RUNNER_ASSERT_MSG(result == 0, "app_label_dir() failed");
252
253     result = nftw(TEST_APP_DIR, &nftw_check_labels_app_dir, FTW_MAX_FDS, FTW_PHYS);
254     RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for app dir");
255
256     result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
257     RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
258 }
259
260 RUNNER_TEST(privilege_control02_app_label_shared_dir)
261 {
262     int result;
263
264     result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
265     RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
266
267     result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
268     RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
269
270     result = app_label_shared_dir(APPID_ADD, APPID_SHARED_DIR, TEST_APP_DIR);
271     RUNNER_ASSERT_MSG(result == 0, "app_label_shared_dir() failed");
272
273     result = nftw(TEST_APP_DIR, &nftw_check_labels_app_shared_dir, FTW_MAX_FDS, FTW_PHYS);
274     RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for shared app dir");
275
276     result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
277     RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
278 }
279
280
281 /**
282  * Add permisions from  test_privilege_control_rules template
283  */
284 RUNNER_TEST(privilege_control03_add_permissions)
285 {
286     char* path;
287
288     int result = app_add_permissions(APPID_ADD, PRIVS);
289     RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
290             " Error adding app permissions. Errno: " << result);
291
292     // Check if the accesses are realy applied..
293     result = test_have_all_accesses(rulesAdd);
294     RUNNER_ASSERT_MSG(result==1, "Permissions not added.");
295
296     ///Investigate created SMACK rules files..
297     RUNNER_ASSERT_MSG(asprintf(&path, SMACK_RULES_DIR "%s", APPID_ADD) != -1,
298             "Error in asprintf");
299
300     //// File exists?
301     FILE *pFile = fopen(path, "rb");
302     RUNNER_ASSERT_MSG(pFile != NULL,
303             "SMACK file NOT created!. Errno: " << errno);
304
305     //// Is it empty?
306     fseek(pFile, 0L, SEEK_END);
307     int smack_file_length = ftell(pFile);
308     RUNNER_ASSERT_MSG(smack_file_length>0,
309             "SMACK file empty, but privileges list was not empty.. Errno: " << errno);
310
311     // Clean up
312     result = app_revoke_permissions(APPID_ADD);
313     RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
314             "Error revoking app permissions. Errno: " << result);
315
316     if (pFile != NULL)
317         fclose(pFile);
318
319 }
320
321
322 /**
323  * Revoke permissions from the list. Should be executed as privileged user.
324  */
325 RUNNER_TEST(privilege_control04_revoke_permissions)
326 {
327     int result;
328
329     // Prepare permissions that we want to revoke
330     result = app_add_permissions(APPID_REVOKE, PRIVS);
331     RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
332             " Error adding app permissions. Errno: " << result);
333
334     // Revoke permissions
335     result = app_revoke_permissions(APPID_REVOKE);
336     RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
337             "Error revoking app permissions. Errno: " << result);
338
339     // Are all the permissions revoked?
340     result = test_have_all_accesses(rulesRevoke);
341     RUNNER_ASSERT_MSG(result!=1, "Not all permisions revoked.");
342
343     // Investigate SMACK rules file
344     char* path;
345     RUNNER_ASSERT_MSG(asprintf(&path, SMACK_RULES_DIR "%s", APPID_REVOKE) != -1,
346             "Error in asprintf");
347
348     //// Is the smack file deleted?
349     FILE *pFile = fopen(path, "rb");
350     RUNNER_ASSERT_MSG(pFile == NULL,
351             "SMACK file NOT deleted after revoking ALL privileges. Errno: " << errno);
352
353     RUNNER_ASSERT_MSG(errno == ENOENT,
354             "SMACK file NOT deleted after revoking ALL privileges. Errno: " << errno);
355
356     if (pFile != NULL)
357         fclose(pFile);
358 }
359
360 /**
361  * Set APP privileges.
362  */
363 RUNNER_TEST(privilege_control05_set_app_privilege)
364 {
365     int result;
366     char* labelApp = "test_pc_label";
367
368     // Preset exec label
369     smack_setlabel(APP_SET_PRIV_PATH,labelApp, SMACK_LABEL_EXEC);
370
371     // Set APP privileges
372     result = set_app_privilege(APP_SET_PRIV, NULL, APP_SET_PRIV_PATH);
373     RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS, "Error in set_app_privilege. Error: " << result);
374
375     // Check if SMACK label really set
376     char * label;
377     result = smack_new_label_from_self(&label);
378     RUNNER_ASSERT_MSG(result == 0, "Error setting label for exec" << result);
379     result = strcmp(labelApp, label);
380     RUNNER_ASSERT_MSG(result == 0, "Label NOT set");
381
382     // Check if DAC privileges really set
383     RUNNER_ASSERT_MSG(getuid() == APP_UID, "Wrong UID");
384     RUNNER_ASSERT_MSG(getgid() == APP_GID, "Wrong GID");
385
386     result = strcmp(getenv("HOME"), APP_HOME_DIR);
387     RUNNER_ASSERT_MSG(result == 0, "Wrong HOME DIR");
388
389     result = strcmp(getenv("USER"), APP_USER_NAME);
390     RUNNER_ASSERT_MSG(result == 0, "Wrong user USER NAME");
391 }
392