Add card Inserted implementation and fix bug
[platform/core/connectivity/smartcard-service.git] / server / ServerGDBus.cpp
index 87a0c65..f12f39b 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#ifdef USE_GDBUS
+/* standard library header */
 #include <unistd.h>
 #include <glib.h>
 #include <gio/gio.h>
@@ -22,6 +22,7 @@
 #include <string>
 #include <sys/socket.h>
 
+/* local header */
 #include "smartcard-types.h"
 #include "Debug.h"
 #include "ByteArray.h"
 #include "GDBusHelper.h"
 #include "ServerGDBus.h"
 
+#ifdef USE_CYNARA
+#include "cynara-client.h"
+#include "cynara-creds-gdbus.h"
+#include "cynara-session.h"
+
+#define SMARTCARD_PRIVILEGE "http://tizen.org/privilege/secureelement"
+#endif
+
 using namespace std;
 
+#ifdef __PRIVATE
+extern "C" bool smartcard_service_init_access_control(void *connection);
+extern "C" void smartcard_service_deinit_access_control();
+#endif
+
 namespace smartcard_service_api
 {
        GDBusDispatcher::GDBusDispatcher() : Synchronous()
@@ -48,22 +62,27 @@ namespace smartcard_service_api
                return dispatcher;
        }
 
-       void GDBusDispatcher::push(dispatcher_cb_t cb, const vector<void *> &params)
+       void GDBusDispatcher::_push(dispatcher_cb_t cb,
+               const vector<void *> &params)
        {
-               _BEGIN();
-
                syncLock();
 
                q.push(make_pair(cb, params));
+               _INFO("request pushed, count [%zu]", q.size());
+
                if (q.size() == 1) {
                        /* start dispatch */
-                       _INFO("start dispatch");
+                       _INFO("start dispatcher");
                        g_idle_add(&GDBusDispatcher::dispatch, this);
                }
 
                syncUnlock();
+       }
 
-               _END();
+       void GDBusDispatcher::push(dispatcher_cb_t cb,
+               const vector<void *> &params)
+       {
+               GDBusDispatcher::getInstance()._push(cb, params);
        }
 
        gboolean GDBusDispatcher::dispatch(gpointer user_data)
@@ -85,12 +104,14 @@ namespace smartcard_service_api
                dispatcher->syncLock();
 
                dispatcher->q.pop();
+               /* LCOV_EXCL_START */
                if (dispatcher->q.size() > 0) {
-                       _INFO("remaining messages : %d", dispatcher->q.size());
+                       _INFO("remaining messages : %zu", dispatcher->q.size());
 
                        result = true;
+               /* LCOV_EXCL_STOP */
                } else {
-                       _INFO("dispatch finish");
+                       _INFO("dispatch finished");
                }
 
                dispatcher->syncUnlock();
@@ -117,10 +138,16 @@ namespace smartcard_service_api
                return serverGDBus;
        }
 
-       void ServerGDBus::name_owner_changed(GDBusProxy *proxy,
+       static void name_owner_changed(GDBusProxy *proxy,
                const gchar *name, const gchar *old_owner,
                const gchar *new_owner, void *user_data)
        {
+               /* LCOV_EXCL_START */
+               if (name == NULL || old_owner == NULL || new_owner == NULL) {
+                       _ERR("invalid parameter");
+                       return;
+               }
+               /* LCOV_EXCL_STOP */
                if (strlen(new_owner) == 0) {
                        ClientInstance *client;
 
@@ -131,13 +158,34 @@ namespace smartcard_service_api
                                _INFO("terminated client, pid [%d]", client->getPID());
                                resource.removeClient(old_owner);
 
-                               if (resource.getClientCount() == 0) {
-                                       g_main_loop_quit((GMainLoop *)resource.getMainLoopInstance());
-                               }
+                               resource.finish();
                        }
                }
        }
 
+       static void _on_name_owner_changed(GDBusConnection *connection,
+               const gchar *sender_name, const gchar *object_path,
+               const gchar *interface_name, const gchar *signal_name,
+               GVariant *parameters, gpointer user_data)
+       {
+               gchar *name;
+               gchar *old_owner;
+               gchar *new_owner;
+
+               g_variant_get(parameters,
+                       "(sss)",
+                       &name,
+                       &old_owner,
+                       &new_owner);
+
+               name_owner_changed((GDBusProxy *)connection,
+                       name, old_owner, new_owner, user_data);
+
+               g_free(name);
+               g_free(old_owner);
+               g_free(new_owner);
+       }
+
        bool ServerGDBus::_init()
        {
                GError *error = NULL;
@@ -153,15 +201,24 @@ namespace smartcard_service_api
                        &error);
                if (dbus_proxy == NULL)
                {
+                       /* LCOV_EXCL_START */
                        _ERR("Can not create proxy : %s", error->message);
                        g_error_free(error);
 
                        return false;
+                       /* LCOV_EXCL_STOP */
                }
 
-               g_signal_connect(dbus_proxy, "name-owner-changed",
-                               G_CALLBACK(&ServerGDBus::name_owner_changed),
-                               this);
+               /* subscribe signal */
+               g_dbus_connection_signal_subscribe(connection,
+                       "org.freedesktop.DBus", /* bus name */
+                       "org.freedesktop.DBus", /* interface */
+                       "NameOwnerChanged", /* member */
+                       "/org/freedesktop/DBus", /* path */
+                       NULL, /* arg0 */
+                       G_DBUS_SIGNAL_FLAGS_NONE,
+                       _on_name_owner_changed,
+                       NULL, NULL);
 
                return true;
        }
@@ -178,38 +235,45 @@ namespace smartcard_service_api
        {
                GError *error = NULL;
 
-               _init();
-
                connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
                if (connection != NULL) {
+               /* LCOV_EXCL_START */
                } else {
                        _ERR("Can not get connection %s", error->message);
                        g_error_free(error);
 
                        return false;
                }
+               /* LCOV_EXCL_STOP */
+
+               _init();
 
                initSEService();
                initReader();
                initSession();
                initChannel();
-
+#ifdef __PRIVATE
+               smartcard_service_init_access_control(connection);
+#endif
                return true;
        }
 
        void ServerGDBus::deinit()
        {
-               deinitSEService();
-               deinitReader();
-               deinitSession();
+#ifdef __PRIVATE
+               smartcard_service_deinit_access_control();
+#endif
                deinitChannel();
+               deinitSession();
+               deinitReader();
+               deinitSEService();
+
+               _deinit();
 
                if (connection != NULL) {
                        g_object_unref(connection);
                        connection = NULL;
                }
-
-               _deinit();
        }
 
        static gboolean _call_get_connection_unix_process_id_sync(
@@ -218,10 +282,10 @@ namespace smartcard_service_api
                GVariant *_ret;
 
                _ret = g_dbus_proxy_call_sync(proxy,
-                               "GetConnectionUnixProcessID",
-                               g_variant_new("(s)", arg_name),
-                               G_DBUS_CALL_FLAGS_NONE,
-                               -1, cancellable, error);
+                       "GetConnectionUnixProcessID",
+                       g_variant_new("(s)", arg_name),
+                       G_DBUS_CALL_FLAGS_NONE,
+                       -1, cancellable, error);
                if (_ret != NULL) {
                        g_variant_get(_ret, "(u)", out_pid);
                        g_variant_unref(_ret);
@@ -238,19 +302,108 @@ namespace smartcard_service_api
                if (_call_get_connection_unix_process_id_sync(
                        (GDBusProxy *)dbus_proxy, name,
                        &pid, NULL, &error) == true) {
+               /* LCOV_EXCL_START */
                } else {
                        _ERR("_g_freedesktop_dbus_call_get_connection_unix_process_id_sync failed  : %s", error->message);
                        g_error_free(error);
                }
+               /* LCOV_EXCL_STOP */
 
                return pid;
        }
 
+#ifdef USE_CYNARA
+       static bool _get_credentials(GDBusMethodInvocation *invocation)
+       {
+               int ret = 0;
+               int pid = 0;
+               char *user;
+               char *client;
+               char *client_session;
+               cynara *p_cynara = NULL;
+               const char *sender_unique_name;
+               GDBusConnection *connection;
+
+               connection = g_dbus_method_invocation_get_connection(invocation);
+               sender_unique_name = g_dbus_method_invocation_get_sender(invocation);
+
+               pid = ServerGDBus::getInstance().getPID(sender_unique_name);
+
+               ret = cynara_initialize(&p_cynara, NULL);
+               /* LCOV_EXCL_START */
+               if (ret != CYNARA_API_SUCCESS) {
+                       _ERR("cynara_initialize() failed");
+                       return false;
+               }
+               /* LCOV_EXCL_STOP */
+
+               ret = cynara_creds_gdbus_get_user(connection, sender_unique_name, USER_METHOD_DEFAULT, &user);
+               /* LCOV_EXCL_START */
+               if (ret != CYNARA_API_SUCCESS) {
+                       _ERR("cynara_creds_gdbus_get_user() failed");
+                       return false;
+               }
+               /* LCOV_EXCL_STOP */
+
+               ret = cynara_creds_gdbus_get_client(connection, sender_unique_name, CLIENT_METHOD_DEFAULT, &client);
+               /* LCOV_EXCL_START */
+               if (ret != CYNARA_API_SUCCESS) {
+                       _ERR("cynara_creds_gdbus_get_client() failed");
+                       g_free(user);
+                       return false;
+               }
+               /* LCOV_EXCL_STOP */
+
+               _ERR("user :%s , client :%s ,unique_name : %s, pid() : %d", user, client, sender_unique_name, pid);
+
+               client_session = cynara_session_from_pid(pid);
+
+               /* LCOV_EXCL_START */
+               if (!client_session) {
+                       _ERR("cynara_session_from_pid() failed");
+                       g_free(client);
+                       g_free(user);
+                       return false;
+               }
+               /* LCOV_EXCL_STOP */
+
+               ret = cynara_check(p_cynara, client, client_session, user, SMARTCARD_PRIVILEGE);
+               if ( ret == CYNARA_API_ACCESS_ALLOWED ) {
+                       _INFO("cynara PASS");
+               }
+
+               g_free(client_session);
+               g_free(client);
+               g_free(user);
+
+               if (p_cynara) {
+                       cynara_finish(p_cynara);
+                       p_cynara = NULL;
+               }
+
+               return (ret == CYNARA_API_ACCESS_ALLOWED ) ? true : false;
+       }
+#endif
+
+       static bool _is_authorized_request(GDBusMethodInvocation *invocation)
+       {
+               bool result = false;
+
+#ifdef USE_CYNARA
+               result = _get_credentials(invocation);
+#endif
+
+               _ERR("api security check result : %d", result);
+
+               return result;
+       }
+
        /* SEService *
         *
         *
         */
-       static GVariant *_reader_to_variant(vector<pair<unsigned int, string> > &readers)
+       static GVariant *_reader_to_variant(
+               vector<pair<unsigned int, string> > &readers)
        {
                GVariantBuilder builder;
                uint32_t i;
@@ -258,32 +411,36 @@ namespace smartcard_service_api
                g_variant_builder_init(&builder, G_VARIANT_TYPE("a(us)"));
 
                for (i = 0; i < readers.size(); i++) {
-                       g_variant_builder_add(&builder, "(us)", readers[i].first, readers[i].second.c_str());
+                       g_variant_builder_add(&builder, "(us)",
+                               readers[i].first, readers[i].second.c_str());
                }
 
                return g_variant_builder_end(&builder);
        }
 
        static gboolean __process_se_service(SmartcardServiceSeService *object,
-               GDBusMethodInvocation *invocation, void *user_data)
+               GDBusMethodInvocation *invocation,
+               void *user_data)
        {
-               _INFO("[MSG_REQUEST_READERS]");
-
                gint result = SCARD_ERROR_OK;
                GVariant *readers = NULL;
                vector<pair<unsigned int, string> > list;
                unsigned int handle = IntegerHandle::INVALID_HANDLE;
+               const char *name;
+               pid_t pid;
+
+               _INFO("[MSG_REQUEST_READERS]");
 
                ServerResource &resource = ServerResource::getInstance();
 
+               name = g_dbus_method_invocation_get_sender(invocation);
+
                /* load secure elements */
                resource.loadSecureElements();
 
-               const char *name = g_dbus_method_invocation_get_sender(invocation);
-
-               pid_t pid = ServerGDBus::getInstance().getPID(name);
+               pid = ServerGDBus::getInstance().getPID(name);
 
-               _INFO("service requested, pid [%d]", pid);
+               _DBG("service requested, pid [%d]", pid);
 
                if (pid > 0) {
                        ClientInstance *instance;
@@ -295,9 +452,12 @@ namespace smartcard_service_api
                                resource.createClient(name, pid);
 
                                instance = resource.getClient(name);
-
-                               /* generate certification hashes */
-                               instance->generateCertificationHashes();
+                               if (instance != NULL) {
+                                       /* generate certification hashes */
+                                       instance->generateCertificationHashes();
+                               } else {
+                                       _ERR("createClient failed"); /* LCOV_EXCL_LINE */
+                               }
                        }
 
                        if (instance != NULL) {
@@ -306,10 +466,13 @@ namespace smartcard_service_api
                                /* create service */
                                service = resource.createService(name);
                                if (service != NULL) {
-
                                        handle = service->getHandle();
                                        resource.getReaders(list);
 
+                                       if (list.size() == 0) {
+                                               _INFO("no secure elements");
+                                       }
+                               /* LCOV_EXCL_START */
                                } else {
                                        _ERR("createService failed");
 
@@ -325,12 +488,9 @@ namespace smartcard_service_api
 
                        result = SCARD_ERROR_IPC_FAILED;
                }
+               /* LCOV_EXCL_STOP */
 
                readers = _reader_to_variant(list);
-               if (list.size() > 0) {
-               } else {
-                       _INFO("no secure elements");
-               }
 
                /* response to client */
                smartcard_service_se_service_complete_se_service(object,
@@ -345,53 +505,80 @@ namespace smartcard_service_api
                GDBusMethodInvocation *invocation;
                void *user_data;
 
+               /* LCOV_EXCL_START */
                if (params.size() != 3) {
                        _ERR("invalid parameter");
 
                        return;
                }
+               /* LCOV_EXCL_STOP */
 
                object = (SmartcardServiceSeService *)params[0];
                invocation = (GDBusMethodInvocation *)params[1];
                user_data = params[2];
 
                __process_se_service(object, invocation, user_data);
+
+               g_object_unref(object);
+               g_object_unref(invocation);
        }
 
        static gboolean _handle_se_service(SmartcardServiceSeService *object,
-               GDBusMethodInvocation *invocation, void *user_data)
+               GDBusMethodInvocation *invocation,
+               void *user_data)
        {
                vector<void *> params;
 
-               g_object_ref(object);
-               params.push_back((void *)object);
+               /* apply user space smack */
+               if (_is_authorized_request(invocation) == true) {
+                       g_object_ref(object);
+                       params.push_back((void *)object);
 
-               g_object_ref(invocation);
-               params.push_back((void *)invocation);
+                       g_object_ref(invocation);
+                       params.push_back((void *)invocation);
 
-               params.push_back((void *)user_data);
+                       params.push_back((void *)user_data);
 
-               GDBusDispatcher::getInstance().push(_process_se_service,
-                       params);
+                       GDBusDispatcher::push(_process_se_service, params);
+               /* LCOV_EXCL_START */
+               } else {
+                       vector<pair<unsigned int, string> > list;
+
+                       _ERR("access denied");
+
+                       /* response to client */
+                       smartcard_service_se_service_complete_se_service(object,
+                               invocation,
+                               SCARD_ERROR_SECURITY_NOT_ALLOWED,
+                               IntegerHandle::INVALID_HANDLE,
+                               _reader_to_variant(list));
+               }
+               /* LCOV_EXCL_STOP */
 
                return true;
        }
 
-
        static gboolean __process_shutdown(SmartcardServiceSeService *object,
                GDBusMethodInvocation *invocation,
                guint handle, void *user_data)
        {
+               const char *name;
+
                _INFO("[MSG_REQUEST_SHUTDOWN]");
 
-               const char *name = g_dbus_method_invocation_get_sender(invocation);
+               ServerResource &resource = ServerResource::getInstance();
 
-               ServerResource::getInstance().removeService(name, handle);
+               name = g_dbus_method_invocation_get_sender(invocation);
+
+               resource.removeService(name, handle);
 
                /* response to client */
                smartcard_service_se_service_complete_shutdown(object,
                        invocation, SCARD_ERROR_OK);
 
+               /* terminate */
+               resource.finish();
+
                return true;
        }
 
@@ -402,37 +589,53 @@ namespace smartcard_service_api
                guint handle;
                void *user_data;
 
+               /* LCOV_EXCL_START */
                if (params.size() != 4) {
                        _ERR("invalid parameter");
 
                        return;
                }
+               /* LCOV_EXCL_STOP */
 
                object = (SmartcardServiceSeService *)params[0];
                invocation = (GDBusMethodInvocation *)params[1];
-               handle = (guint)params[2];
+               handle = (gulong)params[2];
                user_data = params[3];
 
                __process_shutdown(object, invocation, handle, user_data);
+
+               g_object_unref(object);
+               g_object_unref(invocation);
        }
 
        static gboolean _handle_shutdown(SmartcardServiceSeService *object,
-               GDBusMethodInvocation *invocation, guint handle,
+               GDBusMethodInvocation *invocation,
+               guint handle,
                void *user_data)
        {
                vector<void *> params;
 
-               g_object_ref(object);
-               params.push_back((void *)object);
+               /* apply user space smack */
+               if (_is_authorized_request(invocation) == true) {
+                       g_object_ref(object);
+                       params.push_back((void *)object);
+
+                       g_object_ref(invocation);
+                       params.push_back((void *)invocation);
 
-               g_object_ref(invocation);
-               params.push_back((void *)invocation);
+                       params.push_back((void *)handle);
+                       params.push_back(user_data);
 
-               params.push_back((void *)handle);
-               params.push_back(user_data);
+                       GDBusDispatcher::push(_process_shutdown, params);
+               /* LCOV_EXCL_START */
+               } else {
+                       _ERR("access denied");
 
-               GDBusDispatcher::getInstance().push(_process_shutdown,
-                       params);
+                       /* response to client */
+                       smartcard_service_se_service_complete_shutdown(object,
+                               invocation, SCARD_ERROR_SECURITY_NOT_ALLOWED);
+               }
+               /* LCOV_EXCL_STOP */
 
                return true;
        }
@@ -453,6 +656,7 @@ namespace smartcard_service_api
                        G_CALLBACK(_handle_shutdown),
                        this);
 
+               /* LCOV_EXCL_START */
                if (g_dbus_interface_skeleton_export(
                        G_DBUS_INTERFACE_SKELETON(seService),
                        connection,
@@ -467,6 +671,7 @@ namespace smartcard_service_api
 
                        return false;
                }
+               /* LCOV_EXCL_STOP */
 
                return true;
        }
@@ -482,17 +687,41 @@ namespace smartcard_service_api
        void ServerGDBus::emitReaderInserted(unsigned int reader_id,
                const char *reader_name)
        {
+               /* LCOV_EXCL_START */
                smartcard_service_se_service_emit_reader_inserted(
                        SMARTCARD_SERVICE_SE_SERVICE(seService),
                        reader_id, reader_name);
+               /* LCOV_EXCL_STOP */
        }
 
        void ServerGDBus::emitReaderRemoved(unsigned int reader_id,
                const char *reader_name)
        {
+               /* LCOV_EXCL_START */
                smartcard_service_se_service_emit_reader_removed(
                        SMARTCARD_SERVICE_SE_SERVICE(seService),
                        reader_id, reader_name);
+               /* LCOV_EXCL_STOP */
+       }
+
+       void ServerGDBus::emitCardInserted(unsigned int reader_id,
+               const char *reader_name)
+       {
+               /* LCOV_EXCL_START */
+               smartcard_service_se_service_emit_card_inserted(
+                       SMARTCARD_SERVICE_SE_SERVICE(seService),
+                       reader_id, reader_name);
+               /* LCOV_EXCL_STOP */
+       }
+
+       void ServerGDBus::emitCardRemoved(unsigned int reader_id,
+               const char *reader_name)
+       {
+               /* LCOV_EXCL_START */
+               smartcard_service_se_service_emit_card_removed(
+                       SMARTCARD_SERVICE_SE_SERVICE(seService),
+                       reader_id, reader_name);
+               /* LCOV_EXCL_STOP */
        }
 
        /* Reader *
@@ -505,32 +734,35 @@ namespace smartcard_service_api
        {
                unsigned int handle = IntegerHandle::INVALID_HANDLE;
                int result;
+               const char *name;
 
                _INFO("[MSG_REQUEST_OPEN_SESSION]");
 
                ServerResource &resource = ServerResource::getInstance();
 
-               const char *name = g_dbus_method_invocation_get_sender(invocation);
+               name = g_dbus_method_invocation_get_sender(invocation);
 
-               if (resource.isValidReaderHandle(reader_id))
-               {
+               if (resource.isValidReaderHandle(reader_id)) {
                        vector<ByteArray> temp;
 
-                       handle = resource.createSession(name, service_id, reader_id, temp, (void *)NULL);
-                       if (handle != IntegerHandle::INVALID_HANDLE)
-                       {
+                       handle = resource.createSession(name,
+                               service_id,
+                               reader_id,
+                               temp,
+                               (void *)NULL);
+                       if (handle != IntegerHandle::INVALID_HANDLE) {
                                result = SCARD_ERROR_OK;
-                       }
-                       else
-                       {
+                       } else {
+                               /* LCOV_EXCL_START */
                                _ERR("createSession failed [%d]", handle);
+
                                result = SCARD_ERROR_OUT_OF_MEMORY;
                        }
-               }
-               else
-               {
+               } else {
                        _ERR("request invalid reader handle [%d]", reader_id);
+
                        result = SCARD_ERROR_ILLEGAL_PARAM;
+                       /* LCOV_EXCL_STOP */
                }
 
                /* response to client */
@@ -549,39 +781,57 @@ namespace smartcard_service_api
                void *user_data;
 
                if (params.size() != 5) {
+                       /* LCOV_EXCL_START */
                        _ERR("invalid parameter");
 
                        return;
+                       /* LCOV_EXCL_STOP */
                }
 
                object = (SmartcardServiceReader *)params[0];
                invocation = (GDBusMethodInvocation *)params[1];
-               service_id = (guint)params[2];
-               reader_id = (guint)params[3];
+               service_id = (gulong)params[2];
+               reader_id = (gulong)params[3];
                user_data = params[4];
 
                __process_open_session(object, invocation, service_id,
                        reader_id, user_data);
+
+               g_object_unref(object);
+               g_object_unref(invocation);
        }
 
        static gboolean _handle_open_session(SmartcardServiceReader *object,
-               GDBusMethodInvocation *invocation, guint service_id,
+               GDBusMethodInvocation *invocation,
+               guint service_id,
                guint reader_id, void *user_data)
        {
                vector<void *> params;
 
-               g_object_ref(object);
-               params.push_back((void *)object);
+               /* apply user space smack */
+               if (_is_authorized_request(invocation) == true) {
+                       g_object_ref(object);
+                       params.push_back((void *)object);
 
-               g_object_ref(invocation);
-               params.push_back((void *)invocation);
+                       g_object_ref(invocation);
+                       params.push_back((void *)invocation);
 
-               params.push_back((void *)service_id);
-               params.push_back((void *)reader_id);
-               params.push_back(user_data);
+                       params.push_back((void *)service_id);
+                       params.push_back((void *)reader_id);
+                       params.push_back(user_data);
 
-               GDBusDispatcher::getInstance().push(_process_open_session,
-                       params);
+                       GDBusDispatcher::push(_process_open_session, params);
+               } else {
+                       /* LCOV_EXCL_START */
+                       _ERR("access denied");
+
+                       /* response to client */
+                       smartcard_service_reader_complete_open_session(object,
+                               invocation,
+                               SCARD_ERROR_SECURITY_NOT_ALLOWED,
+                               IntegerHandle::INVALID_HANDLE);
+                       /* LCOV_EXCL_STOP */
+               }
 
                return true;
        }
@@ -603,6 +853,7 @@ namespace smartcard_service_api
                        "/org/tizen/SmartcardService/Reader",
                        &error) == false)
                {
+                       /* LCOV_EXCL_START */
                        _ERR("Can not skeleton_export %s", error->message);
 
                        g_error_free(error);
@@ -610,6 +861,7 @@ namespace smartcard_service_api
                        reader = NULL;
 
                        return false;
+                       /* LCOV_EXCL_STOP */
                }
 
                return true;
@@ -617,10 +869,12 @@ namespace smartcard_service_api
 
        void ServerGDBus::deinitReader()
        {
+       /* LCOV_EXCL_START */
                if (reader != NULL) {
                        g_object_unref(reader);
                        reader = NULL;
                }
+       /* LCOV_EXCL_STOP */
        }
 
        /* Session *
@@ -631,15 +885,20 @@ namespace smartcard_service_api
                GDBusMethodInvocation *invocation, guint service_id,
                guint session_id, void *user_data)
        {
+               const char *name;
+
                _INFO("[MSG_REQUEST_CLOSE_SESSION]");
 
                ServerResource &resource = ServerResource::getInstance();
 
-               const char *name = g_dbus_method_invocation_get_sender(invocation);
+               name = g_dbus_method_invocation_get_sender(invocation);
 
-               if (resource.isValidSessionHandle(name, service_id, session_id))
-               {
-                       resource.removeSession(name, service_id, session_id);
+               if (resource.isValidSessionHandle(name, service_id,
+                       session_id)) {
+                       resource.removeSession(name, service_id,
+                               session_id);
+               } else {
+                       _ERR("invalid parameters"); //LCOV_EXCL_LINE
                }
 
                /* response to client */
@@ -658,39 +917,55 @@ namespace smartcard_service_api
                void *user_data;
 
                if (params.size() != 5) {
+                       /* LCOV_EXCL_START */
                        _ERR("invalid parameter");
 
                        return;
+                       /* LCOV_EXCL_STOP */
                }
 
                object = (SmartcardServiceSession *)params[0];
                invocation = (GDBusMethodInvocation *)params[1];
-               service_id = (guint)params[2];
-               session_id = (guint)params[3];
+               service_id = (gulong)params[2];
+               session_id = (gulong)params[3];
                user_data = params[4];
 
                __process_close_session(object, invocation, service_id,
                        session_id, user_data);
+
+               g_object_unref(object);
+               g_object_unref(invocation);
        }
 
        static gboolean _handle_close_session(SmartcardServiceSession *object,
-               GDBusMethodInvocation *invocation, guint service_id,
+               GDBusMethodInvocation *invocation,
+               guint service_id,
                guint session_id, void *user_data)
        {
                vector<void *> params;
 
-               g_object_ref(object);
-               params.push_back((void *)object);
+               /* apply user space smack */
+               if (_is_authorized_request(invocation) == true) {
+                       g_object_ref(object);
+                       params.push_back((void *)object);
 
-               g_object_ref(invocation);
-               params.push_back((void *)invocation);
+                       g_object_ref(invocation);
+                       params.push_back((void *)invocation);
 
-               params.push_back((void *)service_id);
-               params.push_back((void *)session_id);
-               params.push_back(user_data);
+                       params.push_back((void *)service_id);
+                       params.push_back((void *)session_id);
+                       params.push_back(user_data);
 
-               GDBusDispatcher::getInstance().push(_process_close_session,
-                       params);
+                       GDBusDispatcher::push(_process_close_session, params);
+               } else {
+                       /* LCOV_EXCL_START */
+                       _ERR("access denied");
+
+                       /* response to client */
+                       smartcard_service_session_complete_close_session(object,
+                               invocation, SCARD_ERROR_SECURITY_NOT_ALLOWED);
+                       /* LCOV_EXCL_STOP */
+               }
 
                return true;
        }
@@ -700,51 +975,49 @@ namespace smartcard_service_api
                guint session_id, void *user_data)
        {
                int result;
+               ByteArray resp;
                GVariant *atr = NULL;
+               const char *name;
                ServiceInstance *client = NULL;
 
                _INFO("[MSG_REQUEST_GET_ATR]");
 
                ServerResource &resource = ServerResource::getInstance();
 
-               const char *name = g_dbus_method_invocation_get_sender(invocation);
+               name = g_dbus_method_invocation_get_sender(invocation);
 
-               if ((client = resource.getService(name, service_id)) != NULL)
-               {
-                       Terminal *terminal = NULL;
+               client = resource.getService(name, service_id);
+               /* LCOV_EXCL_START */
+               if (client != NULL) {
+                       Terminal *terminal;
 
-                       if ((terminal = client->getTerminal(session_id)) != NULL)
-                       {
-                               int rv;
-                               ByteArray temp;
+                       terminal = client->getTerminal(session_id);
+                       if (terminal != NULL) {
+                               if (terminal->open() == true) {
+                                       result = terminal->getATRSync(resp);
+                                       if (result < SCARD_ERROR_OK) {
+                                               _ERR("getATRSync failed : name [%s], service_id [%d], session_id [%d]", name, service_id, session_id);
+                                       }
 
-                               if ((rv = terminal->getATRSync(temp)) == 0)
-                               {
-                                       atr = GDBusHelper::convertByteArrayToVariant(temp);
-                                       result = SCARD_ERROR_OK;
-                               }
-                               else
-                               {
-                                       _ERR("transmit failed [%d]", rv);
+                                       terminal->close();
+                               } else {
+                                       _ERR("terminal->open failed");
 
-                                       result = rv;
+                                       result = SCARD_ERROR_UNAVAILABLE;
                                }
-                       }
-                       else
-                       {
+                       } else {
                                _ERR("getTerminal failed : name [%s], service_id [%d], session_id [%d]", name, service_id, session_id);
+
                                result = SCARD_ERROR_UNAVAILABLE;
                        }
-               }
-               else
-               {
+               } else {
                        _ERR("getClient failed : name [%s], service_id [%d], session_id [%d]", name, service_id, session_id);
+
                        result = SCARD_ERROR_UNAVAILABLE;
                }
+               /* LCOV_EXCL_STOP */
 
-               if (atr == NULL) {
-                       atr = GDBusHelper::convertByteArrayToVariant(ByteArray::EMPTY);
-               }
+               atr = GDBusHelper::convertByteArrayToVariant(resp);
 
                /* response to client */
                smartcard_service_session_complete_get_atr(object, invocation,
@@ -762,94 +1035,123 @@ namespace smartcard_service_api
                void *user_data;
 
                if (params.size() != 5) {
+       /* LCOV_EXCL_START */
                        _ERR("invalid parameter");
 
                        return;
+       /* LCOV_EXCL_STOP */
                }
 
                object = (SmartcardServiceSession *)params[0];
                invocation = (GDBusMethodInvocation *)params[1];
-               service_id = (guint)params[2];
-               session_id = (guint)params[3];
+               service_id = (gulong)params[2];
+               session_id = (gulong)params[3];
                user_data = params[4];
 
                __process_get_atr(object, invocation, service_id,
                        session_id, user_data);
+
+               g_object_unref(object);
+               g_object_unref(invocation);
        }
 
        static gboolean _handle_get_atr(SmartcardServiceSession *object,
-               GDBusMethodInvocation *invocation, guint service_id,
+               GDBusMethodInvocation *invocation,
+               guint service_id,
                guint session_id, void *user_data)
        {
                vector<void *> params;
 
-               g_object_ref(object);
-               params.push_back((void *)object);
+               /* apply user space smack */
+               if (_is_authorized_request(invocation) == true) {
+                       g_object_ref(object);
+                       params.push_back((void *)object);
 
-               g_object_ref(invocation);
-               params.push_back((void *)invocation);
+                       g_object_ref(invocation);
+                       params.push_back((void *)invocation);
 
-               params.push_back((void *)service_id);
-               params.push_back((void *)session_id);
-               params.push_back(user_data);
+                       params.push_back((void *)service_id);
+                       params.push_back((void *)session_id);
+                       params.push_back(user_data);
 
-               GDBusDispatcher::getInstance().push(_process_get_atr,
-                       params);
+                       GDBusDispatcher::push(_process_get_atr, params);
+               } else {
+                       /* LCOV_EXCL_START */
+                       ByteArray resp;
+
+                       _ERR("access denied");
+
+                       /* response to client */
+                       smartcard_service_session_complete_get_atr(
+                               object,
+                               invocation,
+                               SCARD_ERROR_SECURITY_NOT_ALLOWED,
+                               GDBusHelper::convertByteArrayToVariant(resp));
+                       /* LCOV_EXCL_STOP */
+               }
 
                return true;
        }
 
        static gboolean __process_open_channel(SmartcardServiceSession *object,
                GDBusMethodInvocation *invocation, guint service_id,
-               guint session_id, guint type, GVariant *aid, void *user_data)
+               guint session_id, guint type, GVariant *aid, guint8 P2, void *user_data)
        {
+               int channelNum = -1;
                int result = SCARD_ERROR_UNKNOWN;
+               ByteArray resp;
                GVariant *response = NULL;
                unsigned int channelID = IntegerHandle::INVALID_HANDLE;
+               const char *name;
 
                _INFO("[MSG_REQUEST_OPEN_CHANNEL]");
+               _INFO("P2 is %x", P2);
 
                ServerResource &resource = ServerResource::getInstance();
 
-               const char *name = g_dbus_method_invocation_get_sender(invocation);
+               name = g_dbus_method_invocation_get_sender(invocation);
 
                try
                {
                        ByteArray tempAid;
 
-                       GDBusHelper::convertVariantToByteArray(aid, tempAid);
+                       GDBusHelper::convertVariantToByteArray(aid,
+                               tempAid);
 
-                       channelID = resource.createChannel(name, service_id, session_id, type, tempAid);
-                       if (channelID != IntegerHandle::INVALID_HANDLE)
-                       {
+                       channelID = resource.createChannel(name,
+                               service_id, session_id, type, tempAid);
+                       /* LCOV_EXCL_START */
+                       if (channelID != IntegerHandle::INVALID_HANDLE) {
                                ServerChannel *temp;
 
-                               temp = (ServerChannel *)resource.getChannel(name, service_id, channelID);
-                               if (temp != NULL)
-                               {
+                               temp = (ServerChannel *)resource.getChannel(
+                                       name, service_id, channelID);
+                               if (temp != NULL) {
+                                       resp = temp->getSelectResponse();
+                                       channelNum = temp->getChannelNumber();
                                        result = SCARD_ERROR_OK;
-                                       response = GDBusHelper::convertByteArrayToVariant(temp->getSelectResponse());
+                               } else {
+                                       _ERR("getChannel is failed");
+                                       result = SCARD_ERROR_UNAVAILABLE;
                                }
-                       }
-                       else
-                       {
+                       } else {
                                _ERR("channel is null.");
 
                                /* set error value */
                                result = SCARD_ERROR_UNAVAILABLE;
                        }
+                       /* LCOV_EXCL_STOP */
                }
                catch (ExceptionBase &e)
                {
                        result = e.getErrorCode();
                }
 
-               if (response == NULL) {
-                       response = GDBusHelper::convertByteArrayToVariant(ByteArray::EMPTY);
-               }
+               response = GDBusHelper::convertByteArrayToVariant(resp);
+
                /* response to client */
                smartcard_service_session_complete_open_channel(object,
-                       invocation, result, channelID, response);
+                       invocation, result, channelID, channelNum, response);
 
                return true;
        }
@@ -861,49 +1163,75 @@ namespace smartcard_service_api
                guint service_id;
                guint session_id;
                guint type;
+               guint8 P2;
                GVariant *aid;
                void *user_data;
 
-               if (params.size() != 7) {
+               if (params.size() != 8) {
+                       /* LCOV_EXCL_START */
                        _ERR("invalid parameter");
 
                        return;
+                       /* LCOV_EXCL_STOP */
                }
 
                object = (SmartcardServiceSession *)params[0];
                invocation = (GDBusMethodInvocation *)params[1];
-               service_id = (guint)params[2];
-               session_id = (guint)params[3];
-               type = (guint)params[4];
+               service_id = (gulong)params[2];
+               session_id = (gulong)params[3];
+               type = (gulong)params[4];
                aid = (GVariant *)params[5];
-               user_data = params[6];
+               P2 = (guint8)((gulong)params[6]);
+               user_data = params[7];
 
                __process_open_channel(object, invocation, service_id,
-                       session_id, type, aid, user_data);
+                       session_id, type, aid, P2, user_data);
+
+               g_object_unref(object);
+               g_object_unref(invocation);
+               g_variant_unref(aid);
        }
 
        static gboolean _handle_open_channel(SmartcardServiceSession *object,
-               GDBusMethodInvocation *invocation, guint service_id,
-               guint session_id, guint type, GVariant *aid, void *user_data)
+               GDBusMethodInvocation *invocation,
+               guint service_id,
+               guint session_id, guint type, GVariant *aid, guint8 P2, void *user_data)
        {
                vector<void *> params;
 
-               g_object_ref(object);
-               params.push_back((void *)object);
+               /* apply user space smack */
+               if (_is_authorized_request(invocation) == true) {
+                       g_object_ref(object);
+                       params.push_back((void *)object);
 
-               g_object_ref(invocation);
-               params.push_back((void *)invocation);
+                       g_object_ref(invocation);
+                       params.push_back((void *)invocation);
 
-               params.push_back((void *)service_id);
-               params.push_back((void *)session_id);
-               params.push_back((void *)type);
+                       params.push_back((void *)service_id);
+                       params.push_back((void *)session_id);
+                       params.push_back((void *)type);
 
-               g_object_ref(aid);
-               params.push_back((void *)aid);
-               params.push_back(user_data);
+                       g_variant_ref(aid);
+                       params.push_back((void *)aid);
+                       params.push_back((void *)((int)P2));
+                       params.push_back(user_data);
 
-               GDBusDispatcher::getInstance().push(_process_open_channel,
-                       params);
+                       GDBusDispatcher::push(_process_open_channel, params);
+               } else {
+                       /* LCOV_EXCL_START */
+                       ByteArray resp;
+
+                       _ERR("access denied");
+
+                       /* response to client */
+                       smartcard_service_session_complete_open_channel(object,
+                               invocation,
+                               SCARD_ERROR_SECURITY_NOT_ALLOWED,
+                               IntegerHandle::INVALID_HANDLE,
+                               -1,
+                               GDBusHelper::convertByteArrayToVariant(resp));
+                       /* LCOV_EXCL_STOP */
+               }
 
                return true;
        }
@@ -935,6 +1263,7 @@ namespace smartcard_service_api
                        "/org/tizen/SmartcardService/Session",
                        &error) == false)
                {
+                       /* LCOV_EXCL_START */
                        _ERR("Can not skeleton_export %s", error->message);
 
                        g_error_free(error);
@@ -942,6 +1271,7 @@ namespace smartcard_service_api
                        session = NULL;
 
                        return false;
+                       /* LCOV_EXCL_STOP */
                }
 
                return true;
@@ -964,19 +1294,17 @@ namespace smartcard_service_api
                guint channel_id, void *user_data)
        {
                int result;
+               const char *name;
 
                _INFO("[MSG_REQUEST_CLOSE_CHANNEL]");
 
                ServerResource &resource = ServerResource::getInstance();
 
-               const char *name = g_dbus_method_invocation_get_sender(invocation);
+               name = g_dbus_method_invocation_get_sender(invocation);
 
-               result = SCARD_ERROR_OK;
+               resource.removeChannel(name, service_id, channel_id);
 
-               if (resource.getChannel(name, service_id, channel_id) != NULL)
-               {
-                       resource.removeChannel(name, service_id, channel_id);
-               }
+               result = SCARD_ERROR_OK;
 
                /* response to client */
                smartcard_service_channel_complete_close_channel(object,
@@ -993,85 +1321,104 @@ namespace smartcard_service_api
                guint channel_id;
                void *user_data;
 
-               if (params.size() != 7) {
+               if (params.size() != 5) {
+                       /* LCOV_EXCL_START */
                        _ERR("invalid parameter");
 
                        return;
+                       /* LCOV_EXCL_STOP */
                }
 
                object = (SmartcardServiceChannel *)params[0];
                invocation = (GDBusMethodInvocation *)params[1];
-               service_id = (guint)params[2];
-               channel_id = (guint)params[3];
+               service_id = (gulong)params[2];
+               channel_id = (gulong)params[3];
                user_data = params[4];
 
                __process_close_channel(object, invocation, service_id,
                        channel_id, user_data);
+
+               g_object_unref(object);
+               g_object_unref(invocation);
        }
 
        static gboolean _handle_close_channel(SmartcardServiceChannel *object,
-               GDBusMethodInvocation *invocation, guint service_id,
-               guint channel_id, void *user_data)
+               GDBusMethodInvocation *invocation,
+               guint service_id, guint channel_id, void *user_data)
        {
                vector<void *> params;
 
-               g_object_ref(object);
-               params.push_back((void *)object);
+               /* apply user space smack */
+               if (_is_authorized_request(invocation) == true) {
+                       g_object_ref(object);
+                       params.push_back((void *)object);
 
-               g_object_ref(invocation);
-               params.push_back((void *)invocation);
+                       g_object_ref(invocation);
+                       params.push_back((void *)invocation);
 
-               params.push_back((void *)service_id);
-               params.push_back((void *)channel_id);
-               params.push_back(user_data);
+                       params.push_back((void *)service_id);
+                       params.push_back((void *)channel_id);
+                       params.push_back(user_data);
 
-               GDBusDispatcher::getInstance().push(_process_close_channel,
-                       params);
+                       GDBusDispatcher::push(_process_close_channel, params);
+               } else {
+                       /* LCOV_EXCL_START */
+                       _ERR("access denied");
+
+                       /* response to client */
+                       smartcard_service_channel_complete_close_channel(
+                               object,
+                               invocation,
+                               SCARD_ERROR_SECURITY_NOT_ALLOWED);
+                       /* LCOV_EXCL_STOP */
+               }
 
                return true;
        }
 
        static gboolean __process_transmit(SmartcardServiceChannel *object,
-               GDBusMethodInvocation *invocation, guint service_id,
-               guint channel_id, GVariant *command, void *user_data)
+               GDBusMethodInvocation *invocation,
+               guint service_id,
+               guint channel_id,
+               GVariant *command,
+               void *user_data)
        {
                int result;
                Channel *channel = NULL;
+               ByteArray resp;
                GVariant *response = NULL;
+               const char *name;
 
                _INFO("[MSG_REQUEST_TRANSMIT]");
 
                ServerResource &resource = ServerResource::getInstance();
 
-               const char *name = g_dbus_method_invocation_get_sender(invocation);
+               name = g_dbus_method_invocation_get_sender(invocation);
 
-               if ((channel = resource.getChannel(name, service_id, channel_id)) != NULL)
-               {
+               channel = resource.getChannel(name, service_id, channel_id);
+               /* LCOV_EXCL_START */
+               if (channel != NULL) {
                        int rv;
-                       ByteArray cmd, resp;
+                       ByteArray cmd;
 
                        GDBusHelper::convertVariantToByteArray(command, cmd);
 
-                       if ((rv = channel->transmitSync(cmd, resp)) == 0)
-                       {
-                               response = GDBusHelper::convertByteArrayToVariant(resp);
+                       rv = channel->transmitSync(cmd, resp);
+                       if (rv == 0) {
                                result = SCARD_ERROR_OK;
-                       }
-                       else
-                       {
+                       } else {
                                _ERR("transmit failed [%d]", rv);
+
                                result = rv;
                        }
-               }
-               else
-               {
+               } else {
                        _ERR("invalid handle : name [%s], service_id [%d], channel_id [%d]", name, service_id, channel_id);
+
                        result = SCARD_ERROR_UNAVAILABLE;
                }
+               /* LCOV_EXCL_STOP */
 
-               if (response == NULL) {
-                       response = GDBusHelper::convertByteArrayToVariant(ByteArray::EMPTY);
-               }
+               response = GDBusHelper::convertByteArrayToVariant(resp);
 
                /* response to client */
                smartcard_service_channel_complete_transmit(object, invocation,
@@ -1089,45 +1436,93 @@ namespace smartcard_service_api
                GVariant *command;
                void *user_data;
 
-               if (params.size() != 7) {
+               if (params.size() != 6) {
+                       /* LCOV_EXCL_START */
                        _ERR("invalid parameter");
 
                        return;
+                       /* LCOV_EXCL_STOP */
                }
 
                object = (SmartcardServiceChannel *)params[0];
                invocation = (GDBusMethodInvocation *)params[1];
-               service_id = (guint)params[2];
-               channel_id = (guint)params[3];
+               service_id = (gulong)params[2];
+               channel_id = (gulong)params[3];
                command = (GVariant *)params[4];
                user_data = params[5];
 
                __process_transmit(object, invocation, service_id,
                        channel_id, command, user_data);
+
+               g_object_unref(object);
+               g_object_unref(invocation);
+               g_object_unref(command);
+       }
+
+       static GVariant *_copy_variant(GVariant *src)
+       {
+               GVariantBuilder builder;
+
+               GVariantIter *iter;
+               guint8 element;
+               guint i;
+
+               g_variant_get(src, "a(y)", &iter);
+
+               g_variant_builder_init(&builder, G_VARIANT_TYPE("a(y)"));
+
+               for (i = 0; g_variant_iter_loop(iter, "(y)", &element); i++) {
+                       g_variant_builder_add(&builder, "(y)", element);
+               }
+
+               g_variant_iter_free(iter);
+
+               return g_variant_builder_end(&builder);
        }
 
        static gboolean _handle_transmit(SmartcardServiceChannel *object,
-               GDBusMethodInvocation *invocation, guint service_id,
-               guint channel_id, GVariant *command, void *user_data)
+               GDBusMethodInvocation *invocation,
+               guint service_id,
+               guint channel_id,
+               GVariant *command,
+               void *user_data)
        {
                vector<void *> params;
+               GVariant *_command;
 
-               g_object_ref(object);
-               params.push_back((void *)object);
+               _command = _copy_variant(command);
 
-               g_object_ref(invocation);
-               params.push_back((void *)invocation);
+               /* apply user space smack */
+               if (_is_authorized_request(invocation) == true) {
+                       /* enqueue message */
+                       g_object_ref(object);
+                       params.push_back((void *)object);
 
-               params.push_back((void *)service_id);
-               params.push_back((void *)channel_id);
+                       g_object_ref(invocation);
+                       params.push_back((void *)invocation);
 
-               g_object_ref(command);
-               params.push_back((void *)command);
+                       params.push_back((void *)service_id);
+                       params.push_back((void *)channel_id);
 
-               params.push_back(user_data);
+                       g_object_ref(_command);
+                       params.push_back((void *)_command);
 
-               GDBusDispatcher::getInstance().push(_process_transmit,
-                       params);
+                       params.push_back(user_data);
+
+                       GDBusDispatcher::push(_process_transmit, params);
+               } else {
+                       /* LCOV_EXCL_START */
+                       ByteArray resp;
+
+                       _ERR("access denied");
+
+                       /* response to client */
+                       smartcard_service_channel_complete_transmit(object,
+                               invocation,
+                               SCARD_ERROR_SECURITY_NOT_ALLOWED,
+                               GDBusHelper::convertByteArrayToVariant(resp));
+                       /* LCOV_EXCL_STOP */
+               }
 
                return true;
        }
@@ -1154,6 +1549,7 @@ namespace smartcard_service_api
                        "/org/tizen/SmartcardService/Channel",
                        &error) == false)
                {
+                       /* LCOV_EXCL_START */
                        _ERR("Can not skeleton_export %s", error->message);
 
                        g_error_free(error);
@@ -1161,6 +1557,7 @@ namespace smartcard_service_api
                        channel = NULL;
 
                        return false;
+                       /* LCOV_EXCL_STOP */
                }
 
                return true;
@@ -1174,4 +1571,3 @@ namespace smartcard_service_api
                }
        }
 } /* namespace smartcard_service_api */
-#endif