Adjust comment
[platform/core/connectivity/smartcard-service.git] / server / ServerResource.cpp
index 0e3c5a2..7cc61dc 100644 (file)
@@ -1,19 +1,18 @@
 /*
-* Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
+ * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 /* standard library header */
 #include <stdio.h>
@@ -287,7 +286,41 @@ namespace smartcard_service_api
                return result;
        }
 
-       unsigned int ServerResource::createSession(int socket, unsigned int context, unsigned int terminalID, vector<ByteArray> &certHashes, void *caller)
+       Terminal *ServerResource::getTerminalByReaderID(unsigned int readerID)
+       {
+               Terminal *result = NULL;
+               map<unsigned int, unsigned int>::iterator item;
+
+               if ((item = mapReaders.find(readerID)) != mapReaders.end())
+               {
+                       result = getTerminal(item->second);
+               }
+               else
+               {
+                       SCARD_DEBUG_ERR("Terminal doesn't exist, reader ID [%d]", readerID);
+               }
+
+               return result;
+       }
+
+       unsigned int ServerResource::getTerminalID(const char *name)
+       {
+               unsigned int result = IntegerHandle::INVALID_HANDLE;
+               map<unsigned int, Terminal *>::iterator item;
+
+               for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
+               {
+                       if (strncmp(name, item->second->getName(), strlen(name)) == 0)
+                       {
+                               result = item->first;
+                               break;
+                       }
+               }
+
+               return result;
+       }
+
+       unsigned int ServerResource::createSession(int socket, unsigned int context, unsigned int readerID, vector<ByteArray> &certHashes, void *caller)
        {
                unsigned int result = -1;
                Terminal *temp = NULL;
@@ -295,7 +328,7 @@ namespace smartcard_service_api
 
                if ((instance = getService(socket, context)) != NULL)
                {
-                       if ((temp = getTerminal(terminalID)) != NULL)
+                       if ((temp = getTerminalByReaderID(readerID)) != NULL)
                        {
                                result = instance->openSession(temp, certHashes, caller);
                        }
@@ -356,7 +389,7 @@ namespace smartcard_service_api
                }
        }
 
-       bool ServerResource::_isAuthorizedAccess(Terminal *terminal, int pid, ByteArray aid, vector<ByteArray> &hashes)
+       bool ServerResource::_isAuthorizedAccess(ServerChannel *channel, int pid, ByteArray aid, vector<ByteArray> &hashes)
        {
                bool result = true;
 
@@ -369,9 +402,12 @@ namespace smartcard_service_api
                if (strncmp(filename, "ozD3Dw1MZruTDKHWGgYaDib2B2LV4/nfT+8b/g1Vsk8=", sizeof(filename)) != 0)
                {
                        /* request open channel sequence */
-                       if ((acList = getAccessControlList(terminal)) != NULL)
+                       if ((acList = getAccessControlList(channel)) != NULL)
                        {
 #if 1
+                               PKCS15 pkcs15(channel);
+
+                               acList->loadACL(channel);
                                result = acList->isAuthorizedAccess(aid, hashes);
 #else
                                result = acList->isAuthorizedAccess(aid, session->packageCert);
@@ -388,6 +424,7 @@ namespace smartcard_service_api
                return result;
        }
 
+#if 0
        unsigned int ServerResource::_createChannel(Terminal *terminal, ServiceInstance *service, int channelType, unsigned int sessionID, ByteArray aid)
        {
                unsigned int result = IntegerHandle::INVALID_HANDLE;
@@ -458,6 +495,156 @@ namespace smartcard_service_api
 
                return result;
        }
+#else
+       int ServerResource::_openLogicalChannel(Terminal *terminal)
+       {
+               int result = -1;
+               int rv = 0;
+               ByteArray command;
+               ByteArray response;
+
+               /* open channel */
+               command = APDUHelper::generateAPDU(APDUHelper::COMMAND_OPEN_LOGICAL_CHANNEL, 0, ByteArray::EMPTY);
+               rv = terminal->transmitSync(command, response);
+               if (rv == 0 && response.getLength() >= 2)
+               {
+                       ResponseHelper resp(response);
+
+                       if (resp.getStatus() == 0)
+                       {
+                               result = resp.getDataField()[0];
+                       }
+                       else
+                       {
+                               SCARD_DEBUG_ERR("status word [%d][ %02X %02X ]", resp.getStatus(), resp.getSW1(), resp.getSW2());
+                               if (0)
+                               {
+                                       /* TODO : if there is no more channel, return error code */
+                                       SCARD_DEBUG_ERR("no more logical channel");
+                                       result = -2;
+                               }
+                       }
+               }
+               else
+               {
+                       SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, response.getLength());
+               }
+
+               return result;
+       }
+
+       int ServerResource::_closeLogicalChannel(Terminal *terminal, int channelNum)
+       {
+               int result = -1;
+               int rv = 0;
+               ByteArray command;
+               ByteArray response;
+
+               /* open channel */
+               command = APDUHelper::generateAPDU(APDUHelper::COMMAND_CLOSE_LOGICAL_CHANNEL, channelNum, ByteArray::EMPTY);
+               rv = terminal->transmitSync(command, response);
+               if (rv == 0 && response.getLength() >= 2)
+               {
+                       ResponseHelper resp(response);
+
+                       if (resp.getStatus() == 0)
+                       {
+                               SCARD_DEBUG("channel closed [%d]", channelNum);
+                               result = 0;
+                       }
+                       else
+                       {
+                               SCARD_DEBUG_ERR("status word [%d][ %02X %02X ]", resp.getStatus(), resp.getSW1(), resp.getSW2());
+                       }
+               }
+               else
+               {
+                       SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, response.getLength());
+               }
+
+               return result;
+       }
+
+       unsigned int ServerResource::_createChannel(Terminal *terminal, ServiceInstance *service, int channelType, unsigned int sessionID, ByteArray aid)
+       {
+               unsigned int result = IntegerHandle::INVALID_HANDLE;
+               int channelNum = 0;
+               ServerChannel *channel = NULL;
+
+               /* open logical channel */
+               if (channelType == 1)
+               {
+                       channelNum = _openLogicalChannel(terminal);
+                       if (channelNum > 0)
+                       {
+                               SCARD_DEBUG("channelNum [%d]", result);
+                       }
+                       else
+                       {
+                               SCARD_DEBUG_ERR("_openLogicalChannel failed [%d]", channelNum);
+                               return result;
+                       }
+               }
+
+               /* create channel instance */
+               result = service->openChannel(sessionID, channelNum, ByteArray::EMPTY);
+               if (result == IntegerHandle::INVALID_HANDLE)
+               {
+                       SCARD_DEBUG_ERR("channel is null.");
+
+                       /* close logical channel */
+                       if (channelNum > 0)
+                       {
+                               _closeLogicalChannel(terminal, channelNum);
+                       }
+                       return result;
+               }
+
+               channel = service->getChannel(result);
+
+               /* check */
+               if (_isAuthorizedAccess(channel, service->getParent()->getPID(),
+                               aid, service->getParent()->getCertificationHashes()) == true)
+               {
+                       int rv = 0;
+                       ByteArray command;
+                       ByteArray response;
+
+                       /* select aid */
+                       command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_DF_NAME, channelNum, aid);
+                       rv = channel->transmitSync(command, response);
+                       if (rv == 0 && response.getLength() >= 2)
+                       {
+                               ResponseHelper resp(response);
+
+                               if (resp.getStatus() == 0)
+                               {
+                                       channel->selectResponse = response;
+                                       /* remove privilege mode */
+                                       channel->unsetPrivilegeMode();
+                               }
+                               else
+                               {
+                                       SCARD_DEBUG_ERR("status word [%d][ %02X %02X ]", resp.getStatus(), resp.getSW1(), resp.getSW2());
+                               }
+                       }
+                       else
+                       {
+                               SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, response.getLength());
+                       }
+               }
+               else
+               {
+                       SCARD_DEBUG_ERR("unauthorized access");
+
+                       service->closeChannel(result);
+                       result = IntegerHandle::INVALID_HANDLE;
+               }
+
+
+               return result;
+       }
+#endif
 
        unsigned int ServerResource::createChannel(int socket, unsigned int context, unsigned int sessionID, int channelType, ByteArray aid)
        {
@@ -475,13 +662,10 @@ namespace smartcard_service_api
                                session = service->getSession(sessionID);
                                if (terminal != NULL && session != NULL)
                                {
-                                       if (_isAuthorizedAccess(terminal, service->getParent()->getPID(), aid, service->getParent()->getCertificationHashes()) == true)
+                                       result = _createChannel(terminal, service, channelType, sessionID, aid);
+                                       if (result == IntegerHandle::INVALID_HANDLE)
                                        {
-                                               result = _createChannel(terminal, service, channelType, sessionID, aid);
-                                       }
-                                       else
-                                       {
-                                               SCARD_DEBUG_ERR("access denied [%d]", sessionID);
+                                               SCARD_DEBUG_ERR("create channel failed [%d]", sessionID);
                                        }
                                }
                                else
@@ -540,19 +724,37 @@ namespace smartcard_service_api
 
                if ((item = mapACL.find(terminal)) == mapACL.end())
                {
-                       ServerChannel *channel = new ServerChannel(NULL, NULL, 0, terminal);
-                       if (channel != NULL)
+                       /* load access control */
+                       result = new GPSEACL();
+                       if (result != NULL)
                        {
-                               /* load access control */
-                               result = new GPSEACL(channel);
-                               if (result != NULL)
-                               {
-                                       mapACL.insert(make_pair(terminal, result));
-                               }
-                               else
-                               {
-                                       SCARD_DEBUG_ERR("alloc failed");
-                               }
+                               mapACL.insert(make_pair(terminal, result));
+                       }
+                       else
+                       {
+                               SCARD_DEBUG_ERR("alloc failed");
+                       }
+               }
+               else
+               {
+                       result = item->second;
+               }
+
+               return result;
+       }
+
+       AccessControlList *ServerResource::getAccessControlList(ServerChannel *channel)
+       {
+               AccessControlList *result = NULL;
+               map<Terminal *, AccessControlList *>::iterator item;
+
+               if ((item = mapACL.find(channel->getTerminal())) == mapACL.end())
+               {
+                       /* load access control */
+                       result = new GPSEACL();
+                       if (result != NULL)
+                       {
+                               mapACL.insert(make_pair(channel->getTerminal(), result));
                        }
                        else
                        {
@@ -616,6 +818,11 @@ namespace smartcard_service_api
 
                                SCARD_DEBUG("register success [%s] [%p] [%s] [%p]", library, libHandle, terminal->getName(), terminal);
 
+                               if (terminal->isSecureElementPresence() == true)
+                               {
+                                       createReader(handle);
+                               }
+
                                result = true;
                        }
                        else
@@ -698,14 +905,14 @@ namespace smartcard_service_api
 
        bool ServerResource::isValidReaderHandle(unsigned int reader)
        {
-               return (getTerminal(reader) != NULL);
+               return (getTerminalByReaderID(reader) != NULL);
        }
 
        bool ServerResource::isValidSessionHandle(int socket, unsigned int context, unsigned int session)
        {
                ServiceInstance *instance = NULL;
 
-               return (((instance = getService(socket, context)) != NULL) && (getService(socket, context)->isVaildSessionHandle(session)));
+               return (((instance = getService(socket, context)) != NULL) && (instance->isVaildSessionHandle(session)));
        }
 
        int ServerResource::getReadersInformation(ByteArray &info)
@@ -716,16 +923,24 @@ namespace smartcard_service_api
                unsigned int offset = 0;
                unsigned int nameLen = 0;
 
-               if (mapTerminals.size() > 0)
+               if (mapReaders.size() > 0)
                {
-                       map<unsigned int, Terminal *>::iterator item;
+                       Terminal *terminal = NULL;
+                       map<unsigned int, unsigned int>::iterator item;
 
-                       for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
+                       for (item = mapReaders.begin(); item != mapReaders.end(); item++)
                        {
-                               if (item->second->isSecureElementPresence())
+                               if (item->second != IntegerHandle::INVALID_HANDLE)
                                {
-                                       length += sizeof(nameLen) + strlen(item->second->getName()) + sizeof(unsigned int);
-                                       result++;
+                                       terminal = getTerminal(item->second);
+                                       if (terminal != NULL)
+                                       {
+                                               if (terminal->isSecureElementPresence())
+                                               {
+                                                       length += sizeof(nameLen) + strlen(terminal->getName()) + sizeof(unsigned int);
+                                                       result++;
+                                               }
+                                       }
                                }
                        }
 
@@ -734,20 +949,27 @@ namespace smartcard_service_api
                        {
                                memset(buffer, 0, length);
 
-                               for (item = mapTerminals.begin(); item != mapTerminals.end(); item++)
+                               for (item = mapReaders.begin(); item != mapReaders.end(); item++)
                                {
-                                       if (item->second->isSecureElementPresence())
+                                       if (item->second != IntegerHandle::INVALID_HANDLE)
                                        {
-                                               nameLen = strlen(item->second->getName());
-
-                                               memcpy(buffer + offset, &nameLen, sizeof(nameLen));
-                                               offset += sizeof(nameLen);
-
-                                               memcpy(buffer + offset, item->second->getName(), nameLen);
-                                               offset += nameLen;
-
-                                               memcpy(buffer + offset, &item->first, sizeof(unsigned int));
-                                               offset += sizeof(unsigned int);
+                                               terminal = getTerminal(item->second);
+                                               if (terminal != NULL)
+                                               {
+                                                       if (terminal->isSecureElementPresence())
+                                                       {
+                                                               nameLen = strlen(terminal->getName());
+
+                                                               memcpy(buffer + offset, &nameLen, sizeof(nameLen));
+                                                               offset += sizeof(nameLen);
+
+                                                               memcpy(buffer + offset, terminal->getName(), nameLen);
+                                                               offset += nameLen;
+
+                                                               memcpy(buffer + offset, &item->first, sizeof(unsigned int));
+                                                               offset += sizeof(unsigned int);
+                                                       }
+                                               }
                                        }
                                }
 
@@ -784,37 +1006,48 @@ namespace smartcard_service_api
 
        void ServerResource::terminalCallback(void *terminal, int event, int error, void *user_param)
        {
-               SCARD_BEGIN();
+               SCARD_DEBUG("terminal [%s], event [%d], error [%d], user_param [%p]", (char *)terminal, event, error, user_param);
 
                switch (event)
                {
                case Terminal::NOTIFY_SE_AVAILABLE :
                        {
+                               ServerResource &instance = ServerResource::getInstance();
+                               unsigned int terminalID = IntegerHandle::INVALID_HANDLE;
                                Message msg;
 
                                SCARD_DEBUG("[NOTIFY_SE_AVAILABLE]");
-                               SCARD_DEBUG("terminal [%s], error [%d], user_param [%p]", (char *)terminal, error, user_param);
 
-                               /* send all client to refresh reader */
-                               msg.message = msg.MSG_NOTIFY_SE_INSERTED;
-                               msg.data.setBuffer((unsigned char *)terminal, strlen((char *)terminal) + 1);
+                               terminalID = instance.getTerminalID((char *)terminal);
+                               if (terminalID != IntegerHandle::INVALID_HANDLE)
+                               {
+                                       /* send all client to refresh reader */
+                                       msg.message = msg.MSG_NOTIFY_SE_INSERTED;
+                                       msg.param1 = instance.createReader(terminalID);
+                                       msg.data.setBuffer((unsigned char *)terminal, strlen((char *)terminal) + 1);
 
-                               ServerResource::getInstance().sendMessageToAllClients(msg);
+                                       instance.sendMessageToAllClients(msg);
+                               }
                        }
                        break;
 
                case Terminal::NOTIFY_SE_NOT_AVAILABLE :
                        {
+                               ServerResource &instance = ServerResource::getInstance();
+                               unsigned int readerID = IntegerHandle::INVALID_HANDLE;
                                Message msg;
 
                                SCARD_DEBUG("[NOTIFY_SE_NOT_AVAILABLE]");
-                               SCARD_DEBUG("terminal [%s], error [%d], user_param [%p]", (char *)terminal, error, user_param);
+
+                               readerID = instance.getReaderID((char *)terminal);
 
                                /* send all client to refresh reader */
                                msg.message = msg.MSG_NOTIFY_SE_REMOVED;
+                               msg.param1 = readerID;
                                msg.data.setBuffer((unsigned char *)terminal, strlen((char *)terminal) + 1);
 
-                               ServerResource::getInstance().sendMessageToAllClients(msg);
+                               instance.sendMessageToAllClients(msg);
+                               instance.removeReader(readerID);
                        }
                        break;
 
@@ -822,8 +1055,49 @@ namespace smartcard_service_api
                        SCARD_DEBUG("terminal [%s], event [%d], error [%d], user_param [%p]", (char *)terminal, event, error, user_param);
                        break;
                }
+       }
 
-               SCARD_END();
+       unsigned int ServerResource::createReader(unsigned int terminalID)
+       {
+               unsigned int result = -1;
+
+               result = IntegerHandle::assignHandle();
+
+               mapReaders.insert(make_pair(result, terminalID));
+
+               return result;
+       }
+
+       unsigned int ServerResource::getReaderID(const char *name)
+       {
+               unsigned int result = IntegerHandle::INVALID_HANDLE, terminalID = IntegerHandle::INVALID_HANDLE;
+
+               terminalID = getTerminalID(name);
+               if (terminalID != IntegerHandle::INVALID_HANDLE)
+               {
+                       map<unsigned int, unsigned int>::iterator item;
+
+                       for (item = mapReaders.begin(); item != mapReaders.end(); item++)
+                       {
+                               if (item->second == terminalID)
+                               {
+                                       result = item->first;
+                                       break;
+                               }
+                       }
+               }
+
+               return result;
+       }
+
+       void ServerResource::removeReader(unsigned int readerID)
+       {
+               map<unsigned int, unsigned int>::iterator item;
+
+               if ((item = mapReaders.find(readerID)) != mapReaders.end())
+               {
+                       item->second = IntegerHandle::INVALID_HANDLE;
+               }
        }
 
 } /* namespace smartcard_service_api */