From 8efb2f81a22aee3aac4e38e385a80322cae53635 Mon Sep 17 00:00:00 2001 From: frankmorgner Date: Sat, 9 Oct 2010 13:33:32 +0000 Subject: [PATCH] - added more error handling to RelayOS - vicc in relay mode terminates when card is removed - created cleanup routines to use with atexit.register git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@309 96b47cad-a561-4643-ad3b-153ac7d7599c --- .../src/vpicc/VirtualSmartcard.py | 82 ++++++++++++------- 1 file changed, 54 insertions(+), 28 deletions(-) diff --git a/virtualsmartcard/src/vpicc/VirtualSmartcard.py b/virtualsmartcard/src/vpicc/VirtualSmartcard.py index 8116d1e..68f49af 100644 --- a/virtualsmartcard/src/vpicc/VirtualSmartcard.py +++ b/virtualsmartcard/src/vpicc/VirtualSmartcard.py @@ -23,13 +23,14 @@ from SmartcardFilesystem import prettyprint_anything, MF, DF, CryptoflexMF, Tran from utils import C_APDU, R_APDU, hexdump, inttostring from SmartcardSAM import SAM, PassportSAM, CryptoflexSAM import CardGenerator +from smartcard.CardMonitoring import CardMonitor, CardObserver from pickle import dumps, loads import socket, struct, sys, signal, atexit, traceback import struct, getpass, anydbm -class SmartcardOS(object): +class SmartcardOS(object): # {{{ """Base class for a smart card OS""" mf = make_property("mf", "master file") @@ -57,6 +58,7 @@ class SmartcardOS(object): msg -- the APDU as string of characters """ return "" +# }}} class Iso7816OS(SmartcardOS): # {{{ def __init__(self, mf, sam, ins2handler=None, maxle=MAX_SHORT_LE): @@ -363,24 +365,51 @@ class CryptoflexOS(Iso7816OS): # {{{ return r # }}} -class RelayOS(SmartcardOS): # {{{ +class RelayOS(SmartcardOS): # {{{ + + import smartcard + class RelayCardObserver(smartcard.CardMonitoring.CardObserver): # {{{ + + def __init__(self, relayos): + self.os = relayos + + def update(self, observable, (addedcards, removedcards)): + for removed in removedcards: + if removed.reader == self.os.reader: + if removed.atr == self.os.atr: + print "Card removed from %s. Terminating." % self.os.reader + sys.exit() + # }}} + + def __init__(self, readernum): import smartcard + readers = smartcard.System.listReaders() + if len(readers) <= readernum: + print "Invalid number of reader '%u' (only %u available)" % (readernum, len(readers)) + sys.exit() + # XXX this is a workaround, see on sourceforge bug #3083254 + # should better use + # self.reader = smartcard.System.readers()[readernum] + self.reader = readers[readernum] + try: + self.session = smartcard.Session(self.reader) + except smartcard.Exceptions.CardConnectionException, e: + print "Could not connect to card: %s" % str(e) + sys.exit() + self.atr = self.session.getATR() + self.cm = CardMonitor() + self.cm.addObserver(RelayOS.RelayCardObserver(self)) - if readernum: - # XXX this is a workaround, see on sourceforge bug #3083254 - # should better use - # self.reader = smartcard.System.readers()[readernum] - self.reader = smartcard.System.listReaders()[readernum] - else: - self.reader = None + print "Connected to card in %s" % self.session.readerName - self.session = smartcard.Session(self.reader) + atexit.register(self.stop) - print "Connected to %s" % self.session.readerName + def stop(self): + self.session.close() def getATR(self): - return "".join([chr(b) for b in self.session.getATR()]) + return "".join([chr(b) for b in self.atr]) def powerUp(self): import smartcard @@ -388,13 +417,10 @@ class RelayOS(SmartcardOS): # {{{ self.session.getATR() except smartcard.Exceptions.CardConnectionException: self.session = smartcard.Session(self.reader) + self.atr = self.session.getATR() def powerDown(self): - import smartcard - try: - self.session.close() - except smartcard.Exceptions.CardConnectionException: - pass + self.session.close() def execute(self, msg): #apdu = [].append(ord(b) for b in msg) @@ -437,14 +463,12 @@ class VirtualICC(object): # {{{ self.cardGenerator = CardGenerator.CardGenerator(type) #If a filename is specified, try to load the card from disk - if filename == None: - print "No filename specified. The card will not be safed!" - else: + if filename != None: self.filename = filename if exists(filename): self.cardGenerator.loadCard(self.filename) else: - print "No file " + self.filename + " found. Will create new file at termination of program." + print "Creating new card which will be saved in %s." % self.filename MF, SAM = self.cardGenerator.getCard() @@ -466,19 +490,15 @@ class VirtualICC(object): # {{{ self.sock = self.connectToPort(host, port) self.sock.settimeout(None) except socket.error, e: - print "Failed to open socket: " + str(e) + ". Is pcscd running? Is vpcd installed?" + print "Failed to open socket: " + str(e) + ". Is pcscd running? Is vpcd loaded?" sys.exit() self.lenlen = lenlen + signal.signal(signal.SIGINT, self.signalHandler) - #atexit.register(self.signalHandler) - #atexit.register(saveCard) + atexit.register(self.stop) def signalHandler(self, signal=None, frame=None): - self.sock.close() - if self.filename != None: - self.cardGenerator.setCard(self.os.mf, self.os.SAM) - self.cardGenerator.saveCard(self.filename) sys.exit() @staticmethod @@ -526,6 +546,12 @@ class VirtualICC(object): # {{{ answer = self.os.execute(msg) print "RESP (%d Bytes):\n%s\n" % (len(answer),hexdump(answer, short=True)) self.__sendToVPICC(answer) + + def stop(self): + self.sock.close() + if self.filename != None: + self.cardGenerator.setCard(self.os.mf, self.os.SAM) + self.cardGenerator.saveCard(self.filename) # }}} if __name__ == "__main__":