Adjust AccessProvider api to current security-server.
[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 #include <memory.h>
36
37 #define PROPER_COOKIE_SIZE 20
38
39
40 RUNNER_TEST_GROUP_INIT(SECURITY_SERVER_TESTS_CLIENT_SMACK)
41
42 /*
43  * test: tc04_security_server_get_gid
44  * description: Checking for security_server_get_gid
45  *              with nonexisting gid and existing one
46  * expected: security_server_get_gid should return
47  *           SECURITY_SERVER_ERROR_NO_SUCH_OBJECT with first call
48  *           and group id with second call
49  */
50 RUNNER_CHILD_TEST_SMACK(tc04_security_server_get_gid)
51 {
52     SecurityServer::AccessProvider provider("tc04mylabel");
53     provider.allowSS();
54     provider.applyAndSwithToUser(APP_UID, APP_GID);
55
56     int ret = security_server_get_gid("abc123xyz_pysiaczek");
57     LogDebug("ret = " << ret);
58     RUNNER_ASSERT_MSG_BT(SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT == ret, "Ret: " << ret);
59     ret = security_server_get_gid("root");
60     LogDebug("ret = " << ret);
61     RUNNER_ASSERT_MSG_BT(0 == ret, "Ret: " << ret);
62 }
63
64 /*
65  * test: tc05_check_privilege_by_cookie
66  * description: Function security_server_check_privilege_by_cookie should
67  * return status of access rights of cookie owner. In this case cookie owner
68  * is the same process that ask for the rights.
69  * expected: Function call with access rights set to "r" should return SUCCESS,
70  * with "rw" should return ACCESS DENIED.
71  */
72 RUNNER_CHILD_TEST_SMACK(tc05_check_privilege_by_cookie)
73 {
74     RUNNER_IGNORED_MSG("security_server_check_privilege_by_cookie is temporarily disabled: always returns success");
75     char cookie[20];
76     const char *object_label = "tc05objectlabel";
77     const char *access_rights = "r";
78     const char *access_rights_ext = "rw";
79     const char *subject_label = "tc05subjectlabel";
80
81     SecurityServer::AccessProvider provider(subject_label);
82     provider.allowSS();
83     provider.addObjectRule(object_label, access_rights);
84     provider.applyAndSwithToUser(APP_UID, APP_GID);
85
86     RUNNER_ASSERT_BT(SECURITY_SERVER_API_SUCCESS ==
87         security_server_request_cookie(cookie,20));
88
89     RUNNER_ASSERT_BT(SECURITY_SERVER_API_SUCCESS ==
90         security_server_check_privilege_by_cookie(
91             cookie,
92             object_label,
93             access_rights));
94
95     RUNNER_ASSERT_BT(SECURITY_SERVER_API_ERROR_ACCESS_DENIED ==
96         security_server_check_privilege_by_cookie(
97             cookie,
98             object_label,
99             access_rights_ext));
100 }
101
102 /*
103  * test: security_server_check_privilege_by_sockfd
104  * description: This test will create dummy server that will accept connection
105  * and die. The client will try to check access rights using connection descriptor.
106  * expected: Function call with access rights set to "r" should return SUCCESS,
107  * with "rw" should return ACCESS DENIED.
108  */
109 RUNNER_MULTIPROCESS_TEST_SMACK(tc06_check_privilege_by_sockfd)
110 {
111     RUNNER_IGNORED_MSG("security_server_check_privilege_by_sockfd is temporarily disabled: always returns success");
112     const char *object_label = "tc06objectlabel";
113     const char *access_rights = "r";
114     const char *access_rights_ext = "rw";
115     const char *subject_label = "tc06subjectlabel";
116
117     int result1 = -1;
118     int result2 = -1;
119
120     smack_accesses *handle;
121     RUNNER_ASSERT_BT(0 == smack_accesses_new(&handle));
122     RUNNER_ASSERT_BT(0 == smack_accesses_add(handle,
123             subject_label,
124             object_label,
125             access_rights));
126     RUNNER_ASSERT_BT(0 == smack_accesses_apply(handle));
127     smack_accesses_free(handle);
128
129     int pid = fork();
130     char *label;
131     RUNNER_ASSERT_BT(-1 != pid);
132
133     if (0 == pid) {
134         // child
135         RUNNER_ASSERT_MSG_BT(0 == smack_set_label_for_self(subject_label), "child label " << subject_label << " not set");
136
137         int sockfd = create_new_socket();
138         RUNNER_ASSERT_MSG_BT(sockfd >= 0, "create_new_socket() failed");
139
140         SockUniquePtr sockfd_ptr(&sockfd);
141
142         label = security_server_get_smacklabel_sockfd(sockfd);
143         RUNNER_ASSERT_MSG_BT(label != NULL, "security_server_get_smacklabel_sockfd failed");
144         RUNNER_ASSERT_MSG_BT(strcmp(label,"") == 0, "label is \"" << label << "\"");
145         free(label);
146
147         RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
148
149         RUNNER_ASSERT_MSG_BT(listen(sockfd, 5) >= 0, "child listen failed");
150
151         label = security_server_get_smacklabel_sockfd(sockfd);
152         RUNNER_ASSERT_MSG_BT(label != NULL, "security_server_get_smacklabel_sockfd failed");
153         RUNNER_ASSERT_MSG_BT(strcmp(label,"") == 0, "label is \"" << label << "\"");
154         free(label);
155
156         struct sockaddr_un client_addr;
157         socklen_t client_len = sizeof(client_addr);
158         int csockfd;
159         RUNNER_ASSERT_MSG_BT((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) > 0, "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_BT(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_BT(label != NULL, "security_server_get_smacklabel_sockfd failed");
175         RUNNER_ASSERT_MSG_BT(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_BT(SECURITY_SERVER_API_SUCCESS == result1, "result = " << result1);
189     RUNNER_ASSERT_MSG_BT(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_BT(-1 != pid);
219
220     if (0 == pid) {
221
222         pid = fork();
223         RUNNER_ASSERT_BT(-1 != pid);
224
225         if (0 == pid) {
226             // child
227             int sockfd = create_new_socket();
228             RUNNER_ASSERT_MSG_BT(sockfd >= 0, "create_new_socket() failed");
229
230             SockUniquePtr sockfd_ptr(&sockfd);
231
232             RUNNER_ASSERT_MSG_BT(0 == smack_set_label_for_self(subject_label), "child label " << subject_label << " not set");
233
234             RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
235
236             RUNNER_ASSERT_MSG_BT(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_BT(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_BT(SECURITY_SERVER_API_SUCCESS == result1, "result1 = " << result1);
263             RUNNER_ASSERT_MSG_BT(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_BT(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_BT(ret == SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT, "ret = " << ret);
282     ret = security_server_get_gid("root");
283     RUNNER_ASSERT_MSG_BT(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_BT(security_server_request_cookie(cookie,20) == SECURITY_SERVER_API_SUCCESS);
300
301     RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
302
303     RUNNER_ASSERT_BT(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_BT(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_BT(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_BT(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_BT(label != NULL, "security_server_get_smacklabel_sockfd failed");
350         ret = strcmp(label, "");
351         free(label);
352         RUNNER_ASSERT_MSG_BT(ret == 0, "label is \"" << label << "\"");
353
354         RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
355
356         RUNNER_ASSERT_MSG_BT(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_MSG_BT((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) > 0, "child accept failed");
363
364         //wait a little bit for parent to do it's job
365         usleep(200);
366
367         //if everything works, cleanup and return 0
368         close(csockfd);
369         exit(0);
370     } else {
371         //parent
372         sleep(1);
373         int sockfd = connect_to_testserver();
374         RUNNER_ASSERT_MSG_BT(sockfd >= 0, "Failed to connect to server.");
375
376         SockUniquePtr sockfd_ptr(&sockfd);
377
378         label = security_server_get_smacklabel_sockfd(sockfd);
379         RUNNER_ASSERT_MSG_BT(label != NULL, "get_smacklabel_sockfd failed.");
380         ret = strcmp(label, "");
381         free(label);
382         RUNNER_ASSERT_MSG_BT(ret == 0, "label is \"" << label << "\"");
383
384         result1 = security_server_check_privilege_by_sockfd(sockfd, object_label, "r");
385         result2 = security_server_check_privilege_by_sockfd(sockfd, object_label, "rw");
386     }
387
388     RUNNER_ASSERT_MSG_BT(result1 == SECURITY_SERVER_API_SUCCESS, "result = " << result1);
389     RUNNER_ASSERT_MSG_BT(result2 == SECURITY_SERVER_API_SUCCESS, "result = " << result2);
390 }
391
392 /**
393  * NOSMACK version of tc07 test.
394  */
395 RUNNER_MULTIPROCESS_TEST_NOSMACK(tc07_check_privilege_by_sockfd_nosmack)
396 {
397     RUNNER_IGNORED_MSG("security_server_check_privilege_by_sockfd is temporarily disabled: always returns success");
398     const char* object_label = "tc07objectlabel";
399
400     int result1 = -1;
401     int result2 = -1;
402
403     int pid = fork();
404     RUNNER_ASSERT_BT(-1 != pid);
405
406     if (pid == 0) {
407
408         pid = fork();
409         RUNNER_ASSERT_BT(-1 != pid);
410
411         if (pid == 0) { //child process
412             //Create socket
413             int sockfd = create_new_socket();
414             RUNNER_ASSERT_MSG_BT(sockfd >= 0, "create_new_socket() failed");
415
416             SockUniquePtr sockfd_ptr(&sockfd);
417
418             //Drop privileges
419             RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
420
421             //Prepare for accepting
422             RUNNER_ASSERT_MSG_BT(listen(sockfd, 5) >= 0, "child listen failed");
423
424             struct sockaddr_un client_addr;
425             socklen_t client_len = sizeof(client_addr);
426
427             //Accept connections
428             int csockfd;
429             RUNNER_ASSERT_MSG_BT((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) > 0, "child accept failed");
430
431             //wait a little bit for parent to do it's job
432             usleep(200);
433
434             //cleanup and kill child
435             close(csockfd);
436             exit(0);
437         } else {    //parent process
438             //Drop root privileges
439             RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
440
441             //Wait for server to set up
442             sleep(1);
443
444             //Connect and check privileges
445             int sockfd = connect_to_testserver();
446             RUNNER_ASSERT_MSG_BT(sockfd >= 0, "Failed to create socket fd.");
447
448             result1 = security_server_check_privilege_by_sockfd(sockfd, object_label, "r");
449             result2 = security_server_check_privilege_by_sockfd(sockfd, object_label, "rw");
450
451             close(sockfd);
452
453             //Both results (just like in the previous test case) should return success.
454             RUNNER_ASSERT_MSG_BT(SECURITY_SERVER_API_SUCCESS == result1, "result1 = " << result1);
455             RUNNER_ASSERT_MSG_BT(SECURITY_SERVER_API_SUCCESS == result2, "result2 = " << result2);
456         }
457     }
458 }
459
460 RUNNER_TEST_SMACK(tc18_security_server_get_smacklabel_cookie) {
461     int res;
462
463     char *label_smack = NULL;
464     char *label_ss = NULL;
465     char *cookie = NULL;
466
467     int cookie_size = security_server_get_cookie_size();
468     RUNNER_ASSERT_MSG_BT(PROPER_COOKIE_SIZE == cookie_size, "Wrong cookie size from security-server");
469
470     cookie = (char*) calloc(cookie_size, 1);
471     RUNNER_ASSERT_MSG_BT(NULL != cookie, "Memory allocation error");
472
473     res = security_server_request_cookie(cookie, cookie_size);
474     if (res != SECURITY_SERVER_API_SUCCESS) {
475         free(cookie);
476         RUNNER_ASSERT_MSG_BT(res == SECURITY_SERVER_API_SUCCESS, "Error in requesting cookie from security-server");
477     }
478
479     label_ss = security_server_get_smacklabel_cookie(cookie);
480     free(cookie);
481     RUNNER_ASSERT_MSG_BT(label_ss != NULL, "Error in getting label by cookie");
482
483
484     std::string label_cookie(label_ss);
485     free(label_ss);
486
487     res = smack_new_label_from_self(&label_smack);
488     if (res < 0) {
489         free(label_smack);
490         RUNNER_ASSERT_MSG_BT(res == 0, "Error in getting self SMACK label");
491     }
492     std::string label_self(label_smack ? label_smack : "");
493     free(label_smack);
494
495     RUNNER_ASSERT_MSG_BT(label_self == label_cookie, "No match in SMACK labels");
496
497
498     //TODO: here could be label change using SMACK API and checking if it
499     //is changed using security-server API function based on the same cookie
500 }
501
502 /**
503  * NOSMACK version of tc_security_server_get_smacklabel_cookie test.
504  *
505  * Most of this test goes exactly as the original one. The only difference are the labels:
506  * - We assume that libsmack tests passed and smack_new_label_from_self will return -1 and NULL
507  *   label - there is no need to re-check it.
508  * - Label acquired from security_server_get_smacklabel_cookie should be an empty string.
509  */
510 RUNNER_TEST_NOSMACK(tc18_security_server_get_smacklabel_cookie_nosmack) {
511     int res;
512
513     char* label_ss = NULL;
514     char* cookie = NULL;
515
516     int cookie_size = security_server_get_cookie_size();
517     RUNNER_ASSERT_MSG_BT(PROPER_COOKIE_SIZE == cookie_size,
518             "Wrong cookie size from security-server. Size: " << cookie_size);
519
520     cookie = (char*) calloc(cookie_size, sizeof(char));
521     RUNNER_ASSERT_MSG_BT(NULL != cookie, "Memory allocation error");
522
523     //Request cookie from SS
524     res = security_server_request_cookie(cookie, cookie_size);
525     CookieUniquePtr cookie_ptr(cookie);
526     cookie = NULL;
527     RUNNER_ASSERT_MSG_BT(res == SECURITY_SERVER_API_SUCCESS,
528             "Error in requesting cookie from security-server. Result: " << res);
529
530     label_ss = security_server_get_smacklabel_cookie(cookie_ptr.get());
531     RUNNER_ASSERT_MSG_BT(label_ss != NULL, "Error in getting label by cookie");
532
533     std::string label(label_ss);
534     free(label_ss);
535     RUNNER_ASSERT_MSG_BT(label.empty(), "label_ss is not an empty string.");
536
537 }
538
539 ////////////////////
540 /////MAIN///////////
541 ////////////////////
542
543 int main(int argc, char *argv[])
544 {
545     SummaryCollector::Register();
546     return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
547 }