Changing tests to run properly on RUNNER_MULTIPROCESS_TEST macro.
[platform/core/test/security-tests.git] / tests / security-server-tests / security_server_tests_client_smack.cpp
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
3  */
4 /*
5  * @file    security_server_tests_client_smack.cpp
6  * @author  Bartlomiej Grzelewski (b.grzelewski@samsung.com)
7  * @version 1.1
8  * @brief   Test cases for security-server-client-smack.
9  */
10
11 #include <unistd.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <sys/smack.h>
15 #include <sys/wait.h>
16 #include <sys/un.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <errno.h>
20
21 #include <memory>
22 #include <functional>
23
24 #include <dpl/log/log.h>
25 #include <dpl/test/test_runner.h>
26 #include <dpl/test/test_runner_child.h>
27 #include <dpl/test/test_runner_multiprocess.h>
28 #include "security_server_mockup.h"
29
30 #include <security-server.h>
31
32 #include "tests_common.h"
33
34 #define ENVIRONMENT                                                       \
35     do {                                                                  \
36         const char *subject_label = "mylabel";                            \
37         RUNNER_ASSERT_MSG(-1 != system("touch /opt/home/root/pid_cycle"), \
38             "Cannot prepare environment for test.");                      \
39         RUNNER_ASSERT_MSG(0 == smack_set_label_for_self(subject_label),   \
40             "Cannot prepare environment for test.");                      \
41         RUNNER_ASSERT_MSG(-1 != setgid(1),                                \
42             "Cannot prepare environment for test.");                      \
43         RUNNER_ASSERT_MSG(-1 != setuid(1),                                \
44             "Cannot prepare environment for test");                       \
45     } while (0)
46
47
48 /**
49  * Environment preparation should only differ in setting label. On NOSMACK system
50  * smack_set_label_for_self returns error because of no access to /proc/self/attr/current.
51  */
52 #define ENVIRONMENT_NOSMACK                                               \
53     do {                                                                  \
54         int fd = open("/opt/home/root/pid_cycle", O_CREAT|O_APPEND, 0444);\
55         RUNNER_ASSERT_MSG(fd >= 0,                                        \
56             "Couldn't create pid_cycle file. errno: " << strerror(errno));\
57         close(fd);                                                        \
58         RUNNER_ASSERT_MSG(-1 != setgid(1),                                \
59             "Cannot prepare environment for test.");                      \
60         RUNNER_ASSERT_MSG(-1 != setuid(1),                                \
61             "Cannot prepare environment for test");                       \
62     } while (0)
63
64 /**
65  * Unique_ptr typedef for NOSMACK version of tc06 test
66  */
67 void closesockfdptr(int* sockfd_ptr)
68 {
69     close(*sockfd_ptr);
70 }
71 typedef std::unique_ptr<int, std::function<void(int*)> > SockFDUniquePtr;
72
73 /**
74  * Dropping root privileges
75  * returns 0 on success, 1 on error
76  */
77 int drop_root_privileges()
78 {
79     if (getuid() == 0) {
80         /* process is running as root, drop privileges */
81         if (setgid(5000) != 0)
82             return 1;
83         if (setuid(5000) != 0)
84             return 1;
85     }
86     int uid = getuid();
87     if (uid == 5000)
88         return 0;
89
90     return 1;
91 }
92
93 RUNNER_TEST_GROUP_INIT(SECURITY_SERVER_TESTS_CLIENT_SMACK)
94
95 /*
96  * test: Check cookie size returned by security_server_get_cookie_size.
97  * description: Cookie used by security-server is 20 bytes long.
98  * Any other size of cookies should be treated as error.
99  * expected: Function security_server_get_cookie_size returns 20.
100  */
101 RUNNER_CHILD_TEST_SMACK(tc01_security_server_get_cookie_size)
102 {
103     ENVIRONMENT;
104
105     int ret = security_server_get_cookie_size();
106     RUNNER_ASSERT_MSG(20 == ret, "ret = " << ret);
107 }
108
109 /*
110  * test: security_server_request_cookie
111  * description: Function security_server_request_cookie will return
112  * 20 bytes long cookie.
113  * expected: function will set up cookie in the array and return
114  * SECURITY_SERVER_API_SUCCESS.
115  */
116 RUNNER_CHILD_TEST_SMACK(tc02_security_server_request_cookie_normal_case)
117 {
118     ENVIRONMENT;
119
120     char cookie[20];
121     int ret = security_server_request_cookie(cookie, 20);
122     LogDebug("ret = " << ret);
123     RUNNER_ASSERT(SECURITY_SERVER_API_SUCCESS == ret);
124 }
125
126 /*
127  * test: security_server_request_cookie
128  * description: Function security_server_request_cookie will return
129  * 20 bytes long cookie.
130  * expected: function will set up cookie in the array and return
131  * SECURITY_SERVER_API_SUCCESS.
132  */
133 RUNNER_CHILD_TEST_SMACK(tc03_security_server_request_cookie_too_small_buffer_size)
134 {
135     ENVIRONMENT;
136
137     char cookie[20];
138     int ret = security_server_request_cookie(cookie, 10);
139     LogDebug("ret = " << ret);
140     RUNNER_ASSERT(SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMALL == ret);
141 }
142
143 /*
144  * test: tc04_security_server_get_gid
145  * description: Checking for security_server_get_gid
146  *              with nonexisting gid and existing one
147  * expected: security_server_get_gid should return
148  *           SECURITY_SERVER_ERROR_NO_SUCH_OBJECT with first call
149  *           and group id with second call
150  */
151 RUNNER_CHILD_TEST_SMACK(tc04_security_server_get_gid)
152 {
153     ENVIRONMENT;
154
155     int ret = security_server_get_gid("abc123xyz_pysiaczek");
156     LogDebug("ret = " << ret);
157     RUNNER_ASSERT_MSG(SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT == ret, "Ret: " << ret);
158     ret = security_server_get_gid("root");
159     LogDebug("ret = " << ret);
160     RUNNER_ASSERT_MSG(0 == ret, "Ret: " << ret);
161 }
162
163 /*
164  * test: tc05_check_privilege_by_cookie
165  * description: Function security_server_check_privilege_by_cookie should
166  * return status of access rights of cookie owner. In this case cookie owner
167  * is the same process that ask for the rights.
168  * expected: Function call with access rights set to "r" should return SUCCESS,
169  * with "rw" should return ACCESS DENIED.
170  */
171 RUNNER_CHILD_TEST_SMACK(tc05_check_privilege_by_cookie)
172 {
173     char cookie[20];
174     const char *object_label = "tc05objectlabel";
175     const char *access_rights = "r";
176     const char *access_rights_ext = "rw";
177     const char *subject_label = "tc05subjectlabel";
178
179     smack_accesses *handle;
180
181     RUNNER_ASSERT(0 == smack_accesses_new(&handle));
182
183     RUNNER_ASSERT(0 == smack_accesses_add(handle,
184             subject_label,
185             object_label,
186             access_rights));
187
188     RUNNER_ASSERT(0 == smack_accesses_apply(handle));
189
190     smack_accesses_free(handle);
191
192     RUNNER_ASSERT(0 == smack_set_label_for_self(subject_label));
193
194     RUNNER_ASSERT(SECURITY_SERVER_API_SUCCESS ==
195         security_server_request_cookie(cookie,20));
196
197     RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
198
199     RUNNER_ASSERT(SECURITY_SERVER_API_SUCCESS ==
200         security_server_check_privilege_by_cookie(
201             cookie,
202             object_label,
203             access_rights));
204
205     RUNNER_ASSERT(SECURITY_SERVER_API_ERROR_ACCESS_DENIED ==
206         security_server_check_privilege_by_cookie(
207             cookie,
208             object_label,
209             access_rights_ext));
210 }
211
212 /*
213  * test: security_server_check_privilege_by_sockfd
214  * description: This test will create dummy server that will accept connection
215  * and die. The client will try to check access rights using connection descriptor.
216  * expected: Function call with access rights set to "r" should return SUCCESS,
217  * with "rw" should return ACCESS DENIED.
218  */
219 RUNNER_MULTIPROCESS_TEST_SMACK(tc06_check_privilege_by_sockfd)
220 {
221     const char *object_label = "tc06objectlabel";
222     const char *access_rights = "r";
223     const char *access_rights_ext = "rw";
224     const char *subject_label = "tc06subjectlabel";
225
226     int result1 = -1;
227     int result2 = -1;
228
229     smack_accesses *handle;
230     RUNNER_ASSERT(0 == smack_accesses_new(&handle));
231     RUNNER_ASSERT(0 == smack_accesses_add(handle,
232             subject_label,
233             object_label,
234             access_rights));
235     RUNNER_ASSERT(0 == smack_accesses_apply(handle));
236     smack_accesses_free(handle);
237
238     int pid = fork();
239     char *label;
240     RUNNER_ASSERT(-1 != pid);
241
242     if (0 == pid) {
243         // child
244         RUNNER_ASSERT_MSG(0 == smack_set_label_for_self(subject_label), "child label " << subject_label << " not set");
245
246         int sockfd = create_new_socket();
247         RUNNER_ASSERT_MSG(sockfd >= 0, "create_new_socket() failed");
248
249         SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
250
251         label = security_server_get_smacklabel_sockfd(sockfd);
252         RUNNER_ASSERT_MSG(label != NULL, "security_server_get_smacklabel_sockfd failed");
253         RUNNER_ASSERT_MSG(strcmp(label,"") == 0, "label is \"" << label << "\"");
254         free(label);
255
256         RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
257
258         RUNNER_ASSERT_MSG(listen(sockfd, 5) >= 0, "child listen failed");
259
260         label = security_server_get_smacklabel_sockfd(sockfd);
261         RUNNER_ASSERT_MSG(label != NULL, "security_server_get_smacklabel_sockfd failed");
262         RUNNER_ASSERT_MSG(strcmp(label,"") == 0, "label is \"" << label << "\"");
263         free(label);
264
265         struct sockaddr_un client_addr;
266         socklen_t client_len = sizeof(client_addr);
267         int csockfd;
268         RUNNER_ASSERT_MSG((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) > 0, "child accept failed");
269
270         usleep(500);
271
272         close(csockfd);
273         exit(0);
274     } else {
275         // parent
276         sleep(1);
277         int sockfd = connect_to_testserver();
278         RUNNER_ASSERT_MSG(sockfd >= 0, "connect_to_testserver() failed");
279
280         SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
281
282         label = security_server_get_smacklabel_sockfd(sockfd);
283         RUNNER_ASSERT_MSG(label != NULL, "security_server_get_smacklabel_sockfd failed");
284         RUNNER_ASSERT_MSG(strcmp(label,subject_label) == 0, "label is \"" << label << "\"" << ", subject_label is \"" << subject_label << "\"" );
285         free(label);
286
287         result1 = security_server_check_privilege_by_sockfd(
288             sockfd,
289             object_label,
290             access_rights);
291         result2 = security_server_check_privilege_by_sockfd(
292             sockfd,
293             object_label,
294             access_rights_ext);
295     }
296
297     RUNNER_ASSERT_MSG(SECURITY_SERVER_API_SUCCESS == result1, "result = " << result1);
298     RUNNER_ASSERT_MSG(SECURITY_SERVER_API_ERROR_ACCESS_DENIED == result2, "result = " << result2);
299 }
300
301 /*
302  * test: security_server_check_privilege_by_sockfd
303  * description: This test will create dummy server that will accept connection
304  * and die. The client will try to check access rights using connection descriptor.
305  * Because we read a smack label not from socket directly, but from from pid of process
306  * on the other end of socket - that's why smack label will be updated.
307  * In this test client is running under root and server is not - to test the extreme case.
308  * expected: Function call with access rights set to "r" should return SUCCESS,
309  * with "rw" should return ACCESS DENIED.
310  */
311 RUNNER_MULTIPROCESS_TEST_SMACK(tc07_check_privilege_by_sockfd)
312 {
313     const char *object_label = "tc07objectlabel";
314     const char *access_rights = "r";
315     const char *access_rights_ext = "rw";
316     const char *subject_label = "tc07subjectlabel";
317
318     int result1 = -1;
319     int result2 = -1;
320
321     smack_accesses *handle;
322     RUNNER_ASSERT(0 == smack_accesses_new(&handle));
323     RUNNER_ASSERT(0 == smack_accesses_add(handle,
324             subject_label,
325             object_label,
326             access_rights));
327     RUNNER_ASSERT(0 == smack_accesses_apply(handle));
328     smack_accesses_free(handle);
329
330     int pid = fork();
331     RUNNER_ASSERT(-1 != pid);
332
333     if (0 == pid) {
334         // child
335         int sockfd = create_new_socket();
336         RUNNER_ASSERT_MSG(sockfd >= 0, "create_new_socket() failed");
337
338         SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
339
340         RUNNER_ASSERT_MSG(0 == smack_set_label_for_self(subject_label), "child label " << subject_label << " not set");
341
342         RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
343
344         RUNNER_ASSERT_MSG(listen(sockfd, 5) >= 0, "child listen failed");
345
346         struct sockaddr_un client_addr;
347         socklen_t client_len = sizeof(client_addr);
348         int csockfd;
349         RUNNER_ASSERT_MSG((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) > 0, "child accept failed");
350
351         usleep(500);
352
353         close(csockfd);
354         exit(0);
355     } else {
356         // parent
357
358         RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
359
360         sleep(1);
361         int sockfd = connect_to_testserver();
362         RUNNER_ASSERT_MSG(sockfd >= 0, "connect_to_testserver() failed");
363
364         result1 = security_server_check_privilege_by_sockfd(
365             sockfd,
366             object_label,
367             access_rights);
368         result2 = security_server_check_privilege_by_sockfd(
369             sockfd,
370             object_label,
371             access_rights_ext);
372
373         close(sockfd);
374     }
375
376     RUNNER_ASSERT_MSG(SECURITY_SERVER_API_SUCCESS == result1, "result1 = " << result1);
377     RUNNER_ASSERT_MSG(SECURITY_SERVER_API_ERROR_ACCESS_DENIED == result2, " result2 = " << result2);
378 }
379
380 ///////////////////////////
381 /////NOSMACK ENV TESTS/////
382 ///////////////////////////
383
384 /**
385  * First four test cases are the same as their SMACK versions. The only difference is environment
386  * preparation (described near ENVIRONMENT_NOSMACK macro).
387  */
388 RUNNER_CHILD_TEST_NOSMACK(tc01_security_server_get_cookie_size_nosmack)
389 {
390     ENVIRONMENT_NOSMACK;
391
392     int ret = security_server_get_cookie_size();
393     RUNNER_ASSERT_MSG(ret == 20, "ret = " << ret);
394 }
395
396 RUNNER_CHILD_TEST_NOSMACK(tc02_security_server_request_cookie_normal_case_nosmack)
397 {
398     ENVIRONMENT_NOSMACK;
399
400     char cookie[20];
401     int ret = security_server_request_cookie(cookie, 20);
402     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS, "ret = " << ret);
403 }
404
405 RUNNER_CHILD_TEST_NOSMACK(tc03_security_server_request_cookie_too_small_buffer_size_nosmack)
406 {
407     ENVIRONMENT_NOSMACK;
408
409     char cookie[20];
410     int ret = security_server_request_cookie(cookie, 10);
411     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMALL, "ret = " << ret);
412 }
413
414 RUNNER_CHILD_TEST_NOSMACK(tc04_security_server_get_gid_nosmack)
415 {
416     ENVIRONMENT_NOSMACK;
417
418     int ret = security_server_get_gid("definitely_not_existing_object");
419     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT, "ret = " << ret);
420     ret = security_server_get_gid("root");
421     RUNNER_ASSERT_MSG(ret == 0, "ret = " << ret);
422 }
423
424 /*
425  * NOSMACK version of tc05 test.
426  *
427  * Correct behaviour of smack_accesses_apply and smack_set_label_for_self was checked by libsmack
428  * tests. We assume, that those tests pass. Additionally security_server_check_privilege_by_cookie
429  * should return SUCCESS no matter what access_rights we give to this function.
430  */
431 RUNNER_CHILD_TEST_NOSMACK(tc05_check_privilege_by_cookie_nosmack)
432 {
433     char cookie[20];
434     const char* object_label = "tc05objectlabel";
435
436     RUNNER_ASSERT(security_server_request_cookie(cookie,20) == SECURITY_SERVER_API_SUCCESS);
437
438     RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
439
440     RUNNER_ASSERT(SECURITY_SERVER_API_SUCCESS ==
441         security_server_check_privilege_by_cookie(cookie, object_label, "r"));
442
443     //On NOSMACK env security server should return success on any accesses, even those that are
444     //incorrect.
445     RUNNER_ASSERT(SECURITY_SERVER_API_SUCCESS ==
446         security_server_check_privilege_by_cookie(cookie, object_label, "rw"));
447 }
448
449 /**
450  * NOSMACK version of tc06 test.
451  *
452  * Differences between this and SMACK version (server):
453  * - Skipped setting access_rights
454  * - Skipped setting label for server
455  * - get_smacklabel_sockfd is called only once for server, almost right after fork and creation
456  *   of socket (because it should do nothing when SMACK is off)
457  * - After get_smacklabel_sockfd privileges are dropped and server is prepared to accept connections
458  *   from client
459  *
460  * For client the only difference are expected results from check_privilege_by_sockfd - both should
461  * return SUCCESS.
462  */
463 RUNNER_MULTIPROCESS_TEST_NOSMACK(tc06_check_privilege_by_sockfd_nosmack)
464 {
465     const char* object_label = "tc06objectlabel";
466
467     int result1 = -1;
468     int result2 = -1;
469
470     int pid = fork();
471     char* label;
472     RUNNER_ASSERT(pid >= 0);
473
474     int ret;
475
476     if (pid == 0) { //child process - server
477         //create new socket
478         int sockfd = create_new_socket();
479         RUNNER_ASSERT_MSG(sockfd >= 0, "create_new_socket() failed");
480
481         SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
482
483         //check if get_smacklabel_sockfd works correctly
484         label = security_server_get_smacklabel_sockfd(sockfd);
485         RUNNER_ASSERT_MSG(label != NULL, "security_server_get_smacklabel_sockfd failed");
486         ret = strcmp(label, "");
487         free(label);
488         RUNNER_ASSERT_MSG(ret == 0, "label is \"" << label << "\"");
489
490         RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
491
492         RUNNER_ASSERT_MSG(listen(sockfd, 5) >= 0, "child listen failed");
493
494         struct sockaddr_un client_addr;
495         socklen_t client_len = sizeof(client_addr);
496
497         int csockfd;
498         RUNNER_ASSERT_MSG((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) > 0, "child accept failed");
499
500         //wait a little bit for parent to do it's job
501         usleep(200);
502
503         //if everything works, cleanup and return 0
504         close(csockfd);
505         exit(0);
506     } else {
507         //parent
508         sleep(1);
509         int sockfd = connect_to_testserver();
510         RUNNER_ASSERT_MSG(sockfd >= 0, "Failed to connect to server.");
511
512         SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
513
514         label = security_server_get_smacklabel_sockfd(sockfd);
515         RUNNER_ASSERT_MSG(label != NULL, "get_smacklabel_sockfd failed.");
516         ret = strcmp(label, "");
517         free(label);
518         RUNNER_ASSERT_MSG(ret == 0, "label is \"" << label << "\"");
519
520         result1 = security_server_check_privilege_by_sockfd(sockfd, object_label, "r");
521         result2 = security_server_check_privilege_by_sockfd(sockfd, object_label, "rw");
522     }
523
524     RUNNER_ASSERT_MSG(result1 == SECURITY_SERVER_API_SUCCESS, "result = " << result1);
525     RUNNER_ASSERT_MSG(result2 == SECURITY_SERVER_API_SUCCESS, "result = " << result2);
526 }
527
528 /**
529  * NOSMACK version of tc07 test.
530  */
531 RUNNER_MULTIPROCESS_TEST_NOSMACK(tc07_check_privilege_by_sockfd_nosmack)
532 {
533     const char* object_label = "tc07objectlabel";
534
535     int result1 = -1;
536     int result2 = -1;
537
538     int pid = fork();
539     RUNNER_ASSERT(-1 != pid);
540
541     if (pid == 0) { //child process
542         //Create socket
543         int sockfd = create_new_socket();
544         RUNNER_ASSERT_MSG(sockfd >= 0, "create_new_socket() failed");
545
546         SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
547
548         //Drop privileges
549         RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
550
551         //Prepare for accepting
552         RUNNER_ASSERT_MSG(listen(sockfd, 5) >= 0, "child listen failed");
553
554         struct sockaddr_un client_addr;
555         socklen_t client_len = sizeof(client_addr);
556
557         //Accept connections
558         int csockfd;
559         RUNNER_ASSERT_MSG((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) > 0, "child accept failed");
560
561         //wait a little bit for parent to do it's job
562         usleep(200);
563
564         //cleanup and kill child
565         close(csockfd);
566         exit(0);
567     } else {    //parent process
568         //Drop root privileges
569         RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
570
571         //Wait for server to set up
572         sleep(1);
573
574         //Connect and check privileges
575         int sockfd = connect_to_testserver();
576         RUNNER_ASSERT_MSG(sockfd >= 0, "Failed to create socket fd.");
577
578         result1 = security_server_check_privilege_by_sockfd(sockfd, object_label, "r");
579         result2 = security_server_check_privilege_by_sockfd(sockfd, object_label, "rw");
580
581         close(sockfd);
582     }
583
584     //Both results (just like in the previous test case) should return success.
585     RUNNER_ASSERT_MSG(SECURITY_SERVER_API_SUCCESS == result1, "result1 = " << result1);
586     RUNNER_ASSERT_MSG(SECURITY_SERVER_API_SUCCESS == result2, "result2 = " << result2);
587 }
588
589 ////////////////////
590 /////MAIN///////////
591 ////////////////////
592
593 int main(int argc, char *argv[])
594 {
595     return
596         DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
597 }