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