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 1695 2005-10-29 16:27:33Z rousseau $
00010  */
00011 
00022 #include "config.h"
00023 #include <time.h>
00024 #include <stdio.h>
00025 #include <string.h>
00026 
00027 #include "pcsclite.h"
00028 #include "winscard.h"
00029 #include "debuglog.h"
00030 #include "winscard_msg.h"
00031 #include "winscard_svc.h"
00032 #include "sys_generic.h"
00033 #include "thread_generic.h"
00034 
00040 static struct _psContext
00041 {
00042     SCARDCONTEXT hContext;
00043     SCARDHANDLE hCard[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
00044     DWORD dwClientID;           /* Connection ID used to reference the Client. */
00045     PCSCLITE_THREAD_T pthThread;        /* Event polling thread's ID */
00046     sharedSegmentMsg msgStruct;     /* Msg sent by the Client */
00047     int protocol_major, protocol_minor; /* Protocol number agreed between client and server*/
00048 } psContext[PCSCLITE_MAX_APPLICATIONS_CONTEXTS];
00049 
00053 static DWORD dwNextContextIndex;
00054 
00055 LONG MSGCheckHandleAssociation(SCARDHANDLE, DWORD);
00056 LONG MSGFunctionDemarshall(psharedSegmentMsg, DWORD);
00057 LONG MSGAddContext(SCARDCONTEXT, DWORD);
00058 LONG MSGRemoveContext(SCARDCONTEXT, DWORD);
00059 LONG MSGAddHandle(SCARDCONTEXT, SCARDHANDLE, DWORD);
00060 LONG MSGRemoveHandle(SCARDHANDLE, DWORD);
00061 LONG MSGCleanupClient(DWORD);
00062 
00063 static void ContextThread(DWORD* pdwIndex);
00064 
00065 LONG ContextsInitialize(void)
00066 {
00067     memset(psContext, 0, sizeof(struct _psContext)*PCSCLITE_MAX_APPLICATIONS_CONTEXTS);
00068     return 1;
00069 }
00070 
00081 LONG CreateContextThread(PDWORD pdwClientID)
00082 {
00083     int i;
00084 
00085     for (i = 0; i < PCSCLITE_MAX_APPLICATIONS_CONTEXTS; i++)
00086     {
00087         if (psContext[i].dwClientID == 0)
00088         {
00089             psContext[i].dwClientID = *pdwClientID;
00090             *pdwClientID = 0;
00091             break;
00092         }
00093     }
00094 
00095     if (i == PCSCLITE_MAX_APPLICATIONS_CONTEXTS)
00096     {
00097         SYS_CloseFile(psContext[i].dwClientID);
00098         psContext[i].dwClientID = 0; 
00099         return SCARD_F_INTERNAL_ERROR;
00100     }
00101     
00102     dwNextContextIndex = i;
00103 
00104     if (SYS_ThreadCreate(&psContext[i].pthThread, THREAD_ATTR_DETACHED,
00105         (PCSCLITE_THREAD_FUNCTION( )) ContextThread,
00106         (LPVOID) &dwNextContextIndex) != 1)
00107     {
00108         SYS_CloseFile(psContext[i].dwClientID);
00109         psContext[i].dwClientID = 0; 
00110         return SCARD_E_NO_MEMORY;
00111     }
00112 
00113     return SCARD_S_SUCCESS;
00114 }
00115 
00116 /*
00117  * A list of local functions used to keep track of clients and their
00118  * connections 
00119  */
00120 
00129 static void ContextThread(DWORD* pdwIndex)
00130 {
00131     LONG rv;
00132     sharedSegmentMsg msgStruct;
00133     DWORD dwContextIndex = *pdwIndex;
00134 
00135     Log2(PCSC_LOG_DEBUG, "Thread is started: %d",
00136         psContext[dwContextIndex].dwClientID);
00137     
00138     while (1)
00139     {
00140         switch (rv = SHMProcessEventsContext(&psContext[dwContextIndex].dwClientID, &msgStruct, 0))
00141         {
00142         case 0:
00143             if (msgStruct.mtype == CMD_CLIENT_DIED)
00144             {
00145                 /*
00146                  * Clean up the dead client
00147                  */
00148                 Log2(PCSC_LOG_DEBUG, "Client die: %d",
00149                     psContext[dwContextIndex].dwClientID);
00150                 MSGCleanupClient(dwContextIndex);
00151                 SYS_ThreadExit((LPVOID) NULL);
00152             } 
00153             break;
00154 
00155         case 1:
00156             if (msgStruct.mtype == CMD_FUNCTION)
00157             {
00158                 /*
00159                  * Command must be found
00160                  */
00161                 MSGFunctionDemarshall(&msgStruct, dwContextIndex);
00162                 rv = SHMMessageSend(&msgStruct, psContext[dwContextIndex].dwClientID,
00163                             PCSCLITE_SERVER_ATTEMPTS);
00164             }
00165             else
00166                 /* pcsc-lite client/server protocol version */
00167                 if (msgStruct.mtype == CMD_VERSION)
00168                 {
00169                     version_struct *veStr;
00170                     veStr = (version_struct *) msgStruct.data;
00171 
00172                     /* get the client protocol version */
00173                     psContext[dwContextIndex].protocol_major = veStr->major;
00174                     psContext[dwContextIndex].protocol_minor = veStr->minor;
00175 
00176                     Log3(PCSC_LOG_DEBUG,
00177                         "Client is protocol version %d:%d",
00178                         veStr->major, veStr->minor);
00179 
00180                     /* set the server protocol version */
00181                     veStr->major = PROTOCOL_VERSION_MAJOR;
00182                     veStr->minor = PROTOCOL_VERSION_MINOR;
00183                     veStr->rv = SCARD_S_SUCCESS;
00184 
00185                     /* send back the response */
00186                     rv = SHMMessageSend(&msgStruct,
00187                         psContext[dwContextIndex].dwClientID,
00188                         PCSCLITE_SERVER_ATTEMPTS);
00189                 }
00190                 else
00191                     continue;
00192 
00193             break;
00194 
00195         case 2:
00196             /*
00197              * timeout in SHMProcessEventsContext(): do nothing
00198              * this is used to catch the Ctrl-C signal at some time when
00199              * nothing else happens
00200              */
00201             break;
00202             
00203         case -1:
00204             Log1(PCSC_LOG_ERROR, "Error in SHMProcessEventsContext");
00205             break;
00206             
00207         default:
00208             Log2(PCSC_LOG_ERROR,
00209                 "SHMProcessEventsContext unknown retval: %d", rv);
00210             break;
00211         }
00212     }
00213 }
00214 
00230 LONG MSGFunctionDemarshall(psharedSegmentMsg msgStruct, DWORD dwContextIndex)
00231 {
00232     LONG rv;
00233     establish_struct *esStr;
00234     release_struct *reStr;
00235     connect_struct *coStr;
00236     reconnect_struct *rcStr;
00237     disconnect_struct *diStr;
00238     begin_struct *beStr;
00239     cancel_struct *caStr;
00240     end_struct *enStr;
00241     status_struct *stStr;
00242     transmit_struct *trStr;
00243     control_struct *ctStr;
00244     getset_struct *gsStr;
00245 
00246     /*
00247      * Zero out everything 
00248      */
00249     rv = 0;
00250     switch (msgStruct->command)
00251     {
00252 
00253     case SCARD_ESTABLISH_CONTEXT:
00254         esStr = ((establish_struct *) msgStruct->data);
00255         esStr->rv = SCardEstablishContext(esStr->dwScope, 0, 0,
00256             &esStr->phContext);
00257 
00258         if (esStr->rv == SCARD_S_SUCCESS)
00259             esStr->rv =
00260                 MSGAddContext(esStr->phContext, dwContextIndex);
00261         break;
00262 
00263     case SCARD_RELEASE_CONTEXT:
00264         reStr = ((release_struct *) msgStruct->data);
00265         reStr->rv = SCardReleaseContext(reStr->hContext);
00266 
00267         if (reStr->rv == SCARD_S_SUCCESS)
00268             reStr->rv =
00269                 MSGRemoveContext(reStr->hContext, dwContextIndex);
00270 
00271         break;
00272 
00273     case SCARD_CONNECT:
00274         coStr = ((connect_struct *) msgStruct->data);
00275         coStr->rv = SCardConnect(coStr->hContext, coStr->szReader,
00276             coStr->dwShareMode, coStr->dwPreferredProtocols,
00277             &coStr->phCard, &coStr->pdwActiveProtocol);
00278 
00279         if (coStr->rv == SCARD_S_SUCCESS)
00280             coStr->rv =
00281                 MSGAddHandle(coStr->hContext, coStr->phCard, dwContextIndex);
00282 
00283         break;
00284 
00285     case SCARD_RECONNECT:
00286         rcStr = ((reconnect_struct *) msgStruct->data);
00287         rv = MSGCheckHandleAssociation(rcStr->hCard, dwContextIndex);
00288         if (rv != 0) return rv;
00289 
00290         rcStr->rv = SCardReconnect(rcStr->hCard, rcStr->dwShareMode,
00291             rcStr->dwPreferredProtocols,
00292             rcStr->dwInitialization, &rcStr->pdwActiveProtocol);
00293         break;
00294 
00295     case SCARD_DISCONNECT:
00296         diStr = ((disconnect_struct *) msgStruct->data);
00297         rv = MSGCheckHandleAssociation(diStr->hCard, dwContextIndex);
00298         if (rv != 0) return rv;
00299         diStr->rv = SCardDisconnect(diStr->hCard, diStr->dwDisposition);
00300 
00301         if (diStr->rv == SCARD_S_SUCCESS)
00302             diStr->rv =
00303                 MSGRemoveHandle(diStr->hCard, dwContextIndex);
00304         break;
00305 
00306     case SCARD_BEGIN_TRANSACTION:
00307         beStr = ((begin_struct *) msgStruct->data);
00308         rv = MSGCheckHandleAssociation(beStr->hCard, dwContextIndex);
00309         if (rv != 0) return rv;
00310         beStr->rv = SCardBeginTransaction(beStr->hCard);
00311         break;
00312 
00313     case SCARD_END_TRANSACTION:
00314         enStr = ((end_struct *) msgStruct->data);
00315         rv = MSGCheckHandleAssociation(enStr->hCard, dwContextIndex);
00316         if (rv != 0) return rv;
00317         enStr->rv =
00318             SCardEndTransaction(enStr->hCard, enStr->dwDisposition);
00319         break;
00320 
00321     case SCARD_CANCEL_TRANSACTION:
00322         caStr = ((cancel_struct *) msgStruct->data);
00323         rv = MSGCheckHandleAssociation(caStr->hCard, dwContextIndex);
00324         if (rv != 0) return rv;
00325         caStr->rv = SCardCancelTransaction(caStr->hCard);
00326         break;
00327 
00328     case SCARD_STATUS:
00329         stStr = ((status_struct *) msgStruct->data);
00330         rv = MSGCheckHandleAssociation(stStr->hCard, dwContextIndex);
00331         if (rv != 0) return rv;
00332         stStr->rv = SCardStatus(stStr->hCard, stStr->mszReaderNames,
00333             &stStr->pcchReaderLen, &stStr->pdwState,
00334             &stStr->pdwProtocol, stStr->pbAtr, &stStr->pcbAtrLen);
00335         break;
00336 
00337     case SCARD_TRANSMIT:
00338         trStr = ((transmit_struct *) msgStruct->data);
00339         rv = MSGCheckHandleAssociation(trStr->hCard, dwContextIndex);
00340         if (rv != 0) return rv;
00341         trStr->rv = SCardTransmit(trStr->hCard, &trStr->pioSendPci,
00342             trStr->pbSendBuffer, trStr->cbSendLength,
00343             &trStr->pioRecvPci, trStr->pbRecvBuffer,
00344             &trStr->pcbRecvLength);
00345         break;
00346 
00347     case SCARD_CONTROL:
00348         ctStr = ((control_struct *) msgStruct->data);
00349         rv = MSGCheckHandleAssociation(ctStr->hCard, dwContextIndex);
00350         if (rv != 0) return rv;
00351         ctStr->rv = SCardControl(ctStr->hCard, ctStr->dwControlCode,
00352             ctStr->pbSendBuffer, ctStr->cbSendLength,
00353             ctStr->pbRecvBuffer, ctStr->cbRecvLength,
00354             &ctStr->dwBytesReturned);
00355         break;
00356 
00357     case SCARD_GET_ATTRIB:
00358         gsStr = ((getset_struct *) msgStruct->data);
00359         rv = MSGCheckHandleAssociation(gsStr->hCard, dwContextIndex);
00360         if (rv != 0) return rv;
00361         gsStr->rv = SCardGetAttrib(gsStr->hCard, gsStr->dwAttrId,
00362             gsStr->pbAttr, &gsStr->cbAttrLen);
00363         break;
00364 
00365     case SCARD_SET_ATTRIB:
00366         gsStr = ((getset_struct *) msgStruct->data);
00367         rv = MSGCheckHandleAssociation(gsStr->hCard, dwContextIndex);
00368         if (rv != 0) return rv;
00369         gsStr->rv = SCardSetAttrib(gsStr->hCard, gsStr->dwAttrId,
00370             gsStr->pbAttr, gsStr->cbAttrLen);
00371         break;
00372 
00373     default:
00374         return -1;
00375     }
00376 
00377     return 0;
00378 }
00379 
00380 LONG MSGAddContext(SCARDCONTEXT hContext, DWORD dwContextIndex)
00381 {
00382     psContext[dwContextIndex].hContext = hContext;
00383     return SCARD_S_SUCCESS;
00384 }
00385 
00386 LONG MSGRemoveContext(SCARDCONTEXT hContext, DWORD dwContextIndex)
00387 {
00388     int i;
00389     LONG rv;
00390 
00391     if (psContext[dwContextIndex].hContext == hContext)
00392     {
00393 
00394         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
00395         {
00396             /*
00397              * Disconnect each of these just in case 
00398              */
00399             
00400             if (psContext[dwContextIndex].hCard[i] != 0)
00401             {
00402                 
00403                 /*
00404                  * We will use SCardStatus to see if the card has been 
00405                  * reset there is no need to reset each time
00406                  * Disconnect is called 
00407                  */
00408                 
00409                 rv = SCardStatus(psContext[dwContextIndex].hCard[i], 0, 0, 0, 0, 0, 0);
00410                 
00411                 if (rv == SCARD_W_RESET_CARD
00412                     || rv == SCARD_W_REMOVED_CARD)
00413                 {
00414                     SCardDisconnect(psContext[dwContextIndex].hCard[i], SCARD_LEAVE_CARD);
00415                 } else
00416                 {
00417                     SCardDisconnect(psContext[dwContextIndex].hCard[i], SCARD_RESET_CARD);
00418                 }
00419 
00420                 psContext[dwContextIndex].hCard[i] = 0;
00421             }
00422 
00423         }
00424 
00425         psContext[dwContextIndex].hContext = 0;
00426         return SCARD_S_SUCCESS;
00427     } 
00428 
00429     return SCARD_E_INVALID_VALUE;
00430 }
00431 
00432 LONG MSGAddHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard, DWORD dwContextIndex)
00433 {
00434     int i;
00435 
00436     if (psContext[dwContextIndex].hContext == hContext)
00437     {
00438         
00439         /*
00440          * Find an empty spot to put the hCard value 
00441          */
00442         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
00443         {
00444             if (psContext[dwContextIndex].hCard[i] == 0)
00445             {
00446                 psContext[dwContextIndex].hCard[i] = hCard;
00447                 break;
00448             }
00449         }
00450         
00451         if (i == PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS)
00452         {
00453             return SCARD_F_INTERNAL_ERROR;
00454         } else
00455         {
00456             return SCARD_S_SUCCESS;
00457         }
00458 
00459     }
00460     
00461     return SCARD_E_INVALID_VALUE;
00462 }
00463 
00464 LONG MSGRemoveHandle(SCARDHANDLE hCard, DWORD dwContextIndex)
00465 {
00466     int i;
00467 
00468     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
00469     {
00470         if (psContext[dwContextIndex].hCard[i] == hCard)
00471         {
00472             psContext[dwContextIndex].hCard[i] = 0;
00473             return SCARD_S_SUCCESS;
00474         }
00475     }
00476 
00477     return SCARD_E_INVALID_VALUE;
00478 }
00479 
00480 
00481 LONG MSGCheckHandleAssociation(SCARDHANDLE hCard, DWORD dwContextIndex)
00482 {
00483     int i;
00484 
00485     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
00486     {
00487         if (psContext[dwContextIndex].hCard[i] == hCard)
00488         {
00489             return 0;
00490         }
00491     }
00492     
00493     /* Must be a rogue client, debug log and sleep a couple of seconds */
00494     Log1(PCSC_LOG_ERROR, "Client failed to authenticate");
00495     SYS_Sleep(2);
00496 
00497     return -1;
00498 }
00499 
00500 LONG MSGCleanupClient(DWORD dwContextIndex)
00501 {
00502     if (psContext[dwContextIndex].hContext != 0)
00503     {
00504         SCardReleaseContext(psContext[dwContextIndex].hContext);    
00505         MSGRemoveContext(psContext[dwContextIndex].hContext, dwContextIndex);
00506     }
00507 
00508     psContext[dwContextIndex].dwClientID = 0;
00509     psContext[dwContextIndex].protocol_major = 0;
00510     psContext[dwContextIndex].protocol_minor = 0;
00511     
00512     return 0;
00513 }

Generated on Fri Mar 24 04:30:06 2006 for pcsc-lite by  doxygen 1.4.6