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