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