955c57d8c53b0a3f56d1597b8561a3739fd1ff6b
[platform/core/test/security-tests.git] / tests / security-server-tests / security_server_tests_server.cpp
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
3  */
4 /*
5  * @file    security_server_tests_server.cpp
6  * @author  Bumjin Im (bj.im@samsung.com)
7  * @author  Mariusz Domanski (m.domanski@samsung.com)
8  * @version 1.0
9  * @brief   Test cases for security server
10  */
11
12 #include <stdio.h>
13 #include <errno.h>
14 #include <stdlib.h>
15 #include <sys/types.h>
16 #include <sys/param.h>
17 #include <fcntl.h>
18 #include <sys/un.h>
19 #include <unistd.h>
20 #include <poll.h>
21 #include <sys/socket.h>
22 #include <sys/stat.h>
23 #include <sys/smack.h>
24 #include "security-server.h"
25 #include <dpl/test/test_runner.h>
26 #include <dpl/test/test_runner_child.h>
27 #include <dlog.h>
28 #include "test.h"
29
30 #define SECURITY_SERVER_SOCK_PATH    "/tmp/.security_server.sock"
31 #define COOKIE_SIZE 20
32 #define OBJ_NAME_SIZE 30
33 #define OLABEL_SIZE 1024
34 #define ARIGHTS_SIZE 32
35
36
37 /* Message */
38 typedef struct
39 {
40     unsigned char version;
41     unsigned char msg_id;
42     unsigned short msg_len;
43 } basic_header;
44
45 typedef struct
46 {
47     basic_header basic_hdr;
48     unsigned char return_code;
49 } response_header;
50
51 int server_sockfd, client_sockfd, ret, recved_gid, client_len, i;
52 unsigned char cookie[COOKIE_SIZE], wrong_cookie[COOKIE_SIZE];
53 char obj_name[OBJ_NAME_SIZE];
54 struct sockaddr_un clientaddr;
55
56 /* Create a Unix domain socket and bind */
57 int create_new_socket()
58 {
59     int localsockfd = 0, flags;
60     struct sockaddr_un serveraddr;
61     mode_t sock_mode;
62
63     if (unlink(SECURITY_SERVER_TEST_SOCK_PATH) == -1 && errno != ENOENT) {
64         LOGE("%s : %s\n", "unlink()", strerror(errno));
65         goto error;
66     }
67
68     /* Create Unix domain socket */
69     if((localsockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
70     {
71         LOGE("%s : %s\n", "socket()", strerror(errno));
72         goto error;
73     }
74
75     /* Make socket as non blocking */
76     if((flags = fcntl(localsockfd, F_GETFL, 0)) < 0 ||
77             fcntl(localsockfd, F_SETFL, flags | O_NONBLOCK) < 0)
78     {
79         LOGE("%s : %s\n", "fcntl()", strerror(errno));
80         goto error;
81     }
82
83     bzero (&serveraddr, sizeof(serveraddr));
84     serveraddr.sun_family = AF_UNIX;
85     strncpy(serveraddr.sun_path, SECURITY_SERVER_TEST_SOCK_PATH,
86             strlen(SECURITY_SERVER_TEST_SOCK_PATH) + 1);
87
88     /* Bind the socket */
89     if((bind(localsockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
90     {
91         LOGE("%s : %s\n", "bind()", strerror(errno));
92         goto error;
93     }
94
95     /* Change permission to accept all processes that has different uID/gID */
96     sock_mode = (S_IRWXU | S_IRWXG | S_IRWXO);
97     /* Flawfinder hits this chmod function as level 5 CRITICAL as race condition flaw *
98     * Flawfinder recommends to user fchmod insted of chmod
99     * But, fchmod doesn't work on socket file so there is no other choice at this point */
100     if(chmod(SECURITY_SERVER_TEST_SOCK_PATH, sock_mode) < 0)        /* Flawfinder: ignore */
101     {
102         LOGE("%s : %s\n", "chmod()", strerror(errno));
103         goto error;
104     }
105
106     return localsockfd;
107 error:
108
109     close(localsockfd);
110     localsockfd = -1;
111     return localsockfd;
112 }
113
114 int check_socket_poll(int sockfd, int event, int timeout)
115 {
116     struct pollfd poll_fd[1];
117     int retval;
118
119     poll_fd[0].fd = sockfd;
120     poll_fd[0].events = event;
121     retval = poll(poll_fd, 1, timeout);
122     if(retval < 0)
123     {
124         LOGE("%s : %s\n", "poll()", strerror(errno));
125         return -1;
126     }
127
128     /* Timed out */
129     if(retval == 0)
130     {
131         LOGE("%s", "poll() timeout");
132         return 0;
133     }
134     return 1;
135 }
136
137 int send_gid_request(int sock_fd, const char* object)
138 {
139     basic_header hdr;
140     int retval, send_len = 0;
141     unsigned char *buf = NULL;
142
143     hdr.version = 0x01; /* SECURITY_SERVER_MSG_VERSION; */
144     hdr.msg_id = 0x07; /* SECURITY_SERVER_MSG_TYPE_GID_REQUEST; */
145     hdr.msg_len = strlen(object);
146
147     send_len = sizeof(hdr) + strlen(object);
148
149     buf = (unsigned char *) malloc(send_len);
150     if(buf == NULL)
151     {
152         LOGE("%s\n", "out of memory");
153         return -1;
154     }
155
156     memcpy(buf, &hdr, sizeof(hdr));
157     memcpy(buf + sizeof(hdr), object, strlen(object));
158
159     /* Check poll */
160     retval = check_socket_poll(sock_fd, POLLOUT, 1000);
161     if(retval == -1)
162     {
163         LOGE("%s\n", "poll() error");
164         if(buf != NULL)
165             free(buf);
166         return -1;
167     }
168     if(retval == 0)
169     {
170         LOGE("%s\n", "poll() timeout");
171         if(buf != NULL)
172             free(buf);
173         return -1;
174     }
175
176     retval = write(sock_fd, buf, send_len);
177     if(retval < send_len)
178     {
179         /* Write error */
180         LOGE("Error on write(): %d. errno=%d, sockfd=%d\n", retval, errno, sock_fd);
181         if(buf != NULL)
182             free(buf);
183         return -1;
184     }
185     if(buf != NULL)
186         free(buf);
187
188     return 0;
189 }
190
191 int connect_to_server(int *fd)
192 {
193     struct sockaddr_un clientaddr;
194     int client_len = 0, localsockfd, ret, flags;
195     *fd = -1;
196
197     /* Create a socket */
198     localsockfd = socket(AF_UNIX, SOCK_STREAM, 0);
199     if(localsockfd < 0)
200     {
201         LOGE("%s : %s\n", "socket()", strerror(errno));
202         return -1;
203     }
204
205     /* Make socket as non blocking */
206     if((flags = fcntl(localsockfd, F_GETFL, 0)) < 0 ||
207             fcntl(localsockfd, F_SETFL, flags | O_NONBLOCK) < 0)
208     {
209         close(localsockfd);
210         LOGE("%s : %s\n", "fcntl()", strerror(errno));
211         return -1;
212     }
213
214     bzero(&clientaddr, sizeof(clientaddr));
215     clientaddr.sun_family = AF_UNIX;
216     strncpy(clientaddr.sun_path, SECURITY_SERVER_SOCK_PATH, strlen(SECURITY_SERVER_SOCK_PATH));
217     clientaddr.sun_path[strlen(SECURITY_SERVER_SOCK_PATH)] = 0;
218     client_len = sizeof(clientaddr);
219
220     ret = connect(localsockfd, (struct sockaddr*)&clientaddr, client_len);
221     if( ret < 0)
222     {
223         if(errno == EINPROGRESS)
224         {
225             LOGD("%s\n", "Connection is in progress");
226             check_socket_poll(localsockfd, POLLOUT, 1000);
227             if(ret == -1)
228             {
229                 LOGE("%s\n", "poll() error");
230                 close(localsockfd);
231                 return -1;
232             }
233             ret = connect(localsockfd, (struct sockaddr*)&clientaddr, client_len);
234             if(ret < 0)
235             {
236                 LOGE("%s\n", "connection failed");
237                 close(localsockfd);
238                 return -1;
239             }
240         }
241         else
242         {
243             LOGE("%s\n", "Connection failed");
244             close(localsockfd);
245             return -1;
246         }
247     }
248
249     *fd = localsockfd;
250     return 0;
251 }
252
253
254 int fake_get_gid(const char *object)
255 {
256     int sockfd = -1, retval, gid;
257     response_header hdr;
258
259     retval = connect_to_server(&sockfd);
260     if(retval != 0)
261     {
262         /* Error on socket */
263         LOGE("Connection failed: %d\n", retval);
264         goto error;
265     }
266
267     /* make request packet and send to server*/
268     retval = send_gid_request(sockfd, object);
269     if(retval != 0)
270     {
271         /* Error on socket */
272         LOGE("Send request failed: %d\n", retval);
273         goto error;
274     }
275     LOGD("%s", "Just closing the socket and exit\n");
276
277 error:
278     if(sockfd > 0)
279         close(sockfd);
280
281     return 0;
282 }
283
284 RUNNER_TEST_GROUP_INIT(SECURITY_SERVER_TESTS_SERVER);
285
286 RUNNER_TEST(tc_getting_default_cookie)
287 {
288     printhex(cookie, COOKIE_SIZE);
289     RUNNER_ASSERT(security_server_request_cookie((char *)cookie, 20) == SECURITY_SERVER_API_SUCCESS);
290 }
291
292 RUNNER_TEST(tc_security_server_get_gid_normal_case_trying_to_get_gid_of_tel_gprs)
293 {
294     RUNNER_ASSERT(security_server_get_gid("tel_gprs") >= 0);
295 }
296
297 RUNNER_TEST(tc_security_server_get_gid_empty_object_name)
298 {
299     RUNNER_ASSERT(security_server_get_gid("") == SECURITY_SERVER_API_ERROR_INPUT_PARAM);
300 }
301
302 RUNNER_TEST(tc_security_server_get_gid_wrong_object_name_teltel)
303 {
304     RUNNER_ASSERT(security_server_get_gid("teltel") == SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT);
305 }
306
307 RUNNER_TEST(tc_security_server_get_object_name_normal_case_trying_6001)
308 {
309     ret = security_server_get_object_name(6001, obj_name, sizeof(obj_name));
310     LOGD("Result: %s\n", obj_name);
311     RUNNER_ASSERT(ret == SECURITY_SERVER_API_SUCCESS);
312 }
313
314 RUNNER_TEST(tc_security_server_get_object_name_too_small_buffer_size)
315 {
316     ret = security_server_get_object_name(6001, obj_name, 5);
317     RUNNER_ASSERT(ret == SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMALL);
318 }
319
320 RUNNER_TEST(tc_security_server_get_object_name_invalid_gid)
321 {
322     ret = security_server_get_object_name(9876, obj_name, sizeof(obj_name));
323     RUNNER_ASSERT(ret == SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT);
324 }
325
326 RUNNER_TEST(tc_ask_for_privilege_with_default_cookie_normal_case_to_check_audio_privilege)
327 {
328         printhex(cookie, COOKIE_SIZE);
329         RUNNER_ASSERT(security_server_request_cookie((char *)cookie, COOKIE_SIZE) == SECURITY_SERVER_API_SUCCESS);
330     ret = security_server_get_gid("audio");
331     ret = security_server_check_privilege((char *) cookie, ret);
332     RUNNER_ASSERT(ret == SECURITY_SERVER_API_SUCCESS);
333 }
334
335 RUNNER_TEST(tc_ask_for_privilege_with_default_cookie_case_with_wrong_cookie)
336 {
337     ret = security_server_get_gid("audio");
338     srand(time(NULL));
339     for(i=0; i<COOKIE_SIZE; i++)
340         wrong_cookie[i] = rand() % 255;
341     ret = security_server_check_privilege((const char *) wrong_cookie, ret);
342     RUNNER_ASSERT(ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED);
343 }
344
345
346 RUNNER_TEST(tc_fake_security_server_get_gid)
347 {
348
349     /* Close socket just after sending request msg.
350      * This is done with fake security_server_get_gid()*/
351
352     ret = fake_get_gid("audio");
353     RUNNER_IGNORED_MSG("Watch whether security server has crashed or not.");
354 }
355
356 RUNNER_TEST(tc_get_pid_of_a_given_cookie_default_cookie_case)
357 {
358     RUNNER_ASSERT(security_server_get_cookie_pid((const char *) cookie) == getpid());
359 }
360
361 RUNNER_TEST(tc_get_pid_of_non_existing_cookie)
362 {
363     RUNNER_ASSERT(security_server_get_cookie_pid((const char *) wrong_cookie)== SECURITY_SERVER_API_ERROR_NO_SUCH_COOKIE);
364 }
365
366 RUNNER_TEST(tc_get_pid_of_null_cookie)
367 {
368     RUNNER_ASSERT(security_server_get_cookie_pid(NULL) == SECURITY_SERVER_API_ERROR_INPUT_PARAM);
369 }
370
371 RUNNER_CHILD_TEST(tc01a_security_server_app_give_access)
372 {
373     const char *subject = "abc345v34sfa";
374     const char *object = "efg678x2lkjz";
375     smack_accesses *tmp = NULL;
376
377     RUNNER_ASSERT(0 == smack_accesses_new(&tmp));
378
379     std::unique_ptr<smack_accesses,std::function<void(smack_accesses*)>>
380         smack(tmp, smack_accesses_free);
381
382     RUNNER_ASSERT(0 == smack_accesses_add(smack.get(), subject, object, "-----"));
383     RUNNER_ASSERT(0 == smack_accesses_apply(smack.get()));
384
385     smack_set_label_for_self(object);
386     security_server_app_give_access(subject, getpid());
387
388     RUNNER_ASSERT(1 == smack_have_access(subject, object, "rwxat"));
389 }
390
391 RUNNER_TEST(tc01b_security_server_app_give_access)
392 {
393     const char *subject = "abc345v34sfa";
394     const char *object = "efg678x2lkjz";
395
396     // After part A thread from security-server will be notified about
397     // process end and revoke permissions. We need to give him some
398     // time.
399     sleep(1);
400
401     RUNNER_ASSERT(0 == smack_have_access(subject, object, "r----"));
402     RUNNER_ASSERT(0 == smack_have_access(subject, object, "-w---"));
403     RUNNER_ASSERT(0 == smack_have_access(subject, object, "--x--"));
404     RUNNER_ASSERT(0 == smack_have_access(subject, object, "---a-"));
405     RUNNER_ASSERT(0 == smack_have_access(subject, object, "----t"));
406 }
407
408 int main(int argc, char *argv[])
409 {
410     server_sockfd = -1;
411
412     ret = getuid();
413     if(ret != 0)
414     {
415         printf("Error: %s must be executed by root\n", argv[0]);
416         exit(1);
417     }
418
419     int status =
420         DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
421
422     if(server_sockfd > 0)
423         close(server_sockfd);
424     if(client_sockfd > 0)
425         close(client_sockfd);
426
427     return status;
428 }