b53d2b1f2f4b56906f0726eb5dcbe019f4d7640b
[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 /* Get all cookie info response *
42  * packet format
43  *  0                   1                   2                   3
44  *  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 
45  * |---------------------------------------------------------------|
46  * | version=0x01  |MessageID=0x52 |       Message Length          |
47  * |---------------------------------------------------------------|
48  * |  return code  |             tot # of cooks (32bit)            |
49  * |---------------------------------------------------------------|
50  * |   cont'd...   |            1st cmdline_len (32bit)            |
51  * |---------------------------------------------------------------|
52  * |   cont'd...   |           1st permission_len (32bit)          |
53  * ----------------------------------------------------------------|
54  * |   cont'd...   |                                               |
55  * |----------------                                               |
56  * |                         1st cookie                            |
57  * |                                                               |
58  * |---------------------------------------------------------------|
59  * |                         1st PID (32bit)                       |
60  * |---------------------------------------------------------------|
61  * |                     1st cmdline (string)                      |
62  * |---------------------------------------------------------------|
63  * |                           1st perm_1                          |
64  * |---------------------------------------------------------------|
65  * |                           1st perm_2                          |
66  * |---------------------------------------------------------------|
67  * |                              ...                              |
68  * |---------------------------------------------------------------|
69  * |                      2nd cmdline_len  (32bit)                 |
70  * |---------------------------------------------------------------|
71  * |                     2nd permission_len (32bit)                |
72  * |---------------------------------------------------------------|
73  * |                                                               |
74  * |                        2nd cookie                             |
75  * |                                                               |
76  * |---------------------------------------------------------------|
77  * |                         2nd PID (32 bit)                      |
78  * |---------------------------------------------------------------|
79  * |                     2nd cmdline (string)                      |
80  * |---------------------------------------------------------------|
81  * |                           2st perm_1                          |
82  * |---------------------------------------------------------------|
83  * |                           2st perm_2                          |
84  * |---------------------------------------------------------------|
85  * |                              ...                              |
86  * |---------------------------------------------------------------|
87  * |                                                               |
88  * |                             ...                               |
89  * |                                                               |
90  * |                                                               |
91  */
92  unsigned char * get_all_cookie_info(cookie_list *list, int *size)
93 {
94         cookie_list *current = list;
95         int ptr, total_num, total_size, tempnum, i;
96         unsigned char *buf = NULL, *tempptr = NULL;
97         response_header hdr;
98
99         total_size = sizeof(hdr) + sizeof(int);
100
101         buf = malloc(total_size); /* header size */
102         ptr = sizeof(hdr) + sizeof(int);
103         total_num = 0;  /* Total # of cookies initial value */
104
105         while(current != NULL)
106         {
107                 current = garbage_collection(current);
108                 if(current == NULL)
109                         break;
110
111                 total_num++;
112                 total_size += sizeof(int) + sizeof(int) + SECURITY_SERVER_COOKIE_LEN + sizeof(int) + current->path_len + (current->permission_len * sizeof(int));
113                 tempptr = realloc(buf, total_size);
114                 if(tempptr == NULL)
115                 {
116                         SEC_SVR_DBG("%s", "Out of memory");
117                         return NULL;
118                 }
119                 buf = tempptr;
120
121                 tempnum = current->path_len;
122                 memcpy(buf+ptr, &tempnum, sizeof(int));
123                 ptr += sizeof(int);
124                 tempnum = current->permission_len;
125                 memcpy(buf+ptr, &tempnum, sizeof(int));
126                 ptr += sizeof(int);
127                 memcpy(buf+ptr, current->cookie, SECURITY_SERVER_COOKIE_LEN);
128                 ptr += SECURITY_SERVER_COOKIE_LEN;
129                 tempnum = current->pid;
130                 memcpy(buf+ptr, &tempnum, sizeof(int));
131                 ptr += sizeof(int);
132                 memcpy(buf+ptr, current->path, current->path_len);
133                 ptr += current->path_len;
134
135                 for(i=0;i<current->permission_len;i++)
136                 {
137                         tempnum = current->permissions[i];
138                         memcpy(buf+ptr, &tempnum, sizeof(int));
139                         ptr += sizeof(int);
140                 }
141                 current = current->next;
142         }
143
144         if(total_size > 65530)
145         {
146                 SEC_SVR_DBG("Packet too big. message length overflow: %d", total_size);
147                 free(buf);
148                 return  NULL;
149         }
150
151         hdr.basic_hdr.version = SECURITY_SERVER_MSG_VERSION;
152         hdr.basic_hdr.msg_id = SECURITY_SERVER_MSG_TYPE_GET_ALL_COOKIES_RESPONSE;
153         hdr.basic_hdr.msg_len =(unsigned short)( total_size - sizeof(hdr));
154         hdr.return_code = SECURITY_SERVER_RETURN_CODE_SUCCESS;
155         memcpy(buf, &hdr, sizeof(hdr));
156         tempnum = total_num;
157         memcpy(buf + sizeof(hdr), &tempnum, sizeof(int));
158         *size = total_size;
159         return buf;
160 }
161
162 int send_all_cookie_info(const unsigned char *buf, int size, int sockfd)
163 {
164         int ret;
165         /* Check poll */
166         ret = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
167         if(ret == SECURITY_SERVER_ERROR_POLL)
168         {
169                 SEC_SVR_DBG("%s", "poll() error");
170                 return SECURITY_SERVER_ERROR_SEND_FAILED;
171         }
172         if(ret == SECURITY_SERVER_ERROR_TIMEOUT)
173         {
174                 SEC_SVR_DBG("%s", "poll() timeout");
175                 return SECURITY_SERVER_ERROR_SEND_FAILED;
176         }
177
178         /* Send to client */
179         ret = TEMP_FAILURE_RETRY(write(sockfd, buf, size));
180
181         if(ret < size)
182                 return SECURITY_SERVER_ERROR_SEND_FAILED;
183         return SECURITY_SERVER_SUCCESS;
184 }
185
186 /* Get one cookie info response *
187  * packet format
188  *  0                   1                   2                   3
189  *  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 
190  * |---------------------------------------------------------------|
191  * | version=0x01  |MessageID=0x54 |       Message Length          |
192  * |---------------------------------------------------------------|
193  * |  return code  |              cmdline_len (32bit)t)            |
194  * |---------------------------------------------------------------|
195  * |   cont'd...   |              permission_len (32bit)           |
196  * ----------------------------------------------------------------|
197  * |   cont'd...   |                                               |
198  * |----------------                                               |
199  * |                             cookie                            |
200  * |                                                               |
201  * |---------------------------------------------------------------|
202  * |                           PID (32bit)                         |
203  * |---------------------------------------------------------------|
204  * |                         cmdline (string)                      |
205  * |---------------------------------------------------------------|
206  * |                             perm_1                            |
207  * |---------------------------------------------------------------|
208  * |                             perm_2                            |
209  * |---------------------------------------------------------------|
210  * |                              ...                              |
211  * |---------------------------------------------------------------|
212 */
213 int send_one_cookie_info(const cookie_list *list, int sockfd)
214 {
215         unsigned char *buf = NULL;
216         response_header hdr;
217         int total_size, ptr = 0, tempnum, ret, i;
218
219         total_size = sizeof(hdr) + sizeof(int) + sizeof(int) + SECURITY_SERVER_COOKIE_LEN + sizeof(int) + list->path_len + (list->permission_len * sizeof(int));
220         buf = malloc(total_size);
221         if(buf == NULL)
222         {
223                 SEC_SVR_DBG("%s", "Out of memory");
224                 return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
225         }
226
227         hdr.basic_hdr.version = SECURITY_SERVER_MSG_VERSION;
228         hdr.basic_hdr.msg_id = SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE;
229         hdr.basic_hdr.msg_len =sizeof(int) + sizeof(int) + SECURITY_SERVER_COOKIE_LEN + sizeof(int) + list->path_len + (list->permission_len * sizeof(int));
230         hdr.return_code = SECURITY_SERVER_RETURN_CODE_SUCCESS;
231         memcpy(buf, &hdr, sizeof(hdr));
232         ptr += sizeof(hdr);
233
234         tempnum = list->path_len;
235         memcpy(buf+ptr, &tempnum, sizeof(int));
236         ptr += sizeof(int);
237         tempnum = list->permission_len;
238         memcpy(buf+ptr, &tempnum, sizeof(int));
239         ptr += sizeof(int);
240         memcpy(buf+ptr, list->cookie, SECURITY_SERVER_COOKIE_LEN);
241         ptr += SECURITY_SERVER_COOKIE_LEN;
242         tempnum = list->pid;
243         memcpy(buf+ptr, &tempnum, sizeof(int));
244         ptr += sizeof(int);
245         memcpy(buf+ptr, list->path, list->path_len);
246         ptr += list->path_len;
247
248         for(i=0;i<list->permission_len;i++)
249         {
250                 tempnum = list->permissions[i];
251                 memcpy(buf+ptr, &tempnum, sizeof(int));
252                 ptr += sizeof(int);
253         }
254
255         ret = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
256         if(ret == SECURITY_SERVER_ERROR_POLL)
257         {
258                 SEC_SVR_DBG("%s", "poll() error");
259                 free(buf);
260                 return SECURITY_SERVER_ERROR_SEND_FAILED;
261         }
262         if(ret == SECURITY_SERVER_ERROR_TIMEOUT)
263         {
264                 SEC_SVR_DBG("%s", "poll() timeout");
265                 free(buf);
266                 return SECURITY_SERVER_ERROR_SEND_FAILED;
267         }
268
269         /* Send to client */
270         ret = TEMP_FAILURE_RETRY(write(sockfd, buf, total_size));
271         free(buf);
272         if(ret < total_size)
273             return SECURITY_SERVER_ERROR_SEND_FAILED;
274         return SECURITY_SERVER_SUCCESS;
275 }
276
277 int util_process_all_cookie(int sockfd, cookie_list* list)
278 {
279         unsigned char *buf = NULL;
280         int ret;
281         buf = get_all_cookie_info(list, &ret);
282         if(buf == NULL)
283         {
284                 return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
285         }
286
287         ret = send_all_cookie_info(buf, ret, sockfd);
288
289         if(buf != NULL)
290                 free(buf);
291         return ret;
292 }
293 int util_process_cookie_from_pid(int sockfd, cookie_list* list)
294 {
295         int pid, ret;
296         cookie_list *result = NULL;
297
298         ret = TEMP_FAILURE_RETRY(read(sockfd, &pid, sizeof(int)));
299         if(ret < (int)sizeof(int))
300         {
301                 SEC_SVR_DBG("Received cookie size is too small: %d", ret);
302                 return SECURITY_SERVER_ERROR_RECV_FAILED;
303         }
304         if(pid == 0)
305         {
306                 SEC_SVR_DBG("%s", "ERROR: Default cookie is not allowed to be retrieved");
307                 ret = send_generic_response(sockfd, SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE,
308                         SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
309                 if(ret != SECURITY_SERVER_SUCCESS)
310                 {
311                         SEC_SVR_DBG("ERROR: Cannot send generic response: %d", ret);
312                 }
313         }
314         result = search_cookie_from_pid(list, pid);
315         if(result == NULL)
316         {
317                 ret = send_generic_response(sockfd, SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE,
318                         SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE);
319                 if(ret != SECURITY_SERVER_SUCCESS)
320                 {
321                         SEC_SVR_DBG("ERROR: Cannot send generic response: %d", ret);
322                 }
323         }
324         else
325         {
326                 ret = send_one_cookie_info(result, sockfd);
327                 if(ret != SECURITY_SERVER_SUCCESS)
328                 {
329                         SEC_SVR_DBG("ERROR: Cannot send cookie info response: %d", ret);
330                 }
331         }
332         
333         return ret;
334 }
335
336 int util_process_cookie_from_cookie(int sockfd, cookie_list* list)
337 {
338         unsigned char cookie[SECURITY_SERVER_COOKIE_LEN];
339         int ret;
340     int privileges[] = { 0 };   //only one privilege to check - root
341         cookie_list *result = NULL;
342
343         ret = TEMP_FAILURE_RETRY(read(sockfd, cookie, SECURITY_SERVER_COOKIE_LEN));
344         if(ret < SECURITY_SERVER_COOKIE_LEN)
345         {
346                 SEC_SVR_DBG("Received cookie size is too small: %d", ret);
347                 return SECURITY_SERVER_ERROR_RECV_FAILED;
348         }
349         result = search_cookie(list, cookie, privileges, 1);
350         if(result == NULL)
351         {
352                 ret = send_generic_response(sockfd, SECURITY_SERVER_MSG_TYPE_GET_COOKIEINFO_RESPONSE,
353                         SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE);
354                 if(ret != SECURITY_SERVER_SUCCESS)
355                 {
356                         SEC_SVR_DBG("ERROR: Cannot send generic response: %d", ret);
357                 }
358         }
359         else
360         {
361                 ret = send_one_cookie_info(result, sockfd);
362                 if(ret != SECURITY_SERVER_SUCCESS)
363                 {
364                         SEC_SVR_DBG("ERROR: Cannot send cookie info response: %d", ret);
365                 }
366         }
367         
368         return ret;
369 }
370
371 int util_smack_label_is_valid(const char *smack_label){
372         int i;
373
374         if (!smack_label || smack_label[0] == '\0' || smack_label[0] == '-')
375                 goto err;
376
377         for (i = 0; smack_label[i]; ++i) {
378                 if (i >= SMACK_LABEL_LEN)
379                         return 0;
380                 switch (smack_label[i]) {
381                 case '~':
382                 case ' ':
383                 case '/':
384                 case '"':
385                 case '\\':
386                 case '\'':
387                         goto err;
388                 default:
389                         break;
390                 }
391         }
392
393         return 1;
394 err:
395         // TODO replace it with SEC_SVR_DBG when master is merged
396         SEC_SVR_DBG("ERROR: Invalid Smack label: %s", smack_label);
397         return 0;
398 }