Files
vsmartcard/virtualsmartcard/win32/BixVReader/TcpIpReader.cpp
2018-02-06 09:54:01 +01:00

331 lines
9.3 KiB
C++

#include "internal.h"
#include "VirtualSCReader.h"
#include "reader.h"
#include "device.h"
#include <winscard.h>
#include "memory.h"
#include <Sddl.h>
#include "sectionLocker.h"
int TcpIpReader::portBase;
TcpIpReader::TcpIpReader() {
rpcType=1;
state=SCARD_ABSENT;
}
void TcpIpReader::init(wchar_t *section) {
portBase=GetPrivateProfileInt(L"Driver",L"RPC_PORT_BASE",29500,L"BixVReader.ini");
port=GetPrivateProfileInt(section,L"TCP_PORT",portBase+(instance<<1),L"BixVReader.ini");
eventPort=GetPrivateProfileInt(section,L"TCP_EVENT_PORT",portBase+1+(instance<<1),L"BixVReader.ini");
InitializeCriticalSection(&eventSection);
InitializeCriticalSection(&dataSection);
}
bool TcpIpReader::CheckATR() {
if (AcceptSocket==NULL)
return false;
int read=0;
DWORD command=1;
if ((read=send(AcceptSocket,(char*)&command,sizeof(DWORD),NULL))<=0) {
return false;
}
DWORD size=0;
if ((read=recv(AcceptSocket,(char*)&size,sizeof(DWORD),MSG_WAITALL))<=0) {
return false;
}
if (size==0)
return false;
BYTE ATR[100];
if ((read=recv(AcceptSocket,(char*)ATR,size,MSG_WAITALL))<=0) {
return false;
}
return true;
}
bool TcpIpReader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen) {
if (AcceptSocket==NULL)
return false;
DWORD command=2;
DWORD read=0;
if ((read=send(AcceptSocket,(char*)&command,sizeof(DWORD),NULL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
DWORD dwAPDUlen=(DWORD)APDUlen;
if ((read=send(AcceptSocket,(char*)&dwAPDUlen,sizeof(DWORD),NULL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
if ((read=send(AcceptSocket,(char*)APDU,APDUlen,NULL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
DWORD dwRespLen=0;
if ((read=recv(AcceptSocket,(char*)&dwRespLen,sizeof(DWORD),MSG_WAITALL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
BYTE *p=(BYTE *)realloc(*Resp, dwRespLen);
if (p==NULL) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
*Resp=p;
if ((read=recv(AcceptSocket,(char*)*Resp,dwRespLen,MSG_WAITALL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
(*Resplen)=(int)dwRespLen;
return true;
}
bool TcpIpReader::QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset) {
if (AcceptSocket==NULL)
return false;
int read=0;
DWORD command=reset ? 0 : 1;
if ((read=send(AcceptSocket,(char*)&command,sizeof(DWORD),NULL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
DWORD size=0;
if ((read=recv(AcceptSocket,(char*)&size,sizeof(DWORD),MSG_WAITALL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
if (size==0)
return false;
if ((read=recv(AcceptSocket,(char*)ATR,size,MSG_WAITALL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
(*ATRsize)=size;
return true;
}
DWORD TcpIpReader::startServer() {
breakSocket=false;
wchar_t log[300];
while (true) {
//__try {
fd_set readfds;
FD_ZERO(&readfds);
// Set server socket to set
FD_SET(socket, &readfds);
// Timeout parameter
timeval tv = { 0 };
tv.tv_sec = 5;
while(true) {
if (breakSocket)
return 0;
FD_SET(socket, &readfds);
int ret = select(0, &readfds, NULL, NULL, &tv);
if (ret > 0)
break;
if (ret<0) {
DWORD err=WSAGetLastError();
swprintf(log,L"[BixVReader]wsa err:%x",err);
OutputDebugString(log);
if (err==0x2736) {
socket=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,0);
sockaddr_in Service;
Service.sin_family = AF_INET;
Service.sin_addr.s_addr = inet_addr("127.0.0.1");
Service.sin_port = htons((u_short)(port));
bind(socket, (SOCKADDR *) &Service, sizeof (Service));
listen(socket, 1);
FD_ZERO(&readfds);
// Set server socket to set
FD_SET(socket, &readfds);
}
}
}
SOCKET AcceptEventSocket;
AcceptSocket = accept(socket, NULL, NULL);
closesocket(socket);
socket=NULL;
if (AcceptSocket == INVALID_SOCKET)
return 0;
swprintf(log,L"[BixVReader]Socket connected:%i",AcceptSocket);
OutputDebugString(log);
FD_ZERO(&readfds);
// Set server socket to set
FD_SET(eventsocket, &readfds);
while(true) {
if (breakSocket)
return 0;
FD_SET(eventsocket, &readfds);
int ret = select(0, &readfds, NULL, NULL, &tv);
if (ret > 0)
break;
if (ret<0) {
DWORD err=WSAGetLastError();
swprintf(log,L"[BixVReader]wsa err:%x",err);
OutputDebugString(log);
if (err==0x2736) {
eventsocket=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,0);
sockaddr_in eventService;
eventService.sin_family = AF_INET;
eventService.sin_addr.s_addr = inet_addr("127.0.0.1");
eventService.sin_port = htons((u_short)(eventPort));
bind(eventsocket, (SOCKADDR *) &eventService, sizeof (eventService));
listen(eventsocket, 1);
FD_ZERO(&readfds);
// Set server socket to set
FD_SET(eventsocket, &readfds);
}
}
}
AcceptEventSocket = accept(eventsocket, NULL, NULL);
closesocket(eventsocket);
eventsocket=NULL;
if (AcceptEventSocket == INVALID_SOCKET)
return 0;
swprintf(log,L"[BixVReader]Event Socket connected:%i",AcceptEventSocket);
OutputDebugString(log);
if (!waitInsertIpr.empty()) {
// if I'm waiting for card insertion, verify if there's a card present
if (initProtocols()) {
SectionLocker lock(device->m_RequestLock);
while (!waitInsertIpr.empty()) {
CComPtr<IWDFIoRequest> ipr = waitInsertIpr.back();
if (ipr->UnmarkCancelable()==S_OK) {
ipr->CompleteWithInformation(STATUS_SUCCESS, 0);
}
waitInsertIpr.pop_back();
}
state=SCARD_SWALLOWED;
}
}
while (true) {
// wait for a command
DWORD command=0;
int read=0;
if ((read=recv(AcceptEventSocket,(char*)&command,sizeof(DWORD),MSG_WAITALL))<=0) {
state=SCARD_ABSENT;
OutputDebugString(L"[BixVReader]Socket error");
powered=0;
::shutdown(AcceptSocket,SD_BOTH);
::shutdown(AcceptEventSocket,SD_BOTH);
if (!waitRemoveIpr.empty()) {
// card inserted
SectionLocker lock(device->m_RequestLock);
while (!waitRemoveIpr.empty()) {
CComPtr<IWDFIoRequest> ipr = waitRemoveIpr.back();
OutputDebugString(L"[BixVReader]complete Wait Remove");
if (ipr->UnmarkCancelable()==S_OK) {
OutputDebugString(L"[BixVReader]Wait Remove Unmarked");
ipr->CompleteWithInformation(STATUS_SUCCESS, 0);
OutputDebugString(L"[BixVReader]Wait Remove Completed");
}
waitRemoveIpr.pop_back();
}
}
if (!waitInsertIpr.empty()) {
// card removed
SectionLocker lock(device->m_RequestLock);
while (!waitInsertIpr.empty()) {
CComPtr<IWDFIoRequest> ipr = waitInsertIpr.back();
OutputDebugString(L"[BixVReader]cancel Wait Remove");
if (ipr->UnmarkCancelable()==S_OK) {
OutputDebugString(L"[BixVReader]Wait Insert Unmarked");
ipr->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_CANCELLED), 0);
OutputDebugString(L"[BixVReader]Wait Insert Cancelled");
}
waitInsertIpr.pop_back();
}
}
break;
}
OutputDebugString(L"[BixVReader]Socket data");
if (command==0)
powered=0;
if (command==0 && !waitRemoveIpr.empty()) {
// card removed
SectionLocker lock(device->m_RequestLock);
state=SCARD_ABSENT;
while (!waitRemoveIpr.empty()) {
CComPtr<IWDFIoRequest> ipr = waitRemoveIpr.back();
if (ipr->UnmarkCancelable()==S_OK)
ipr->CompleteWithInformation(STATUS_SUCCESS, 0);
waitRemoveIpr.pop_back();
}
}
else if (command==1 && !waitInsertIpr.empty()) {
// card inserted
SectionLocker lock(device->m_RequestLock);
state=SCARD_SWALLOWED;
initProtocols();
while (!waitInsertIpr.empty()) {
CComPtr<IWDFIoRequest> ipr = waitInsertIpr.back();
if (ipr->UnmarkCancelable()==S_OK)
ipr->CompleteWithInformation(STATUS_SUCCESS, 0);
waitInsertIpr.pop_back();
}
}
}
//}
//__except(EXCEPTION_EXECUTE_HANDLER) {
// wchar_t log[300];
// DWORD err=GetExceptionCode();
// swprintf(log,L"Exception:%08X",err);
// OutputDebugString(log);
//}
}
OutputDebugString(L"[BixVReader]Socket quit!!!");
return 0;
}
void TcpIpReader::shutdown() {
state=SCARD_ABSENT;
breakSocket=true;
{
closesocket(eventsocket);
closesocket(socket);
}
WaitForSingleObject(serverThread,10000);
serverThread=NULL;
eventsocket=NULL;
socket=NULL;
while (!waitRemoveIpr.empty()) {
SectionLocker lock(device->m_RequestLock);
CComPtr<IWDFIoRequest> ipr = waitRemoveIpr.back();
if (ipr->UnmarkCancelable()==S_OK)
ipr->Complete(HRESULT_FROM_WIN32(ERROR_CANCELLED));
waitRemoveIpr.pop_back();
}
while (!waitInsertIpr.empty()) {
SectionLocker lock(device->m_RequestLock);
CComPtr<IWDFIoRequest> ipr = waitInsertIpr.back();
if (ipr->UnmarkCancelable()==S_OK)
ipr->Complete(HRESULT_FROM_WIN32(ERROR_CANCELLED));
waitInsertIpr.pop_back();
}
}