2006-11-01 22:26:55 +01:00
|
|
|
/*
|
|
|
|
rdesktop: A Remote Desktop Protocol client.
|
|
|
|
Smart Card support
|
|
|
|
Copyright (C) Alexi Volkov <alexi@myrealbox.com> 2006
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
2006-11-01 21:52:01 +01:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <strings.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <time.h>
|
|
|
|
#ifndef MAKE_PROTO
|
2006-11-01 22:23:08 +01:00
|
|
|
#ifdef PCSC_OSX
|
2007-01-05 00:19:54 +01:00
|
|
|
#include <PCSC/wintypes.h>
|
2006-11-01 22:23:08 +01:00
|
|
|
#include <PCSC/pcsclite.h>
|
|
|
|
#include <PCSC/winscard.h>
|
|
|
|
#else
|
2007-01-05 00:19:54 +01:00
|
|
|
#include <wintypes.h>
|
2006-11-01 21:52:01 +01:00
|
|
|
#include <pcsclite.h>
|
|
|
|
#include <winscard.h>
|
2006-11-01 22:23:08 +01:00
|
|
|
#endif /* PCSC_OSX */
|
2007-01-05 00:19:54 +01:00
|
|
|
#include "rdesktop.h"
|
2006-11-01 21:52:01 +01:00
|
|
|
#include "scard.h"
|
|
|
|
|
|
|
|
/* variable segment */
|
|
|
|
|
|
|
|
#define SCARD_MAX_MEM 102400
|
|
|
|
#define SCARD_AUTOALLOCATE -1
|
|
|
|
#define OUT_STREAM_SIZE 4096
|
|
|
|
#define STREAM_COUNT 8
|
|
|
|
|
|
|
|
static struct stream out[STREAM_COUNT];
|
|
|
|
static int cur_stream_id = 0;
|
2006-11-04 00:51:35 +01:00
|
|
|
static pthread_mutex_t **scard_mutex = NULL;
|
2006-11-01 21:52:01 +01:00
|
|
|
|
|
|
|
static uint32 curDevice = 0, curId = 0, curBytesOut = 0;
|
|
|
|
static PSCNameMapRec nameMapList = NULL;
|
|
|
|
static int nameMapCount = 0;
|
|
|
|
|
|
|
|
static pthread_t queueHandler;
|
|
|
|
static pthread_mutex_t queueAccess;
|
|
|
|
static pthread_mutex_t queueEmpty;
|
|
|
|
static pthread_mutex_t hcardAccess;
|
|
|
|
|
|
|
|
static PMEM_HANDLE threadListHandle = NULL;
|
|
|
|
static PThreadListElement threadList = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
static PSCThreadData queueFirst = NULL, queueLast = NULL;
|
|
|
|
static int threadCount = 0;
|
|
|
|
|
|
|
|
static PSCHCardRec hcardFirst = NULL;
|
|
|
|
|
|
|
|
static void *queue_handler_function(void *data);
|
|
|
|
|
|
|
|
/* code segment */
|
|
|
|
|
|
|
|
#endif /* MAKE_PROTO */
|
|
|
|
void
|
|
|
|
scardSetInfo(uint32 device, uint32 id, uint32 bytes_out)
|
|
|
|
{
|
|
|
|
curDevice = device;
|
|
|
|
curId = id;
|
|
|
|
curBytesOut = bytes_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef MAKE_PROTO
|
|
|
|
|
2007-01-04 15:38:48 +01:00
|
|
|
static RD_NTSTATUS
|
2006-11-01 21:52:01 +01:00
|
|
|
scard_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
|
2007-01-04 15:38:48 +01:00
|
|
|
uint32 flags_and_attributes, char *filename, RD_NTHANDLE * phandle)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
2007-01-04 15:38:48 +01:00
|
|
|
return RD_STATUS_SUCCESS;
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
|
2007-01-04 15:38:48 +01:00
|
|
|
static RD_NTSTATUS
|
|
|
|
scard_close(RD_NTHANDLE handle)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
2007-01-04 15:38:48 +01:00
|
|
|
return RD_STATUS_SUCCESS;
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
|
2007-01-04 15:38:48 +01:00
|
|
|
static RD_NTSTATUS
|
|
|
|
scard_read(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
2007-01-04 15:38:48 +01:00
|
|
|
return RD_STATUS_SUCCESS;
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
|
2007-01-04 15:38:48 +01:00
|
|
|
static RD_NTSTATUS
|
|
|
|
scard_write(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
2007-01-04 15:38:48 +01:00
|
|
|
return RD_STATUS_SUCCESS;
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
#endif /* MAKE_PROTO */
|
|
|
|
|
|
|
|
/* Enumeration of devices from rdesktop.c */
|
|
|
|
/* returns numer of units found and initialized. */
|
|
|
|
/* optarg looks like ':"ReaderName=ReaderAlias"' */
|
|
|
|
/* when it arrives to this function. */
|
|
|
|
|
|
|
|
int
|
|
|
|
scard_enum_devices(uint32 * id, char *optarg)
|
|
|
|
{
|
|
|
|
char *name = optarg + 1;
|
|
|
|
char *alias;
|
|
|
|
int count = 0;
|
|
|
|
PSCNameMapRec tmpMap;
|
|
|
|
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SCARDCONTEXT hContext;
|
|
|
|
|
|
|
|
/* code segment */
|
|
|
|
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
|
|
|
|
if (rv != SCARD_S_SUCCESS)
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
error("[SMART CARD: PCSC service not available]\n");
|
2006-11-01 21:52:01 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rv = SCardReleaseContext(hContext);
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
|
|
|
|
if (0 != pthread_mutex_init(&queueAccess, NULL))
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
error("[SMART CARD: Can't initialize queue access mutex]\n");
|
2006-11-01 21:52:01 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 != pthread_mutex_init(&queueEmpty, NULL))
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
error("[SMART CARD: Can't initialize queue control mutex]\n");
|
2006-11-01 21:52:01 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 != pthread_mutex_init(&hcardAccess, NULL))
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
error("[SMART CARD: Can't initialize hcard list access mutex]\n");
|
2006-11-01 21:52:01 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 !=
|
|
|
|
pthread_create(&queueHandler, NULL, (void *(*)(void *)) queue_handler_function, NULL))
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
error("[SMART CARD: Can't create queue handling Thread]\n");
|
2006-11-01 21:52:01 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(g_rdpdr_device[*id].name, "SCARD\0\0\0", 8);
|
|
|
|
toupper_str(g_rdpdr_device[*id].name);
|
|
|
|
g_rdpdr_device[*id].local_path = "/dev/scard";
|
|
|
|
g_rdpdr_device[*id].pdevice_data = NULL;
|
|
|
|
g_rdpdr_device[*id].handle = 0;
|
|
|
|
g_rdpdr_device[*id].device_type = DEVICE_TYPE_SCARD;
|
|
|
|
count++;
|
|
|
|
(*id)++;
|
|
|
|
|
|
|
|
if (*optarg == ':')
|
|
|
|
{
|
|
|
|
while ((optarg = next_arg(name, ',')) && *id < RDPDR_MAX_DEVICES)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
char *vendor = NULL;
|
|
|
|
alias = next_arg(name, '=');
|
|
|
|
vendor = next_arg(alias, ';');
|
|
|
|
|
|
|
|
if (strlen(name) > 0)
|
|
|
|
{
|
|
|
|
if (!strlen(alias))
|
|
|
|
{
|
|
|
|
alias = name;
|
|
|
|
vendor = "\0";
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("Static/aliased Device:\n");
|
|
|
|
printf(" Lin name: [%s]\n", name);
|
|
|
|
printf(" Win name: [%s]\n", alias);
|
|
|
|
printf(" Vendor : [%s]\n", vendor);
|
|
|
|
nameMapCount++;
|
|
|
|
|
|
|
|
if (nameMapList == NULL)
|
|
|
|
nameMapList = xmalloc(nameMapCount * sizeof(TSCNameMapRec));
|
|
|
|
else
|
|
|
|
nameMapList =
|
|
|
|
xrealloc(nameMapList,
|
|
|
|
nameMapCount * sizeof(TSCNameMapRec));
|
|
|
|
|
|
|
|
tmpMap = nameMapList + nameMapCount - 1;
|
|
|
|
|
|
|
|
len = strlen(alias);
|
|
|
|
strncpy(tmpMap->alias, alias, (len > 127) ? (127) : (len));
|
|
|
|
len = strlen(name);
|
|
|
|
strncpy(tmpMap->name, name, (len > 127) ? (127) : (len));
|
|
|
|
|
|
|
|
if (vendor)
|
|
|
|
{
|
|
|
|
len = strlen(vendor);
|
|
|
|
if (len > 0)
|
|
|
|
{
|
|
|
|
memset(tmpMap->vendor, 0, 128);
|
|
|
|
strncpy(tmpMap->vendor, vendor,
|
|
|
|
(len > 127) ? (127) : (len));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
tmpMap->vendor[0] = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
tmpMap->vendor[0] = '\0';
|
|
|
|
}
|
|
|
|
name = optarg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef MAKE_PROTO
|
|
|
|
/* ---------------------------------- */
|
|
|
|
|
|
|
|
/* These two functions depend heavily on the actual implementation of the smart
|
|
|
|
* card handle in PC/SC Lite 1.3.1. Here are the salient bits:
|
|
|
|
*
|
|
|
|
* From winscard.c:331, in SCardConnect:
|
|
|
|
* *phCard = RFCreateReaderHandle(rContext);
|
|
|
|
*
|
|
|
|
* RFCreateReaderHandle (readerfactory.c:1161) creates a random short (16-bit
|
|
|
|
* integer) and makes sure it's unique. Then it adds it to
|
|
|
|
* rContext->dwIdentity.
|
|
|
|
*
|
|
|
|
* From readerfactory.c:173, in RFAddReader:
|
|
|
|
* (sReadersContexts[dwContext])->dwIdentity =
|
|
|
|
* (dwContext + 1) << (sizeof(DWORD) / 2) * 8;
|
|
|
|
*
|
|
|
|
* dwContext must be less than PCSCLITE_MAX_READERS_CONTEXTS, which is defined
|
|
|
|
* to be 16 in the 1.3.1 release.
|
|
|
|
*
|
|
|
|
* The use of "(sizeof(DWORD) / 2) * 8" is what makes conversion necessary in
|
|
|
|
* order to use 64-bit card handles when talking to PC/SC Lite, and 32-bit card
|
|
|
|
* handles when talking with the server, without losing any data: a card handle
|
|
|
|
* made by a 32-bit PC/SC Lite looks like 0x00014d32, where the 4d32 is the
|
|
|
|
* random 16 bits, 01 is the reader context index + 1, and it's left-shifted by
|
|
|
|
* 16 bits (sizeof(DWORD) == 4, divided by 2 is 2, times 8 is 16.) But a 64-bit
|
|
|
|
* PC/SC Lite makes a card handle that looks like 0x0000000100004d32. The
|
|
|
|
* reader context index+1 is left-shifted 32 bits because sizeof(DWORD) is 8,
|
|
|
|
* not 4. This means the handle won't fit in 32 bits. (The multiplication by 8
|
|
|
|
* is because sizeofs are in bytes, but saying how many places to left-shift is
|
|
|
|
* speaking in bits.)
|
|
|
|
*
|
|
|
|
* So then. Maximum value of dwContext+1 is 17; we'll say this fits in a byte
|
|
|
|
* to be loose and have plenty of room. This is then left-shifted by
|
|
|
|
* sizeof(DWORD) / 2 * 8 - which in this file is sizeof(MYPCSC_DWORD) / 2 * 8.
|
|
|
|
*
|
|
|
|
* At any rate, if we take the handle as passed from PC/SC Lite, right-shift by
|
|
|
|
* sizeof(MYPCSC_DWORD) / 2, left-shift by sizeof(SERVER_DWORD) / 2, and add
|
|
|
|
* the lower two bytes of the value (the random number), we can fit all the
|
|
|
|
* information into 32 bits without losing any. Of course, any time we want to
|
|
|
|
* hand that back to PC/SC Lite, we'll have to expand it again. (And if
|
|
|
|
* sizeof(MYPCSC_DWORD) == sizeof(SERVER_DWORD), we're essentially doing
|
|
|
|
* nothing, which will not break anything.)
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* - jared.jennings@eglin.af.mil, 2 Aug 2006
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
static MYPCSC_SCARDHANDLE
|
|
|
|
scHandleToMyPCSC(SERVER_SCARDHANDLE server)
|
|
|
|
{
|
|
|
|
return (((MYPCSC_SCARDHANDLE) server >> (sizeof(SERVER_DWORD) * 8 / 2) & 0xffff)
|
|
|
|
<< (sizeof(MYPCSC_DWORD) * 8 / 2)) + (server & 0xffff);
|
|
|
|
}
|
|
|
|
|
|
|
|
static SERVER_SCARDHANDLE
|
|
|
|
scHandleToServer(MYPCSC_SCARDHANDLE mypcsc)
|
|
|
|
{
|
|
|
|
return ((mypcsc >> (sizeof(MYPCSC_DWORD) * 8 / 2) & 0xffff)
|
|
|
|
<< (sizeof(SERVER_DWORD) * 8 / 2)) + (mypcsc & 0xffff);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------- */
|
|
|
|
|
|
|
|
static void *
|
|
|
|
SC_xmalloc(PMEM_HANDLE * memHandle, unsigned int size)
|
|
|
|
{
|
|
|
|
PMEM_HANDLE handle = NULL;
|
|
|
|
if (size > 0 && memHandle)
|
|
|
|
{
|
|
|
|
handle = xmalloc(size + sizeof(MEM_HANDLE));
|
|
|
|
if (handle)
|
|
|
|
{
|
|
|
|
handle->prevHandle = NULL;
|
|
|
|
handle->nextHandle = NULL;
|
|
|
|
handle->dataSize = size;
|
|
|
|
if (*memHandle)
|
|
|
|
{
|
|
|
|
handle->prevHandle = *memHandle;
|
|
|
|
(*memHandle)->nextHandle = handle;
|
|
|
|
}
|
|
|
|
*memHandle = handle;
|
|
|
|
return handle + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
SC_xfree(PMEM_HANDLE * handle, void *memptr)
|
|
|
|
{
|
|
|
|
if (memptr != NULL)
|
|
|
|
{
|
|
|
|
PMEM_HANDLE lcHandle = (PMEM_HANDLE) memptr - 1;
|
|
|
|
if (lcHandle->dataSize > 0)
|
|
|
|
{
|
|
|
|
memset(memptr, 0, lcHandle->dataSize);
|
|
|
|
if (lcHandle->nextHandle)
|
|
|
|
lcHandle->nextHandle->prevHandle = lcHandle->prevHandle;
|
|
|
|
if (lcHandle->prevHandle)
|
|
|
|
lcHandle->prevHandle->nextHandle = lcHandle->nextHandle;
|
|
|
|
if (*handle == lcHandle)
|
|
|
|
{
|
|
|
|
if (lcHandle->prevHandle)
|
|
|
|
*handle = lcHandle->prevHandle;
|
|
|
|
else
|
|
|
|
*handle = lcHandle->nextHandle;
|
|
|
|
}
|
|
|
|
xfree(lcHandle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
SC_xfreeallmemory(PMEM_HANDLE * handle)
|
|
|
|
{
|
|
|
|
if (handle && (*handle))
|
|
|
|
{
|
|
|
|
if ((*handle)->prevHandle)
|
|
|
|
{
|
|
|
|
(*handle)->prevHandle->nextHandle = NULL;
|
|
|
|
SC_xfreeallmemory(&((*handle)->prevHandle));
|
|
|
|
}
|
|
|
|
if ((*handle)->nextHandle)
|
|
|
|
{
|
|
|
|
(*handle)->nextHandle->prevHandle = NULL;
|
|
|
|
SC_xfreeallmemory(&((*handle)->nextHandle));
|
|
|
|
}
|
|
|
|
memset(*handle, 0, (*handle)->dataSize + sizeof(MEM_HANDLE));
|
|
|
|
xfree(*handle);
|
|
|
|
*handle = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------- */
|
|
|
|
|
|
|
|
static char *
|
|
|
|
getName(char *alias)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
PSCNameMapRec tmpMap;
|
|
|
|
for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
|
|
|
|
{
|
|
|
|
if (strcmp(tmpMap->alias, alias) == 0)
|
|
|
|
return tmpMap->name;
|
|
|
|
}
|
|
|
|
return alias;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
getVendor(char *name)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
PSCNameMapRec tmpMap;
|
|
|
|
for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
|
|
|
|
{
|
|
|
|
if (strcmp(tmpMap->name, name) == 0)
|
|
|
|
return tmpMap->vendor;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
getAlias(char *name)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
PSCNameMapRec tmpMap;
|
|
|
|
for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
|
|
|
|
{
|
|
|
|
if (strcmp(tmpMap->name, name) == 0)
|
|
|
|
return tmpMap->alias;
|
|
|
|
}
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
hasAlias(char *name)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
PSCNameMapRec tmpMap;
|
|
|
|
for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
|
|
|
|
{
|
|
|
|
if (strcmp(tmpMap->name, name) == 0)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
inRepos(STREAM in, unsigned int read)
|
|
|
|
{
|
|
|
|
SERVER_DWORD add = 4 - read % 4;
|
|
|
|
if (add < 4 && add > 0)
|
|
|
|
{
|
|
|
|
in_uint8s(in, add);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
outRepos(STREAM out, unsigned int written)
|
|
|
|
{
|
|
|
|
SERVER_DWORD add = (4 - written % 4) % 4;
|
|
|
|
if (add > 0)
|
|
|
|
{
|
|
|
|
out_uint8s(out, add);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
outBufferStartWithLimit(STREAM out, int length, int highLimit)
|
|
|
|
{
|
|
|
|
int header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length));
|
|
|
|
out_uint32_le(out, header);
|
|
|
|
out_uint32_le(out, 0x00000001); /* Magic DWORD - any non zero */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
outBufferStart(STREAM out, int length)
|
|
|
|
{
|
|
|
|
outBufferStartWithLimit(out, length, 0x7FFFFFFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
outBufferFinishWithLimit(STREAM out, char *buffer, unsigned int length, unsigned int highLimit)
|
|
|
|
{
|
|
|
|
int header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length));
|
|
|
|
out_uint32_le(out, header);
|
|
|
|
|
|
|
|
if (length <= 0)
|
|
|
|
{
|
|
|
|
out_uint32_le(out, 0x00000000);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (header < length)
|
|
|
|
length = header;
|
|
|
|
out_uint8p(out, buffer, length);
|
|
|
|
outRepos(out, length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
outBufferFinish(STREAM out, char *buffer, unsigned int length)
|
|
|
|
{
|
|
|
|
outBufferFinishWithLimit(out, buffer, length, 0x7FFFFFFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-11-03 00:12:25 +01:00
|
|
|
outForceAlignment(STREAM out, unsigned int seed)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
SERVER_DWORD add = (seed - (out->p - out->data) % seed) % seed;
|
|
|
|
if (add > 0)
|
|
|
|
out_uint8s(out, add);
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
2007-01-08 05:47:06 +01:00
|
|
|
inString(PMEM_HANDLE * handle, STREAM in, char **destination, SERVER_DWORD dataLength, RD_BOOL wide)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
unsigned int Result = (wide) ? (2 * dataLength) : (dataLength);
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
char *buffer = SC_xmalloc(&lcHandle, Result + 2);
|
|
|
|
char *reader;
|
|
|
|
|
|
|
|
/* code segment */
|
|
|
|
|
|
|
|
if (wide)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
in_uint8a(in, buffer, 2 * dataLength);
|
|
|
|
for (i = 0; i < dataLength; i++)
|
|
|
|
if ((buffer[2 * i] < 0) || (buffer[2 * i + 1] != 0))
|
|
|
|
buffer[i] = '?';
|
|
|
|
else
|
|
|
|
buffer[i] = buffer[2 * i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
in_uint8a(in, buffer, dataLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer[dataLength] = '\0';
|
|
|
|
reader = getName(buffer);
|
|
|
|
*destination = SC_xmalloc(handle, strlen(reader) + 1);
|
|
|
|
strcpy(*destination, reader);
|
|
|
|
|
|
|
|
SC_xfreeallmemory(&lcHandle);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
2007-01-08 05:47:06 +01:00
|
|
|
outString(STREAM out, char *source, RD_BOOL wide)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
char *reader = getAlias(source);
|
|
|
|
unsigned int dataLength = strlen(reader) + 1;
|
|
|
|
unsigned int Result = (wide) ? (2 * dataLength) : (dataLength);
|
|
|
|
|
|
|
|
/* code segment */
|
|
|
|
|
|
|
|
if (wide)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *buffer = SC_xmalloc(&lcHandle, Result);
|
|
|
|
|
|
|
|
for (i = 0; i < dataLength; i++)
|
|
|
|
{
|
|
|
|
if (source[i] < 0)
|
|
|
|
buffer[2 * i] = '?';
|
|
|
|
else
|
|
|
|
buffer[2 * i] = reader[i];
|
|
|
|
buffer[2 * i + 1] = '\0';
|
|
|
|
}
|
|
|
|
out_uint8p(out, buffer, 2 * dataLength);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
out_uint8p(out, reader, dataLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
SC_xfreeallmemory(&lcHandle);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-01-08 05:47:06 +01:00
|
|
|
inReaderName(PMEM_HANDLE * handle, STREAM in, char **destination, RD_BOOL wide)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
SERVER_DWORD dataLength;
|
|
|
|
in->p += 0x08;
|
|
|
|
in_uint32_le(in, dataLength);
|
|
|
|
inRepos(in, inString(handle, in, destination, dataLength, wide));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
inSkipLinked(STREAM in)
|
|
|
|
{
|
|
|
|
SERVER_DWORD len;
|
|
|
|
in_uint32_le(in, len);
|
|
|
|
if (len > 0)
|
|
|
|
{
|
|
|
|
in_uint8s(in, len);
|
|
|
|
inRepos(in, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------- */
|
|
|
|
/* Smart Card processing functions: */
|
|
|
|
/* ---------------------------------- */
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
SC_returnCode(MYPCSC_DWORD rc, PMEM_HANDLE * handle, STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
SC_xfreeallmemory(handle);
|
|
|
|
out_uint8s(out, 256);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
SC_returnNoMemoryError(PMEM_HANDLE * handle, STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
return SC_returnCode(SCARD_E_NO_MEMORY, handle, in, out);
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
TS_SCardEstablishContext(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
MYPCSC_SCARDCONTEXT hContext;
|
|
|
|
/* code segment */
|
|
|
|
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("Establishing PC/SC Context... \n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
|
|
|
|
if (rv)
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardEstablishContext Code=0x%.8x, %s]-->\n",
|
|
|
|
(unsigned int) rv, pcsc_stringify_error(rv)));
|
2006-11-02 21:48:28 +01:00
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
else
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardEstablishContext-->\n"));
|
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
|
|
|
|
out_uint32_le(out, 0x00000004);
|
|
|
|
out_uint32_le(out, (SERVER_DWORD) hContext); /* must not be 0 (Seems to be pointer), don't know what is this (I use hContext as value) */
|
|
|
|
/* i hope it's not a pointer because i just downcasted it - jlj */
|
|
|
|
out_uint32_le(out, 0x00000004);
|
|
|
|
out_uint32_le(out, (SERVER_DWORD) hContext);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
TS_SCardReleaseContext(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hContext;
|
|
|
|
|
|
|
|
in->p += 0x1C;
|
|
|
|
in_uint32_le(in, hContext);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
|
|
|
|
DEBUG_SCARD(("Releasing context... \n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
rv = SCardReleaseContext((MYPCSC_SCARDCONTEXT) hContext);
|
2006-11-02 21:48:28 +01:00
|
|
|
|
2006-11-01 21:52:01 +01:00
|
|
|
if (rv)
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardReleaseContext Code=0x%.8x, %s-->\n", (unsigned int) rv,
|
|
|
|
pcsc_stringify_error(rv)));
|
2006-11-02 21:48:28 +01:00
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
else
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardReleaseContext-->\n"));
|
|
|
|
}
|
|
|
|
|
2006-11-01 21:52:01 +01:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
TS_SCardIsValidContext(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hContext;
|
|
|
|
char *readers;
|
|
|
|
DWORD readerCount = 1024;
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
|
|
|
|
in->p += 0x1C;
|
|
|
|
in_uint32_le(in, hContext);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
|
|
|
|
DEBUG_SCARD(("Checking... \n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
/* There is no realization of SCardIsValidContext in PC/SC Lite so we call SCardListReaders */
|
|
|
|
|
|
|
|
readers = SC_xmalloc(&lcHandle, 1024);
|
|
|
|
if (!readers)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
|
|
|
|
rv = SCardListReaders((MYPCSC_SCARDCONTEXT) hContext, NULL, readers, &readerCount);
|
2006-11-02 21:48:28 +01:00
|
|
|
|
2006-11-01 21:52:01 +01:00
|
|
|
if (rv)
|
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardListReaders (no SCardIsValidContext) Code=0x%.8x, %s-->\n", (unsigned int) rv, pcsc_stringify_error(rv)));
|
2006-11-01 21:52:01 +01:00
|
|
|
rv = SCARD_E_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
else
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardListReaders (no SCardIsValidContext)-->\n"));
|
|
|
|
}
|
|
|
|
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
SC_xfreeallmemory(&lcHandle);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
2007-01-08 05:47:06 +01:00
|
|
|
TS_SCardListReaders(STREAM in, STREAM out, RD_BOOL wide)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
#define readerArraySize 1024
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hContext;
|
|
|
|
SERVER_DWORD dataLength;
|
|
|
|
MYPCSC_DWORD cchReaders = readerArraySize;
|
|
|
|
unsigned char *plen1, *plen2, *pend;
|
|
|
|
char *readers, *cur;
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
|
|
|
|
in->p += 0x2C;
|
|
|
|
in_uint32_le(in, hContext);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
|
2006-11-01 21:52:01 +01:00
|
|
|
plen1 = out->p;
|
|
|
|
out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
|
|
|
|
out_uint32_le(out, 0x01760650);
|
|
|
|
plen2 = out->p;
|
|
|
|
out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
|
|
|
|
|
|
|
|
dataLength = 0;
|
|
|
|
readers = SC_xmalloc(&lcHandle, readerArraySize);
|
|
|
|
if (!readers)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
|
|
|
|
|
|
|
|
readers[0] = '\0';
|
|
|
|
readers[1] = '\0';
|
|
|
|
rv = SCardListReaders((MYPCSC_SCARDCONTEXT) hContext, NULL, readers, &cchReaders);
|
|
|
|
cur = readers;
|
|
|
|
if (!rv)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
PSCNameMapRec tmpMap;
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
|
|
|
DEBUG_SCARD(("[CALL RESULT of SCardListReaders 0x%.8x]\n", (unsigned int) rv));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump((void *) readers, cchReaders);
|
|
|
|
#endif
|
|
|
|
for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
|
|
|
|
{
|
|
|
|
dataLength += outString(out, tmpMap->alias, wide);
|
|
|
|
}
|
|
|
|
|
|
|
|
int lenSC = strlen(cur);
|
|
|
|
if (lenSC == 0)
|
|
|
|
dataLength += outString(out, "\0", wide);
|
|
|
|
else
|
|
|
|
while (lenSC > 0)
|
|
|
|
{
|
|
|
|
if (!hasAlias(cur))
|
|
|
|
dataLength += outString(out, cur, wide);
|
|
|
|
cur = (void *) ((unsigned char *) cur + lenSC + 1);
|
|
|
|
lenSC = strlen(cur);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dataLength += outString(out, "\0", wide);
|
|
|
|
outRepos(out, dataLength);
|
|
|
|
|
|
|
|
pend = out->p;
|
|
|
|
out->p = plen1;
|
|
|
|
out_uint32_le(out, dataLength);
|
|
|
|
out->p = plen2;
|
|
|
|
out_uint32_le(out, dataLength);
|
|
|
|
out->p = pend;
|
|
|
|
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
SC_xfreeallmemory(&lcHandle);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
2007-01-08 05:47:06 +01:00
|
|
|
TS_SCardConnect(STREAM in, STREAM out, RD_BOOL wide)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SCARDCONTEXT hContext;
|
|
|
|
char *szReader;
|
|
|
|
SERVER_DWORD dwShareMode;
|
|
|
|
SERVER_DWORD dwPreferredProtocol;
|
|
|
|
MYPCSC_SCARDHANDLE myHCard;
|
|
|
|
SERVER_SCARDHANDLE hCard;
|
|
|
|
|
|
|
|
MYPCSC_DWORD dwActiveProtocol;
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
|
|
|
|
in->p += 0x1C;
|
|
|
|
in_uint32_le(in, dwShareMode);
|
|
|
|
in_uint32_le(in, dwPreferredProtocol);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[SHARE %8x]\n", (unsigned int) dwShareMode));
|
|
|
|
DEBUG_SCARD(("[PROTO %8x]\n", (unsigned int) dwPreferredProtocol));
|
2006-11-01 21:52:01 +01:00
|
|
|
inReaderName(&lcHandle, in, &szReader, wide);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[CONNECT TO READER \"%s\"\n", (szReader != NULL) ? (szReader) : ("NULL")));
|
2006-11-01 21:52:01 +01:00
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, hContext);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
|
2006-11-01 21:52:01 +01:00
|
|
|
rv = SCardConnect(hContext, szReader, (MYPCSC_DWORD) dwShareMode,
|
|
|
|
(MYPCSC_DWORD) dwPreferredProtocol, &myHCard, &dwActiveProtocol);
|
|
|
|
hCard = scHandleToServer(myHCard);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[RECEIVED HCARD 0x%016lx]\n", (unsigned long) myHCard));
|
|
|
|
DEBUG_SCARD(("[MANGLED HCARD 0x%08x]\n", hCard));
|
2006-11-01 21:52:01 +01:00
|
|
|
if (rv != SCARD_S_SUCCESS)
|
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardConnect Code=0x%.8x, %s-->\n", (unsigned int) rv,
|
|
|
|
pcsc_stringify_error(rv)));
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *szVendor = getVendor(szReader);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<--SUCCESS ScardConnect-->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
if (szVendor && (strlen(szVendor) > 0))
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("Set Attribute ATTR_VENDOR_NAME\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
pthread_mutex_lock(&hcardAccess);
|
|
|
|
PSCHCardRec hcard = xmalloc(sizeof(TSCHCardRec));
|
|
|
|
if (hcard)
|
|
|
|
{
|
|
|
|
hcard->hCard = hCard;
|
|
|
|
hcard->vendor = szVendor;
|
|
|
|
hcard->next = NULL;
|
|
|
|
hcard->prev = NULL;
|
|
|
|
|
|
|
|
if (hcardFirst)
|
|
|
|
{
|
|
|
|
hcardFirst->prev = hcard;
|
|
|
|
hcard->next = hcardFirst;
|
|
|
|
}
|
|
|
|
hcardFirst = hcard;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&hcardAccess);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out_uint32_le(out, 0x00000000);
|
|
|
|
out_uint32_le(out, 0x00000000);
|
|
|
|
out_uint32_le(out, 0x00000004);
|
|
|
|
out_uint32_le(out, 0x016Cff34);
|
|
|
|
/* if the active protocol > 4 billion, this is trouble. odds are low */
|
|
|
|
out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
|
|
|
|
out_uint32_le(out, 0x00000004);
|
|
|
|
out_uint32_le(out, hCard);
|
|
|
|
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
SC_xfreeallmemory(&lcHandle);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
TS_SCardReconnect(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SCARDCONTEXT hContext;
|
|
|
|
SERVER_SCARDHANDLE hCard;
|
|
|
|
MYPCSC_SCARDHANDLE myHCard;
|
|
|
|
SERVER_DWORD dwShareMode;
|
|
|
|
SERVER_DWORD dwPreferredProtocol;
|
|
|
|
SERVER_DWORD dwInitialization;
|
|
|
|
MYPCSC_DWORD dwActiveProtocol;
|
|
|
|
|
|
|
|
in->p += 0x20;
|
|
|
|
in_uint32_le(in, dwShareMode);
|
|
|
|
in_uint32_le(in, dwPreferredProtocol);
|
|
|
|
in_uint32_le(in, dwInitialization);
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, hContext);
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, hCard);
|
|
|
|
myHCard = scHandleToMyPCSC(hCard);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[SHARE = 0x%.8x]\n", (unsigned int) dwShareMode));
|
|
|
|
DEBUG_SCARD(("[PROTO = 0x%.8x]\n", (unsigned int) dwPreferredProtocol));
|
|
|
|
DEBUG_SCARD(("[INIT = 0x%.8x]\n", (unsigned int) dwInitialization));
|
|
|
|
DEBUG_SCARD(("[hContext = 0x%.8x]\n", (unsigned int) hContext));
|
|
|
|
DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
|
|
|
|
DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
|
2006-11-01 21:52:01 +01:00
|
|
|
rv = SCardReconnect(myHCard, (MYPCSC_DWORD) dwShareMode, (MYPCSC_DWORD) dwPreferredProtocol,
|
|
|
|
(MYPCSC_DWORD) dwInitialization, &dwActiveProtocol);
|
|
|
|
if (rv != SCARD_S_SUCCESS)
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardReconnect Code=0x%.8x, %s-->\n", (unsigned int) rv,
|
|
|
|
pcsc_stringify_error(rv)));
|
2006-11-02 21:48:28 +01:00
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
else
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardReconnect-->\n"));
|
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
TS_SCardDisconnect(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hContext;
|
|
|
|
SERVER_SCARDHANDLE hCard;
|
|
|
|
MYPCSC_SCARDHANDLE myHCard;
|
|
|
|
SERVER_DWORD dwDisposition;
|
|
|
|
|
|
|
|
in->p += 0x20;
|
|
|
|
in_uint32_le(in, dwDisposition);
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, hContext);
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, hCard);
|
|
|
|
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[hContext = 0x%.8x]\n", (unsigned int) hContext));
|
|
|
|
DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
|
|
|
|
DEBUG_SCARD(("[dwDisposition = 0x%.8x]\n", (unsigned int) dwDisposition));
|
2006-11-01 21:52:01 +01:00
|
|
|
|
|
|
|
pthread_mutex_lock(&hcardAccess);
|
|
|
|
PSCHCardRec hcard = hcardFirst;
|
|
|
|
while (hcard)
|
|
|
|
{
|
|
|
|
if (hcard->hCard == hCard)
|
|
|
|
{
|
|
|
|
if (hcard->prev)
|
|
|
|
hcard->prev->next = hcard->next;
|
|
|
|
if (hcard->next)
|
|
|
|
hcard->next->prev = hcard->prev;
|
|
|
|
if (hcardFirst == hcard)
|
|
|
|
hcardFirst = hcard->next;
|
|
|
|
xfree(hcard);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
hcard = hcard->next;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&hcardAccess);
|
|
|
|
|
|
|
|
myHCard = scHandleToMyPCSC(hCard);
|
|
|
|
rv = SCardDisconnect(myHCard, (MYPCSC_DWORD) dwDisposition);
|
|
|
|
|
|
|
|
if (rv != SCARD_S_SUCCESS)
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardDisconnect Code=0x%.8x, %s-->\n", (unsigned int) rv,
|
|
|
|
pcsc_stringify_error(rv)));
|
2006-11-02 21:48:28 +01:00
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
else
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardDisconnect-->\n"));
|
|
|
|
}
|
|
|
|
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
needStatusRecheck(MYPCSC_DWORD rv, MYPCSC_LPSCARD_READERSTATE_A rsArray, SERVER_DWORD dwCount)
|
|
|
|
{
|
|
|
|
int i, recall = 0;
|
|
|
|
if (rv == SCARD_S_SUCCESS)
|
|
|
|
{
|
|
|
|
MYPCSC_LPSCARD_READERSTATE_A cur;
|
|
|
|
for (i = 0, cur = rsArray; i < dwCount; i++, cur++)
|
|
|
|
{
|
|
|
|
if (cur->dwEventState & SCARD_STATE_UNKNOWN)
|
|
|
|
{
|
|
|
|
cur->dwCurrentState = cur->dwEventState;
|
|
|
|
recall++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return recall;
|
|
|
|
}
|
|
|
|
|
2007-01-08 13:38:34 +01:00
|
|
|
static RD_BOOL
|
2006-11-01 21:52:01 +01:00
|
|
|
mappedStatus(MYPCSC_DWORD code)
|
|
|
|
{
|
|
|
|
code >>= 16;
|
|
|
|
code &= 0x0000FFFF;
|
|
|
|
return (code % 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
2007-01-08 05:47:06 +01:00
|
|
|
incStatus(MYPCSC_DWORD code, RD_BOOL mapped)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
if (mapped || (code & SCARD_STATE_CHANGED))
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD count = (code >> 16) & 0x0000FFFF;
|
|
|
|
count++;
|
|
|
|
if (mapped && !(count % 2))
|
|
|
|
count++;
|
|
|
|
return (code & 0x0000FFFF) | (count << 16);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
copyReaderState_MyPCSCToServer(MYPCSC_LPSCARD_READERSTATE_A src, SERVER_LPSCARD_READERSTATE_A dst,
|
|
|
|
MYPCSC_DWORD readerCount)
|
|
|
|
{
|
|
|
|
MYPCSC_LPSCARD_READERSTATE_A srcIter;
|
|
|
|
SERVER_LPSCARD_READERSTATE_A dstIter;
|
|
|
|
MYPCSC_DWORD i;
|
|
|
|
|
|
|
|
for (i = 0, srcIter = src, dstIter = dst; i < readerCount; i++, srcIter++, dstIter++)
|
|
|
|
{
|
|
|
|
dstIter->szReader = srcIter->szReader;
|
|
|
|
dstIter->pvUserData = srcIter->pvUserData;
|
|
|
|
dstIter->dwCurrentState = srcIter->dwCurrentState;
|
|
|
|
dstIter->dwEventState = srcIter->dwEventState;
|
|
|
|
dstIter->cbAtr = srcIter->cbAtr;
|
|
|
|
memcpy(dstIter->rgbAtr, srcIter->rgbAtr, MAX_ATR_SIZE * sizeof(unsigned char));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
copyReaderState_ServerToMyPCSC(SERVER_LPSCARD_READERSTATE_A src, MYPCSC_LPSCARD_READERSTATE_A dst,
|
|
|
|
SERVER_DWORD readerCount)
|
|
|
|
{
|
|
|
|
SERVER_LPSCARD_READERSTATE_A srcIter;
|
|
|
|
MYPCSC_LPSCARD_READERSTATE_A dstIter;
|
|
|
|
SERVER_DWORD i;
|
|
|
|
|
|
|
|
for (i = 0, srcIter = src, dstIter = dst; i < readerCount; i++, srcIter++, dstIter++)
|
|
|
|
{
|
|
|
|
dstIter->szReader = srcIter->szReader;
|
|
|
|
dstIter->pvUserData = srcIter->pvUserData;
|
|
|
|
dstIter->dwCurrentState = srcIter->dwCurrentState;
|
|
|
|
dstIter->dwEventState = srcIter->dwEventState;
|
|
|
|
dstIter->cbAtr = srcIter->cbAtr;
|
|
|
|
memcpy(dstIter->rgbAtr, srcIter->rgbAtr, MAX_ATR_SIZE * sizeof(unsigned char));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
2007-01-08 05:47:06 +01:00
|
|
|
TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hContext;
|
|
|
|
SERVER_DWORD dwTimeout;
|
|
|
|
SERVER_DWORD dwCount;
|
|
|
|
SERVER_LPSCARD_READERSTATE_A rsArray, cur;
|
|
|
|
SERVER_DWORD *stateArray = NULL, *curState;
|
|
|
|
MYPCSC_LPSCARD_READERSTATE_A myRsArray;
|
|
|
|
long i;
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
#if 0
|
2007-01-08 05:47:06 +01:00
|
|
|
RD_BOOL mapped = False;
|
2006-11-01 21:52:01 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
in->p += 0x18;
|
|
|
|
in_uint32_le(in, dwTimeout);
|
|
|
|
in_uint32_le(in, dwCount);
|
|
|
|
in->p += 0x08;
|
|
|
|
in_uint32_le(in, hContext);
|
|
|
|
in->p += 0x04;
|
2006-11-02 21:48:28 +01:00
|
|
|
|
|
|
|
DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
|
|
|
|
DEBUG_SCARD(("[dwTimeout 0x%.8x]\n", (unsigned int) dwTimeout));
|
|
|
|
DEBUG_SCARD(("[COUNT %d]\n", (unsigned int) dwCount));
|
|
|
|
DEBUG_SCARD(("[TYPE SIZE %d]\n", (unsigned int) sizeof(SERVER_SCARD_READERSTATE_A)));
|
|
|
|
|
2006-11-01 21:52:01 +01:00
|
|
|
if (dwCount > 0)
|
|
|
|
{
|
|
|
|
rsArray = SC_xmalloc(&lcHandle, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
|
|
|
|
if (!rsArray)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
memset(rsArray, 0, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
|
|
|
|
stateArray = SC_xmalloc(&lcHandle, dwCount * sizeof(MYPCSC_DWORD));
|
|
|
|
if (!stateArray)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
/* skip two pointers at beginning of struct */
|
|
|
|
for (i = 0, cur = (SERVER_LPSCARD_READERSTATE_A) ((unsigned char **) rsArray + 2);
|
|
|
|
i < dwCount; i++, cur++)
|
|
|
|
{
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint8a(in, cur, SERVER_SCARDSTATESIZE);
|
|
|
|
}
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
|
|
|
DEBUG_SCARD(("[READERS DUMP 1]------------------\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump((void *) rsArray, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0, cur = rsArray, curState = stateArray;
|
|
|
|
i < dwCount; i++, cur++, curState++)
|
|
|
|
{
|
|
|
|
SERVER_DWORD dataLength;
|
|
|
|
|
|
|
|
/* reset Current state hign bytes; */
|
|
|
|
*curState = cur->dwCurrentState;
|
|
|
|
cur->dwCurrentState &= 0x0000FFFF;
|
|
|
|
cur->dwEventState &= 0x0000FFFF;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (cur->dwCurrentState == (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT))
|
|
|
|
{
|
|
|
|
cur->dwCurrentState = 0x00000000;
|
|
|
|
mapped = True;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mappedStatus(*curState))
|
|
|
|
{
|
|
|
|
cur->dwCurrentState &= ~SCARD_STATE_INUSE;
|
|
|
|
cur->dwEventState &= ~SCARD_STATE_INUSE;
|
|
|
|
|
|
|
|
if (cur->dwCurrentState & SCARD_STATE_EMPTY)
|
|
|
|
{
|
|
|
|
cur->dwCurrentState &= ~SCARD_STATE_EMPTY;
|
|
|
|
cur->dwCurrentState |= SCARD_STATE_UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
in->p += 0x08;
|
|
|
|
in_uint32_le(in, dataLength);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[%d] Data Length %d]\n", (unsigned int) i, dataLength));
|
2006-11-01 21:52:01 +01:00
|
|
|
inRepos(in,
|
|
|
|
inString(&lcHandle, in, (char **) &(cur->szReader), dataLength,
|
|
|
|
wide));
|
|
|
|
|
|
|
|
if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0)
|
|
|
|
cur->dwCurrentState |= SCARD_STATE_IGNORE;
|
|
|
|
}
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
|
|
|
DEBUG_SCARD(("[READERS DUMP 2]------------------\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump((void *) rsArray, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rsArray = NULL;
|
|
|
|
stateArray = NULL;
|
|
|
|
}
|
|
|
|
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("\nCalling SCardGetStatusChange...\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
|
|
|
|
|
|
|
|
myRsArray = SC_xmalloc(&lcHandle, dwCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
|
|
|
|
if (!rsArray)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
memset(myRsArray, 0, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
|
|
|
|
copyReaderState_ServerToMyPCSC(rsArray, myRsArray, (SERVER_DWORD) dwCount);
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
|
|
|
DEBUG_SCARD(("[TRANSLATION OF READERS]--------------------\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump((void *) myRsArray, dwCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
rv = SCardGetStatusChange((MYPCSC_SCARDCONTEXT) hContext, (MYPCSC_DWORD) dwTimeout,
|
|
|
|
myRsArray, (MYPCSC_DWORD) dwCount);
|
|
|
|
copyReaderState_MyPCSCToServer(myRsArray, rsArray, (MYPCSC_DWORD) dwCount);
|
|
|
|
|
|
|
|
if (rv != SCARD_S_SUCCESS)
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardGetStatusChange Code=0x%.8x, %s-->\n",
|
|
|
|
(unsigned int) rv, pcsc_stringify_error(rv)));
|
2006-11-02 21:48:28 +01:00
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
else
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardGetStatusChange-->\n"));
|
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
2006-11-01 21:52:01 +01:00
|
|
|
if (dwCount > 0)
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[READERS DUMP]------------------\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump((void *) rsArray, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
out_uint32_le(out, dwCount);
|
|
|
|
out_uint32_le(out, 0x00084dd8);
|
|
|
|
out_uint32_le(out, dwCount);
|
|
|
|
|
|
|
|
for (i = 0, cur = rsArray, curState = stateArray; i < dwCount; i++, cur++, curState++)
|
|
|
|
{
|
|
|
|
|
|
|
|
cur->dwCurrentState = (*curState);
|
|
|
|
cur->dwEventState |= (*curState) & 0xFFFF0000;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (mapped && (cur->dwCurrentState & SCARD_STATE_PRESENT)
|
|
|
|
&& (cur->dwCurrentState & SCARD_STATE_CHANGED)
|
|
|
|
&& (cur->dwEventState & SCARD_STATE_PRESENT)
|
|
|
|
&& (cur->dwEventState & SCARD_STATE_CHANGED))
|
|
|
|
{
|
|
|
|
cur->dwEventState |= SCARD_STATE_INUSE;
|
|
|
|
}
|
|
|
|
else if (cur->dwEventState & SCARD_STATE_UNKNOWN)
|
|
|
|
{
|
|
|
|
cur->dwEventState &= ~SCARD_STATE_UNKNOWN;
|
|
|
|
cur->dwEventState |= SCARD_STATE_EMPTY;
|
|
|
|
mapped = True;
|
|
|
|
}
|
|
|
|
else if ((!mapped) && (cur->dwEventState & SCARD_STATE_INUSE))
|
|
|
|
{
|
|
|
|
mapped = True;
|
|
|
|
cur->dwEventState &= ~SCARD_STATE_INUSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
cur->dwEventState = incStatus(cur->dwEventState, mapped);
|
|
|
|
#endif
|
|
|
|
cur->dwEventState = incStatus(cur->dwEventState, False);
|
|
|
|
|
|
|
|
out_uint8p(out, (void *) ((unsigned char **) cur + 2),
|
|
|
|
sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
|
|
|
|
}
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
SC_xfreeallmemory(&lcHandle);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
TS_SCardCancel(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hContext;
|
|
|
|
|
|
|
|
in->p += 0x1C;
|
|
|
|
in_uint32_le(in, hContext);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
|
|
|
|
DEBUG_SCARD(("Canceling... \n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
rv = SCardCancel((MYPCSC_SCARDCONTEXT) hContext);
|
|
|
|
if (rv != SCARD_S_SUCCESS)
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardCancel Code=0x%.8x, %s-->\n", (unsigned int) rv,
|
|
|
|
pcsc_stringify_error(rv)));
|
2006-11-02 21:48:28 +01:00
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
else
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardCancel-->\n"));
|
|
|
|
}
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
2007-01-08 05:47:06 +01:00
|
|
|
TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
int i, j, k;
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hContext;
|
|
|
|
/* The SCARD_ATRMASK_L struct doesn't contain any longs or DWORDs -
|
|
|
|
no need to split into SERVER_ and MYPCSC_ */
|
|
|
|
LPSCARD_ATRMASK_L pAtrMasks, cur;
|
|
|
|
SERVER_DWORD atrMaskCount = 0;
|
|
|
|
SERVER_DWORD readerCount = 0;
|
|
|
|
SERVER_LPSCARD_READERSTATE_A rsArray, ResArray, rsCur;
|
|
|
|
MYPCSC_LPSCARD_READERSTATE_A myRsArray;
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
|
|
|
|
in->p += 0x2C;
|
|
|
|
in_uint32_le(in, hContext);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
|
2006-11-01 21:52:01 +01:00
|
|
|
in_uint32_le(in, atrMaskCount);
|
|
|
|
pAtrMasks = SC_xmalloc(&lcHandle, atrMaskCount * sizeof(SCARD_ATRMASK_L));
|
|
|
|
if (!pAtrMasks)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
in_uint8a(in, pAtrMasks, atrMaskCount * sizeof(SCARD_ATRMASK_L));
|
|
|
|
|
|
|
|
in_uint32_le(in, readerCount);
|
|
|
|
rsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SCARD_READERSTATE_A));
|
|
|
|
if (!rsArray)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
memset(rsArray, 0, readerCount * sizeof(SCARD_READERSTATE_A));
|
|
|
|
|
|
|
|
for (i = 0, rsCur = (SERVER_LPSCARD_READERSTATE_A) ((unsigned char **) rsArray + 2);
|
|
|
|
i < readerCount; i++, rsCur++)
|
|
|
|
{
|
|
|
|
in_uint8s(in, 4);
|
|
|
|
in_uint8a(in, rsCur, SERVER_SCARDSTATESIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
ResArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
|
|
|
|
if (!ResArray)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
memcpy(ResArray, rsArray, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
|
|
|
|
|
|
|
|
for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++)
|
|
|
|
{
|
|
|
|
inReaderName(&lcHandle, in, (char **) &rsCur->szReader, wide);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[CHECK READER %s]\n",
|
|
|
|
(rsCur->szReader) ? (rsCur->szReader) : ("NULL")));
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[CALL subfunction \"SCardGetStatusChange\"]\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
/* FIXME segfault here. */
|
|
|
|
myRsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
|
|
|
|
if (!myRsArray)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
rv = SCardGetStatusChange((MYPCSC_SCARDCONTEXT) hContext, 0x00000001, myRsArray,
|
|
|
|
readerCount);
|
|
|
|
copyReaderState_MyPCSCToServer(myRsArray, rsArray, readerCount);
|
|
|
|
if (rv != SCARD_S_SUCCESS)
|
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardGetStatusChange (no SCardLocateCardsByATR) Code=0x%.8x, %s-->\n", (unsigned int) rv, pcsc_stringify_error(rv)));
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardGetStatusChange (no SCardLocateCardsByATR)-->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
cur = pAtrMasks;
|
|
|
|
for (i = 0, cur = pAtrMasks; i < atrMaskCount; i++, cur++)
|
|
|
|
{
|
|
|
|
for (j = 0, rsCur = rsArray; j < readerCount; j++, rsCur++)
|
|
|
|
{
|
2007-01-08 05:47:06 +01:00
|
|
|
RD_BOOL equal = 1;
|
2006-11-01 21:52:01 +01:00
|
|
|
for (k = 0; k < cur->cbAtr; k++)
|
|
|
|
{
|
|
|
|
/* This line check if them equal */
|
|
|
|
if (cur->rgbAtr[k] != rsCur->rgbAtr[k])
|
|
|
|
/* Next Line was make to search with mask (some strange behavours with applications which use eToken SmartCards) */
|
|
|
|
/* if((cur->rgbAtr[k]&cur->rgbMask[k])!=(rsCur->rgbAtr[k]&cur->rgbMask[k])){ */
|
|
|
|
{
|
|
|
|
equal = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (equal)
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[FOUND]\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
rsCur->dwEventState |= 0x00000040; /* SCARD_STATE_ATRMATCH 0x00000040 */
|
|
|
|
memcpy(ResArray + j, rsCur, sizeof(SCARD_READERSTATE_A));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out_uint32_le(out, readerCount);
|
|
|
|
out_uint32_le(out, 0x00084dd8);
|
|
|
|
out_uint32_le(out, readerCount);
|
|
|
|
|
|
|
|
for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++)
|
|
|
|
{
|
|
|
|
out_uint8p(out, (void *) ((unsigned char **) rsCur + 2),
|
|
|
|
sizeof(SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
|
|
|
|
}
|
|
|
|
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
SC_xfreeallmemory(&lcHandle);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
TS_SCardBeginTransaction(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hCard;
|
|
|
|
MYPCSC_SCARDCONTEXT myHCard;
|
|
|
|
|
|
|
|
in->p += 0x30;
|
|
|
|
in_uint32_le(in, hCard);
|
|
|
|
myHCard = scHandleToMyPCSC(hCard);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
|
|
|
|
DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
|
2006-11-01 21:52:01 +01:00
|
|
|
rv = SCardBeginTransaction(myHCard);
|
|
|
|
if (rv != SCARD_S_SUCCESS)
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardBeginTransaction Code=0x%.8x, %s-->\n",
|
|
|
|
(unsigned int) rv, pcsc_stringify_error(rv)));
|
2006-11-02 21:48:28 +01:00
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
else
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardBeginTransaction-->\n"));
|
|
|
|
}
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
TS_SCardEndTransaction(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hCard;
|
|
|
|
MYPCSC_SCARDCONTEXT myHCard;
|
|
|
|
SERVER_DWORD dwDisposition = 0;
|
|
|
|
|
|
|
|
in->p += 0x20;
|
|
|
|
in_uint32_le(in, dwDisposition);
|
|
|
|
in->p += 0x0C;
|
|
|
|
in_uint32_le(in, hCard);
|
|
|
|
myHCard = scHandleToMyPCSC(hCard);
|
2006-11-02 21:48:28 +01:00
|
|
|
|
|
|
|
DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
|
|
|
|
DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
|
|
|
|
DEBUG_SCARD(("[dwDisposition = 0x%.8x]\n", (unsigned int) dwDisposition));
|
|
|
|
|
2006-11-01 21:52:01 +01:00
|
|
|
rv = SCardEndTransaction(myHCard, (MYPCSC_DWORD) dwDisposition);
|
|
|
|
if (rv != SCARD_S_SUCCESS)
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardEndTransaction Code=0x%.8x, %s-->\n", (unsigned int) rv,
|
|
|
|
pcsc_stringify_error(rv)));
|
2006-11-02 21:48:28 +01:00
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
else
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardEndTransaction-->\n"));
|
|
|
|
}
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
copyIORequest_MyPCSCToServer(MYPCSC_LPSCARD_IO_REQUEST src, SERVER_LPSCARD_IO_REQUEST dst)
|
|
|
|
{
|
|
|
|
unsigned char *srcBytes, *dstBytes;
|
|
|
|
size_t bytesToCopy = src->cbPciLength - sizeof(MYPCSC_SCARD_IO_REQUEST);
|
|
|
|
srcBytes = ((unsigned char *) src + sizeof(MYPCSC_SCARD_IO_REQUEST));
|
|
|
|
dstBytes = ((unsigned char *) dst + sizeof(SERVER_SCARD_IO_REQUEST));
|
|
|
|
dst->dwProtocol = src->dwProtocol;
|
|
|
|
dst->cbPciLength = src->cbPciLength
|
|
|
|
- sizeof(MYPCSC_SCARD_IO_REQUEST) + sizeof(SERVER_SCARD_IO_REQUEST);
|
|
|
|
memcpy(dstBytes, srcBytes, bytesToCopy);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
copyIORequest_ServerToMyPCSC(SERVER_LPSCARD_IO_REQUEST src, MYPCSC_LPSCARD_IO_REQUEST dst)
|
|
|
|
{
|
|
|
|
unsigned char *srcBytes, *dstBytes;
|
|
|
|
size_t bytesToCopy = src->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST);
|
|
|
|
srcBytes = ((unsigned char *) src + sizeof(SERVER_SCARD_IO_REQUEST));
|
|
|
|
dstBytes = ((unsigned char *) dst + sizeof(MYPCSC_SCARD_IO_REQUEST));
|
|
|
|
dst->dwProtocol = src->dwProtocol;
|
|
|
|
dst->cbPciLength = src->cbPciLength
|
|
|
|
- sizeof(SERVER_SCARD_IO_REQUEST) + sizeof(MYPCSC_SCARD_IO_REQUEST);
|
|
|
|
memcpy(dstBytes, srcBytes, bytesToCopy);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
TS_SCardTransmit(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_DWORD map[7], linkedLen;
|
|
|
|
void *tmp;
|
|
|
|
SERVER_SCARDCONTEXT hCard;
|
|
|
|
MYPCSC_SCARDCONTEXT myHCard;
|
|
|
|
SERVER_LPSCARD_IO_REQUEST pioSendPci, pioRecvPci;
|
|
|
|
MYPCSC_LPSCARD_IO_REQUEST myPioSendPci, myPioRecvPci;
|
|
|
|
unsigned char *sendBuf = NULL, *recvBuf = NULL;
|
|
|
|
SERVER_DWORD cbSendLength, cbRecvLength;
|
|
|
|
MYPCSC_DWORD myCbRecvLength;
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
|
|
|
|
in->p += 0x14;
|
|
|
|
in_uint32_le(in, map[0]);
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, map[1]);
|
|
|
|
pioSendPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
|
|
|
|
if (!pioSendPci)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
in_uint8a(in, pioSendPci, sizeof(SERVER_SCARD_IO_REQUEST));
|
|
|
|
in_uint32_le(in, map[2]);
|
|
|
|
in_uint32_le(in, cbSendLength);
|
|
|
|
in_uint32_le(in, map[3]);
|
|
|
|
in_uint32_le(in, map[4]);
|
|
|
|
in_uint32_le(in, map[5]);
|
|
|
|
in_uint32_le(in, cbRecvLength);
|
|
|
|
if (map[0] & INPUT_LINKED)
|
|
|
|
inSkipLinked(in);
|
|
|
|
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, hCard);
|
|
|
|
myHCard = scHandleToMyPCSC(hCard);
|
|
|
|
|
|
|
|
if (map[2] & INPUT_LINKED)
|
|
|
|
{
|
|
|
|
in_uint32_le(in, linkedLen);
|
|
|
|
pioSendPci->cbPciLength = linkedLen + sizeof(SERVER_SCARD_IO_REQUEST);
|
|
|
|
tmp = SC_xmalloc(&lcHandle, pioSendPci->cbPciLength);
|
|
|
|
if (!tmp)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
in_uint8a(in, (void *) ((unsigned char *) tmp + sizeof(SERVER_SCARD_IO_REQUEST)),
|
|
|
|
linkedLen);
|
|
|
|
memcpy(tmp, pioSendPci, sizeof(SERVER_SCARD_IO_REQUEST));
|
|
|
|
SC_xfree(&lcHandle, pioSendPci);
|
|
|
|
pioSendPci = tmp;
|
|
|
|
tmp = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pioSendPci->cbPciLength = sizeof(SERVER_SCARD_IO_REQUEST);
|
|
|
|
|
|
|
|
if (map[3] & INPUT_LINKED)
|
|
|
|
{
|
|
|
|
in_uint32_le(in, linkedLen);
|
|
|
|
sendBuf = SC_xmalloc(&lcHandle, linkedLen);
|
|
|
|
if (!sendBuf)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
in_uint8a(in, sendBuf, linkedLen);
|
|
|
|
inRepos(in, linkedLen);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
sendBuf = NULL;
|
|
|
|
|
|
|
|
if (cbRecvLength)
|
|
|
|
{
|
|
|
|
recvBuf = SC_xmalloc(&lcHandle, cbRecvLength);
|
|
|
|
if (!recvBuf)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (map[4] & INPUT_LINKED)
|
|
|
|
{
|
|
|
|
pioRecvPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
|
|
|
|
if (!pioRecvPci)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
in_uint8a(in, pioRecvPci, sizeof(SERVER_SCARD_IO_REQUEST));
|
|
|
|
in_uint32_le(in, map[6]);
|
|
|
|
if (map[6] & INPUT_LINKED)
|
|
|
|
{
|
|
|
|
in_uint32_le(in, linkedLen);
|
|
|
|
pioRecvPci->cbPciLength = linkedLen + sizeof(SERVER_SCARD_IO_REQUEST);
|
|
|
|
tmp = SC_xmalloc(&lcHandle, pioRecvPci->cbPciLength);
|
|
|
|
if (!tmp)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
in_uint8a(in,
|
|
|
|
(void *) ((unsigned char *) tmp +
|
|
|
|
sizeof(SERVER_SCARD_IO_REQUEST)), linkedLen);
|
|
|
|
memcpy(tmp, pioRecvPci, sizeof(SERVER_SCARD_IO_REQUEST));
|
|
|
|
SC_xfree(&lcHandle, pioRecvPci);
|
|
|
|
pioRecvPci = tmp;
|
|
|
|
tmp = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pioRecvPci->cbPciLength = sizeof(SERVER_SCARD_IO_REQUEST);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pioRecvPci = NULL;
|
|
|
|
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
|
|
|
DEBUG_SCARD(("++++++++++\n"));
|
|
|
|
DEBUG_SCARD(("[SEND LEN = %d]\n", (unsigned int) cbSendLength));
|
|
|
|
DEBUG_SCARD(("[RECV LEN = %d]\n", (unsigned int) cbRecvLength));
|
|
|
|
DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
|
|
|
|
DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
|
|
|
|
DEBUG_SCARD(("[pioSendPci]\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
if (pioSendPci == NULL)
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
|
|
|
DEBUG_SCARD(("NULL\n"));
|
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
else
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump((void *) pioSendPci, pioSendPci->cbPciLength);
|
2006-11-02 21:48:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG_SCARD(("[pioRecvPci]\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
if (pioRecvPci == NULL)
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
|
|
|
DEBUG_SCARD(("NULL\n"));
|
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
else
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump((void *) pioRecvPci, pioRecvPci->cbPciLength);
|
2006-11-02 21:48:28 +01:00
|
|
|
}
|
|
|
|
DEBUG_SCARD(("[sendBuf]\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump(sendBuf, cbSendLength);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("++++++++++\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
myCbRecvLength = cbRecvLength;
|
|
|
|
myPioSendPci = SC_xmalloc(&lcHandle,
|
|
|
|
sizeof(MYPCSC_SCARD_IO_REQUEST)
|
|
|
|
+ pioSendPci->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST));
|
|
|
|
if (!myPioSendPci)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
copyIORequest_ServerToMyPCSC(pioSendPci, myPioSendPci);
|
|
|
|
/* always a send, not always a recv */
|
|
|
|
if (pioRecvPci)
|
|
|
|
{
|
|
|
|
myPioRecvPci = SC_xmalloc(&lcHandle,
|
|
|
|
sizeof(MYPCSC_SCARD_IO_REQUEST)
|
|
|
|
+ pioRecvPci->cbPciLength
|
|
|
|
- sizeof(SERVER_SCARD_IO_REQUEST));
|
|
|
|
if (!myPioRecvPci)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
copyIORequest_ServerToMyPCSC(pioRecvPci, myPioRecvPci);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
myPioRecvPci = NULL;
|
|
|
|
}
|
|
|
|
rv = SCardTransmit(myHCard, myPioSendPci, sendBuf, (MYPCSC_DWORD) cbSendLength,
|
|
|
|
myPioRecvPci, recvBuf, &myCbRecvLength);
|
|
|
|
cbRecvLength = myCbRecvLength;
|
2006-11-02 12:09:35 +01:00
|
|
|
|
|
|
|
/* FIXME: handle responses with length > 448 bytes */
|
|
|
|
if (cbRecvLength > 448)
|
|
|
|
{
|
|
|
|
warning("Card response limited from %d to 448 bytes!\n", cbRecvLength);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[RECV LEN %d -> %d]\n", (unsigned int) cbRecvLength, 400));
|
2006-11-02 12:09:35 +01:00
|
|
|
cbRecvLength = 448;
|
|
|
|
}
|
|
|
|
|
2006-11-01 21:52:01 +01:00
|
|
|
if (pioRecvPci)
|
|
|
|
{
|
|
|
|
copyIORequest_MyPCSCToServer(myPioRecvPci, pioRecvPci);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rv != SCARD_S_SUCCESS)
|
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardTransmit Code=0x%.8x, %s-->\n", (unsigned int) rv,
|
|
|
|
pcsc_stringify_error(rv)));
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardTransmit-->\n"));
|
|
|
|
DEBUG_SCARD(("RESULT %d\n", (unsigned int) cbRecvLength));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump(recvBuf, cbRecvLength);
|
|
|
|
if (myPioRecvPci)
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("--- myPioRecvPci ---\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump((void *) myPioRecvPci, myPioRecvPci->cbPciLength);
|
|
|
|
}
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("------------------\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
#endif
|
|
|
|
#if 0
|
|
|
|
if ((pioRecvPci != NULL) && (pioRecvPci->cbPciLength > 0))
|
|
|
|
{
|
|
|
|
out_uint32_le(out, (DWORD) pioRecvPci); /* if not NULL, this 4 bytes indicates that pioRecvPci is present */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
out_uint32_le(out, 0); /* pioRecvPci 0x00; */
|
|
|
|
|
|
|
|
outBufferStart(out, cbRecvLength); /* start of recvBuf output */
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if ((pioRecvPci) && (pioRecvPci->cbPciLength > 0))
|
|
|
|
{
|
|
|
|
out_uint32_le(out, pioRecvPci->dwProtocol);
|
|
|
|
int len = pioRecvPci->cbPciLength - sizeof(pioRecvPci);
|
|
|
|
outBufferStartWithLimit(out, len, 12);
|
|
|
|
outBufferFinishWithLimit(out,
|
|
|
|
(char *) ((DWORD) pioRecvPci + sizeof(pioRecvPci)),
|
|
|
|
len, 12);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
outBufferFinish(out, (char *) recvBuf, cbRecvLength);
|
|
|
|
}
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
SC_xfreeallmemory(&lcHandle);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
2007-01-08 05:47:06 +01:00
|
|
|
TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hCard;
|
|
|
|
MYPCSC_SCARDCONTEXT myHCard;
|
|
|
|
SERVER_DWORD dwState = 0, dwProtocol = 0, dwReaderLen, dwAtrLen;
|
|
|
|
MYPCSC_DWORD state, protocol, readerLen, atrLen;
|
|
|
|
SERVER_DWORD dataLength;
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
char *readerName;
|
|
|
|
unsigned char *atr;
|
|
|
|
|
|
|
|
in->p += 0x24;
|
|
|
|
in_uint32_le(in, dwReaderLen);
|
|
|
|
in_uint32_le(in, dwAtrLen);
|
|
|
|
in->p += 0x0C;
|
|
|
|
in_uint32_le(in, hCard);
|
|
|
|
in->p += 0x04;
|
|
|
|
myHCard = scHandleToMyPCSC(hCard);
|
2006-11-02 21:48:28 +01:00
|
|
|
|
|
|
|
DEBUG_SCARD(("[hCard 0x%.8x]\n", (unsigned int) hCard));
|
|
|
|
DEBUG_SCARD(("[myHCard 0x%016lx]\n", (unsigned long) myHCard));
|
|
|
|
DEBUG_SCARD(("[dwReaderLen %d]\n", (unsigned int) dwReaderLen));
|
|
|
|
DEBUG_SCARD(("[dwAtrLen %d]\n", (unsigned int) dwAtrLen));
|
2006-11-01 21:52:01 +01:00
|
|
|
|
|
|
|
if (dwReaderLen <= 0 || dwReaderLen == SCARD_AUTOALLOCATE || dwReaderLen > SCARD_MAX_MEM)
|
|
|
|
dwReaderLen = SCARD_MAX_MEM;
|
|
|
|
if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM)
|
|
|
|
dwAtrLen = SCARD_MAX_MEM;
|
|
|
|
|
|
|
|
readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2);
|
|
|
|
if (!readerName)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
|
|
|
|
atr = SC_xmalloc(&lcHandle, dwAtrLen + 1);
|
|
|
|
if (!atr)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
|
|
|
|
state = dwState;
|
|
|
|
protocol = dwProtocol;
|
|
|
|
readerLen = dwReaderLen;
|
|
|
|
atrLen = dwAtrLen;
|
|
|
|
rv = SCardStatus(myHCard, readerName, &readerLen, &state, &protocol, atr, &atrLen);
|
|
|
|
dwAtrLen = atrLen;
|
|
|
|
dwReaderLen = readerLen;
|
|
|
|
dwProtocol = protocol;
|
|
|
|
dwState = state;
|
|
|
|
|
|
|
|
|
|
|
|
if (rv != SCARD_S_SUCCESS)
|
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardStatus Code=0x%.8x, %s-->\n", (unsigned int) rv,
|
|
|
|
pcsc_stringify_error(rv)));
|
2006-11-01 21:52:01 +01:00
|
|
|
return SC_returnCode(rv, &lcHandle, in, out);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardStatus-->\n"));
|
|
|
|
DEBUG_SCARD(("[dwState 0x%.8x]\n", (unsigned int) dwState));
|
|
|
|
DEBUG_SCARD(("[dwProtocol 0x%.8x]\n", (unsigned int) dwProtocol));
|
|
|
|
DEBUG_SCARD(("[Reader Name]\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump((unsigned char *) readerName, dwReaderLen);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[Atr]\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump(atr, dwAtrLen);
|
|
|
|
#endif
|
|
|
|
if (dwState & (SCARD_SPECIFIC | SCARD_NEGOTIABLE))
|
|
|
|
dwState = 0x00000006;
|
|
|
|
else
|
|
|
|
#if 0
|
|
|
|
if (dwState & SCARD_SPECIFIC)
|
|
|
|
dwState = 0x00000006;
|
|
|
|
else if (dwState & SCARD_NEGOTIABLE)
|
|
|
|
dwState = 0x00000005;
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
if (dwState & SCARD_POWERED)
|
|
|
|
dwState = 0x00000004;
|
|
|
|
else if (dwState & SCARD_SWALLOWED)
|
|
|
|
dwState = 0x00000003;
|
|
|
|
else if (dwState & SCARD_PRESENT)
|
|
|
|
dwState = 0x00000002;
|
|
|
|
else if (dwState & SCARD_ABSENT)
|
|
|
|
dwState = 0x00000001;
|
|
|
|
else
|
|
|
|
dwState = 0x00000000;
|
|
|
|
|
|
|
|
void *p_len1 = out->p;
|
|
|
|
out_uint32_le(out, dwReaderLen);
|
|
|
|
out_uint32_le(out, 0x00020000);
|
|
|
|
out_uint32_le(out, dwState);
|
|
|
|
out_uint32_le(out, dwProtocol);
|
|
|
|
out_uint8p(out, atr, dwAtrLen);
|
|
|
|
if (dwAtrLen < 32)
|
|
|
|
{
|
|
|
|
out_uint8s(out, 32 - dwAtrLen);
|
|
|
|
}
|
|
|
|
out_uint32_le(out, dwAtrLen);
|
|
|
|
|
|
|
|
void *p_len2 = out->p;
|
|
|
|
out_uint32_le(out, dwReaderLen);
|
|
|
|
dataLength = outString(out, readerName, wide);
|
|
|
|
dataLength += outString(out, "\0", wide);
|
|
|
|
outRepos(out, dataLength);
|
|
|
|
void *psave = out->p;
|
|
|
|
out->p = p_len1;
|
|
|
|
out_uint32_le(out, dataLength);
|
|
|
|
out->p = p_len2;
|
|
|
|
out_uint32_le(out, dataLength);
|
|
|
|
out->p = psave;
|
|
|
|
}
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
SC_xfreeallmemory(&lcHandle);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
TS_SCardState(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hCard;
|
|
|
|
MYPCSC_SCARDCONTEXT myHCard;
|
|
|
|
SERVER_DWORD dwState = 0, dwProtocol = 0, dwReaderLen, dwAtrLen;
|
|
|
|
MYPCSC_DWORD state, protocol, readerLen, atrLen;
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
char *readerName;
|
|
|
|
unsigned char *atr;
|
|
|
|
|
|
|
|
in->p += 0x24;
|
|
|
|
in_uint32_le(in, dwAtrLen);
|
|
|
|
in->p += 0x0C;
|
|
|
|
in_uint32_le(in, hCard);
|
|
|
|
in->p += 0x04;
|
|
|
|
myHCard = scHandleToMyPCSC(hCard);
|
|
|
|
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[hCard 0x%.8x]\n", (unsigned int) hCard));
|
|
|
|
DEBUG_SCARD(("[myHCard 0x%.8x]\n", (unsigned int) myHCard));
|
|
|
|
DEBUG_SCARD(("[dwAtrLen %d]\n", (unsigned int) dwAtrLen));
|
2006-11-01 21:52:01 +01:00
|
|
|
|
|
|
|
dwReaderLen = SCARD_MAX_MEM;
|
|
|
|
if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM)
|
|
|
|
dwAtrLen = SCARD_MAX_MEM;
|
|
|
|
|
|
|
|
readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2);
|
|
|
|
if (!readerName)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
|
|
|
|
atr = SC_xmalloc(&lcHandle, dwAtrLen + 1);
|
|
|
|
if (!atr)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
|
|
|
|
state = dwState;
|
|
|
|
protocol = dwProtocol;
|
|
|
|
readerLen = dwReaderLen;
|
|
|
|
atrLen = dwAtrLen;
|
|
|
|
rv = SCardStatus(myHCard, readerName, &readerLen, &state, &protocol, atr, &atrLen);
|
|
|
|
dwAtrLen = atrLen;
|
|
|
|
dwReaderLen = readerLen;
|
|
|
|
dwProtocol = protocol;
|
|
|
|
dwState = state;
|
|
|
|
|
|
|
|
if (rv != SCARD_S_SUCCESS)
|
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardStatus (no ScardState) Code=0x%.8x, %s-->\n",
|
|
|
|
(unsigned int) rv, pcsc_stringify_error(rv)));
|
2006-11-01 21:52:01 +01:00
|
|
|
return SC_returnCode(rv, &lcHandle, in, out);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardStatus (no ScardState)-->\n"));
|
|
|
|
DEBUG_SCARD(("[dwState 0x%.8x]\n", (unsigned int) dwState));
|
|
|
|
DEBUG_SCARD(("[dwProtocol 0x%.8x]\n", (unsigned int) dwProtocol));
|
|
|
|
DEBUG_SCARD(("[Atr]\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump(atr, dwAtrLen);
|
|
|
|
#endif
|
|
|
|
if (dwState & (SCARD_SPECIFIC | SCARD_NEGOTIABLE))
|
|
|
|
dwState = 0x00000006;
|
|
|
|
else
|
|
|
|
#if 0
|
|
|
|
if (dwState & SCARD_SPECIFIC)
|
|
|
|
dwState = 0x00000006;
|
|
|
|
else if (dwState & SCARD_NEGOTIABLE)
|
|
|
|
dwState = 0x00000005;
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
if (dwState & SCARD_POWERED)
|
|
|
|
dwState = 0x00000004;
|
|
|
|
else if (dwState & SCARD_SWALLOWED)
|
|
|
|
dwState = 0x00000003;
|
|
|
|
else if (dwState & SCARD_PRESENT)
|
|
|
|
dwState = 0x00000002;
|
|
|
|
else if (dwState & SCARD_ABSENT)
|
|
|
|
dwState = 0x00000001;
|
|
|
|
else
|
|
|
|
dwState = 0x00000000;
|
|
|
|
|
|
|
|
out_uint32_le(out, dwState);
|
|
|
|
out_uint32_le(out, dwProtocol);
|
|
|
|
out_uint32_le(out, dwAtrLen);
|
|
|
|
out_uint32_le(out, 0x00000001);
|
|
|
|
out_uint32_le(out, dwAtrLen);
|
|
|
|
out_uint8p(out, atr, dwAtrLen);
|
|
|
|
outRepos(out, dwAtrLen);
|
|
|
|
}
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
SC_xfreeallmemory(&lcHandle);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef WITH_PCSC120
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
TS_SCardListReaderGroups(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hContext;
|
|
|
|
SERVER_DWORD dwGroups;
|
|
|
|
MYPCSC_DWORD groups;
|
|
|
|
char *szGroups;
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
|
|
|
|
in->p += 0x20;
|
|
|
|
in_uint32_le(in, dwGroups);
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, hContext);
|
|
|
|
|
|
|
|
if (dwGroups <= 0 || dwGroups == SCARD_AUTOALLOCATE || dwGroups > SCARD_MAX_MEM)
|
|
|
|
dwGroups = SCARD_MAX_MEM;
|
|
|
|
|
|
|
|
szGroups = SC_xmalloc(&lcHandle, dwGroups);
|
|
|
|
if (!szGroups)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
|
|
|
|
groups = dwGroups;
|
|
|
|
rv = SCardListReaderGroups((MYPCSC_SCARDCONTEXT) hContext, szGroups, &groups);
|
|
|
|
dwGroups = groups;
|
|
|
|
|
|
|
|
if (rv)
|
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardListReaderGroups Code=0x%.8x, %s-->\n",
|
|
|
|
(unsigned int) rv, pcsc_stringify_error(rv)));
|
2006-11-01 21:52:01 +01:00
|
|
|
return SC_returnCode(rv, &lcHandle, in, out);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardListReaderGroups-->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
out_uint32_le(out, dwGroups);
|
|
|
|
out_uint32_le(out, 0x00200000);
|
|
|
|
out_uint32_le(out, dwGroups);
|
|
|
|
out_uint8a(out, szGroups, dwGroups);
|
|
|
|
outRepos(out, dwGroups);
|
|
|
|
out_uint32_le(out, 0x00000000);
|
|
|
|
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
SC_xfreeallmemory(&lcHandle);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
TS_SCardGetAttrib(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hCard;
|
|
|
|
MYPCSC_SCARDCONTEXT myHCard;
|
|
|
|
SERVER_DWORD dwAttrId, dwAttrLen;
|
|
|
|
MYPCSC_DWORD attrLen;
|
|
|
|
unsigned char *pbAttr;
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
|
|
|
|
in->p += 0x20;
|
|
|
|
in_uint32_le(in, dwAttrId);
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, dwAttrLen);
|
|
|
|
in->p += 0x0C;
|
|
|
|
in_uint32_le(in, hCard);
|
|
|
|
myHCard = scHandleToMyPCSC(hCard);
|
|
|
|
|
|
|
|
dwAttrId = dwAttrId & 0x0000FFFF;
|
|
|
|
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
|
|
|
|
DEBUG_SCARD(("[myHCard 0x%.8x]\n", (unsigned int) myHCard));
|
|
|
|
DEBUG_SCARD(("[dwAttrId = 0x%.8x]\n", (unsigned int) dwAttrId));
|
|
|
|
DEBUG_SCARD(("[dwAttrLen = 0x%.8x]\n", (unsigned int) dwAttrLen));
|
2006-11-01 21:52:01 +01:00
|
|
|
|
|
|
|
if (dwAttrLen > MAX_BUFFER_SIZE)
|
|
|
|
dwAttrLen = MAX_BUFFER_SIZE;
|
|
|
|
|
|
|
|
|
|
|
|
if (dwAttrLen > SCARD_AUTOALLOCATE)
|
|
|
|
pbAttr = NULL;
|
|
|
|
else if ((dwAttrLen < 0) || (dwAttrLen > SCARD_MAX_MEM))
|
|
|
|
{
|
|
|
|
dwAttrLen = SCARD_AUTOALLOCATE;
|
|
|
|
pbAttr = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pbAttr = SC_xmalloc(&lcHandle, dwAttrLen);
|
|
|
|
if (!pbAttr)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
}
|
|
|
|
|
|
|
|
attrLen = dwAttrLen;
|
|
|
|
rv = SCardGetAttrib(myHCard, (MYPCSC_DWORD) dwAttrId, pbAttr, &attrLen);
|
|
|
|
dwAttrLen = attrLen;
|
|
|
|
|
|
|
|
if (dwAttrId == 0x00000100 && rv != SCARD_S_SUCCESS)
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("Get Attribute ATTR_VENDOR_NAME\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
pthread_mutex_lock(&hcardAccess);
|
|
|
|
PSCHCardRec hcard = hcardFirst;
|
|
|
|
while (hcard)
|
|
|
|
{
|
|
|
|
if (hcard->hCard == hCard)
|
|
|
|
{
|
|
|
|
dwAttrLen = strlen(hcard->vendor);
|
|
|
|
memcpy(pbAttr, hcard->vendor, dwAttrLen);
|
|
|
|
rv = SCARD_S_SUCCESS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
hcard = hcard->next;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&hcardAccess);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[0x%.8x]\n", (unsigned int) rv));
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (rv != SCARD_S_SUCCESS)
|
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardGetAttrib Code=0x%.8x, %s-->\n", (unsigned int) rv,
|
|
|
|
pcsc_stringify_error(rv)));
|
2006-11-01 21:52:01 +01:00
|
|
|
return SC_returnCode(rv, &lcHandle, in, out);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardGetAttrib-->\n"));
|
|
|
|
DEBUG_SCARD(("[LENGTH %d]\n", (unsigned int) dwAttrLen));
|
|
|
|
DEBUG_SCARD(("+++++++++++++++++++++\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump(pbAttr, dwAttrLen);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("+++++++++++++++++++++\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
#endif
|
|
|
|
out_uint32_le(out, dwAttrLen);
|
|
|
|
out_uint32_le(out, 0x00000200);
|
|
|
|
out_uint32_le(out, dwAttrLen);
|
|
|
|
if (!pbAttr)
|
|
|
|
{
|
|
|
|
out_uint8s(out, dwAttrLen);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
out_uint8p(out, pbAttr, dwAttrLen);
|
|
|
|
}
|
|
|
|
outRepos(out, dwAttrLen);
|
|
|
|
out_uint32_le(out, 0x00000000);
|
|
|
|
}
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
TS_SCardSetAttrib(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hCard;
|
|
|
|
MYPCSC_SCARDCONTEXT myHCard;
|
|
|
|
SERVER_DWORD dwAttrId;
|
|
|
|
SERVER_DWORD dwAttrLen;
|
|
|
|
unsigned char *pbAttr;
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
|
|
|
|
in->p += 0x20;
|
|
|
|
in_uint32_le(in, dwAttrId);
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, dwAttrLen);
|
|
|
|
in->p += 0x0C;
|
|
|
|
in_uint32_le(in, hCard);
|
|
|
|
myHCard = scHandleToMyPCSC(hCard);
|
|
|
|
|
|
|
|
dwAttrId = dwAttrId & 0x0000FFFF;
|
|
|
|
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
|
|
|
|
DEBUG_SCARD(("[myHCard 0x%.8x]\n", (unsigned int) myHCard));
|
|
|
|
DEBUG_SCARD(("[dwAttrId = 0x%.8x]\n", (unsigned int) dwAttrId));
|
|
|
|
DEBUG_SCARD(("[dwAttrLen = 0x%.8x]\n", (unsigned int) dwAttrLen));
|
2006-11-01 21:52:01 +01:00
|
|
|
|
|
|
|
if (dwAttrLen > MAX_BUFFER_SIZE)
|
|
|
|
dwAttrLen = MAX_BUFFER_SIZE;
|
|
|
|
|
|
|
|
pbAttr = SC_xmalloc(&lcHandle, dwAttrLen);
|
|
|
|
if (!pbAttr)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
|
|
|
|
in_uint8a(in, pbAttr, dwAttrLen);
|
|
|
|
rv = SCardSetAttrib(myHCard, (MYPCSC_DWORD) dwAttrId, pbAttr, (MYPCSC_DWORD) dwAttrLen);
|
|
|
|
|
|
|
|
if (rv)
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardSetAttrib Code=0x%.8x, %s-->\n", (unsigned int) rv,
|
|
|
|
pcsc_stringify_error(rv)));
|
2006-11-02 21:48:28 +01:00
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
else
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardSetAttrib-->\n"));
|
|
|
|
}
|
|
|
|
|
2006-11-01 21:52:01 +01:00
|
|
|
out_uint32_le(out, 0x00000000);
|
|
|
|
out_uint32_le(out, 0x00000200);
|
|
|
|
out_uint32_le(out, 0x00000000);
|
|
|
|
out_uint32_le(out, 0x00000000);
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
SC_xfreeallmemory(&lcHandle);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
TS_SCardControl(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
MYPCSC_DWORD rv;
|
|
|
|
SERVER_SCARDCONTEXT hContext;
|
|
|
|
SERVER_SCARDHANDLE hCard;
|
|
|
|
MYPCSC_SCARDHANDLE myHCard;
|
|
|
|
SERVER_DWORD map[3];
|
|
|
|
SERVER_DWORD dwControlCode;
|
2006-11-01 22:23:08 +01:00
|
|
|
unsigned char *pInBuffer, *pOutBuffer;
|
2006-11-01 21:52:01 +01:00
|
|
|
SERVER_DWORD nInBufferSize, nOutBufferSize, nOutBufferRealSize, nBytesReturned;
|
|
|
|
MYPCSC_DWORD sc_nBytesReturned;
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
|
|
|
|
pInBuffer = NULL;
|
|
|
|
pOutBuffer = NULL;
|
|
|
|
|
|
|
|
in->p += 0x14;
|
|
|
|
in_uint32_le(in, map[0]);
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, map[1]);
|
|
|
|
in_uint32_le(in, dwControlCode);
|
|
|
|
in_uint32_le(in, nInBufferSize);
|
|
|
|
in_uint32_le(in, map[2]);
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, nOutBufferSize);
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, hContext);
|
|
|
|
in->p += 0x04;
|
|
|
|
in_uint32_le(in, hCard);
|
|
|
|
if (map[2] & INPUT_LINKED)
|
|
|
|
{
|
|
|
|
/* read real input size */
|
|
|
|
in_uint32_le(in, nInBufferSize);
|
|
|
|
pInBuffer = SC_xmalloc(&lcHandle, nInBufferSize);
|
|
|
|
if (!pInBuffer)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
in_uint8a(in, pInBuffer, nInBufferSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (nOutBufferSize > 0)
|
|
|
|
{
|
|
|
|
nOutBufferRealSize = nOutBufferSize;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
nOutBufferRealSize = 1024;
|
|
|
|
|
|
|
|
nBytesReturned = nOutBufferRealSize;
|
|
|
|
|
|
|
|
nBytesReturned = nOutBufferRealSize;
|
|
|
|
pOutBuffer = SC_xmalloc(&lcHandle, nOutBufferRealSize);
|
|
|
|
if (!pOutBuffer)
|
|
|
|
return SC_returnNoMemoryError(&lcHandle, in, out);
|
|
|
|
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
|
|
|
DEBUG_SCARD(("[hContext = 0x%.8x]\n", (unsigned int) hContext));
|
|
|
|
DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
|
|
|
|
DEBUG_SCARD(("[dwControlCode = 0x%.8x]\n", (unsigned int) dwControlCode));
|
|
|
|
DEBUG_SCARD(("[nInBufferSize = %d]\n", (unsigned int) nInBufferSize));
|
|
|
|
DEBUG_SCARD(("[nOutBufferSize = %d]\n", (unsigned int) nOutBufferSize));
|
2006-11-01 21:52:01 +01:00
|
|
|
if (nInBufferSize > 0)
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[In buffer]\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump((unsigned char *) pInBuffer, nInBufferSize);
|
|
|
|
}
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("---> Calling SCardControl\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
sc_nBytesReturned = nBytesReturned;
|
|
|
|
myHCard = scHandleToMyPCSC(hCard);
|
2006-11-01 23:46:05 +01:00
|
|
|
#ifdef WITH_PCSC120
|
2006-11-01 21:52:01 +01:00
|
|
|
rv = SCardControl(myHCard, pInBuffer, (MYPCSC_DWORD) nInBufferSize, pOutBuffer,
|
|
|
|
&sc_nBytesReturned);
|
|
|
|
#else
|
|
|
|
rv = SCardControl(myHCard, (MYPCSC_DWORD) dwControlCode, pInBuffer,
|
|
|
|
(MYPCSC_DWORD) nInBufferSize, pOutBuffer,
|
|
|
|
(MYPCSC_DWORD) nOutBufferRealSize, &sc_nBytesReturned);
|
|
|
|
#endif
|
2006-11-01 23:46:05 +01:00
|
|
|
nBytesReturned = sc_nBytesReturned;
|
2006-11-01 21:52:01 +01:00
|
|
|
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
2006-11-01 21:52:01 +01:00
|
|
|
if (rv != SCARD_S_SUCCESS)
|
2006-11-02 21:48:28 +01:00
|
|
|
{
|
2006-11-04 21:02:42 +01:00
|
|
|
DEBUG_SCARD(("<--ERROR SCardControl Code=0x%.8x, %s-->\n", (unsigned int) rv,
|
|
|
|
pcsc_stringify_error(rv)));
|
2006-11-02 21:48:28 +01:00
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
else
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<--SUCCESS SCardControl-->\n"));
|
|
|
|
DEBUG_SCARD(("[LENGTH %d]\n", (unsigned int) nBytesReturned));
|
|
|
|
DEBUG_SCARD(("+++++++++++++++++++++\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump((unsigned char *) pOutBuffer, nBytesReturned);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("+++++++++++++++++++++\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
out_uint32_le(out, nBytesReturned);
|
|
|
|
out_uint32_le(out, 0x00000004);
|
|
|
|
out_uint32_le(out, nBytesReturned);
|
|
|
|
if (nBytesReturned > 0)
|
|
|
|
{
|
|
|
|
out_uint8p(out, pOutBuffer, nBytesReturned);
|
|
|
|
outRepos(out, nBytesReturned);
|
|
|
|
}
|
|
|
|
|
2006-11-03 19:57:09 +01:00
|
|
|
outForceAlignment(out, 8);
|
2006-11-01 21:52:01 +01:00
|
|
|
SC_xfreeallmemory(&lcHandle);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MYPCSC_DWORD
|
|
|
|
TS_SCardAccessStartedEvent(STREAM in, STREAM out)
|
|
|
|
{
|
|
|
|
out_uint8s(out, 8);
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-04 15:38:48 +01:00
|
|
|
static RD_NTSTATUS
|
|
|
|
scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
SERVER_DWORD Result = 0x00000000;
|
|
|
|
unsigned char *psize, *pend, *pStatusCode;
|
|
|
|
SERVER_DWORD addToEnd = 0;
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
2006-11-01 21:52:01 +01:00
|
|
|
unsigned char *pbeg = out->p;
|
2006-11-02 21:48:28 +01:00
|
|
|
|
|
|
|
DEBUG_SCARD(("--------------------------------\n"));
|
|
|
|
DEBUG_SCARD(("[NTHANDLE %08X]\n", handle));
|
|
|
|
DEBUG_SCARD(("[REQUEST %08X]\n", request));
|
|
|
|
DEBUG_SCARD(("[INPUT DUMP]--------------------\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump(in->p, in->end - in->p);
|
|
|
|
#endif
|
|
|
|
/* Processing request */
|
|
|
|
|
|
|
|
out_uint32_le(out, 0x00081001); /* Header lines */
|
|
|
|
out_uint32_le(out, 0xCCCCCCCC);
|
|
|
|
psize = out->p;
|
|
|
|
out_uint32_le(out, 0x00000000); /* Size of data portion */
|
|
|
|
out_uint32_le(out, 0x00000000); /* Zero bytes (may be usefull) */
|
|
|
|
pStatusCode = out->p;
|
|
|
|
out_uint32_le(out, 0x00000000); /* Status Code */
|
|
|
|
|
|
|
|
switch (request)
|
|
|
|
{
|
|
|
|
/* SCardEstablishContext */
|
|
|
|
case SC_ESTABLISH_CONTEXT:
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardEstablishContext--->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardEstablishContext(in, out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* SCardReleaseContext */
|
|
|
|
case SC_RELEASE_CONTEXT:
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardReleaseContext--->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardReleaseContext(in, out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* SCardIsValidContext */
|
|
|
|
case SC_IS_VALID_CONTEXT:
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardIsValidContext--->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardIsValidContext(in, out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* SCardListReaders */
|
|
|
|
case SC_LIST_READERS: /* SCardListReadersA */
|
|
|
|
case SC_LIST_READERS + 4: /* SCardListReadersW */
|
|
|
|
{
|
2007-01-08 13:38:34 +01:00
|
|
|
RD_BOOL wide = request != SC_LIST_READERS;
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardListReaders---> (%s)\n",
|
|
|
|
(wide) ? ("WIDE") : ("ASCII")));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardListReaders(in, out, wide);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* ScardConnect */
|
|
|
|
case SC_CONNECT: /* ScardConnectA */
|
|
|
|
case SC_CONNECT + 4: /* SCardConnectW */
|
|
|
|
{
|
2007-01-08 05:47:06 +01:00
|
|
|
RD_BOOL wide = request != SC_CONNECT;
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardConnect---> (%s)\n",
|
|
|
|
(wide) ? ("WIDE") : ("ASCII")));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardConnect(in, out, wide);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* ScardReconnect */
|
|
|
|
case SC_RECONNECT:
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardReconnect--->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardReconnect(in, out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* ScardDisconnect */
|
|
|
|
case SC_DISCONNECT:
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardDisconnect--->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardDisconnect(in, out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* ScardGetStatusChange */
|
|
|
|
case SC_GET_STATUS_CHANGE: /* SCardGetStatusChangeA */
|
|
|
|
case SC_GET_STATUS_CHANGE + 4: /* SCardGetStatusChangeW */
|
|
|
|
{
|
2007-01-08 05:47:06 +01:00
|
|
|
RD_BOOL wide = request != SC_GET_STATUS_CHANGE;
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardGetStatusChange---> (%s)\n",
|
|
|
|
(wide) ? ("WIDE") : ("ASCII")));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardGetStatusChange(in, out, wide);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* SCardCancel */
|
|
|
|
case SC_CANCEL:
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardCancel--->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardCancel(in, out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* SCardLocateCardsByATR */
|
|
|
|
case SC_LOCATE_CARDS_BY_ATR: /* SCardLocateCardsByATRA */
|
|
|
|
case SC_LOCATE_CARDS_BY_ATR + 4: /* SCardLocateCardsByATRW */
|
|
|
|
{
|
2007-01-08 05:47:06 +01:00
|
|
|
RD_BOOL wide = request != SC_LOCATE_CARDS_BY_ATR;
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardLocateCardsByATR---> (%s)\n",
|
|
|
|
(wide) ? ("WIDE") : ("ASCII")));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardLocateCardsByATR(in, out, wide);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* SCardBeginTransaction */
|
|
|
|
case SC_BEGIN_TRANSACTION:
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardBeginTransaction--->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardBeginTransaction(in, out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* SCardBeginTransaction */
|
|
|
|
case SC_END_TRANSACTION:
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardEndTransaction--->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardEndTransaction(in, out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* ScardTransmit */
|
|
|
|
case SC_TRANSMIT:
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardTransmit--->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardTransmit(in, out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* SCardControl */
|
|
|
|
case SC_CONTROL:
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardControl--->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardControl(in, out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* SCardGetAttrib */
|
|
|
|
#ifndef WITH_PCSC120
|
|
|
|
case SC_GETATTRIB:
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardGetAttrib--->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardGetAttrib(in, out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
case SC_ACCESS_STARTED_EVENT:
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardAccessStartedEvent-->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardAccessStartedEvent(in, out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SC_STATUS: /* SCardStatusA */
|
|
|
|
case SC_STATUS + 4: /* SCardStatusW */
|
|
|
|
{
|
2007-01-08 05:47:06 +01:00
|
|
|
RD_BOOL wide = request != SC_STATUS;
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardStatus---> (%s)\n",
|
|
|
|
(wide) ? ("WIDE") : ("ASCII")));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardStatus(in, out, wide);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SC_STATE: /* SCardState */
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---SCardState--->"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = (SERVER_DWORD) TS_SCardState(in, out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("<---UNSUPPORTED-FUNC--->\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
Result = 0x80100014;
|
|
|
|
out_uint8s(out, 256);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
out_uint32_le(out, 0x00000000);
|
|
|
|
#endif
|
|
|
|
/* Setting modified variables */
|
|
|
|
pend = out->p;
|
|
|
|
/* setting data size */
|
|
|
|
out->p = psize;
|
|
|
|
out_uint32_le(out, pend - psize - 16);
|
|
|
|
/* setting status code */
|
|
|
|
out->p = pStatusCode;
|
|
|
|
out_uint32_le(out, Result);
|
|
|
|
/* finish */
|
|
|
|
out->p = pend;
|
|
|
|
|
|
|
|
addToEnd = (pend - pStatusCode) % 16;
|
|
|
|
if (addToEnd < 16 && addToEnd > 0)
|
|
|
|
{
|
|
|
|
out_uint8s(out, addToEnd);
|
|
|
|
}
|
|
|
|
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
|
|
|
DEBUG_SCARD(("[OUTPUT DUMP]-------------------\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
hexdump(pbeg, (size_t) (out->p) - (size_t) pbeg);
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("--------------------------------\n"));
|
2006-11-01 21:52:01 +01:00
|
|
|
#endif
|
2007-01-04 15:38:48 +01:00
|
|
|
return RD_STATUS_SUCCESS;
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Thread functions */
|
|
|
|
|
|
|
|
static STREAM
|
2007-01-08 05:47:06 +01:00
|
|
|
duplicateStream(PMEM_HANDLE * handle, STREAM s, uint32 buffer_size, RD_BOOL isInputStream)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
STREAM d = SC_xmalloc(handle, sizeof(struct stream));
|
|
|
|
if (d != NULL)
|
|
|
|
{
|
|
|
|
if (isInputStream)
|
|
|
|
d->size = (size_t) (s->end) - (size_t) (s->data);
|
|
|
|
else if (buffer_size < s->size)
|
|
|
|
d->size = s->size;
|
|
|
|
else
|
|
|
|
d->size = buffer_size;
|
|
|
|
|
|
|
|
d->data = SC_xmalloc(handle, d->size);
|
|
|
|
|
|
|
|
d->end = (void *) ((size_t) (d->data) + (size_t) (s->end) - (size_t) (s->data));
|
|
|
|
d->p = (void *) ((size_t) (d->data) + (size_t) (s->p) - (size_t) (s->data));
|
|
|
|
d->iso_hdr =
|
|
|
|
(void *) ((size_t) (d->data) + (size_t) (s->iso_hdr) - (size_t) (s->data));
|
|
|
|
d->mcs_hdr =
|
|
|
|
(void *) ((size_t) (d->data) + (size_t) (s->mcs_hdr) - (size_t) (s->data));
|
|
|
|
d->sec_hdr =
|
|
|
|
(void *) ((size_t) (d->data) + (size_t) (s->sec_hdr) - (size_t) (s->data));
|
|
|
|
d->sec_hdr =
|
|
|
|
(void *) ((size_t) (d->data) + (size_t) (s->sec_hdr) - (size_t) (s->data));
|
|
|
|
d->rdp_hdr =
|
|
|
|
(void *) ((size_t) (d->data) + (size_t) (s->rdp_hdr) - (size_t) (s->data));
|
|
|
|
d->channel_hdr =
|
|
|
|
(void *) ((size_t) (d->data) + (size_t) (s->channel_hdr) -
|
|
|
|
(size_t) (s->data));
|
|
|
|
if (isInputStream)
|
|
|
|
memcpy(d->data, s->data, (size_t) (s->end) - (size_t) (s->data));
|
|
|
|
else
|
|
|
|
memcpy(d->data, s->data, (size_t) (s->p) - (size_t) (s->data));
|
|
|
|
}
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
freeStream(PMEM_HANDLE * handle, STREAM s)
|
|
|
|
{
|
|
|
|
if (s != NULL)
|
|
|
|
{
|
|
|
|
if (s->data != NULL)
|
|
|
|
SC_xfree(handle, s->data);
|
|
|
|
SC_xfree(handle, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static PSCThreadData
|
2007-01-04 15:38:48 +01:00
|
|
|
SC_addToQueue(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
PMEM_HANDLE lcHandle = NULL;
|
|
|
|
PSCThreadData data = SC_xmalloc(&lcHandle, sizeof(TSCThreadData));
|
|
|
|
|
|
|
|
if (!data)
|
|
|
|
return NULL;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
data->memHandle = lcHandle;
|
|
|
|
data->device = curDevice;
|
|
|
|
data->id = curId;
|
|
|
|
data->handle = handle;
|
|
|
|
data->request = request;
|
|
|
|
data->in = duplicateStream(&(data->memHandle), in, 0, SC_TRUE);
|
|
|
|
if (data->in == NULL)
|
|
|
|
{
|
|
|
|
SC_xfreeallmemory(&(data->memHandle));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
data->out =
|
|
|
|
duplicateStream(&(data->memHandle), out, OUT_STREAM_SIZE + curBytesOut,
|
|
|
|
SC_FALSE);
|
|
|
|
if (data->out == NULL)
|
|
|
|
{
|
|
|
|
SC_xfreeallmemory(&(data->memHandle));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
data->next = NULL;
|
|
|
|
|
|
|
|
pthread_mutex_lock(&queueAccess);
|
|
|
|
|
|
|
|
if (queueLast)
|
|
|
|
queueLast->next = data;
|
|
|
|
queueLast = data;
|
|
|
|
if (!queueFirst)
|
|
|
|
queueFirst = data;
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&queueEmpty);
|
|
|
|
pthread_mutex_unlock(&queueAccess);
|
|
|
|
}
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
SC_destroyThreadData(PSCThreadData data)
|
|
|
|
{
|
|
|
|
if (data)
|
|
|
|
{
|
|
|
|
PMEM_HANDLE handle = data->memHandle;
|
|
|
|
SC_xfreeallmemory(&handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static PSCThreadData
|
|
|
|
SC_getNextInQueue()
|
|
|
|
{
|
|
|
|
PSCThreadData Result = NULL;
|
|
|
|
pthread_mutex_lock(&queueAccess);
|
|
|
|
if (queueFirst != NULL)
|
|
|
|
{
|
|
|
|
Result = queueFirst;
|
|
|
|
queueFirst = queueFirst->next;
|
|
|
|
if (!queueFirst)
|
|
|
|
{
|
|
|
|
queueLast = NULL;
|
|
|
|
pthread_mutex_trylock(&queueEmpty);
|
|
|
|
}
|
|
|
|
Result->next = NULL;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&queueAccess);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
SC_deviceControl(PSCThreadData data)
|
|
|
|
{
|
|
|
|
size_t buffer_len = 0;
|
|
|
|
scard_device_control(data->handle, data->request, data->in, data->out);
|
|
|
|
buffer_len = (size_t) data->out->p - (size_t) data->out->data;
|
|
|
|
rdpdr_send_completion(data->device, data->id, 0, buffer_len, data->out->data, buffer_len);
|
|
|
|
SC_destroyThreadData(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void *
|
|
|
|
thread_function(PThreadListElement listElement)
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
2006-11-01 21:52:01 +01:00
|
|
|
long sTime = 0;
|
|
|
|
#endif
|
|
|
|
if ((listElement != NULL) && (listElement->data != NULL))
|
|
|
|
{
|
|
|
|
while (1)
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
#ifdef WITH_DEBUG_SCARD
|
2006-11-01 21:52:01 +01:00
|
|
|
sTime = time(NULL);
|
|
|
|
#endif
|
|
|
|
pthread_mutex_lock(&listElement->nodata);
|
|
|
|
SC_deviceControl(listElement->data);
|
|
|
|
listElement->data = NULL;
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[HANDLING TIME %d]\n", (int) (time(NULL) - sTime)));
|
2006-11-01 21:52:01 +01:00
|
|
|
pthread_mutex_unlock(&listElement->busy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pthread_exit(NULL);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
SC_handleRequest(PSCThreadData data)
|
|
|
|
{
|
|
|
|
int Result = 0;
|
|
|
|
PThreadListElement cur = threadList, last = threadList;
|
|
|
|
|
2006-11-02 21:48:28 +01:00
|
|
|
DEBUG_SCARD(("[THREAD COUNT %d]\n", threadCount));
|
2006-11-01 21:52:01 +01:00
|
|
|
|
|
|
|
while (cur)
|
|
|
|
{
|
|
|
|
if (0 == pthread_mutex_trylock(&cur->busy))
|
|
|
|
{
|
|
|
|
cur->data = data;
|
|
|
|
pthread_mutex_unlock(&cur->nodata);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
last = cur;
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cur = SC_xmalloc(&threadListHandle, sizeof(TThreadListElement));
|
|
|
|
if (!cur)
|
|
|
|
return;
|
|
|
|
|
|
|
|
threadCount++;
|
|
|
|
|
|
|
|
cur->next = NULL;
|
|
|
|
pthread_mutex_init(&cur->busy, NULL);
|
|
|
|
pthread_mutex_init(&cur->nodata, NULL);
|
|
|
|
pthread_mutex_trylock(&cur->busy);
|
|
|
|
cur->data = data;
|
|
|
|
pthread_mutex_unlock(&cur->nodata);
|
|
|
|
|
|
|
|
Result = pthread_create(&cur->thread, NULL, (void *(*)(void *)) thread_function, cur);
|
|
|
|
if (0 != Result)
|
|
|
|
{
|
2006-11-02 21:48:28 +01:00
|
|
|
error("[THREAD CREATE ERROR 0x%.8x]\n", Result);
|
2006-11-01 21:52:01 +01:00
|
|
|
SC_xfree(&threadListHandle, cur);
|
|
|
|
SC_destroyThreadData(data);
|
|
|
|
data = NULL;
|
|
|
|
}
|
|
|
|
else if (last)
|
|
|
|
last->next = cur;
|
|
|
|
else
|
|
|
|
threadList = cur;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
|
|
|
queue_handler_function(void *data)
|
|
|
|
{
|
|
|
|
PSCThreadData cur_data = NULL;
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
cur_data = SC_getNextInQueue();
|
|
|
|
if (cur_data != NULL)
|
|
|
|
{
|
|
|
|
switch (cur_data->request)
|
|
|
|
{
|
|
|
|
case SC_ESTABLISH_CONTEXT:
|
|
|
|
case SC_RELEASE_CONTEXT:
|
|
|
|
{
|
|
|
|
SC_deviceControl(cur_data);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
SC_handleRequest(cur_data);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cur_data = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pthread_mutex_lock(&queueEmpty);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-01-04 15:38:48 +01:00
|
|
|
static RD_NTSTATUS
|
|
|
|
thread_wrapper(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
|
|
|
if (SC_addToQueue(handle, request, in, out))
|
2007-01-04 15:38:48 +01:00
|
|
|
return RD_STATUS_PENDING | 0xC0000000;
|
2006-11-01 21:52:01 +01:00
|
|
|
else
|
2007-01-04 15:38:48 +01:00
|
|
|
return RD_STATUS_NO_SUCH_FILE;
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEVICE_FNS scard_fns = {
|
|
|
|
scard_create,
|
|
|
|
scard_close,
|
|
|
|
scard_read,
|
|
|
|
scard_write,
|
|
|
|
thread_wrapper
|
|
|
|
};
|
|
|
|
#endif /* MAKE_PROTO */
|
|
|
|
|
|
|
|
void
|
2006-11-04 00:51:35 +01:00
|
|
|
scard_lock(int lock)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
2006-11-04 00:51:35 +01:00
|
|
|
if (!scard_mutex)
|
2006-11-01 21:52:01 +01:00
|
|
|
{
|
2006-11-04 18:33:15 +01:00
|
|
|
int i;
|
|
|
|
|
2006-11-04 00:51:35 +01:00
|
|
|
scard_mutex =
|
|
|
|
(pthread_mutex_t **) xmalloc(sizeof(pthread_mutex_t *) * SCARD_LOCK_LAST);
|
2006-11-04 18:33:15 +01:00
|
|
|
|
|
|
|
for (i = 0; i < SCARD_LOCK_LAST; i++)
|
|
|
|
{
|
|
|
|
scard_mutex[i] = NULL;
|
|
|
|
}
|
2006-11-01 21:52:01 +01:00
|
|
|
}
|
|
|
|
|
2006-11-04 00:51:35 +01:00
|
|
|
if (!scard_mutex[lock])
|
2006-11-03 20:56:42 +01:00
|
|
|
{
|
2006-11-04 00:51:35 +01:00
|
|
|
scard_mutex[lock] = (pthread_mutex_t *) xmalloc(sizeof(pthread_mutex_t));
|
|
|
|
pthread_mutex_init(scard_mutex[lock], NULL);
|
2006-11-03 20:56:42 +01:00
|
|
|
}
|
|
|
|
|
2006-11-04 00:51:35 +01:00
|
|
|
pthread_mutex_lock(scard_mutex[lock]);
|
2006-11-03 20:56:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-11-04 00:51:35 +01:00
|
|
|
scard_unlock(int lock)
|
2006-11-03 20:56:42 +01:00
|
|
|
{
|
2006-11-04 00:51:35 +01:00
|
|
|
pthread_mutex_unlock(scard_mutex[lock]);
|
2006-11-03 20:56:42 +01:00
|
|
|
}
|
|
|
|
|
2006-11-01 21:52:01 +01:00
|
|
|
STREAM
|
|
|
|
scard_tcp_init(void)
|
|
|
|
{
|
|
|
|
STREAM result = NULL;
|
|
|
|
|
|
|
|
result = &out[cur_stream_id];
|
|
|
|
cur_stream_id = (cur_stream_id + 1) % STREAM_COUNT;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
scard_tcp_connect(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < STREAM_COUNT; i++)
|
|
|
|
{
|
|
|
|
out[i].size = 4096;
|
|
|
|
out[i].data = (uint8 *) xmalloc(out[i].size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
scard_tcp_reset_state(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct stream *p;
|
|
|
|
|
|
|
|
for (i = 0, p = out; i < STREAM_COUNT; i++, p++)
|
|
|
|
{
|
|
|
|
if (p->data != NULL)
|
|
|
|
xfree(p->data);
|
|
|
|
p->p = NULL;
|
|
|
|
p->end = NULL;
|
|
|
|
p->data = NULL;
|
|
|
|
p->size = 0;
|
|
|
|
p->iso_hdr = NULL;
|
|
|
|
p->mcs_hdr = NULL;
|
|
|
|
p->sec_hdr = NULL;
|
|
|
|
p->rdp_hdr = NULL;
|
|
|
|
p->channel_hdr = NULL;
|
|
|
|
}
|
|
|
|
}
|