Add card Inserted implementation and fix bug
[platform/core/connectivity/smartcard-service.git] / server / ServerGDBus.cpp
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /* standard library header */
18 #include <unistd.h>
19 #include <glib.h>
20 #include <gio/gio.h>
21 #include <vector>
22 #include <string>
23 #include <sys/socket.h>
24
25 /* local header */
26 #include "smartcard-types.h"
27 #include "Debug.h"
28 #include "ByteArray.h"
29 #include "ServerResource.h"
30 #include "GDBusHelper.h"
31 #include "ServerGDBus.h"
32
33 #ifdef USE_CYNARA
34 #include "cynara-client.h"
35 #include "cynara-creds-gdbus.h"
36 #include "cynara-session.h"
37
38 #define SMARTCARD_PRIVILEGE "http://tizen.org/privilege/secureelement"
39 #endif
40
41 using namespace std;
42
43 #ifdef __PRIVATE
44 extern "C" bool smartcard_service_init_access_control(void *connection);
45 extern "C" void smartcard_service_deinit_access_control();
46 #endif
47
48 namespace smartcard_service_api
49 {
50         GDBusDispatcher::GDBusDispatcher() : Synchronous()
51         {
52         }
53
54         GDBusDispatcher::~GDBusDispatcher()
55         {
56         }
57
58         GDBusDispatcher &GDBusDispatcher::getInstance()
59         {
60                 static GDBusDispatcher dispatcher;
61
62                 return dispatcher;
63         }
64
65         void GDBusDispatcher::_push(dispatcher_cb_t cb,
66                 const vector<void *> &params)
67         {
68                 syncLock();
69
70                 q.push(make_pair(cb, params));
71                 _INFO("request pushed, count [%zu]", q.size());
72
73                 if (q.size() == 1) {
74                         /* start dispatch */
75                         _INFO("start dispatcher");
76                         g_idle_add(&GDBusDispatcher::dispatch, this);
77                 }
78
79                 syncUnlock();
80         }
81
82         void GDBusDispatcher::push(dispatcher_cb_t cb,
83                 const vector<void *> &params)
84         {
85                 GDBusDispatcher::getInstance()._push(cb, params);
86         }
87
88         gboolean GDBusDispatcher::dispatch(gpointer user_data)
89         {
90                 GDBusDispatcher *dispatcher = (GDBusDispatcher *)user_data;
91                 gboolean result = false;
92
93                 _BEGIN();
94
95                 dispatcher->syncLock();
96
97                 pair<dispatcher_cb_t, vector<void *> > &job =
98                         dispatcher->q.front();
99
100                 dispatcher->syncUnlock();
101
102                 job.first(job.second);
103
104                 dispatcher->syncLock();
105
106                 dispatcher->q.pop();
107                 /* LCOV_EXCL_START */
108                 if (dispatcher->q.size() > 0) {
109                         _INFO("remaining messages : %zu", dispatcher->q.size());
110
111                         result = true;
112                 /* LCOV_EXCL_STOP */
113                 } else {
114                         _INFO("dispatch finished");
115                 }
116
117                 dispatcher->syncUnlock();
118
119                 _END();
120
121                 return result;
122         }
123
124         ServerGDBus::ServerGDBus() : dbus_proxy(NULL), connection(NULL),
125                 seService(NULL), reader(NULL), session(NULL), channel(NULL)
126         {
127         }
128
129         ServerGDBus::~ServerGDBus()
130         {
131                 deinit();
132         }
133
134         ServerGDBus &ServerGDBus::getInstance()
135         {
136                 static ServerGDBus serverGDBus;
137
138                 return serverGDBus;
139         }
140
141         static void name_owner_changed(GDBusProxy *proxy,
142                 const gchar *name, const gchar *old_owner,
143                 const gchar *new_owner, void *user_data)
144         {
145                 /* LCOV_EXCL_START */
146                 if (name == NULL || old_owner == NULL || new_owner == NULL) {
147                         _ERR("invalid parameter");
148                         return;
149                 }
150                 /* LCOV_EXCL_STOP */
151                 if (strlen(new_owner) == 0) {
152                         ClientInstance *client;
153
154                         ServerResource &resource = ServerResource::getInstance();
155
156                         client = resource.getClient(old_owner);
157                         if (client != NULL) {
158                                 _INFO("terminated client, pid [%d]", client->getPID());
159                                 resource.removeClient(old_owner);
160
161                                 resource.finish();
162                         }
163                 }
164         }
165
166         static void _on_name_owner_changed(GDBusConnection *connection,
167                 const gchar *sender_name, const gchar *object_path,
168                 const gchar *interface_name, const gchar *signal_name,
169                 GVariant *parameters, gpointer user_data)
170         {
171                 gchar *name;
172                 gchar *old_owner;
173                 gchar *new_owner;
174
175                 g_variant_get(parameters,
176                         "(sss)",
177                         &name,
178                         &old_owner,
179                         &new_owner);
180
181                 name_owner_changed((GDBusProxy *)connection,
182                         name, old_owner, new_owner, user_data);
183
184                 g_free(name);
185                 g_free(old_owner);
186                 g_free(new_owner);
187         }
188
189         bool ServerGDBus::_init()
190         {
191                 GError *error = NULL;
192
193                 /* init default context */
194                 dbus_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
195                         G_DBUS_PROXY_FLAGS_NONE,
196                         NULL, /* GDBusInterfaceInfo */
197                         "org.freedesktop.DBus",
198                         "/org/freedesktop/DBus",
199                         "org.freedesktop.DBus",
200                         NULL, /* GCancellable */
201                         &error);
202                 if (dbus_proxy == NULL)
203                 {
204                         /* LCOV_EXCL_START */
205                         _ERR("Can not create proxy : %s", error->message);
206                         g_error_free(error);
207
208                         return false;
209                         /* LCOV_EXCL_STOP */
210                 }
211
212                 /* subscribe signal */
213                 g_dbus_connection_signal_subscribe(connection,
214                         "org.freedesktop.DBus", /* bus name */
215                         "org.freedesktop.DBus", /* interface */
216                         "NameOwnerChanged", /* member */
217                         "/org/freedesktop/DBus", /* path */
218                         NULL, /* arg0 */
219                         G_DBUS_SIGNAL_FLAGS_NONE,
220                         _on_name_owner_changed,
221                         NULL, NULL);
222
223                 return true;
224         }
225
226         void ServerGDBus::_deinit()
227         {
228                 if (dbus_proxy != NULL) {
229                         g_object_unref(dbus_proxy);
230                         dbus_proxy = NULL;
231                 }
232         }
233
234         bool ServerGDBus::init()
235         {
236                 GError *error = NULL;
237
238                 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
239                 if (connection != NULL) {
240                 /* LCOV_EXCL_START */
241                 } else {
242                         _ERR("Can not get connection %s", error->message);
243                         g_error_free(error);
244
245                         return false;
246                 }
247                 /* LCOV_EXCL_STOP */
248
249                 _init();
250
251                 initSEService();
252                 initReader();
253                 initSession();
254                 initChannel();
255 #ifdef __PRIVATE
256                 smartcard_service_init_access_control(connection);
257 #endif
258                 return true;
259         }
260
261         void ServerGDBus::deinit()
262         {
263 #ifdef __PRIVATE
264                 smartcard_service_deinit_access_control();
265 #endif
266                 deinitChannel();
267                 deinitSession();
268                 deinitReader();
269                 deinitSEService();
270
271                 _deinit();
272
273                 if (connection != NULL) {
274                         g_object_unref(connection);
275                         connection = NULL;
276                 }
277         }
278
279         static gboolean _call_get_connection_unix_process_id_sync(
280                 GDBusProxy *proxy, const gchar *arg_name, guint *out_pid,
281                 GCancellable *cancellable, GError **error) {
282                 GVariant *_ret;
283
284                 _ret = g_dbus_proxy_call_sync(proxy,
285                         "GetConnectionUnixProcessID",
286                         g_variant_new("(s)", arg_name),
287                         G_DBUS_CALL_FLAGS_NONE,
288                         -1, cancellable, error);
289                 if (_ret != NULL) {
290                         g_variant_get(_ret, "(u)", out_pid);
291                         g_variant_unref(_ret);
292                 }
293
294                 return _ret != NULL;
295         }
296
297         pid_t ServerGDBus::getPID(const char *name)
298         {
299                 guint pid = 0;
300                 GError *error = NULL;
301
302                 if (_call_get_connection_unix_process_id_sync(
303                         (GDBusProxy *)dbus_proxy, name,
304                         &pid, NULL, &error) == true) {
305                 /* LCOV_EXCL_START */
306                 } else {
307                         _ERR("_g_freedesktop_dbus_call_get_connection_unix_process_id_sync failed  : %s", error->message);
308                         g_error_free(error);
309                 }
310                 /* LCOV_EXCL_STOP */
311
312                 return pid;
313         }
314
315 #ifdef USE_CYNARA
316         static bool _get_credentials(GDBusMethodInvocation *invocation)
317         {
318                 int ret = 0;
319                 int pid = 0;
320                 char *user;
321                 char *client;
322                 char *client_session;
323                 cynara *p_cynara = NULL;
324                 const char *sender_unique_name;
325                 GDBusConnection *connection;
326
327                 connection = g_dbus_method_invocation_get_connection(invocation);
328                 sender_unique_name = g_dbus_method_invocation_get_sender(invocation);
329
330                 pid = ServerGDBus::getInstance().getPID(sender_unique_name);
331
332                 ret = cynara_initialize(&p_cynara, NULL);
333                 /* LCOV_EXCL_START */
334                 if (ret != CYNARA_API_SUCCESS) {
335                         _ERR("cynara_initialize() failed");
336                         return false;
337                 }
338                 /* LCOV_EXCL_STOP */
339
340                 ret = cynara_creds_gdbus_get_user(connection, sender_unique_name, USER_METHOD_DEFAULT, &user);
341                 /* LCOV_EXCL_START */
342                 if (ret != CYNARA_API_SUCCESS) {
343                         _ERR("cynara_creds_gdbus_get_user() failed");
344                         return false;
345                 }
346                 /* LCOV_EXCL_STOP */
347
348                 ret = cynara_creds_gdbus_get_client(connection, sender_unique_name, CLIENT_METHOD_DEFAULT, &client);
349                 /* LCOV_EXCL_START */
350                 if (ret != CYNARA_API_SUCCESS) {
351                         _ERR("cynara_creds_gdbus_get_client() failed");
352                         g_free(user);
353                         return false;
354                 }
355                 /* LCOV_EXCL_STOP */
356
357                 _ERR("user :%s , client :%s ,unique_name : %s, pid() : %d", user, client, sender_unique_name, pid);
358
359                 client_session = cynara_session_from_pid(pid);
360
361                 /* LCOV_EXCL_START */
362                 if (!client_session) {
363                         _ERR("cynara_session_from_pid() failed");
364                         g_free(client);
365                         g_free(user);
366                         return false;
367                 }
368                 /* LCOV_EXCL_STOP */
369
370                 ret = cynara_check(p_cynara, client, client_session, user, SMARTCARD_PRIVILEGE);
371                 if ( ret == CYNARA_API_ACCESS_ALLOWED ) {
372                         _INFO("cynara PASS");
373                 }
374
375                 g_free(client_session);
376                 g_free(client);
377                 g_free(user);
378
379                 if (p_cynara) {
380                         cynara_finish(p_cynara);
381                         p_cynara = NULL;
382                 }
383
384                 return (ret == CYNARA_API_ACCESS_ALLOWED ) ? true : false;
385         }
386 #endif
387
388         static bool _is_authorized_request(GDBusMethodInvocation *invocation)
389         {
390                 bool result = false;
391
392 #ifdef USE_CYNARA
393                 result = _get_credentials(invocation);
394 #endif
395
396                 _ERR("api security check result : %d", result);
397
398                 return result;
399         }
400
401         /* SEService *
402          *
403          *
404          */
405         static GVariant *_reader_to_variant(
406                 vector<pair<unsigned int, string> > &readers)
407         {
408                 GVariantBuilder builder;
409                 uint32_t i;
410
411                 g_variant_builder_init(&builder, G_VARIANT_TYPE("a(us)"));
412
413                 for (i = 0; i < readers.size(); i++) {
414                         g_variant_builder_add(&builder, "(us)",
415                                 readers[i].first, readers[i].second.c_str());
416                 }
417
418                 return g_variant_builder_end(&builder);
419         }
420
421         static gboolean __process_se_service(SmartcardServiceSeService *object,
422                 GDBusMethodInvocation *invocation,
423                 void *user_data)
424         {
425                 gint result = SCARD_ERROR_OK;
426                 GVariant *readers = NULL;
427                 vector<pair<unsigned int, string> > list;
428                 unsigned int handle = IntegerHandle::INVALID_HANDLE;
429                 const char *name;
430                 pid_t pid;
431
432                 _INFO("[MSG_REQUEST_READERS]");
433
434                 ServerResource &resource = ServerResource::getInstance();
435
436                 name = g_dbus_method_invocation_get_sender(invocation);
437
438                 /* load secure elements */
439                 resource.loadSecureElements();
440
441                 pid = ServerGDBus::getInstance().getPID(name);
442
443                 _DBG("service requested, pid [%d]", pid);
444
445                 if (pid > 0) {
446                         ClientInstance *instance;
447
448                         instance = resource.getClient(name);
449                         if (instance == NULL) {
450                                 _INFO("create client instance, pid [%d]", pid);
451
452                                 resource.createClient(name, pid);
453
454                                 instance = resource.getClient(name);
455                                 if (instance != NULL) {
456                                         /* generate certification hashes */
457                                         instance->generateCertificationHashes();
458                                 } else {
459                                         _ERR("createClient failed"); /* LCOV_EXCL_LINE */
460                                 }
461                         }
462
463                         if (instance != NULL) {
464                                 ServiceInstance *service;
465
466                                 /* create service */
467                                 service = resource.createService(name);
468                                 if (service != NULL) {
469                                         handle = service->getHandle();
470                                         resource.getReaders(list);
471
472                                         if (list.size() == 0) {
473                                                 _INFO("no secure elements");
474                                         }
475                                 /* LCOV_EXCL_START */
476                                 } else {
477                                         _ERR("createService failed");
478
479                                         result = SCARD_ERROR_OUT_OF_MEMORY;
480                                 }
481                         } else {
482                                 _ERR("client doesn't exist, pid [%d]", pid);
483
484                                 result = SCARD_ERROR_OUT_OF_MEMORY;
485                         }
486                 } else {
487                         _ERR("invalid pid, [%d]", pid);
488
489                         result = SCARD_ERROR_IPC_FAILED;
490                 }
491                 /* LCOV_EXCL_STOP */
492
493                 readers = _reader_to_variant(list);
494
495                 /* response to client */
496                 smartcard_service_se_service_complete_se_service(object,
497                         invocation, result, handle, readers);
498
499                 return true;
500         }
501
502         static void _process_se_service(vector<void *> &params)
503         {
504                 SmartcardServiceSeService *object;
505                 GDBusMethodInvocation *invocation;
506                 void *user_data;
507
508                 /* LCOV_EXCL_START */
509                 if (params.size() != 3) {
510                         _ERR("invalid parameter");
511
512                         return;
513                 }
514                 /* LCOV_EXCL_STOP */
515
516                 object = (SmartcardServiceSeService *)params[0];
517                 invocation = (GDBusMethodInvocation *)params[1];
518                 user_data = params[2];
519
520                 __process_se_service(object, invocation, user_data);
521
522                 g_object_unref(object);
523                 g_object_unref(invocation);
524         }
525
526         static gboolean _handle_se_service(SmartcardServiceSeService *object,
527                 GDBusMethodInvocation *invocation,
528                 void *user_data)
529         {
530                 vector<void *> params;
531
532                 /* apply user space smack */
533                 if (_is_authorized_request(invocation) == true) {
534                         g_object_ref(object);
535                         params.push_back((void *)object);
536
537                         g_object_ref(invocation);
538                         params.push_back((void *)invocation);
539
540                         params.push_back((void *)user_data);
541
542                         GDBusDispatcher::push(_process_se_service, params);
543                 /* LCOV_EXCL_START */
544                 } else {
545                         vector<pair<unsigned int, string> > list;
546
547                         _ERR("access denied");
548
549                         /* response to client */
550                         smartcard_service_se_service_complete_se_service(object,
551                                 invocation,
552                                 SCARD_ERROR_SECURITY_NOT_ALLOWED,
553                                 IntegerHandle::INVALID_HANDLE,
554                                 _reader_to_variant(list));
555                 }
556                 /* LCOV_EXCL_STOP */
557
558                 return true;
559         }
560
561         static gboolean __process_shutdown(SmartcardServiceSeService *object,
562                 GDBusMethodInvocation *invocation,
563                 guint handle, void *user_data)
564         {
565                 const char *name;
566
567                 _INFO("[MSG_REQUEST_SHUTDOWN]");
568
569                 ServerResource &resource = ServerResource::getInstance();
570
571                 name = g_dbus_method_invocation_get_sender(invocation);
572
573                 resource.removeService(name, handle);
574
575                 /* response to client */
576                 smartcard_service_se_service_complete_shutdown(object,
577                         invocation, SCARD_ERROR_OK);
578
579                 /* terminate */
580                 resource.finish();
581
582                 return true;
583         }
584
585         static void _process_shutdown(vector<void *> &params)
586         {
587                 SmartcardServiceSeService *object;
588                 GDBusMethodInvocation *invocation;
589                 guint handle;
590                 void *user_data;
591
592                 /* LCOV_EXCL_START */
593                 if (params.size() != 4) {
594                         _ERR("invalid parameter");
595
596                         return;
597                 }
598                 /* LCOV_EXCL_STOP */
599
600                 object = (SmartcardServiceSeService *)params[0];
601                 invocation = (GDBusMethodInvocation *)params[1];
602                 handle = (gulong)params[2];
603                 user_data = params[3];
604
605                 __process_shutdown(object, invocation, handle, user_data);
606
607                 g_object_unref(object);
608                 g_object_unref(invocation);
609         }
610
611         static gboolean _handle_shutdown(SmartcardServiceSeService *object,
612                 GDBusMethodInvocation *invocation,
613                 guint handle,
614                 void *user_data)
615         {
616                 vector<void *> params;
617
618                 /* apply user space smack */
619                 if (_is_authorized_request(invocation) == true) {
620                         g_object_ref(object);
621                         params.push_back((void *)object);
622
623                         g_object_ref(invocation);
624                         params.push_back((void *)invocation);
625
626                         params.push_back((void *)handle);
627                         params.push_back(user_data);
628
629                         GDBusDispatcher::push(_process_shutdown, params);
630                 /* LCOV_EXCL_START */
631                 } else {
632                         _ERR("access denied");
633
634                         /* response to client */
635                         smartcard_service_se_service_complete_shutdown(object,
636                                 invocation, SCARD_ERROR_SECURITY_NOT_ALLOWED);
637                 }
638                 /* LCOV_EXCL_STOP */
639
640                 return true;
641         }
642
643         bool ServerGDBus::initSEService()
644         {
645                 GError *error = NULL;
646
647                 seService = smartcard_service_se_service_skeleton_new();
648
649                 g_signal_connect(seService,
650                         "handle-se-service",
651                         G_CALLBACK(_handle_se_service),
652                         this);
653
654                 g_signal_connect(seService,
655                         "handle-shutdown",
656                         G_CALLBACK(_handle_shutdown),
657                         this);
658
659                 /* LCOV_EXCL_START */
660                 if (g_dbus_interface_skeleton_export(
661                         G_DBUS_INTERFACE_SKELETON(seService),
662                         connection,
663                         "/org/tizen/SmartcardService/SeService",
664                         &error) == false)
665                 {
666                         _ERR("Can not skeleton_export %s", error->message);
667
668                         g_error_free(error);
669                         g_object_unref(seService);
670                         seService = NULL;
671
672                         return false;
673                 }
674                 /* LCOV_EXCL_STOP */
675
676                 return true;
677         }
678
679         void ServerGDBus::deinitSEService()
680         {
681                 if (seService != NULL) {
682                         g_object_unref(seService);
683                         seService = NULL;
684                 }
685         }
686
687         void ServerGDBus::emitReaderInserted(unsigned int reader_id,
688                 const char *reader_name)
689         {
690                 /* LCOV_EXCL_START */
691                 smartcard_service_se_service_emit_reader_inserted(
692                         SMARTCARD_SERVICE_SE_SERVICE(seService),
693                         reader_id, reader_name);
694                 /* LCOV_EXCL_STOP */
695         }
696
697         void ServerGDBus::emitReaderRemoved(unsigned int reader_id,
698                 const char *reader_name)
699         {
700                 /* LCOV_EXCL_START */
701                 smartcard_service_se_service_emit_reader_removed(
702                         SMARTCARD_SERVICE_SE_SERVICE(seService),
703                         reader_id, reader_name);
704                 /* LCOV_EXCL_STOP */
705         }
706
707         void ServerGDBus::emitCardInserted(unsigned int reader_id,
708                 const char *reader_name)
709         {
710                 /* LCOV_EXCL_START */
711                 smartcard_service_se_service_emit_card_inserted(
712                         SMARTCARD_SERVICE_SE_SERVICE(seService),
713                         reader_id, reader_name);
714                 /* LCOV_EXCL_STOP */
715         }
716
717         void ServerGDBus::emitCardRemoved(unsigned int reader_id,
718                 const char *reader_name)
719         {
720                 /* LCOV_EXCL_START */
721                 smartcard_service_se_service_emit_card_removed(
722                         SMARTCARD_SERVICE_SE_SERVICE(seService),
723                         reader_id, reader_name);
724                 /* LCOV_EXCL_STOP */
725         }
726
727         /* Reader *
728          *
729          *
730          */
731         static gboolean __process_open_session(SmartcardServiceReader *object,
732                 GDBusMethodInvocation *invocation, guint service_id,
733                 guint reader_id, void *user_data)
734         {
735                 unsigned int handle = IntegerHandle::INVALID_HANDLE;
736                 int result;
737                 const char *name;
738
739                 _INFO("[MSG_REQUEST_OPEN_SESSION]");
740
741                 ServerResource &resource = ServerResource::getInstance();
742
743                 name = g_dbus_method_invocation_get_sender(invocation);
744
745                 if (resource.isValidReaderHandle(reader_id)) {
746                         vector<ByteArray> temp;
747
748                         handle = resource.createSession(name,
749                                 service_id,
750                                 reader_id,
751                                 temp,
752                                 (void *)NULL);
753                         if (handle != IntegerHandle::INVALID_HANDLE) {
754                                 result = SCARD_ERROR_OK;
755                         } else {
756                                 /* LCOV_EXCL_START */
757                                 _ERR("createSession failed [%d]", handle);
758
759                                 result = SCARD_ERROR_OUT_OF_MEMORY;
760                         }
761                 } else {
762                         _ERR("request invalid reader handle [%d]", reader_id);
763
764                         result = SCARD_ERROR_ILLEGAL_PARAM;
765                         /* LCOV_EXCL_STOP */
766                 }
767
768                 /* response to client */
769                 smartcard_service_reader_complete_open_session(object,
770                         invocation, result, handle);
771
772                 return true;
773         }
774
775         static void _process_open_session(vector<void *> &params)
776         {
777                 SmartcardServiceReader *object;
778                 GDBusMethodInvocation *invocation;
779                 guint service_id;
780                 guint reader_id;
781                 void *user_data;
782
783                 if (params.size() != 5) {
784                         /* LCOV_EXCL_START */
785                         _ERR("invalid parameter");
786
787                         return;
788                         /* LCOV_EXCL_STOP */
789                 }
790
791                 object = (SmartcardServiceReader *)params[0];
792                 invocation = (GDBusMethodInvocation *)params[1];
793                 service_id = (gulong)params[2];
794                 reader_id = (gulong)params[3];
795                 user_data = params[4];
796
797                 __process_open_session(object, invocation, service_id,
798                         reader_id, user_data);
799
800                 g_object_unref(object);
801                 g_object_unref(invocation);
802         }
803
804         static gboolean _handle_open_session(SmartcardServiceReader *object,
805                 GDBusMethodInvocation *invocation,
806                 guint service_id,
807                 guint reader_id, void *user_data)
808         {
809                 vector<void *> params;
810
811                 /* apply user space smack */
812                 if (_is_authorized_request(invocation) == true) {
813                         g_object_ref(object);
814                         params.push_back((void *)object);
815
816                         g_object_ref(invocation);
817                         params.push_back((void *)invocation);
818
819                         params.push_back((void *)service_id);
820                         params.push_back((void *)reader_id);
821                         params.push_back(user_data);
822
823                         GDBusDispatcher::push(_process_open_session, params);
824                 } else {
825                         /* LCOV_EXCL_START */
826                         _ERR("access denied");
827
828                         /* response to client */
829                         smartcard_service_reader_complete_open_session(object,
830                                 invocation,
831                                 SCARD_ERROR_SECURITY_NOT_ALLOWED,
832                                 IntegerHandle::INVALID_HANDLE);
833                         /* LCOV_EXCL_STOP */
834                 }
835
836                 return true;
837         }
838
839         bool ServerGDBus::initReader()
840         {
841                 GError *error = NULL;
842
843                 reader = smartcard_service_reader_skeleton_new();
844
845                 g_signal_connect(reader,
846                         "handle-open-session",
847                         G_CALLBACK(_handle_open_session),
848                         this);
849
850                 if (g_dbus_interface_skeleton_export(
851                         G_DBUS_INTERFACE_SKELETON(reader),
852                         connection,
853                         "/org/tizen/SmartcardService/Reader",
854                         &error) == false)
855                 {
856                         /* LCOV_EXCL_START */
857                         _ERR("Can not skeleton_export %s", error->message);
858
859                         g_error_free(error);
860                         g_object_unref(reader);
861                         reader = NULL;
862
863                         return false;
864                         /* LCOV_EXCL_STOP */
865                 }
866
867                 return true;
868         }
869
870         void ServerGDBus::deinitReader()
871         {
872         /* LCOV_EXCL_START */
873                 if (reader != NULL) {
874                         g_object_unref(reader);
875                         reader = NULL;
876                 }
877         /* LCOV_EXCL_STOP */
878         }
879
880         /* Session *
881          *
882          *
883          */
884         static gboolean __process_close_session(SmartcardServiceSession *object,
885                 GDBusMethodInvocation *invocation, guint service_id,
886                 guint session_id, void *user_data)
887         {
888                 const char *name;
889
890                 _INFO("[MSG_REQUEST_CLOSE_SESSION]");
891
892                 ServerResource &resource = ServerResource::getInstance();
893
894                 name = g_dbus_method_invocation_get_sender(invocation);
895
896                 if (resource.isValidSessionHandle(name, service_id,
897                         session_id)) {
898                         resource.removeSession(name, service_id,
899                                 session_id);
900                 } else {
901                         _ERR("invalid parameters"); //LCOV_EXCL_LINE
902                 }
903
904                 /* response to client */
905                 smartcard_service_session_complete_close_session(object,
906                         invocation, SCARD_ERROR_OK);
907
908                 return true;
909         }
910
911         static void _process_close_session(vector<void *> &params)
912         {
913                 SmartcardServiceSession *object;
914                 GDBusMethodInvocation *invocation;
915                 guint service_id;
916                 guint session_id;
917                 void *user_data;
918
919                 if (params.size() != 5) {
920                         /* LCOV_EXCL_START */
921                         _ERR("invalid parameter");
922
923                         return;
924                         /* LCOV_EXCL_STOP */
925                 }
926
927                 object = (SmartcardServiceSession *)params[0];
928                 invocation = (GDBusMethodInvocation *)params[1];
929                 service_id = (gulong)params[2];
930                 session_id = (gulong)params[3];
931                 user_data = params[4];
932
933                 __process_close_session(object, invocation, service_id,
934                         session_id, user_data);
935
936                 g_object_unref(object);
937                 g_object_unref(invocation);
938         }
939
940         static gboolean _handle_close_session(SmartcardServiceSession *object,
941                 GDBusMethodInvocation *invocation,
942                 guint service_id,
943                 guint session_id, void *user_data)
944         {
945                 vector<void *> params;
946
947                 /* apply user space smack */
948                 if (_is_authorized_request(invocation) == true) {
949                         g_object_ref(object);
950                         params.push_back((void *)object);
951
952                         g_object_ref(invocation);
953                         params.push_back((void *)invocation);
954
955                         params.push_back((void *)service_id);
956                         params.push_back((void *)session_id);
957                         params.push_back(user_data);
958
959                         GDBusDispatcher::push(_process_close_session, params);
960                 } else {
961                         /* LCOV_EXCL_START */
962                         _ERR("access denied");
963
964                         /* response to client */
965                         smartcard_service_session_complete_close_session(object,
966                                 invocation, SCARD_ERROR_SECURITY_NOT_ALLOWED);
967                         /* LCOV_EXCL_STOP */
968                 }
969
970                 return true;
971         }
972
973         static gboolean __process_get_atr(SmartcardServiceSession *object,
974                 GDBusMethodInvocation *invocation, guint service_id,
975                 guint session_id, void *user_data)
976         {
977                 int result;
978                 ByteArray resp;
979                 GVariant *atr = NULL;
980                 const char *name;
981                 ServiceInstance *client = NULL;
982
983                 _INFO("[MSG_REQUEST_GET_ATR]");
984
985                 ServerResource &resource = ServerResource::getInstance();
986
987                 name = g_dbus_method_invocation_get_sender(invocation);
988
989                 client = resource.getService(name, service_id);
990                 /* LCOV_EXCL_START */
991                 if (client != NULL) {
992                         Terminal *terminal;
993
994                         terminal = client->getTerminal(session_id);
995                         if (terminal != NULL) {
996                                 if (terminal->open() == true) {
997                                         result = terminal->getATRSync(resp);
998                                         if (result < SCARD_ERROR_OK) {
999                                                 _ERR("getATRSync failed : name [%s], service_id [%d], session_id [%d]", name, service_id, session_id);
1000                                         }
1001
1002                                         terminal->close();
1003                                 } else {
1004                                         _ERR("terminal->open failed");
1005
1006                                         result = SCARD_ERROR_UNAVAILABLE;
1007                                 }
1008                         } else {
1009                                 _ERR("getTerminal failed : name [%s], service_id [%d], session_id [%d]", name, service_id, session_id);
1010
1011                                 result = SCARD_ERROR_UNAVAILABLE;
1012                         }
1013                 } else {
1014                         _ERR("getClient failed : name [%s], service_id [%d], session_id [%d]", name, service_id, session_id);
1015
1016                         result = SCARD_ERROR_UNAVAILABLE;
1017                 }
1018                 /* LCOV_EXCL_STOP */
1019
1020                 atr = GDBusHelper::convertByteArrayToVariant(resp);
1021
1022                 /* response to client */
1023                 smartcard_service_session_complete_get_atr(object, invocation,
1024                         result, atr);
1025
1026                 return true;
1027         }
1028
1029         static void _process_get_atr(vector<void *> &params)
1030         {
1031                 SmartcardServiceSession *object;
1032                 GDBusMethodInvocation *invocation;
1033                 guint service_id;
1034                 guint session_id;
1035                 void *user_data;
1036
1037                 if (params.size() != 5) {
1038         /* LCOV_EXCL_START */
1039                         _ERR("invalid parameter");
1040
1041                         return;
1042         /* LCOV_EXCL_STOP */
1043                 }
1044
1045                 object = (SmartcardServiceSession *)params[0];
1046                 invocation = (GDBusMethodInvocation *)params[1];
1047                 service_id = (gulong)params[2];
1048                 session_id = (gulong)params[3];
1049                 user_data = params[4];
1050
1051                 __process_get_atr(object, invocation, service_id,
1052                         session_id, user_data);
1053
1054                 g_object_unref(object);
1055                 g_object_unref(invocation);
1056         }
1057
1058         static gboolean _handle_get_atr(SmartcardServiceSession *object,
1059                 GDBusMethodInvocation *invocation,
1060                 guint service_id,
1061                 guint session_id, void *user_data)
1062         {
1063                 vector<void *> params;
1064
1065                 /* apply user space smack */
1066                 if (_is_authorized_request(invocation) == true) {
1067                         g_object_ref(object);
1068                         params.push_back((void *)object);
1069
1070                         g_object_ref(invocation);
1071                         params.push_back((void *)invocation);
1072
1073                         params.push_back((void *)service_id);
1074                         params.push_back((void *)session_id);
1075                         params.push_back(user_data);
1076
1077                         GDBusDispatcher::push(_process_get_atr, params);
1078                 } else {
1079                         /* LCOV_EXCL_START */
1080                         ByteArray resp;
1081
1082                         _ERR("access denied");
1083
1084                         /* response to client */
1085                         smartcard_service_session_complete_get_atr(
1086                                 object,
1087                                 invocation,
1088                                 SCARD_ERROR_SECURITY_NOT_ALLOWED,
1089                                 GDBusHelper::convertByteArrayToVariant(resp));
1090                         /* LCOV_EXCL_STOP */
1091                 }
1092
1093                 return true;
1094         }
1095
1096         static gboolean __process_open_channel(SmartcardServiceSession *object,
1097                 GDBusMethodInvocation *invocation, guint service_id,
1098                 guint session_id, guint type, GVariant *aid, guint8 P2, void *user_data)
1099         {
1100                 int channelNum = -1;
1101                 int result = SCARD_ERROR_UNKNOWN;
1102                 ByteArray resp;
1103                 GVariant *response = NULL;
1104                 unsigned int channelID = IntegerHandle::INVALID_HANDLE;
1105                 const char *name;
1106
1107                 _INFO("[MSG_REQUEST_OPEN_CHANNEL]");
1108                 _INFO("P2 is %x", P2);
1109
1110                 ServerResource &resource = ServerResource::getInstance();
1111
1112                 name = g_dbus_method_invocation_get_sender(invocation);
1113
1114                 try
1115                 {
1116                         ByteArray tempAid;
1117
1118                         GDBusHelper::convertVariantToByteArray(aid,
1119                                 tempAid);
1120
1121                         channelID = resource.createChannel(name,
1122                                 service_id, session_id, type, tempAid);
1123                         /* LCOV_EXCL_START */
1124                         if (channelID != IntegerHandle::INVALID_HANDLE) {
1125                                 ServerChannel *temp;
1126
1127                                 temp = (ServerChannel *)resource.getChannel(
1128                                         name, service_id, channelID);
1129                                 if (temp != NULL) {
1130                                         resp = temp->getSelectResponse();
1131                                         channelNum = temp->getChannelNumber();
1132                                         result = SCARD_ERROR_OK;
1133                                 } else {
1134                                         _ERR("getChannel is failed");
1135                                         result = SCARD_ERROR_UNAVAILABLE;
1136                                 }
1137                         } else {
1138                                 _ERR("channel is null.");
1139
1140                                 /* set error value */
1141                                 result = SCARD_ERROR_UNAVAILABLE;
1142                         }
1143                         /* LCOV_EXCL_STOP */
1144                 }
1145                 catch (ExceptionBase &e)
1146                 {
1147                         result = e.getErrorCode();
1148                 }
1149
1150                 response = GDBusHelper::convertByteArrayToVariant(resp);
1151
1152                 /* response to client */
1153                 smartcard_service_session_complete_open_channel(object,
1154                         invocation, result, channelID, channelNum, response);
1155
1156                 return true;
1157         }
1158
1159         static void _process_open_channel(vector<void *> &params)
1160         {
1161                 SmartcardServiceSession *object;
1162                 GDBusMethodInvocation *invocation;
1163                 guint service_id;
1164                 guint session_id;
1165                 guint type;
1166                 guint8 P2;
1167                 GVariant *aid;
1168                 void *user_data;
1169
1170                 if (params.size() != 8) {
1171                         /* LCOV_EXCL_START */
1172                         _ERR("invalid parameter");
1173
1174                         return;
1175                         /* LCOV_EXCL_STOP */
1176                 }
1177
1178                 object = (SmartcardServiceSession *)params[0];
1179                 invocation = (GDBusMethodInvocation *)params[1];
1180                 service_id = (gulong)params[2];
1181                 session_id = (gulong)params[3];
1182                 type = (gulong)params[4];
1183                 aid = (GVariant *)params[5];
1184                 P2 = (guint8)((gulong)params[6]);
1185                 user_data = params[7];
1186
1187                 __process_open_channel(object, invocation, service_id,
1188                         session_id, type, aid, P2, user_data);
1189
1190                 g_object_unref(object);
1191                 g_object_unref(invocation);
1192                 g_variant_unref(aid);
1193         }
1194
1195         static gboolean _handle_open_channel(SmartcardServiceSession *object,
1196                 GDBusMethodInvocation *invocation,
1197                 guint service_id,
1198                 guint session_id, guint type, GVariant *aid, guint8 P2, void *user_data)
1199         {
1200                 vector<void *> params;
1201
1202                 /* apply user space smack */
1203                 if (_is_authorized_request(invocation) == true) {
1204                         g_object_ref(object);
1205                         params.push_back((void *)object);
1206
1207                         g_object_ref(invocation);
1208                         params.push_back((void *)invocation);
1209
1210                         params.push_back((void *)service_id);
1211                         params.push_back((void *)session_id);
1212                         params.push_back((void *)type);
1213
1214                         g_variant_ref(aid);
1215                         params.push_back((void *)aid);
1216                         params.push_back((void *)((int)P2));
1217                         params.push_back(user_data);
1218
1219                         GDBusDispatcher::push(_process_open_channel, params);
1220                 } else {
1221                         /* LCOV_EXCL_START */
1222                         ByteArray resp;
1223
1224                         _ERR("access denied");
1225
1226                         /* response to client */
1227                         smartcard_service_session_complete_open_channel(object,
1228                                 invocation,
1229                                 SCARD_ERROR_SECURITY_NOT_ALLOWED,
1230                                 IntegerHandle::INVALID_HANDLE,
1231                                 -1,
1232                                 GDBusHelper::convertByteArrayToVariant(resp));
1233                         /* LCOV_EXCL_STOP */
1234                 }
1235
1236                 return true;
1237         }
1238
1239         bool ServerGDBus::initSession()
1240         {
1241                 GError *error = NULL;
1242
1243                 session = smartcard_service_session_skeleton_new();
1244
1245                 g_signal_connect(session,
1246                         "handle-close-session",
1247                         G_CALLBACK(_handle_close_session),
1248                         this);
1249
1250                 g_signal_connect(session,
1251                         "handle-get-atr",
1252                         G_CALLBACK(_handle_get_atr),
1253                         this);
1254
1255                 g_signal_connect(session,
1256                         "handle-open-channel",
1257                         G_CALLBACK(_handle_open_channel),
1258                         this);
1259
1260                 if (g_dbus_interface_skeleton_export(
1261                         G_DBUS_INTERFACE_SKELETON(session),
1262                         connection,
1263                         "/org/tizen/SmartcardService/Session",
1264                         &error) == false)
1265                 {
1266                         /* LCOV_EXCL_START */
1267                         _ERR("Can not skeleton_export %s", error->message);
1268
1269                         g_error_free(error);
1270                         g_object_unref(session);
1271                         session = NULL;
1272
1273                         return false;
1274                         /* LCOV_EXCL_STOP */
1275                 }
1276
1277                 return true;
1278         }
1279
1280         void ServerGDBus::deinitSession()
1281         {
1282                 if (session != NULL) {
1283                         g_object_unref(session);
1284                         session = NULL;
1285                 }
1286         }
1287
1288         /* Channel *
1289          *
1290          *
1291          */
1292         static gboolean __process_close_channel(SmartcardServiceChannel *object,
1293                 GDBusMethodInvocation *invocation, guint service_id,
1294                 guint channel_id, void *user_data)
1295         {
1296                 int result;
1297                 const char *name;
1298
1299                 _INFO("[MSG_REQUEST_CLOSE_CHANNEL]");
1300
1301                 ServerResource &resource = ServerResource::getInstance();
1302
1303                 name = g_dbus_method_invocation_get_sender(invocation);
1304
1305                 resource.removeChannel(name, service_id, channel_id);
1306
1307                 result = SCARD_ERROR_OK;
1308
1309                 /* response to client */
1310                 smartcard_service_channel_complete_close_channel(object,
1311                         invocation, result);
1312
1313                 return true;
1314         }
1315
1316         static void _process_close_channel(vector<void *> &params)
1317         {
1318                 SmartcardServiceChannel *object;
1319                 GDBusMethodInvocation *invocation;
1320                 guint service_id;
1321                 guint channel_id;
1322                 void *user_data;
1323
1324                 if (params.size() != 5) {
1325                         /* LCOV_EXCL_START */
1326                         _ERR("invalid parameter");
1327
1328                         return;
1329                         /* LCOV_EXCL_STOP */
1330                 }
1331
1332                 object = (SmartcardServiceChannel *)params[0];
1333                 invocation = (GDBusMethodInvocation *)params[1];
1334                 service_id = (gulong)params[2];
1335                 channel_id = (gulong)params[3];
1336                 user_data = params[4];
1337
1338                 __process_close_channel(object, invocation, service_id,
1339                         channel_id, user_data);
1340
1341                 g_object_unref(object);
1342                 g_object_unref(invocation);
1343         }
1344
1345         static gboolean _handle_close_channel(SmartcardServiceChannel *object,
1346                 GDBusMethodInvocation *invocation,
1347                 guint service_id, guint channel_id, void *user_data)
1348         {
1349                 vector<void *> params;
1350
1351                 /* apply user space smack */
1352                 if (_is_authorized_request(invocation) == true) {
1353                         g_object_ref(object);
1354                         params.push_back((void *)object);
1355
1356                         g_object_ref(invocation);
1357                         params.push_back((void *)invocation);
1358
1359                         params.push_back((void *)service_id);
1360                         params.push_back((void *)channel_id);
1361                         params.push_back(user_data);
1362
1363                         GDBusDispatcher::push(_process_close_channel, params);
1364                 } else {
1365                         /* LCOV_EXCL_START */
1366                         _ERR("access denied");
1367
1368                         /* response to client */
1369                         smartcard_service_channel_complete_close_channel(
1370                                 object,
1371                                 invocation,
1372                                 SCARD_ERROR_SECURITY_NOT_ALLOWED);
1373                         /* LCOV_EXCL_STOP */
1374                 }
1375
1376                 return true;
1377         }
1378
1379         static gboolean __process_transmit(SmartcardServiceChannel *object,
1380                 GDBusMethodInvocation *invocation,
1381                 guint service_id,
1382                 guint channel_id,
1383                 GVariant *command,
1384                 void *user_data)
1385         {
1386                 int result;
1387                 Channel *channel = NULL;
1388                 ByteArray resp;
1389                 GVariant *response = NULL;
1390                 const char *name;
1391
1392                 _INFO("[MSG_REQUEST_TRANSMIT]");
1393
1394                 ServerResource &resource = ServerResource::getInstance();
1395
1396                 name = g_dbus_method_invocation_get_sender(invocation);
1397
1398                 channel = resource.getChannel(name, service_id, channel_id);
1399                 /* LCOV_EXCL_START */
1400                 if (channel != NULL) {
1401                         int rv;
1402                         ByteArray cmd;
1403
1404                         GDBusHelper::convertVariantToByteArray(command, cmd);
1405
1406                         rv = channel->transmitSync(cmd, resp);
1407                         if (rv == 0) {
1408                                 result = SCARD_ERROR_OK;
1409                         } else {
1410                                 _ERR("transmit failed [%d]", rv);
1411
1412                                 result = rv;
1413                         }
1414                 } else {
1415                         _ERR("invalid handle : name [%s], service_id [%d], channel_id [%d]", name, service_id, channel_id);
1416
1417                         result = SCARD_ERROR_UNAVAILABLE;
1418                 }
1419                 /* LCOV_EXCL_STOP */
1420
1421                 response = GDBusHelper::convertByteArrayToVariant(resp);
1422
1423                 /* response to client */
1424                 smartcard_service_channel_complete_transmit(object, invocation,
1425                         result, response);
1426
1427                 return true;
1428         }
1429
1430         static void _process_transmit(vector<void *> &params)
1431         {
1432                 SmartcardServiceChannel *object;
1433                 GDBusMethodInvocation *invocation;
1434                 guint service_id;
1435                 guint channel_id;
1436                 GVariant *command;
1437                 void *user_data;
1438
1439                 if (params.size() != 6) {
1440                         /* LCOV_EXCL_START */
1441                         _ERR("invalid parameter");
1442
1443                         return;
1444                         /* LCOV_EXCL_STOP */
1445                 }
1446
1447                 object = (SmartcardServiceChannel *)params[0];
1448                 invocation = (GDBusMethodInvocation *)params[1];
1449                 service_id = (gulong)params[2];
1450                 channel_id = (gulong)params[3];
1451                 command = (GVariant *)params[4];
1452                 user_data = params[5];
1453
1454                 __process_transmit(object, invocation, service_id,
1455                         channel_id, command, user_data);
1456
1457                 g_object_unref(object);
1458                 g_object_unref(invocation);
1459                 g_object_unref(command);
1460         }
1461
1462         static GVariant *_copy_variant(GVariant *src)
1463         {
1464                 GVariantBuilder builder;
1465
1466                 GVariantIter *iter;
1467                 guint8 element;
1468                 guint i;
1469
1470                 g_variant_get(src, "a(y)", &iter);
1471
1472                 g_variant_builder_init(&builder, G_VARIANT_TYPE("a(y)"));
1473
1474                 for (i = 0; g_variant_iter_loop(iter, "(y)", &element); i++) {
1475                         g_variant_builder_add(&builder, "(y)", element);
1476                 }
1477
1478                 g_variant_iter_free(iter);
1479
1480                 return g_variant_builder_end(&builder);
1481         }
1482
1483         static gboolean _handle_transmit(SmartcardServiceChannel *object,
1484                 GDBusMethodInvocation *invocation,
1485                 guint service_id,
1486                 guint channel_id,
1487                 GVariant *command,
1488                 void *user_data)
1489         {
1490                 vector<void *> params;
1491                 GVariant *_command;
1492
1493                 _command = _copy_variant(command);
1494
1495                 /* apply user space smack */
1496                 if (_is_authorized_request(invocation) == true) {
1497                         /* enqueue message */
1498                         g_object_ref(object);
1499                         params.push_back((void *)object);
1500
1501                         g_object_ref(invocation);
1502                         params.push_back((void *)invocation);
1503
1504                         params.push_back((void *)service_id);
1505                         params.push_back((void *)channel_id);
1506
1507                         g_object_ref(_command);
1508                         params.push_back((void *)_command);
1509
1510                         params.push_back(user_data);
1511
1512                         GDBusDispatcher::push(_process_transmit, params);
1513                 } else {
1514                         /* LCOV_EXCL_START */
1515                         ByteArray resp;
1516
1517                         _ERR("access denied");
1518
1519                         /* response to client */
1520                         smartcard_service_channel_complete_transmit(object,
1521                                 invocation,
1522                                 SCARD_ERROR_SECURITY_NOT_ALLOWED,
1523                                 GDBusHelper::convertByteArrayToVariant(resp));
1524                         /* LCOV_EXCL_STOP */
1525                 }
1526
1527                 return true;
1528         }
1529
1530         bool ServerGDBus::initChannel()
1531         {
1532                 GError *error = NULL;
1533
1534                 channel = smartcard_service_channel_skeleton_new();
1535
1536                 g_signal_connect(channel,
1537                         "handle-close-channel",
1538                         G_CALLBACK(_handle_close_channel),
1539                         this);
1540
1541                 g_signal_connect(channel,
1542                         "handle-transmit",
1543                         G_CALLBACK(_handle_transmit),
1544                         this);
1545
1546                 if (g_dbus_interface_skeleton_export(
1547                         G_DBUS_INTERFACE_SKELETON(channel),
1548                         connection,
1549                         "/org/tizen/SmartcardService/Channel",
1550                         &error) == false)
1551                 {
1552                         /* LCOV_EXCL_START */
1553                         _ERR("Can not skeleton_export %s", error->message);
1554
1555                         g_error_free(error);
1556                         g_object_unref(channel);
1557                         channel = NULL;
1558
1559                         return false;
1560                         /* LCOV_EXCL_STOP */
1561                 }
1562
1563                 return true;
1564         }
1565
1566         void ServerGDBus::deinitChannel()
1567         {
1568                 if (channel != NULL) {
1569                         g_object_unref(channel);
1570                         channel = NULL;
1571                 }
1572         }
1573 } /* namespace smartcard_service_api */