Check if SMACK is enabled, if not skip code so cookie creation doesn't fail
[profile/ivi/security-server.git] / src / security-srv / server / security-server-cookie.c
1 /*
2  *  security-server
3  *  Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
4  *
5  *  Contact: Bumjin Im <bj.im@samsung.com>
6  *
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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
18  *
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <sys/stat.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <fcntl.h>
29 #include <sys/smack.h>
30
31 #include "security-server-cookie.h"
32
33 /* Delete useless cookie item *
34  * then connect prev and next */
35 int free_cookie_item(cookie_list *cookie)
36 {
37         if(cookie->path != NULL)
38                 free(cookie->path);
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;
47         free(cookie);
48         cookie = NULL;
49         return 0;
50 }
51
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)
56 {
57         cookie_list *retval = NULL;
58         if(cookie == NULL)
59         {
60                 SEC_SVR_DBG("%s", "Cannot delete null cookie");
61                 return retval;
62         }
63
64         /* Reconnect cookie item */
65         if(cookie->next != NULL)
66         {
67                 cookie->prev->next = cookie->next;
68                 cookie->next->prev = cookie->prev;
69                 retval = cookie->next;
70         }
71         else
72         {
73                 cookie->prev->next = NULL;
74         }
75         
76         free_cookie_item(cookie);
77         return retval;
78 }
79
80 cookie_list * garbage_collection(cookie_list *cookie)
81 {
82         char path[17];
83         cookie_list *retval = NULL;
84         struct stat statbuf;
85         int ret;
86
87         while(cookie != NULL)
88         {
89                 /* Skip default cookie */
90                 if(cookie->pid ==0)
91                         return cookie;
92
93                 /* Try to find the PID directory from proc fs */
94                 snprintf(path, sizeof(path), "/proc/%d", cookie->pid);
95                 path[16] = 0;
96                 ret = stat(path, &statbuf);
97                 if(ret != 0)
98                 {
99                         /* If it's not exist, delete the cookie */
100                         if(errno == ENOENT)
101                         {
102                                 SEC_SVR_DBG("Garbage found. PID:%d, deleting...", cookie->pid);
103                                 cookie = delete_cookie_item(cookie);
104                                 continue;
105                         }
106                         else
107                         {
108                                 /* Some error occurred */
109                                 SEC_SVR_DBG("Error occurred on stat: errno = %d", errno);
110                                 return cookie;
111                         }
112                 }
113                 else
114                 {
115                         /* This is not a garbage. returning */
116                         return cookie;
117                 }
118         }
119         return retval;
120 }
121
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)
125 {
126         cookie_list *current =(cookie_list *)c_list, *cookie = NULL;
127         char *cmdline = NULL, *debug_cmdline = NULL;
128
129         /* Search from the list */
130         while(current != NULL)
131         {
132                 /* print_cookie(current);*/
133                 current = garbage_collection(current);
134                 if(current == NULL)
135                         break;
136
137                 /* PID must be same */
138                 if(current->pid == pid)
139                 {
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);
143                         if(cmdline == NULL)
144                         {
145                                 SEC_SVR_DBG("%s", "cannot read cmdline");
146                                 return NULL;
147                         }
148                         /* Check the path is different */
149                         if(strncmp(cmdline, current->path, current->path_len) != 0 || strlen(cmdline) != current->path_len)
150                         {
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)
154                                 {
155                                         SEC_SVR_DBG("%s", "out of memory error");
156                                         free(cmdline);
157                                         return NULL;
158                                 }
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)
163                                 {
164                                         free(debug_cmdline);
165                                         debug_cmdline = NULL;
166                                 }
167                                 /* Okay. delete current cookie */
168                                 current = delete_cookie_item(current);
169                                 if(cmdline != NULL)
170                                 {
171                                         free(cmdline);
172                                         cmdline = NULL;
173                                 }
174                                 continue;
175                         }
176                         else
177                         {
178                                 SEC_SVR_DBG("%s", "cookie found");
179                                 cookie = current;
180                         }
181
182                         if(cmdline != NULL)
183                         {
184                                 free(cmdline);
185                                 cmdline = NULL;
186                         }
187                 }
188                 current = current->next;
189         }
190         return cookie;
191 }
192
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)
196 {
197         cookie_list *current = (cookie_list *)c_list, *retval = NULL;
198
199         /* Search from the list */
200         while(current != NULL)
201         {
202                 /* print_cookie(current);*/
203                 /* PID must be same */
204                 current = garbage_collection(current);
205                 if(current == NULL)
206                         break;
207
208                 if(current->pid == pid)
209                 {
210                         SEC_SVR_DBG("%s", "cookie has been found");
211                         retval = current;
212                         goto finish;
213                 }
214                 current = current->next;
215         }
216 finish:
217         return retval;
218 }
219
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)
223 {
224         cookie_list *current = (cookie_list *)c_list, *retval = NULL;
225         int i;
226
227         /* Search from the list */
228         while(current != NULL)
229         {
230                 /* print_cookie(current);*/
231                 /* PID must be same */
232                 current = garbage_collection(current);
233                 if(current == NULL)
234                         break;
235
236                 if(memcmp(current->cookie, cookie, SECURITY_SERVER_COOKIE_LEN) == 0)
237                 {
238                         SEC_SVR_DBG("%s", "cookie has been found");
239
240                         /* default cookie is for root process which is pid is set to 0 */
241                         if(current->pid == 0 || privilege == 0)
242                         {
243                                 retval = current;
244                                 goto finish;
245                         }
246                         else
247                         {
248                                 for(i=0 ; i < current->permission_len ; i++)
249                                 {
250                                         if(privilege == current->permissions[i])
251                                         {
252                                                 SEC_SVR_DBG("Found privilege %d", privilege);
253                                                 retval = current;
254                                                 goto finish;
255                                         }
256                                 }
257                         }
258                 }
259                 current = current->next;
260         }
261 finish:
262         return retval;
263 }
264
265
266 cookie_list *search_cookie_new(const cookie_list *c_list,
267                                const unsigned char *cookie,
268                                const char *object,
269                                const char *access_rights)
270 {
271         cookie_list *current = (cookie_list *)c_list, *retval = NULL;
272         int ret;
273         int i;
274
275         /* Search from the list */
276         while(current != NULL)
277         {
278                 /* print_cookie(current);*/
279                 /* PID must be same */
280                 current = garbage_collection(current);
281                 if(current == NULL)
282                         break;
283
284                 if(memcmp(current->cookie, cookie, SECURITY_SERVER_COOKIE_LEN) == 0)
285                 {
286                         SEC_SVR_DBG("%s", "cookie has been found");
287
288                                 ret = smack_have_access(current->smack_label, object, access_rights);
289           SEC_SVR_DBG("smack_have_access, subject >%s< object >%s< access >%s< ===> %d",
290                     current->smack_label, object, access_rights, ret);
291                                 if (ret == 1)
292                                 {
293                                         retval = current;
294                                         goto finish;
295                                 }
296                 }
297                 current = current->next;
298         }
299 finish:
300         return retval;
301 }
302
303
304 /* Generage a random stream value of size to cookie *
305  * by reading /dev/uranddom file */
306 int generate_random_cookie(unsigned char *cookie, int size)
307 {
308         int fd, ret;
309
310     if (cookie == NULL) {
311         SEC_SVR_DBG("%s", "Null pointer passed to function");
312         return SECURITY_SERVER_ERROR_UNKNOWN;
313     }
314         fd = open("/dev/urandom", O_RDONLY);
315         if(fd < 0)
316         {
317                 SEC_SVR_DBG("%s", "Cannot open /dev/urandom");
318                 return SECURITY_SERVER_ERROR_FILE_OPERATION;
319         }
320         ret = read(fd, cookie, size);
321         if(ret < size)
322         {
323                 SEC_SVR_DBG("Cannot read /dev/urandom: %d", ret);
324                 ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
325                 goto error;
326         }
327         close(fd);
328         ret = SECURITY_SERVER_SUCCESS;
329 error:
330         if(fd >= 0)
331                 close(fd);
332         return ret;
333 }
334
335 /* Create a cookie item from PID */
336 cookie_list *create_cookie_item(int pid, int sockfd, cookie_list *c_list)
337 {
338         int ret, tempint;
339         cookie_list *added = NULL, *current = NULL;
340         char path[24], *cmdline = NULL;
341         char *buf = NULL, inputed, *tempptr = NULL;
342         char delim[] = ": ", *token = NULL;
343         int *permissions = NULL, perm_num = 1, cnt, i, *tempperm = NULL;
344         char *smack_label = NULL;
345         FILE *fp = NULL;
346
347         current = search_existing_cookie(pid, c_list);
348         if(current != NULL)
349         {
350                 /* There is a cookie for this process already */
351                 added = current;
352                 SEC_SVR_DBG("%s", "Existing cookie found");
353                 goto error;
354         }
355
356         /* Read command line of the PID from proc fs */
357         cmdline = (char *)read_cmdline_from_proc(pid);
358         if(cmdline == NULL)
359         {
360                 SEC_SVR_DBG("Error on reading /proc/%d/cmdline", pid);
361                 goto error;
362         }
363
364         /*
365          * modified by security part
366          *  - get gid from /etc/group
367          */
368         /* Read group info of the PID from proc fs - /proc/[PID]/status */
369         snprintf(path, sizeof(path), "/proc/%d/status", pid);
370         fp = fopen(path, "r");
371
372         /* Find the line which starts with 'Groups:' */
373         i = 0;
374         
375         while(1)
376         {
377                 buf = (char*)malloc(sizeof(char) * 128);
378                 if(buf == NULL)
379                 {
380                         SEC_SVR_DBG("%s", "Error on malloc()");
381                         goto error;
382                 }
383                 memset(buf, 0x00, 128);
384                 cnt = 128;
385
386                 /* get one line from /proc/[PID]/status */
387                 while(1)
388                 {
389                         tempint = fgetc(fp);
390                         inputed = (char)tempint;
391                         if(tempint == EOF)
392                                 goto out_of_while;
393                         else if(inputed == '\n')
394                         {
395                                 buf[i] = '\0';
396                                 break;
397                         }
398                         else if((i == cnt) && (inputed != '\n'))
399                         {
400                                 tempptr = (char*)realloc(buf, sizeof(char) * (i + 128));
401                                 if(tempptr == NULL)
402                                 {
403                                         SEC_SVR_DBG("%s", "Error on realloc()");
404                                         goto error;
405                                 }
406                                 buf = tempptr;
407                                 buf[i++] = inputed;
408                                 cnt = i + 128;
409                         }
410                         else
411                                 buf[i++] = inputed;
412                 }
413                 i = 0;
414
415                 /* find 'Groups:' */
416                 if(strncmp(buf, "Groups:", 7) == 0)
417                 {
418                         /* get gid from the line and insert to 'permissions' array */
419                         token = strtok(buf, delim); // first string is "Groups"
420                         while((token = strtok(NULL, delim)))
421                         {
422                                 tempperm = realloc(permissions, sizeof(int) * perm_num);
423                                 if(tempperm == NULL)
424                                 {
425                                         SEC_SVR_DBG("%s", "Error on realloc()");
426                                         goto error;
427                                 }
428                                 permissions = tempperm;
429                                 errno = 0;
430                                 permissions[perm_num - 1] = strtoul(token, 0, 10);
431                                 if (errno != 0)
432                                 {
433                                         SEC_SVR_DBG("cannot change string to integer [%s]", token);
434                                         ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
435                                         goto error;
436                                 }
437                                 perm_num++;
438                         }
439                         perm_num--;
440
441                         /* goto out of while loop */
442                         break;
443                 }
444                 if(buf != NULL)
445                 {
446                         free(buf);
447                         buf = NULL;
448                 }
449         }
450 out_of_while:
451                 
452         /* Each group ID is stored in each line of the file */
453 //      while(fgets(permline, sizeof(permline), fp) != NULL)
454 //      {
455 //              permissions = realloc(permissions, sizeof(int) * perm_num);
456 //              if(permissions == NULL)
457 //              {
458 //                      SEC_SVR_DBG("%s", "Error on realloc()");
459 //                      goto error;
460 //              }
461 //              permissions[perm_num -1] = strtoul(permline, 0, 10);
462 //              perm_num++;
463 //      }
464 //      perm_num--;
465         /*
466          * modifying end
467          */
468
469         /* Go to last cookie from the list */
470         current = c_list;
471         while(current->next != NULL)
472         {
473                 current = current->next;
474         }
475
476         /* Create a new one and assign values */
477         added = malloc(sizeof(cookie_list));
478         if(added == NULL)
479                 goto error;
480
481         ret = generate_random_cookie(added->cookie, SECURITY_SERVER_COOKIE_LEN);
482         if(ret != SECURITY_SERVER_SUCCESS)
483         {
484                 SEC_SVR_DBG("Error on making random cookie: %d", ret);
485                 free(added);
486                 added = NULL;
487                 goto error;
488         }
489
490 #ifdef SMACK_ENABLED
491         /* Check SMACK label */
492         ret = smack_new_label_from_socket(sockfd, &smack_label);
493         if (ret != 0)
494         {
495                 SEC_SVR_DBG("Error checking peer label: %d", ret);
496                 free(added);
497                 added = NULL;
498                 goto error;
499         }
500 #endif        
501
502         added->path_len = strlen(cmdline);
503         added->path = calloc(1, strlen(cmdline));
504         memcpy(added->path, cmdline, strlen(cmdline));
505
506         added->permission_len = perm_num;
507         added->pid = pid;
508         added->permissions = permissions;
509 #ifdef SMACK_ENABLED    
510         added->smack_label = smack_label;
511 #endif  
512         added->prev = current;
513         current->next = added;
514         added->next = NULL;
515
516 error:
517         if(cmdline != NULL)
518                 free(cmdline);
519         if(fp != NULL)
520                 fclose(fp);
521         if(buf != NULL)
522                 free(buf);
523
524         if(added == NULL && permissions != NULL)
525                 free(permissions);
526
527         return added;
528 }
529
530 /* Check stored default cookie, if it's not exist make a new one and store it */
531 int check_stored_cookie(unsigned char *cookie, int size)
532 {
533         int fd, ret;
534
535         /* First, check the default cookie is stored */
536         fd = open(SECURITY_SERVER_DEFAULT_COOKIE_PATH, O_RDONLY);
537         if(fd < 0)
538         {
539                 if(errno != ENOENT)
540                 {
541                         SEC_SVR_DBG("Cannot open default cookie. errno=%d", errno);
542                         ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
543                         unlink(SECURITY_SERVER_DEFAULT_COOKIE_PATH);
544                 }
545
546                 ret = generate_random_cookie(cookie, size);
547
548                 /* Save cookie to disk */
549                 fd = open(SECURITY_SERVER_DEFAULT_COOKIE_PATH, O_WRONLY | O_CREAT, 0600);
550                 if (fd < 0)
551                 {
552                         SEC_SVR_DBG("Cannot open default cookie errno=%d", errno);
553                         ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
554                         goto error;
555                 }
556                 ret = write(fd, cookie, size);
557                 if(ret < size)
558                 {
559                         SEC_SVR_DBG("%s", "Cannot save default cookie");
560                         ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
561                         goto error;
562                 }
563
564                 close(fd);
565                 return SECURITY_SERVER_SUCCESS;
566         }
567
568         ret = read (fd, cookie, size);
569         if(ret < size)
570         {
571                 SEC_SVR_DBG("Cannot read default cookie errno=%d", errno);
572                 ret = SECURITY_SERVER_ERROR_FILE_OPERATION;
573                 goto error;
574         }
575         ret = SECURITY_SERVER_SUCCESS;
576
577 error:
578         if(fd >= 0)
579                 close(fd);
580         return ret;
581 }
582 /* Create a cookie item from PID */
583
584 /* Create a default cookie when security server is executed *
585  * Default cookie is for root processes that needs cookie */
586 cookie_list *create_default_cookie(void)
587 {
588         cookie_list *first = NULL;
589         int ret;
590
591         first = malloc(sizeof(cookie_list));
592
593         ret = check_stored_cookie(first->cookie, SECURITY_SERVER_COOKIE_LEN);
594         if(ret != SECURITY_SERVER_SUCCESS)
595         {
596                 SEC_SVR_DBG("Error on making random cookie: %d", ret);
597                 free(first);
598                 return NULL;
599         }
600
601         first->path_len = 0;
602         first->permission_len = 0;
603         first->pid = 0;
604         first->path = NULL;
605         first->permissions = NULL;
606         first->smack_label = NULL;
607         first->prev = NULL;
608         first->next = NULL;
609         return first;
610 }