tizen beta release
[platform/core/appfw/app-checker.git] / src / ac_server.c
1 /*
2  *  app-checker
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@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 <stdio.h>
24 #include <glib.h>
25 #include <poll.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <dirent.h>
31 #include <stdlib.h>
32 #include <dlfcn.h>
33
34 #include <app-checker.h>
35 #include "ac_sock.h"
36 #include "internal.h"
37
38 #define PLUGINS_PREFIX "/usr/lib/ac-plugins"
39 #define MAX_LOCAL_BUFSZ         512
40
41 #ifndef SLPAPI
42 #define SLPAPI __attribute__ ((visibility("default")))
43 #endif
44
45 GSList *pkg_type_list = NULL;
46
47 typedef struct _ac_type_list_t {
48         char *pkg_type;
49         GSList *so_list;
50 } ac_type_list_t;
51
52 typedef struct _ac_so_list_t {
53         char *so_name;
54         int (*ac_check)(const char*);
55         int (*ac_register)(const char*);
56         int (*ac_unregister)(const char*);
57 } ac_so_list_t;
58
59 static int __send_to_sigkill(int pid)
60 {
61         int pgid;
62
63         pgid = getpgid(pid);
64         if (pgid <= 1)
65                 return -1;
66
67         if (killpg(pgid, SIGKILL) < 0)
68                 return -1;
69
70         return 0;
71 }
72
73 static int __check_launch_privilege(const char *pkg_name, const char *pkg_type, int pid)
74 {
75         GSList *iter = NULL;
76         GSList *iter2 = NULL;
77         ac_type_list_t *type_t;
78         ac_so_list_t *so_t;
79         
80         for (iter = pkg_type_list; iter != NULL; iter = g_slist_next(iter)) {
81                 type_t = iter->data;
82                 if (strncmp(type_t->pkg_type, pkg_type, MAX_PACKAGE_TYPE_SIZE) == 0) {
83                         for (iter2 = type_t->so_list; iter2 != NULL; iter2 = g_slist_next(iter2)) {
84                                 so_t = iter2->data;
85                                 _D("type : %s / so name : %s / func : %x", type_t->pkg_type, so_t->so_name, so_t->ac_check);
86                                 if (so_t->ac_check && so_t->ac_check(pkg_name) < 0) {
87                                         if(pid > 0)
88                                                 __send_to_sigkill(pid);                                 
89                                         return AC_R_ERROR;
90                                 }
91                         }
92                         return AC_R_OK;
93                 }                                               
94         }
95
96         return AC_R_ENOPULUGINS;
97 }
98
99 static int __register_launch_privilege(const char *pkg_name, const char *pkg_type)
100 {
101         GSList *iter = NULL;
102         GSList *iter2 = NULL;
103         ac_type_list_t *type_t;
104         ac_so_list_t *so_t;
105         int ret = AC_R_OK;
106         
107         for (iter = pkg_type_list; iter != NULL; iter = g_slist_next(iter)) {
108                 type_t = iter->data;
109                 if (strncmp(type_t->pkg_type, pkg_type, MAX_PACKAGE_TYPE_SIZE) == 0) {
110                         for (iter2 = type_t->so_list; iter2 != NULL; iter = g_slist_next(iter2)) {
111                                 so_t = iter2->data;
112                                 if (so_t->ac_register && so_t->ac_register(pkg_name) < 0) {
113                                         ret = AC_R_ERROR;
114                                 }
115                         }
116                         return ret;
117                 }                                               
118         }
119
120         return AC_R_ENOPULUGINS;
121
122 }
123
124 static int __unregister_launch_privilege(const char *pkg_name, const char *pkg_type)
125 {
126         GSList *iter = NULL;
127         GSList *iter2 = NULL;
128         ac_type_list_t *type_t;
129         ac_so_list_t *so_t;
130         int ret = AC_R_OK;
131         
132         for (iter = pkg_type_list; iter != NULL; iter = g_slist_next(iter)) {
133                 type_t = iter->data;
134                 if (strncmp(type_t->pkg_type, pkg_type, MAX_PACKAGE_TYPE_SIZE) == 0) {
135                         for (iter2 = type_t->so_list; iter2 != NULL; iter = g_slist_next(iter2)) {
136                                 so_t = iter2->data;
137                                 if (so_t->ac_unregister && so_t->ac_unregister(pkg_name) < 0) {
138                                         ret = AC_R_ERROR;
139                                 }
140                         }
141                         return ret;
142                 }                                               
143         }
144
145         return AC_R_ENOPULUGINS;;
146
147 }
148
149 static gboolean __ac_handler(gpointer data)
150 {
151         GPollFD *gpollfd = (GPollFD *) data;
152         int fd = gpollfd->fd;
153         ac_pkt_t *pkt;
154         int clifd;
155         struct ucred cr;
156         struct ac_data *ad;
157         int ret = -1;
158         int size;
159
160         if ((pkt = _app_recv_raw(fd, &clifd, &cr)) == NULL) {
161                 _E("recv error");
162                 return FALSE;
163         }
164
165         ad = (struct ac_data *)g_base64_decode(pkt->data, &size);
166
167         _D("cmd : %d, pkgname : %s, pkgtype : %s", pkt->cmd, ad->pkg_name, ad->pkg_type);
168
169         switch (pkt->cmd) {
170         case AC_CHECK:
171                 _send_result_to_server(clifd, AC_R_OK);
172                 ret = __check_launch_privilege(ad->pkg_name, ad->pkg_type, ad->pid);
173                 g_free(ad); 
174                 free(pkt);
175                 return TRUE;
176                 break;
177         case AC_REGISTER:
178                 ret = __register_launch_privilege(ad->pkg_name, ad->pkg_type);
179                 break;          
180         case AC_UNREGISTER:
181                 ret = __unregister_launch_privilege(ad->pkg_name, ad->pkg_type);
182                 break;          
183         default:
184                 _E("no support packet");
185         }
186
187         _send_result_to_server(clifd, ret);
188         
189         g_free(ad);
190         free(pkt);
191         return TRUE;
192 }
193
194 static gboolean __ac_glib_check(GSource *src)
195 {
196         GSList *fd_list;
197         GPollFD *tmp;
198
199         fd_list = src->poll_fds;
200         do {
201                 tmp = (GPollFD *) fd_list->data;
202                 if ((tmp->revents & (POLLIN | POLLPRI)))
203                         return TRUE;
204                 fd_list = fd_list->next;
205         } while (fd_list);
206
207         return FALSE;
208 }
209
210 static gboolean __ac_glib_dispatch(GSource *src, GSourceFunc callback,
211                                   gpointer data)
212 {
213         callback(data);
214         return TRUE;
215 }
216
217 static gboolean __ac_glib_prepare(GSource *src, gint *timeout)
218 {
219         return FALSE;
220 }
221
222 static GSourceFuncs funcs = {
223         .prepare = __ac_glib_prepare,
224         .check = __ac_glib_check,
225         .dispatch = __ac_glib_dispatch,
226         .finalize = NULL
227 };
228
229 static void __pkt_type_list_free()
230 {
231         GSList *iter = NULL;
232         GSList *iter2 = NULL;
233         ac_type_list_t *type_t;
234         ac_so_list_t *so_t;
235         
236         for (iter = pkg_type_list; iter != NULL; iter = g_slist_next(iter)) {
237                 type_t = iter->data;
238                 if(type_t) {
239                         for (iter2 = type_t->so_list; iter2 != NULL; iter2 = g_slist_next(iter2)) {
240                                 so_t = iter2->data;
241                                 if(so_t) {
242                                         if(so_t->so_name)
243                                                 free(so_t->so_name);
244                                         free(so_t);
245                                 }
246                         }
247                         g_slist_free(type_t->so_list);
248                 
249                 
250                         if(type_t->pkg_type)
251                                 free(type_t->pkg_type);
252                         free(type_t);
253                 }
254         }
255         g_slist_free(pkg_type_list);
256         return;
257 }
258
259 int __initialize()
260 {
261         int fd;
262         GPollFD *gpollfd;
263         GSource *src;
264         int ret;
265
266         _D("app checker server initialize");
267
268         fd = _create_server_sock();
269
270         src = g_source_new(&funcs, sizeof(GSource));
271
272         gpollfd = (GPollFD *) g_malloc(sizeof(GPollFD));
273         gpollfd->events = POLLIN;
274         gpollfd->fd = fd;
275
276         g_source_add_poll(src, gpollfd);
277         g_source_set_callback(src, (GSourceFunc) __ac_handler,
278                               (gpointer) gpollfd, NULL);
279         g_source_set_priority(src, G_PRIORITY_DEFAULT);
280
281         ret = g_source_attach(src, NULL);
282         if (ret == 0)
283         {
284                 /* TODO: error handle*/
285                 return AC_R_ERROR;
286         }
287
288         g_source_unref(src);
289
290         DIR *dp;
291         struct dirent *dentry;
292         DIR *sub_dp;
293         struct dirent *sub_dentry;
294         char buf[MAX_LOCAL_BUFSZ];
295         char buf2[MAX_LOCAL_BUFSZ];
296         ac_type_list_t *type_t = NULL;
297         void *handle = NULL;
298         ac_so_list_t *so_t = NULL;
299         
300         dp = opendir(PLUGINS_PREFIX);
301         if (dp == NULL) {
302                 return AC_R_ERROR;
303         }
304         while ((dentry = readdir(dp)) != NULL) {
305                 
306                 if(dentry->d_type != DT_DIR) 
307                         continue;
308                 if(strcmp(dentry->d_name,".") == 0 || strcmp(dentry->d_name,"..") == 0) 
309                         continue;
310                 
311                 snprintf(buf,MAX_LOCAL_BUFSZ,"%s/%s",PLUGINS_PREFIX,dentry->d_name);
312                 _D("type : %s", dentry->d_name);
313
314                 type_t = malloc(sizeof(ac_type_list_t));
315                 if(type_t == NULL) {
316                         __pkt_type_list_free();
317                         return AC_R_ERROR;
318                 }
319                 memset(type_t, 0, sizeof(ac_type_list_t));
320                 type_t->pkg_type = strdup(dentry->d_name);
321                 type_t->so_list = NULL;
322
323                 pkg_type_list = g_slist_append(pkg_type_list, (void *)type_t);
324                 
325                 sub_dp = opendir(buf);
326                 
327                 while ((sub_dentry = readdir(sub_dp)) != NULL) {
328                         
329                         if(sub_dentry->d_type == DT_DIR) 
330                                 continue;
331                         snprintf(buf2,MAX_LOCAL_BUFSZ,"%s/%s", buf, sub_dentry->d_name);
332                         _D("so_name : %s", buf2);
333                         
334                         handle = dlopen(buf2, RTLD_LAZY);
335                         if(handle == NULL) 
336                                 continue;
337                         so_t = malloc(sizeof(ac_so_list_t));
338                         if(so_t == NULL) {
339                                 __pkt_type_list_free();
340                                 return AC_R_ERROR;
341                         }
342                         memset(type_t, 0, sizeof(ac_so_list_t));
343                         so_t->so_name = strdup(sub_dentry->d_name);
344                         so_t->ac_check = dlsym(handle, "check_launch_privilege");
345                         so_t->ac_register = dlsym(handle, "check_register_privilege");
346                         so_t->ac_unregister = dlsym(handle, "check_unregister_privilege");
347
348                         type_t->so_list = g_slist_append(type_t->so_list, (void *)so_t);
349                         handle = NULL;
350                 }
351         }
352
353         return AC_R_OK;
354 }
355
356 SLPAPI int ac_server_initailize()
357 {
358         int ret = AC_R_OK;
359         
360         ret = __initialize();
361         
362         return ret;
363 }
364