2 * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
5 * @file security_server_tests_client_smack.cpp
6 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
8 * @brief Test cases for security-server-client-smack.
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <sys/smack.h>
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"
31 #include <security-server.h>
32 #include <access_provider.h>
33 #include "tests_common.h"
34 #include <summary_collector.h>
37 #define PROPER_COOKIE_SIZE 20
40 * Unique_ptr typedef for NOSMACK version of tc06 test
42 void closesockfdptr(int* sockfd_ptr)
46 typedef std::unique_ptr<int, std::function<void(int*)> > SockFDUniquePtr;
48 RUNNER_TEST_GROUP_INIT(SECURITY_SERVER_TESTS_CLIENT_SMACK)
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
58 RUNNER_CHILD_TEST_SMACK(tc04_security_server_get_gid)
60 SecurityServer::AccessProvider provider("tc04mylabel");
61 provider.allowFunction("security_server_get_gid");
62 provider.applyAndSwithToUser(APP_UID, APP_GID);
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);
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.
80 RUNNER_CHILD_TEST_SMACK(tc05_check_privilege_by_cookie)
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";
89 access.add(subject_label, object_label, access_rights);
90 access.add(subject_label, "security-server::api-cookie-check", "w");
93 RUNNER_ASSERT_BT(0 == smack_set_label_for_self(subject_label));
95 RUNNER_ASSERT_BT(SECURITY_SERVER_API_SUCCESS ==
96 security_server_request_cookie(cookie,20));
98 RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
100 RUNNER_ASSERT_BT(SECURITY_SERVER_API_SUCCESS ==
101 security_server_check_privilege_by_cookie(
106 RUNNER_ASSERT_BT(SECURITY_SERVER_API_ERROR_ACCESS_DENIED ==
107 security_server_check_privilege_by_cookie(
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.
120 RUNNER_MULTIPROCESS_TEST_SMACK(tc06_check_privilege_by_sockfd)
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";
130 smack_accesses *handle;
131 RUNNER_ASSERT_BT(0 == smack_accesses_new(&handle));
132 RUNNER_ASSERT_BT(0 == smack_accesses_add(handle,
136 RUNNER_ASSERT_BT(0 == smack_accesses_apply(handle));
137 smack_accesses_free(handle);
141 RUNNER_ASSERT_BT(-1 != pid);
145 RUNNER_ASSERT_MSG_BT(0 == smack_set_label_for_self(subject_label), "child label " << subject_label << " not set");
147 int sockfd = create_new_socket();
148 RUNNER_ASSERT_MSG_BT(sockfd >= 0, "create_new_socket() failed");
150 SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
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 << "\"");
157 RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
159 RUNNER_ASSERT_MSG_BT(listen(sockfd, 5) >= 0, "child listen failed");
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 << "\"");
166 struct sockaddr_un client_addr;
167 socklen_t client_len = sizeof(client_addr);
169 RUNNER_ASSERT_MSG_BT((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) > 0, "child accept failed");
178 int sockfd = connect_to_testserver();
179 RUNNER_ASSERT_MSG_BT(sockfd >= 0, "connect_to_testserver() failed");
181 SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
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 << "\"" );
188 result1 = security_server_check_privilege_by_sockfd(
192 result2 = security_server_check_privilege_by_sockfd(
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);
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.
212 RUNNER_MULTIPROCESS_TEST_SMACK(tc07_check_privilege_by_sockfd)
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";
223 access.add(subject_label, object_label, access_rights);
227 RUNNER_ASSERT_BT(-1 != pid);
232 RUNNER_ASSERT_BT(-1 != pid);
236 int sockfd = create_new_socket();
237 RUNNER_ASSERT_MSG_BT(sockfd >= 0, "create_new_socket() failed");
239 SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
241 RUNNER_ASSERT_MSG_BT(0 == smack_set_label_for_self(subject_label), "child label " << subject_label << " not set");
243 RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
245 RUNNER_ASSERT_MSG_BT(listen(sockfd, 5) >= 0, "child listen failed");
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));
257 int sockfd = connect_to_testserver();
258 RUNNER_ASSERT_MSG_BT(sockfd >= 0, "connect_to_testserver() failed");
260 result1 = security_server_check_privilege_by_sockfd(
264 result2 = security_server_check_privilege_by_sockfd(
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);
277 ///////////////////////////
278 /////NOSMACK ENV TESTS/////
279 ///////////////////////////
281 RUNNER_CHILD_TEST_NOSMACK(tc04_security_server_get_gid_nosmack)
285 ret = drop_root_privileges();
286 RUNNER_ASSERT_MSG_BT(ret == 0,
287 "Failed to drop root privileges. Result: " << ret << "uid = " << getuid());
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);
296 * NOSMACK version of tc05 test.
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.
302 RUNNER_CHILD_TEST_NOSMACK(tc05_check_privilege_by_cookie_nosmack)
305 const char* object_label = "tc05objectlabel";
307 RUNNER_ASSERT_BT(security_server_request_cookie(cookie,20) == SECURITY_SERVER_API_SUCCESS);
309 RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
311 RUNNER_ASSERT_BT(SECURITY_SERVER_API_SUCCESS ==
312 security_server_check_privilege_by_cookie(cookie, object_label, "r"));
314 //On NOSMACK env security server should return success on any accesses, even those that are
316 RUNNER_ASSERT_BT(SECURITY_SERVER_API_SUCCESS ==
317 security_server_check_privilege_by_cookie(cookie, object_label, "rw"));
321 * NOSMACK version of tc06 test.
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
331 * For client the only difference are expected results from check_privilege_by_sockfd - both should
334 RUNNER_MULTIPROCESS_TEST_NOSMACK(tc06_check_privilege_by_sockfd_nosmack)
336 const char* object_label = "tc06objectlabel";
343 RUNNER_ASSERT_BT(pid >= 0);
347 if (pid == 0) { //child process - server
349 int sockfd = create_new_socket();
350 RUNNER_ASSERT_MSG_BT(sockfd >= 0, "create_new_socket() failed");
352 SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
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, "");
359 RUNNER_ASSERT_MSG_BT(ret == 0, "label is \"" << label << "\"");
361 RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
363 RUNNER_ASSERT_MSG_BT(listen(sockfd, 5) >= 0, "child listen failed");
365 struct sockaddr_un client_addr;
366 socklen_t client_len = sizeof(client_addr);
369 RUNNER_ASSERT_MSG_BT((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) > 0, "child accept failed");
371 //wait a little bit for parent to do it's job
374 //if everything works, cleanup and return 0
380 int sockfd = connect_to_testserver();
381 RUNNER_ASSERT_MSG_BT(sockfd >= 0, "Failed to connect to server.");
383 SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
385 label = security_server_get_smacklabel_sockfd(sockfd);
386 RUNNER_ASSERT_MSG_BT(label != NULL, "get_smacklabel_sockfd failed.");
387 ret = strcmp(label, "");
389 RUNNER_ASSERT_MSG_BT(ret == 0, "label is \"" << label << "\"");
391 result1 = security_server_check_privilege_by_sockfd(sockfd, object_label, "r");
392 result2 = security_server_check_privilege_by_sockfd(sockfd, object_label, "rw");
395 RUNNER_ASSERT_MSG_BT(result1 == SECURITY_SERVER_API_SUCCESS, "result = " << result1);
396 RUNNER_ASSERT_MSG_BT(result2 == SECURITY_SERVER_API_SUCCESS, "result = " << result2);
400 * NOSMACK version of tc07 test.
402 RUNNER_MULTIPROCESS_TEST_NOSMACK(tc07_check_privilege_by_sockfd_nosmack)
404 const char* object_label = "tc07objectlabel";
410 RUNNER_ASSERT_BT(-1 != pid);
415 RUNNER_ASSERT_BT(-1 != pid);
417 if (pid == 0) { //child process
419 int sockfd = create_new_socket();
420 RUNNER_ASSERT_MSG_BT(sockfd >= 0, "create_new_socket() failed");
422 SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
425 RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
427 //Prepare for accepting
428 RUNNER_ASSERT_MSG_BT(listen(sockfd, 5) >= 0, "child listen failed");
430 struct sockaddr_un client_addr;
431 socklen_t client_len = sizeof(client_addr);
435 RUNNER_ASSERT_MSG_BT((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) > 0, "child accept failed");
437 //wait a little bit for parent to do it's job
440 //cleanup and kill child
443 } else { //parent process
444 //Drop root privileges
445 RUNNER_ASSERT_MSG_BT(drop_root_privileges() == 0, "uid = " << getuid());
447 //Wait for server to set up
450 //Connect and check privileges
451 int sockfd = connect_to_testserver();
452 RUNNER_ASSERT_MSG_BT(sockfd >= 0, "Failed to create socket fd.");
454 result1 = security_server_check_privilege_by_sockfd(sockfd, object_label, "r");
455 result2 = security_server_check_privilege_by_sockfd(sockfd, object_label, "rw");
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);
466 RUNNER_TEST_SMACK(tc18_security_server_get_smacklabel_cookie) {
469 char *label_smack = NULL;
470 char *label_ss = NULL;
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");
476 cookie = (char*) calloc(cookie_size, 1);
477 RUNNER_ASSERT_MSG_BT(NULL != cookie, "Memory allocation error");
479 res = security_server_request_cookie(cookie, cookie_size);
480 if (res != SECURITY_SERVER_API_SUCCESS) {
482 RUNNER_ASSERT_MSG_BT(res == SECURITY_SERVER_API_SUCCESS, "Error in requesting cookie from security-server");
485 label_ss = security_server_get_smacklabel_cookie(cookie);
487 RUNNER_ASSERT_MSG_BT(label_ss != NULL, "Error in getting label by cookie");
490 std::string label_cookie(label_ss);
493 res = smack_new_label_from_self(&label_smack);
496 RUNNER_ASSERT_MSG_BT(res == 0, "Error in getting self SMACK label");
498 std::string label_self(label_smack ? label_smack : "");
501 RUNNER_ASSERT_MSG_BT(label_self == label_cookie, "No match in SMACK labels");
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
509 * NOSMACK version of tc_security_server_get_smacklabel_cookie test.
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.
516 RUNNER_TEST_NOSMACK(tc18_security_server_get_smacklabel_cookie_nosmack) {
519 char* label_ss = NULL;
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);
526 cookie = (char*) calloc(cookie_size, sizeof(char));
527 RUNNER_ASSERT_MSG_BT(NULL != cookie, "Memory allocation error");
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);
533 RUNNER_ASSERT_MSG_BT(res == SECURITY_SERVER_API_SUCCESS,
534 "Error in requesting cookie from security-server. Result: " << res);
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");
539 std::string label(label_ss);
541 RUNNER_ASSERT_MSG_BT(label.empty(), "label_ss is not an empty string.");
549 int main(int argc, char *argv[])
551 SummaryCollector::Register();
552 return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);