This is part of the series: "OS X Yosemite and smart cards: known bugs".
It is a really stupid bug and very easy to fix for Apple.
Apple bug report #19306215 "PC/SC SCardStatus returns SCARD_E_INSUFFICIENT_BUFFER". Closed by Apple, 9th January 2015, as a duplicated of #18890042.
If I uncomment the line: len += 1; I get:
Note that the reader length returned by the first
Note that the length returned by the first
SCardStatus returns SCARD_E_INSUFFICIENT_BUFFER
SCardStatus() does not correctly report the reader name length. The terminating NUL character of the reader name is not counted. So a second call toSCardStatus()
using the size returned by the first SCardStatus()
call will fail with 0x80100008
(that is SCARD_E_INSUFFICIENT_BUFFER
).It is a really stupid bug and very easy to fix for Apple.
See also
"Problem with SCardStatus on MAC OS X 10.10 (Yosemite)" at https://smartcardservices.macosforge.org/trac/ticket/140.Apple bug report #19306215 "PC/SC SCardStatus returns SCARD_E_INSUFFICIENT_BUFFER". Closed by Apple, 9th January 2015, as a duplicated of #18890042.
Sample code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __APPLE__
#include <PCSC/winscard.h>
#include <PCSC/wintypes.h>
#else
#include <winscard.h>
#endif
int main(int argc, const char * argv[]) {
SCARDCONTEXT hContext;
LPSTR mszReaders;
DWORD err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
if (err != SCARD_S_SUCCESS) {
printf("ScardEstablishedContext: 0x%08x\n",err);
return -1;
}
DWORD cchReaders = 0;
err = SCardListReaders(hContext, "SCard$AllReaders", NULL, &cchReaders);
if (err != 0) {
printf("ScardListReaders: 0x%08x\n",err);
return -1;
}
mszReaders = calloc(cchReaders, sizeof(char));
if (!mszReaders) {
printf("calloc\n");
return -1;
}
err = SCardListReaders(hContext,"SCard$AllReaders", mszReaders, &cchReaders);
if (err != SCARD_S_SUCCESS) {
printf("ScardListReaders: 0x%08x\n",err);
return -1;
}
printf("Reader: %s\n", mszReaders);
SCARDHANDLE hCard;
DWORD dwActiveProtocol;
err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
if (err != SCARD_S_SUCCESS) {
printf("ScardConnect: 0x%08x\n",err);
return -1;
}
/* 1st SCardStatus call to get the reader name length */
char name[100];
DWORD len;
err = SCardStatus(hCard, NULL, &len, NULL, NULL, NULL, NULL);
if (err != SCARD_S_SUCCESS) {
printf("SCardStatus: 0x%08x\n",err);
return -1;
}
printf("reader name length: %d\n", len);
//len += 1;
/* 2nd SCardStatus call to get the reader name value */
err = SCardStatus(hCard, name, &len, NULL, NULL, NULL, NULL);
if (err != SCARD_S_SUCCESS) {
printf("SCardStatus: 0x%08x\n",err);
return -1;
}
printf("Reader name: %s (%ld)\n", name, strlen(name));
SCardDisconnect(hCard, SCARD_LEAVE_CARD);
SCardReleaseContext(hContext);
return 0;
}
Result (on Yosemite)
$ CFLAGS="-framework PCSC" make main
cc -framework PCSC main.c -o main
$ ./main
Reader: Gemalto PC Twin Reader
reader name length: 22
SCardStatus: 0x80100008
If I uncomment the line: len += 1; I get:
$ ./main
Reader: Gemalto PC Twin Reader
reader name length: 22
Reader name: Gemalto PC Twin Reader (22)
Note that the reader length returned by the first
SCardStatus()
call is identical to the value returned by strlen(name)
. And strlen()
does NOT includes the terminating NUL character.Expected result (on Debian)
$ CFLAGS=`pkg-config --cflags libpcsclite` LDFLAGS=`pkg-config --libs libpcsclite` make main
cc -pthread -I/usr/include/PCSC -lpcsclite main.c -o main
$ ./main
Reader: Gemalto PC Twin Reader 00 00
reader length: 29
Reader name: Gemalto PC Twin Reader 00 00 (28)
Note that the length returned by the first
SCardStatus()
call is strlen(name) + 1
.Known workaround
Add 1 to the reader length returned bySCardStatus()
.
ConversionConversion EmoticonEmoticon