Added Gtest for smartcard-service
[platform/core/connectivity/smartcard-service.git] / server / ServerResource.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 <stdio.h>
19 #include <string.h>
20 #include <dlfcn.h>
21 #include <errno.h>
22 #include <dirent.h>
23
24 /* SLP library header */
25
26 /* local header */
27 #include "Debug.h"
28 #include "ServerResource.h"
29 #include "TerminalInterface.h"
30 #include "APDUHelper.h"
31 #include "SignatureHelper.h"
32 #include "GPACE.h"
33 #include "PKCS15.h"
34 #include "ServerGDBus.h"
35 #include "smartcard-daemon.h"
36
37 #ifndef EXTERN_API
38 #define EXTERN_API __attribute__((visibility("default")))
39 #endif
40
41 using namespace std;
42
43 namespace smartcard_service_api
44 {
45         unsigned int IntegerHandle::newHandle = 0;
46         set<unsigned int> IntegerHandle::setHandles;
47         PMutex IntegerHandle::mutexLock;
48
49         unsigned int IntegerHandle::assignHandle()
50         {
51                 SCOPE_LOCK(mutexLock)
52                 {
53                         pair<set<unsigned int>::iterator, bool> result;
54
55                         do
56                         {
57                                 newHandle++;
58                                 if (newHandle == (unsigned int)-1)
59                                 {
60                                         newHandle = 1;
61                                 }
62
63                                 result = setHandles.insert(newHandle);
64                         }
65                         while (!result.second);
66                 }
67
68                 _DBG("assign handle : newHandle [%d]", newHandle);
69
70                 return newHandle;
71         }
72
73         void IntegerHandle::releaseHandle(unsigned int handle)
74         {
75                 _DBG("will be released : Handle [%d]", handle);
76
77                 SCOPE_LOCK(mutexLock)
78                 {
79                         setHandles.erase(handle);
80                 }
81         }
82
83 #define OMAPI_SE_PATH "/usr/lib/se"
84
85         ServerResource::ServerResource() : seLoaded(false)
86         {
87                 _BEGIN();
88                 _END();
89         }
90
91         ServerResource::~ServerResource()
92         {
93         }
94
95         ServerResource &ServerResource::getInstance()
96         {
97                 static ServerResource serverResource;
98
99                 return serverResource;
100         }
101
102         bool ServerResource::createClient(const char *name, pid_t pid)
103         {
104                 bool result = false;
105
106                 if (getClient(name) == NULL) {
107                         ClientInstance *instance = new ClientInstance(name, pid);
108                         if (instance != NULL) {
109                                 mapClients.insert(make_pair(name, instance));
110                                 result = true;
111                         } else {
112                                 _ERR("alloc failed"); //LCOV_EXCL_LINE
113                         }
114                 } else {
115                         _ERR("client already exist, name [%s]", name); //LCOV_EXCL_LINE
116                 }
117
118                 return result;
119         }
120
121         ClientInstance *ServerResource::getClient(const char *name)
122         {
123                 ClientInstance *result = NULL;
124                 map<string, ClientInstance *>::iterator item;
125
126                 if ((item = mapClients.find(name)) != mapClients.end())
127                 {
128                         result = item->second;
129                 }
130
131                 return result;
132         }
133
134         void ServerResource::removeClient(const char *name)
135         {
136                 map<string, ClientInstance *>::iterator item;
137
138                 if ((item = mapClients.find(name)) != mapClients.end()) {
139                         delete item->second;
140                         mapClients.erase(item);
141                 } else {
142                         _DBG("client removed already, name [%s]", name); //LCOV_EXCL_LINE
143                 }
144         }
145
146         /* LCOV_EXCL_START */
147         void ServerResource::removeClients()
148         {
149                 map<string, ClientInstance *>::iterator item;
150
151                 for (item = mapClients.begin(); item != mapClients.end(); item++)
152                 {
153                         delete item->second;
154                 }
155
156                 mapClients.clear();
157         }
158
159         int ServerResource::getClientCount() const
160         {
161                 return (int)mapClients.size();
162         }
163
164         ServiceInstance *ServerResource::createService(const char *name)
165         {
166                 ServiceInstance *result = NULL;
167                 ClientInstance *instance = NULL;
168
169                 if ((instance = getClient(name)) != NULL) {
170                         if ((result = instance->createService()) == NULL) {
171                                 _ERR("ClientInstance::createService failed [%d]", name);
172                         }
173                 } else {
174                         _ERR("client doesn't exist, name [%s]", name);
175                 }
176
177                 return result;
178         }
179
180         ServiceInstance *ServerResource::getService(const char *name, unsigned int handle)
181         {
182                 ServiceInstance *result = NULL;
183                 ClientInstance *instance = NULL;
184
185                 if ((instance = getClient(name)) != NULL) {
186                         result = instance->getService(handle);
187                 } else {
188                         _ERR("client doesn't exist, name [%s]", name);
189                 }
190
191                 return result;
192         }
193
194         void ServerResource::removeService(const char *name, unsigned int handle)
195         {
196                 ClientInstance *instance = NULL;
197
198                 if ((instance = getClient(name)) != NULL) {
199                         instance->removeService(handle);
200                         if (instance->getServiceCounts() == 0) {
201                                 /* remove client instance */
202                                 removeClient(name);
203                         }
204                 } else {
205                         _ERR("client doesn't exist, name [%s]", name);
206                 }
207         }
208
209         void ServerResource::removeServices(const char *name)
210         {
211                 ClientInstance *instance = NULL;
212
213                 if ((instance = getClient(name)) != NULL) {
214                         instance->removeServices();
215
216                         /* remove client instance */
217                         removeClient(name);
218                 } else {
219                         _ERR("client doesn't exist, name [%s]", name);
220                 }
221         }
222
223         unsigned int ServerResource::createSession(const char *name, unsigned int handle, unsigned int readerID, vector<ByteArray> &certHashes, void *caller)
224         {
225                 unsigned int result = -1;
226                 Terminal *temp = NULL;
227                 ServiceInstance *instance = NULL;
228
229                 if ((instance = getService(name, handle)) != NULL) {
230                         if ((temp = getTerminalByReaderID(readerID)) != NULL) {
231                                 result = instance->openSession(temp, certHashes, caller);
232                         }
233                 } else {
234                         _ERR("getService doesn't exist : name [%s], handle [%d]", name, handle);
235                 }
236
237                 return result;
238         }
239
240         ServerSession *ServerResource::getSession(const char *name, unsigned int handle, unsigned int sessionID)
241         {
242                 ServerSession *result = NULL;
243                 ServiceInstance *instance = NULL;
244
245                 if ((instance = getService(name, handle)) != NULL) {
246                         result = instance->getSession(sessionID);
247                 } else {
248                         _ERR("Session doesn't exist : name [%s], handle [%d], handle [%d]", name, handle, sessionID);
249                 }
250
251                 return result;
252         }
253
254         bool ServerResource::isValidSessionHandle(const char *name, unsigned int handle, unsigned int session)
255         {
256                 ServiceInstance *instance = NULL;
257
258                 return (((instance = getService(name, handle)) != NULL) && (instance->isVaildSessionHandle(session)));
259         }
260
261         bool ServerResource::isValidChannelHandle(const char *name, unsigned int handle, unsigned int channel)
262         {
263                 ServiceInstance *instance = NULL;
264
265                 return (((instance = getService(name, handle)) != NULL) && (instance->isVaildChannelHandle(channel)));
266         }
267
268         unsigned int ServerResource::getChannelCount(const char *name, unsigned int handle, unsigned int sessionID)
269         {
270                 unsigned int result = -1;
271                 ServiceInstance *instance = NULL;
272
273                 if ((instance = getService(name, handle)) != NULL) {
274                         result = instance->getChannelCountBySession(sessionID);
275                 } else {
276                         _ERR("getService doesn't exist : name [%s], handle [%d]", name, handle);
277                 }
278
279                 return result;
280         }
281
282         void ServerResource::removeSession(const char *name, unsigned int handle, unsigned int sessionID)
283         {
284                 ServiceInstance *instance = NULL;
285
286                 if ((instance = getService(name, handle)) != NULL) {
287                         instance->closeSession(sessionID);
288                 } else {
289                         _ERR("getService doesn't exist : name [%s], handle [%d]", name, handle);
290                 }
291         }
292
293         unsigned int ServerResource::createChannel(const char *name, unsigned int handle, unsigned int sessionID, int channelType, ByteArray aid)
294                 throw(ExceptionBase &)
295         {
296                 unsigned int result = -1;
297                 ServiceInstance *service = NULL;
298
299                 if ((service = getService(name, handle)) != NULL) {
300                         if (service->isVaildSessionHandle(sessionID) == true) {
301                                 ServerSession *session = NULL;
302                                 Terminal *terminal = NULL;
303
304                                 terminal = service->getTerminal(sessionID);
305                                 session = service->getSession(sessionID);
306                                 if (terminal != NULL && session != NULL) {
307                                         if (terminal->open() == true) {
308                                                 result = _createChannel(terminal, service, channelType, sessionID, aid);
309                                                 if (result == IntegerHandle::INVALID_HANDLE) {
310                                                         _ERR("create channel failed [%d]", sessionID);
311
312                                                         terminal->close();
313                                                 }
314                                         } else {
315                                                 _ERR("terminal open failed");
316                                                 throw ExceptionBase(SCARD_ERROR_UNAVAILABLE);
317                                         }
318                                 } else {
319                                         _ERR("session is invalid [%d]", sessionID);
320                                         throw ExceptionBase(SCARD_ERROR_UNAVAILABLE);
321                                 }
322                         } else {
323                                 _ERR("session is invalid [%d]", sessionID);
324                                 throw ExceptionBase(SCARD_ERROR_ILLEGAL_STATE);
325                         }
326                 } else {
327                         _ERR("getService is failed, name [%s], handle [%d]", name, handle);
328                         throw ExceptionBase(SCARD_ERROR_UNAVAILABLE);
329                 }
330
331                 return result;
332         }
333
334         Channel *ServerResource::getChannel(const char *name, unsigned int handle, unsigned int channelID)
335         {
336                 Channel *result = NULL;
337                 ServiceInstance *instance = NULL;
338
339                 if ((instance = getService(name, handle)) != NULL) {
340                         result = instance->getChannel(channelID);
341                 } else {
342                         _ERR("Channel doesn't exist : name [%s], handle [%d], handle [%d]", name, handle, channelID);
343                 }
344
345                 return result;
346         }
347
348         void ServerResource::removeChannel(const char *name, unsigned int handle, unsigned int channelID)
349         {
350                 ServiceInstance *instance = NULL;
351
352                 if ((instance = getService(name, handle)) != NULL) {
353                         ServerChannel *channel;
354                         Terminal *terminal = NULL;
355
356                         channel = instance->getChannel(channelID);
357                         if (channel != NULL) {
358                                 terminal = channel->getTerminal();
359                         }
360
361                         instance->closeChannel(channelID);
362
363                         if (terminal != NULL) {
364                                 terminal->close();
365                         }
366                 } else {
367                         _ERR("getService doesn't exist : name [%s], handle [%d]", name, handle);
368                 }
369         }
370
371         Terminal *ServerResource::getTerminal(unsigned int terminalID)
372         {
373                 Terminal *result = NULL;
374                 map<unsigned int, Terminal *>::iterator item;
375
376                 if ((item = mapTerminals.find(terminalID)) != mapTerminals.end()) {
377                         result = item->second;
378                 } else {
379                         _ERR("Terminal doesn't exist [%d]", terminalID);
380                 }
381
382                 return result;
383         }
384
385         const Terminal *ServerResource::getTerminal(unsigned int terminalID) const
386         {
387                 const Terminal *result = NULL;
388                 map<unsigned int, Terminal *>::const_iterator item;
389
390                 if ((item = mapTerminals.find(terminalID)) != mapTerminals.end()) {
391                         result = item->second;
392                 } else {
393                         _ERR("Terminal doesn't exist [%d]", terminalID);
394                 }
395
396                 return result;
397         }
398
399         Terminal *ServerResource::getTerminal(const char *name)
400         {
401                 Terminal *result = NULL;
402                 map<unsigned int, Terminal *>::iterator item;
403
404                 for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
405                 {
406                         if (strncmp(name, item->second->getName(), strlen(name)) == 0)
407                         {
408                                 result = item->second;
409                                 break;
410                         }
411                 }
412
413                 return result;
414         }
415
416         Terminal *ServerResource::getTerminalByReaderID(unsigned int readerID)
417         {
418                 Terminal *result = NULL;
419                 map<unsigned int, unsigned int>::iterator item;
420
421                 if ((item = mapReaders.find(readerID)) != mapReaders.end()) {
422                         result = getTerminal(item->second);
423                 } else {
424                         _ERR("Terminal doesn't exist, reader ID [%d]", readerID);
425                 }
426
427                 return result;
428         }
429
430         const Terminal *ServerResource::getTerminalByReaderID(unsigned int readerID) const
431         {
432                 const Terminal *result = NULL;
433                 map<unsigned int, unsigned int>::const_iterator item;
434
435                 if ((item = mapReaders.find(readerID)) != mapReaders.end()) {
436                         result = getTerminal(item->second);
437                 } else {
438                         _ERR("Terminal doesn't exist, reader ID [%d]", readerID);
439                 }
440
441                 return result;
442         }
443
444         unsigned int ServerResource::getTerminalID(const char *name) const
445         {
446                 unsigned int result = IntegerHandle::INVALID_HANDLE;
447                 map<unsigned int, Terminal *>::const_iterator item;
448
449                 for (item = mapTerminals.begin();
450                         item != mapTerminals.end(); item++)
451                 {
452                         if (strncmp(name, item->second->getName(),
453                                 strlen(name)) == 0)
454                         {
455                                 result = item->first;
456                                 break;
457                         }
458                 }
459
460                 return result;
461         }
462
463         bool ServerResource::_isAuthorizedAccess(ServerChannel *channel,
464                 const ByteArray &aid, const vector<ByteArray> &hashes)
465         {
466                 bool result = false;
467                 AccessControlList *acList = NULL;
468
469                 /* request open channel sequence */
470                 if ((acList = getAccessControlList(channel)) == NULL) {
471                         /* load access control defined by Global Platform */
472                         GPACE *acl = new GPACE();
473                         if (acl != NULL) {
474                                 int ret;
475
476                                 ret = acl->loadACL(channel);
477                                 if (ret >= SCARD_ERROR_OK) {
478                                         acList = acl;
479                                         addAccessControlList(channel, acList);
480                                 } else {
481                                         _ERR("unknown error, 0x%x", -ret);
482                                         delete acl;
483                                 }
484                         } else {
485                                 _ERR("alloc failed");
486                         }
487                 } else {
488                         acList->loadACL(channel);
489                 }
490
491                 if (acList != NULL) {
492                         result = acList->isAuthorizedAccess(aid, hashes);
493                 }
494
495                 return result;
496         }
497
498         int ServerResource::_openLogicalChannel(Terminal *terminal)
499         {
500                 int result = -1;
501                 int rv = 0;
502                 ByteArray command;
503                 ByteArray response;
504
505                 /* open channel */
506                 command = APDUHelper::generateAPDU(APDUHelper::COMMAND_OPEN_LOGICAL_CHANNEL, 0, ByteArray::EMPTY);
507
508                 _DBG("command [%d] : %s", command.size(), command.toString().c_str());
509
510                 rv = terminal->transmitSync(command, response);
511                 if (rv == 0 && response.size() >= 2) {
512                         ResponseHelper resp(response);
513
514                         if (resp.getStatus() >= 0) {
515                                 result = resp.getDataField()[0];
516                         } else {
517                                 result = resp.getStatus();
518                         }
519                 } else {
520                         _ERR("transmitSync failed, rv [%d], length [%d]", rv, response.size());
521                 }
522
523                 return result;
524         }
525
526         int ServerResource::_closeLogicalChannel(Terminal *terminal, int channelNum)
527         {
528                 int result = SCARD_ERROR_UNKNOWN;
529                 int rv = 0;
530                 ByteArray command;
531                 ByteArray response;
532
533                 /* open channel */
534                 command = APDUHelper::generateAPDU(APDUHelper::COMMAND_CLOSE_LOGICAL_CHANNEL, channelNum, ByteArray::EMPTY);
535
536                 _DBG("command [%d] : %s", command.size(), command.toString().c_str());
537
538                 rv = terminal->transmitSync(command, response);
539                 if (rv == 0 && response.size() >= 2) {
540                         ResponseHelper resp(response);
541
542                         if (resp.getStatus() >= 0) {
543                                 _DBG("channel closed [%d]", channelNum);
544                                 result = SCARD_ERROR_OK;
545                         } else {
546                                 _ERR("status word [ %02X %02X ]", resp.getSW1(), resp.getSW2());
547                         }
548                 } else {
549                         _ERR("select apdu is failed, rv [%d], length [%d]", rv, response.size());
550                 }
551
552                 return result;
553         }
554
555         unsigned int ServerResource::_createChannel(Terminal *terminal,
556                 ServiceInstance *service, int channelType,
557                 unsigned int sessionID, const ByteArray &aid)
558                 throw(ExceptionBase &)
559         {
560                 unsigned int result = IntegerHandle::INVALID_HANDLE;
561                 int channelNum = 0;
562                 ServerChannel *channel = NULL;
563
564                 /* open logical channel */
565                 if (channelType == 1) {
566                         channelNum = _openLogicalChannel(terminal);
567                         if (channelNum > 0) {
568                                 _DBG("channelNum [%d]", channelNum);
569                         } else {
570                                 _ERR("_openLogicalChannel failed [%d]", channelNum);
571                                 throw ExceptionBase(SCARD_ERROR_NOT_ENOUGH_RESOURCE);
572                         }
573                 }
574
575                 /* create channel instance */
576                 result = service->openChannel(sessionID, channelNum, ByteArray::EMPTY);
577                 if (result == IntegerHandle::INVALID_HANDLE)
578                 {
579                         _ERR("channel is null.");
580
581                         /* close logical channel */
582                         if (channelNum > 0)
583                         {
584                                 _closeLogicalChannel(terminal, channelNum);
585                         }
586                         throw ExceptionBase(SCARD_ERROR_OUT_OF_MEMORY);
587                 }
588
589                 channel = service->getChannel(result);
590                 if(channel == NULL)
591                 {
592                         _ERR("channel is null.");
593
594                          throw ExceptionBase(SCARD_ERROR_OUT_OF_MEMORY);
595                 }
596
597                 /* NOTICE : This code is Access contol implementation in OpenMobile Specification.
598                  If you need the Access control in your target, please remove this comment.*/
599                 /*
600                 if (_isAuthorizedAccess(channel, aid,
601                         service->getParent()->getCertificationHashes()) == true) {
602                         int rv = 0;
603
604                         if (aid == PKCS15::PKCS15_AID) {
605                                 PKCS15 pkcs15(channel);
606
607                                 rv = pkcs15.select();
608                                 if (rv >= SCARD_ERROR_OK) {
609                                         channel->unsetPrivilegeMode();
610                                         channel->setSelectResponse(pkcs15.getSelectResponse());
611                                 } else {
612                                         _ERR("select failed, [%x]", -rv);
613
614                                         service->closeChannel(result);
615                                         throw ExceptionBase(SCARD_ERROR_IO_FAILED);
616                                 }
617                         } else {
618                                 FileObject file(channel);
619
620                                 rv = file.select(aid);
621                                 if (rv >= SCARD_ERROR_OK) {
622                                         channel->unsetPrivilegeMode();
623                                         channel->setSelectResponse(file.getSelectResponse());
624                                 } else {
625                                         _ERR("select failed [%x]", -rv);
626
627                                         service->closeChannel(result);
628                                         throw ExceptionBase(SCARD_ERROR_IO_FAILED);
629                                 }
630                         }
631                 } else {
632                         _ERR("unauthorized access");
633
634                         service->closeChannel(result);
635                         throw ExceptionBase(SCARD_ERROR_SECURITY_NOT_ALLOWED);
636                 }
637                 */
638                 return result;
639         }
640
641         void ServerResource::addAccessControlList(Terminal *terminal, AccessControlList *acl)
642         {
643                 map<Terminal *, AccessControlList *>::iterator item;
644
645                 if ((item = mapACL.find(terminal)) == mapACL.end()) {
646                         mapACL.insert(make_pair(terminal, acl));
647                 } else {
648                         item->second = acl;
649                 }
650         }
651
652         void ServerResource::addAccessControlList(ServerChannel *channel, AccessControlList *acl)
653         {
654                 map<Terminal *, AccessControlList *>::iterator item;
655
656                 if ((item = mapACL.find(channel->getTerminal())) == mapACL.end()) {
657                         mapACL.insert(make_pair(channel->getTerminal(), acl));
658                 } else {
659                         item->second = acl;
660                 }
661         }
662
663         AccessControlList *ServerResource::getAccessControlList(Terminal *terminal)
664         {
665                 AccessControlList *result = NULL;
666                 map<Terminal *, AccessControlList *>::iterator item;
667
668                 if ((item = mapACL.find(terminal)) != mapACL.end())
669                 {
670                         result = item->second;
671                 }
672
673                 return result;
674         }
675
676         AccessControlList *ServerResource::getAccessControlList(ServerChannel *channel)
677         {
678                 AccessControlList *result = NULL;
679                 map<Terminal *, AccessControlList *>::iterator item;
680
681                 if ((item = mapACL.find(channel->getTerminal())) != mapACL.end())
682                 {
683                         result = item->second;
684                 }
685
686                 return result;
687         }
688
689         Terminal *ServerResource::createInstance(void *library)
690         {
691                 Terminal *terminal = NULL;
692                 terminal_create_instance_fn createInstance = NULL;
693
694                 /* create se instance */
695                 createInstance = (terminal_create_instance_fn)dlsym(library, "create_instance");
696                 if (createInstance != NULL) {
697                         terminal = (Terminal *)createInstance();
698                         if (terminal != NULL) {
699                                 _DBG("terminal [%p]", terminal);
700                         } else {
701                                 _ERR("terminal is null");
702                         }
703                 } else {
704                         _ERR("create_instance is null [%d]", errno);
705                 }
706
707                 return terminal;
708         }
709
710         bool ServerResource::appendSELibrary(char *library)
711         {
712                 void *libHandle = NULL;
713                 bool result = false;
714
715                 libHandle = dlopen(library, RTLD_LAZY);
716                 if (libHandle != NULL) {
717                         Terminal *terminal = NULL;
718
719                         terminal = createInstance(libHandle);
720                         if (terminal != NULL) {
721                                 unsigned int handle = IntegerHandle::assignHandle();
722
723                                 mapTerminals.insert(make_pair(handle, terminal));
724                                 libraries.push_back(libHandle);
725
726                                 terminal->setStatusCallback(&ServerResource::terminalCallback);
727
728                                 _DBG("register success [%s] [%p] [%s] [%p]", library, libHandle, terminal->getName(), terminal);
729
730                                 if (terminal->isSecureElementPresence() == true) {
731                                         createReader(handle);
732                                 }
733
734                                 result = true;
735                         } else {
736                                 _ERR("terminal is null [%s]", library);
737
738                                 dlclose(libHandle);
739                         }
740                 } else {
741                         _ERR("it is not se file [%s] [%d]", library, errno);
742                 }
743
744                 return result;
745         }
746
747         int ServerResource::loadSecureElements()
748         {
749                 int result = 0;
750
751                 if (seLoaded == false) {
752                         DIR *dir;
753                         struct dirent *entry;
754
755                         if ((dir = opendir(OMAPI_SE_PATH)) != NULL) {
756                                 while ((entry = readdir(dir)) != NULL) {
757                                         if (strncmp(entry->d_name, ".", 1) != 0 &&
758                                                 strncmp(entry->d_name, "..", 2) != 0) {
759                                                 char fullPath[1024];
760                                                 /* TODO : need additional name rule :) */
761
762                                                 /* append each files */
763                                                 snprintf(fullPath, sizeof(fullPath),
764                                                         "%s/%s", OMAPI_SE_PATH, entry->d_name);
765
766                                                 SECURE_LOGD("se name [%s]", fullPath); //LCOV_EXCL_LINE
767
768                                                 result = appendSELibrary(fullPath);
769                                         }
770                                 }
771
772                                 closedir(dir);
773
774                                 seLoaded = true;
775                         } else {
776                                 result = -1;
777                         }
778                 }
779
780                 return result;
781         }
782
783         void ServerResource::unloadSecureElements()
784         {
785                 if (seLoaded == true)
786                 {
787                         size_t i;
788                         map<unsigned int, Terminal *>::iterator item;
789
790                         for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
791                         {
792                                 item->second->finalize();
793
794                                 IntegerHandle::releaseHandle(item->first);
795                         }
796
797                         mapTerminals.clear();
798
799                         for (i = 0; i < libraries.size(); i++)
800                         {
801                                 if (libraries[i] != NULL)
802                                         dlclose(libraries[i]);
803                         }
804
805                         libraries.clear();
806
807                         seLoaded = false;
808                 }
809         }
810
811         bool ServerResource::isValidReaderHandle(unsigned int reader) const
812         {
813                 return (getTerminalByReaderID(reader) != NULL);
814         }
815
816         void ServerResource::getReaders(vector<pair<unsigned int, string> > &readers) const
817         {
818                 const Terminal *terminal;
819                 map<unsigned int, unsigned int>::const_iterator item;
820
821                 readers.clear();
822
823                 for (item = mapReaders.begin(); item != mapReaders.end(); item++)
824                 {
825                         if (item->second != IntegerHandle::INVALID_HANDLE)
826                         {
827                                 terminal = getTerminal(item->second);
828                                 if (terminal != NULL && terminal->isSecureElementPresence() == true)
829                                 {
830                                         readers.push_back(make_pair(item->first, terminal->getName()));
831                                 }
832                         }
833                 }
834         }
835
836         int ServerResource::getReadersInformation(ByteArray &info) const
837         {
838                 int result = 0;
839                 unsigned char *buffer = NULL;
840                 unsigned int length = 0;
841                 unsigned int offset = 0;
842                 unsigned int nameLen = 0;
843
844                 if (mapReaders.size() > 0) {
845                         const Terminal *terminal = NULL;
846                         map<unsigned int, unsigned int>::const_iterator item;
847
848                         for (item = mapReaders.begin(); item != mapReaders.end(); item++) {
849                                 if (item->second != IntegerHandle::INVALID_HANDLE) {
850                                         terminal = getTerminal(item->second);
851                                         if (terminal != NULL) {
852                                                 if (terminal->isSecureElementPresence()) {
853                                                         length += sizeof(nameLen) + strlen(terminal->getName()) + sizeof(unsigned int);
854                                                         result++;
855                                                 }
856                                         }
857                                 }
858                         }
859
860                         buffer = new unsigned char[length];
861                         if (buffer != NULL) {
862                                 memset(buffer, 0, length);
863
864                                 for (item = mapReaders.begin(); item != mapReaders.end(); item++) {
865                                         if (item->second != IntegerHandle::INVALID_HANDLE) {
866                                                 terminal = getTerminal(item->second);
867                                                 if (terminal != NULL) {
868                                                         if (terminal->isSecureElementPresence()) {
869                                                                 nameLen = strlen(terminal->getName());
870
871                                                                 memcpy(buffer + offset, &nameLen, sizeof(nameLen));
872                                                                 offset += sizeof(nameLen);
873
874                                                                 memcpy(buffer + offset, terminal->getName(), nameLen);
875                                                                 offset += nameLen;
876
877                                                                 memcpy(buffer + offset, &item->first, sizeof(unsigned int));
878                                                                 offset += sizeof(unsigned int);
879                                                         }
880                                                 }
881                                         }
882                                 }
883
884                                 info.assign(buffer, length);
885                                 delete []buffer;
886                         } else {
887                                 _ERR("alloc failed");
888                                 result = -1;
889                         }
890                 } else {
891                         _INFO("no secure element");
892                 }
893
894                 return result;
895         }
896
897         void ServerResource::terminalCallback(const void *terminal, int event,
898                 int error, void *user_param)
899         {
900                 _DBG("terminal [%s], event [%d], error [%d], user_param [%p]", (char *)terminal, event, error, user_param);
901
902                 switch (event)
903                 {
904                 case Terminal::NOTIFY_SE_AVAILABLE :
905                         {
906                                 ServerResource &instance = ServerResource::getInstance();
907                                 unsigned int terminalID = IntegerHandle::INVALID_HANDLE;
908
909                                 _INFO("[NOTIFY_SE_AVAILABLE]");
910
911                                 terminalID = instance.getTerminalID((char *)terminal);
912                                 if (terminalID != IntegerHandle::INVALID_HANDLE)
913                                 {
914                                         unsigned int readerID = instance.createReader(terminalID);
915
916                                         ServerGDBus::getInstance().emitReaderInserted(readerID, (const char *)terminal);
917                                 }
918                         }
919                         break;
920
921                 case Terminal::NOTIFY_SE_NOT_AVAILABLE :
922                         {
923                                 ServerResource &instance = ServerResource::getInstance();
924                                 unsigned int readerID = IntegerHandle::INVALID_HANDLE;
925
926                                 _INFO("[NOTIFY_SE_NOT_AVAILABLE]");
927
928                                 readerID = instance.getReaderID((char *)terminal);
929
930                                 ServerGDBus::getInstance().emitReaderRemoved(
931                                         readerID, (const char *)terminal);
932
933                                 instance.removeReader(readerID);
934                         }
935                         break;
936
937                 default :
938                         _DBG("terminal [%s], event [%d], error [%d], user_param [%p]", (char *)terminal, event, error, user_param);
939                         break;
940                 }
941         }
942
943         unsigned int ServerResource::createReader(unsigned int terminalID)
944         {
945                 unsigned int result = -1;
946
947                 result = IntegerHandle::assignHandle();
948
949                 mapReaders.insert(make_pair(result, terminalID));
950
951                 return result;
952         }
953
954         unsigned int ServerResource::getReaderID(const char *name) const
955         {
956                 unsigned int result = IntegerHandle::INVALID_HANDLE,
957                         terminalID = IntegerHandle::INVALID_HANDLE;
958
959                 terminalID = getTerminalID(name);
960                 if (terminalID != IntegerHandle::INVALID_HANDLE)
961                 {
962                         map<unsigned int, unsigned int>::const_iterator item;
963
964                         for (item = mapReaders.begin();
965                                 item != mapReaders.end(); item++)
966                         {
967                                 if (item->second == terminalID)
968                                 {
969                                         result = item->first;
970                                         break;
971                                 }
972                         }
973                 }
974
975                 return result;
976         }
977
978         void ServerResource::removeReader(unsigned int readerID)
979         {
980                 map<unsigned int, unsigned int>::iterator item;
981
982                 if ((item = mapReaders.find(readerID)) != mapReaders.end())
983                 {
984                         item->second = IntegerHandle::INVALID_HANDLE;
985                 }
986         }
987
988         ServerChannel *ServerResource::createInternalChannel(Terminal *terminal,
989                 int channelType)
990         {
991                 int channelNum = 0;
992                 ServerChannel *channel = NULL;
993
994                 /* open logical channel */
995                 if (channelType == 1) {
996                         channelNum = _openLogicalChannel(terminal);
997                         if (channelNum > 0) {
998                                 _DBG("channelNum [%d]", channelNum);
999                         } else {
1000                                 _ERR("_openLogicalChannel failed [%d]", channelNum);
1001                                 throw ExceptionBase(SCARD_ERROR_NOT_ENOUGH_RESOURCE);
1002                         }
1003                 }
1004
1005                 /* create channel instance */
1006                 channel = new ServerChannel(NULL, NULL, channelNum, terminal);
1007
1008                 return channel;
1009         }
1010
1011         bool ServerResource::isAuthorizedNFCAccess(Terminal *terminal,
1012                 const ByteArray &aid, const vector<ByteArray> &hashes)
1013         {
1014                 bool result = false;
1015                 ServerChannel *channel;
1016
1017                 if (terminal == NULL) {
1018                         return result;
1019                 }
1020
1021                 channel = createInternalChannel(terminal, 1);
1022                 if (channel != NULL) {
1023                         AccessControlList *acl = getAccessControlList(channel);
1024                         if (acl == NULL) {
1025                                 /* load access control defined by Global Platform */
1026                                 acl = new GPACE();
1027                                 if (acl != NULL) {
1028                                         int ret;
1029
1030                                         ret = acl->loadACL(channel);
1031                                         if (ret >= SCARD_ERROR_OK) {
1032                                                 addAccessControlList(channel, acl);
1033                                         } else {
1034                                                 _ERR("unknown error, 0x%x", -ret);
1035
1036                                                 delete acl;
1037                                                 acl = NULL;
1038                                         }
1039                                 } else {
1040                                         _ERR("alloc failed");
1041                                 }
1042                         } else {
1043                                 acl->updateACL(channel);
1044                         }
1045
1046                         if (acl != NULL) {
1047                                 result = acl->isAuthorizedNFCAccess(aid, hashes);
1048                         } else {
1049                                 _ERR("acl is null");
1050                         }
1051
1052                         delete channel;
1053                 } else {
1054                         _ERR("alloc failed");
1055                 }
1056
1057                 return result;
1058         }
1059
1060         bool ServerResource::isAuthorizedAccess(Terminal *terminal,
1061                 const ByteArray &aid, const vector<ByteArray> &hashes)
1062         {
1063                 bool result = false;
1064                 ServerChannel *channel;
1065
1066                 if (terminal == NULL) {
1067                         return result;
1068                 }
1069
1070                 channel = createInternalChannel(terminal, 1);
1071                 if (channel != NULL) {
1072                         AccessControlList *acl = getAccessControlList(channel);
1073                         if (acl == NULL) {
1074                                 /* load access control defined by Global Platform */
1075                                 acl = new GPACE();
1076                                 if (acl != NULL) {
1077                                         int ret;
1078
1079                                         ret = acl->loadACL(channel);
1080                                         if (ret >= SCARD_ERROR_OK) {
1081                                                 addAccessControlList(channel, acl);
1082                                         } else {
1083                                                 _ERR("unknown error, 0x%x", -ret);
1084
1085                                                 delete acl;
1086                                                 acl = NULL;
1087                                         }
1088                                 } else {
1089                                         _ERR("alloc failed");
1090                                 }
1091                         } else {
1092                                 acl->updateACL(channel);
1093                         }
1094
1095                         if (acl != NULL) {
1096                                 result = acl->isAuthorizedAccess(aid, hashes);
1097                         } else {
1098                                 _ERR("acl is null");
1099                         }
1100
1101                         delete channel;
1102                 } else {
1103                         _ERR("alloc failed");
1104                 }
1105
1106                 return result;
1107         }
1108         /* LCOV_EXCL_STOP */
1109
1110         void ServerResource::finish()
1111         {
1112                 if (getClientCount() == 0) {
1113                         _INFO("no client connected. terminate server");
1114
1115                         smartcard_daemon_exit();
1116                 }
1117         }
1118 } /* namespace smartcard_service_api */