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