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