/*
-* 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>
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;
if ((instance = getService(socket, context)) != NULL)
{
- if ((temp = getTerminal(terminalID)) != NULL)
+ if ((temp = getTerminalByReaderID(readerID)) != NULL)
{
result = instance->openSession(temp, certHashes, caller);
}
}
}
- 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;
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);
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;
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)
{
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
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
{
SCARD_DEBUG("register success [%s] [%p] [%s] [%p]", library, libHandle, terminal->getName(), terminal);
+ if (terminal->isSecureElementPresence() == true)
+ {
+ createReader(handle);
+ }
+
result = true;
}
else
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)
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++;
+ }
+ }
}
}
{
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);
+ }
+ }
}
}
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;
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 */