Split existing tests into environment categories.
[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
18 #include <dpl/log/log.h>
19 #include <dpl/test/test_runner.h>
20 #include <dpl/test/test_runner_child.h>
21 #include "security_server_mockup.h"
22
23 #include <security-server.h>
24
25 #include "tests_common.h"
26
27 #define ENVIRONMENT                                                       \
28     do {                                                                  \
29         const char *subject_label = "mylabel";                            \
30         RUNNER_ASSERT_MSG(-1 != system("touch /opt/home/root/pid_cycle"), \
31             "Cannot prepare environment for test.");                      \
32         RUNNER_ASSERT_MSG(0 == smack_set_label_for_self(subject_label),   \
33             "Cannot prepare environment for test.");                      \
34         RUNNER_ASSERT_MSG(-1 != setgid(1),                                \
35             "Cannot prepare environment for test.");                      \
36         RUNNER_ASSERT_MSG(-1 != setuid(1),                                \
37             "Cannot prepare environment for test");                       \
38     } while (0)
39
40 /**
41  * Dropping root privileges
42  * returns 0 on success, 1 on error
43  */
44 int drop_root_privileges()
45 {
46     if (getuid() == 0) {
47         /* process is running as root, drop privileges */
48         if (setgid(5000) != 0)
49             return 1;
50         if (setuid(5000) != 0)
51             return 1;
52     }
53     int uid = getuid();
54     if (uid == 5000)
55         return 0;
56
57     return 1;
58 }
59
60 RUNNER_TEST_GROUP_INIT(SECURITY_SERVER_TESTS_CLIENT_SMACK)
61
62 /*
63  * test: Check cookie size returned by security_server_get_cookie_size.
64  * description: Cookie used by security-server is 20 bytes long.
65  * Any other size of cookies should be treated as error.
66  * expected: Function security_server_get_cookie_size returns 20.
67  */
68 RUNNER_CHILD_TEST_SMACK(tc01_security_server_get_cookie_size)
69 {
70     ENVIRONMENT;
71
72     int ret = security_server_get_cookie_size();
73     RUNNER_ASSERT_MSG(20 == ret, "ret = " << ret);
74 }
75
76 /*
77  * test: security_server_request_cookie
78  * description: Function security_server_request_cookie will return
79  * 20 bytes long cookie.
80  * expected: function will set up cookie in the array and return
81  * SECURITY_SERVER_API_SUCCESS.
82  */
83 RUNNER_CHILD_TEST_SMACK(tc02_security_server_request_cookie_normal_case)
84 {
85     ENVIRONMENT;
86
87     char cookie[20];
88     int ret = security_server_request_cookie(cookie, 20);
89     LogDebug("ret = " << ret);
90     RUNNER_ASSERT(SECURITY_SERVER_API_SUCCESS == ret);
91 }
92
93 /*
94  * test: security_server_request_cookie
95  * description: Function security_server_request_cookie will return
96  * 20 bytes long cookie.
97  * expected: function will set up cookie in the array and return
98  * SECURITY_SERVER_API_SUCCESS.
99  */
100 RUNNER_CHILD_TEST_SMACK(tc03_security_server_request_cookie_too_small_buffer_size)
101 {
102     ENVIRONMENT;
103
104     char cookie[20];
105     int ret = security_server_request_cookie(cookie, 10);
106     LogDebug("ret = " << ret);
107     RUNNER_ASSERT(SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMALL == ret);
108 }
109
110 /*
111  * test: tc04_security_server_get_gid
112  * description: Checking for security_server_get_gid
113  *              with nonexisting gid and existing one
114  * expected: security_server_get_gid should return
115  *           SECURITY_SERVER_ERROR_NO_SUCH_OBJECT with first call
116  *           and group id with second call
117  */
118 RUNNER_CHILD_TEST_SMACK(tc04_security_server_get_gid)
119 {
120     ENVIRONMENT;
121
122     int ret = security_server_get_gid("abc123xyz_pysiaczek");
123     LogDebug("ret = " << ret);
124     RUNNER_ASSERT_MSG(SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT == ret, "Ret: " << ret);
125     ret = security_server_get_gid("root");
126     LogDebug("ret = " << ret);
127     RUNNER_ASSERT_MSG(0 == ret, "Ret: " << ret);
128 }
129
130 /*
131  * test: tc05_check_privilege_by_cookie
132  * description: Function security_server_check_privilege_by_cookie should
133  * return status of access rights of cookie owner. In this case cookie owner
134  * is the same process that ask for the rights.
135  * expected: Function call with access rights set to "r" should return SUCCESS,
136  * with "rw" should return ACCESS DENIED.
137  */
138 RUNNER_CHILD_TEST_SMACK(tc05_check_privilege_by_cookie)
139 {
140     char cookie[20];
141     const char *object_label = "tc05objectlabel";
142     const char *access_rights = "r";
143     const char *access_rights_ext = "rw";
144     const char *subject_label = "tc05subjectlabel";
145
146     smack_accesses *handle;
147
148     RUNNER_ASSERT(0 == smack_accesses_new(&handle));
149
150     RUNNER_ASSERT(0 == smack_accesses_add(handle,
151             subject_label,
152             object_label,
153             access_rights));
154
155     RUNNER_ASSERT(0 == smack_accesses_apply(handle));
156
157     smack_accesses_free(handle);
158
159     RUNNER_ASSERT(0 == smack_set_label_for_self(subject_label));
160
161     RUNNER_ASSERT(SECURITY_SERVER_API_SUCCESS ==
162         security_server_request_cookie(cookie,20));
163
164     RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
165
166     RUNNER_ASSERT(SECURITY_SERVER_API_SUCCESS ==
167         security_server_check_privilege_by_cookie(
168             cookie,
169             object_label,
170             access_rights));
171
172     RUNNER_ASSERT(SECURITY_SERVER_API_ERROR_ACCESS_DENIED ==
173         security_server_check_privilege_by_cookie(
174             cookie,
175             object_label,
176             access_rights_ext));
177 }
178
179 /*
180  * test: security_server_check_privilege_by_sockfd
181  * description: This test will create dummy server that will accept connection
182  * and die. The client will try to check access rights using connection descriptor.
183  * expected: Function call with access rights set to "r" should return SUCCESS,
184  * with "rw" should return ACCESS DENIED.
185  */
186 RUNNER_TEST_SMACK(tc06_check_privilege_by_sockfd)
187 {
188     const char *object_label = "tc06objectlabel";
189     const char *access_rights = "r";
190     const char *access_rights_ext = "rw";
191     const char *subject_label = "tc06subjectlabel";
192
193     int result1 = -1;
194     int result2 = -1;
195
196     smack_accesses *handle;
197     RUNNER_ASSERT(0 == smack_accesses_new(&handle));
198     RUNNER_ASSERT(0 == smack_accesses_add(handle,
199             subject_label,
200             object_label,
201             access_rights));
202     RUNNER_ASSERT(0 == smack_accesses_apply(handle));
203     smack_accesses_free(handle);
204
205     int pid = fork();
206     char *label;
207     RUNNER_ASSERT(-1 != pid);
208
209     if (0 == pid) {
210         // child
211         if (0 != smack_set_label_for_self(subject_label)) {
212             LogDebug("child, failed");
213             exit(1);
214         }
215
216         LogDebug("child, create_new_socket");
217         int sockfd = create_new_socket();
218
219
220         label = security_server_get_smacklabel_sockfd(sockfd);
221         RUNNER_ASSERT_MSG(label != NULL, "security_server_get_smacklabel_sockfd failed");
222         RUNNER_ASSERT_MSG(strcmp(label,"") == 0, "label is \"" << label << "\"");
223         free(label);
224
225         RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
226
227         LogDebug("child, listen");
228         if (listen(sockfd, 5) < 0) {
229             LogDebug("child, exit");
230             exit(1);
231         }
232
233         label = security_server_get_smacklabel_sockfd(sockfd);
234         RUNNER_ASSERT_MSG(label != NULL, "security_server_get_smacklabel_sockfd failed");
235         RUNNER_ASSERT_MSG(strcmp(label,"") == 0, "label is \"" << label << "\"");
236         free(label);
237
238
239         LogDebug("child, accept");
240         struct sockaddr_un client_addr;
241         socklen_t client_len = sizeof(client_addr);
242         int csockfd;
243         while (0 <= (csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len))) {
244             LogDebug("child, loop");
245             close(csockfd);
246         }
247
248
249         label = security_server_get_smacklabel_sockfd(sockfd);
250         RUNNER_ASSERT_MSG(label != NULL, "security_server_get_smacklabel_sockfd failed");
251         RUNNER_ASSERT_MSG(strcmp(label,subject_label) == 0, "label is \"" << label << "\"" << "subject_label is \"" << subject_label << "\"" );
252         free(label);
253
254         LogDebug("Exit!");
255         exit(1);
256     } else {
257         // parent
258         LogDebug("Parent, sleep 2");
259         sleep(1);
260         int sockfd = connect_to_testserver();
261
262         label = security_server_get_smacklabel_sockfd(sockfd);
263         RUNNER_ASSERT_MSG(label != NULL, "security_server_get_smacklabel_sockfd failed");
264         RUNNER_ASSERT_MSG(strcmp(label,subject_label) == 0, "label is \"" << label << "\"" << "subject_label is \"" << subject_label << "\"" );
265         free(label);
266
267         LogDebug("Parent: sockfd: " << sockfd);
268         if (sockfd >= 0) {
269             result1 = security_server_check_privilege_by_sockfd(
270                 sockfd,
271                 object_label,
272                 access_rights);
273             result2 = security_server_check_privilege_by_sockfd(
274                 sockfd,
275                 object_label,
276                 access_rights_ext);
277         }
278         LogDebug("Parent: Close desc");
279         close(sockfd);
280         LogDebug("Parent: killing child");
281         kill(pid, SIGKILL);
282     }
283
284     int status;
285     waitpid(pid, &status, 0);
286
287     RUNNER_ASSERT_MSG(SECURITY_SERVER_API_SUCCESS == result1, "result = " << result1);
288     RUNNER_ASSERT_MSG(SECURITY_SERVER_API_ERROR_ACCESS_DENIED == result2, "result = " << result2);
289 }
290
291 /*
292  * test: security_server_check_privilege_by_sockfd
293  * description: This test will create dummy server that will accept connection
294  * and die. The client will try to check access rights using connection descriptor.
295  * Because we read a smack label not from socket directly, but from from pid of process
296  * on the other end of socket - that's why smack label will be updated.
297  * In this test client is running under root and server is not - to test the extreme case.
298  * expected: Function call with access rights set to "r" should return SUCCESS,
299  * with "rw" should return ACCESS DENIED.
300  */
301 RUNNER_TEST_SMACK(tc07_check_privilege_by_sockfd)
302 {
303     const char *object_label = "tc07objectlabel";
304     const char *access_rights = "r";
305     const char *access_rights_ext = "rw";
306     const char *subject_label = "tc07subjectlabel";
307
308     int result1 = -1;
309     int result2 = -1;
310     int kill_result = -1;
311
312     smack_accesses *handle;
313     RUNNER_ASSERT(0 == smack_accesses_new(&handle));
314     RUNNER_ASSERT(0 == smack_accesses_add(handle,
315             subject_label,
316             object_label,
317             access_rights));
318     RUNNER_ASSERT(0 == smack_accesses_apply(handle));
319     smack_accesses_free(handle);
320
321     int pid = fork();
322     RUNNER_ASSERT(-1 != pid);
323
324     if (0 == pid) {
325         // child
326         LogDebug("child, create_new_socket");
327         int sockfd = create_new_socket();
328
329         if (0 != smack_set_label_for_self(subject_label)) {
330             LogDebug("child, failed");
331             exit(1);
332         }
333
334         RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
335
336         LogDebug("child, listen");
337         if (listen(sockfd, 5) < 0) {
338             LogDebug("child, exit");
339             exit(1);
340         }
341         LogDebug("child, accept");
342
343         struct sockaddr_un client_addr;
344         socklen_t client_len = sizeof(client_addr);
345         int csockfd;
346         while (0 <= (csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len))) {
347             LogDebug("child, loop");
348             close(csockfd);
349         }
350         LogDebug("Exit!");
351         exit(1);
352     } else {
353         // parent
354
355         RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
356
357         LogDebug("Parent, sleep 2");
358         sleep(2);
359         int sockfd = connect_to_testserver();
360         LogDebug("Parent: sockfd: " << sockfd);
361         if (sockfd >= 0) {
362             result1 = security_server_check_privilege_by_sockfd(
363                 sockfd,
364                 object_label,
365                 access_rights);
366             result2 = security_server_check_privilege_by_sockfd(
367                 sockfd,
368                 object_label,
369                 access_rights_ext);
370         }
371         LogDebug("Parent: Close desc");
372         close(sockfd);
373         LogDebug("Parent: killing child");
374         // we cannot kill child - because of dropping privileges
375         kill_result = kill(pid, SIGKILL);
376     }
377
378     if (kill_result == 0) {
379         int status;
380         waitpid(pid, &status, 0);
381     }
382     else
383         sleep(2);
384
385     RUNNER_ASSERT_MSG(SECURITY_SERVER_API_SUCCESS == result1, "result1 = " << result1);
386     RUNNER_ASSERT_MSG(SECURITY_SERVER_API_ERROR_ACCESS_DENIED == result2, " result2 = " << result2);
387 }
388
389 int main(int argc, char *argv[])
390 {
391     return
392         DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
393 }