Merge branch 'tizen' into security-manager
[platform/core/test/security-tests.git] / src / security-server-tests / server.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  */
4 /*
5  * @file    security_server_tests_server.cpp
6  * @author  Bumjin Im (bj.im@samsung.com)
7  * @author  Mariusz Domanski (m.domanski@samsung.com)
8  * @version 1.0
9  * @brief   Test cases for security server
10  */
11
12 #include <stdio.h>
13 #include <errno.h>
14 #include <stdlib.h>
15 #include <sys/types.h>
16 #include <sys/param.h>
17 #include <fcntl.h>
18 #include <sys/un.h>
19 #include <unistd.h>
20 #include <poll.h>
21 #include <sys/socket.h>
22 #include <sys/stat.h>
23 #include <sys/smack.h>
24 #include <sys/wait.h>
25 #include "security-server.h"
26 #include "security_server_clean_env.h"
27 #include <dpl/test/test_runner.h>
28 #include <dpl/test/test_runner_child.h>
29 #include <dlog.h>
30 #include <privilege-control.h>
31 #include <ftw.h>
32 #include "security_server_tests_common.h"
33 #include "tests_common.h"
34 #include <smack_access.h>
35 #include <access_provider.h>
36
37 const char *TEST03_SUBJECT = "subject_0f09f7cc";
38 const char *TEST04_SUBJECT = "subject_57dfbfc5";
39 const char *TEST07_SUBJECT = "subject_cd738844";
40 const char *TEST08_SUBJECT = "subject_fd84ba7f";
41
42 void clear_password()
43 {
44     int ret = -1;
45     unsigned int attempt, max_attempt, expire_sec;
46
47     reset_security_server();
48
49     attempt = max_attempt = expire_sec = UINT_MAX;
50     ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
51
52     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_PASSWORD, "ret: " << ret);
53     RUNNER_ASSERT(expire_sec == 0);
54     RUNNER_ASSERT(max_attempt == 0);
55     RUNNER_ASSERT(attempt == 0);
56
57     sleep(1);
58 }
59
60 void check_API_passwd(bool smack) {
61     int ret = -1;
62     int err, err_is_pwd_valid;
63     unsigned int attempt, max_attempt, expire_sec;
64
65     err = smack ? SECURITY_SERVER_API_ERROR_ACCESS_DENIED : SECURITY_SERVER_API_SUCCESS;
66     err_is_pwd_valid = smack ? SECURITY_SERVER_API_ERROR_ACCESS_DENIED : SECURITY_SERVER_API_ERROR_PASSWORD_EXIST;
67     attempt = max_attempt = expire_sec = 0;
68
69     if (smack) {
70         SecurityServer::AccessProvider privider(TEST04_SUBJECT);
71         privider.applyAndSwithToUser(APP_UID, APP_GID);
72     } else {
73         RUNNER_ASSERT_MSG((ret = drop_root_privileges()) == 0,
74                 "Failed to drop root privileges. Result: " << ret << "uid = " << getuid());
75     }
76
77     ret = security_server_set_pwd_validity(APP_UID);
78     RUNNER_ASSERT_MSG(ret == err,
79             "security_server_set_pwd_validity has failed,"
80             " ret: " << ret);
81
82     ret = security_server_set_pwd_max_challenge(5);
83     RUNNER_ASSERT_MSG(ret == err,
84             "security_server_set_pwd_max_challenge has failed,"
85             " ret: " << ret);
86
87     ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
88     RUNNER_ASSERT_MSG(ret == err_is_pwd_valid,
89             "security_server_is_pwd_valid should return password exist,"
90             " ret: " << ret);
91
92     usleep(PASSWORD_RETRY_TIMEOUT_US);
93     ret = security_server_set_pwd("12345", "12346", 0, 0);
94     RUNNER_ASSERT_MSG(ret == err,
95             "security_server_set_pwd has failed, ret: " << ret);
96
97     ret = security_server_reset_pwd("12346",0, 0);
98     RUNNER_ASSERT_MSG(ret == err,
99             "security_server_reset_pwd has failed, ret: " << ret);
100     usleep(PASSWORD_RETRY_TIMEOUT_US);
101     ret = security_server_chk_pwd("12346", &attempt, &max_attempt, &expire_sec);
102     RUNNER_ASSERT_MSG(ret == err,
103             "security_server_chk_pwd has failed, ret: " << ret);
104
105     ret = security_server_set_pwd_history(10);
106     RUNNER_ASSERT_MSG(ret == err,
107             "security_server_set_pwd_history has failed, ret: " << ret);
108 }
109
110 RUNNER_TEST_GROUP_INIT(SECURITY_SERVER_TESTS_SERVER);
111
112 RUNNER_TEST(tc_security_server_get_gid_normal_case_trying_to_get_gid_of_tel_gprs)
113 {
114     RUNNER_ASSERT(security_server_get_gid("tel_gprs") >= 0);
115 }
116
117 RUNNER_TEST(tc_security_server_get_gid_empty_object_name)
118 {
119     RUNNER_ASSERT(security_server_get_gid("") == SECURITY_SERVER_API_ERROR_INPUT_PARAM);
120 }
121
122 RUNNER_TEST(tc_security_server_get_gid_wrong_object_name_teltel)
123 {
124     RUNNER_ASSERT(security_server_get_gid("teltel") == SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT);
125 }
126
127 RUNNER_CHILD_TEST_SMACK(tc01a_security_server_app_give_access)
128 {
129     const char *subject = "abc345v34sfa";
130     const char *object = "efg678x2lkjz";
131
132     SecurityServer::AccessProvider provider(object);
133     provider.allowSS();
134     provider.applyAndSwithToUser(APP_UID, APP_GID);
135
136     security_server_app_give_access(subject, getpid());
137
138     RUNNER_ASSERT(1 == smack_have_access(subject, object, "rwxat"));
139 }
140
141 /*
142  * Currently we are NOT revoking any permissions given by
143  * security_server_app_give_access function
144  */
145 /*RUNNER_TEST(tc01b_security_server_app_give_access)
146 {
147     const char *subject = "abc345v34sfa";
148     const char *object = "efg678x2lkjz";
149
150     // After part A thread from security-server will be notified about
151     // process end and revoke permissions. We need to give him some
152     // time.
153     sleep(1);
154
155     RUNNER_ASSERT(0 == smack_have_access(subject, object, "r----"));
156     RUNNER_ASSERT(0 == smack_have_access(subject, object, "-w---"));
157     RUNNER_ASSERT(0 == smack_have_access(subject, object, "--x--"));
158     RUNNER_ASSERT(0 == smack_have_access(subject, object, "---a-"));
159     RUNNER_ASSERT(0 == smack_have_access(subject, object, "----t"));
160 }*/
161
162 RUNNER_CHILD_TEST_SMACK(tc01c_security_server_app_give_access_no_access)
163 {
164     const char *subject = "xxx45v34sfa";
165     const char *object = "yyy78x2lkjz";
166
167     SmackAccess smack;
168     smack.add(subject, object, "-----");
169     smack.apply();
170
171     RUNNER_ASSERT_MSG(0 == smack_set_label_for_self(object), "Error in smack_label_for_self");
172
173     RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
174
175     RUNNER_ASSERT(SECURITY_SERVER_API_ERROR_ACCESS_DENIED ==
176             security_server_app_give_access(subject, getpid()));
177
178     RUNNER_ASSERT(0 == smack_have_access(subject, object, "r"));
179 }
180
181 RUNNER_TEST_SMACK(tc02_check_privilege_by_pid)
182 {
183     RUNNER_IGNORED_MSG("security_server_check_privilege_by_pid is temporarily disabled: always returns success");
184     int ret;
185     int pid;
186
187     pid = getpid();
188
189     //we checking existing rule, it should return positive
190     ret = security_server_check_privilege_by_pid(pid, "_", "rx");
191     RUNNER_ASSERT(ret == SECURITY_SERVER_API_SUCCESS);
192
193     //we checking rule with label that not exist
194     ret = security_server_check_privilege_by_pid(pid, "thislabelisnotreal", "rwxat");
195     RUNNER_ASSERT(ret != SECURITY_SERVER_API_SUCCESS);
196 }
197
198 RUNNER_CHILD_TEST_SMACK(tc03_check_API_passwd_allow)
199 {
200     int ret = -1;
201     unsigned int attempt, max_attempt, expire_sec;
202
203     attempt = max_attempt = expire_sec = 0;
204
205     clear_password();
206
207     SecurityServer::AccessProvider provider(TEST03_SUBJECT);
208     provider.allowSS();
209     provider.applyAndSwithToUser(APP_UID, APP_GID);
210
211     ret = security_server_set_pwd_validity(10);
212     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_PASSWORD, "ret: " << ret);
213
214     ret = security_server_set_pwd_max_challenge(5);
215     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_PASSWORD, "ret: " << ret);
216
217     ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
218     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_PASSWORD, "ret: " << ret);
219
220     usleep(PASSWORD_RETRY_TIMEOUT_US);
221     ret = security_server_set_pwd(nullptr, "12345", 0, 0);
222     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS, "ret: " << ret);
223
224     ret = security_server_reset_pwd("12345",0, 0);
225     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS, "ret: " << ret);
226
227     usleep(PASSWORD_RETRY_TIMEOUT_US);
228     ret = security_server_chk_pwd("12345", &attempt, &max_attempt, &expire_sec);
229     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS, "ret: " << ret);
230
231     ret = security_server_set_pwd_history(10);
232     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS, "ret: " << ret);
233 }
234
235 RUNNER_CHILD_TEST_SMACK(tc04_check_API_passwd_denied)
236 {
237     check_API_passwd(true);
238 }
239
240 RUNNER_CHILD_TEST_NOSMACK(tc04_check_API_app_user_passwd_allow_nosmack)
241 {
242     check_API_passwd(false);
243 }
244
245 RUNNER_CHILD_TEST_SMACK(tc07_check_API_data_share_allow)
246 {
247     SecurityServer::AccessProvider provider(TEST07_SUBJECT);
248     provider.allowSS();
249     provider.applyAndSwithToUser(APP_UID, APP_GID);
250
251     int ret = security_server_app_give_access(TEST07_SUBJECT, getpid());
252     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS, "ret: " << ret);
253 }
254
255 RUNNER_CHILD_TEST_SMACK(tc08_check_API_data_share_denied)
256 {
257     SecurityServer::AccessProvider provider(TEST08_SUBJECT);
258     provider.applyAndSwithToUser(APP_UID, APP_GID);
259
260     int ret = security_server_app_give_access(TEST08_SUBJECT, getpid());
261     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED,
262             "security_server_app_give_access should return access denied,"
263             " ret: " << ret);
264 }
265
266 //////////////////////////////////////////
267 /////////NOSMACK ENV TESTS////////////////
268 //////////////////////////////////////////
269
270 /**
271  * NOSMACK version of tc01a and tc01c tests.
272  *
273  * SMACK is turned off - that means for us, that we don't need any accesses added to our process
274  * in SMACK before dropping root privileges. This test drops root privileges, calls
275  * security_server_app_give_access and then checks if smack_have_access returns error (because
276  * SMACK is off).
277  *
278  * security_server_app_give_access shouldn't return anything else than success when SMACK is off,
279  * hence there is only one test that replaces tests tc01a and tc01c.
280  */
281 RUNNER_CHILD_TEST_NOSMACK(tc01_security_server_app_give_access_nosmack)
282 {
283     const char* subject = "abc345v34sfa";
284     const char* object = "efg678x2lkjz";
285     int result = 0;
286
287     result = drop_root_privileges();
288     RUNNER_ASSERT_MSG(result == 0,
289             "Failed to drop root privileges. Result: " << result << "uid = " << getuid());
290
291     result = security_server_app_give_access(subject, getpid());
292     RUNNER_ASSERT_MSG(result == SECURITY_SERVER_API_SUCCESS,
293             "Error in security_server_app_give_access. Result: " << result);
294
295     result = smack_have_access(subject, object, "rwxat");
296     RUNNER_ASSERT_MSG(result == -1,
297             "smack_have_access should return error when SMACK is off. Result: " << result);
298 }
299
300 /**
301  * NOSMACK version of tc02 test.
302  *
303  * check_privilege_by_pid should always return success when SMACK is off, no matter if label is
304  * real or not.
305  */
306 RUNNER_TEST_NOSMACK(tc02_check_privilege_by_pid_nosmack)
307 {
308     RUNNER_IGNORED_MSG("security_server_check_privilege_by_pid is temporarily disabled: always returns success");
309     int ret;
310     int pid;
311
312     pid = getpid();
313
314     //we checking existing rule, it should return positive
315     ret = security_server_check_privilege_by_pid(pid, "_", "rx");
316     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
317             "check_privilege_by_pid for existing label failed. Result: " << ret);
318
319     //we checking rule with label that not exist
320     ret = security_server_check_privilege_by_pid(pid, "thislabelisnotreal", "rwxat");
321     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
322             "check_privilege_by_pid for nonexisting label failed. Result: " << ret);
323 }
324
325 /**
326  * NOSMACK version of clear_password function.
327  *
328  * Compared to SMACK version of this function, this one skips adding rules and setting label.
329  */
330 int clear_password_nosmack()
331 {
332     int ret = -1;
333     unsigned int attempt, max_attempt, expire_sec;
334
335     if (getuid() == 0) {
336         reset_security_server();
337
338         attempt = max_attempt = expire_sec = UINT_MAX;
339         ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
340
341         RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_PASSWORD,
342                 "is_pwd_faild should return no password error. Result: " << ret);
343         RUNNER_ASSERT_MSG(expire_sec == 0, "expire_sec = " << expire_sec << ", should be 0.");
344         RUNNER_ASSERT_MSG(max_attempt == 0, "max_attempt = " << max_attempt << ", should be 0.");
345         RUNNER_ASSERT_MSG(attempt == 0, "attempt = " << attempt << ", should be 0.");
346
347         return 0;
348     }
349     return -1;
350 }
351
352 /**
353  * NOSMACK version of tc03 test.
354  *
355  * Just as tc01a/tc01c NOSMACK replacement, we don't need to do anything with SMACK because most
356  * important functions will return errors (that is smack_accesses_apply/smack_have_access etc.).
357  * First clear password, then drop privileges and proceed to regular testing.
358  */
359
360 RUNNER_CHILD_TEST_NOSMACK(tc03_check_API_passwd_allow_nosmack)
361 {
362     int ret = -1;
363     unsigned int attempt, max_attempt, expire_sec;
364
365     attempt = max_attempt = expire_sec = 0;
366
367     clear_password_nosmack();
368
369     // drop root privileges
370     ret = drop_root_privileges();
371     RUNNER_ASSERT_MSG(ret == 0,
372             "Failed to drop root privileges. Result: " << ret << "uid = " << getuid());
373
374     ret = security_server_set_pwd_validity(10);
375     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_PASSWORD,
376             "set_pwd_validity should return no password error. Result: " << ret);
377
378     ret = security_server_set_pwd_max_challenge(5);
379     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_PASSWORD,
380             "set_pwd_max_challenge should return no password error. Result: " << ret);
381
382     ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
383     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_PASSWORD,
384             "is_pwd_valid should return no password error. Result: " << ret);
385
386     usleep(PASSWORD_RETRY_TIMEOUT_US);
387     ret = security_server_set_pwd(nullptr, "12345", 0, 0);
388     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
389             "set_pwd failed. Result: " << ret);
390
391     ret = security_server_reset_pwd("12345",0, 0);
392     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
393             "reset_pwd failed. Result: " << ret);
394
395     usleep(PASSWORD_RETRY_TIMEOUT_US);
396     ret = security_server_chk_pwd("12345", &attempt, &max_attempt, &expire_sec);
397     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
398             "chk_pwd failed. Result: " << ret);
399
400     ret = security_server_set_pwd_history(10);
401     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
402             "set_pwd_history failed. Result: " << ret);
403 }
404
405 /**
406  * NOSMACK version of tc07 test.
407  *
408  * Similarily to previous tests - no need to set self label because SMACK is off. Just as
409  * tc01a/tc01c replacement, security_server_app_give_access should return only success. Hence the
410  * NOSMACK version of tc08 test is skipped.
411  */
412 RUNNER_CHILD_TEST_NOSMACK(tc07_check_API_data_share_allow_nosmack)
413 {
414     int ret = -1;
415
416     // drop root privileges
417     ret = drop_root_privileges();
418     RUNNER_ASSERT_MSG(ret == 0,
419             "Failed to drop root privileges. Result: " << ret << "uid = " << getuid());
420
421     ret = security_server_app_give_access(TEST07_SUBJECT, getpid());
422     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
423             "app_give_access failed. Result: " << ret);
424 }
425
426 int main(int argc, char *argv[]) {
427     if (0 != getuid()) {
428         printf("Error: %s must be executed by root\n", argv[0]);
429         exit(1);
430     }
431     return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
432 }