Hi,

The patch addresses the following.

1. Fixes bug in SCardGetStatusChange where Context index was being used
instead of Reader index, it worked only when there was just one context.
2. Adds cleanup code to SCardUnload.
3. Changes isOCFServerRunning(.) because of memory leak issues in
libsmartcard.so on Solaris 8, everytime SCF_Session_getSession -
SCF_Session_close is called libsmartcard leaks memory.
4. Fix issue where SCardGetStatusChange returns incorrect status when it is
called right after SCardEstablishContext the first time after the
libpcsclite.so is loaded in memory, the fix is to make PCSC_Initialize()
wait till OCF has been initialized and the internal states are consistent.


Regards,

Najam.



--- winscard_scf.c      2005-08-08 14:58:20.000000000 -0500
+++ winscard_scf.new.c  2005-10-05 15:25:47.197470400 -0500
@@ -34,6 +34,8 @@
 #include "eventhandler.h"
 #include "sys_generic.h"
 
+#include <time.h>
+
 #define TRUE   1
 #define FALSE  0
 
@@ -94,6 +96,12 @@ static PCSCLITE_MUTEX clientMutex = PTHR
  * so to get lock on the clientMutex may affect the performance of the ocf
server.
  */
 static PCSCLITE_MUTEX EventMutex = PTHREAD_MUTEX_INITIALIZER;
+static PCSCLITE_MUTEX SCFInitMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t EventCondition = PTHREAD_COND_INITIALIZER;
+
+
+
+static int g_fPCSC_Initialized = 0;
 
 static LONG isOCFServerRunning(void);
 LONG SCardLockThread(void);
@@ -122,6 +130,7 @@ static LONG SCardAddHandle(SCARDHANDLE P
        SCF_Session_t hSession, SCF_Terminal_t hTerminal,
        SCF_Card_t SCF_hCard, int, DWORD);
 static LONG SCardGetHandleIndice(SCARDHANDLE hCard);
+static LONG isActiveContextPresent ( void );
 
 
 static LONG SCardEstablishContextTH(DWORD dwScope, LPCVOID pvReserved1,
@@ -684,7 +693,7 @@ LONG SCardGetStatusChange(SCARDCONTEXT h
        LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
 {
 
-       LONG rv, retIndice;
+       LONG rv, retIndice, readerIndice;
        PSCARD_READERSTATE_A currReader;
        PREADER_STATE rContext;
        LPTSTR lpcReaderName;
@@ -706,6 +715,7 @@ LONG SCardGetStatusChange(SCARDCONTEXT h
        i = 0;
        currReader = 0;
        retIndice = 0;
+       readerIndice = 0;
        dwBreakFlag = 0;
 
        if (rgReaderStates == 0 && cReaders > 0)
@@ -781,9 +791,9 @@ LONG SCardGetStatusChange(SCARDCONTEXT h
 
                        lpcReaderName = (char *) currReader->szReader;
 
-                       retIndice = SCardGetReaderIndice(lpcReaderName);
+                       readerIndice = SCardGetReaderIndice(lpcReaderName);
                        /* The requested reader name is not recognized */
-                       if (0 > retIndice)
+                       if (0 > readerIndice)
                        {
                                if (currReader->dwCurrentState &
SCARD_STATE_UNKNOWN)
                                {
@@ -811,7 +821,7 @@ LONG SCardGetStatusChange(SCARDCONTEXT h
        /*****************************************************************/
                                SCardEventLock();
                                /* Now we check all the Reader States */
-                               dwState =
psReaderMap[retIndice].dwCurrentState;
+                               dwState =
psReaderMap[readerIndice].dwCurrentState;
 
        /*********** Check if the reader is in the correct state ********/
                                if (dwState & SCARD_STATE_UNKNOWN)
@@ -844,8 +854,8 @@ LONG SCardGetStatusChange(SCARDCONTEXT h
 
                                if (dwState & SCARD_STATE_PRESENT)
                                {
-                                       currReader->cbAtr =
psReaderMap[retIndice].dwAtrLength;
-                                       memcpy(currReader->rgbAtr,
psReaderMap[retIndice].bAtr,
+                                       currReader->cbAtr =
psReaderMap[readerIndice].dwAtrLength;
+                                       memcpy(currReader->rgbAtr,
psReaderMap[readerIndice].bAtr,
                                                currReader->cbAtr);
                                }
                                else
@@ -920,7 +930,7 @@ LONG SCardGetStatusChange(SCARDCONTEXT h
                                        }
                                }
 
-                               if (-1 ==
psReaderMap[retIndice].SharedRefCount)
+                               if (-1 ==
psReaderMap[readerIndice].SharedRefCount)
                                {
                                        currReader->dwEventState |=
SCARD_STATE_EXCLUSIVE;
                                        currReader->dwEventState &=
~SCARD_STATE_INUSE;
@@ -930,7 +940,7 @@ LONG SCardGetStatusChange(SCARDCONTEXT h
                                                dwBreakFlag = 1;
                                        }
                                }
-                               else if
(psReaderMap[retIndice].SharedRefCount >= 1)
+                               else if
(psReaderMap[readerIndice].SharedRefCount >= 1)
                                {
                                        /* A card must be inserted for it to
be INUSE */
                                        if (dwState & SCARD_STATE_PRESENT)
@@ -1581,9 +1591,26 @@ LONG SCardEventUnlock(void)
        return SYS_MutexUnLock(&EventMutex);
 }
 
+static LONG isActiveContextPresent (  ) 
+{
+    long fActiveContext = FALSE;
+    int i = 0;
+    
+    for ( i=0; i<PCSCLITE_MAX_APPLICATION_CONTEXTS; i++ ) 
+    {
+        if ( psContextMap[i].hContext != 0 ) 
+        {
+               fActiveContext = TRUE;
+            break;
+        }
+    }
+    return fActiveContext;
+}
+
 static void EventCallback(SCF_Event_t eventType, SCF_Terminal_t hTerm,
        void *cbdata)
 {
+    static int bInitialized = 0;
        int i = 0;
        int ReaderIndice = 0;
        SCF_Card_t hCard;
@@ -1671,6 +1698,23 @@ static void EventCallback(SCF_Event_t ev
        default:
                break;
        }                                                       /* switch */
+
+    /*
+        The OCF Server always calls the registered callback function 
+        immediately after the callback function is registered,
+        but always with the state of SCF_EVENT_CARDABSENT even if 
+        there is a card present in the reader, the OCF server then 
+        calls the callback the second time with the correct state,
+        that is the reason for the check if( bInitialized == 2 ).
+        If there is no card present in the reader the PCSC_SCF_Initialize's

+        pthread_cond_timedwait times out after 2 secs.
+    */
+    if(!bInitialized || bInitialized == 1)
+    {
+        bInitialized++;
+        if( bInitialized == 2 )
+               pthread_cond_signal( &EventCondition );
+    }    
        SCardEventUnlock();
 }
 
@@ -1681,6 +1725,14 @@ static LONG isOCFServerRunning(void)
        SCF_Status_t status;
        SCF_Session_t hSession;
 
+    /* return SCARD_S_SUCCESS here, everytime we call a
SCF_Session_getSession - SCF_Session_close
+        libsmartcard leaks memory. The consequences of returning true here
will be
+        that the next SCF call will fail anyways, but may not return the
correct error,
+        i.e. SCARD_E_NO_SERVICE.
+    */
+    return SCARD_S_SUCCESS;
+
+
        if (FALSE == isRunning)
                return SCARD_E_NO_SERVICE;
 
@@ -1699,10 +1751,9 @@ static LONG PCSC_SCF_Initialize(void)
 {
        SCF_Status_t status;
        char **tList = NULL;
-       static int first_time = 1;
        int i;
-
-       if (!first_time)
+    
+       if (g_fPCSC_Initialized)
                return SCARD_S_SUCCESS;
        for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
        {
@@ -1759,7 +1810,31 @@ static LONG PCSC_SCF_Initialize(void)
                }
        }
        SCF_Session_freeInfo(g_hSession, tList);
-       first_time = 0;
+       
+       SYS_MutexLock( &SCFInitMutex );
+       
+       /*wait for ocfserver to initialize... or 2 secs whichever is
earlier.
+    */
+    struct timeval CurrTime;
+    void *zero = 0;
+    
+    gettimeofday(&CurrTime,zero);
+
+    struct timespec Abstime;
+
+    // Calculate absolute time to time out.
+
+    Abstime.tv_sec = CurrTime.tv_sec + 2;
+    Abstime.tv_nsec = CurrTime.tv_usec*1000 + (2%1000)*1000000;
+    if(Abstime.tv_nsec>999999999) {
+        Abstime.tv_sec++;
+        Abstime.tv_nsec -= 1000000000;
+    }
+    
+    pthread_cond_timedwait( &EventCondition, &SCFInitMutex, &Abstime);
+    SYS_MutexUnLock( &SCFInitMutex );
+
+    g_fPCSC_Initialized = 1;
        return SCARD_S_SUCCESS;
 }
 
@@ -1847,6 +1922,41 @@ void SCardUnload(void)
        SYS_CloseFile(mapAddr);
        isExecuted = 0;
 #endif
+
+    int i=0;
+
+    /*
+        Cleanup only if PCSC has been initialized and there are no active 
+        context. Checking for active context is critical when libpcsclite
is linked with 
+        multiple modules. for eg. an application links with pcsclite and a
PAM module 
+        also links with pcsclite, when the PAM is unloaded from memory and
if it calls
+        SCardUnload, pcsclite will un-initialize even though there are
active references from the 
+        application. Now, why dont we add SCardUnload to the array of
functions to be called 
+        on unload (-zfiniarray=SCUnload), well, that does not seem to solve
the problem, 
+        SCardUnload is called when PAM is unloaded from memory having the
same impact that
+        PCSC is uninitialized enen though there are active references.
+    */
+    if(!g_fPCSC_Initialized ||
+       isActiveContextPresent()) 
+    {
+        return;
+    }
+    for(i=0;i<PCSCLITE_MAX_READERS_CONTEXTS;i++) 
+    {
+           if(psReaderMap[i].hTerminal)
+           {
+               SCF_Terminal_removeEventListener( psReaderMap[i].hTerminal,
+                                             psReaderMap[i].lHandle );
+               SCF_Terminal_close(psReaderMap[i].hTerminal); 
+               if( psReaderMap[i].ReaderName )
+               {
+                       free( psReaderMap[i].ReaderName );
+               }
+           }   
+    }
+    
+    SCF_Session_close(  g_hSession );
+    g_fPCSC_Initialized = 0;
 }
 
 /*


_______________________________________________
Muscle mailing list
[email protected]
http://lists.drizzle.com/mailman/listinfo/muscle

Reply via email to