Support launch_on_event with user event 26/198326/6
authorInkyun Kil <inkyun.kil@samsung.com>
Thu, 24 Jan 2019 00:08:16 +0000 (09:08 +0900)
committerjusung son <jusung07.son@samsung.com>
Fri, 25 Jan 2019 06:28:33 +0000 (15:28 +0900)
Change-Id: I809ca8ec8727c4ad40f81db6002f55d73af4613c
Signed-off-by: Inkyun Kil <inkyun.kil@samsung.com>
Signed-off-by: jusung son <jusung07.son@samsung.com>
CMakeLists.txt
packaging/esd.spec
src/esd_main.c

index 3936be4..ef58439 100644 (file)
@@ -19,7 +19,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src)
 ### Required packages
 INCLUDE(FindPkgConfig)
 
-pkg_check_modules(pkgs REQUIRED dlog bundle pkgmgr-info glib-2.0 gio-2.0 appsvc aul vconf libtzplatform-config libsystemd-daemon cynara-client cynara-creds-gdbus cynara-session security-manager)
+pkg_check_modules(pkgs REQUIRED dlog bundle pkgmgr-info glib-2.0 gio-2.0 appsvc aul vconf libtzplatform-config libsystemd-daemon cert-svc-vcore cynara-client cynara-creds-gdbus cynara-session security-manager)
 
 FOREACH(flag ${pkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
index 873477a..95ed77a 100644 (file)
@@ -19,6 +19,7 @@ BuildRequires:  pkgconfig(eventsystem)
 BuildRequires:  pkgconfig(vconf)
 BuildRequires:  pkgconfig(libtzplatform-config)
 BuildRequires:  pkgconfig(libsystemd-daemon)
+BuildRequires:  pkgconfig(cert-svc-vcore)
 BuildRequires:  pkgconfig(cynara-client)
 BuildRequires:  pkgconfig(cynara-creds-gdbus)
 BuildRequires:  pkgconfig(cynara-session)
index d0b58dc..4826b08 100644 (file)
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <glib.h>
 #include <aul.h>
+#include <aul_svc.h>
 #include <unistd.h>
 #include <ctype.h>
 #include <dlog.h>
@@ -15,6 +16,8 @@
 #include <vconf.h>
 #include <tzplatform_config.h>
 #include <systemd/sd-login.h>
+#include <cert-svc/ccert.h>
+#include <cert-svc/cinstance.h>
 #include <cynara-client.h>
 #include <cynara-creds-gdbus.h>
 #include <cynara-session.h>
@@ -96,9 +99,16 @@ typedef struct __eventlaunch_item_param {
        char *app_id;
 } eventlaunch_item_param_s;
 
+enum trusted_result {
+       TRUSTED_UNKNOWN,
+       TRUSTED_ALLOWED,
+       TRUSTED_DENIED,
+};
+
 typedef struct esd_list_item {
        char *pkg_id;
        char *app_id;
+       int trusted_info;
        uid_t uid;
 } esd_list_item_s;
 
@@ -125,6 +135,10 @@ typedef struct __pkgmgr_event {
 typedef struct __esd_event_param {
        char *event_name;
        bundle *event_data;
+       uid_t sender_uid;
+       char *sender_appid;
+       bool is_user_event;
+       bool trusted;
        void *user_data;
 } esd_event_param;
 
@@ -190,6 +204,74 @@ static int __esd_check_earlier_support(const char *event_name)
 }
 #endif
 
+static bool __esd_check_platform_cert(const char *pkgid, uid_t uid)
+{
+       _D("Checking if %s has a platform certification", pkgid);
+
+       int r;
+       const char *cert_value;
+       pkgmgrinfo_certinfo_h certinfo;
+       CertSvcInstance instance;
+       CertSvcCertificate certificate;
+       CertSvcVisibility visibility = CERTSVC_VISIBILITY_PUBLIC;
+
+       r = pkgmgrinfo_pkginfo_create_certinfo(&certinfo);
+       if (r != PMINFO_R_OK) {
+               _E("Failed to create certinfo");
+               return false;
+       }
+
+       r = pkgmgrinfo_pkginfo_load_certinfo(pkgid, certinfo, uid);
+       if (r != PMINFO_R_OK) {
+               _E("Failed to load certinfo");
+               pkgmgrinfo_pkginfo_destroy_certinfo(certinfo);
+               return false;
+       }
+
+       r = pkgmgrinfo_pkginfo_get_cert_value(certinfo,
+                       PMINFO_DISTRIBUTOR_ROOT_CERT, &cert_value);
+       if (r != PMINFO_R_OK || cert_value == NULL) {
+               _E("Failed to get cert value");
+               pkgmgrinfo_pkginfo_destroy_certinfo(certinfo);
+               return false;
+       }
+
+       r = certsvc_instance_new(&instance);
+       if (r != CERTSVC_SUCCESS) {
+               _E("certsvc_instance_new() is failed.");
+               pkgmgrinfo_pkginfo_destroy_certinfo(certinfo);
+               return false;
+       }
+
+       r = certsvc_certificate_new_from_memory(instance,
+                       (const unsigned char *)cert_value,
+                       strlen(cert_value),
+                       CERTSVC_FORM_DER_BASE64,
+                       &certificate);
+       if (r != CERTSVC_SUCCESS) {
+               _E("certsvc_certificate_new_from_memory() is failed.");
+               pkgmgrinfo_pkginfo_destroy_certinfo(certinfo);
+               certsvc_instance_free(instance);
+               return false;
+       }
+
+       r = certsvc_certificate_get_visibility(certificate, &visibility);
+       if (r != CERTSVC_SUCCESS)
+               _E("certsvc_certificate_get_visibility() is failed.");
+
+       pkgmgrinfo_pkginfo_destroy_certinfo(certinfo);
+       certsvc_instance_free(instance);
+       certsvc_certificate_free(certificate);
+
+       _D("visibility is %d", visibility);
+       if (visibility & CERTSVC_VISIBILITY_PLATFORM) {
+               _D("%s has a platform certification", pkgid);
+               return true;
+       }
+
+       return false;
+}
+
 static int __esd_check_event_launch_support(const char *event_name)
 {
        int i = 0;
@@ -544,13 +626,15 @@ static int __esd_add_list_item(uid_t uid, event_launch_item *el_item,
        item_of_list->uid = uid;
        item_of_list->app_id = (char *)app_id;
        item_of_list->pkg_id = (char *)pkg_id;
+       item_of_list->trusted_info = TRUSTED_UNKNOWN;
        el_item->app_list_evtlaunch =
                g_list_append(el_item->app_list_evtlaunch, item_of_list);
 
        return ES_R_OK;
 }
 
-static int __esd_add_launch_item(uid_t uid, const char *event_name, const char *appid, const char *pkgid)
+static int __esd_add_launch_item(uid_t uid, const char *event_name,
+               const char *appid, const char *pkgid)
 {
        GList *app_list = NULL;
        guint subscription_id = 0;
@@ -752,18 +836,39 @@ static void __esd_event_launch_with_appid(gpointer data, gpointer user_data)
        int pid;
        char event_uri[1024];
        bundle *b;
+       int ret;
+
+       _D("launch_on_event: app_id(%s), event_name(%s), uid(%d), is_user(%d), trusted(%d)",
+                       app_id, eep->event_name, uid, eep->is_user_event, eep->trusted);
 
-       _D("launch_on_event: app_id(%s), event_name(%s), uid(%d)",
-                       app_id, eep->event_name, uid);
+       if (eep->is_user_event && eep->trusted) {
+               if (item->trusted_info == TRUSTED_UNKNOWN) {
+                       ret = __esd_check_certificate_match(uid, app_id, eep->sender_uid, eep->sender_appid);
+                       if (ret == ES_R_EINVAL) {
+                               item->trusted_info = TRUSTED_DENIED;
+                               return;
+                       } else if (ret == ES_R_ERROR) {
+                               return;
+                       } else {
+                               item->trusted_info = TRUSTED_ALLOWED;
+                       }
+               } else if (item->trusted_info == TRUSTED_DENIED) {
+                       return;
+               }
+       }
 
        if (!aul_app_is_running_for_uid(app_id, uid)) {
-               snprintf(event_uri, sizeof(event_uri), "event://%s", eep->event_name);
                b = bundle_dup(eep->event_data);
+               if (eep->is_user_event)
+                       snprintf(event_uri, sizeof(event_uri), "%s%s", USER_EVENT_NAME_PREFIX, eep->event_name);
+               else
+                       snprintf(event_uri, sizeof(event_uri), "%s%s", SYSTEM_EVENT_NAME_PREFIX, eep->event_name);
+
                appsvc_set_operation(b, APPSVC_OPERATION_LAUNCH_ON_EVENT);
                appsvc_set_uri(b, event_uri);
                appsvc_set_appid(b, app_id);
 
-               pid = appsvc_usr_run_service(b, req_id++, NULL, eep->user_data, uid);
+               pid = aul_svc_run_service_async_for_uid(b, req_id++, NULL, eep->user_data, uid);
                _D("uid(%d), pid(%d)", uid, pid);
 
                bundle_free(b);
@@ -783,7 +888,9 @@ static void __esd_check_event_launch_with_eventid(gpointer data, gpointer user_d
        }
 }
 
-static void __esd_launch_event_handler(char *event_name, bundle *data, void *user_data)
+static void __esd_launch_event_handler(char *event_name, bundle *data,
+               const bool is_user_event, const bool trusted,
+               const uid_t sender_uid, char *sender_appid, void *user_data)
 {
        const char *val;
        const char *msg_type;
@@ -798,38 +905,40 @@ static void __esd_launch_event_handler(char *event_name, bundle *data, void *use
                return;
 
        if (el_item->app_list_evtlaunch != NULL) {
-               if (strcmp(SYS_EVENT_BATTERY_CHARGER_STATUS, event_name) == 0) {
-                       val = bundle_get_val(data, EVT_KEY_BATTERY_CHARGER_STATUS);
-                       _D("charger val(%s)", val);
-                       if (val && (strcmp(EVT_VAL_BATTERY_CHARGER_CONNECTED, val) != 0))
-                               return;
-               } else if (strcmp(SYS_EVENT_USB_STATUS, event_name) == 0) {
-                       val = bundle_get_val(data, EVT_KEY_USB_STATUS);
-                       _D("usb val(%s)", val);
-                       if (val && (strcmp(EVT_VAL_USB_CONNECTED, val) != 0))
-                               return;
-               } else if (strcmp(SYS_EVENT_EARJACK_STATUS, event_name) == 0) {
-                       val = bundle_get_val(data, EVT_KEY_EARJACK_STATUS);
-                       _D("earjack val(%s)", val);
-                       if (val && (strcmp(EVT_VAL_EARJACK_CONNECTED, val) != 0))
-                               return;
-               } else if (strcmp(SYS_EVENT_INCOMMING_MSG, event_name) == 0) {
-                       msg_type = bundle_get_val(data, EVT_KEY_MSG_TYPE);
-                       _D("msg_type(%s)", msg_type);
-                       if (msg_type == NULL)
-                               return;
-
-                       msg_id = bundle_get_val(data, EVT_KEY_MSG_ID);
-                       _D("msg_id(%s)", msg_id);
-                       if (msg_id == NULL)
-                               return;
-               } else if (strcmp(SYS_EVENT_WIFI_STATE, event_name) == 0) {
-                       val = bundle_get_val(data, EVT_KEY_WIFI_STATE);
-                       if (val == NULL)
-                               return;
-                       _D("wifi_state(%s)", val);
-                       if (strcmp(EVT_VAL_WIFI_CONNECTED, val) != 0)
-                               return;
+               if (is_user_event == false) {
+                       if (strcmp(SYS_EVENT_BATTERY_CHARGER_STATUS, event_name) == 0) {
+                               val = bundle_get_val(data, EVT_KEY_BATTERY_CHARGER_STATUS);
+                               _D("charger val(%s)", val);
+                               if (val && (strcmp(EVT_VAL_BATTERY_CHARGER_CONNECTED, val) != 0))
+                                       return;
+                       } else if (strcmp(SYS_EVENT_USB_STATUS, event_name) == 0) {
+                               val = bundle_get_val(data, EVT_KEY_USB_STATUS);
+                               _D("usb val(%s)", val);
+                               if (val && (strcmp(EVT_VAL_USB_CONNECTED, val) != 0))
+                                       return;
+                       } else if (strcmp(SYS_EVENT_EARJACK_STATUS, event_name) == 0) {
+                               val = bundle_get_val(data, EVT_KEY_EARJACK_STATUS);
+                               _D("earjack val(%s)", val);
+                               if (val && (strcmp(EVT_VAL_EARJACK_CONNECTED, val) != 0))
+                                       return;
+                       } else if (strcmp(SYS_EVENT_INCOMMING_MSG, event_name) == 0) {
+                               msg_type = bundle_get_val(data, EVT_KEY_MSG_TYPE);
+                               _D("msg_type(%s)", msg_type);
+                               if (msg_type == NULL)
+                                       return;
+
+                               msg_id = bundle_get_val(data, EVT_KEY_MSG_ID);
+                               _D("msg_id(%s)", msg_id);
+                               if (msg_id == NULL)
+                                       return;
+                       } else if (strcmp(SYS_EVENT_WIFI_STATE, event_name) == 0) {
+                               val = bundle_get_val(data, EVT_KEY_WIFI_STATE);
+                               if (val == NULL)
+                                       return;
+                               _D("wifi_state(%s)", val);
+                               if (strcmp(EVT_VAL_WIFI_CONNECTED, val) != 0)
+                                       return;
+                       }
                }
 
                eep = calloc(1, sizeof(esd_event_param));
@@ -839,6 +948,10 @@ static void __esd_launch_event_handler(char *event_name, bundle *data, void *use
                }
                eep->event_name = event_name;
                eep->event_data = data;
+               eep->sender_uid = sender_uid;
+               eep->sender_appid = sender_appid;
+               eep->is_user_event = is_user_event;
+               eep->trusted = trusted;
                eep->user_data = (void *)user_data;
                __esd_check_event_launch_with_eventid(el_item, eep);
                free(eep);
@@ -915,7 +1028,8 @@ static void __esd_event_handler(char *event_name, bundle *data, void *user_data)
 #endif
 
        if (__esd_check_event_launch_support(event_name))
-               __esd_launch_event_handler(event_name, data, user_data);
+               __esd_launch_event_handler(event_name, data,
+                               false, true, ROOT_USER, NULL, user_data);
 }
 
 static void __esd_trusted_busname_remove_item(char *bus_name)
@@ -1126,6 +1240,13 @@ static const gchar introspection_xml[] =
 "                      <arg type='s' name='own_name' direction='in'/>"
 "                      <arg type='i' name='ret' direction='out'/>"
 "              </method>"
+"              <method name='LaunchOnEventFromUserEvent'>"
+"                      <arg type='s' name='eventname' direction='in'/>"
+"                      <arg type='s' name='eventdata' direction='in'/>"
+"                      <arg type='i' name='datalen' direction='in'/>"
+"                      <arg type='b' name='trusted' direction='in'/>"
+"                      <arg type='i' name='ret' direction='out'/>"
+"              </method>"
 "      </interface>"
 "</node>";
 
@@ -1614,6 +1735,56 @@ out:
        g_dbus_method_invocation_return_value(invocation, param);
 }
 
+static void launch_on_event_from_userevent(GDBusConnection *connection,
+               const gchar *sender, GVariant *parameters,
+               GDBusMethodInvocation *invocation)
+{
+       GVariant *param;
+       int result = ES_R_OK;
+       int len;
+       bool trusted;
+       int sender_pid;
+       uid_t sender_uid;
+       char *event_name;
+       char app_id[128];
+       char *buf;
+       bundle *b;
+
+       g_variant_get(parameters, "(&s&sib)", &event_name, &buf, &len, &trusted);
+
+       if (!event_name) {
+               result = ES_R_ERROR;
+               _E("invalid event_name");
+               goto out;
+       }
+
+       sender_pid = __get_sender_pid(connection, sender);
+       sender_uid = (uid_t)__get_sender_uid(connection, sender);
+       if (__esd_get_appid_by_pid(sender_pid, sender_uid, app_id,
+                               sizeof(app_id)) < 0) {
+               _E("failed to get appid by pid");
+               result = ES_R_ERROR;
+               goto out;
+       }
+
+       b = bundle_decode((bundle_raw *)buf, len);
+       if (b == NULL) {
+               _E("Out of memory");
+               result = ES_R_ENOMEM;
+               goto out;
+       }
+
+       __esd_launch_event_handler(event_name, b, true, trusted,
+                       sender_uid, app_id, NULL);
+
+       bundle_free(b);
+
+out:
+       param = g_variant_new("(i)", result);
+
+       g_dbus_method_invocation_return_value(invocation, param);
+}
+
 static void handle_method_call(GDBusConnection *connection,
        const gchar *sender, const gchar *object_path,
        const gchar *interface_name, const gchar *method_name,
@@ -1638,6 +1809,8 @@ static void handle_method_call(GDBusConnection *connection,
                keep_last_data_method_call(connection, sender, parameters, invocation);
        } else if (g_strcmp0(method_name, "CheckLastData") == 0) {
                check_last_data_method_call(connection, sender, parameters, invocation);
+       }  else if (g_strcmp0(method_name, "LaunchOnEventFromUserEvent") == 0) {
+               launch_on_event_from_userevent(connection, sender, parameters, invocation);
        }
 }
 
@@ -1905,7 +2078,6 @@ static int __esd_appcontrol_cb(const char *operation,
        char *appid = NULL;
        char *pkgid = NULL;
        char *event_name = NULL;
-       const char *prefix = "event://";
        uid_t uid = 0;
 
        if (cb_data == NULL) {
@@ -1920,25 +2092,33 @@ static int __esd_appcontrol_cb(const char *operation,
                uid, appid, pkgid, operation, uri, mime);
 
        if (!strcmp(operation, APPSVC_OPERATION_LAUNCH_ON_EVENT)) {
-               if (uri && !strncmp(uri, prefix, strlen(prefix))) {
+               if (uri && !strncmp(uri, SYSTEM_EVENT_NAME_PREFIX, strlen(SYSTEM_EVENT_NAME_PREFIX))) {
                        event_name = strdup(&uri[8]);
                        if (event_name) {
                                _D("appid(%s), event_name(%s)", appid, event_name);
-                               if (!__esd_check_event_launch_support(event_name)) {
+                               if (!__esd_check_event_launch_support(event_name))
                                        _E("failed to add item (not support event)");
-                               } else if (!__esd_check_app_privileged_event(uid, appid, pkgid, event_name)) {
+                               else if (!__esd_check_app_privileged_event(uid, appid, pkgid, event_name))
                                        _E("failed to add item (no privilege)");
-                               } else {
+                               else if (__esd_add_launch_item(uid, event_name, appid, pkgid))
+                                       _E("failed to add item");
+
+                       } else {
+                               _E("out of memory");
+                       }
+               } else if (uri && !strncmp(uri, USER_EVENT_NAME_PREFIX, strlen(USER_EVENT_NAME_PREFIX))) {
+                       event_name = strdup(uri);
+                       if (event_name) {
+                               _D("appid(%s), event_name(%s)", appid, event_name);
+                               if (__esd_check_platform_cert(pkgid, uid)) {
                                        if (__esd_add_launch_item(uid, event_name, appid, pkgid))
                                                _E("failed to add item");
                                }
-                               FREE_AND_NULL(event_name);
                        } else {
                                _E("out of memory");
                        }
-               } else {
-                       _E("Invalid uri(%s) for event_name", uri);
                }
+               FREE_AND_NULL(event_name);
        }
 
        return 0;
@@ -2041,9 +2221,10 @@ static int __esd_pkgmgr_event_callback(uid_t target_uid, int req_id,
                                return 0;
                        }
                        ret = pkgmgrinfo_appinfo_get_usr_list(handle,
-                               PMINFO_ALL_APP, __esd_add_appinfo_handler, &target_uid, target_uid);
+                               PMINFO_SVC_APP, __esd_add_appinfo_handler, &target_uid, target_uid);
                        if (ret < 0) {
                                _E("failed to get appinfo");
+                               pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
                                __esd_pkgmgr_event_free(pkg_event);
                                return 0;
                        }