channels/smartcard: fix reader name aliasing

This commit is contained in:
Marc-André Moreau 2014-04-15 13:49:52 -04:00
parent 09a540b40b
commit 38d05b48a0
2 changed files with 128 additions and 124 deletions

View File

@ -145,32 +145,6 @@ const char* smartcard_get_ioctl_string(UINT32 ioControlCode, BOOL funcName)
return funcName ? "SCardUnknown" : "SCARD_IOCTL_UNKNOWN"; return funcName ? "SCardUnknown" : "SCARD_IOCTL_UNKNOWN";
} }
size_t smartcard_multi_string_length_a(const char* msz)
{
char* p = (char*) msz;
if (!p)
return 0;
while ((p[0] != 0) && (p[1] != 0))
p++;
return (p - msz) + 1;
}
size_t smartcard_multi_string_length_w(const WCHAR* msz)
{
WCHAR* p = (WCHAR*) msz;
if (!p)
return 0;
while ((p[0] != 0) && (p[1] != 0))
p++;
return (p - msz) + 1;
}
static UINT32 smartcard_EstablishContext(SMARTCARD_DEVICE* smartcard, IRP* irp) static UINT32 smartcard_EstablishContext(SMARTCARD_DEVICE* smartcard, IRP* irp)
{ {
UINT32 status; UINT32 status;

View File

@ -26,6 +26,7 @@
#include <ctype.h> #include <ctype.h>
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/synch.h> #include <winpr/synch.h>
#include <winpr/library.h> #include <winpr/library.h>
#include <winpr/smartcard.h> #include <winpr/smartcard.h>
@ -311,23 +312,38 @@ BOOL PCSC_AddReaderNameAlias(char* namePCSC, char* nameWinSCard)
return TRUE; return TRUE;
} }
static int PCSC_AtoiWithLength(const char* str, int length)
{
int index;
int value = 0;
for (index = 0; index < length; ++index)
{
if (!isdigit(str[index]))
return -1;
value = value * 10 + (str[index] - '0');
}
return value;
}
char* PCSC_ConvertReaderNameToWinSCard(const char* name) char* PCSC_ConvertReaderNameToWinSCard(const char* name)
{ {
int slot; int slot;
int index; int index;
int size; int size;
int length; int length;
int ctoken;
int ntokens;
char *p, *q;
char* tokens[64][2];
char* nameWinSCard; char* nameWinSCard;
char *na1, *na2 = NULL;
char *if1, *if2 = NULL;
char *se1, *se2 = NULL;
char *in1, *in2 = NULL;
char *sl1, *sl2 = NULL;
/** /**
* pcsc-lite reader name format: * pcsc-lite reader name format:
*
* name [interface] (serial) index slot * name [interface] (serial) index slot
*
* Athena IDProtect Key v2 [Main Interface] 00 00 * Athena IDProtect Key v2 [Main Interface] 00 00
* *
* name: Athena IDProtect Key v2 * name: Athena IDProtect Key v2
@ -336,6 +352,22 @@ char* PCSC_ConvertReaderNameToWinSCard(const char* name)
* index: 00 * index: 00
* slot: 00 * slot: 00
* *
* Athena ASE IIIe 0
*
* name: Athena ASE IIIe
* interface: N/A
* serial: N/A
* index: 0
* slot: 0
*
* Athena ASE IIIe [CCID Bulk Interface] 00 00
*
* name: Athena ASE IIIe
* interface: CCID Bulk Interface
* serial: N/A
* index: 00
* slot: 00
*
* the serial component is optional * the serial component is optional
* the index is a two digit zero-padded integer * the index is a two digit zero-padded integer
* the slot is a two digit zero-padded integer * the slot is a two digit zero-padded integer
@ -346,44 +378,75 @@ char* PCSC_ConvertReaderNameToWinSCard(const char* name)
if (length < 10) if (length < 10)
return NULL; return NULL;
na1 = (char*) name; ntokens = 0;
na2 = (char*) &name[length - 7]; p = q = (char*) name;
if1 = strchr(name, '['); while (*p)
{
if (*p == ' ')
{
tokens[ntokens][0] = q;
tokens[ntokens][1] = p;
q = p + 1;
ntokens++;
}
if (if1) p++;
if2 = strchr(if1 + 1, ']'); }
se1 = strchr(name, '('); tokens[ntokens][0] = q;
tokens[ntokens][1] = p;
ntokens++;
if (se1) if (ntokens < 2)
se2 = strchr(se1 + 1, ')');
in1 = (char*) &name[length - 5];
in2 = (char*) &name[length - 4];
sl1 = (char*) &name[length - 2];
sl2 = (char*) &name[length - 1];
if (!(if1 && if2))
return NULL; return NULL;
if (!(isdigit(*in1) && isdigit(*in2))) slot = index = -1;
ctoken = ntokens - 1;
slot = PCSC_AtoiWithLength(tokens[ctoken][0], (int) (tokens[ctoken][1] - tokens[ctoken][0]));
ctoken--;
index = PCSC_AtoiWithLength(tokens[ctoken][0], (int) (tokens[ctoken][1] - tokens[ctoken][0]));
ctoken--;
if (index < 0)
{
slot = -1;
index = slot;
ctoken++;
}
if ((index < 0) || (slot < 0))
return NULL; return NULL;
if (!(isdigit(*sl1) && isdigit(*sl2))) if (*(tokens[ctoken][1] - 1) == ')')
{
while ((*(tokens[ctoken][0]) != '(') && (ctoken > 0))
ctoken--;
}
if (ctoken < 1)
return NULL; return NULL;
na2 = if1 - 1; if (*(tokens[ctoken][1] - 1) == ']')
{
while ((*(tokens[ctoken][0]) != '[') && (ctoken > 0))
ctoken--;
}
while ((*na2 == ' ') && (na2 > na1)) if (ctoken < 1)
na2--; return NULL;
na2++;
index = ((*in1 - 0x30) * 10) + (*in2 - 0x30); ctoken--;
slot = ((*sl1 - 0x30) * 10) + (*sl2 - 0x30);
length = (na2 - na1); if (ctoken < 1)
return NULL;
p = tokens[0][0];
q = tokens[ctoken][1];
length = (q - p);
size = length + 16; size = length + 16;
nameWinSCard = (char*) malloc(size); nameWinSCard = (char*) malloc(size);
@ -391,12 +454,22 @@ char* PCSC_ConvertReaderNameToWinSCard(const char* name)
if (!nameWinSCard) if (!nameWinSCard)
return NULL; return NULL;
sprintf_s(nameWinSCard, size, "%.*s %d", length, na1, index); /**
* pcsc-lite appears to use an index number based on all readers,
* while WinSCard uses an index number based on readers of the same name.
* Force an index number of 0 for now, fix later.
*/
index = 0;
sprintf_s(nameWinSCard, size, "%.*s %d", length, p, index);
printf("Smart Card Reader Name Alias: %s -> %s\n", p, nameWinSCard);
return nameWinSCard; return nameWinSCard;
} }
char* PCSC_ConvertReaderNamesToWinSCard(const char* names) char* PCSC_ConvertReaderNamesToWinSCard(const char* names, LPDWORD pcchReaders)
{ {
char *p, *q; char *p, *q;
int plen, qlen; int plen, qlen;
@ -445,22 +518,23 @@ char* PCSC_ConvertReaderNamesToWinSCard(const char* names)
CopyMemory(q, p, qlen); CopyMemory(q, p, qlen);
} }
p += plen + 1;
q += qlen; q += qlen;
*q = '\0'; *q = '\0';
q++; q++;
p += plen + 1;
plen = strlen(p); plen = strlen(p);
} }
*q = '\0'; *q = '\0';
q++; q++;
*pcchReaders = (DWORD) (q - namesWinSCard);
return namesWinSCard; return namesWinSCard;
} }
char* PCSC_ConvertReaderNamesFromWinSCard(const char* names) char* PCSC_ConvertReaderNamesToPCSC(const char* names, LPDWORD pcchReaders)
{ {
char *p, *q; char *p, *q;
int plen, qlen; int plen, qlen;
@ -513,35 +587,11 @@ char* PCSC_ConvertReaderNamesFromWinSCard(const char* names)
*q = '\0'; *q = '\0';
q++; q++;
*pcchReaders = (DWORD) (q - namesPCSC);
return namesPCSC; return namesPCSC;
} }
size_t PCSC_MultiStringLengthA(const char* msz)
{
char* p = (char*) msz;
if (!p)
return 0;
while ((p[0] != 0) && (p[1] != 0))
p++;
return (p - msz) + 1;
}
size_t PCSC_MultiStringLengthW(const WCHAR* msz)
{
WCHAR* p = (WCHAR*) msz;
if (!p)
return 0;
while ((p[0] != 0) && (p[1] != 0))
p++;
return (p - msz) + 1;
}
void PCSC_AddCardHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard) void PCSC_AddCardHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard)
{ {
if (!g_CardHandles) if (!g_CardHandles)
@ -700,6 +750,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext,
if (g_PCSC.pfnSCardListReaders) if (g_PCSC.pfnSCardListReaders)
{ {
char* mszReadersWinSCard = NULL;
BOOL pcchReadersWrapAlloc = FALSE; BOOL pcchReadersWrapAlloc = FALSE;
LPSTR* pMszReaders = (LPSTR*) mszReaders; LPSTR* pMszReaders = (LPSTR*) mszReaders;
@ -735,6 +786,19 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext,
} }
status = PCSC_MapErrorCodeToWinSCard(status); status = PCSC_MapErrorCodeToWinSCard(status);
if (status == SCARD_S_SUCCESS)
{
mszReadersWinSCard = PCSC_ConvertReaderNamesToWinSCard(*pMszReaders, pcchReaders);
if (mszReadersWinSCard)
{
PCSC_SCardFreeMemory_Internal(hContext, *pMszReaders);
*pMszReaders = mszReadersWinSCard;
PCSC_AddMemoryBlock(hContext, *pMszReaders);
}
}
} }
return status; return status;
@ -749,26 +813,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersA(SCARDCONTEXT hContext,
if (g_PCSC.pfnSCardListReaders) if (g_PCSC.pfnSCardListReaders)
{ {
char* mszReadersWinSCard = NULL;
LPSTR* pMszReaders = (LPSTR*) mszReaders;
status = PCSC_SCardListReaders_Internal(hContext, mszGroups, mszReaders, pcchReaders); status = PCSC_SCardListReaders_Internal(hContext, mszGroups, mszReaders, pcchReaders);
if (!status)
{
mszReadersWinSCard = PCSC_ConvertReaderNamesToWinSCard(*pMszReaders);
if (mszReadersWinSCard)
{
PCSC_SCardFreeMemory_Internal(hContext, *pMszReaders);
*pMszReaders = mszReadersWinSCard;
*pcchReaders = PCSC_MultiStringLengthA(*pMszReaders) + 2;
PCSC_AddMemoryBlock(hContext, *pMszReaders);
}
}
status = PCSC_MapErrorCodeToWinSCard(status);
} }
PCSC_UnlockCardContext(hContext); PCSC_UnlockCardContext(hContext);
@ -787,7 +832,6 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext,
{ {
LPSTR mszGroupsA = NULL; LPSTR mszGroupsA = NULL;
LPSTR mszReadersA = NULL; LPSTR mszReadersA = NULL;
char* mszReadersWinSCard = NULL;
LPSTR* pMszReadersA = &mszReadersA; LPSTR* pMszReadersA = &mszReadersA;
mszGroups = NULL; /* mszGroups is not supported by pcsc-lite */ mszGroups = NULL; /* mszGroups is not supported by pcsc-lite */
@ -797,27 +841,14 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext,
status = PCSC_SCardListReaders_Internal(hContext, mszGroupsA, (LPTSTR) &mszReadersA, pcchReaders); status = PCSC_SCardListReaders_Internal(hContext, mszGroupsA, (LPTSTR) &mszReadersA, pcchReaders);
if (!status) if (status == SCARD_S_SUCCESS)
{ {
mszReadersWinSCard = PCSC_ConvertReaderNamesToWinSCard(mszReadersA);
if (mszReadersWinSCard)
{
PCSC_SCardFreeMemory_Internal(hContext, *pMszReadersA);
*pMszReadersA = mszReadersWinSCard;
*pcchReaders = PCSC_MultiStringLengthA(*pMszReadersA) + 2;
PCSC_AddMemoryBlock(hContext, *pMszReadersA);
}
*pcchReaders = ConvertToUnicode(CP_UTF8, 0, *pMszReadersA, *pcchReaders, (WCHAR**) mszReaders, 0); *pcchReaders = ConvertToUnicode(CP_UTF8, 0, *pMszReadersA, *pcchReaders, (WCHAR**) mszReaders, 0);
PCSC_AddMemoryBlock(hContext, mszReaders); PCSC_AddMemoryBlock(hContext, mszReaders);
PCSC_SCardFreeMemory_Internal(hContext, *pMszReadersA); PCSC_SCardFreeMemory_Internal(hContext, *pMszReadersA);
} }
status = PCSC_MapErrorCodeToWinSCard(status);
free(mszGroupsA); free(mszGroupsA);
} }
@ -1467,14 +1498,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard,
status = PCSC_MapErrorCodeToWinSCard(status); status = PCSC_MapErrorCodeToWinSCard(status);
mszReaderNamesPCSC = PCSC_ConvertReaderNamesToWinSCard(*pMszReaderNames); mszReaderNamesPCSC = PCSC_ConvertReaderNamesToPCSC(*pMszReaderNames, pcchReaderLen);
if (mszReaderNamesPCSC) if (mszReaderNamesPCSC)
{ {
PCSC_SCardFreeMemory_Internal(hContext, *pMszReaderNames); PCSC_SCardFreeMemory_Internal(hContext, *pMszReaderNames);
*pMszReaderNames = mszReaderNamesPCSC; *pMszReaderNames = mszReaderNamesPCSC;
*pcchReaderLen = PCSC_MultiStringLengthA(*pMszReaderNames) + 2;
PCSC_AddMemoryBlock(hContext, *pMszReaderNames); PCSC_AddMemoryBlock(hContext, *pMszReaderNames);
} }