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

Generated on Sat Oct 14 22:17:36 2006 for pcsc-lite by  doxygen 1.4.7