Add card Inserted implementation and fix bug
[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 [%s]", 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         {
295                 unsigned int result = -1;
296                 ServiceInstance *service = NULL;
297
298                 if ((service = getService(name, handle)) != NULL) {
299                         if (service->isVaildSessionHandle(sessionID) == true) {
300                                 ServerSession *session = NULL;
301                                 Terminal *terminal = NULL;
302
303                                 terminal = service->getTerminal(sessionID);
304                                 session = service->getSession(sessionID);
305                                 if (terminal != NULL && session != NULL) {
306                                         if (terminal->open() == true) {
307                                                 result = _createChannel(terminal, service, channelType, sessionID, aid);
308                                                 if (result == IntegerHandle::INVALID_HANDLE) {
309                                                         _ERR("create channel failed [%d]", sessionID);
310
311                                                         terminal->close();
312                                                 }
313                                         } else {
314                                                 _ERR("terminal open failed");
315                                                 throw ExceptionBase(SCARD_ERROR_UNAVAILABLE);
316                                         }
317                                 } else {
318                                         _ERR("session is invalid [%d]", sessionID);
319                                         throw ExceptionBase(SCARD_ERROR_UNAVAILABLE);
320                                 }
321                         } else {
322                                 _ERR("session is invalid [%d]", sessionID);
323                                 throw ExceptionBase(SCARD_ERROR_ILLEGAL_STATE);
324                         }
325                 } else {
326                         _ERR("getService is failed, name [%s], handle [%d]", name, handle);
327                         throw ExceptionBase(SCARD_ERROR_UNAVAILABLE);
328                 }
329
330                 return result;
331         }
332
333         Channel *ServerResource::getChannel(const char *name, unsigned int handle, unsigned int channelID)
334         {
335                 Channel *result = NULL;
336                 ServiceInstance *instance = NULL;
337
338                 if ((instance = getService(name, handle)) != NULL) {
339                         result = instance->getChannel(channelID);
340                 } else {
341                         _ERR("Channel doesn't exist : name [%s], handle [%d], handle [%d]", name, handle, channelID);
342                 }
343
344                 return result;
345         }
346
347         void ServerResource::removeChannel(const char *name, unsigned int handle, unsigned int channelID)
348         {
349                 ServiceInstance *instance = NULL;
350
351                 if ((instance = getService(name, handle)) != NULL) {
352                         ServerChannel *channel;
353                         Terminal *terminal = NULL;
354
355                         channel = instance->getChannel(channelID);
356                         if (channel != NULL) {
357                                 terminal = channel->getTerminal();
358                         }
359
360                         instance->closeChannel(channelID);
361
362                         if (terminal != NULL) {
363                                 terminal->close();
364                         }
365                 } else {
366                         _ERR("getService doesn't exist : name [%s], handle [%d]", name, handle);
367                 }
368         }
369
370         Terminal *ServerResource::getTerminal(unsigned int terminalID)
371         {
372                 Terminal *result = NULL;
373                 map<unsigned int, Terminal *>::iterator item;
374
375                 if ((item = mapTerminals.find(terminalID)) != mapTerminals.end()) {
376                         result = item->second;
377                 } else {
378                         _ERR("Terminal doesn't exist [%d]", terminalID);
379                 }
380
381                 return result;
382         }
383
384         const Terminal *ServerResource::getTerminal(unsigned int terminalID) const
385         {
386                 const Terminal *result = NULL;
387                 map<unsigned int, Terminal *>::const_iterator item;
388
389                 if ((item = mapTerminals.find(terminalID)) != mapTerminals.end()) {
390                         result = item->second;
391                 } else {
392                         _ERR("Terminal doesn't exist [%d]", terminalID);
393                 }
394
395                 return result;
396         }
397
398         Terminal *ServerResource::getTerminal(const char *name)
399         {
400                 Terminal *result = NULL;
401                 map<unsigned int, Terminal *>::iterator item;
402
403                 for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
404                 {
405                         if (strncmp(name, item->second->getName(), strlen(name)) == 0)
406                         {
407                                 result = item->second;
408                                 break;
409                         }
410                 }
411
412                 return result;
413         }
414
415         Terminal *ServerResource::getTerminalByReaderID(unsigned int readerID)
416         {
417                 Terminal *result = NULL;
418                 map<unsigned int, unsigned int>::iterator item;
419
420                 if ((item = mapReaders.find(readerID)) != mapReaders.end()) {
421                         result = getTerminal(item->second);
422                 } else {
423                         _ERR("Terminal doesn't exist, reader ID [%d]", readerID);
424                 }
425
426                 return result;
427         }
428
429         const Terminal *ServerResource::getTerminalByReaderID(unsigned int readerID) const
430         {
431                 const Terminal *result = NULL;
432                 map<unsigned int, unsigned int>::const_iterator item;
433
434                 if ((item = mapReaders.find(readerID)) != mapReaders.end()) {
435                         result = getTerminal(item->second);
436                 } else {
437                         _ERR("Terminal doesn't exist, reader ID [%d]", readerID);
438                 }
439
440                 return result;
441         }
442
443         unsigned int ServerResource::getTerminalID(const char *name) const
444         {
445                 unsigned int result = IntegerHandle::INVALID_HANDLE;
446                 map<unsigned int, Terminal *>::const_iterator item;
447
448                 for (item = mapTerminals.begin();
449                         item != mapTerminals.end(); item++)
450                 {
451                         if (strncmp(name, item->second->getName(),
452                                 strlen(name)) == 0)
453                         {
454                                 result = item->first;
455                                 break;
456                         }
457                 }
458
459                 return result;
460         }
461
462         bool ServerResource::_isAuthorizedAccess(ServerChannel *channel,
463                 const ByteArray &aid, const vector<ByteArray> &hashes)
464         {
465                 bool result = false;
466                 AccessControlList *acList = NULL;
467
468                 /* request open channel sequence */
469                 if ((acList = getAccessControlList(channel)) == NULL) {
470                         /* load access control defined by Global Platform */
471                         GPACE *acl = new GPACE();
472                         if (acl != NULL) {
473                                 int ret;
474
475                                 ret = acl->loadACL(channel);
476                                 if (ret >= SCARD_ERROR_OK) {
477                                         acList = acl;
478                                         addAccessControlList(channel, acList);
479                                 } else {
480                                         _ERR("unknown error, 0x%x", -ret);
481                                         delete acl;
482                                 }
483                         } else {
484                                 _ERR("alloc failed");
485                         }
486                 } else {
487                         acList->loadACL(channel);
488                 }
489
490                 if (acList != NULL) {
491                         result = acList->isAuthorizedAccess(aid, hashes);
492                 }
493
494                 return result;
495         }
496
497         int ServerResource::_openLogicalChannel(Terminal *terminal)
498         {
499                 int result = -1;
500                 int rv = 0;
501                 ByteArray command;
502                 ByteArray response;
503
504                 /* open channel */
505                 command = APDUHelper::generateAPDU(APDUHelper::COMMAND_OPEN_LOGICAL_CHANNEL, 0, ByteArray::EMPTY);
506
507                 _DBG("command [%zu] : %s", command.size(), command.toString().c_str());
508
509                 rv = terminal->transmitSync(command, response);
510                 if (rv == 0 && response.size() >= 2) {
511                         ResponseHelper resp(response);
512
513                         if (resp.getStatus() >= 0) {
514                                 result = resp.getDataField()[0];
515                         } else {
516                                 result = resp.getStatus();
517                         }
518                 } else {
519                         _ERR("transmitSync failed, rv [%d], length [%zu]", rv, response.size());
520                 }
521
522                 return result;
523         }
524
525         int ServerResource::_closeLogicalChannel(Terminal *terminal, int channelNum)
526         {
527                 int result = SCARD_ERROR_UNKNOWN;
528                 int rv = 0;
529                 ByteArray command;
530                 ByteArray response;
531
532                 /* open channel */
533                 command = APDUHelper::generateAPDU(APDUHelper::COMMAND_CLOSE_LOGICAL_CHANNEL, channelNum, ByteArray::EMPTY);
534
535                 _DBG("command [%zu] : %s", command.size(), command.toString().c_str());
536
537                 rv = terminal->transmitSync(command, response);
538                 if (rv == 0 && response.size() >= 2) {
539                         ResponseHelper resp(response);
540
541                         if (resp.getStatus() >= 0) {
542                                 _DBG("channel closed [%d]", channelNum);
543                                 result = SCARD_ERROR_OK;
544                         } else {
545                                 _ERR("status word [ %02X %02X ]", resp.getSW1(), resp.getSW2());
546                         }
547                 } else {
548                         _ERR("select apdu is failed, rv [%d], length [%zu]", rv, response.size());
549                 }
550
551                 return result;
552         }
553
554         unsigned int ServerResource::_createChannel(Terminal *terminal,
555                 ServiceInstance *service, int channelType,
556                 unsigned int sessionID, const ByteArray &aid)
557         {
558                 unsigned int result = IntegerHandle::INVALID_HANDLE;
559                 int channelNum = 0;
560                 ServerChannel *channel = NULL;
561
562                 /* open logical channel */
563                 if (channelType == 1) {
564                         channelNum = _openLogicalChannel(terminal);
565                         if (channelNum > 0) {
566                                 _DBG("channelNum [%d]", channelNum);
567                         } else {
568                                 _ERR("_openLogicalChannel failed [%d]", channelNum);
569                                 throw ExceptionBase(SCARD_ERROR_NOT_ENOUGH_RESOURCE);
570                         }
571                 }
572
573                 /* create channel instance */
574                 result = service->openChannel(sessionID, channelNum, ByteArray::EMPTY);
575                 if (result == IntegerHandle::INVALID_HANDLE)
576                 {
577                         _ERR("channel is null.");
578
579                         /* close logical channel */
580                         if (channelNum > 0)
581                         {
582                                 _closeLogicalChannel(terminal, channelNum);
583                         }
584                         throw ExceptionBase(SCARD_ERROR_OUT_OF_MEMORY);
585                 }
586
587                 channel = service->getChannel(result);
588                 if(channel == NULL)
589                 {
590                         _ERR("channel is null.");
591
592                          throw ExceptionBase(SCARD_ERROR_OUT_OF_MEMORY);
593                 }
594
595                 /* NOTICE : This code is Access contol implementation in OpenMobile Specification.
596                  If you need the Access control in your target, please remove this comment.*/
597                 /*
598                 if (_isAuthorizedAccess(channel, aid,
599                         service->getParent()->getCertificationHashes()) == true) {
600                         int rv = 0;
601
602                         if (aid == PKCS15::PKCS15_AID) {
603                                 PKCS15 pkcs15(channel);
604
605                                 rv = pkcs15.select();
606                                 if (rv >= SCARD_ERROR_OK) {
607                                         channel->unsetPrivilegeMode();
608                                         channel->setSelectResponse(pkcs15.getSelectResponse());
609                                 } else {
610                                         _ERR("select failed, [%x]", -rv);
611
612                                         service->closeChannel(result);
613                                         throw ExceptionBase(SCARD_ERROR_IO_FAILED);
614                                 }
615                         } else {
616                                 FileObject file(channel);
617
618                                 rv = file.select(aid);
619                                 if (rv >= SCARD_ERROR_OK) {
620                                         channel->unsetPrivilegeMode();
621                                         channel->setSelectResponse(file.getSelectResponse());
622                                 } else {
623                                         _ERR("select failed [%x]", -rv);
624
625                                         service->closeChannel(result);
626                                         throw ExceptionBase(SCARD_ERROR_IO_FAILED);
627                                 }
628                         }
629                 } else {
630                         _ERR("unauthorized access");
631
632                         service->closeChannel(result);
633                         throw ExceptionBase(SCARD_ERROR_SECURITY_NOT_ALLOWED);
634                 }
635                 */
636                 return result;
637         }
638
639         void ServerResource::addAccessControlList(Terminal *terminal, AccessControlList *acl)
640         {
641                 map<Terminal *, AccessControlList *>::iterator item;
642
643                 if ((item = mapACL.find(terminal)) == mapACL.end()) {
644                         mapACL.insert(make_pair(terminal, acl));
645                 } else {
646                         item->second = acl;
647                 }
648         }
649
650         void ServerResource::addAccessControlList(ServerChannel *channel, AccessControlList *acl)
651         {
652                 map<Terminal *, AccessControlList *>::iterator item;
653
654                 if ((item = mapACL.find(channel->getTerminal())) == mapACL.end()) {
655                         mapACL.insert(make_pair(channel->getTerminal(), acl));
656                 } else {
657                         item->second = acl;
658                 }
659         }
660
661         AccessControlList *ServerResource::getAccessControlList(Terminal *terminal)
662         {
663                 AccessControlList *result = NULL;
664                 map<Terminal *, AccessControlList *>::iterator item;
665
666                 if ((item = mapACL.find(terminal)) != mapACL.end())
667                 {
668                         result = item->second;
669                 }
670
671                 return result;
672         }
673
674         AccessControlList *ServerResource::getAccessControlList(ServerChannel *channel)
675         {
676                 AccessControlList *result = NULL;
677                 map<Terminal *, AccessControlList *>::iterator item;
678
679                 if ((item = mapACL.find(channel->getTerminal())) != mapACL.end())
680                 {
681                         result = item->second;
682                 }
683
684                 return result;
685         }
686
687         Terminal *ServerResource::createInstance(void *library)
688         {
689                 Terminal *terminal = NULL;
690                 terminal_create_instance_fn createInstance = NULL;
691
692                 /* create se instance */
693                 createInstance = (terminal_create_instance_fn)dlsym(library, "create_instance");
694                 if (createInstance != NULL) {
695                         terminal = (Terminal *)createInstance();
696                         if (terminal != NULL) {
697                                 _DBG("terminal [%p]", terminal);
698                         } else {
699                                 _ERR("terminal is null");
700                         }
701                 } else {
702                         _ERR("create_instance is null [%d]", errno);
703                 }
704
705                 return terminal;
706         }
707
708         bool ServerResource::appendSELibrary(char *library)
709         {
710                 void *libHandle = NULL;
711                 bool result = false;
712
713                 libHandle = dlopen(library, RTLD_LAZY);
714                 if (libHandle != NULL) {
715                         Terminal *terminal = NULL;
716
717                         terminal = createInstance(libHandle);
718                         if (terminal != NULL) {
719                                 unsigned int handle = IntegerHandle::assignHandle();
720
721                                 mapTerminals.insert(make_pair(handle, terminal));
722                                 libraries.push_back(libHandle);
723
724                                 terminal->setStatusCallback(&ServerResource::terminalCallback);
725
726                                 _DBG("register success [%s] [%p] [%s] [%p]", library, libHandle, terminal->getName(), terminal);
727
728                                 if (terminal->isSecureElementPresence() == true) {
729                                         createReader(handle);
730                                 }
731
732                                 result = true;
733                         } else {
734                                 _ERR("terminal is null [%s]", library);
735
736                                 dlclose(libHandle);
737                         }
738                 } else {
739                         _ERR("it is not se file [%s] [%d]", library, errno);
740                 }
741
742                 return result;
743         }
744
745         int ServerResource::loadSecureElements()
746         {
747                 int result = 0;
748
749                 if (seLoaded == false) {
750                         DIR *dir;
751                         struct dirent *entry;
752
753                         if ((dir = opendir(OMAPI_SE_PATH)) != NULL) {
754                                 while ((entry = readdir(dir)) != NULL) {
755                                         if (strncmp(entry->d_name, ".", 1) != 0 &&
756                                                 strncmp(entry->d_name, "..", 2) != 0) {
757                                                 char fullPath[1024];
758                                                 /* TODO : need additional name rule :) */
759
760                                                 /* append each files */
761                                                 snprintf(fullPath, sizeof(fullPath),
762                                                         "%s/%s", OMAPI_SE_PATH, entry->d_name);
763
764                                                 SECURE_LOGD("se name [%s]", fullPath); //LCOV_EXCL_LINE
765
766                                                 result = appendSELibrary(fullPath);
767                                         }
768                                 }
769
770                                 closedir(dir);
771
772                                 seLoaded = true;
773                         } else {
774                                 result = -1;
775                         }
776                 }
777
778                 return result;
779         }
780
781         void ServerResource::unloadSecureElements()
782         {
783                 if (seLoaded == true)
784                 {
785                         size_t i;
786                         map<unsigned int, Terminal *>::iterator item;
787
788                         for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
789                         {
790                                 item->second->finalize();
791
792                                 IntegerHandle::releaseHandle(item->first);
793                         }
794
795                         mapTerminals.clear();
796
797                         for (i = 0; i < libraries.size(); i++)
798                         {
799                                 if (libraries[i] != NULL)
800                                         dlclose(libraries[i]);
801                         }
802
803                         libraries.clear();
804
805                         seLoaded = false;
806                 }
807         }
808
809         bool ServerResource::isValidReaderHandle(unsigned int reader) const
810         {
811                 return (getTerminalByReaderID(reader) != NULL);
812         }
813
814         void ServerResource::getReaders(vector<pair<unsigned int, string> > &readers) const
815         {
816                 const Terminal *terminal;
817                 map<unsigned int, unsigned int>::const_iterator item;
818
819                 readers.clear();
820
821                 for (item = mapReaders.begin(); item != mapReaders.end(); item++)
822                 {
823                         if (item->second != IntegerHandle::INVALID_HANDLE)
824                         {
825                                 terminal = getTerminal(item->second);
826                                 if (terminal != NULL && terminal->isSecureElementPresence() == true)
827                                 {
828                                         readers.push_back(make_pair(item->first, terminal->getName()));
829                                 }
830                         }
831                 }
832         }
833
834         int ServerResource::getReadersInformation(ByteArray &info) const
835         {
836                 int result = 0;
837                 unsigned char *buffer = NULL;
838                 unsigned int length = 0;
839                 unsigned int offset = 0;
840                 unsigned int nameLen = 0;
841
842                 if (mapReaders.size() > 0) {
843                         const Terminal *terminal = NULL;
844                         map<unsigned int, unsigned int>::const_iterator item;
845
846                         for (item = mapReaders.begin(); item != mapReaders.end(); item++) {
847                                 if (item->second != IntegerHandle::INVALID_HANDLE) {
848                                         terminal = getTerminal(item->second);
849                                         if (terminal != NULL) {
850                                                 if (terminal->getName() == NULL) {
851                                                         _ERR("terminal name is NULL");
852                                                         return -1;
853                                                 }
854
855                                                 if (terminal->isSecureElementPresence()) {
856                                                         length += sizeof(nameLen) + strlen(terminal->getName()) + sizeof(unsigned int);
857                                                         result++;
858                                                 }
859                                         }
860                                 }
861                         }
862
863                         buffer = new unsigned char[length + 1];
864                         if (buffer != NULL) {
865                                 memset(buffer, 0, length + 1);
866
867                                 for (item = mapReaders.begin(); item != mapReaders.end(); item++) {
868                                         if (item->second != IntegerHandle::INVALID_HANDLE) {
869                                                 terminal = getTerminal(item->second);
870                                                 if (terminal != NULL) {
871                                                         if (terminal->isSecureElementPresence()) {
872                                                                 nameLen = strlen(terminal->getName());
873
874                                                                 memcpy(buffer + offset, &nameLen, sizeof(nameLen));
875                                                                 offset += sizeof(nameLen);
876
877                                                                 memcpy(buffer + offset, terminal->getName(), nameLen);
878                                                                 offset += nameLen;
879
880                                                                 memcpy(buffer + offset, &item->first, sizeof(unsigned int));
881                                                                 offset += sizeof(unsigned int);
882
883                                                                 buffer[offset] = '\0';
884                                                         }
885                                                 }
886                                         }
887                                 }
888
889                                 info.assign(buffer, length);
890                                 delete []buffer;
891                         } else {
892                                 _ERR("alloc failed");
893                                 result = -1;
894                         }
895                 } else {
896                         _INFO("no secure element");
897                 }
898
899                 return result;
900         }
901
902         void ServerResource::terminalCallback(const void *terminal, int event,
903                 int error, void *user_param)
904         {
905                 _DBG("terminal [%s], event [%d], error [%d], user_param [%p]", (char *)terminal, event, error, user_param);
906
907                 switch (event)
908                 {
909                 case Terminal::NOTIFY_SE_AVAILABLE :
910                         {
911                                 ServerResource &instance = ServerResource::getInstance();
912                                 unsigned int terminalID = IntegerHandle::INVALID_HANDLE;
913
914                                 _INFO("[NOTIFY_SE_AVAILABLE]");
915
916                                 terminalID = instance.getTerminalID((char *)terminal);
917                                 if (terminalID != IntegerHandle::INVALID_HANDLE)
918                                 {
919                                         unsigned int readerID = instance.createReader(terminalID);
920
921                                         ServerGDBus::getInstance().emitReaderInserted(readerID, (const char *)terminal);
922                                 }
923                         }
924                         break;
925
926                 case Terminal::NOTIFY_SE_NOT_AVAILABLE :
927                         {
928                                 ServerResource &instance = ServerResource::getInstance();
929                                 unsigned int readerID = IntegerHandle::INVALID_HANDLE;
930
931                                 _INFO("[NOTIFY_SE_NOT_AVAILABLE]");
932
933                                 readerID = instance.getReaderID((char *)terminal);
934
935                                 ServerGDBus::getInstance().emitReaderRemoved(
936                                         readerID, (const char *)terminal);
937
938                                 instance.removeReader(readerID);
939                         }
940                         break;
941
942                 case Terminal::NOTIFY_CARD_AVAILABLE :
943                         {
944                                 ServerResource &instance = ServerResource::getInstance();
945                                 unsigned int readerID = IntegerHandle::INVALID_HANDLE;
946
947                                 _INFO("[NOTIFY_CARD_AVAILABLE]");
948
949                                 readerID = instance.getReaderID((char *)terminal);
950
951                                 ServerGDBus::getInstance().emitCardInserted(
952                                         readerID, (const char *)terminal);
953                         }
954                         break;
955                 case Terminal::NOTIFY_CARD_NOT_AVAILABLE :
956                         {
957                                 ServerResource &instance = ServerResource::getInstance();
958                                 unsigned int readerID = IntegerHandle::INVALID_HANDLE;
959
960                                 _INFO("[NOTIFY_CARD_NOT_AVAILABLE]");
961
962                                 readerID = instance.getReaderID((char *)terminal);
963
964                                 ServerGDBus::getInstance().emitCardRemoved(
965                                         readerID, (const char *)terminal);
966                         }
967                         break;
968                 default :
969                         _DBG("terminal [%s], event [%d], error [%d], user_param [%p]", (char *)terminal, event, error, user_param);
970                         break;
971                 }
972         }
973
974         unsigned int ServerResource::createReader(unsigned int terminalID)
975         {
976                 unsigned int result = -1;
977
978                 result = IntegerHandle::assignHandle();
979
980                 mapReaders.insert(make_pair(result, terminalID));
981
982                 return result;
983         }
984
985         unsigned int ServerResource::getReaderID(const char *name) const
986         {
987                 unsigned int result = IntegerHandle::INVALID_HANDLE,
988                         terminalID = IntegerHandle::INVALID_HANDLE;
989
990                 terminalID = getTerminalID(name);
991                 if (terminalID != IntegerHandle::INVALID_HANDLE)
992                 {
993                         map<unsigned int, unsigned int>::const_iterator item;
994
995                         for (item = mapReaders.begin();
996                                 item != mapReaders.end(); item++)
997                         {
998                                 if (item->second == terminalID)
999                                 {
1000                                         result = item->first;
1001                                         break;
1002                                 }
1003                         }
1004                 }
1005
1006                 return result;
1007         }
1008
1009         void ServerResource::removeReader(unsigned int readerID)
1010         {
1011                 map<unsigned int, unsigned int>::iterator item;
1012
1013                 if ((item = mapReaders.find(readerID)) != mapReaders.end())
1014                 {
1015                         item->second = IntegerHandle::INVALID_HANDLE;
1016                 }
1017         }
1018
1019         ServerChannel *ServerResource::createInternalChannel(Terminal *terminal,
1020                 int channelType)
1021         {
1022                 int channelNum = 0;
1023                 ServerChannel *channel = NULL;
1024
1025                 /* open logical channel */
1026                 if (channelType == 1) {
1027                         channelNum = _openLogicalChannel(terminal);
1028                         if (channelNum > 0) {
1029                                 _DBG("channelNum [%d]", channelNum);
1030                         } else {
1031                                 _ERR("_openLogicalChannel failed [%d]", channelNum);
1032                                 throw ExceptionBase(SCARD_ERROR_NOT_ENOUGH_RESOURCE);
1033                         }
1034                 }
1035
1036                 /* create channel instance */
1037                 channel = new ServerChannel(NULL, NULL, channelNum, terminal);
1038
1039                 return channel;
1040         }
1041
1042         bool ServerResource::isAuthorizedNFCAccess(Terminal *terminal,
1043                 const ByteArray &aid, const vector<ByteArray> &hashes)
1044         {
1045                 bool result = false;
1046                 ServerChannel *channel;
1047
1048                 if (terminal == NULL) {
1049                         return result;
1050                 }
1051
1052                 channel = createInternalChannel(terminal, 1);
1053                 if (channel != NULL) {
1054                         AccessControlList *acl = getAccessControlList(channel);
1055                         if (acl == NULL) {
1056                                 /* load access control defined by Global Platform */
1057                                 acl = new GPACE();
1058                                 if (acl != NULL) {
1059                                         int ret;
1060
1061                                         ret = acl->loadACL(channel);
1062                                         if (ret >= SCARD_ERROR_OK) {
1063                                                 addAccessControlList(channel, acl);
1064                                         } else {
1065                                                 _ERR("unknown error, 0x%x", -ret);
1066
1067                                                 delete acl;
1068                                                 acl = NULL;
1069                                         }
1070                                 } else {
1071                                         _ERR("alloc failed");
1072                                 }
1073                         } else {
1074                                 acl->updateACL(channel);
1075                         }
1076
1077                         if (acl != NULL) {
1078                                 result = acl->isAuthorizedNFCAccess(aid, hashes);
1079                         } else {
1080                                 _ERR("acl is null");
1081                         }
1082
1083                         delete channel;
1084                 } else {
1085                         _ERR("alloc failed");
1086                 }
1087
1088                 return result;
1089         }
1090
1091         bool ServerResource::isAuthorizedAccess(Terminal *terminal,
1092                 const ByteArray &aid, const vector<ByteArray> &hashes)
1093         {
1094                 bool result = false;
1095                 ServerChannel *channel;
1096
1097                 if (terminal == NULL) {
1098                         return result;
1099                 }
1100
1101                 channel = createInternalChannel(terminal, 1);
1102                 if (channel != NULL) {
1103                         AccessControlList *acl = getAccessControlList(channel);
1104                         if (acl == NULL) {
1105                                 /* load access control defined by Global Platform */
1106                                 acl = new GPACE();
1107                                 if (acl != NULL) {
1108                                         int ret;
1109
1110                                         ret = acl->loadACL(channel);
1111                                         if (ret >= SCARD_ERROR_OK) {
1112                                                 addAccessControlList(channel, acl);
1113                                         } else {
1114                                                 _ERR("unknown error, 0x%x", -ret);
1115
1116                                                 delete acl;
1117                                                 acl = NULL;
1118                                         }
1119                                 } else {
1120                                         _ERR("alloc failed");
1121                                 }
1122                         } else {
1123                                 acl->updateACL(channel);
1124                         }
1125
1126                         if (acl != NULL) {
1127                                 result = acl->isAuthorizedAccess(aid, hashes);
1128                         } else {
1129                                 _ERR("acl is null");
1130                         }
1131
1132                         delete channel;
1133                 } else {
1134                         _ERR("alloc failed");
1135                 }
1136
1137                 return result;
1138         }
1139         /* LCOV_EXCL_STOP */
1140
1141         void ServerResource::finish()
1142         {
1143                 if (getClientCount() == 0) {
1144                         _INFO("no client connected. terminate server");
1145
1146                         smartcard_daemon_exit();
1147                 }
1148         }
1149 } /* namespace smartcard_service_api */