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