Cookie executable path logic fixed and refactored.
[framework/security/security-server.git] / src / util / security-server-util-common.c
1 /*
2  *  security-server
3  *
4  *  Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  *  Contact: Bumjin Im <bj.im@samsung.com>
7  *
8  *  Licensed under the Apache License, Version 2.0 (the "License");
9  *  you may not use this file except in compliance with the License.
10  *  You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *  Unless required by applicable law or agreed to in writing, software
15  *  distributed under the License is distributed on an "AS IS" BASIS,
16  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *  See the License for the specific language governing permissions and
18  *  limitations under the License
19  *
20  */
21
22
23 #include <poll.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/socket.h>
27 #include <sys/types.h>
28 #include <sys/smack.h>
29 #include <fcntl.h>
30 #include <sys/un.h>
31 #include <errno.h>
32 #include <unistd.h>
33
34 #include "security-server-common.h"
35 #include "security-server-cookie.h"
36 #include "security-server-comm.h"
37 #include "security-server-util.h"
38 #include "security-server.h"
39
40 /*
41  * @buffer   output buffer
42  * @position target position in output buffer
43  * @source   source data
44  * @len      source data length
45  */
46 static void append_to_buffer(unsigned char *buffer, int* position, const void* source, size_t len) {
47         if (len <= 0) {
48                 SEC_SVR_DBG("Appending nothing.");
49                 return;
50         }
51         memcpy(buffer + *position, source, len);
52         *position += len;
53 }
54
55 static void append_cookie(unsigned char *buffer, int* position, const cookie_list* cookie) {
56         int i;
57         int path_len = cookie->path ? strlen(cookie->path) : 0;
58
59         append_to_buffer(buffer, position, &path_len, sizeof(int));
60         append_to_buffer(buffer, position, &cookie->permission_len, sizeof(int));
61         append_to_buffer(buffer, position, &cookie->cookie, SECURITY_SERVER_COOKIE_LEN);
62         append_to_buffer(buffer, position, &cookie->pid, sizeof(pid_t));
63         append_to_buffer(buffer, position, &cookie->path, path_len);
64
65         for(i=0;i<cookie->permission_len;++i)
66                 append_to_buffer(buffer, position, &cookie->permissions[i], sizeof(int));
67 }
68
69 /* Get all cookie info response *
70  * packet format
71  *  0                   1                   2                   3
72  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
73  * |---------------------------------------------------------------|
74  * | version=0x01  |MessageID=0x52 |       Message Length          |
75  * |---------------------------------------------------------------|
76  * |  return code  |             tot # of cooks (32bit)            |
77  * |---------------------------------------------------------------|
78  * |   cont'd...   |            1st cmdline_len (32bit)            |
79  * |---------------------------------------------------------------|
80  * |   cont'd...   |           1st permission_len (32bit)          |
81  * ----------------------------------------------------------------|
82  * |   cont'd...   |                                               |
83  * |----------------                                               |
84  * |                         1st cookie                            |
85  * |                                                               |
86  * |---------------------------------------------------------------|
87  * |                         1st PID (32bit)                       |
88  * |---------------------------------------------------------------|
89  * |                     1st cmdline (string)                      |
90  * |---------------------------------------------------------------|
91  * |                           1st perm_1                          |
92  * |---------------------------------------------------------------|
93  * |                           1st perm_2                          |
94  * |---------------------------------------------------------------|
95  * |                              ...                              |
96  * |---------------------------------------------------------------|
97  * |                      2nd cmdline_len  (32bit)                 |
98  * |---------------------------------------------------------------|
99  * |                     2nd permission_len (32bit)                |
100  * |---------------------------------------------------------------|
101  * |                                                               |
102  * |                        2nd cookie                             |
103  * |                                                               |
104  * |---------------------------------------------------------------|
105  * |                         2nd PID (32 bit)                      |
106  * |---------------------------------------------------------------|
107  * |                     2nd cmdline (string)                      |
108  * |---------------------------------------------------------------|
109  * |                           2st perm_1                          |
110  * |---------------------------------------------------------------|
111  * |                           2st perm_2                          |
112  * |---------------------------------------------------------------|
113  * |                              ...                              |
114  * |---------------------------------------------------------------|
115  * |                                                               |
116  * |                             ...                               |
117  * |                                                               |
118  * |                                                               |
119  */
120 unsigned char * get_all_cookie_info(cookie_list *list, int *size)
121 {
122         cookie_list *current = list;
123         int ptr, total_num, total_size, path_len;
124         unsigned char *buf = NULL, *tempptr = NULL;
125         response_header hdr;
126
127         total_size = sizeof(hdr) + sizeof(int);
128
129         buf = malloc(total_size); /* header size */
130         ptr = sizeof(hdr) + sizeof(int);
131         total_num = 0;  /* Total # of cookies initial value */
132
133         while(current != NULL)
134         {
135                 current = garbage_collection(current);
136                 if(current == NULL)
137                         break;
138
139                 total_num++;
140                 path_len = current->path ? strlen(current->path) : 0;
141                 total_size += sizeof(int) + sizeof(int) + SECURITY_SERVER_COOKIE_LEN + sizeof(pid_t) + path_len + (current->permission_len * sizeof(int));
142                 tempptr = realloc(buf, total_size);
143                 if(tempptr == NULL)
144                 {
145                         SEC_SVR_DBG("%s", "Out of memory");
146                         return NULL;
147                 }
148                 buf = tempptr;
149
150                 append_cookie(buf, &ptr, current);
151                 current = current->next;
152         }
153
154         if(total_size > 65530)
155         {
156                 SEC_SVR_DBG("Packet too big. message length overflow: %d", total_size);
157                 free(buf);
158                 return  NULL;
159         }
160
161         hdr.basic_hdr.version = SECURITY_SERVER_MSG_VERSION;
162         hdr.basic_hdr.msg_id = SECURITY_SERVER_MSG_TYPE_GET_ALL_COOKIES_RESPONSE;
163         hdr.basic_hdr.msg_len =(unsigned short)( total_size - sizeof(hdr));
164         hdr.return_code = SECURITY_SERVER_RETURN_CODE_SUCCESS;
165
166         // reset buffer position to the beginning of buffer and insert header
167         ptr = 0;
168         append_to_buffer(buf, &ptr, &hdr, sizeof(hdr));
169         append_to_buffer(buf, &ptr, &total_num, sizeof(total_num));
170         *size = total_size;
171         return buf;
172 }
173
174 int send_all_cookie_info(const unsigned char *buf, int size, int sockfd)
175 {
176         int ret;
177         /* Check poll */
178         ret = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
179         if(ret == SECURITY_SERVER_ERROR_POLL)
180         {
181                 SEC_SVR_DBG("%s", "poll() error");
182                 return SECURITY_SERVER_ERROR_SEND_FAILED;
183         }
184         if(ret == SECURITY_SERVER_ERROR_TIMEOUT)
185         {
186                 SEC_SVR_DBG("%s", "poll() timeout");
187                 return SECURITY_SERVER_ERROR_SEND_FAILED;
188         }
189
190         /* Send to client */
191         ret = TEMP_FAILURE_RETRY(write(sockfd, buf, size));
192
193         if(ret < size)
194                 return SECURITY_SERVER_ERROR_SEND_FAILED;
195         return SECURITY_SERVER_SUCCESS;
196 }
197
198 /* Get one cookie info response *
199  * packet format
200  *  0                   1                   2                   3
201  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
202  * |---------------------------------------------------------------|
203  * | version=0x01  |MessageID=0x54 |       Message Length          |
204  * |---------------------------------------------------------------|
205  * |  return code  |              cmdline_len (32bit)t)            |
206  * |---------------------------------------------------------------|
207  * |   cont'd...   |              permission_len (32bit)           |
208  * ----------------------------------------------------------------|
209  * |   cont'd...   |                                               |
210  * |----------------                                               |
211  * |                             cookie                            |
212  * |                                                               |
213  * |---------------------------------------------------------------|
214  * |                           PID (32bit)                         |
215  * |---------------------------------------------------------------|
216  * |                         cmdline (string)                      |
217  * |---------------------------------------------------------------|
218  * |                             perm_1                            |
219  * |---------------------------------------------------------------|
220  * |                             perm_2                            |
221  * |---------------------------------------------------------------|
222  * |                              ...                              |
223  * |---------------------------------------------------------------|
224 */
225 int send_one_cookie_info(const cookie_list *list, int sockfd)
226 {
227         unsigned char *buf = NULL;
228         response_header hdr;
229         int total_size, ptr = 0, ret, path_len;
230
231         path_len = list->path ? strlen(list->path) : 0;
232
233         total_size = sizeof(hdr) + sizeof(int) + sizeof(int) + SECURITY_SERVER_COOKIE_LEN + sizeof(pid_t) + path_len + (list->permission_len * sizeof(int));
234         buf = malloc(total_size);
235         if(buf == NULL)
236         {
237                 SEC_SVR_DBG("%s", "Out of memory");
238                 return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
239         }
240
241         hdr.basic_hdr.version = SECURITY_SERVER_MSG_VERSION;
242         hdr.basic_hdr.msg_id = SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE;
243         hdr.basic_hdr.msg_len =sizeof(int) + sizeof(int) + SECURITY_SERVER_COOKIE_LEN + sizeof(pid_t) + path_len + (list->permission_len * sizeof(int));
244         hdr.return_code = SECURITY_SERVER_RETURN_CODE_SUCCESS;
245
246         // header
247         append_to_buffer(buf, &ptr, &hdr, sizeof(hdr));
248         // cookie
249         append_cookie(buf, &ptr, list);
250
251         ret = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
252         if(ret == SECURITY_SERVER_ERROR_POLL)
253         {
254                 SEC_SVR_DBG("%s", "poll() error");
255                 free(buf);
256                 return SECURITY_SERVER_ERROR_SEND_FAILED;
257         }
258         if(ret == SECURITY_SERVER_ERROR_TIMEOUT)
259         {
260                 SEC_SVR_DBG("%s", "poll() timeout");
261                 free(buf);
262                 return SECURITY_SERVER_ERROR_SEND_FAILED;
263         }
264
265         /* Send to client */
266         ret = TEMP_FAILURE_RETRY(write(sockfd, buf, total_size));
267         free(buf);
268         if(ret < total_size)
269             return SECURITY_SERVER_ERROR_SEND_FAILED;
270         return SECURITY_SERVER_SUCCESS;
271 }
272
273 int util_process_all_cookie(int sockfd, cookie_list* list)
274 {
275         unsigned char *buf = NULL;
276         int ret;
277         buf = get_all_cookie_info(list, &ret);
278         if(buf == NULL)
279         {
280                 return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
281         }
282
283         ret = send_all_cookie_info(buf, ret, sockfd);
284
285         if(buf != NULL)
286                 free(buf);
287         return ret;
288 }
289 int util_process_cookie_from_pid(int sockfd, cookie_list* list)
290 {
291         int pid, ret;
292         cookie_list *result = NULL;
293
294         ret = TEMP_FAILURE_RETRY(read(sockfd, &pid, sizeof(int)));
295         if(ret < (int)sizeof(int))
296         {
297                 SEC_SVR_DBG("Received cookie size is too small: %d", ret);
298                 return SECURITY_SERVER_ERROR_RECV_FAILED;
299         }
300         if(pid == 0)
301         {
302                 SEC_SVR_DBG("%s", "ERROR: Default cookie is not allowed to be retrieved");
303                 ret = send_generic_response(sockfd, SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE,
304                         SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
305                 if(ret != SECURITY_SERVER_SUCCESS)
306                 {
307                         SEC_SVR_DBG("ERROR: Cannot send generic response: %d", ret);
308                 }
309         }
310         result = search_cookie_from_pid(list, pid);
311         if(result == NULL)
312         {
313                 ret = send_generic_response(sockfd, SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE,
314                         SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE);
315                 if(ret != SECURITY_SERVER_SUCCESS)
316                 {
317                         SEC_SVR_DBG("ERROR: Cannot send generic response: %d", ret);
318                 }
319         }
320         else
321         {
322                 ret = send_one_cookie_info(result, sockfd);
323                 if(ret != SECURITY_SERVER_SUCCESS)
324                 {
325                         SEC_SVR_DBG("ERROR: Cannot send cookie info response: %d", ret);
326                 }
327         }
328         
329         return ret;
330 }
331
332 int util_process_cookie_from_cookie(int sockfd, cookie_list* list)
333 {
334         unsigned char cookie[SECURITY_SERVER_COOKIE_LEN];
335         int ret;
336     int privileges[] = { 0 };   //only one privilege to check - root
337         cookie_list *result = NULL;
338
339         ret = TEMP_FAILURE_RETRY(read(sockfd, cookie, SECURITY_SERVER_COOKIE_LEN));
340         if(ret < SECURITY_SERVER_COOKIE_LEN)
341         {
342                 SEC_SVR_DBG("Received cookie size is too small: %d", ret);
343                 return SECURITY_SERVER_ERROR_RECV_FAILED;
344         }
345         result = search_cookie(list, cookie, privileges, 1);
346         if(result == NULL)
347         {
348                 ret = send_generic_response(sockfd, SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE,
349                         SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE);
350                 if(ret != SECURITY_SERVER_SUCCESS)
351                 {
352                         SEC_SVR_DBG("ERROR: Cannot send generic response: %d", ret);
353                 }
354         }
355         else
356         {
357                 ret = send_one_cookie_info(result, sockfd);
358                 if(ret != SECURITY_SERVER_SUCCESS)
359                 {
360                         SEC_SVR_DBG("ERROR: Cannot send cookie info response: %d", ret);
361                 }
362         }
363         
364         return ret;
365 }
366
367 int util_smack_label_is_valid(const char *smack_label){
368         int i;
369
370         if (!smack_label || smack_label[0] == '\0' || smack_label[0] == '-')
371                 goto err;
372
373         for (i = 0; smack_label[i]; ++i) {
374                 if (i >= SMACK_LABEL_LEN)
375                         return 0;
376                 switch (smack_label[i]) {
377                 case '~':
378                 case ' ':
379                 case '/':
380                 case '"':
381                 case '\\':
382                 case '\'':
383                         goto err;
384                 default:
385                         break;
386                 }
387         }
388
389         return 1;
390 err:
391         // TODO replace it with SEC_SVR_DBG when master is merged
392         SEC_SVR_DBG("ERROR: Invalid Smack label: %s", smack_label);
393         return 0;
394 }