tizen 2.3.1 release
[framework/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                                 SECURE_LOGD("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((const gchar*)pkt->data, (gsize *)&size);
166         if (ad == NULL) {
167                 _E("out of memory");
168                 free(pkt);
169                 close(clifd);
170                 return FALSE;
171         }
172
173         SECURE_LOGD("cmd : %d, pkgname : %s, pkgtype : %s", pkt->cmd, ad->pkg_name, ad->pkg_type);
174
175         switch (pkt->cmd) {
176         case AC_CHECK:
177                 _send_result_to_server(clifd, AC_R_OK);
178                 ret = __check_launch_privilege(ad->pkg_name, ad->pkg_type, ad->pid);
179                 g_free(ad);
180                 free(pkt);
181                 return TRUE;
182                 break;
183         case AC_REGISTER:
184                 ret = __register_launch_privilege(ad->pkg_name, ad->pkg_type);
185                 break;
186         case AC_UNREGISTER:
187                 ret = __unregister_launch_privilege(ad->pkg_name, ad->pkg_type);
188                 break;
189         default:
190                 _E("no support packet");
191         }
192
193         _send_result_to_server(clifd, ret);
194
195         g_free(ad);
196         free(pkt);
197         return TRUE;
198 }
199
200 static gboolean __ac_glib_check(GSource *src)
201 {
202         GSList *fd_list;
203         GPollFD *tmp;
204
205         fd_list = src->poll_fds;
206         do {
207                 tmp = (GPollFD *) fd_list->data;
208                 if ((tmp->revents & (POLLIN | POLLPRI)))
209                         return TRUE;
210                 fd_list = fd_list->next;
211         } while (fd_list);
212
213         return FALSE;
214 }
215
216 static gboolean __ac_glib_dispatch(GSource *src, GSourceFunc callback,
217                                   gpointer data)
218 {
219         callback(data);
220         return TRUE;
221 }
222
223 static gboolean __ac_glib_prepare(GSource *src, gint *timeout)
224 {
225         return FALSE;
226 }
227
228 static GSourceFuncs funcs = {
229         .prepare = __ac_glib_prepare,
230         .check = __ac_glib_check,
231         .dispatch = __ac_glib_dispatch,
232         .finalize = NULL
233 };
234
235 static void __pkt_type_list_free()
236 {
237         GSList *iter = NULL;
238         GSList *iter2 = NULL;
239         ac_type_list_t *type_t;
240         ac_so_list_t *so_t;
241
242         for (iter = pkg_type_list; iter != NULL; iter = g_slist_next(iter)) {
243                 type_t = iter->data;
244                 if(type_t) {
245                         for (iter2 = type_t->so_list; iter2 != NULL; iter2 = g_slist_next(iter2)) {
246                                 so_t = iter2->data;
247                                 if(so_t) {
248                                         if(so_t->so_name)
249                                                 free(so_t->so_name);
250                                         free(so_t);
251                                 }
252                         }
253                         g_slist_free(type_t->so_list);
254
255
256                         if(type_t->pkg_type)
257                                 free(type_t->pkg_type);
258                         free(type_t);
259                 }
260         }
261         g_slist_free(pkg_type_list);
262         return;
263 }
264
265 int __initialize()
266 {
267         int fd;
268         GPollFD *gpollfd;
269         GSource *src;
270         int ret;
271
272         _D("app checker server initialize");
273
274         fd = _create_server_sock();
275
276         src = g_source_new(&funcs, sizeof(GSource));
277
278         gpollfd = (GPollFD *) g_malloc(sizeof(GPollFD));
279         if (gpollfd == NULL) {
280                 _E("out of memory");
281                 g_source_unref(src);
282                 close(fd);
283                 return AC_R_ERROR;
284         }
285
286         gpollfd->events = POLLIN;
287         gpollfd->fd = fd;
288
289         g_source_add_poll(src, gpollfd);
290         g_source_set_callback(src, (GSourceFunc) __ac_handler,
291                               (gpointer) gpollfd, NULL);
292         g_source_set_priority(src, G_PRIORITY_DEFAULT);
293
294         ret = g_source_attach(src, NULL);
295         if (ret == 0)
296         {
297                 /* TODO: error handle*/
298                 return AC_R_ERROR;
299         }
300
301         g_source_unref(src);
302
303         DIR *dp;
304         struct dirent *dentry;
305         DIR *sub_dp = NULL;
306         struct dirent *sub_dentry;
307         char buf[MAX_LOCAL_BUFSZ];
308         char buf2[MAX_LOCAL_BUFSZ];
309         ac_type_list_t *type_t = NULL;
310         void *handle = NULL;
311         ac_so_list_t *so_t = NULL;
312
313         dp = opendir(PLUGINS_PREFIX);
314         if (dp == NULL) {
315                 return AC_R_ERROR;
316         }
317         while ((dentry = readdir(dp)) != NULL) {
318
319                 if(dentry->d_type != DT_DIR)
320                         continue;
321                 if(strcmp(dentry->d_name,".") == 0 || strcmp(dentry->d_name,"..") == 0) 
322                         continue;
323
324                 snprintf(buf,MAX_LOCAL_BUFSZ,"%s/%s",PLUGINS_PREFIX,dentry->d_name);
325                 SECURE_LOGD("type : %s", dentry->d_name);
326
327                 type_t = malloc(sizeof(ac_type_list_t));
328                 if(type_t == NULL) {
329                         __pkt_type_list_free();
330                         closedir(dp);
331                         return AC_R_ERROR;
332                 }
333                 memset(type_t, 0, sizeof(ac_type_list_t));
334                 type_t->pkg_type = strdup(dentry->d_name);
335                 type_t->so_list = NULL;
336
337                 pkg_type_list = g_slist_append(pkg_type_list, (void *)type_t);
338
339                 sub_dp = opendir(buf);
340                 if (sub_dp == NULL) {
341                         __pkt_type_list_free();
342                         closedir(dp);
343                         return AC_R_ERROR;
344                 }
345
346                 while ((sub_dentry = readdir(sub_dp)) != NULL) {
347
348                         if(sub_dentry->d_type == DT_DIR)
349                                 continue;
350                         snprintf(buf2,MAX_LOCAL_BUFSZ,"%s/%s", buf, sub_dentry->d_name);
351                         SECURE_LOGD("so_name : %s", buf2);
352
353                         handle = dlopen(buf2, RTLD_LAZY);
354                         if(handle == NULL)
355                                 continue;
356                         so_t = malloc(sizeof(ac_so_list_t));
357                         if(so_t == NULL) {
358                                 __pkt_type_list_free();
359                                 dlclose(handle);
360                                 handle = NULL;
361                                 closedir(sub_dp);
362                                 closedir(dp);
363                                 return AC_R_ERROR;
364                         }
365                         memset(so_t, 0, sizeof(ac_so_list_t));
366                         so_t->so_name = strdup(sub_dentry->d_name);
367                         so_t->ac_check = dlsym(handle, "check_launch_privilege");
368                         so_t->ac_register = dlsym(handle, "check_register_privilege");
369                         so_t->ac_unregister = dlsym(handle, "check_unregister_privilege");
370
371                         type_t->so_list = g_slist_append(type_t->so_list, (void *)so_t);
372                         handle = NULL;
373                 }
374                 closedir(sub_dp);
375         }
376         closedir(dp);
377
378         return AC_R_OK;
379 }
380
381 SLPAPI int ac_server_initialize()
382 {
383         int ret = AC_R_OK;
384
385         ret = __initialize();
386
387         return ret;
388 }
389
390 SLPAPI int ac_server_check_launch_privilege(const char *pkg_name, const char *pkg_type, int pid)
391 {
392         int ret = -1;
393         ret = __check_launch_privilege(pkg_name, pkg_type, pid);
394
395         return ret;
396 }