From: <jda...@us...> - 2010-08-18 13:40:58
|
Revision: 509 http://pyscard.svn.sourceforge.net/pyscard/?rev=509&view=rev Author: jdaussel Date: 2010-08-18 13:40:51 +0000 (Wed, 18 Aug 2010) Log Message: ----------- Added partial support of remote pcsc readers with pyro Added Paths: ----------- trunk/pyscard/src/smartcard/pyro/ trunk/pyscard/src/smartcard/pyro/PyroReader.py trunk/pyscard/src/smartcard/pyro/__init__.py trunk/pyscard/src/smartcard/pyro/server/ trunk/pyscard/src/smartcard/pyro/server/PyroDaemon.py trunk/pyscard/src/smartcard/pyro/server/PyroEventServer.py trunk/pyscard/src/smartcard/pyro/server/PyroNameServer.py trunk/pyscard/src/smartcard/pyro/server/RemoteCardConnection.py trunk/pyscard/src/smartcard/pyro/server/RemoteReaderServer.py trunk/pyscard/src/smartcard/pyro/server/__init__.py Added: trunk/pyscard/src/smartcard/pyro/PyroReader.py =================================================================== --- trunk/pyscard/src/smartcard/pyro/PyroReader.py (rev 0) +++ trunk/pyscard/src/smartcard/pyro/PyroReader.py 2010-08-18 13:40:51 UTC (rev 509) @@ -0,0 +1,90 @@ +"""PyroReaderClient: concrete reader class for Remote Readers + +__author__ = "gemalto http://www.gemalto.com" + +Copyright 2001-2010 gemalto +Author: Jean-Daniel Aussel, mailto:jea...@ge... + +This file is part of pyscard. + +pyscard is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +pyscard is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with pyscard; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + +import Pyro.core +import Pyro.naming + +from smartcard.Exceptions import CardConnectionException, NoCardException +from smartcard.reader.Reader import Reader +from smartcard.reader.ReaderFactory import ReaderFactory + +class PyroReader(Reader): + """Remote reader class.""" + def __init__( self, readername ): + """Constructs a new Remote Reader client implementation from a Pyro URI.""" + ns=Pyro.naming.NameServerLocator().getNS() + self.uri = ns.resolve(':pyscard.smartcard.readers.'+readername) + self.reader = Pyro.core.getAttrProxyForURI(self.uri) + self.name = self.reader.name + + def addtoreadergroup( self, groupname ): + """Add reader to a reader group.""" + self.reader.addtoreadergroup( groupname ) + + def removefromreadergroup( self, groupname ): + """Remove a reader from a reader group""" + self.reader.removefromreadergroup( groupname ) + + def createConnection( self ): + """Return a card connection thru a remote reader.""" + uri = self.reader.createConnection() + return Pyro.core.getAttrProxyForURI(uri) + + class Factory: + def create(readername): + return PyroReader( readername ) + create = staticmethod(create) + + def readers(groups=[]): + readernames = [] + try: + ns=Pyro.naming.NameServerLocator().getNS() + readernames = ns.list(':pyscard.smartcard.readers') + except Pyro.errors.NamingError: + print 'Warning: pyro name server not found' + + remotereaders=[] + for readername in readernames: + remotereaders.append( PyroReader.Factory.create(readername[0]) ) + + return remotereaders + readers = staticmethod(readers) + +if __name__ == '__main__': + SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] + DF_TELECOM = [0x7F, 0x10] + from smartcard.util import * + + remotereaders = PyroReader.readers() + for reader in remotereaders: + try: + print reader.name, ', uri: ', reader.uri + connection = reader.createConnection() + connection.connect() + print toHexString( connection.getATR() ) + data, sw1, sw2 = connection.transmit(SELECT + DF_TELECOM) + print "%X %X" % (sw1, sw2) + except NoCardException,x: + print 'no card in reader' + Added: trunk/pyscard/src/smartcard/pyro/__init__.py =================================================================== --- trunk/pyscard/src/smartcard/pyro/__init__.py (rev 0) +++ trunk/pyscard/src/smartcard/pyro/__init__.py 2010-08-18 13:40:51 UTC (rev 509) @@ -0,0 +1 @@ + Added: trunk/pyscard/src/smartcard/pyro/server/PyroDaemon.py =================================================================== --- trunk/pyscard/src/smartcard/pyro/server/PyroDaemon.py (rev 0) +++ trunk/pyscard/src/smartcard/pyro/server/PyroDaemon.py 2010-08-18 13:40:51 UTC (rev 509) @@ -0,0 +1,92 @@ +"""PyroDaemon: Wrapper class around pyro daemon + +__author__ = "gemalto http://www.gemalto.com" + +Copyright 2001-2010 gemalto +Author: Jean-Daniel Aussel, mailto:jea...@ge... + +This file is part of pyscard. + +pyscard is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +pyscard is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with pyscard; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + +import signal +from threading import Thread +import time + +import Pyro.core +import Pyro.naming + +class PyroDaemon: + """Singleton class to wrap the pyro daemon.""" + + class _PyroDaemon: + """The pyro daemon actual wrapper class. + + A single instance of this class is created + by the public PyroDaemon class. + """ + def __init__(self): + self.daemon = Pyro.core.Daemon() + self.handler = signal.signal( signal.SIGINT, self ) + ns=Pyro.naming.NameServerLocator().getNS() + self.daemon.useNameServer(ns) + + def __call__(self, signame, sf): + """Ctrl+c handler that will gracefully shutdown the server + upon Ctrl+C signal""" + print 'PyroDaemon Ctrl+C handler' + self.daemon.shutdown(True) + time.sleep(1) + self.handler( signame, sf ) + + def connect(self,object,name=None): + return self.daemon.connect(object,name) + + def disconnect(self,object): + return self.daemon.disconnect(object) + + def start(self): + """start pyro daemon.""" + self.daemon.requestLoop() + + # the singleton + instance = None + + def __init__(self): + if not PyroDaemon.instance: + PyroDaemon.instance = PyroDaemon._PyroDaemon() + + def __getattr__( self, name ): + return getattr( self.instance, name ) + +class PyroDaemonThread(Thread): + """Thread running the Pyro daemon server. + """ + + def __init__(self): + """Initialize pyro event server with command line arguments. + For a complete list of command line arguments, see pyro documentation + for pyro-es start script.""" + Thread.__init__( self ) + self.setDaemon( True ) + self.setName( 'smartcard.pyro.server.PyroDaemonThread' ) + self.daemon = PyroDaemon() + + def run(self): + """Starts Pyro daemon.""" + self.daemon.start() + + Added: trunk/pyscard/src/smartcard/pyro/server/PyroEventServer.py =================================================================== --- trunk/pyscard/src/smartcard/pyro/server/PyroEventServer.py (rev 0) +++ trunk/pyscard/src/smartcard/pyro/server/PyroEventServer.py 2010-08-18 13:40:51 UTC (rev 509) @@ -0,0 +1,103 @@ +"""Utility class to start/stop Pyro Event Server. + +__author__ = "http://www.gemalto.com" + +Copyright 2001-2010 gemalto +Author: Jean-Daniel Aussel, mailto:jea...@ge... + +This file is part of pyscard. + +pyscard is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +pyscard is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with pyscard; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + +import signal +import sys +from threading import Thread +import time + +import Pyro.EventService.Server +import Pyro.naming +import Pyro.nsc +import Pyro.util + +class PyroEventServer(Thread): + """Thread running the Pyro Event server. + """ + + def __init__(self,args=[]): + """Initialize pyro event server with command line arguments. + For a complete list of command line arguments, see pyro documentation + for pyro-es start script.""" + Thread.__init__( self ) + self.setDaemon( True ) + self.setName( 'smartcard.pyro.server.PyroEventServer' ) + self.args = args + self.handler = signal.signal( signal.SIGINT, self ) + self.starter = None + + def run(self): + """Starts Pyro naming server with command line arguments (see pyro documentation) + """ + args=[] + for arg in self.args: args.append(arg) + Args = Pyro.util.ArgParser() + Args.parse(args,'hkmrvxn:p:b:c:d:s:i:1:2:') + + hostname = Args.getOpt('n',None) + identification = Args.getOpt('i',None) + port = None + useNameServer = True + + if port: + port=int(port) + norange = (port==0) + + self.starter = Pyro.EventService.Server.EventServiceStarter(identification=identification) + self.starter.start(hostname,port,useNameServer=useNameServer,norange=norange) + + def stop(self): + """Shutdown pyro event server.""" + pass + + def waitStarted(self): + """wait until name server is started.""" + started = False + while not started: + if self.starter!=None: + started = self.starter.waitUntilStarted(0.5) + + def __call__(self, signame, sf): + """Ctrl+c handler that will gracefully shutdown the server + upon Ctrl+C signal""" + print 'PyroEventServer Ctrl+C handler' + self.stop() + time.sleep(1) + self.handler( signame, sf ) + + +if __name__ == '__main__': + import sys + from smartcard.pyro.server.PyroNameServer import PyroNameServer + pn = PyroNameServer(sys.argv[1:]) + pn.start() + pn.waitStarted() + pe = PyroEventServer(sys.argv[1:]) + pe.start() + pe.waitStarted() + pn.listall() + pe.stop() + pn.stop() + + Added: trunk/pyscard/src/smartcard/pyro/server/PyroNameServer.py =================================================================== --- trunk/pyscard/src/smartcard/pyro/server/PyroNameServer.py (rev 0) +++ trunk/pyscard/src/smartcard/pyro/server/PyroNameServer.py 2010-08-18 13:40:51 UTC (rev 509) @@ -0,0 +1,118 @@ +"""Utility class to start/stop Pyro Name Server. + +__author__ = "http://www.gemalto.com" + +Copyright 2001-2010 gemalto +Author: Jean-Daniel Aussel, mailto:jea...@ge... + +This file is part of pyscard. + +pyscard is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +pyscard is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with pyscard; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + +import signal +import sys +from threading import Thread +import time + +import Pyro.naming +import Pyro.nsc +import Pyro.util + +class PyroNameServer(Thread): + """Thread running the Pyro Name server. + """ + + def __init__(self,args=[]): + """Initialize pyro name server with command line arguments. + For a complete list of command line arguments, see pyro documentation + for pyro-ns start script.""" + Thread.__init__( self ) + self.setDaemon( True ) + self.setName( 'smartcard.pyro.server.PyroNameServer' ) + self.args = args + self.handler = signal.signal( signal.SIGINT, self ) + + _args=[] + for arg in self.args: _args.append(arg) + Args = Pyro.util.ArgParser() + Args.parse(_args,'hkmrvxn:p:b:c:d:s:i:1:2:') + self.host = Args.getOpt('n',None) + self.bcport = Args.getOpt('b',None) + self.bcaddr = Args.getOpt('c',None) + self.identification = Args.getOpt('i',None) + + def getShutdownArgs(self): + """return command line arguments for shutting down the + server; this command line is built from the name server + startup arguments.""" + shutdownArgs = [] + if self.host: shutdownArgs += [ '-h', self.host ] + if self.bcport: shutdownArgs += [ '-p', self.bcport ] + if self.bcaddr: shutdownArgs += [ '-c', self.bcaddr ] + if self.identification: shutdownArgs += [ '-i', self.identification ] + + return shutdownArgs + + def listall(self): + """List pyro namespace.""" + args = self.getShutdownArgs() + ['listall'] + Pyro.nsc.main( args ) + + def ping(self): + """Ping pyro naming server.""" + args = self.getShutdownArgs() + ['ping'] + Pyro.nsc.main( args ) + + def run(self): + """Starts Pyro naming server with command line arguments (see pyro documentation) + """ + args=[] + for arg in self.args: args.append(arg) + Pyro.naming.main( args ) + + def stop(self): + """Shutdown pyro naming server.""" + args = self.getShutdownArgs() + ['shutdown'] + Pyro.nsc.main( args ) + self.join() + + def waitStarted(self): + """wait until name server is started.""" + ns = None + while not ns: + try: + time.sleep(3) + ns=Pyro.naming.NameServerLocator(identification=self.identification).getNS() + except Pyro.errors.NamingError as er: + pass + + def __call__(self, signame, sf): + """Ctrl+c handler that will gracefully shutdown the server + upon Ctrl+C signal""" + print 'PyroNameServer Ctrl+C handler' + self.stop() + time.sleep(1) + self.handler( signame, sf ) + + +if __name__ == '__main__': + import sys + pt = PyroNameServer( sys.argv[1:] ) + pt.start() + pt.waitStarted() + pt.stop() + + Added: trunk/pyscard/src/smartcard/pyro/server/RemoteCardConnection.py =================================================================== --- trunk/pyscard/src/smartcard/pyro/server/RemoteCardConnection.py (rev 0) +++ trunk/pyscard/src/smartcard/pyro/server/RemoteCardConnection.py 2010-08-18 13:40:51 UTC (rev 509) @@ -0,0 +1,44 @@ +"""RemoteCardConnection class manages connections to a remote reader +thru pyro (http://www.xs4all.nl/~irmen/pyro3/). + +__author__ = "http://www.gemalto.com" + +Copyright 2001-2010 gemalto +Author: Jean-Daniel Aussel, mailto:jea...@ge... + +This file is part of pyscard. + +pyscard is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +pyscard is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with pyscard; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + +import Pyro.core +import Pyro.naming + +from smartcard.CardConnection import CardConnection +from smartcard.CardConnectionDecorator import CardConnectionDecorator +from smartcard.Exceptions import CardConnectionException, NoCardException +from smartcard.Observer import Observable + +class RemoteCardConnection(CardConnectionDecorator,Pyro.core.ObjBase): + """Remote connection class. Handles connection with a card inserted inside a remote PC.""" + + def __init__(self, cardConnectionComponent): + """Construct a new remote card connection. + + connection: the reader connection + """ + Pyro.core.ObjBase.__init__(self) + CardConnectionDecorator.__init__( self, cardConnectionComponent ) + Added: trunk/pyscard/src/smartcard/pyro/server/RemoteReaderServer.py =================================================================== --- trunk/pyscard/src/smartcard/pyro/server/RemoteReaderServer.py (rev 0) +++ trunk/pyscard/src/smartcard/pyro/server/RemoteReaderServer.py 2010-08-18 13:40:51 UTC (rev 509) @@ -0,0 +1,121 @@ +"""RemoteReaderServer: monitor local readers and publish them as pyro +Remote Readers. + +__author__ = "gemalto http://www.gemalto.com" + +Copyright 2001-2010 gemalto +Author: Jean-Daniel Aussel, mailto:jea...@ge... + +This file is part of pyscard. + +pyscard is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +pyscard is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with pyscard; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + +try: + import Pyro.core + import Pyro.naming +except: + print 'You need pyro (python remote objects) at http://www.xs4all.nl/~irmen/pyro3/' + import sys + sys.exit() + +import signal +import time + +import smartcard.System +from smartcard.reader.Reader import Reader +from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver +from smartcard.pyro.server.RemoteCardConnection import RemoteCardConnection +from smartcard.pyro.server import PyroDaemon +from smartcard.pyro.server import PyroNameServer + +class RemoteReader(Reader,Pyro.core.ObjBase): + """Remote reader class that embeds a local reader.""" + + def __init__(self,reader): + """Encapsulate a local reader and publish as a pyro remote reader. + + reader: the local reader to publish remotely + """ + Pyro.core.ObjBase.__init__(self) + self.readerobj = reader + self.name = reader.name + + def addtoreadergroup( self, groupname ): + """Add reader to a reader group.""" + self.readerobj.reader.addtoreadergroup( groupname ) + + def removefromreadergroup( self, groupname ): + """Remove a reader from a reader group""" + self.readerobj.reader.removefromreadergroup( groupname ) + + def createConnection( self ): + """Return a card connection thru the reader.""" + connection = RemoteCardConnection( self.readerobj.createConnection() ) + daemon = PyroDaemon.PyroDaemon() + uri = daemon.connect(connection) + return uri + + + +class RemoteReaderServer(ReaderObserver): + """Monitor local readers, and publish them as remote pyro readers. + """ + def __init__(self): + """Starts pyro name server and constructs reader name space.""" + self.pn = PyroNameServer.PyroNameServer() + self.pn.start() + self.pn.waitStarted() + + Pyro.core.initServer() + self.ns=Pyro.naming.NameServerLocator().getNS() + try: + self.ns.createGroup(':pyscard') + self.ns.createGroup(':pyscard.smartcard') + self.ns.createGroup(':pyscard.smartcard.readers') + except Pyro.errors.NamingError as error: + print error + self.daemon = PyroDaemon.PyroDaemon() + self.remotereaders = {} + + def start(self): + """Start pyro daemon and accept incoming requests.""" + self.daemon.start() + + + def update(self, observable, (addedreaders, removedreaders)): + """Called when a local reader is added or removed. + Create remote pyro reader objects for added readers. + Delete remote pyro reader objects for removed readers.""" + for reader in addedreaders: + remotereader = RemoteReader(reader) + self.remotereaders[reader.name] = remotereader + name = "".join(reader.name.split(' ')) + name = ":pyscard.smartcard.readers."+"".join(name.split('.')) + uri = self.daemon.connect(remotereader,name) + for reader in removedreaders: + remotereader = self.remotereaders[reader.name] + self.daemon.disconnect(remotereader) + del self.remotereaders[reader.name] + self.pn.listall() + + +if __name__ == '__main__': + readerserver = RemoteReaderServer() + readermonitor = ReaderMonitor() + readermonitor.addObserver(readerserver) + print 'Reader remote server up and running', + print 'Please enter Ctrl+C to stop and exit...' + readerserver.start() Added: trunk/pyscard/src/smartcard/pyro/server/__init__.py =================================================================== --- trunk/pyscard/src/smartcard/pyro/server/__init__.py (rev 0) +++ trunk/pyscard/src/smartcard/pyro/server/__init__.py 2010-08-18 13:40:51 UTC (rev 509) @@ -0,0 +1 @@ + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |