Merge "Fix 64bit build break" into tizen
[platform/core/connectivity/smartcard-service.git] / server / ServerGDBus.cpp
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /* standard library header */
18 #include <unistd.h>
19 #include <glib.h>
20 #include <gio/gio.h>
21 #include <vector>
22 #include <string>
23 #include <sys/socket.h>
24
25 /* local header */
26 #include "smartcard-types.h"
27 #include "Debug.h"
28 #include "ByteArray.h"
29 #include "ServerResource.h"
30 #include "GDBusHelper.h"
31 #include "ServerGDBus.h"
32
33 using namespace std;
34
35 #ifdef __PRIVATE
36 extern "C" bool smartcard_service_init_access_control(void *connection);
37 extern "C" void smartcard_service_deinit_access_control();
38 #endif
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 #ifdef __PRIVATE
237                 smartcard_service_init_access_control(connection);
238 #endif
239                 return true;
240         }
241
242         void ServerGDBus::deinit()
243         {
244 #ifdef __PRIVATE
245                 smartcard_service_deinit_access_control();
246 #endif
247                 deinitChannel();
248                 deinitSession();
249                 deinitReader();
250                 deinitSEService();
251
252                 _deinit();
253
254                 if (connection != NULL) {
255                         g_object_unref(connection);
256                         connection = NULL;
257                 }
258         }
259
260         static gboolean _call_get_connection_unix_process_id_sync(
261                 GDBusProxy *proxy, const gchar *arg_name, guint *out_pid,
262                 GCancellable *cancellable, GError **error) {
263                 GVariant *_ret;
264
265                 _ret = g_dbus_proxy_call_sync(proxy,
266                         "GetConnectionUnixProcessID",
267                         g_variant_new("(s)", arg_name),
268                         G_DBUS_CALL_FLAGS_NONE,
269                         -1, cancellable, error);
270                 if (_ret != NULL) {
271                         g_variant_get(_ret, "(u)", out_pid);
272                         g_variant_unref(_ret);
273                 }
274
275                 return _ret != NULL;
276         }
277
278         pid_t ServerGDBus::getPID(const char *name)
279         {
280                 guint pid = 0;
281                 GError *error = NULL;
282
283                 if (_call_get_connection_unix_process_id_sync(
284                         (GDBusProxy *)dbus_proxy, name,
285                         &pid, NULL, &error) == true) {
286                 } else {
287                         _ERR("_g_freedesktop_dbus_call_get_connection_unix_process_id_sync failed  : %s", error->message);
288                         g_error_free(error);
289                 }
290
291                 return pid;
292         }
293
294         static bool _is_authorized_request(GDBusMethodInvocation *invocation,
295                 const char *rights)
296         {
297                 bool result = true;
298
299                 return result;
300         }
301
302         /* SEService *
303          *
304          *
305          */
306         static GVariant *_reader_to_variant(
307                 vector<pair<unsigned int, string> > &readers)
308         {
309                 GVariantBuilder builder;
310                 uint32_t i;
311
312                 g_variant_builder_init(&builder, G_VARIANT_TYPE("a(us)"));
313
314                 for (i = 0; i < readers.size(); i++) {
315                         g_variant_builder_add(&builder, "(us)",
316                                 readers[i].first, readers[i].second.c_str());
317                 }
318
319                 return g_variant_builder_end(&builder);
320         }
321
322         static gboolean __process_se_service(SmartcardServiceSeService *object,
323                 GDBusMethodInvocation *invocation,
324                 void *user_data)
325         {
326                 gint result = SCARD_ERROR_OK;
327                 GVariant *readers = NULL;
328                 vector<pair<unsigned int, string> > list;
329                 unsigned int handle = IntegerHandle::INVALID_HANDLE;
330                 const char *name;
331                 pid_t pid;
332
333                 _INFO("[MSG_REQUEST_READERS]");
334
335                 ServerResource &resource = ServerResource::getInstance();
336
337                 name = g_dbus_method_invocation_get_sender(invocation);
338
339                 /* load secure elements */
340                 resource.loadSecureElements();
341
342                 pid = ServerGDBus::getInstance().getPID(name);
343
344                 _DBG("service requested, pid [%d]", pid);
345
346                 if (pid > 0) {
347                         ClientInstance *instance;
348
349                         instance = resource.getClient(name);
350                         if (instance == NULL) {
351                                 _INFO("create client instance, pid [%d]", pid);
352
353                                 resource.createClient(name, pid);
354
355                                 instance = resource.getClient(name);
356                                 if (instance != NULL) {
357                                         /* generate certification hashes */
358                                         instance->generateCertificationHashes();
359                                 } else {
360                                         _ERR("createClient failed");
361                                 }
362                         }
363
364                         if (instance != NULL) {
365                                 ServiceInstance *service;
366
367                                 /* create service */
368                                 service = resource.createService(name);
369                                 if (service != NULL) {
370
371                                         handle = service->getHandle();
372                                         resource.getReaders(list);
373
374                                         if (list.size() == 0) {
375                                                 _INFO("no secure elements");
376                                         }
377                                 } else {
378                                         _ERR("createService failed");
379
380                                         result = SCARD_ERROR_OUT_OF_MEMORY;
381                                 }
382                         } else {
383                                 _ERR("client doesn't exist, pid [%d]", pid);
384
385                                 result = SCARD_ERROR_OUT_OF_MEMORY;
386                         }
387                 } else {
388                         _ERR("invalid pid, [%d]", pid);
389
390                         result = SCARD_ERROR_IPC_FAILED;
391                 }
392
393                 readers = _reader_to_variant(list);
394
395                 /* response to client */
396                 smartcard_service_se_service_complete_se_service(object,
397                         invocation, result, handle, readers);
398
399                 return true;
400         }
401
402         static void _process_se_service(vector<void *> &params)
403         {
404                 SmartcardServiceSeService *object;
405                 GDBusMethodInvocation *invocation;
406                 void *user_data;
407
408                 if (params.size() != 3) {
409                         _ERR("invalid parameter");
410
411                         return;
412                 }
413
414                 object = (SmartcardServiceSeService *)params[0];
415                 invocation = (GDBusMethodInvocation *)params[1];
416                 user_data = params[2];
417
418                 __process_se_service(object, invocation, user_data);
419
420                 g_object_unref(object);
421                 g_object_unref(invocation);
422         }
423
424         static gboolean _handle_se_service(SmartcardServiceSeService *object,
425                 GDBusMethodInvocation *invocation,
426                 void *user_data)
427         {
428                 vector<void *> params;
429
430                 /* apply user space smack */
431                 if (_is_authorized_request(invocation, "r") == true) {
432                         g_object_ref(object);
433                         params.push_back((void *)object);
434
435                         g_object_ref(invocation);
436                         params.push_back((void *)invocation);
437
438                         params.push_back((void *)user_data);
439
440                         GDBusDispatcher::push(_process_se_service, params);
441                 } else {
442                         vector<pair<unsigned int, string> > list;
443
444                         _ERR("access denied");
445
446                         /* response to client */
447                         smartcard_service_se_service_complete_se_service(object,
448                                 invocation,
449                                 SCARD_ERROR_SECURITY_NOT_ALLOWED,
450                                 IntegerHandle::INVALID_HANDLE,
451                                 _reader_to_variant(list));
452                 }
453
454                 return true;
455         }
456
457         static gboolean __process_shutdown(SmartcardServiceSeService *object,
458                 GDBusMethodInvocation *invocation,
459                 guint handle, void *user_data)
460         {
461                 const char *name;
462
463                 _INFO("[MSG_REQUEST_SHUTDOWN]");
464
465                 ServerResource &resource = ServerResource::getInstance();
466
467                 name = g_dbus_method_invocation_get_sender(invocation);
468
469                 resource.removeService(name, handle);
470
471                 /* response to client */
472                 smartcard_service_se_service_complete_shutdown(object,
473                         invocation, SCARD_ERROR_OK);
474
475                 /* terminate */
476                 resource.finish();
477
478                 return true;
479         }
480
481         static void _process_shutdown(vector<void *> &params)
482         {
483                 SmartcardServiceSeService *object;
484                 GDBusMethodInvocation *invocation;
485                 guint handle;
486                 void *user_data;
487
488                 if (params.size() != 4) {
489                         _ERR("invalid parameter");
490
491                         return;
492                 }
493
494                 object = (SmartcardServiceSeService *)params[0];
495                 invocation = (GDBusMethodInvocation *)params[1];
496                 handle = (gulong)params[2];
497                 user_data = params[3];
498
499                 __process_shutdown(object, invocation, handle, user_data);
500
501                 g_object_unref(object);
502                 g_object_unref(invocation);
503         }
504
505         static gboolean _handle_shutdown(SmartcardServiceSeService *object,
506                 GDBusMethodInvocation *invocation,
507                 guint handle,
508                 void *user_data)
509         {
510                 vector<void *> params;
511
512                 /* apply user space smack */
513                 if (_is_authorized_request(invocation, "r") == true) {
514                         g_object_ref(object);
515                         params.push_back((void *)object);
516
517                         g_object_ref(invocation);
518                         params.push_back((void *)invocation);
519
520                         params.push_back((void *)handle);
521                         params.push_back(user_data);
522
523                         GDBusDispatcher::push(_process_shutdown, params);
524                 } else {
525                         _ERR("access denied");
526
527                         /* response to client */
528                         smartcard_service_se_service_complete_shutdown(object,
529                                 invocation, SCARD_ERROR_SECURITY_NOT_ALLOWED);
530                 }
531
532                 return true;
533         }
534
535         bool ServerGDBus::initSEService()
536         {
537                 GError *error = NULL;
538
539                 seService = smartcard_service_se_service_skeleton_new();
540
541                 g_signal_connect(seService,
542                         "handle-se-service",
543                         G_CALLBACK(_handle_se_service),
544                         this);
545
546                 g_signal_connect(seService,
547                         "handle-shutdown",
548                         G_CALLBACK(_handle_shutdown),
549                         this);
550
551                 if (g_dbus_interface_skeleton_export(
552                         G_DBUS_INTERFACE_SKELETON(seService),
553                         connection,
554                         "/org/tizen/SmartcardService/SeService",
555                         &error) == false)
556                 {
557                         _ERR("Can not skeleton_export %s", error->message);
558
559                         g_error_free(error);
560                         g_object_unref(seService);
561                         seService = NULL;
562
563                         return false;
564                 }
565
566                 return true;
567         }
568
569         void ServerGDBus::deinitSEService()
570         {
571                 if (seService != NULL) {
572                         g_object_unref(seService);
573                         seService = NULL;
574                 }
575         }
576
577         void ServerGDBus::emitReaderInserted(unsigned int reader_id,
578                 const char *reader_name)
579         {
580                 smartcard_service_se_service_emit_reader_inserted(
581                         SMARTCARD_SERVICE_SE_SERVICE(seService),
582                         reader_id, reader_name);
583         }
584
585         void ServerGDBus::emitReaderRemoved(unsigned int reader_id,
586                 const char *reader_name)
587         {
588                 smartcard_service_se_service_emit_reader_removed(
589                         SMARTCARD_SERVICE_SE_SERVICE(seService),
590                         reader_id, reader_name);
591         }
592
593         /* Reader *
594          *
595          *
596          */
597         static gboolean __process_open_session(SmartcardServiceReader *object,
598                 GDBusMethodInvocation *invocation, guint service_id,
599                 guint reader_id, void *user_data)
600         {
601                 unsigned int handle = IntegerHandle::INVALID_HANDLE;
602                 int result;
603                 const char *name;
604
605                 _INFO("[MSG_REQUEST_OPEN_SESSION]");
606
607                 ServerResource &resource = ServerResource::getInstance();
608
609                 name = g_dbus_method_invocation_get_sender(invocation);
610
611                 if (resource.isValidReaderHandle(reader_id)) {
612                         vector<ByteArray> temp;
613
614                         handle = resource.createSession(name,
615                                 service_id,
616                                 reader_id,
617                                 temp,
618                                 (void *)NULL);
619                         if (handle != IntegerHandle::INVALID_HANDLE) {
620                                 result = SCARD_ERROR_OK;
621                         } else {
622                                 _ERR("createSession failed [%d]", handle);
623
624                                 result = SCARD_ERROR_OUT_OF_MEMORY;
625                         }
626                 } else {
627                         _ERR("request invalid reader handle [%d]", reader_id);
628
629                         result = SCARD_ERROR_ILLEGAL_PARAM;
630                 }
631
632                 /* response to client */
633                 smartcard_service_reader_complete_open_session(object,
634                         invocation, result, handle);
635
636                 return true;
637         }
638
639         static void _process_open_session(vector<void *> &params)
640         {
641                 SmartcardServiceReader *object;
642                 GDBusMethodInvocation *invocation;
643                 guint service_id;
644                 guint reader_id;
645                 void *user_data;
646
647                 if (params.size() != 5) {
648                         _ERR("invalid parameter");
649
650                         return;
651                 }
652
653                 object = (SmartcardServiceReader *)params[0];
654                 invocation = (GDBusMethodInvocation *)params[1];
655                 service_id = (gulong)params[2];
656                 reader_id = (gulong)params[3];
657                 user_data = params[4];
658
659                 __process_open_session(object, invocation, service_id,
660                         reader_id, user_data);
661
662                 g_object_unref(object);
663                 g_object_unref(invocation);
664         }
665
666         static gboolean _handle_open_session(SmartcardServiceReader *object,
667                 GDBusMethodInvocation *invocation,
668                 guint service_id,
669                 guint reader_id, void *user_data)
670         {
671                 vector<void *> params;
672
673                 /* apply user space smack */
674                 if (_is_authorized_request(invocation, "r") == true) {
675                         g_object_ref(object);
676                         params.push_back((void *)object);
677
678                         g_object_ref(invocation);
679                         params.push_back((void *)invocation);
680
681                         params.push_back((void *)service_id);
682                         params.push_back((void *)reader_id);
683                         params.push_back(user_data);
684
685                         GDBusDispatcher::push(_process_open_session, params);
686                 } else {
687                         _ERR("access denied");
688
689                         /* response to client */
690                         smartcard_service_reader_complete_open_session(object,
691                                 invocation,
692                                 SCARD_ERROR_SECURITY_NOT_ALLOWED,
693                                 IntegerHandle::INVALID_HANDLE);
694                 }
695
696                 return true;
697         }
698
699         bool ServerGDBus::initReader()
700         {
701                 GError *error = NULL;
702
703                 reader = smartcard_service_reader_skeleton_new();
704
705                 g_signal_connect(reader,
706                         "handle-open-session",
707                         G_CALLBACK(_handle_open_session),
708                         this);
709
710                 if (g_dbus_interface_skeleton_export(
711                         G_DBUS_INTERFACE_SKELETON(reader),
712                         connection,
713                         "/org/tizen/SmartcardService/Reader",
714                         &error) == false)
715                 {
716                         _ERR("Can not skeleton_export %s", error->message);
717
718                         g_error_free(error);
719                         g_object_unref(reader);
720                         reader = NULL;
721
722                         return false;
723                 }
724
725                 return true;
726         }
727
728         void ServerGDBus::deinitReader()
729         {
730                 if (reader != NULL) {
731                         g_object_unref(reader);
732                         reader = NULL;
733                 }
734         }
735
736         /* Session *
737          *
738          *
739          */
740         static gboolean __process_close_session(SmartcardServiceSession *object,
741                 GDBusMethodInvocation *invocation, guint service_id,
742                 guint session_id, void *user_data)
743         {
744                 const char *name;
745
746                 _INFO("[MSG_REQUEST_CLOSE_SESSION]");
747
748                 ServerResource &resource = ServerResource::getInstance();
749
750                 name = g_dbus_method_invocation_get_sender(invocation);
751
752                 if (resource.isValidSessionHandle(name, service_id,
753                         session_id)) {
754                         resource.removeSession(name, service_id,
755                                 session_id);
756                 } else {
757                         _ERR("invalid parameters");
758                 }
759
760                 /* response to client */
761                 smartcard_service_session_complete_close_session(object,
762                         invocation, SCARD_ERROR_OK);
763
764                 return true;
765         }
766
767         static void _process_close_session(vector<void *> &params)
768         {
769                 SmartcardServiceSession *object;
770                 GDBusMethodInvocation *invocation;
771                 guint service_id;
772                 guint session_id;
773                 void *user_data;
774
775                 if (params.size() != 5) {
776                         _ERR("invalid parameter");
777
778                         return;
779                 }
780
781                 object = (SmartcardServiceSession *)params[0];
782                 invocation = (GDBusMethodInvocation *)params[1];
783                 service_id = (gulong)params[2];
784                 session_id = (gulong)params[3];
785                 user_data = params[4];
786
787                 __process_close_session(object, invocation, service_id,
788                         session_id, user_data);
789
790                 g_object_unref(object);
791                 g_object_unref(invocation);
792         }
793
794         static gboolean _handle_close_session(SmartcardServiceSession *object,
795                 GDBusMethodInvocation *invocation,
796                 guint service_id,
797                 guint session_id, void *user_data)
798         {
799                 vector<void *> params;
800
801                 /* apply user space smack */
802                 if (_is_authorized_request(invocation, "r") == true) {
803                         g_object_ref(object);
804                         params.push_back((void *)object);
805
806                         g_object_ref(invocation);
807                         params.push_back((void *)invocation);
808
809                         params.push_back((void *)service_id);
810                         params.push_back((void *)session_id);
811                         params.push_back(user_data);
812
813                         GDBusDispatcher::push(_process_close_session, params);
814                 } else {
815                         _ERR("access denied");
816
817                         /* response to client */
818                         smartcard_service_session_complete_close_session(object,
819                                 invocation, SCARD_ERROR_SECURITY_NOT_ALLOWED);
820                 }
821
822                 return true;
823         }
824
825         static gboolean __process_get_atr(SmartcardServiceSession *object,
826                 GDBusMethodInvocation *invocation, guint service_id,
827                 guint session_id, void *user_data)
828         {
829                 int result;
830                 ByteArray resp;
831                 GVariant *atr = NULL;
832                 const char *name;
833                 ServiceInstance *client = NULL;
834
835                 _INFO("[MSG_REQUEST_GET_ATR]");
836
837                 ServerResource &resource = ServerResource::getInstance();
838
839                 name = g_dbus_method_invocation_get_sender(invocation);
840
841                 client = resource.getService(name, service_id);
842                 if (client != NULL) {
843                         Terminal *terminal;
844
845                         terminal = client->getTerminal(session_id);
846                         if (terminal != NULL) {
847                                 if (terminal->open() == true) {
848                                         result = terminal->getATRSync(resp);
849                                         if (result < SCARD_ERROR_OK) {
850                                                 _ERR("getATRSync failed : name [%s], service_id [%d], session_id [%d]", name, service_id, session_id);
851                                         }
852
853                                         terminal->close();
854                                 } else {
855                                         _ERR("terminal->open failed");
856
857                                         result = SCARD_ERROR_UNAVAILABLE;
858                                 }
859                         } else {
860                                 _ERR("getTerminal failed : name [%s], service_id [%d], session_id [%d]", name, service_id, session_id);
861
862                                 result = SCARD_ERROR_UNAVAILABLE;
863                         }
864                 } else {
865                         _ERR("getClient failed : name [%s], service_id [%d], session_id [%d]", name, service_id, session_id);
866
867                         result = SCARD_ERROR_UNAVAILABLE;
868                 }
869
870                 atr = GDBusHelper::convertByteArrayToVariant(resp);
871
872                 /* response to client */
873                 smartcard_service_session_complete_get_atr(object, invocation,
874                         result, atr);
875
876                 return true;
877         }
878
879         static void _process_get_atr(vector<void *> &params)
880         {
881                 SmartcardServiceSession *object;
882                 GDBusMethodInvocation *invocation;
883                 guint service_id;
884                 guint session_id;
885                 void *user_data;
886
887                 if (params.size() != 5) {
888                         _ERR("invalid parameter");
889
890                         return;
891                 }
892
893                 object = (SmartcardServiceSession *)params[0];
894                 invocation = (GDBusMethodInvocation *)params[1];
895                 service_id = (gulong)params[2];
896                 session_id = (gulong)params[3];
897                 user_data = params[4];
898
899                 __process_get_atr(object, invocation, service_id,
900                         session_id, user_data);
901
902                 g_object_unref(object);
903                 g_object_unref(invocation);
904         }
905
906         static gboolean _handle_get_atr(SmartcardServiceSession *object,
907                 GDBusMethodInvocation *invocation,
908                 guint service_id,
909                 guint session_id, void *user_data)
910         {
911                 vector<void *> params;
912
913                 /* apply user space smack */
914                 if (_is_authorized_request(invocation, "r") == true) {
915                         g_object_ref(object);
916                         params.push_back((void *)object);
917
918                         g_object_ref(invocation);
919                         params.push_back((void *)invocation);
920
921                         params.push_back((void *)service_id);
922                         params.push_back((void *)session_id);
923                         params.push_back(user_data);
924
925                         GDBusDispatcher::push(_process_get_atr, params);
926                 } else {
927                         ByteArray resp;
928
929                         _ERR("access denied");
930
931                         /* response to client */
932                         smartcard_service_session_complete_get_atr(
933                                 object,
934                                 invocation,
935                                 SCARD_ERROR_SECURITY_NOT_ALLOWED,
936                                 GDBusHelper::convertByteArrayToVariant(resp));
937                 }
938
939                 return true;
940         }
941
942         static gboolean __process_open_channel(SmartcardServiceSession *object,
943                 GDBusMethodInvocation *invocation, guint service_id,
944                 guint session_id, guint type, GVariant *aid, guint8 P2, void *user_data)
945         {
946                 int channelNum = -1;
947                 int result = SCARD_ERROR_UNKNOWN;
948                 ByteArray resp;
949                 GVariant *response = NULL;
950                 unsigned int channelID = IntegerHandle::INVALID_HANDLE;
951                 const char *name;
952
953                 _INFO("[MSG_REQUEST_OPEN_CHANNEL]");
954                 _INFO("P2 is %x", P2);
955
956                 ServerResource &resource = ServerResource::getInstance();
957
958                 name = g_dbus_method_invocation_get_sender(invocation);
959
960                 try
961                 {
962                         ByteArray tempAid;
963
964                         GDBusHelper::convertVariantToByteArray(aid,
965                                 tempAid);
966
967                         channelID = resource.createChannel(name,
968                                 service_id, session_id, type, tempAid);
969                         if (channelID != IntegerHandle::INVALID_HANDLE) {
970                                 ServerChannel *temp;
971
972                                 temp = (ServerChannel *)resource.getChannel(
973                                         name, service_id, channelID);
974                                 if (temp != NULL) {
975                                         resp = temp->getSelectResponse();
976                                         channelNum = temp->getChannelNumber();
977                                         result = SCARD_ERROR_OK;
978                                 }
979                                 else{
980                                         _ERR("getChannel is failed");
981                                         result = SCARD_ERROR_UNAVAILABLE;
982                                 }
983                         } else {
984                                 _ERR("channel is null.");
985
986                                 /* set error value */
987                                 result = SCARD_ERROR_UNAVAILABLE;
988                         }
989                 }
990                 catch (ExceptionBase &e)
991                 {
992                         result = e.getErrorCode();
993                 }
994
995                 response = GDBusHelper::convertByteArrayToVariant(resp);
996
997                 /* response to client */
998                 smartcard_service_session_complete_open_channel(object,
999                         invocation, result, channelID, channelNum, response);
1000
1001                 return true;
1002         }
1003
1004         static void _process_open_channel(vector<void *> &params)
1005         {
1006                 SmartcardServiceSession *object;
1007                 GDBusMethodInvocation *invocation;
1008                 guint service_id;
1009                 guint session_id;
1010                 guint type;
1011                 guint8 P2;
1012                 GVariant *aid;
1013                 void *user_data;
1014
1015                 if (params.size() != 8) {
1016                         _ERR("invalid parameter");
1017
1018                         return;
1019                 }
1020
1021                 object = (SmartcardServiceSession *)params[0];
1022                 invocation = (GDBusMethodInvocation *)params[1];
1023                 service_id = (gulong)params[2];
1024                 session_id = (gulong)params[3];
1025                 type = (gulong)params[4];
1026                 aid = (GVariant *)params[5];
1027                 P2 = (guint8)((gulong)params[6]);
1028                 user_data = params[7];
1029
1030                 __process_open_channel(object, invocation, service_id,
1031                         session_id, type, aid, P2, user_data);
1032
1033                 g_object_unref(object);
1034                 g_object_unref(invocation);
1035                 g_variant_unref(aid);
1036         }
1037
1038         static gboolean _handle_open_channel(SmartcardServiceSession *object,
1039                 GDBusMethodInvocation *invocation,
1040                 guint service_id,
1041                 guint session_id, guint type, GVariant *aid, guint8 P2, void *user_data)
1042         {
1043                 vector<void *> params;
1044
1045                 /* apply user space smack */
1046                 if (_is_authorized_request(invocation, "rw") == true) {
1047                         g_object_ref(object);
1048                         params.push_back((void *)object);
1049
1050                         g_object_ref(invocation);
1051                         params.push_back((void *)invocation);
1052
1053                         params.push_back((void *)service_id);
1054                         params.push_back((void *)session_id);
1055                         params.push_back((void *)type);
1056
1057                         g_variant_ref(aid);
1058                         params.push_back((void *)aid);
1059                         params.push_back((void *)((int)P2));
1060                         params.push_back(user_data);
1061
1062                         GDBusDispatcher::push(_process_open_channel, params);
1063                 } else {
1064                         ByteArray resp;
1065
1066                         _ERR("access denied");
1067
1068                         /* response to client */
1069                         smartcard_service_session_complete_open_channel(object,
1070                                 invocation,
1071                                 SCARD_ERROR_SECURITY_NOT_ALLOWED,
1072                                 IntegerHandle::INVALID_HANDLE,
1073                                 -1,
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 = (gulong)params[2];
1172                 channel_id = (gulong)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 = (gulong)params[2];
1281                 channel_id = (gulong)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 */