winscard_svc.c

Go to the documentation of this file.
00001 /*
00002  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
00003  *
00004  * Copyright (C) 2001-2004
00005  *  David Corcoran <corcoran@linuxnet.com>
00006  *  Damien Sauveron <damien.sauveron@labri.fr>
00007  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00008  *
00009  * $Id: winscard_svc.c 3267 2009-01-05 13:58:14Z rousseau $
00010  */
00011 
00022 #include "config.h"
00023 #include <time.h>
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include <stddef.h>
00027 
00028 #include "pcscd.h"
00029 #include "winscard.h"
00030 #include "debuglog.h"
00031 #include "winscard_msg.h"
00032 #include "winscard_svc.h"
00033 #include "sys_generic.h"
00034 #include "thread_generic.h"
00035 #include "readerfactory.h"
00036 
00042 static struct _psContext
00043 {
00044     uint32_t hContext;
00045     uint32_t hCard[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
00046     uint32_t dwClientID;            
00047     PCSCLITE_THREAD_T pthThread;        
00048     sharedSegmentMsg msgStruct;     
00049     int protocol_major, protocol_minor; 
00050 } psContext[PCSCLITE_MAX_APPLICATIONS_CONTEXTS];
00051 
00052 static LONG MSGCheckHandleAssociation(SCARDHANDLE, DWORD);
00053 static LONG MSGFunctionDemarshall(psharedSegmentMsg, DWORD);
00054 static LONG MSGAddContext(SCARDCONTEXT, DWORD);
00055 static LONG MSGRemoveContext(SCARDCONTEXT, DWORD);
00056 static LONG MSGAddHandle(SCARDCONTEXT, SCARDHANDLE, DWORD);
00057 static LONG MSGRemoveHandle(SCARDHANDLE, DWORD);
00058 static LONG MSGCleanupClient(DWORD);
00059 
00060 static void ContextThread(LPVOID pdwIndex);
00061 
00062 LONG ContextsInitialize(void)
00063 {
00064     memset(psContext, 0, sizeof(struct _psContext)*PCSCLITE_MAX_APPLICATIONS_CONTEXTS);
00065     return 1;
00066 }
00067 
00078 LONG CreateContextThread(uint32_t *pdwClientID)
00079 {
00080     long i;
00081     int rv;
00082 
00083     for (i = 0; i < PCSCLITE_MAX_APPLICATIONS_CONTEXTS; i++)
00084     {
00085         if (psContext[i].dwClientID == 0)
00086         {
00087             psContext[i].dwClientID = *pdwClientID;
00088             *pdwClientID = 0;
00089             break;
00090         }
00091     }
00092 
00093     if (i == PCSCLITE_MAX_APPLICATIONS_CONTEXTS)
00094     {
00095         Log2(PCSC_LOG_CRITICAL, "No more context available (max: %d)",
00096             PCSCLITE_MAX_APPLICATIONS_CONTEXTS);
00097         return SCARD_F_INTERNAL_ERROR;
00098     }
00099 
00100     rv = SYS_ThreadCreate(&psContext[i].pthThread, THREAD_ATTR_DETACHED,
00101         (PCSCLITE_THREAD_FUNCTION( )) ContextThread, (LPVOID) i);
00102     if (rv)
00103     {
00104         (void)SYS_CloseFile(psContext[i].dwClientID);
00105         psContext[i].dwClientID = 0;
00106         Log2(PCSC_LOG_CRITICAL, "SYS_ThreadCreate failed: %s", strerror(rv));
00107         return SCARD_E_NO_MEMORY;
00108     }
00109 
00110     return SCARD_S_SUCCESS;
00111 }
00112 
00113 /*
00114  * A list of local functions used to keep track of clients and their
00115  * connections
00116  */
00117 
00126 static void ContextThread(LPVOID dwIndex)
00127 {
00128     LONG rv;
00129     sharedSegmentMsg msgStruct;
00130     DWORD dwContextIndex = (DWORD)dwIndex;
00131 
00132     Log2(PCSC_LOG_DEBUG, "Thread is started: %d",
00133         psContext[dwContextIndex].dwClientID);
00134 
00135     while (1)
00136     {
00137         switch (rv = SHMProcessEventsContext(psContext[dwContextIndex].dwClientID, &msgStruct))
00138         {
00139         case 0:
00140             if (msgStruct.mtype == CMD_CLIENT_DIED)
00141             {
00142                 /*
00143                  * Clean up the dead client
00144                  */
00145                 Log2(PCSC_LOG_DEBUG, "Client die: %d",
00146                     psContext[dwContextIndex].dwClientID);
00147                 (void)MSGCleanupClient(dwContextIndex);
00148                 (void)SYS_ThreadExit((LPVOID) NULL);
00149             }
00150             break;
00151 
00152         case 1:
00153             if (msgStruct.mtype == CMD_FUNCTION)
00154             {
00155                 /*
00156                  * Command must be found
00157                  */
00158                 rv = MSGFunctionDemarshall(&msgStruct, dwContextIndex);
00159                 if (rv)
00160                 {
00161                     Log2(PCSC_LOG_DEBUG, "MSGFunctionDemarshall failed: %d",
00162                         rv);
00163                     (void)SHMClientCloseSession(psContext[dwContextIndex].dwClientID);
00164                     (void)MSGCleanupClient(dwContextIndex);
00165                     (void)SYS_ThreadExit((LPVOID) NULL);
00166                 }
00167 
00168                 /* the SCARD_TRANSMIT_EXTENDED anwser is already sent by
00169                  * MSGFunctionDemarshall */
00170                 if ((msgStruct.command != SCARD_TRANSMIT_EXTENDED)
00171                     && (msgStruct.command != SCARD_CONTROL_EXTENDED))
00172                     rv = SHMMessageSend(&msgStruct, sizeof(msgStruct),
00173                         psContext[dwContextIndex].dwClientID,
00174                         PCSCLITE_SERVER_ATTEMPTS);
00175             }
00176             else
00177                 /* pcsc-lite client/server protocol version */
00178                 if (msgStruct.mtype == CMD_VERSION)
00179                 {
00180                     version_struct *veStr;
00181                     veStr = (version_struct *) msgStruct.data;
00182 
00183                     /* get the client protocol version */
00184                     psContext[dwContextIndex].protocol_major = veStr->major;
00185                     psContext[dwContextIndex].protocol_minor = veStr->minor;
00186 
00187                     Log3(PCSC_LOG_DEBUG,
00188                         "Client is protocol version %d:%d",
00189                         veStr->major, veStr->minor);
00190 
00191                     veStr->rv = SCARD_S_SUCCESS;
00192 
00193                     /* client is newer than server */
00194                     if ((veStr->major > PROTOCOL_VERSION_MAJOR)
00195                         || (veStr->major == PROTOCOL_VERSION_MAJOR
00196                             && veStr->minor > PROTOCOL_VERSION_MINOR))
00197                     {
00198                         Log3(PCSC_LOG_CRITICAL,
00199                             "Client protocol is too new %d:%d",
00200                             veStr->major, veStr->minor);
00201                         Log3(PCSC_LOG_CRITICAL,
00202                             "Server protocol is %d:%d",
00203                             PROTOCOL_VERSION_MAJOR, PROTOCOL_VERSION_MINOR);
00204                         veStr->rv = SCARD_E_NO_SERVICE;
00205                     }
00206 
00207                     /* set the server protocol version */
00208                     veStr->major = PROTOCOL_VERSION_MAJOR;
00209                     veStr->minor = PROTOCOL_VERSION_MINOR;
00210 
00211                     /* send back the response */
00212                     rv = SHMMessageSend(&msgStruct, sizeof(msgStruct),
00213                         psContext[dwContextIndex].dwClientID,
00214                         PCSCLITE_SERVER_ATTEMPTS);
00215                 }
00216                 else
00217                     continue;
00218 
00219             break;
00220 
00221         case 2:
00222             /*
00223              * timeout in SHMProcessEventsContext(): do nothing
00224              * this is used to catch the Ctrl-C signal at some time when
00225              * nothing else happens
00226              */
00227             break;
00228 
00229         case -1:
00230             Log1(PCSC_LOG_ERROR, "Error in SHMProcessEventsContext");
00231             break;
00232 
00233         default:
00234             Log2(PCSC_LOG_ERROR,
00235                 "SHMProcessEventsContext unknown retval: %d", rv);
00236             break;
00237         }
00238     }
00239 }
00240 
00256 static LONG MSGFunctionDemarshall(psharedSegmentMsg msgStruct,
00257     DWORD dwContextIndex)
00258 {
00259     LONG rv;
00260     establish_struct *esStr;
00261     release_struct *reStr;
00262     connect_struct *coStr;
00263     reconnect_struct *rcStr;
00264     disconnect_struct *diStr;
00265     begin_struct *beStr;
00266     cancel_struct *caStr;
00267     end_struct *enStr;
00268     status_struct *stStr;
00269     transmit_struct *trStr;
00270     control_struct *ctStr;
00271     getset_struct *gsStr;
00272 
00273     SCARDCONTEXT hContext;
00274     SCARDHANDLE hCard;
00275     DWORD dwActiveProtocol;
00276 
00277     DWORD cchReaderLen;
00278     DWORD dwState;
00279     DWORD dwProtocol;
00280     DWORD cbAtrLen;
00281     DWORD cbRecvLength;
00282     DWORD dwBytesReturned;
00283     DWORD cbAttrLen;
00284 
00285     SCARD_IO_REQUEST ioSendPci;
00286     SCARD_IO_REQUEST ioRecvPci;
00287 
00288     /*
00289      * Zero out everything
00290      */
00291     rv = 0;
00292     switch (msgStruct->command)
00293     {
00294 
00295     case SCARD_ESTABLISH_CONTEXT:
00296         esStr = ((establish_struct *) msgStruct->data);
00297 
00298         hContext = esStr->phContext;
00299         esStr->rv = SCardEstablishContext(esStr->dwScope, 0, 0, &hContext);
00300         esStr->phContext = hContext;
00301 
00302         if (esStr->rv == SCARD_S_SUCCESS)
00303             esStr->rv =
00304                 MSGAddContext(esStr->phContext, dwContextIndex);
00305         break;
00306 
00307     case SCARD_RELEASE_CONTEXT:
00308         reStr = ((release_struct *) msgStruct->data);
00309         reStr->rv = SCardReleaseContext(reStr->hContext);
00310 
00311         if (reStr->rv == SCARD_S_SUCCESS)
00312             reStr->rv =
00313                 MSGRemoveContext(reStr->hContext, dwContextIndex);
00314 
00315         break;
00316 
00317     case SCARD_CONNECT:
00318         coStr = ((connect_struct *) msgStruct->data);
00319 
00320         hCard = coStr->phCard;
00321         dwActiveProtocol = coStr->pdwActiveProtocol;
00322 
00323         coStr->rv = SCardConnect(coStr->hContext, coStr->szReader,
00324             coStr->dwShareMode, coStr->dwPreferredProtocols,
00325             &hCard, &dwActiveProtocol);
00326 
00327         coStr->phCard = hCard;
00328         coStr->pdwActiveProtocol = dwActiveProtocol;
00329 
00330         if (coStr->rv == SCARD_S_SUCCESS)
00331             coStr->rv =
00332                 MSGAddHandle(coStr->hContext, coStr->phCard, dwContextIndex);
00333 
00334         break;
00335 
00336     case SCARD_RECONNECT:
00337         rcStr = ((reconnect_struct *) msgStruct->data);
00338         rv = MSGCheckHandleAssociation(rcStr->hCard, dwContextIndex);
00339         if (rv != 0) return rv;
00340 
00341         rcStr->rv = SCardReconnect(rcStr->hCard, rcStr->dwShareMode,
00342             rcStr->dwPreferredProtocols,
00343             rcStr->dwInitialization, &dwActiveProtocol);
00344         rcStr->pdwActiveProtocol = dwActiveProtocol;
00345         break;
00346 
00347     case SCARD_DISCONNECT:
00348         diStr = ((disconnect_struct *) msgStruct->data);
00349         rv = MSGCheckHandleAssociation(diStr->hCard, dwContextIndex);
00350         if (rv != 0) return rv;
00351         diStr->rv = SCardDisconnect(diStr->hCard, diStr->dwDisposition);
00352 
00353         if (diStr->rv == SCARD_S_SUCCESS)
00354             diStr->rv =
00355                 MSGRemoveHandle(diStr->hCard, dwContextIndex);
00356         break;
00357 
00358     case SCARD_BEGIN_TRANSACTION:
00359         beStr = ((begin_struct *) msgStruct->data);
00360         rv = MSGCheckHandleAssociation(beStr->hCard, dwContextIndex);
00361         if (rv != 0) return rv;
00362         beStr->rv = SCardBeginTransaction(beStr->hCard);
00363         break;
00364 
00365     case SCARD_END_TRANSACTION:
00366         enStr = ((end_struct *) msgStruct->data);
00367         rv = MSGCheckHandleAssociation(enStr->hCard, dwContextIndex);
00368         if (rv != 0) return rv;
00369         enStr->rv =
00370             SCardEndTransaction(enStr->hCard, enStr->dwDisposition);
00371         break;
00372 
00373     case SCARD_CANCEL_TRANSACTION:
00374         caStr = ((cancel_struct *) msgStruct->data);
00375         rv = MSGCheckHandleAssociation(caStr->hCard, dwContextIndex);
00376         if (rv != 0) return rv;
00377         caStr->rv = SCardCancelTransaction(caStr->hCard);
00378         break;
00379 
00380     case SCARD_STATUS:
00381         stStr = ((status_struct *) msgStruct->data);
00382         rv = MSGCheckHandleAssociation(stStr->hCard, dwContextIndex);
00383         if (rv != 0) return rv;
00384 
00385         cchReaderLen = stStr->pcchReaderLen;
00386         dwState = stStr->pdwState;
00387         dwProtocol = stStr->pdwProtocol;
00388         cbAtrLen = stStr->pcbAtrLen;
00389 
00390         /* avoids buffer overflow */
00391         if ((cchReaderLen > sizeof(stStr->mszReaderNames))
00392             || (cbAtrLen > sizeof(stStr->pbAtr)))
00393         {
00394             stStr->rv = SCARD_E_INSUFFICIENT_BUFFER ;
00395             break;
00396         }
00397 
00398         stStr->rv = SCardStatus(stStr->hCard, stStr->mszReaderNames,
00399             &cchReaderLen, &dwState,
00400             &dwProtocol, stStr->pbAtr, &cbAtrLen);
00401 
00402         stStr->pcchReaderLen = cchReaderLen;
00403         stStr->pdwState = dwState;
00404         stStr->pdwProtocol = dwProtocol;
00405         stStr->pcbAtrLen = cbAtrLen;
00406         break;
00407 
00408     case SCARD_TRANSMIT:
00409         trStr = ((transmit_struct *) msgStruct->data);
00410         rv = MSGCheckHandleAssociation(trStr->hCard, dwContextIndex);
00411         if (rv != 0) return rv;
00412 
00413         /* avoids buffer overflow */
00414         if ((trStr->pcbRecvLength > sizeof(trStr->pbRecvBuffer))
00415             || (trStr->cbSendLength > sizeof(trStr->pbSendBuffer)))
00416         {
00417             trStr->rv = SCARD_E_INSUFFICIENT_BUFFER ;
00418             break;
00419         }
00420 
00421         ioSendPci.dwProtocol = trStr->pioSendPciProtocol;
00422         ioSendPci.cbPciLength = trStr->pioSendPciLength;
00423         ioRecvPci.dwProtocol = trStr->pioRecvPciProtocol;
00424         ioRecvPci.cbPciLength = trStr->pioRecvPciLength;
00425         cbRecvLength = trStr->pcbRecvLength;
00426 
00427         trStr->rv = SCardTransmit(trStr->hCard, &ioSendPci,
00428             trStr->pbSendBuffer, trStr->cbSendLength,
00429             &ioRecvPci, trStr->pbRecvBuffer,
00430             &cbRecvLength);
00431 
00432         trStr->pioSendPciProtocol = ioSendPci.dwProtocol;
00433         trStr->pioSendPciLength = ioSendPci.cbPciLength;
00434         trStr->pioRecvPciProtocol = ioRecvPci.dwProtocol;
00435         trStr->pioRecvPciLength = ioRecvPci.cbPciLength;
00436         trStr->pcbRecvLength = cbRecvLength;
00437 
00438         break;
00439 
00440     case SCARD_CONTROL:
00441         ctStr = ((control_struct *) msgStruct->data);
00442         rv = MSGCheckHandleAssociation(ctStr->hCard, dwContextIndex);
00443         if (rv != 0) return rv;
00444 
00445         /* avoids buffer overflow */
00446         if ((ctStr->cbRecvLength > sizeof(ctStr->pbRecvBuffer))
00447             || (ctStr->cbSendLength > sizeof(ctStr->pbSendBuffer)))
00448         {
00449             ctStr->rv = SCARD_E_INSUFFICIENT_BUFFER;
00450             break;
00451         }
00452 
00453         dwBytesReturned = ctStr->dwBytesReturned;
00454 
00455         ctStr->rv = SCardControl(ctStr->hCard, ctStr->dwControlCode,
00456             ctStr->pbSendBuffer, ctStr->cbSendLength,
00457             ctStr->pbRecvBuffer, ctStr->cbRecvLength,
00458             &dwBytesReturned);
00459 
00460         ctStr->dwBytesReturned = dwBytesReturned;
00461 
00462         break;
00463 
00464     case SCARD_GET_ATTRIB:
00465         gsStr = ((getset_struct *) msgStruct->data);
00466         rv = MSGCheckHandleAssociation(gsStr->hCard, dwContextIndex);
00467         if (rv != 0) return rv;
00468 
00469         /* avoids buffer overflow */
00470         if (gsStr->cbAttrLen > sizeof(gsStr->pbAttr))
00471         {
00472             gsStr->rv = SCARD_E_INSUFFICIENT_BUFFER ;
00473             break;
00474         }
00475 
00476         cbAttrLen = gsStr->cbAttrLen;
00477 
00478         gsStr->rv = SCardGetAttrib(gsStr->hCard, gsStr->dwAttrId,
00479             gsStr->pbAttr, &cbAttrLen);
00480 
00481         gsStr->cbAttrLen = cbAttrLen;
00482 
00483         break;
00484 
00485     case SCARD_SET_ATTRIB:
00486         gsStr = ((getset_struct *) msgStruct->data);
00487         rv = MSGCheckHandleAssociation(gsStr->hCard, dwContextIndex);
00488         if (rv != 0) return rv;
00489 
00490         /* avoids buffer overflow */
00491         if (gsStr->cbAttrLen > sizeof(gsStr->pbAttr))
00492         {
00493             gsStr->rv = SCARD_E_INSUFFICIENT_BUFFER ;
00494             break;
00495         }
00496 
00497         gsStr->rv = SCardSetAttrib(gsStr->hCard, gsStr->dwAttrId,
00498             gsStr->pbAttr, gsStr->cbAttrLen);
00499         break;
00500 
00501     case SCARD_TRANSMIT_EXTENDED:
00502         {
00503             transmit_struct_extended *treStr;
00504             unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
00505             unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
00506 
00507             treStr = ((transmit_struct_extended *) msgStruct->data);
00508             rv = MSGCheckHandleAssociation(treStr->hCard, dwContextIndex);
00509             if (rv != 0) return rv;
00510 
00511             /* avoids buffer overflow */
00512             if ((treStr->size > sizeof(pbSendBuffer))
00513                 || (treStr->cbSendLength > sizeof(pbSendBuffer))
00514                 || (treStr->pcbRecvLength > sizeof(pbRecvBuffer)))
00515             {
00516                 treStr->rv = SCARD_E_INSUFFICIENT_BUFFER;
00517                 break;
00518             }
00519 
00520             /* on more block to read? */
00521             if (treStr->size > PCSCLITE_MAX_MESSAGE_SIZE)
00522             {
00523                 /* copy the first APDU part */
00524                 memcpy(pbSendBuffer, treStr->data,
00525                     PCSCLITE_MAX_MESSAGE_SIZE-offsetof(transmit_struct_extended, data));
00526 
00527                 /* receive the second block */
00528                 rv = SHMMessageReceive(
00529                     pbSendBuffer+PCSCLITE_MAX_MESSAGE_SIZE-offsetof(transmit_struct_extended, data),
00530                     treStr->size - PCSCLITE_MAX_MESSAGE_SIZE,
00531                     psContext[dwContextIndex].dwClientID,
00532                     PCSCLITE_SERVER_ATTEMPTS);
00533                 if (rv)
00534                     Log1(PCSC_LOG_CRITICAL, "reception failed");
00535             }
00536             else
00537                 memcpy(pbSendBuffer, treStr->data, treStr->cbSendLength);
00538 
00539             ioSendPci.dwProtocol = treStr->pioSendPciProtocol;
00540             ioSendPci.cbPciLength = treStr->pioSendPciLength;
00541             ioRecvPci.dwProtocol = treStr->pioRecvPciProtocol;
00542             ioRecvPci.cbPciLength = treStr->pioRecvPciLength;
00543             cbRecvLength = treStr->pcbRecvLength;
00544 
00545             treStr->rv = SCardTransmit(treStr->hCard, &ioSendPci,
00546                 pbSendBuffer, treStr->cbSendLength,
00547                 &ioRecvPci, pbRecvBuffer,
00548                 &cbRecvLength);
00549 
00550             treStr->pioSendPciProtocol = ioSendPci.dwProtocol;
00551             treStr->pioSendPciLength = ioSendPci.cbPciLength;
00552             treStr->pioRecvPciProtocol = ioRecvPci.dwProtocol;
00553             treStr->pioRecvPciLength = ioRecvPci.cbPciLength;
00554             treStr->pcbRecvLength = cbRecvLength;
00555 
00556             treStr->size = offsetof(transmit_struct_extended, data) + treStr->pcbRecvLength;
00557             if (treStr->size > PCSCLITE_MAX_MESSAGE_SIZE)
00558             {
00559                 /* two blocks */
00560                 memcpy(treStr->data, pbRecvBuffer, PCSCLITE_MAX_MESSAGE_SIZE
00561                     - offsetof(transmit_struct_extended, data));
00562 
00563                 rv = SHMMessageSend(msgStruct, sizeof(*msgStruct),
00564                     psContext[dwContextIndex].dwClientID,
00565                     PCSCLITE_SERVER_ATTEMPTS);
00566                 if (rv)
00567                     Log1(PCSC_LOG_CRITICAL, "transmission failed");
00568 
00569                 rv = SHMMessageSend(pbRecvBuffer + PCSCLITE_MAX_MESSAGE_SIZE
00570                     - offsetof(transmit_struct_extended, data),
00571                     treStr->size - PCSCLITE_MAX_MESSAGE_SIZE,
00572                     psContext[dwContextIndex].dwClientID,
00573                     PCSCLITE_SERVER_ATTEMPTS);
00574                 if (rv)
00575                     Log1(PCSC_LOG_CRITICAL, "transmission failed");
00576             }
00577             else
00578             {
00579                 /* one block only */
00580                 memcpy(treStr->data, pbRecvBuffer, treStr->pcbRecvLength);
00581 
00582                 rv = SHMMessageSend(msgStruct, sizeof(*msgStruct),
00583                     psContext[dwContextIndex].dwClientID,
00584                     PCSCLITE_SERVER_ATTEMPTS);
00585                 if (rv)
00586                     Log1(PCSC_LOG_CRITICAL, "transmission failed");
00587             }
00588         }
00589         break;
00590 
00591     case SCARD_CONTROL_EXTENDED:
00592         {
00593             control_struct_extended *cteStr;
00594             unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
00595             unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
00596 
00597             cteStr = ((control_struct_extended *) msgStruct->data);
00598             rv = MSGCheckHandleAssociation(cteStr->hCard, dwContextIndex);
00599             if (rv != 0) return rv;
00600 
00601             /* avoids buffer overflow */
00602             if ((cteStr->size > sizeof(pbSendBuffer))
00603                 || (cteStr->cbSendLength > sizeof(pbSendBuffer))
00604                 || (cteStr->cbRecvLength > sizeof(pbRecvBuffer)))
00605             {
00606                 cteStr->rv = SCARD_E_INSUFFICIENT_BUFFER;
00607                 break;
00608             }
00609 
00610             /* on more block to read? */
00611             if (cteStr->size > PCSCLITE_MAX_MESSAGE_SIZE)
00612             {
00613                 /* copy the first data part */
00614                 memcpy(pbSendBuffer, cteStr->data,
00615                     PCSCLITE_MAX_MESSAGE_SIZE-sizeof(*cteStr));
00616 
00617                 /* receive the second block */
00618                 rv = SHMMessageReceive(
00619                     pbSendBuffer+PCSCLITE_MAX_MESSAGE_SIZE-sizeof(*cteStr),
00620                     cteStr->size - PCSCLITE_MAX_MESSAGE_SIZE,
00621                     psContext[dwContextIndex].dwClientID,
00622                     PCSCLITE_SERVER_ATTEMPTS);
00623                 if (rv)
00624                     Log1(PCSC_LOG_CRITICAL, "reception failed");
00625             }
00626             else
00627                 memcpy(pbSendBuffer, cteStr->data, cteStr->cbSendLength);
00628 
00629             dwBytesReturned = cteStr->pdwBytesReturned;
00630 
00631             cteStr->rv = SCardControl(cteStr->hCard, cteStr->dwControlCode,
00632                 pbSendBuffer, cteStr->cbSendLength,
00633                 pbRecvBuffer, cteStr->cbRecvLength,
00634                 &dwBytesReturned);
00635 
00636             cteStr->pdwBytesReturned = dwBytesReturned;
00637 
00638             cteStr->size = sizeof(*cteStr) + cteStr->pdwBytesReturned;
00639             if (cteStr->size > PCSCLITE_MAX_MESSAGE_SIZE)
00640             {
00641                 /* two blocks */
00642                 memcpy(cteStr->data, pbRecvBuffer, PCSCLITE_MAX_MESSAGE_SIZE
00643                     - sizeof(*cteStr));
00644 
00645                 rv = SHMMessageSend(msgStruct, sizeof(*msgStruct),
00646                     psContext[dwContextIndex].dwClientID,
00647                     PCSCLITE_SERVER_ATTEMPTS);
00648                 if (rv)
00649                     Log1(PCSC_LOG_CRITICAL, "transmission failed");
00650 
00651                 rv = SHMMessageSend(pbRecvBuffer + PCSCLITE_MAX_MESSAGE_SIZE
00652                     - sizeof(*cteStr),
00653                     cteStr->size - PCSCLITE_MAX_MESSAGE_SIZE,
00654                     psContext[dwContextIndex].dwClientID,
00655                     PCSCLITE_SERVER_ATTEMPTS);
00656                 if (rv)
00657                     Log1(PCSC_LOG_CRITICAL, "transmission failed");
00658             }
00659             else
00660             {
00661                 /* one block only */
00662                 memcpy(cteStr->data, pbRecvBuffer, cteStr->pdwBytesReturned);
00663 
00664                 rv = SHMMessageSend(msgStruct, sizeof(*msgStruct),
00665                     psContext[dwContextIndex].dwClientID,
00666                     PCSCLITE_SERVER_ATTEMPTS);
00667                 if (rv)
00668                     Log1(PCSC_LOG_CRITICAL, "transmission failed");
00669             }
00670         }
00671         break;
00672 
00673     default:
00674         Log2(PCSC_LOG_CRITICAL, "Unknown command: %d", msgStruct->command);
00675         return -1;
00676     }
00677 
00678     return 0;
00679 }
00680 
00681 static LONG MSGAddContext(SCARDCONTEXT hContext, DWORD dwContextIndex)
00682 {
00683     psContext[dwContextIndex].hContext = hContext;
00684     return SCARD_S_SUCCESS;
00685 }
00686 
00687 static LONG MSGRemoveContext(SCARDCONTEXT hContext, DWORD dwContextIndex)
00688 {
00689     int i;
00690     LONG rv;
00691 
00692     if (psContext[dwContextIndex].hContext == hContext)
00693     {
00694         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
00695         {
00696             /*
00697              * Disconnect each of these just in case
00698              */
00699 
00700             if (psContext[dwContextIndex].hCard[i] != 0)
00701             {
00702                 PREADER_CONTEXT rContext = NULL;
00703                 DWORD dwLockId;
00704 
00705                 /*
00706                  * Unlock the sharing
00707                  */
00708                 rv = RFReaderInfoById(psContext[dwContextIndex].hCard[i],
00709                     &rContext);
00710                 if (rv != SCARD_S_SUCCESS)
00711                     return rv;
00712 
00713                 dwLockId = rContext->dwLockId;
00714                 rContext->dwLockId = 0;
00715 
00716                 if (psContext[dwContextIndex].hCard[i] != dwLockId)
00717                 {
00718                     /*
00719                      * if the card is locked by someone else we do not reset it
00720                      * and simulate a card removal
00721                      */
00722                     rv = SCARD_W_REMOVED_CARD;
00723                 }
00724                 else
00725                 {
00726                     /*
00727                      * We will use SCardStatus to see if the card has been
00728                      * reset there is no need to reset each time
00729                      * Disconnect is called
00730                      */
00731                     rv = SCardStatus(psContext[dwContextIndex].hCard[i], NULL,
00732                         NULL, NULL, NULL, NULL, NULL);
00733                 }
00734 
00735                 if (rv == SCARD_W_RESET_CARD || rv == SCARD_W_REMOVED_CARD)
00736                     (void)SCardDisconnect(psContext[dwContextIndex].hCard[i],
00737                         SCARD_LEAVE_CARD);
00738                 else
00739                     (void)SCardDisconnect(psContext[dwContextIndex].hCard[i],
00740                         SCARD_RESET_CARD);
00741 
00742                 psContext[dwContextIndex].hCard[i] = 0;
00743             }
00744         }
00745 
00746         psContext[dwContextIndex].hContext = 0;
00747         return SCARD_S_SUCCESS;
00748     }
00749 
00750     return SCARD_E_INVALID_VALUE;
00751 }
00752 
00753 static LONG MSGAddHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard,
00754     DWORD dwContextIndex)
00755 {
00756     int i;
00757 
00758     if (psContext[dwContextIndex].hContext == hContext)
00759     {
00760 
00761         /*
00762          * Find an empty spot to put the hCard value
00763          */
00764         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
00765         {
00766             if (psContext[dwContextIndex].hCard[i] == 0)
00767             {
00768                 psContext[dwContextIndex].hCard[i] = hCard;
00769                 break;
00770             }
00771         }
00772 
00773         if (i == PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS)
00774         {
00775             return SCARD_F_INTERNAL_ERROR;
00776         } else
00777         {
00778             return SCARD_S_SUCCESS;
00779         }
00780 
00781     }
00782 
00783     return SCARD_E_INVALID_VALUE;
00784 }
00785 
00786 static LONG MSGRemoveHandle(SCARDHANDLE hCard, DWORD dwContextIndex)
00787 {
00788     int i;
00789 
00790     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
00791     {
00792         if (psContext[dwContextIndex].hCard[i] == hCard)
00793         {
00794             psContext[dwContextIndex].hCard[i] = 0;
00795             return SCARD_S_SUCCESS;
00796         }
00797     }
00798 
00799     return SCARD_E_INVALID_VALUE;
00800 }
00801 
00802 
00803 static LONG MSGCheckHandleAssociation(SCARDHANDLE hCard, DWORD dwContextIndex)
00804 {
00805     int i;
00806 
00807     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
00808     {
00809         if (psContext[dwContextIndex].hCard[i] == hCard)
00810         {
00811             return 0;
00812         }
00813     }
00814 
00815     /* Must be a rogue client, debug log and sleep a couple of seconds */
00816     Log1(PCSC_LOG_ERROR, "Client failed to authenticate");
00817     (void)SYS_Sleep(2);
00818 
00819     return -1;
00820 }
00821 
00822 static LONG MSGCleanupClient(DWORD dwContextIndex)
00823 {
00824     if (psContext[dwContextIndex].hContext != 0)
00825     {
00826         (void)SCardReleaseContext(psContext[dwContextIndex].hContext);
00827         (void)MSGRemoveContext(psContext[dwContextIndex].hContext,
00828             dwContextIndex);
00829     }
00830 
00831     psContext[dwContextIndex].dwClientID = 0;
00832     psContext[dwContextIndex].protocol_major = 0;
00833     psContext[dwContextIndex].protocol_minor = 0;
00834 
00835     return 0;
00836 }

Generated on 20 Jun 2013 for pcsc-lite by  doxygen 1.6.1