Check privilege via dbus-daemon
[platform/core/appfw/slp-pkgmgr.git] / server / src / request.c
1 #include <sys/types.h>
2
3 #include <glib.h>
4 #include <gio/gio.h>
5
6 #include "comm_config.h"
7 #include "pm-queue.h"
8 #include "pkgmgr-server.h"
9 #include "package-manager-debug.h"
10
11 static const char instropection_xml[] =
12         "<node>"
13         "  <interface name='org.tizen.pkgmgr'>"
14         "    <method name='install'>"
15         "      <arg type='s' name='reqid' direction='in'/>"
16         "      <arg type='s' name='pkgtype' direction='in'/>"
17         "      <arg type='s' name='pkgpath' direction='in'/>"
18         "      <arg type='s' name='args' direction='in'/>"
19         "      <arg type='i' name='ret' direction='out'/>"
20         "    </method>"
21         "    <method name='reinstall'>"
22         "      <arg type='s' name='reqid' direction='in'/>"
23         "      <arg type='s' name='pkgtype' direction='in'/>"
24         "      <arg type='s' name='pkgid' direction='in'/>"
25         "      <arg type='s' name='args' direction='in'/>"
26         "      <arg type='i' name='ret' direction='out'/>"
27         "    </method>"
28         "    <method name='uninstall'>"
29         "      <arg type='s' name='reqid' direction='in'/>"
30         "      <arg type='s' name='pkgtype' direction='in'/>"
31         "      <arg type='s' name='pkgid' direction='in'/>"
32         "      <arg type='s' name='args' direction='in'/>"
33         "      <arg type='i' name='ret' direction='out'/>"
34         "    </method>"
35         "    <method name='cleardata'>"
36         "      <arg type='s' name='reqid' direction='in'/>"
37         "      <arg type='s' name='pkgtype' direction='in'/>"
38         "      <arg type='s' name='pkgid' direction='in'/>"
39         "      <arg type='s' name='args' direction='in'/>"
40         "      <arg type='i' name='ret' direction='out'/>"
41         "    </method>"
42         "    <method name='move'>"
43         "      <arg type='s' name='reqid' direction='in'/>"
44         "      <arg type='s' name='pkgtype' direction='in'/>"
45         "      <arg type='s' name='pkgid' direction='in'/>"
46         "      <arg type='s' name='args' direction='in'/>"
47         "      <arg type='i' name='ret' direction='out'/>"
48         "    </method>"
49         "    <method name='activate'>"
50         "      <arg type='s' name='reqid' direction='in'/>"
51         "      <arg type='s' name='pkgtype' direction='in'/>"
52         "      <arg type='s' name='pkgid' direction='in'/>"
53         "      <arg type='s' name='args' direction='in'/>"
54         "      <arg type='i' name='ret' direction='out'/>"
55         "    </method>"
56         "    <method name='deactivate'>"
57         "      <arg type='s' name='reqid' direction='in'/>"
58         "      <arg type='s' name='pkgtype' direction='in'/>"
59         "      <arg type='s' name='pkgid' direction='in'/>"
60         "      <arg type='s' name='args' direction='in'/>"
61         "      <arg type='i' name='ret' direction='out'/>"
62         "    </method>"
63         "    <method name='getsize'>"
64         "      <arg type='s' name='reqid' direction='in'/>"
65         "      <arg type='s' name='pkgtype' direction='in'/>"
66         "      <arg type='s' name='pkgid' direction='in'/>"
67         "      <arg type='s' name='args' direction='in'/>"
68         "      <arg type='i' name='ret' direction='out'/>"
69         "    </method>"
70         "    <method name='clearcache'>"
71         "      <arg type='s' name='reqid' direction='in'/>"
72         "      <arg type='s' name='pkgtype' direction='in'/>"
73         "      <arg type='s' name='pkgid' direction='in'/>"
74         "      <arg type='i' name='ret' direction='out'/>"
75         "    </method>"
76         "    <method name='kill'>"
77         "      <arg type='s' name='reqid' direction='in'/>"
78         "      <arg type='s' name='pkgtype' direction='in'/>"
79         "      <arg type='s' name='pkgid' direction='in'/>"
80         "      <arg type='i' name='ret' direction='out'/>"
81         "    </method>"
82         "    <method name='check'>"
83         "      <arg type='s' name='reqid' direction='in'/>"
84         "      <arg type='s' name='pkgtype' direction='in'/>"
85         "      <arg type='s' name='pkgid' direction='in'/>"
86         "      <arg type='i' name='ret' direction='out'/>"
87         "    </method>"
88         "  </interface>"
89         "</node>";
90 static GDBusNodeInfo *instropection_data;
91 static guint reg_id;
92 static guint owner_id;
93
94 static int __handle_request_install(uid_t uid, GVariant *parameters)
95 {
96         gchar *reqid;
97         gchar *pkgtype;
98         gchar *pkgpath;
99         gchar *args;
100         pm_dbus_msg *item;
101
102         g_variant_get(parameters, "(&s&s&s&s)", &reqid, &pkgtype, &pkgpath,
103                         &args);
104
105         item = _pm_queue_create_item(uid, reqid, COMM_REQ_TO_INSTALLER,
106                         pkgtype, pkgpath, args);
107         if (item == NULL)
108                 return -1;
109
110         if (_pm_queue_push(item))
111                 return -1;
112
113         return 0;
114 }
115
116 static int __handle_request_reinstall(uid_t uid, GVariant *parameters)
117 {
118         gchar *reqid;
119         gchar *pkgtype;
120         gchar *pkgid;
121         gchar *args;
122         pm_dbus_msg *item;
123
124         g_variant_get(parameters, "(&s&s&s&s)", &reqid, &pkgtype, &pkgid,
125                         &args);
126
127         item = _pm_queue_create_item(uid, reqid, COMM_REQ_TO_INSTALLER,
128                         pkgtype, pkgid, args);
129         if (item == NULL)
130                 return -1;
131
132         if (_pm_queue_push(item))
133                 return -1;
134
135         return 0;
136 }
137
138 static int __handle_request_uninstall(uid_t uid, GVariant *parameters)
139 {
140         gchar *reqid;
141         gchar *pkgtype;
142         gchar *pkgid;
143         gchar *args;
144         pm_dbus_msg *item;
145
146         g_variant_get(parameters, "(&s&s&s&s)", &reqid, &pkgtype, &pkgid,
147                         &args);
148
149         item = _pm_queue_create_item(uid, reqid, COMM_REQ_TO_INSTALLER,
150                         pkgtype, pkgid, args);
151         if (item == NULL)
152                 return -1;
153
154         if (_pm_queue_push(item))
155                 return -1;
156
157         return 0;
158 }
159
160 static int __handle_request_cleardata(uid_t uid, GVariant *parameters)
161 {
162         gchar *reqid;
163         gchar *pkgtype;
164         gchar *pkgid;
165         gchar *args;
166         pm_dbus_msg *item;
167
168         g_variant_get(parameters, "(&s&s&s&s)", &reqid, &pkgtype, &pkgid,
169                         &args);
170
171         item = _pm_queue_create_item(uid, reqid, COMM_REQ_TO_CLEARER,
172                         pkgtype, pkgid, args);
173         if (item == NULL)
174                 return -1;
175
176         if (_pm_queue_push(item))
177                 return -1;
178
179         return 0;
180 }
181
182 static int __handle_request_move(uid_t uid, GVariant *parameters)
183 {
184         gchar *reqid;
185         gchar *pkgtype;
186         gchar *pkgid;
187         gchar *args;
188         pm_dbus_msg *item;
189
190         g_variant_get(parameters, "(&s&s&s&s)", &reqid, &pkgtype, &pkgid,
191                         &args);
192
193         item = _pm_queue_create_item(uid, reqid, COMM_REQ_TO_MOVER,
194                         pkgtype, pkgid, args);
195         if (item == NULL)
196                 return -1;
197
198         if (_pm_queue_push(item))
199                 return -1;
200
201         return 0;
202 }
203
204 static int __handle_request_activate(uid_t uid, GVariant *parameters)
205 {
206         gchar *reqid;
207         gchar *pkgtype;
208         gchar *pkgid;
209         gchar *args;
210         pm_dbus_msg *item;
211
212         g_variant_get(parameters, "(&s&s&s&s)", &reqid, &pkgtype, &pkgid,
213                         &args);
214
215         item = _pm_queue_create_item(uid, reqid, COMM_REQ_TO_ACTIVATOR,
216                         pkgtype, pkgid, args);
217         if (item == NULL)
218                 return -1;
219
220         if (_pm_queue_push(item))
221                 return -1;
222
223         return 0;
224 }
225
226 static int __handle_request_deactivate(uid_t uid, GVariant *parameters)
227 {
228         gchar *reqid;
229         gchar *pkgtype;
230         gchar *pkgid;
231         gchar *args;
232         pm_dbus_msg *item;
233
234         g_variant_get(parameters, "(&s&s&s&s)", &reqid, &pkgtype, &pkgid,
235                         &args);
236
237         item = _pm_queue_create_item(uid, reqid, COMM_REQ_TO_ACTIVATOR,
238                         pkgtype, pkgid, args);
239         if (item == NULL)
240                 return -1;
241
242         if (_pm_queue_push(item))
243                 return -1;
244
245         return 0;
246 }
247
248 static int __handle_request_getsize(uid_t uid, GVariant *parameters)
249 {
250         gchar *reqid;
251         gchar *pkgtype;
252         gchar *pkgid;
253         gchar *args;
254         pm_dbus_msg *item;
255
256         g_variant_get(parameters, "(&s&s&s&s)", &reqid, &pkgtype, &pkgid,
257                         &args);
258
259         item = _pm_queue_create_item(uid, reqid, COMM_REQ_GET_SIZE,
260                         pkgtype, pkgid, args);
261         if (item == NULL)
262                 return -1;
263
264         if (_pm_queue_push(item))
265                 return -1;
266
267         return 0;
268 }
269
270 static int __handle_request_clearcache(uid_t uid, GVariant *parameters)
271 {
272         gchar *reqid;
273         gchar *pkgtype;
274         gchar *pkgid;
275         pm_dbus_msg *item;
276
277         g_variant_get(parameters, "(&s&s&s)", &reqid, &pkgtype, &pkgid);
278
279         item = _pm_queue_create_item(uid, reqid, COMM_REQ_CLEAR_CACHE_DIR,
280                         pkgtype, pkgid, NULL);
281         if (item == NULL)
282                 return -1;
283
284         if (_pm_queue_push(item))
285                 return -1;
286
287         return 0;
288 }
289
290 static int __handle_request_kill(uid_t uid, GVariant *parameters)
291 {
292         gchar *reqid;
293         gchar *pkgtype;
294         gchar *pkgid;
295         pm_dbus_msg *item;
296
297         g_variant_get(parameters, "(&s&s&s)", &reqid, &pkgtype, &pkgid);
298
299         item = _pm_queue_create_item(uid, reqid, COMM_REQ_KILL_APP,
300                         pkgtype, pkgid, NULL);
301         if (item == NULL)
302                 return -1;
303
304         if (_pm_queue_push(item))
305                 return -1;
306
307         return 0;
308 }
309
310 static int __handle_request_check(uid_t uid, GVariant *parameters)
311 {
312         gchar *reqid;
313         gchar *pkgtype;
314         gchar *pkgid;
315         pm_dbus_msg *item;
316
317         g_variant_get(parameters, "(&s&s&s)", &reqid, &pkgtype, &pkgid);
318
319         item = _pm_queue_create_item(uid, reqid, COMM_REQ_CHECK_APP,
320                         pkgtype, pkgid, NULL);
321         if (item == NULL)
322                 return -1;
323
324         if (_pm_queue_push(item))
325                 return -1;
326
327         return 0;
328 }
329
330 static uid_t __get_caller_uid(GDBusConnection *connection, const char *name)
331 {
332         GError *err = NULL;
333         GVariant *result;
334         uid_t uid;
335
336         result = g_dbus_connection_call_sync(connection,
337                         "org.freedesktop.DBus", "/org/freedesktop/DBus",
338                         "org.freedesktop.DBus", "GetConnectionUnixUser",
339                         g_variant_new("(s)", name), NULL,
340                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
341         if (result == NULL) {
342                 ERR("failed to get caller uid: %s", err->message);
343                 g_error_free(err);
344                 return (uid_t)-1;
345         }
346
347         g_variant_get(result, "(u)", &uid);
348
349         return uid;
350 }
351
352 static void __handle_method_call(GDBusConnection *connection,
353                 const gchar *sender, const gchar *object_path,
354                 const gchar *interface_name, const gchar *method_name,
355                 GVariant *parameters, GDBusMethodInvocation *invocation,
356                 gpointer user_data)
357 {
358         int ret;
359         uid_t uid;
360
361         uid = __get_caller_uid(connection,
362                 g_dbus_method_invocation_get_sender(invocation));
363         if (uid == (uid_t)-1)
364                 return;
365
366         if (g_strcmp0(method_name, "install") == 0)
367                 ret = __handle_request_install(uid, parameters);
368         else if (g_strcmp0(method_name, "reinstall") == 0)
369                 ret = __handle_request_reinstall(uid, parameters);
370         else if (g_strcmp0(method_name, "uninstall") == 0)
371                 ret = __handle_request_uninstall(uid, parameters);
372         else if (g_strcmp0(method_name, "cleardata") == 0)
373                 ret = __handle_request_cleardata(uid, parameters);
374         else if (g_strcmp0(method_name, "move") == 0)
375                 ret = __handle_request_move(uid, parameters);
376         else if (g_strcmp0(method_name, "activate") == 0)
377                 ret = __handle_request_activate(uid, parameters);
378         else if (g_strcmp0(method_name, "deactivate") == 0)
379                 ret = __handle_request_deactivate(uid, parameters);
380         else if (g_strcmp0(method_name, "getsize") == 0)
381                 ret = __handle_request_getsize(uid, parameters);
382         else if (g_strcmp0(method_name, "clearcache") == 0)
383                 ret = __handle_request_clearcache(uid, parameters);
384         else if (g_strcmp0(method_name, "kill") == 0)
385                 ret = __handle_request_kill(uid, parameters);
386         else if (g_strcmp0(method_name, "check") == 0)
387                 ret = __handle_request_check(uid, parameters);
388         else
389                 ret = -1;
390
391         g_dbus_method_invocation_return_value(invocation,
392                         g_variant_new("(i)", ret));
393
394         if (ret == 0)
395                 g_idle_add(queue_job, NULL);
396 }
397
398 static const GDBusInterfaceVTable interface_vtable =
399 {
400         __handle_method_call,
401         NULL,
402         NULL,
403 };
404
405 static void __on_bus_acquired(GDBusConnection *connection, const gchar *name,
406                 gpointer user_data)
407 {
408
409         DBG("on bus acquired");
410
411         reg_id = g_dbus_connection_register_object(connection,
412                         COMM_PKGMGR_DBUS_OBJECT_PATH,
413                         instropection_data->interfaces[0],
414                         &interface_vtable, NULL, NULL, NULL);
415
416         if (reg_id < 0)
417                 ERR("failed to register object");
418 }
419
420 static void __on_name_acquired(GDBusConnection *connection, const gchar *name,
421                 gpointer user_data)
422 {
423         DBG("on name acquired: %s", name);
424 }
425
426 static void __on_name_lost(GDBusConnection *connection, const gchar *name,
427                 gpointer user_data)
428 {
429         DBG("on name lost: %s", name);
430 }
431
432 int __init_request_handler(void)
433 {
434         instropection_data = g_dbus_node_info_new_for_xml(instropection_xml, NULL);
435
436         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, COMM_PKGMGR_DBUS_SERVICE,
437                         G_BUS_NAME_OWNER_FLAGS_NONE, __on_bus_acquired,
438                         __on_name_acquired, __on_name_lost, NULL, NULL);
439
440         return 0;
441 }
442
443 void __fini_request_handler(void)
444 {
445         g_bus_unown_name(owner_id);
446         g_dbus_node_info_unref(instropection_data);
447 }