channels/smartcard: fix reader name aliasing
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Tue, 15 Apr 2014 17:49:52 +0000 (13:49 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Tue, 15 Apr 2014 17:49:52 +0000 (13:49 -0400)
channels/smartcard/client/smartcard_operations.c
winpr/libwinpr/smartcard/smartcard_pcsc.c

index cb66727..4d5cf82 100644 (file)
@@ -145,32 +145,6 @@ const char* smartcard_get_ioctl_string(UINT32 ioControlCode, BOOL funcName)
        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)
 {
        UINT32 status;
index eac1676..115a7ec 100644 (file)
@@ -26,6 +26,7 @@
 #include <ctype.h>
 
 #include <winpr/crt.h>
+#include <winpr/print.h>
 #include <winpr/synch.h>
 #include <winpr/library.h>
 #include <winpr/smartcard.h>
@@ -311,23 +312,38 @@ BOOL PCSC_AddReaderNameAlias(char* namePCSC, char* nameWinSCard)
        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)
 {
        int slot;
        int index;
        int size;
        int length;
+       int ctoken;
+       int ntokens;
+       char *p, *q;
+       char* tokens[64][2];
        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:
-        *
         * name [interface] (serial) index slot
+        *
         * Athena IDProtect Key v2 [Main Interface] 00 00
         *
         * name:      Athena IDProtect Key v2
@@ -336,6 +352,22 @@ char* PCSC_ConvertReaderNameToWinSCard(const char* name)
         * index:     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 index 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)
                return NULL;
 
-       na1 = (char*) name;
-       na2 = (char*) &name[length - 7];
+       ntokens = 0;
+       p = q = (char*) name;
+
+       while (*p)
+       {
+               if (*p == ' ')
+               {
+                       tokens[ntokens][0] = q;
+                       tokens[ntokens][1] = p;
+                       q = p + 1;
+                       ntokens++;
+               }
+
+               p++;
+       }
 
-       if1 = strchr(name, '[');
+       tokens[ntokens][0] = q;
+       tokens[ntokens][1] = p;
+       ntokens++;
 
-       if (if1)
-               if2 = strchr(if1 + 1, ']');
+       if (ntokens < 2)
+               return NULL;
 
-       se1 = strchr(name, '(');
+       slot = index = -1;
+       ctoken = ntokens - 1;
 
-       if (se1)
-               se2 = strchr(se1 + 1, ')');
+       slot = PCSC_AtoiWithLength(tokens[ctoken][0], (int) (tokens[ctoken][1] - tokens[ctoken][0]));
+       ctoken--;
 
-       in1 = (char*) &name[length - 5];
-       in2 = (char*) &name[length - 4];
+       index = PCSC_AtoiWithLength(tokens[ctoken][0], (int) (tokens[ctoken][1] - tokens[ctoken][0]));
+       ctoken--;
 
-       sl1 = (char*) &name[length - 2];
-       sl2 = (char*) &name[length - 1];
+       if (index < 0)
+       {
+               slot = -1;
+               index = slot;
+               ctoken++;
+       }
 
-       if (!(if1 && if2))
+       if ((index < 0) || (slot < 0))
                return NULL;
 
-       if (!(isdigit(*in1) && isdigit(*in2)))
+       if (*(tokens[ctoken][1] - 1) == ')')
+       {
+               while ((*(tokens[ctoken][0]) != '(') && (ctoken > 0))
+                       ctoken--;
+       }
+
+       if (ctoken < 1)
                return NULL;
 
-       if (!(isdigit(*sl1) && isdigit(*sl2)))
+       if (*(tokens[ctoken][1] - 1) == ']')
+       {
+               while ((*(tokens[ctoken][0]) != '[') && (ctoken > 0))
+                       ctoken--;
+       }
+
+       if (ctoken < 1)
                return NULL;
 
-       na2 = if1 - 1;
+       ctoken--;
 
-       while ((*na2 == ' ') && (na2 > na1))
-               na2--;
-       na2++;
+       if (ctoken < 1)
+               return NULL;
 
-       index = ((*in1 - 0x30) * 10) + (*in2 - 0x30);
-       slot = ((*sl1 - 0x30) * 10) + (*sl2 - 0x30);
+       p = tokens[0][0];
+       q = tokens[ctoken][1];
 
-       length = (na2 - na1);
+       length = (q - p);
        size = length + 16;
 
        nameWinSCard = (char*) malloc(size);
@@ -391,12 +454,22 @@ char* PCSC_ConvertReaderNameToWinSCard(const char* name)
        if (!nameWinSCard)
                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;
 }
 
-char* PCSC_ConvertReaderNamesToWinSCard(const char* names)
+char* PCSC_ConvertReaderNamesToWinSCard(const char* names, LPDWORD pcchReaders)
 {
        char *p, *q;
        int plen, qlen;
@@ -445,22 +518,23 @@ char* PCSC_ConvertReaderNamesToWinSCard(const char* names)
                        CopyMemory(q, p, qlen);
                }
 
-               p += plen + 1;
-
                q += qlen;
                *q = '\0';
                q++;
 
+               p += plen + 1;
                plen = strlen(p);
        }
 
        *q = '\0';
        q++;
 
+       *pcchReaders = (DWORD) (q - namesWinSCard);
+
        return namesWinSCard;
 }
 
-char* PCSC_ConvertReaderNamesFromWinSCard(const char* names)
+char* PCSC_ConvertReaderNamesToPCSC(const char* names, LPDWORD pcchReaders)
 {
        char *p, *q;
        int plen, qlen;
@@ -513,33 +587,9 @@ char* PCSC_ConvertReaderNamesFromWinSCard(const char* names)
        *q = '\0';
        q++;
 
-       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;
-}
+       *pcchReaders = (DWORD) (q - namesPCSC);
 
-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;
+       return namesPCSC;
 }
 
 void PCSC_AddCardHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard)
@@ -700,6 +750,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext,
 
        if (g_PCSC.pfnSCardListReaders)
        {
+               char* mszReadersWinSCard = NULL;
                BOOL pcchReadersWrapAlloc = FALSE;
                LPSTR* pMszReaders = (LPSTR*) mszReaders;
 
@@ -735,6 +786,19 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext,
                }
 
                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;
@@ -749,26 +813,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersA(SCARDCONTEXT hContext,
 
        if (g_PCSC.pfnSCardListReaders)
        {
-               char* mszReadersWinSCard = NULL;
-               LPSTR* pMszReaders = (LPSTR*) mszReaders;
-
                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);
@@ -787,7 +832,6 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext,
        {
                LPSTR mszGroupsA = NULL;
                LPSTR mszReadersA = NULL;
-               char* mszReadersWinSCard = NULL;
                LPSTR* pMszReadersA = &mszReadersA;
 
                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);
 
-               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);
                        PCSC_AddMemoryBlock(hContext, mszReaders);
 
                        PCSC_SCardFreeMemory_Internal(hContext, *pMszReadersA);
                }
 
-               status = PCSC_MapErrorCodeToWinSCard(status);
-
                free(mszGroupsA);
        }
 
@@ -1467,14 +1498,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard,
 
                status = PCSC_MapErrorCodeToWinSCard(status);
 
-               mszReaderNamesPCSC = PCSC_ConvertReaderNamesToWinSCard(*pMszReaderNames);
+               mszReaderNamesPCSC = PCSC_ConvertReaderNamesToPCSC(*pMszReaderNames, pcchReaderLen);
 
                if (mszReaderNamesPCSC)
                {
                        PCSC_SCardFreeMemory_Internal(hContext, *pMszReaderNames);
 
                        *pMszReaderNames = mszReaderNamesPCSC;
-                       *pcchReaderLen = PCSC_MultiStringLengthA(*pMszReaderNames) + 2;
                        PCSC_AddMemoryBlock(hContext, *pMszReaderNames);
                }