3 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
5 * Contact: Bumjin Im <bj.im@samsung.com>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License
27 #include <sys/types.h>
29 #include <sys/smack.h>
31 #include "security-server-cookie.h"
33 /* Delete useless cookie item *
34 * then connect prev and next */
35 int free_cookie_item(cookie_list *cookie)
37 if(cookie->path != NULL)
39 if(cookie->permissions != NULL)
40 free(cookie->permissions);
41 if(cookie->smack_label != NULL)
42 free(cookie->smack_label);
43 if(cookie->prev != NULL)
44 cookie->prev->next = cookie->next;
45 if(cookie->next != NULL)
46 cookie->next->prev = cookie->prev;
52 /* Cut the link of the current cookie item and connect previous link and next line *
53 * That is remove a cookie item *
54 * Returns next cookie item if exist, NULL for no more cookie item */
55 cookie_list *delete_cookie_item(cookie_list *cookie)
57 cookie_list *retval = NULL;
60 SEC_SVR_DBG("%s", "Cannot delete null cookie");
64 /* Reconnect cookie item */
65 if(cookie->next != NULL)
67 cookie->prev->next = cookie->next;
68 cookie->next->prev = cookie->prev;
69 retval = cookie->next;
73 cookie->prev->next = NULL;
76 free_cookie_item(cookie);
80 cookie_list * garbage_collection(cookie_list *cookie)
83 cookie_list *retval = NULL;
89 /* Skip default cookie */
93 /* Try to find the PID directory from proc fs */
94 snprintf(path, sizeof(path), "/proc/%d", cookie->pid);
96 ret = stat(path, &statbuf);
99 /* If it's not exist, delete the cookie */
102 SEC_SVR_DBG("Garbage found. PID:%d, deleting...", cookie->pid);
103 cookie = delete_cookie_item(cookie);
108 /* Some error occurred */
109 SEC_SVR_DBG("Error occurred on stat: errno = %d", errno);
115 /* This is not a garbage. returning */
122 /* Search existing cookie from the cookie list for the client process *
123 * At the same time, it collects garbage cookie which PID is no longer exist and delete them */
124 cookie_list *search_existing_cookie(int pid, const cookie_list *c_list)
126 cookie_list *current =(cookie_list *)c_list, *cookie = NULL;
127 char *cmdline = NULL, *debug_cmdline = NULL;
129 /* Search from the list */
130 while(current != NULL)
132 /* print_cookie(current);*/
133 current = garbage_collection(current);
137 /* PID must be same */
138 if(current->pid == pid)
140 /* Found cookie for the pid. Check the cookie is reused by dirrent executable */
141 /* Check the path of the process */
142 cmdline = (char*)read_cmdline_from_proc(pid);
145 SEC_SVR_DBG("%s", "cannot read cmdline");
148 /* Check the path is different */
149 if(strncmp(cmdline, current->path, current->path_len) != 0 || strlen(cmdline) != current->path_len)
151 SEC_SVR_DBG("pid [%d] has been reused by %s. deleting the old cookie.", pid, cmdline);
152 debug_cmdline = malloc(current->path_len + 1);
153 if(debug_cmdline == NULL)
155 SEC_SVR_DBG("%s", "out of memory error");
159 strncpy(debug_cmdline, current->path, current->path_len);
160 debug_cmdline[current->path_len] = 0;
161 SEC_SVR_DBG("[%s] --> [%s]", cmdline, debug_cmdline);
162 if(debug_cmdline != NULL)
165 debug_cmdline = NULL;
167 /* Okay. delete current cookie */
168 current = delete_cookie_item(current);
178 SEC_SVR_DBG("%s", "cookie found");
188 current = current->next;
193 /* Search existing cookie from the cookie list for matching pid *
194 * Default cookie (meaning PID 0) is not allowed in here */
195 cookie_list *search_cookie_from_pid(cookie_list *c_list, int pid)
197 cookie_list *current = (cookie_list *)c_list, *retval = NULL;
199 /* Search from the list */
200 while(current != NULL)
202 /* print_cookie(current);*/
203 /* PID must be same */
204 current = garbage_collection(current);
208 if(current->pid == pid)
210 SEC_SVR_DBG("%s", "cookie has been found");
214 current = current->next;
220 /* Search existing cookie from the cookie list for matching cookie and privilege */
221 /* If privilege is 0, just search cookie exists or not */
222 cookie_list *search_cookie(const cookie_list *c_list, const unsigned char *cookie, int privilege)
224 cookie_list *current = (cookie_list *)c_list, *retval = NULL;
227 /* Search from the list */
228 while(current != NULL)
230 /* print_cookie(current);*/
231 /* PID must be same */
232 current = garbage_collection(current);
236 //searching for cookie
237 if(memcmp(current->cookie, cookie, SECURITY_SERVER_COOKIE_LEN) == 0)
239 SEC_SVR_DBG("%s", "cookie has been found");
241 //check if this cookie belongs to root process
242 if(current->is_roots_process == 1)
244 SEC_SVR_DBG("%s", "Root process cookie, special privileges");
245 //we can skip privilege checking
250 for(i=0 ; i < current->permission_len ; i++)
252 if(privilege == current->permissions[i])
254 SEC_SVR_DBG("Found privilege %d", privilege);
260 current = current->next;
267 cookie_list *search_cookie_new(const cookie_list *c_list,
268 const unsigned char *cookie,
270 const char *access_rights)
272 cookie_list *current = (cookie_list *)c_list, *retval = NULL;
276 /* Search from the list */
277 while(current != NULL)
279 /* print_cookie(current);*/
280 /* PID must be same */
281 current = garbage_collection(current);
285 if(memcmp(current->cookie, cookie, SECURITY_SERVER_COOKIE_LEN) == 0)
287 SEC_SVR_DBG("%s", "cookie has been found");
289 ret = smack_have_access(current->smack_label, object, access_rights);
290 SEC_SVR_DBG("smack_have_access, subject >%s< object >%s< access >%s< ===> %d",
291 current->smack_label, object, access_rights, ret);
298 current = current->next;
305 /* Generage a random stream value of size to cookie *
306 * by reading /dev/uranddom file */
307 int generate_random_cookie(unsigned char *cookie, int size)
311 if (cookie == NULL) {
312 SEC_SVR_DBG("%s", "Null pointer passed to function");
313 return SECURITY_SERVER_ERROR_UNKNOWN;
315 fd = open("/dev/urandom", O_RDONLY);
318 SEC_SVR_DBG("%s", "Cannot open /dev/urandom");
319 return SECURITY_SERVER_ERROR_FILE_OPERATION;
321 ret = read(fd, cookie, size);
324 SEC_SVR_DBG("Cannot read /dev/urandom: %d", ret);
325 ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
329 ret = SECURITY_SERVER_SUCCESS;
336 /* Create a cookie item from PID */
337 cookie_list *create_cookie_item(int pid, int sockfd, cookie_list *c_list)
340 cookie_list *added = NULL, *current = NULL;
341 char path[24], *cmdline = NULL;
342 char *buf = NULL, inputed, *tempptr = NULL;
343 char delim[] = ": ", *token = NULL;
344 int *permissions = NULL, perm_num = 1, cnt, i, *tempperm = NULL;
345 char *smack_label = NULL;
348 current = search_existing_cookie(pid, c_list);
351 /* There is a cookie for this process already */
353 SEC_SVR_DBG("%s", "Existing cookie found");
357 /* Read command line of the PID from proc fs */
358 cmdline = (char *)read_cmdline_from_proc(pid);
361 SEC_SVR_DBG("Error on reading /proc/%d/cmdline", pid);
366 * modified by security part
367 * - get gid from /etc/group
369 /* Read group info of the PID from proc fs - /proc/[PID]/status */
370 snprintf(path, sizeof(path), "/proc/%d/status", pid);
371 fp = fopen(path, "r");
373 /* Find the line which starts with 'Groups:' */
378 buf = (char*)malloc(sizeof(char) * 128);
381 SEC_SVR_DBG("%s", "Error on malloc()");
384 memset(buf, 0x00, 128);
387 /* get one line from /proc/[PID]/status */
391 inputed = (char)tempint;
394 else if(inputed == '\n')
399 else if((i == cnt) && (inputed != '\n'))
401 tempptr = (char*)realloc(buf, sizeof(char) * (i + 128));
404 SEC_SVR_DBG("%s", "Error on realloc()");
417 if(strncmp(buf, "Groups:", 7) == 0)
419 /* get gid from the line and insert to 'permissions' array */
420 token = strtok(buf, delim); // first string is "Groups"
421 while((token = strtok(NULL, delim)))
423 tempperm = realloc(permissions, sizeof(int) * perm_num);
426 SEC_SVR_DBG("%s", "Error on realloc()");
429 permissions = tempperm;
431 permissions[perm_num - 1] = strtoul(token, 0, 10);
434 SEC_SVR_DBG("cannot change string to integer [%s]", token);
435 ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
442 /* goto out of while loop */
453 /* Each group ID is stored in each line of the file */
454 // while(fgets(permline, sizeof(permline), fp) != NULL)
456 // permissions = realloc(permissions, sizeof(int) * perm_num);
457 // if(permissions == NULL)
459 // SEC_SVR_DBG("%s", "Error on realloc()");
462 // permissions[perm_num -1] = strtoul(permline, 0, 10);
470 /* Go to last cookie from the list */
472 while(current->next != NULL)
474 current = current->next;
477 /* Create a new one and assign values */
478 added = malloc(sizeof(cookie_list));
482 ret = generate_random_cookie(added->cookie, SECURITY_SERVER_COOKIE_LEN);
483 if(ret != SECURITY_SERVER_SUCCESS)
485 SEC_SVR_DBG("Error on making random cookie: %d", ret);
491 /* Check SMACK label */
492 ret = smack_new_label_from_socket(sockfd, &smack_label);
495 SEC_SVR_DBG("Error checking peer label: %d", ret);
501 added->path_len = strlen(cmdline);
502 added->path = calloc(1, strlen(cmdline));
503 memcpy(added->path, cmdline, strlen(cmdline));
505 added->permission_len = perm_num;
507 added->permissions = permissions;
508 added->smack_label = smack_label;
509 added->prev = current;
510 current->next = added;
521 if(added == NULL && permissions != NULL)
527 /* Check stored default cookie, if it's not exist make a new one and store it */
528 int check_stored_cookie(unsigned char *cookie, int size)
532 /* First, check the default cookie is stored */
533 fd = open(SECURITY_SERVER_DEFAULT_COOKIE_PATH, O_RDONLY);
538 SEC_SVR_DBG("Cannot open default cookie. errno=%d", errno);
539 ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
540 unlink(SECURITY_SERVER_DEFAULT_COOKIE_PATH);
543 ret = generate_random_cookie(cookie, size);
545 /* Save cookie to disk */
546 fd = open(SECURITY_SERVER_DEFAULT_COOKIE_PATH, O_WRONLY | O_CREAT, 0600);
549 SEC_SVR_DBG("Cannot open default cookie errno=%d", errno);
550 ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
553 ret = write(fd, cookie, size);
556 SEC_SVR_DBG("%s", "Cannot save default cookie");
557 ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
562 return SECURITY_SERVER_SUCCESS;
565 ret = read (fd, cookie, size);
568 SEC_SVR_DBG("Cannot read default cookie errno=%d", errno);
569 ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
572 ret = SECURITY_SERVER_SUCCESS;
579 /* Create a cookie item from PID */
581 /* Create a default cookie when security server is executed *
582 * Default cookie is for root processes that needs cookie */
583 cookie_list *create_default_cookie(void)
585 cookie_list *first = NULL;
588 first = malloc(sizeof(cookie_list));
590 ret = check_stored_cookie(first->cookie, SECURITY_SERVER_COOKIE_LEN);
591 if(ret != SECURITY_SERVER_SUCCESS)
593 SEC_SVR_DBG("Error on making random cookie: %d", ret);
599 first->permission_len = 0;
602 first->permissions = NULL;
603 first->smack_label = NULL;