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