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