Initialize Tizen 2.3
[framework/appfw/aul-1.git] / am_daemon / amd_request.c
1 /*
2  *  aul
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 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <dirent.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <dlfcn.h>
29 #include <poll.h>
30 #include <aul.h>
31 #include <glib.h>
32 #include <bundle.h>
33 #include <rua.h>
34 #ifdef WEARABLE_PROFILE
35 #include <proc_stat.h>
36 #endif
37 #include <security-server.h>
38
39 #include "amd_config.h"
40 #include "simple_util.h"
41 #include "app_sock.h"
42 #include "aul_util.h"
43 #include "amd_request.h"
44 #include "amd_key.h"
45 #include "amd_launch.h"
46 #include "amd_appinfo.h"
47 #include "amd_cgutil.h"
48 #include "amd_status.h"
49
50
51 #define INHOUSE_UID     5000
52
53 struct appinfomgr *_raf;
54 struct cginfo *_rcg;
55
56 static int __send_result_to_client(int fd, int res);
57 static gboolean __request_handler(gpointer data);
58
59 static int __send_result_to_client(int fd, int res)
60 {
61         if (send(fd, &res, sizeof(int), MSG_NOSIGNAL) < 0) {
62                 if (errno == EPIPE)
63                         _E("send failed due to EPIPE.\n");
64                 _E("send fail to client");
65         }
66         close(fd);
67         return 0;
68 }
69
70 static void __real_send(int clifd, int ret)
71 {
72         if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
73                 if (errno == EPIPE) {
74                         _E("send failed due to EPIPE.\n");
75                 }
76                 _E("send fail to client");
77         }
78
79         close(clifd);
80 }
81
82 static int __get_caller_pid(bundle *kb)
83 {
84         const char *pid_str;
85         int pid;
86
87         pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
88         if(pid_str)
89                 goto end;
90
91         pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
92         if (pid_str == NULL)
93                 return -1;
94
95 end:
96         pid = atoi(pid_str);
97         if (pid <= 1)
98                 return -1;
99
100         return pid;
101 }
102
103 static int __foward_cmd(int cmd, bundle *kb, int cr_pid)
104 {
105         int pid;
106         int pgid;
107         char tmp_pid[MAX_PID_STR_BUFSZ];
108         int datalen;
109         bundle_raw *kb_data;
110         int res;
111
112         if ((pid = __get_caller_pid(kb)) < 0)
113                         return AUL_R_ERROR;
114
115         pgid = getpgid(cr_pid);
116         if(pgid > 0) {
117                 snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", pgid);
118                 bundle_del(kb,AUL_K_CALLEE_PID);
119                 bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
120         }
121
122         bundle_encode(kb, &kb_data, &datalen);
123         if ((res = __app_send_raw_with_noreply(pid, cmd, kb_data, datalen)) < 0)
124                 res = AUL_R_ERROR;
125
126         free(kb_data);
127
128         return res;
129 }
130
131 static int __app_process_by_pid(int cmd,
132         const char *pkg_name, struct ucred *cr, int clifd)
133 {
134         int pid;
135         int ret = -1;
136         int dummy;
137
138         if (pkg_name == NULL)
139                 return -1;
140
141         if ((cr->uid != 0) && (cr->uid != INHOUSE_UID)) {
142                 _E("reject by security rule, your uid is %u\n", cr->uid);
143                 return -1;
144         }
145
146         pid = atoi(pkg_name);
147         if (pid <= 1) {
148                 _E("invalid pid");
149                 return -1;
150         }
151 #ifdef WEARABLE_PROFILE
152         if (cmd == APP_RESUME_BY_PID)
153                 proc_group_change_status(PROC_CGROUP_SET_RESUME_REQUEST, pid, NULL);
154         else
155                 proc_group_change_status(PROC_CGROUP_SET_TERMINATE_REQUEST, pid, NULL);
156 #endif
157
158         switch (cmd) {
159         case APP_RESUME_BY_PID:
160                 ret = _resume_app(pid);
161                 __real_send(clifd, ret);
162                 break;
163         case APP_TERM_BY_PID:
164                 ret = _term_app(pid, clifd);
165                 break;
166         case APP_KILL_BY_PID:
167                 if ((ret = _send_to_sigkill(pid)) < 0)
168                         _E("fail to killing - %d\n", pid);
169                 __real_send(clifd, ret);
170                 break;
171         case APP_TERM_REQ_BY_PID:
172                 if ((ret = __app_send_raw(pid, APP_TERM_REQ_BY_PID, (unsigned char *)&dummy, sizeof(int))) < 0) {
173                         _D("terminate req packet send error");
174                 }
175                 __real_send(clifd, ret);
176         }
177
178         return ret;
179 }
180
181 static gboolean __add_history_handler(gpointer user_data)
182 {
183         struct rua_rec rec;
184         int ret;
185         bundle *kb = NULL;
186         char *appid = NULL;
187         char *app_path = NULL;
188         struct appinfo *ai;
189         app_pkt_t *pkt = (app_pkt_t *)user_data;
190
191         if (!pkt)
192                 return FALSE;
193
194         kb = bundle_decode(pkt->data, pkt->len);
195         appid = (char *)bundle_get_val(kb, AUL_K_PKG_NAME);
196
197         ai = (struct appinfo *)appinfo_find(_raf, appid);
198         app_path = (char *)appinfo_get_value(ai, AIT_EXEC);
199
200         memset((void *)&rec, 0, sizeof(rec));
201
202         rec.pkg_name = appid;
203         rec.app_path = app_path;
204
205         if(pkt->len > 0) {
206                 rec.arg = (char *)pkt->data;
207         }
208
209         SECURE_LOGD("add rua history %s %s", rec.pkg_name, rec.app_path);
210
211         ret = rua_add_history(&rec);
212         if (ret == -1)
213                 _D("rua add history error");
214
215         if (kb != NULL)
216                 bundle_free(kb);
217         free(pkt);
218
219         return FALSE;
220 }
221
222 static int __get_pid_cb(void *user_data, const char *group, pid_t pid)
223 {
224         int *sz = user_data;
225
226         _D("%s: %d : %d", *sz, pid);
227         *sz = 1; /* 1 is enough */
228
229         return -1; /* stop the iteration */
230 }
231
232 static int __releasable(const char *filename)
233 {
234         int sz;
235         int r;
236
237         if (!filename || !*filename) {
238                 _E("release service: name is empty");
239                 return -1;
240         }
241
242         r = cgutil_exist_group(_rcg, CTRL_MGR, filename);
243         if (r == -1) {
244                 SECURE_LOGE("release service: exist: %s", strerror(errno));
245                 return -1;
246         }
247         if (r == 0) {
248                 SECURE_LOGE("release service: '%s' already not exist", filename);
249                 return -1;
250         }
251
252         sz = 0;
253         r = cgutil_group_foreach_pid(_rcg, CTRL_MGR, filename,
254                         __get_pid_cb, &sz);
255         if (r == -1) {
256                 SECURE_LOGE("release service: '%s' read pid error", filename);
257                 return -1;
258         }
259         if (sz > 0) {
260                 SECURE_LOGE("release service: '%s' group has process", filename);
261                 return -1;
262         }
263
264         return 0;
265 }
266
267 int __release_srv(const char *filename)
268 {
269         int r;
270         const struct appinfo *ai;
271
272         r = __releasable(filename);
273         if (r == -1)
274                 return -1;
275
276         ai = (struct appinfo *)appinfo_find(_raf, filename);
277         if (!ai) {
278                 SECURE_LOGE("release service: '%s' not found", filename);
279                 return -1;
280         }
281
282         r = appinfo_get_boolean(ai, AIT_RESTART);
283         if (r == 1) {
284                 SECURE_LOGD("Auto restart set: '%s'", filename);
285                 return _start_srv(ai, NULL);
286         }
287
288         service_release(filename);
289
290         r = cgutil_remove_group(_rcg, CTRL_MGR, filename);
291         if (r == -1) {
292                 SECURE_LOGE("'%s' group remove error: %s", filename, strerror(errno));
293                 return -1;
294         }
295
296         return 0;
297 }
298
299 static gboolean __request_handler(gpointer data)
300 {
301         GPollFD *gpollfd = (GPollFD *) data;
302         int fd = gpollfd->fd;
303         app_pkt_t *pkt;
304         int clifd;
305         struct ucred cr;
306         int *status;
307         int ret = -1;
308         int free_pkt = 1;
309         char *appid;
310         /*char *app_path;
311         char *tmp_pid;*/
312         int pid;
313         bundle *kb = NULL;
314         const struct appinfo *ai;
315         const char *pkg_status;
316
317         if ((pkt = __app_recv_raw(fd, &clifd, &cr)) == NULL) {
318                 _E("recv error");
319                 return FALSE;
320         }
321
322         switch (pkt->cmd) {
323                 case APP_OPEN:
324                 case APP_RESUME:
325                 case APP_START:
326                 case APP_START_RES:
327                 case APP_START_ASYNC:
328                         ret = security_server_check_privilege_by_sockfd(clifd, "aul::launch", "x");
329                         if(ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) {
330                                 _E("launch request has been denied by smack");
331                                 ret = -EILLEGALACCESS;
332                                 __real_send(clifd, ret);
333                         } else {
334                                 kb = bundle_decode(pkt->data, pkt->len);
335                                 appid = (char *)bundle_get_val(kb, AUL_K_PKG_NAME);
336                                 ret = _start_app(appid, kb, pkt->cmd, cr.pid, cr.uid, clifd);
337
338                                 if(ret > 0) {
339                                         free_pkt = 0;
340                                         g_timeout_add(1000, __add_history_handler, pkt);
341                                 }
342
343                                 if (kb != NULL)
344                                         bundle_free(kb), kb = NULL;
345                         }
346                         break;
347                 case APP_RESULT:
348                 case APP_CANCEL:
349                         kb = bundle_decode(pkt->data, pkt->len);
350                         ret = __foward_cmd(pkt->cmd, kb, cr.pid);
351                         //__real_send(clifd, ret);
352                         close(clifd);
353                         break;
354                 case APP_RESUME_BY_PID:
355                 case APP_TERM_REQ_BY_PID:
356                         kb = bundle_decode(pkt->data, pkt->len);
357                         appid = (char *)bundle_get_val(kb, AUL_K_PKG_NAME);
358                         ret = __app_process_by_pid(pkt->cmd, appid, &cr, clifd);
359                         break;
360                 case APP_TERM_BY_PID:
361                 case APP_KILL_BY_PID:
362                         ret = security_server_check_privilege_by_sockfd(clifd, "aul::terminate", "x");
363                         if(ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) {
364                                 _E("terminate request has been denied by smack");
365                                 ret = -EILLEGALACCESS;
366                                 __real_send(clifd, ret);
367                         } else {
368                                 kb = bundle_decode(pkt->data, pkt->len);
369                                 appid = (char *)bundle_get_val(kb, AUL_K_PKG_NAME);
370                                 ret = __app_process_by_pid(pkt->cmd, appid, &cr, clifd);
371                         }
372                         break;
373                 case APP_RUNNING_INFO:
374                         _status_send_running_appinfo_v2(clifd);
375                         break;
376                 case APP_IS_RUNNING:
377                         appid = malloc(MAX_PACKAGE_STR_SIZE);
378                         strncpy(appid, (const char*)pkt->data, MAX_PACKAGE_STR_SIZE-1);
379                         ret = _status_app_is_running_v2(appid);
380                         SECURE_LOGD("APP_IS_RUNNING : %s : %d",appid, ret);
381                         __send_result_to_client(clifd, ret);
382                         free(appid);
383                         break;
384                 case APP_GET_APPID_BYPID:
385                         memcpy(&pid, pkt->data, pkt->len);
386                         ret = _status_get_appid_bypid(clifd, pid);
387                         _D("APP_GET_APPID_BYPID : %d : %d", pid, ret);
388                         break;
389                 case APP_KEY_RESERVE:
390                         ret = _register_key_event(cr.pid);
391                         __send_result_to_client(clifd, ret);
392                         break;
393                 case APP_KEY_RELEASE:
394                         ret = _unregister_key_event(cr.pid);
395                         __send_result_to_client(clifd, ret);
396                         break;
397                 case APP_STATUS_UPDATE:
398                         status = (int *)pkt->data;
399                         if(*status == STATUS_NORESTART) {
400                                 appid = _status_app_get_appid_bypid(cr.pid);
401                                 ai = appinfo_find(_raf, appid);
402                                 appinfo_set_value(ai, AIT_STATUS, "norestart");
403                         } else {
404                                 ret = _status_update_app_info_list(cr.pid, *status);
405                         }
406                         //__send_result_to_client(clifd, ret);
407                         close(clifd);
408                         break;
409                 case APP_RELEASED:
410                         appid = malloc(MAX_PACKAGE_STR_SIZE);
411                         strncpy(appid, (const char*)pkt->data, MAX_PACKAGE_STR_SIZE-1);
412                         ai = appinfo_find(_raf, appid);
413                         pkg_status = appinfo_get_value(ai, AIT_STATUS);
414                         _D("pkg_status : %s", pkg_status);
415                         if(pkg_status && strncmp(pkg_status, "upgrading", 9) == 0) {
416                                 appinfo_set_value(ai, AIT_STATUS, "restart");
417                         } else if (pkg_status && strncmp(pkg_status, "norestart", 9) == 0) {
418                                 appinfo_set_value(ai, AIT_STATUS, "installed");
419                         } else {
420                                 ret = __release_srv(appid);
421                         }
422                         __send_result_to_client(clifd, ret);
423                         free(appid);
424                         break;
425                 case APP_RUNNING_LIST_UPDATE:
426                         /*kb = bundle_decode(pkt->data, pkt->len);
427                           appid = (char *)bundle_get_val(kb, AUL_K_APPID);
428                           app_path = (char *)bundle_get_val(kb, AUL_K_EXEC);
429                           tmp_pid = (char *)bundle_get_val(kb, AUL_K_PID);
430                           pid = atoi(tmp_pid);
431                           ret = _status_add_app_info_list(appid, app_path, pid);*/
432                         ret = 0;
433                         __send_result_to_client(clifd, ret);
434                         break;
435                 default:
436                         _E("no support packet");
437                         close(clifd);
438         }
439
440         if (free_pkt)
441                 free(pkt);
442
443         if (kb != NULL)
444                 bundle_free(kb), kb = NULL;
445
446         return TRUE;
447 }
448
449 static gboolean __au_glib_check(GSource *src)
450 {
451         GSList *fd_list;
452         GPollFD *tmp;
453
454         fd_list = src->poll_fds;
455         do {
456                 tmp = (GPollFD *) fd_list->data;
457                 if ((tmp->revents & (POLLIN | POLLPRI)))
458                         return TRUE;
459                 fd_list = fd_list->next;
460         } while (fd_list);
461
462         return FALSE;
463 }
464
465 static gboolean __au_glib_dispatch(GSource *src, GSourceFunc callback,
466                 gpointer data)
467 {
468         callback(data);
469         return TRUE;
470 }
471
472 static gboolean __au_glib_prepare(GSource *src, gint *timeout)
473 {
474         return FALSE;
475 }
476
477 static GSourceFuncs funcs = {
478         .prepare = __au_glib_prepare,
479         .check = __au_glib_check,
480         .dispatch = __au_glib_dispatch,
481         .finalize = NULL
482 };
483
484 int _requset_init(struct amdmgr *amd)
485 {
486         int fd;
487         int r;
488         GPollFD *gpollfd;
489         GSource *src;
490
491         fd = __create_server_sock(AUL_UTIL_PID);
492         src = g_source_new(&funcs, sizeof(GSource));
493
494         gpollfd = (GPollFD *) g_malloc(sizeof(GPollFD));
495         gpollfd->events = POLLIN;
496         gpollfd->fd = fd;
497
498         g_source_add_poll(src, gpollfd);
499         g_source_set_callback(src, (GSourceFunc) __request_handler,
500                         (gpointer) gpollfd, NULL);
501         g_source_set_priority(src, G_PRIORITY_DEFAULT);
502
503         r = g_source_attach(src, NULL);
504         if (r  == 0)
505         {
506                 /* TODO: error handle*/
507                 return -1;
508         }
509
510         _raf = amd->af;
511         _rcg = amd->cg;
512
513         r = rua_init();
514         r = rua_clear_history();
515
516         _D("rua_clear_history : %d", r);
517
518         return 0;
519 }
520
521