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