Removed use of pid_cycle file and ENVIRONMENT macros
[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 <stdlib.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <sys/smack.h>
16 #include <sys/wait.h>
17 #include <sys/un.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
20 #include <errno.h>
21
22 #include <memory>
23 #include <functional>
24
25 #include <dpl/log/log.h>
26 #include <dpl/test/test_runner.h>
27 #include <dpl/test/test_runner_child.h>
28 #include <dpl/test/test_runner_multiprocess.h>
29 #include "security_server_mockup.h"
30
31 #include <security-server.h>
32 #include <access_provider.h>
33 #include "tests_common.h"
34 #include <summary_collector.h>
35
36
37 #define PROPER_COOKIE_SIZE 20
38
39 /**
40  * Unique_ptr typedef for NOSMACK version of tc06 test
41  */
42 void closesockfdptr(int* sockfd_ptr)
43 {
44     close(*sockfd_ptr);
45 }
46 typedef std::unique_ptr<int, std::function<void(int*)> > SockFDUniquePtr;
47
48 RUNNER_TEST_GROUP_INIT(SECURITY_SERVER_TESTS_CLIENT_SMACK)
49
50 /*
51  * test: tc04_security_server_get_gid
52  * description: Checking for security_server_get_gid
53  *              with nonexisting gid and existing one
54  * expected: security_server_get_gid should return
55  *           SECURITY_SERVER_ERROR_NO_SUCH_OBJECT with first call
56  *           and group id with second call
57  */
58 RUNNER_CHILD_TEST_SMACK(tc04_security_server_get_gid)
59 {
60     SecurityServer::AccessProvider provider("tc04mylabel");
61     provider.allowFunction("security_server_get_gid");
62     provider.applyAndSwithToUser(APP_UID, APP_GID);
63
64     int ret = security_server_get_gid("abc123xyz_pysiaczek");
65     LogDebug("ret = " << ret);
66     RUNNER_ASSERT_MSG_BT(SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT == ret, "Ret: " << ret);
67     ret = security_server_get_gid("root");
68     LogDebug("ret = " << ret);
69     RUNNER_ASSERT_MSG_BT(0 == ret, "Ret: " << ret);
70 }
71
72 /*
73  * test: tc05_check_privilege_by_cookie
74  * description: Function security_server_check_privilege_by_cookie should
75  * return status of access rights of cookie owner. In this case cookie owner
76  * is the same process that ask for the rights.
77  * expected: Function call with access rights set to "r" should return SUCCESS,
78  * with "rw" should return ACCESS DENIED.
79  */
80 RUNNER_CHILD_TEST_SMACK(tc05_check_privilege_by_cookie)
81 {
82     char cookie[20];
83     const char *object_label = "tc05objectlabel";
84     const char *access_rights = "r";
85     const char *access_rights_ext = "rw";
86     const char *subject_label = "tc05subjectlabel";
87
88     SmackAccess access;
89     access.add(subject_label, object_label, access_rights);
90     access.add(subject_label, "security-server::api-cookie-check", "w");
91     access.apply();
92
93     RUNNER_ASSERT_BT(0 == smack_set_label_for_self(subject_label));
94
95     RUNNER_ASSERT_BT(SECURITY_SERVER_API_SUCCESS ==
96         security_server_request_cookie(cookie,20));
97
98     RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
99
100     RUNNER_ASSERT_BT(SECURITY_SERVER_API_SUCCESS ==
101         security_server_check_privilege_by_cookie(
102             cookie,
103             object_label,
104             access_rights));
105
106     RUNNER_ASSERT_BT(SECURITY_SERVER_API_ERROR_ACCESS_DENIED ==
107         security_server_check_privilege_by_cookie(
108             cookie,
109             object_label,
110             access_rights_ext));
111 }
112
113 /*
114  * test: security_server_check_privilege_by_sockfd
115  * description: This test will create dummy server that will accept connection
116  * and die. The client will try to check access rights using connection descriptor.
117  * expected: Function call with access rights set to "r" should return SUCCESS,
118  * with "rw" should return ACCESS DENIED.
119  */
120 RUNNER_MULTIPROCESS_TEST_SMACK(tc06_check_privilege_by_sockfd)
121 {
122     const char *object_label = "tc06objectlabel";
123     const char *access_rights = "r";
124     const char *access_rights_ext = "rw";
125     const char *subject_label = "tc06subjectlabel";
126
127     int result1 = -1;
128     int result2 = -1;
129
130     smack_accesses *handle;
131     RUNNER_ASSERT_BT(0 == smack_accesses_new(&handle));
132     RUNNER_ASSERT_BT(0 == smack_accesses_add(handle,
133             subject_label,
134             object_label,
135             access_rights));
136     RUNNER_ASSERT_BT(0 == smack_accesses_apply(handle));
137     smack_accesses_free(handle);
138
139     int pid = fork();
140     char *label;
141     RUNNER_ASSERT_BT(-1 != pid);
142
143     if (0 == pid) {
144         // child
145         RUNNER_ASSERT_MSG_BT(0 == smack_set_label_for_self(subject_label), "child label " << subject_label << " not set");
146
147         int sockfd = create_new_socket();
148         RUNNER_ASSERT_MSG_BT(sockfd >= 0, "create_new_socket() failed");
149
150         SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
151
152         label = security_server_get_smacklabel_sockfd(sockfd);
153         RUNNER_ASSERT_MSG_BT(label != NULL, "security_server_get_smacklabel_sockfd failed");
154         RUNNER_ASSERT_MSG_BT(strcmp(label,"") == 0, "label is \"" << label << "\"");
155         free(label);
156
157         RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
158
159         RUNNER_ASSERT_MSG_BT(listen(sockfd, 5) >= 0, "child listen failed");
160
161         label = security_server_get_smacklabel_sockfd(sockfd);
162         RUNNER_ASSERT_MSG_BT(label != NULL, "security_server_get_smacklabel_sockfd failed");
163         RUNNER_ASSERT_MSG_BT(strcmp(label,"") == 0, "label is \"" << label << "\"");
164         free(label);
165
166         struct sockaddr_un client_addr;
167         socklen_t client_len = sizeof(client_addr);
168         int csockfd;
169         RUNNER_ASSERT_MSG_BT((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) > 0, "child accept failed");
170
171         usleep(500);
172
173         close(csockfd);
174         exit(0);
175     } else {
176         // parent
177         sleep(1);
178         int sockfd = connect_to_testserver();
179         RUNNER_ASSERT_MSG_BT(sockfd >= 0, "connect_to_testserver() failed");
180
181         SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
182
183         label = security_server_get_smacklabel_sockfd(sockfd);
184         RUNNER_ASSERT_MSG_BT(label != NULL, "security_server_get_smacklabel_sockfd failed");
185         RUNNER_ASSERT_MSG_BT(strcmp(label,subject_label) == 0, "label is \"" << label << "\"" << ", subject_label is \"" << subject_label << "\"" );
186         free(label);
187
188         result1 = security_server_check_privilege_by_sockfd(
189             sockfd,
190             object_label,
191             access_rights);
192         result2 = security_server_check_privilege_by_sockfd(
193             sockfd,
194             object_label,
195             access_rights_ext);
196     }
197
198     RUNNER_ASSERT_MSG_BT(SECURITY_SERVER_API_SUCCESS == result1, "result = " << result1);
199     RUNNER_ASSERT_MSG_BT(SECURITY_SERVER_API_ERROR_ACCESS_DENIED == result2, "result = " << result2);
200 }
201
202 /*
203  * test: security_server_check_privilege_by_sockfd
204  * description: This test will create dummy server that will accept connection
205  * and die. The client will try to check access rights using connection descriptor.
206  * Because we read a smack label not from socket directly, but from from pid of process
207  * on the other end of socket - that's why smack label will be updated.
208  * In this test client is running under root and server is not - to test the extreme case.
209  * expected: Function call with access rights set to "r" should return SUCCESS,
210  * with "rw" should return ACCESS DENIED.
211  */
212 RUNNER_MULTIPROCESS_TEST_SMACK(tc07_check_privilege_by_sockfd)
213 {
214     const char *object_label = "tc07objectlabel";
215     const char *access_rights = "r";
216     const char *access_rights_ext = "rw";
217     const char *subject_label = "tc07subjectlabel";
218
219     int result1 = -1;
220     int result2 = -1;
221
222     SmackAccess access;
223     access.add(subject_label, object_label, access_rights);
224     access.apply();
225
226     int pid = fork();
227     RUNNER_ASSERT_BT(-1 != pid);
228
229     if (0 == pid) {
230
231         pid = fork();
232         RUNNER_ASSERT_BT(-1 != pid);
233
234         if (0 == pid) {
235             // child
236             int sockfd = create_new_socket();
237             RUNNER_ASSERT_MSG_BT(sockfd >= 0, "create_new_socket() failed");
238
239             SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
240
241             RUNNER_ASSERT_MSG_BT(0 == smack_set_label_for_self(subject_label), "child label " << subject_label << " not set");
242
243             RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
244
245             RUNNER_ASSERT_MSG_BT(listen(sockfd, 5) >= 0, "child listen failed");
246
247             struct sockaddr_un client_addr;
248             socklen_t client_len = sizeof(client_addr);
249             int csockfd = TEMP_FAILURE_RETRY(accept(sockfd,(struct sockaddr*)&client_addr, &client_len));
250             if (csockfd >= 0)
251                 close(csockfd);
252             LogDebug("Exit!");
253             exit(0);
254         } else {
255             // parent
256             sleep(1);
257             int sockfd = connect_to_testserver();
258             RUNNER_ASSERT_MSG_BT(sockfd >= 0, "connect_to_testserver() failed");
259
260             result1 = security_server_check_privilege_by_sockfd(
261                 sockfd,
262                 object_label,
263                 access_rights);
264             result2 = security_server_check_privilege_by_sockfd(
265                 sockfd,
266                 object_label,
267                 access_rights_ext);
268
269             close(sockfd);
270
271             RUNNER_ASSERT_MSG_BT(SECURITY_SERVER_API_SUCCESS == result1, "result1 = " << result1);
272             RUNNER_ASSERT_MSG_BT(SECURITY_SERVER_API_ERROR_ACCESS_DENIED == result2, " result2 = " << result2);
273         }
274     }
275 }
276
277 ///////////////////////////
278 /////NOSMACK ENV TESTS/////
279 ///////////////////////////
280
281 RUNNER_CHILD_TEST_NOSMACK(tc04_security_server_get_gid_nosmack)
282 {
283     int ret;
284
285     ret = drop_root_privileges();
286     RUNNER_ASSERT_MSG_BT(ret == 0,
287             "Failed to drop root privileges. Result: " << ret << "uid = " << getuid());
288
289     ret = security_server_get_gid("definitely_not_existing_object");
290     RUNNER_ASSERT_MSG_BT(ret == SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT, "ret = " << ret);
291     ret = security_server_get_gid("root");
292     RUNNER_ASSERT_MSG_BT(ret == 0, "ret = " << ret);
293 }
294
295 /*
296  * NOSMACK version of tc05 test.
297  *
298  * Correct behaviour of smack_accesses_apply and smack_set_label_for_self was checked by libsmack
299  * tests. We assume, that those tests pass. Additionally security_server_check_privilege_by_cookie
300  * should return SUCCESS no matter what access_rights we give to this function.
301  */
302 RUNNER_CHILD_TEST_NOSMACK(tc05_check_privilege_by_cookie_nosmack)
303 {
304     char cookie[20];
305     const char* object_label = "tc05objectlabel";
306
307     RUNNER_ASSERT_BT(security_server_request_cookie(cookie,20) == SECURITY_SERVER_API_SUCCESS);
308
309     RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
310
311     RUNNER_ASSERT_BT(SECURITY_SERVER_API_SUCCESS ==
312         security_server_check_privilege_by_cookie(cookie, object_label, "r"));
313
314     //On NOSMACK env security server should return success on any accesses, even those that are
315     //incorrect.
316     RUNNER_ASSERT_BT(SECURITY_SERVER_API_SUCCESS ==
317         security_server_check_privilege_by_cookie(cookie, object_label, "rw"));
318 }
319
320 /**
321  * NOSMACK version of tc06 test.
322  *
323  * Differences between this and SMACK version (server):
324  * - Skipped setting access_rights
325  * - Skipped setting label for server
326  * - get_smacklabel_sockfd is called only once for server, almost right after fork and creation
327  *   of socket (because it should do nothing when SMACK is off)
328  * - After get_smacklabel_sockfd privileges are dropped and server is prepared to accept connections
329  *   from client
330  *
331  * For client the only difference are expected results from check_privilege_by_sockfd - both should
332  * return SUCCESS.
333  */
334 RUNNER_MULTIPROCESS_TEST_NOSMACK(tc06_check_privilege_by_sockfd_nosmack)
335 {
336     const char* object_label = "tc06objectlabel";
337
338     int result1 = -1;
339     int result2 = -1;
340
341     int pid = fork();
342     char* label;
343     RUNNER_ASSERT_BT(pid >= 0);
344
345     int ret;
346
347     if (pid == 0) { //child process - server
348         //create new socket
349         int sockfd = create_new_socket();
350         RUNNER_ASSERT_MSG_BT(sockfd >= 0, "create_new_socket() failed");
351
352         SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
353
354         //check if get_smacklabel_sockfd works correctly
355         label = security_server_get_smacklabel_sockfd(sockfd);
356         RUNNER_ASSERT_MSG_BT(label != NULL, "security_server_get_smacklabel_sockfd failed");
357         ret = strcmp(label, "");
358         free(label);
359         RUNNER_ASSERT_MSG_BT(ret == 0, "label is \"" << label << "\"");
360
361         RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
362
363         RUNNER_ASSERT_MSG_BT(listen(sockfd, 5) >= 0, "child listen failed");
364
365         struct sockaddr_un client_addr;
366         socklen_t client_len = sizeof(client_addr);
367
368         int csockfd;
369         RUNNER_ASSERT_MSG_BT((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) > 0, "child accept failed");
370
371         //wait a little bit for parent to do it's job
372         usleep(200);
373
374         //if everything works, cleanup and return 0
375         close(csockfd);
376         exit(0);
377     } else {
378         //parent
379         sleep(1);
380         int sockfd = connect_to_testserver();
381         RUNNER_ASSERT_MSG_BT(sockfd >= 0, "Failed to connect to server.");
382
383         SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
384
385         label = security_server_get_smacklabel_sockfd(sockfd);
386         RUNNER_ASSERT_MSG_BT(label != NULL, "get_smacklabel_sockfd failed.");
387         ret = strcmp(label, "");
388         free(label);
389         RUNNER_ASSERT_MSG_BT(ret == 0, "label is \"" << label << "\"");
390
391         result1 = security_server_check_privilege_by_sockfd(sockfd, object_label, "r");
392         result2 = security_server_check_privilege_by_sockfd(sockfd, object_label, "rw");
393     }
394
395     RUNNER_ASSERT_MSG_BT(result1 == SECURITY_SERVER_API_SUCCESS, "result = " << result1);
396     RUNNER_ASSERT_MSG_BT(result2 == SECURITY_SERVER_API_SUCCESS, "result = " << result2);
397 }
398
399 /**
400  * NOSMACK version of tc07 test.
401  */
402 RUNNER_MULTIPROCESS_TEST_NOSMACK(tc07_check_privilege_by_sockfd_nosmack)
403 {
404     const char* object_label = "tc07objectlabel";
405
406     int result1 = -1;
407     int result2 = -1;
408
409     int pid = fork();
410     RUNNER_ASSERT_BT(-1 != pid);
411
412     if (pid == 0) {
413
414         pid = fork();
415         RUNNER_ASSERT_BT(-1 != pid);
416
417         if (pid == 0) { //child process
418             //Create socket
419             int sockfd = create_new_socket();
420             RUNNER_ASSERT_MSG_BT(sockfd >= 0, "create_new_socket() failed");
421
422             SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
423
424             //Drop privileges
425             RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
426
427             //Prepare for accepting
428             RUNNER_ASSERT_MSG_BT(listen(sockfd, 5) >= 0, "child listen failed");
429
430             struct sockaddr_un client_addr;
431             socklen_t client_len = sizeof(client_addr);
432
433             //Accept connections
434             int csockfd;
435             RUNNER_ASSERT_MSG_BT((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) > 0, "child accept failed");
436
437             //wait a little bit for parent to do it's job
438             usleep(200);
439
440             //cleanup and kill child
441             close(csockfd);
442             exit(0);
443         } else {    //parent process
444             //Drop root privileges
445             RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
446
447             //Wait for server to set up
448             sleep(1);
449
450             //Connect and check privileges
451             int sockfd = connect_to_testserver();
452             RUNNER_ASSERT_MSG_BT(sockfd >= 0, "Failed to create socket fd.");
453
454             result1 = security_server_check_privilege_by_sockfd(sockfd, object_label, "r");
455             result2 = security_server_check_privilege_by_sockfd(sockfd, object_label, "rw");
456
457             close(sockfd);
458
459             //Both results (just like in the previous test case) should return success.
460             RUNNER_ASSERT_MSG_BT(SECURITY_SERVER_API_SUCCESS == result1, "result1 = " << result1);
461             RUNNER_ASSERT_MSG_BT(SECURITY_SERVER_API_SUCCESS == result2, "result2 = " << result2);
462         }
463     }
464 }
465
466 RUNNER_TEST_SMACK(tc18_security_server_get_smacklabel_cookie) {
467     int res;
468
469     char *label_smack = NULL;
470     char *label_ss = NULL;
471     char *cookie = NULL;
472
473     int cookie_size = security_server_get_cookie_size();
474     RUNNER_ASSERT_MSG_BT(PROPER_COOKIE_SIZE == cookie_size, "Wrong cookie size from security-server");
475
476     cookie = (char*) calloc(cookie_size, 1);
477     RUNNER_ASSERT_MSG_BT(NULL != cookie, "Memory allocation error");
478
479     res = security_server_request_cookie(cookie, cookie_size);
480     if (res != SECURITY_SERVER_API_SUCCESS) {
481         free(cookie);
482         RUNNER_ASSERT_MSG_BT(res == SECURITY_SERVER_API_SUCCESS, "Error in requesting cookie from security-server");
483     }
484
485     label_ss = security_server_get_smacklabel_cookie(cookie);
486     free(cookie);
487     RUNNER_ASSERT_MSG_BT(label_ss != NULL, "Error in getting label by cookie");
488
489
490     std::string label_cookie(label_ss);
491     free(label_ss);
492
493     res = smack_new_label_from_self(&label_smack);
494     if (res < 0) {
495         free(label_smack);
496         RUNNER_ASSERT_MSG_BT(res == 0, "Error in getting self SMACK label");
497     }
498     std::string label_self(label_smack ? label_smack : "");
499     free(label_smack);
500
501     RUNNER_ASSERT_MSG_BT(label_self == label_cookie, "No match in SMACK labels");
502
503
504     //TODO: here could be label change using SMACK API and checking if it
505     //is changed using security-server API function based on the same cookie
506 }
507
508 /**
509  * NOSMACK version of tc_security_server_get_smacklabel_cookie test.
510  *
511  * Most of this test goes exactly as the original one. The only difference are the labels:
512  * - We assume that libsmack tests passed and smack_new_label_from_self will return -1 and NULL
513  *   label - there is no need to re-check it.
514  * - Label acquired from security_server_get_smacklabel_cookie should be an empty string.
515  */
516 RUNNER_TEST_NOSMACK(tc18_security_server_get_smacklabel_cookie_nosmack) {
517     int res;
518
519     char* label_ss = NULL;
520     char* cookie = NULL;
521
522     int cookie_size = security_server_get_cookie_size();
523     RUNNER_ASSERT_MSG_BT(PROPER_COOKIE_SIZE == cookie_size,
524             "Wrong cookie size from security-server. Size: " << cookie_size);
525
526     cookie = (char*) calloc(cookie_size, sizeof(char));
527     RUNNER_ASSERT_MSG_BT(NULL != cookie, "Memory allocation error");
528
529     //Request cookie from SS
530     res = security_server_request_cookie(cookie, cookie_size);
531     std::unique_ptr<char, std::function<void(char*)> > cookie_ptr(cookie, free);
532     cookie = NULL;
533     RUNNER_ASSERT_MSG_BT(res == SECURITY_SERVER_API_SUCCESS,
534             "Error in requesting cookie from security-server. Result: " << res);
535
536     label_ss = security_server_get_smacklabel_cookie(cookie_ptr.get());
537     RUNNER_ASSERT_MSG_BT(label_ss != NULL, "Error in getting label by cookie");
538
539     std::string label(label_ss);
540     free(label_ss);
541     RUNNER_ASSERT_MSG_BT(label.empty(), "label_ss is not an empty string.");
542
543 }
544
545 ////////////////////
546 /////MAIN///////////
547 ////////////////////
548
549 int main(int argc, char *argv[])
550 {
551     SummaryCollector::Register();
552     return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
553 }