Okay, so here's some code to illustrate the idea.  I don't think this is 
necessarily the right approach, but it should provide a starting point for 
discussion.  It is intentionally minimal, and somewhat hackish.

This patch:

1.  Adds a notion of reader "ownership" by a given user ID.  When the reader 
is "owned" and a different user tries to exchange APDUs with the card, the 
card will be reset first.
2.  Uses the SCARD_SCOPE_USER flag to SCardEstablishContext as a signal that 
the new context wishes to obtain ownership of readers it talks to.  This is 
probably a bad idea.
3.  Adds code to validate that the user ID reported by the client in the 
message to the server is, in fact, the user ID owning the process that sent 
the request.  Note that the technique used to obtain the UID of the client 
process may be Linux-specific.  I know it does not work on Solaris (though 
Solaris does provide other mechanisms to achieve the same result).

The patch is against SVN trunk.

Comments/flames/chastisement all welcome,

        Shawn.
Index: PCSC/src/readerfactory.h
===================================================================
--- PCSC/src/readerfactory.h	(revision 1969)
+++ PCSC/src/readerfactory.h	(working copy)
@@ -160,6 +160,8 @@
 		DWORD dwSlot;			/* Current Reader Slot */
 		DWORD dwBlockStatus;	/* Current blocking status */
 		DWORD dwLockId;			/* Lock Id */
+		BOOL  bOwned;			/* True if "owned" by a UID */
+		DWORD dwUserID;			/* UID of "owner" */
 		DWORD dwIdentity;		/* Shared ID High Nibble */
 		DWORD dwContexts;		/* Number of open contexts */
 		PDWORD pdwFeeds;		/* Number of shared client to lib */
Index: PCSC/src/sys_generic.h
===================================================================
--- PCSC/src/sys_generic.h	(revision 1969)
+++ PCSC/src/sys_generic.h	(working copy)
@@ -94,6 +94,8 @@
 
 	int SYS_Unlink(char *pcFile);
 
+	int SYS_GetPeerUID(int, unsigned long *);
+
 #ifdef __cplusplus
 }
 #endif
Index: PCSC/src/sys_unix.c
===================================================================
--- PCSC/src/sys_unix.c	(revision 1969)
+++ PCSC/src/sys_unix.c	(working copy)
@@ -21,6 +21,7 @@
 #include <sys/wait.h>
 #include <sys/time.h>
 #include <sys/file.h>
+#include <sys/socket.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
@@ -515,3 +516,17 @@
 	return unlink(pcFile);
 }
 
+
+INTERNAL int SYS_GetPeerUID(int sockfd, unsigned long *pulUid)
+{
+	struct ucred peercred;
+	socklen_t optlen = sizeof(peercred);
+
+	if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &peercred, &optlen) == -1)
+		return -1;
+
+	if (pulUid)
+		*pulUid = peercred.uid;
+
+	return 0;
+}
Index: PCSC/src/winscard_msg_srv.c
===================================================================
--- PCSC/src/winscard_msg_srv.c	(revision 1969)
+++ PCSC/src/winscard_msg_srv.c	(working copy)
@@ -227,6 +227,7 @@
 	fd_set read_fd;
 	int selret, rv;
 	struct timeval tv;
+	unsigned long uid;
 
 	tv.tv_sec = 1;
 	tv.tv_usec = 0;
@@ -268,6 +269,12 @@
 		}
 		
 		/*
+		 * Validate the user_id provided by the client.
+		 */
+		if (SYS_GetPeerUID(*pdwClientID, &uid) == -1 || uid != (unsigned long)(msgStruct->user_id))
+			return -1;
+		
+		/*
 		 * Set the identifier handle 
 		 */
 		Log2(PCSC_LOG_DEBUG, "correctly processed client: %d",
Index: PCSC/src/winscard_svc.c
===================================================================
--- PCSC/src/winscard_svc.c	(revision 1969)
+++ PCSC/src/winscard_svc.c	(working copy)
@@ -31,7 +31,13 @@
 #include "winscard_svc.h"
 #include "sys_generic.h"
 #include "thread_generic.h"
+#include "readerfactory.h"
+#include "ifdwrapper.h"
+#include "eventhandler.h"
 
+#define FALSE 0
+#define TRUE 1
+
 /**
  * @brief Represents the an Application Context on the Server side.
  *
@@ -43,6 +49,7 @@
 	SCARDHANDLE hCard[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
 	DWORD dwClientID;			/* Connection ID used to reference the Client. */
 	PCSCLITE_THREAD_T pthThread;		/* Event polling thread's ID */
+	BOOL bUserLimit;			/* TRUE if user would like to "own" the card. */
 	sharedSegmentMsg msgStruct;		/* Msg sent by the Client */
 	int protocol_major, protocol_minor;	/* Protocol number agreed between client and server*/
 } psContext[PCSCLITE_MAX_APPLICATIONS_CONTEXTS];
@@ -53,8 +60,9 @@
 static DWORD dwNextContextIndex;
 
 LONG MSGCheckHandleAssociation(SCARDHANDLE, DWORD);
+void MSGCheckUserID(SCARDHANDLE, DWORD, DWORD);
 LONG MSGFunctionDemarshall(psharedSegmentMsg, DWORD);
-LONG MSGAddContext(SCARDCONTEXT, DWORD);
+LONG MSGAddContext(SCARDCONTEXT, DWORD, DWORD);
 LONG MSGRemoveContext(SCARDCONTEXT, DWORD);
 LONG MSGAddHandle(SCARDCONTEXT, SCARDHANDLE, DWORD);
 LONG MSGRemoveHandle(SCARDHANDLE, DWORD);
@@ -230,6 +238,7 @@
 LONG MSGFunctionDemarshall(psharedSegmentMsg msgStruct, DWORD dwContextIndex)
 {
 	LONG rv;
+	DWORD dwUserID;
 	establish_struct *esStr;
 	release_struct *reStr;
 	connect_struct *coStr;
@@ -247,6 +256,8 @@
 	 * Zero out everything 
 	 */
 	rv = 0;
+
+	dwUserID = (DWORD)(msgStruct->user_id);
 	switch (msgStruct->command)
 	{
 
@@ -257,7 +268,7 @@
 
 		if (esStr->rv == SCARD_S_SUCCESS)
 			esStr->rv =
-				MSGAddContext(esStr->phContext, dwContextIndex);
+				MSGAddContext(esStr->phContext, esStr->dwScope, dwContextIndex);
 		break;
 
 	case SCARD_RELEASE_CONTEXT:
@@ -338,6 +349,7 @@
 		trStr = ((transmit_struct *) msgStruct->data);
 		rv = MSGCheckHandleAssociation(trStr->hCard, dwContextIndex);
 		if (rv != 0) return rv;
+		MSGCheckUserID(trStr->hCard, dwUserID, dwContextIndex);
 		trStr->rv = SCardTransmit(trStr->hCard, &trStr->pioSendPci,
 			trStr->pbSendBuffer, trStr->cbSendLength,
 			&trStr->pioRecvPci, trStr->pbRecvBuffer,
@@ -348,6 +360,7 @@
 		ctStr = ((control_struct *) msgStruct->data);
 		rv = MSGCheckHandleAssociation(ctStr->hCard, dwContextIndex);
 		if (rv != 0) return rv;
+		MSGCheckUserID(ctStr->hCard, dwUserID, dwContextIndex);
 		ctStr->rv = SCardControl(ctStr->hCard, ctStr->dwControlCode,
 			ctStr->pbSendBuffer, ctStr->cbSendLength,
 			ctStr->pbRecvBuffer, ctStr->cbRecvLength,
@@ -377,9 +390,14 @@
 	return 0;
 }
 
-LONG MSGAddContext(SCARDCONTEXT hContext, DWORD dwContextIndex)
+LONG MSGAddContext(SCARDCONTEXT hContext, DWORD dwScope, DWORD dwContextIndex)
 {
 	psContext[dwContextIndex].hContext = hContext;
+	if (dwScope == SCARD_SCOPE_USER)
+		psContext[dwContextIndex].bUserLimit = TRUE;
+	else
+		psContext[dwContextIndex].bUserLimit = FALSE;
+
 	return SCARD_S_SUCCESS;
 }
 
@@ -497,6 +515,39 @@
 	return -1;
 }
 
+void MSGCheckUserID(SCARDHANDLE hCard, DWORD dwUserID, DWORD dwContextIndex)
+{
+	struct ReaderContext *rContext;
+
+	/*
+	 * Check ownership of the reader
+	 */
+	RFReaderInfoById(hCard, &rContext);	/* TODO -- check return value */
+
+	if (rContext->bOwned && rContext->dwUserID != dwUserID)
+	{
+		/* Reader is owned by a different user.  Reset the card */
+		IFDPowerICC(rContext, IFD_RESET, rContext->readerState->cardAtr,
+					&rContext->readerState->cardAtrLength);
+		
+		if (psContext[dwContextIndex].bUserLimit)
+		{
+			/* This user also wants ownership */
+			rContext->dwUserID = dwUserID;
+		}
+		else
+		{
+			/* This user doesn't care to own the reader, make it unowned */
+			rContext->bOwned = FALSE;
+		}
+	}
+	else if (!rContext->bOwned && psContext[dwContextIndex].bUserLimit)
+	{
+		rContext->dwUserID = dwUserID;
+		rContext->bOwned = TRUE;
+	}
+}
+		
 LONG MSGCleanupClient(DWORD dwContextIndex)
 {
 	if (psContext[dwContextIndex].hContext != 0)
Index: PCSC/src/readerfactory.c
===================================================================
--- PCSC/src/readerfactory.c	(revision 1969)
+++ PCSC/src/readerfactory.c	(working copy)
@@ -170,6 +170,7 @@
 	(sReadersContexts[dwContext])->vHandle = 0;
 	(sReadersContexts[dwContext])->pdwFeeds = NULL;
 	(sReadersContexts[dwContext])->pdwMutex = NULL;
+	(sReadersContexts[dwContext])->bOwned = FALSE;
 	(sReadersContexts[dwContext])->dwIdentity =
 		(dwContext + 1) << (sizeof(DWORD) / 2) * 8;
 	(sReadersContexts[dwContext])->readerState = NULL;
@@ -387,6 +388,7 @@
 		(sReadersContexts[dwContextB])->dwContexts = 0;
 		(sReadersContexts[dwContextB])->dwLockId = 0;
 		(sReadersContexts[dwContextB])->readerState = NULL;
+		(sReadersContexts[dwContextB])->bOwned = FALSE;
 		(sReadersContexts[dwContextB])->dwIdentity =
 			(dwContextB + 1) << (sizeof(DWORD) / 2) * 8;
 
@@ -534,6 +536,7 @@
 		sContext->dwSlot = 0;
 		sContext->dwLockId = 0;
 		sContext->vHandle = 0;
+		sContext->bOwned = FALSE;
 		sContext->dwIdentity = 0;
 		sContext->readerState = NULL;
 
_______________________________________________
Muscle mailing list
[email protected]
http://lists.drizzle.com/mailman/listinfo/muscle

Reply via email to