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