pyscard-1.6.14/0000755000175000017500000000000011747777125015030 5ustar rousseaurousseau00000000000000pyscard-1.6.14/MANIFEST.in0000644000175000017500000000201011255421436016540 0ustar rousseaurousseau00000000000000include LICENSE include MANIFEST.in include README include smartcard/ACKS include smartcard/ChangeLog include smartcard/LICENSE include smartcard/README include smartcard/TODO include smartcard/scard/gemalto.ver include smartcard/scard/helpers.c include smartcard/scard/helpers.h include smartcard/scard/memlog.h include smartcard/scard/pcsctypes.h include smartcard/scard/PcscDefs.i include smartcard/scard/PcscTypemaps.i include smartcard/scard/pyscard-reader.h include smartcard/scard/scard.def include smartcard/scard/scard.i include smartcard/scard/scard.rc include smartcard/scard/winscarddll.c include smartcard/scard/winscarddll.h recursive-include smartcard/wx *.ico recursive-include smartcard/Examples *.txt *.py *.ico include smartcard/test/configcheck.py recursive-include smartcard/test/framework *.txt *.py recursive-include smartcard/test/frameworkpcsc *.txt *.py recursive-include smartcard/test/scard *.txt *.py recursive-include smartcard/doc *.html *.jpg *.css *.js *.png *.txt pyscard-1.6.14/README0000644000175000017500000003615711747776700015722 0ustar rousseaurousseau00000000000000------------------------------------------------------------------------------- pyscard smartcard library for python ------------------------------------------------------------------------------- http://pyscard.sourceforge.net/ ------------------------------------------------------------------------------- Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 ------------------------------------------------------------------------------- Last update : pyscard 1.6.14 (April 2012) ------------------------------------------------------------------------------- pyscard is a python module adding smart cards support to python. It consists of the smartcard.scard module, an extension module wrapping Windows smart card base components (also known as PCSC) on Windows, and PCSC lite on linux and Mac OS X Tiger, and of the smartcard module, a python framework with objects wrapping PCSC API. ------------------------------------------------------------------------------- Documentation ------------------------------------------------------------------------------- All documentation is provided in the smartcard/doc directory of the source distribution. Examples are provided in the smartcard/Examples directory of the source distribution. The binary distribution does not include any documentation, tests scripts or examples. ------------------------------------------------------------------------------- Installation ------------------------------------------------------------------------------- The pyscard library is packaged using the standard distutils python module. Installation on windows ----------------------- Installing on windows from the binary distribution -------------------------------------------------- 1. download the binary msi installer or self-executable installer 2. execute the installer The binary msi installer and self-executable installer are packaged for a specific version of python, and have name similar to pyscard-1.6.14.win32-py2.5.msi and pyscard-1.6.14.win32-py2.5.exe for python 2.5. Installing on windows from the source distribution --------------------------------------------------- 1. you will need swig 1.3.31 from http://www.swig.org, and a C compiler. By default, Visual Studio 2003 is required for building the c language wrapper for python 2.5, and Visual Studio .Net or VisualC++ 6 for python 2.4. You might use another release by fiddling with the python/Lib/distutils/msvccompiler.py file that detects the compiler. 2. download the source distribution The source distribution is available as pyscard-1.6.14.zip for windows, and pyscard-1.6.14.tar.gz for linux. 3. unzip the source distribution, open a console and type the following: setup.py build_ext install This will build pyscard and install it in the site-packages directory of your python distribution, e.g. c:\python25\Lib\site-packages\smartcard. This install procedure does not install the documentation, examples or test files. Installation on linux: ---------------------- Installing on linux from the binary distribution: ------------------------------------------------- 1. download the binary distribution The binary distribution is either an archive file or a rpm file, with names similar to pyscard-1.6.14-1.i386.rpm for the rpm distribution, or pyscard-1.6.14.linux-i686.tar.gz for the archive distribution. 2. untar the binary distribution With root privilege from a terminal, extract the archive from /, or install the rpm. Installing on linux from the source distribution ------------------------------------------------ 1. you will need gcc, swig 1.3.31 (http://www.swig.org), and pcsc-lite (http://pcsclite.alioth.debian.org/) 2. download the source distribution The source distribution is available as pyscard-1.6.14.zip or pyscard-1.6.14.tar.gz. 3. untar the source distribution 4. from a terminal with root privileges, type the following: /usr/bin/python setup.py build_ext install This will build pyscard and install it in the site-packages directory of your python distribution, e.g. /usr/lib/python2.4/site-packages/smartcard. Installation on Max OS X Tiger: -------------------------------- The Mac OS X Tiger support is experimental on pyscard 1.6.14. It was developed and tested on a i386 MacBook Pro. Please drop me a mail if you succeed on a ppc MacBook. Installing on Mac OS X Tiger from the binary distribution: ---------------------------------------------------- 1. download the binary distribution The binary distribution is an archive file, with a name similar to pyscard-1.6.14-py-2.3-macosx10.4.mpkg or pyscard-1.6.14-py-2.5-macosx10.4.mpkg. 2. Open the package and proceed with installation. Python 2.3 is pre-installed, so install pyscard-1.6.14-py-2.3-macosx10.4.mpkg if you did not install another release of python. Install pyscard-1.6.14-py-2.5-macosx10.4.mpkg if you installed python 2.5. Installing on Mac OS X Tiger from the source distribution ---------------------------------------------------------- 1. you will need swig 1.3.31 (http://www.swig.org); gcc and pcsc-lite are available out of the box on Max OS X Tiger 2. download the source distribution The source distribution is available as pyscard-1.6.14.zip or pyscard-1.6.14.tar.gz. 3. untar or unzip the source distribution 4. from a terminal, type the following: sudo python setup.py build_ext install This will build pyscard and install it in the site-packages directory of your python distribution, e.g. /System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/lib/site-packages/smartcard Installation on Max OS X Leopard: --------------------------------- Installing on Mac OS X Leopard from the binary distribution: ---------------------------------------------------- 1. download the binary distribution The binary distribution is an archive file, with a name similar to pyscard-1.6.14-py-2.5-macosx10.5.mpkg. 2. Open the package and proceed with installation. Installing on Mac OS X Leopard from the source distribution ------------------------------------------------------------ 1. you will need swig 1.3.31 (http://www.swig.org); gcc and pcsc-lite are available out of the box on Max OS X Leopard 2. download the source distribution The source distribution is available as pyscard-1.6.14.zip or pyscard-1.6.14.tar.gz. 3. untar or unzip the source distribution 4. from a terminal, type the following: sudo python setup.py build_ext install This will build pyscard and install it in the site-packages directory of your python distribution, e.g. /System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.3/lib/site-packages/smartcard Installation on Max OS X Lion: ------------------------------ Installing on Mac OS X Lion from the binary distribution: ---------------------------=====------------------------- 1. download the binary distribution The binary distribution is an archive file, with a name similar to pyscard-1.6.14-py-2.7-macosx10.7.mpkg. 2. Open the package and proceed with installation. Installing on Mac OS X Lion from the source distribution -------------------------------------------------------- 1. you will need swig 2.0.4 (http://www.swig.org) and Xcode (http://developer.apple.com/xcode/); pcsc-lite is available out of the box on Max OS X Leopard 2. download the source distribution The source distribution is available as pyscard-1.6.14.zip or pyscard-1.6.14.tar.gz. 3. untar or unzip the source distribution 4. from a terminal, type the following: sudo python setup.py build_ext install This will build pyscard and install it in the site-packages directory of your python distribution, e.g. /Library/Python/2.7/lib/site-packages/smartcard ------------------------------------------------------------------------------- Developer documentation, unit tests and examples ------------------------------------------------------------------------------- The developer documentation is in the smartcard/doc directory of the source distribution. Examples are located in the smartcard/Examples directory, and the pyunit unit tests in the smartcard/test directory. ------------------------------------------------------------------------------- Build instructions for packagers ------------------------------------------------------------------------------- Building a binary distribution for Windows ------------------------------------------ To build a binary distribution from the source distribution, you will need a C compiler and swig 1.3.31 (same requirements as for installing from the source distribution). In the root directory of the source distribution, execute the following command in a console: setup.py build_ext bdist_msi setup.py build_ext bdist_wininst This will build the msi installer and self-executable installer in the dist directory, with names similar to pyscard-1.6.14.win32-py2.5.msi and pyscard-1.6.14.win32-py2.5.exe for python 2.5, and pyscard-1.6.14.win32-py2.4.msi and pyscard-1.6.14.win32-py2.4.exe for python 2.4. Building a binary distribution for linux ---------------------------------------- To build a binary distribution from the source distribution, you will need gcc, swig 1.3.31 and pcsc-lite (same requirements as for installing from the source distribution). In the root directory of the source distribution, execute the following command in a terminal: /usr/bin/python setup.py build_ext bdist This will build a package similar to pyscard-1.6.14.linux-i686.tar.gz containing a tree Building a rpm distribution for linux ---------------------------------------- To build a rpm distribution from the source distribution, you will need gcc, swig 1.3.31 and pcsc-lite (same requirements as for installing from the source distribution). In the root directory of the source distribution, execute the following command in a terminal: /usr/bin/python setup.py build bdist_rpm If you have rpm 4.1 or above, you will need to add the %_unpackaged_files_terminate_build 0 options to the /etc/rpm/macros file, e.g.: echo "%_unpackaged_files_terminate_build 0" >> /etc/rpm/macros This will build in the dist directory a binary distribution with a name similar to pyscard-1.6.14-1.i386.rpm. Building a binary distribution for Mac OS X Tiger ------------------------------------------------- To build a binary distribution from the source distribution, you will need swig 1.3.31 (same requirements as for installing from the source distribution) and bdist_mpkg 0.4.3 (http://cheeseshop.python.org/pypi/bdist_mpkg/). If you are using the pre-installed python 2.3 distribution, in the root directory of the source distribution, i.e. in the src directory, execute the following commands in a terminal: python setup.py build_ext /System/Library/Frameworks/Python.Framework/Versions/2.3/bin/bdist_mpkg setup.py This will build package pyscard-1.6.14-py-2.3-macosx10.4.mpkg. If you are using python 2.5, in the root directory of the source distribution, i.e. in the src directory, execute the following commands in a terminal: python setup.py build_ext /Library/Frameworks/Python.Framework/Versions/2.5/bin/bdist_mpkg setup.py This will build package pyscard-1.6.14-py-2.6-macosx10.4.mpkg. Building a binary distribution for Mac OS X Lion ------------------------------------------------- To build a binary distribution from the source distribution, you will need swig 2.0.4 and Xcode (same requirements as for installing from the source distribution) and bdist_mpkg 0.4.4 (http://pypi.python.org/pypi/bdist_mpkg/). Install bdist_mpkg by executing the bdist_mpkg setup.py script with build and install as arguments, i.e. from the root directory of the bdist_mpkg source distribution enter: python setup.py build install. From the root directory of the pyscard source distribution, i.e. in the src directory, execute the following commands in a terminal: python setup.py build_ext bdist_mpkg setup.py This will build package pyscard-1.6.14-py-2.7-macosx10.7.mpkg in the dist directory. Building a binary distribution for Mac OS X Leopard --------------------------------------------------- To build a binary distribution from the source distribution, you will need swig 1.3.31 (same requirements as for installing from the source distribution) and bdist_mpkg 0.4.3 (http://cheeseshop.python.org/pypi/bdist_mpkg/). Apply the following patch to tools.py of bdist_mpkg package: ===== patch start === diff -rNu bdist_mpkg-0.4.3/bdist_mpkg/tools.py bdist_mpkg-0.4.3.leopard/bdist_mpkg/tools.py --- bdist_mpkg-0.4.3/bdist_mpkg/tools.py 2006-07-09 00:39:00.000000000 -0400 +++ bdist_mpkg-0.4.3.leopard/bdist_mpkg/tools.py 2008-08-21 07:43:35.000000000 -0400 @@ -79,15 +79,12 @@ yield os.path.join(root, fn) def get_gid(name, _cache={}): - if not _cache: - for line in os.popen('/usr/bin/nidump group .'): - fields = line.split(':') - if len(fields) >= 3: - _cache[fields[0]] = int(fields[2]) - try: - return _cache[name] - except KeyError: - raise ValueError('group %s not found' % (name,)) + for line in os.popen("dscl . -read /Groups/" + name + " PrimaryGroupID"): + fields = [f.strip() for f in line.split(':')] + if fields[0] == "PrimaryGroupID": + return fields[1] + + raise ValueError('group %s not found' % (name,)) ===== patch end ======== This patch is required since Mac OS X Leopard does not have the nidump command any more. Install bdist_mpkg by executing the bdist_mpkg setup.py script with build and install as arguments, i.e. from the root directory of the bdist_mpkg source distribution enter: python setup.py build install. For python 2.5, from the root directory of the pyscard source distribution, i.e. in the src directory, execute the following commands in a terminal: python setup.py build_ext /Library/Frameworks/Python.Framework/Versions/2.5/Extras/bin/bdist_mpkg setup.py This will build package pyscard-1.6.14-py-2.5-macosx10.5.mpkg. For python 2.6, from the root directory of the pyscard source distribution, i.e. in the src directory, execute the following commands in a terminal: python setup.py build_ext /Library/Frameworks/Python.framework/Versions/2.6/bin/bdist_mpkg setup.py This will build package pyscard-1.6.14-py-2.6-macosx10.5.mpkg. ------------------------------------------------------------------------------- Issue Tracking ------------------------------------------------------------------------------- If you encounter a bug, please report it in the SourceForge bug tracker at http://sourceforge.net/tracker/?group_id=196342&atid=957072 https://sourceforge.net/tracker/?group_id=196342&atid=957072 -jda pyscard-1.6.14/smartcard/0000755000175000017500000000000011747777125017010 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/ReaderMonitoring.py0000644000175000017500000001757511747776700022647 0ustar rousseaurousseau00000000000000"""Smart card reader monitoring classes. ReaderObserver is a base class for objects that are to be notified upon smartcard reader insertion/removal. ReaderMonitor is a singleton object notifying registered ReaderObservers upon reader insertion/removal. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from sys import exc_info from threading import Thread, Event, enumerate from time import sleep import smartcard.System from smartcard.Exceptions import ListReadersException from smartcard.Observer import Observer from smartcard.Observer import Observable from smartcard.Synchronization import * # ReaderObserver interface class ReaderObserver(Observer): """ ReaderObserver is a base abstract class for objects that are to be notified upon smartcard reader insertion/removal. """ def __init__(self): pass def update(self, observable, (addedreaders, removedreaders)): """Called upon reader insertion/removal. observable: addedreaders: list of added readers causing notification removedreaders: list of removed readers causing notification """ pass class ReaderMonitor(Observable): """Class that monitors reader insertion/removal. and notify observers note: a reader monitoring thread will be running as long as the reader monitor has observers, or ReaderMonitor.stop() is called. It implements the shared state design pattern, where objects of the same type all share the same state, in our case essentially the ReaderMonitoring Thread. Thanks to Frank Aune for implementing the shared state pattern logics. """ __shared_state = {} def __init__(self, startOnDemand=True, readerProc=smartcard.System.readers, period=1): self.__dict__ = self.__shared_state Observable.__init__(self) self.startOnDemand = startOnDemand self.readerProc = readerProc self.period = period if self.startOnDemand: self.rmthread = None else: self.rmthread = ReaderMonitoringThread(self, self.readerProc, self.period) self.rmthread.start() def addObserver(self, observer): """Add an observer.""" Observable.addObserver(self, observer) # If self.startOnDemand is True, the reader monitoring # thread only runs when there are observers. if self.startOnDemand: if 0 < self.countObservers(): if not self.rmthread: self.rmthread = ReaderMonitoringThread(self, self.readerProc, self.period) # start reader monitoring thread in another thread to # avoid a deadlock; addObserver and notifyObservers called # in the ReaderMonitoringThread run() method are # synchronized import thread thread.start_new_thread(self.rmthread.start, ()) else: observer.update(self, (self.rmthread.readers, [])) def deleteObserver(self, observer): """Remove an observer.""" Observable.deleteObserver(self, observer) # If self.startOnDemand is True, the reader monitoring # thread is stopped when there are no more observers. if self.startOnDemand: if 0 == self.countObservers(): self.rmthread.stop() del self.rmthread self.rmthread = None def __str__(self): return self.__class__.__name__ synchronize(ReaderMonitor, "addObserver deleteObserver deleteObservers " + "setChanged clearChanged hasChanged " + "countObservers") class ReaderMonitoringThread(Thread): """Reader insertion thread. This thread polls for pcsc reader insertion, since no reader insertion event is available in pcsc. """ __shared_state = {} def __init__(self, observable, readerProc, period): self.__dict__ = self.__shared_state Thread.__init__(self) self.observable = observable self.stopEvent = Event() self.stopEvent.clear() self.readers = [] self.setDaemon(True) self.setName('smartcard.ReaderMonitoringThread') self.readerProc = readerProc self.period = period def run(self): """Runs until stopEvent is notified, and notify observers of all reader insertion/removal. """ while not self.stopEvent.isSet(): try: # no need to monitor if no observers if 0 < self.observable.countObservers(): currentReaders = self.readerProc() addedReaders = [] removedReaders = [] if currentReaders != self.readers: for reader in currentReaders: if not reader in self.readers: addedReaders.append(reader) for reader in self.readers: if not reader in currentReaders: removedReaders.append(reader) if addedReaders or removedReaders: # Notify observers self.readers = [] for r in currentReaders: self.readers.append(r) self.observable.setChanged() self.observable.notifyObservers((addedReaders, removedReaders)) # wait every second on stopEvent self.stopEvent.wait(self.period) except Exception, e: # Most likely raised during interpreter shutdown due # to unclean exit which failed to remove all observers. # To solve this, we set the stop event and pass the # exception to let the thread finish gracefully. self.stopEvent.set() def stop(self): self.stopEvent.set() self.join() if __name__ == "__main__": from smartcard.ReaderMonitoring import ReaderMonitor print 'insert or remove readers in the next 20 seconds' # a simple reader observer that prints added/removed readers class printobserver(ReaderObserver): def __init__(self, obsindex): self.obsindex = obsindex def update(self, observable, (addedreaders, removedreaders)): print "%d - added: " % self.obsindex, addedreaders print "%d - removed: " % self.obsindex, removedreaders class testthread(Thread): def __init__(self, obsindex): Thread.__init__(self) self.readermonitor = ReaderMonitor() self.obsindex = obsindex self.observer = None def run(self): # create and register observer self.observer = printobserver(self.obsindex) self.readermonitor.addObserver(self.observer) sleep(20) self.readermonitor.deleteObserver(self.observer) t1 = testthread(1) t2 = testthread(2) t1.start() t2.start() t1.join() t2.join() pyscard-1.6.14/smartcard/TODO0000644000175000017500000000063711543151200017454 0ustar rousseaurousseau00000000000000- complete support of remote readers with Pyro and add in documentation - document construction of standalone windows application using py2exe - documentation and implementation of card services - documentation of CardConnectionDecorator; add a meaningful example (OP secure channel?) - documentation of wxPython classes; fix wxPython code on Mac OS X - more error checking chains - more unit tests May 2010 pyscard-1.6.14/smartcard/ExclusiveTransmitCardConnection.py0000644000175000017500000000676211747776700025676 0ustar rousseaurousseau00000000000000"""Sample CardConnectionDecorator that provides exclusive transmit() __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardConnection import CardConnection from smartcard.CardConnectionDecorator import CardConnectionDecorator from smartcard.Exceptions import CardConnectionException from smartcard.scard import SCardBeginTransaction, SCardEndTransaction from smartcard.scard import SCARD_LEAVE_CARD from smartcard.scard import SCardGetErrorMessage from smartcard.pcsc import PCSCCardConnection import smartcard.pcsc class ExclusiveTransmitCardConnection(CardConnectionDecorator): '''This decorator uses SCardBeginTransaction/SCardEndTransaction to preserve other processes of threads to access the card during transmit().''' def __init__(self, cardconnection): CardConnectionDecorator.__init__(self, cardconnection) def lock(self): '''Lock card with SCardBeginTransaction.''' component = self.component while True: if isinstance( component, smartcard.pcsc.PCSCCardConnection.PCSCCardConnection): hresult = SCardBeginTransaction(component.hcard) if 0 != hresult: raise CardConnectionException( 'Failed to lock with SCardBeginTransaction' +\ SCardGetErrorMessage(hresult)) else: #print 'locked' pass break if hasattr(component, 'component'): component = component.component else: break def unlock(self): '''Unlock card with SCardEndTransaction.''' component = self.component while True: if isinstance( component, smartcard.pcsc.PCSCCardConnection.PCSCCardConnection): hresult = SCardEndTransaction(component.hcard, SCARD_LEAVE_CARD) if 0 != hresult: raise CardConnectionException( 'Failed to unlock with SCardEndTransaction' +\ SCardGetErrorMessage(hresult)) else: #print 'unlocked' pass break if hasattr(component, 'component'): component = component.component else: break def transmit(self, bytes, protocol=None): '''Gain exclusive access to card during APDU transmission for if this decorator decorates a PCSCCardConnection.''' data, sw1, sw2 = CardConnectionDecorator.transmit( self, bytes, protocol) return data, sw1, sw2 pyscard-1.6.14/smartcard/ACKS0000644000175000017500000000061711255421436017441 0ustar rousseaurousseau00000000000000Acknowledgements ---------------- This list is sorted in alphabetical order, and is probably incomplete. I'd like to thank everybody who contributed in any way, with code, bug reports, and comments. -jda Jarle Bauck Hamar Antonio Aranda Frank Aune Michel Beziat Mattias Brändström Luc Duche Nodir Gulyamov Yong David Huang Adam Laurie Henryk Plotz Michael Roehner Ludovic Rousseau David Wagner pyscard-1.6.14/smartcard/ChangeLog0000644000175000017500000001524511747776700020567 0ustar rousseaurousseau000000000000001.6.14 (April 2012s) =================== * added support for windows 64bit amd64 (Jean-Daniel Aussel) * support python "new" classes (derive classes from object) (Ludovic Rousseau from chrysn feature request ID 3110077) * fixed Reader.__eq__() (Ludovic Rousseau from Bernard Paulus bug ID 3418113) * fixed extended APDU transmit buffer too short by 2 (Jean-Daniel Aussel from bugs ID 2914636 and 3106761) + make Card and Reader objects hashable (Jean-Daniel Aussel from Hans-Peter Jansen feature request and patch) 1.6.12 (August 2010) =================== * comply with PEP 8 (Ludovic Rousseau) * comply with PEP 352 (Jean-Daniel Aussel) * support of pcsclite 1.6 and deprecated LPSCARD_READERSTATE_A (Ludovic Rousseau) * support of py2exe scripts for wxWindows examples (Jean-Daniel Aussel) * partial support of remote pcsc readers with pyro (Jean-Daniel Aussel) 1.6.10 (May 2010) =================== * connect() has a new disposition parameter that is passed to SCardDisconnect (Ludovic Rousseau) * fixed winscard_init() bad initialization causing problems in multithreaded environment (Ludovic Rousseau) * Use MAX_BUFFER_SIZE_EXTENDED (64k) instead of 1024 for SCardControl and SCardTransmit (Ludovic Rousseau, reported by Lukasz Drygiel) * call winscard_init() to load the library only in the %init section instead of in each wrapped function (Ludovic Rousseau) * for Snow Leopard, do not pass -framework PCSC to the compiler (Martin Paljak) * reformatting to meet pep8 (Style Guide for Python Code) guidelines (Ludovic Rousseau) * rename FEATURE_MCT_READERDIRECT in FEATURE_MCT_READER_DIRECT to be conform with PCSC v2 part 10 ch. 2.3 (Ludovic Rousseau) * added missing CARD_E_NO_READERS_AVAILABLE (Kjell Tore Fossbakk) * added support of x86_64 on Mac OS X Snow Leopard (Jakob Schlyter) * ATR can be passed in input in the reader state list (Benoit Allard) * clear state changed bit in waitforcard/waitforcardevent upon time-out or reader removal (Jean-Daniel Aussel) * removed clearing of states and ATR content upon SCardGetStatusChange() error (Benoit Allard); handling is now moved up in python framework (Jean-Daniel Aussel) 1.6.8 (July 2009) ================= * fixed SCARD_ERROR types to match correct types on linux and Mac OS X (Ludovic Rousseau) * store g_rgSCard* references as void* (Ludovic Rousseau) * modified Mac OS X build to locate PCSC headers using -framework option (Ludovic Rousseau) * added contrib root directory and parseATR as first contribution (Ludovic Rousseau) * updated a few samples to support SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 instead of just SCARD_PROTOCOL_T0 (Ludovic Rousseau) * added SCARD_E_NO_READERS_AVAILABLE definition (Ludovic Rousseau) * added simpleAPDU.py, a simple script to send a couple of APDUs (Ludovic Rousseau) * added support for Snow Leopard 10.6 (Ludovic Rousseau) * redefined error codes to be non-Windows or -linux specifics (Ludovic Rousseau) * added definitions of SCARD_ATTR_xxx values for Mac OS X (Jean-Daniel Aussel) * delay SCardEstablishContext call until needed instead of login, to allow use of utility classes such as toHexString, even when the PCSC resource manager or pcscd daemon is not started (Ludovic Rousseau) * added javascript code for Piwik web analytics to documentation pages (Jean-Daniel Aussel) * update sourceforge logo pages to latest sourceforge standard (Jean-Daniel Aussel) * fixed ATR parsing logics (Ludovic Rousseau) * added control() method to CardConnection() (Ludovic Rousseau) * added mode argument to connect() method of CardConnection (Ludovic Rousseau) * added PCSC v2 feature management (Ludovic Rousseau) 1.6.7 ===== * better thread support and clean-up in ReaderMonitoringThread (Frank Aune) * fixed issue on Mac OS X Leopard with dlsym loading of bad SCardControl function (Mattias Brändström) * supported build of documentation files on linux and removed unresolved doc links (Ludovic Rousseau) 1.6.6 ===== * added support for Mac OS X Leopard 1.6.5 ===== * added sample_MonitorCardsAndTransmit.py sample to illustrate how to transmit apdu to a card notified by the card monitor * added support for SCardControl (Ludovic Rousseau) * added support for Max OS X Tiger (Ludovic Rousseau/Jean-Daniel Aussel) (Leopard not supported) * added debian package directory (Ludovice Rousseau) * support for python 2.3, 2.4 and 2.5 distutils * automated insertion of sourceforge logo in html pages generated by epydoc * fixed documentation generation to include examples 1.6.4 ===== * handled several issues reported by Michael Roehner concerning waitforcard() not detecting card in reader/card USB stick; changed the waitforcard() and waitforcardevent() to poll every 100ms for new readers and cards in these readers * following issue reported by Jarle Bauck Hamar, added samples on how to perform exclusive card connection or protect transmit() from being interupted by another thread or process * fixed ATR parsing error for optional interface bytes reported by Jarle Bauck Hamar 1.6.3 ===== * better handling of protocol selection with associated test cases and added getATR_T1 example (issue reported by Adam Laurie for T=1 cards, and request from Yong David Huang for Omnikey CM5321 RFID that failed with T0|T1 mask). * added handling of linux 64-bit platform and graceful exit for unsupported platform, thanks to Henryk Plötz * added support for float value timeout in CardRequest, thanks to Henryk Plötz; updated test cases and a couple of samples with float timeouts. 1.6.2 ===== * started support for Mac OS X Darwin; not yet operational * fixed issue with "'NoneType' object is not callable" exception on some clean-up routines executed from __del__ methods (CardMonitoring, ReaderMonitoring, CardConnection) * added default protocol, protocol argument to CardConnection.connect(), and get/setProtocol methods to CardConnection, PCSCCardConnection and CardConnectionDecorator 1.6.1 ===== * maintenance release: - define LPCTSTR and LPTSTR for recent releases of pcsc-lite - print formatting of userdata in SCardHelper_PrintReaderStateList - updated home page and download links to point to sourceforge.net 1.6.0 ===== * released open-source with LGPL license pyscard-1.6.14/smartcard/guid.py0000644000175000017500000000361411747776700020314 0ustar rousseaurousseau00000000000000"""smartcard.guid Utility functions to handle GUIDs as strings or list of bytes __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from struct import unpack # guid is ulong+ushort+ushort+uchar[8]; we need a map because bytes # are swappted for the first three map = {0: 3, 1: 2, 2: 1, 3: 0, 4: 5, 5: 4, 6: 7, 7: 6, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15} def strToGUID(s): """Converts a GUID string into a list of bytes.""" l = [] for i in unpack('x' + '2s' * 4 + 'x' + '2s2sx' * 3 + '2s' * 6 + 'x', s): l += [int(i, 16)] zr = [] for i in xrange(len(l)): zr.append(l[map[i]]) return zr def GUIDToStr(g): """Converts a GUID sequence of bytes into a string.""" zr = [] for i in xrange(len(g)): zr.append(g[map[i]]) return "{%2X%2X%2X%2X-%2X%2X-%2X%2X-%2X%2X-%2X%2X%2X%2X%2X%2X}" % tuple(zr) if __name__ == "__main__": """Small sample illustrating the use of guid.py.""" import smartcard.guid dummycardguid1 = strToGUID('{AD4F1667-EA75-4124-84D4-641B3B197C65}') print dummycardguid1 print GUIDToStr(dummycardguid1) pyscard-1.6.14/smartcard/CardConnectionObserver.py0000644000175000017500000000436111747776700023765 0ustar rousseaurousseau00000000000000"""CardConnectionObserver interface. CardConnectionObserver is a base class for objects that are to be notified upon CardConnection events. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.util import toHexString from smartcard.Observer import Observer # ReaderObserver interface class CardConnectionObserver(Observer): """ CardConnectionObserver is a base class for objects that are to be notified upon CardConnection events. """ def update(self, cardconnection, cardconnectionevent): """Called upon CardConnection event. cardconnection: the observed card connection object cardconnectionevent: the CardConnectionEvent sent by the connection """ pass class ConsoleCardConnectionObserver(CardConnectionObserver): def update(self, cardconnection, ccevent): if 'connect' == ccevent.type: print 'connecting to ' + cardconnection.getReader() elif 'disconnect' == ccevent.type: print 'disconnecting from ' + cardconnection.getReader() elif 'command' == ccevent.type: print '> ', toHexString(ccevent.args[0]) elif 'response' == ccevent.type: if [] == ccevent.args[0]: print '< [] ', "%-2X %-2X" % tuple(ccevent.args[-2:]) else: print '< ', \ toHexString(ccevent.args[0]), \ "%-2X %-2X" % tuple(ccevent.args[-2:]) pyscard-1.6.14/smartcard/Examples/0000755000175000017500000000000011747777125020566 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/Examples/framework/0000755000175000017500000000000011747777125022563 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/Examples/framework/sample_ATR.py0000644000175000017500000000270111404463362025105 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script for the smartcard.ATR utility class. __author__ = "http://www.gemalto.com" Copyright 2001-2009 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.ATR import ATR from smartcard.util import toHexString atr = ATR([0x3B, 0x9E, 0x95, 0x80, 0x1F, 0xC3, 0x80, 0x31, 0xA0, 0x73, 0xBE, 0x21, 0x13, 0x67, 0x29, 0x02, 0x01, 0x01, 0x81, 0xCD, 0xB9]) print atr print 'historical bytes: ', toHexString(atr.getHistoricalBytes()) print 'checksum: ', "0x%X" % atr.getChecksum() print 'checksum OK: ', atr.checksumOK print 'T0 supported: ', atr.isT0Supported() print 'T1 supported: ', atr.isT1Supported() print 'T15 supported: ', atr.isT15Supported() pyscard-1.6.14/smartcard/Examples/framework/sample_MonitorCards.py0000755000175000017500000000407111747776677027122 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script that monitors smartcard insertion/removal. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from sys import stdin, exc_info from time import sleep from smartcard.CardMonitoring import CardMonitor, CardObserver from smartcard.util import * # a simple card observer that prints inserted/removed cards class printobserver(CardObserver): """A simple card observer that is notified when cards are inserted/removed from the system and prints the list of cards """ def update(self, observable, (addedcards, removedcards)): for card in addedcards: print "+Inserted: ", toHexString(card.atr) for card in removedcards: print "-Removed: ", toHexString(card.atr) try: print "Insert or remove a smartcard in the system." print "This program will exit in 10 seconds" print "" cardmonitor = CardMonitor() cardobserver = printobserver() cardmonitor.addObserver(cardobserver) sleep(10) # don't forget to remove observer, or the # monitor will poll forever... cardmonitor.deleteObserver(cardobserver) import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) except: print exc_info()[0], ':', exc_info()[1] pyscard-1.6.14/smartcard/Examples/framework/sample_MonitorReaders.py0000755000175000017500000000364411747776677027460 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script that monitors smartcard readers. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from sys import stdin, exc_info from time import sleep from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver class printobserver(ReaderObserver): """A simple reader observer that is notified when readers are added/removed from the system and prints the list of readers """ def update(self, observable, (addedreaders, removedreaders)): print "Added readers", addedreaders print "Removed readers", removedreaders try: print "Add or remove a smartcard reader to the system." print "This program will exit in 10 seconds" print "" readermonitor = ReaderMonitor() readerobserver = printobserver() readermonitor.addObserver(readerobserver) sleep(10) # don't forget to remove observer, or the # monitor will poll forever... readermonitor.deleteObserver(readerobserver) import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) except: print exc_info()[0], ':', exc_info()[1] pyscard-1.6.14/smartcard/Examples/framework/sample_ErrorChecking.py0000755000175000017500000000604111747776677027242 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Sample script for APDU error checking. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardType import AnyCardType from smartcard.CardRequest import CardRequest from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.sw.ErrorCheckingChain import ErrorCheckingChain from smartcard.sw.ISO7816_4ErrorChecker import ISO7816_4ErrorChecker from smartcard.sw.ISO7816_8ErrorChecker import ISO7816_8ErrorChecker from smartcard.sw.ISO7816_9ErrorChecker import ISO7816_9ErrorChecker from smartcard.sw.SWExceptions import SWException, WarningProcessingException # define the apdus used in this script GET_RESPONSE = [0XA0, 0XC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] if __name__ == '__main__': print 'Insert a card within 10 seconds' print 'Cards without a DF_TELECOM will except' # request any card type cardtype = AnyCardType() cardrequest = CardRequest(timeout=10, cardType=cardtype) cardservice = cardrequest.waitforcard() # use ISO7816-4 and ISO7816-8 error checking strategy # first check iso7816_8 errors, then iso7816_4 errors errorchain = [] errorchain = [ErrorCheckingChain(errorchain, ISO7816_9ErrorChecker())] errorchain = [ErrorCheckingChain(errorchain, ISO7816_8ErrorChecker())] errorchain = [ErrorCheckingChain(errorchain, ISO7816_4ErrorChecker())] cardservice.connection.setErrorCheckingChain(errorchain) # filter Warning Processing Exceptions (sw1 = 0x62 or 0x63) cardservice.connection.addSWExceptionToFilter(WarningProcessingException) # attach the console tracer observer = ConsoleCardConnectionObserver() cardservice.connection.addObserver(observer) # connect to the card and perform a few transmits cardservice.connection.connect() try: apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) except SWException, e: print str(e) cardservice.connection.disconnect() import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/framework/sample_TransmitCardObserver.py0000755000175000017500000000452211747776677030622 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script that monitors card insertions, connects to cards and transmit an apdu __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from sys import stdin, exc_info from time import sleep from smartcard.CardMonitoring import CardMonitor, CardObserver from smartcard.util import * # replace by your favourite apdu SELECT_DF_TELECOM = [0xA0, 0xA4, 0x00, 0x00, 0x02, 0x7F, 0x10] class transmitobserver(CardObserver): """A card observer that is notified when cards are inserted/removed from the system, connects to cards and SELECT DF_TELECOM """ def __init__(self): self.cards = [] def update(self, observable, (addedcards, removedcards)): for card in addedcards: if card not in self.cards: self.cards += [card] print "+Inserted: ", toHexString(card.atr) card.connection = card.createConnection() card.connection.connect() response, sw1, sw2 = card.connection.transmit( SELECT_DF_TELECOM) print "%.2x %.2x" % (sw1, sw2) for card in removedcards: print "-Removed: ", toHexString(card.atr) if card in self.cards: self.cards.remove(card) try: print "Insert or remove a smartcard in the system." print "This program will exit in 100 seconds" print "" cardmonitor = CardMonitor() cardobserver = transmitobserver() cardmonitor.addObserver(cardobserver) sleep(100) except: print exc_info()[0], ':', exc_info()[1] pyscard-1.6.14/smartcard/Examples/framework/sample_CardConnectionDecorator.py0000755000175000017500000000740011747776677031251 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script that illustrates card connection decorators. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardType import AnyCardType from smartcard.CardRequest import CardRequest from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.CardConnection import CardConnection from smartcard.CardConnectionDecorator import CardConnectionDecorator from smartcard.util import toHexString # define two custom CardConnectionDecorator # the decorators are very simple, just to illustrate # shortly how several decorators can be added to the # card connection class SecureChannelConnection(CardConnectionDecorator): '''This decorator is a mockup of secure channel connection. It merely pretends to cypher/uncypher upon apdu transmission.''' def __init__(self, cardconnection): CardConnectionDecorator.__init__(self, cardconnection) def cypher(self, bytes): '''Cypher mock-up; you would include the secure channel logics here.''' print 'cyphering', toHexString(bytes) return bytes def uncypher(self, data): '''Uncypher mock-up; you would include the secure channel logics here.''' print 'uncyphering', toHexString(data) return data def transmit(self, bytes, protocol=None): """Cypher/uncypher APDUs before transmission""" cypheredbytes = self.cypher(bytes) data, sw1, sw2 = CardConnectionDecorator.transmit( self, cypheredbytes, protocol) if [] != data: data = self.uncypher(data) return data, sw1, sw2 class FakeATRConnection(CardConnectionDecorator): '''This decorator changes the fist byte of the ATR. This is just an example to show that decorators can be nested.''' def __init__(self, cardconnection): CardConnectionDecorator.__init__(self, cardconnection) def getATR(self): """Replace first BYTE of ATR by 3F""" atr = CardConnectionDecorator.getATR(self) return [0x3f] + atr[1:] # define the apdus used in this script GET_RESPONSE = [0XA0, 0XC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] # request any card type cardtype = AnyCardType() cardrequest = CardRequest(timeout=1.5, cardType=cardtype) cardservice = cardrequest.waitforcard() # attach the console tracer observer = ConsoleCardConnectionObserver() cardservice.connection.addObserver(observer) # attach our decorator cardservice.connection = FakeATRConnection( SecureChannelConnection(cardservice.connection)) # connect to the card and perform a few transmits cardservice.connection.connect() print 'ATR', toHexString(cardservice.connection.getATR()) apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/framework/sample_apduTracerInterpreter.py0000755000175000017500000000575211747776677031043 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script that defines a custom card connection observer. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardType import AnyCardType from smartcard.CardRequest import CardRequest from smartcard.CardConnectionObserver import CardConnectionObserver from smartcard.util import toHexString from string import replace class TracerAndSELECTInterpreter(CardConnectionObserver): """This observer will interprer SELECT and GET RESPONSE bytes and replace them with a human readable string.""" def update(self, cardconnection, ccevent): if 'connect' == ccevent.type: print 'connecting to ' + cardconnection.getReader() elif 'disconnect' == ccevent.type: print 'disconnecting from ' + cardconnection.getReader() elif 'command' == ccevent.type: str = toHexString(ccevent.args[0]) str = replace(str, "A0 A4 00 00 02", "SELECT") str = replace(str, "A0 C0 00 00", "GET RESPONSE") print '>', str elif 'response' == ccevent.type: if [] == ccevent.args[0]: print '< []', "%-2X %-2X" % tuple(ccevent.args[-2:]) else: print '<', toHexString(ccevent.args[0]), "%-2X %-2X" % tuple(ccevent.args[-2:]) # define the apdus used in this script GET_RESPONSE = [0XA0, 0XC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] # we request any type and wait for 10s for card insertion cardtype = AnyCardType() cardrequest = CardRequest(timeout=10, cardType=cardtype) cardservice = cardrequest.waitforcard() # create an instance of our observer and attach to the connection observer = TracerAndSELECTInterpreter() cardservice.connection.addObserver(observer) # connect and send APDUs # the observer will trace on the console cardservice.connection.connect() apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) else: print 'no DF_TELECOM' import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/framework/sample_CustomCardType.py0000755000175000017500000000324411747776677027425 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script that demonstrates how to create a custom CardType. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardType import CardType from smartcard.CardRequest import CardRequest from smartcard.util import toHexString class DCCardType(CardType): # define our custom CardType # this card type defines direct convention card (first atr byte equal to 0x3b) def matches(self, atr, reader=None): return atr[0] == 0x3B # request a direct convention card cardtype = DCCardType() cardrequest = CardRequest(timeout=1, cardType=cardtype) cardservice = cardrequest.waitforcard() # connect and print atr and reader cardservice.connection.connect() print toHexString(cardservice.connection.getATR()) print cardservice.connection.getReader() import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/framework/sample_CustomErrorChecker.py0000755000175000017500000000562111747776677030271 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Sample script for APDU error checking with a custom error checker. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardType import AnyCardType from smartcard.CardRequest import CardRequest from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.sw.ErrorCheckingChain import ErrorCheckingChain from smartcard.sw.ErrorChecker import ErrorChecker from smartcard.sw.SWExceptions import SWException class MyErrorChecker(ErrorChecker): """Our custom error checker that will except if 0x61 sw1: raise SWException(data, sw1, sw2) # define the apdus used in this script GET_RESPONSE = [0XA0, 0XC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] if __name__ == '__main__': print 'Insert a card within 10 seconds' print 'Cards without a DF_TELECOM will except' # request any card cardtype = AnyCardType() cardrequest = CardRequest(timeout=10, cardType=cardtype) cardservice = cardrequest.waitforcard() # our error checking chain errorchain = [] errorchain = [ErrorCheckingChain([], MyErrorChecker())] cardservice.connection.setErrorCheckingChain(errorchain) # attach the console tracer observer = ConsoleCardConnectionObserver() cardservice.connection.addObserver(observer) # send a few apdus; exceptions will occur upon errors cardservice.connection.connect() try: SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) if sw1 == 0x9F: GET_RESPONSE = [0XA0, 0XC0, 00, 00] apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) except SWException, e: print e, "%x %x" % (e.sw1, e.sw2) cardservice.connection.disconnect() import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/framework/sample_MonitorCardsAndTransmit.py0000755000175000017500000000547311747776677031276 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script that monitors smartcard insertion/removal and select DF_TELECOM on inserted cards __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from sys import stdin, exc_info from time import sleep from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.CardMonitoring import CardMonitor, CardObserver from smartcard.util import * # define the apdus used in this script GET_RESPONSE = [0XA0, 0XC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] # a simple card observer that tries to select DF_TELECOM on an inserted card class selectDFTELECOMObserver(CardObserver): """A simple card observer that is notified when cards are inserted/removed from the system and prints the list of cards """ def __init__(self): self.observer = ConsoleCardConnectionObserver() def update(self, observable, (addedcards, removedcards)): for card in addedcards: print "+Inserted: ", toHexString(card.atr) card.connection = card.createConnection() card.connection.connect() card.connection.addObserver(self.observer) apdu = SELECT + DF_TELECOM response, sw1, sw2 = card.connection.transmit(apdu) if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = card.connection.transmit(apdu) for card in removedcards: print "-Removed: ", toHexString(card.atr) try: print "Insert or remove a SIM card in the system." print "This program will exit in 60 seconds" print "" cardmonitor = CardMonitor() selectobserver = selectDFTELECOMObserver() cardmonitor.addObserver(selectobserver) sleep(60) # don't forget to remove observer, or the # monitor will poll forever... cardmonitor.deleteObserver(selectobserver) import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) except: print exc_info()[0], ':', exc_info()[1] pyscard-1.6.14/smartcard/Examples/framework/sample_ConsoleConnectionTracer.py0000755000175000017500000000354211747776677031303 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script that monitors card connection events. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardType import AnyCardType from smartcard.CardRequest import CardRequest from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver # define the apdus used in this script GET_RESPONSE = [0XA0, 0XC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] # request any card type cardtype = AnyCardType() cardrequest = CardRequest(timeout=1.5, cardType=cardtype) cardservice = cardrequest.waitforcard() # attach the console tracer observer = ConsoleCardConnectionObserver() cardservice.connection.addObserver(observer) # connect to the card and perform a few transmits cardservice.connection.connect() apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/framework/sample_toHexString.py0000755000175000017500000000443411747776677026777 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script to illustrate toHexString() utility method __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.util import * print 40 * '-' bytes = [59, 101, 0, 0, 156, 17, 1, 1, 3] print 'bytes = [59, 101, 0, 0, 156, 17, 1, 1, 3]' print 'toHexString(bytes) =', toHexString(bytes) print 'toHexString(bytes, COMMA) =', toHexString(bytes, COMMA) print 'toHexString(bytes, PACK) =', toHexString(bytes, PACK) print 'toHexString(bytes, HEX) =', toHexString(bytes, HEX) print 'toHexString(bytes, HEX | COMMA) =', toHexString(bytes, HEX | COMMA) print 'toHexString(bytes, HEX | UPPERCASE) =', \ toHexString(bytes, HEX | UPPERCASE) print 'toHexString(bytes, HEX | UPPERCASE | COMMA) =', \ toHexString(bytes, HEX | UPPERCASE | COMMA) print 40 * '-' bytes = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03] print 'bytes = [ 0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03 ]' print 'toHexString(bytes, COMMA) =', toHexString(bytes, COMMA) print 'toHexString(bytes) =', toHexString(bytes) print 'toHexString(bytes, PACK) =', toHexString(bytes, PACK) print 'toHexString(bytes, HEX) =', toHexString(bytes, HEX) print 'toHexString(bytes, HEX | COMMA) =', toHexString(bytes, HEX | COMMA) print 'toHexString(bytes, HEX | UPPERCASE) =', \ toHexString(bytes, HEX | UPPERCASE) print 'toHexString(bytes, HEX | UPPERCASE | COMMA) =', \ toHexString(bytes, HEX | UPPERCASE | COMMA) import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/framework/sample_ExclusiveCardConnection.py0000755000175000017500000000466211747776677031305 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script that illustrates exclusive card connection decorators. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardType import AnyCardType from smartcard.CardRequest import CardRequest from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.CardConnection import CardConnection from smartcard.util import toHexString from smartcard.ExclusiveConnectCardConnection import \ ExclusiveConnectCardConnection from smartcard.ExclusiveTransmitCardConnection import \ ExclusiveTransmitCardConnection # define the apdus used in this script GET_RESPONSE = [0XA0, 0XC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] # request any card type cardtype = AnyCardType() cardrequest = CardRequest(timeout=5, cardType=cardtype) cardservice = cardrequest.waitforcard() # attach the console tracer observer = ConsoleCardConnectionObserver() cardservice.connection.addObserver(observer) # attach our decorator cardservice.connection = ExclusiveTransmitCardConnection( ExclusiveConnectCardConnection(cardservice.connection)) # connect to the card and perform a few transmits cardservice.connection.connect() print 'ATR', toHexString(cardservice.connection.getATR()) try: cardservice.connection.lock() apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) finally: cardservice.connection.unlock() import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/wx/0000755000175000017500000000000011747777125021224 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/Examples/wx/readerviewer/0000755000175000017500000000000011747777125023710 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/Examples/wx/readerviewer/images/0000755000175000017500000000000011747777125025155 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/Examples/wx/readerviewer/images/readerviewer.ico0000644000175000017500000000047610633575650030334 0ustar rousseaurousseau00000000000000(( €€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿ`ff`p38†`x ³€€ˆp€`xˆˆp€ˆˆˆ‡pxxˆˆˆ‡ppˆ‡xˆˆˆpxˆ‡xˆ‡xˆ‡xpxˆ‡pxpÿŸÿøðâĈ @€àÈž?¿ÿÿpyscard-1.6.14/smartcard/Examples/wx/readerviewer/readerviewer.py0000755000175000017500000000353611747776677026773 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Simple smart card reader monitoring application. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 os.path import sys from smartcard.wx.SimpleSCardApp import * def we_are_frozen(): """Returns whether we are frozen via py2exe. This will affect how we find out where we are located. From WhereAmI page on py2exe wiki.""" return hasattr(sys, "frozen") def module_path(): """ This will get us the program's directory, even if we are frozen using py2exe. From WhereAmI page on py2exe wiki.""" if we_are_frozen(): return os.path.dirname( unicode(sys.executable, sys.getfilesystemencoding())) return os.path.dirname(unicode(__file__, sys.getfilesystemencoding())) def main(argv): app = SimpleSCardApp( appname='A simple reader monitoring tool', apppanel=None, appstyle=TR_READER, appicon=os.path.join(module_path(), 'images', 'readerviewer.ico'), size=(800, 600)) app.MainLoop() if __name__ == "__main__": import sys main(sys.argv) pyscard-1.6.14/smartcard/Examples/wx/readerviewer/setup.py0000644000175000017500000000260611747776677025441 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Setup script to build a standalone readerviewer.exe executable on windows using py2exe. Run: python.exe setup.py py2exe, to build executable file. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from distutils.core import setup import py2exe from smartcard.wx import ICO_SMARTCARD, ICO_READER Mydata_files = [('images', ['images/readerviewer.ico', ICO_SMARTCARD, ICO_READER])] setup(windows=['readerviewer.py'], data_files=Mydata_files, options={"py2exe": {"dll_excludes": ["MSVCP90.dll"]}} ) pyscard-1.6.14/smartcard/Examples/wx/cardmonitor/0000755000175000017500000000000011747777125023545 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/Examples/wx/cardmonitor/images/0000755000175000017500000000000011747777125025012 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/Examples/wx/cardmonitor/images/mysmartcard.ico0000644000175000017500000000047610633575650030033 0ustar rousseaurousseau00000000000000(( €€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³333s333»»»»{»»³·wwwwwws·»·»»{»s·»·»»{»s·ww»»wwsw»·»»{»ww»·»»{»w·»·»»{»s·ww»»wws·»·»»{»s·»·»»{»s·ww{wwws»»»»{»»³»»»»{»»»pyscard-1.6.14/smartcard/Examples/wx/cardmonitor/cardmonitor.py0000755000175000017500000001116211747776677026457 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Simple smart card monitoring application. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 os.path import sys from smartcard.wx.SimpleSCardApp import * from smartcard.wx.SimpleSCardAppEventObserver import \ SimpleSCardAppEventObserver ID_TEXT = 10000 def we_are_frozen(): """Returns whether we are frozen via py2exe. This will affect how we find out where we are located. From WhereAmI page on py2exe wiki.""" return hasattr(sys, "frozen") def module_path(): """ This will get us the program's directory, even if we are frozen using py2exe. From WhereAmI page on py2exe wiki.""" if we_are_frozen(): return os.path.dirname( unicode(sys.executable, sys.getfilesystemencoding())) return os.path.dirname(unicode(__file__, sys.getfilesystemencoding())) class SamplePanel(wx.Panel, SimpleSCardAppEventObserver): '''A simple panel that displays activated cards and readers. The panel implements the SimpleSCardAppEventObserver, and has a chance to react on reader and card activation/deactivation.''' def __init__(self, parent): wx.Panel.__init__(self, parent, -1) sizer = wx.FlexGridSizer(0, 3, 0, 0) sizer.AddGrowableCol(1) sizer.AddGrowableRow(1) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) self.feedbacktext = wx.StaticText( self, ID_TEXT, "", wx.DefaultPosition, wx.DefaultSize, 0) sizer.Add(self.feedbacktext, 0, wx.ALIGN_LEFT | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizer.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) self.SetSizer(sizer) self.SetAutoLayout(True) # callbacks from SimpleSCardAppEventObserver interface def OnActivateCard(self, card): """Called when a card is activated by double-clicking on the card or reader tree control or toolbar. In this sample, we just connect to the card on the first activation.""" SimpleSCardAppEventObserver.OnActivateCard(self, card) self.feedbacktext.SetLabel('Activated card: ' + repr(card)) def OnActivateReader(self, reader): """Called when a reader is activated by double-clicking on the reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnActivateReader(self, reader) self.feedbacktext.SetLabel('Activated reader: ' + repr(reader)) def OnDeactivateCard(self, card): """Called when a card is deactivated in the reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnActivateCard(self, card) self.feedbacktext.SetLabel('Deactivated card: ' + repr(card)) def OnSelectCard(self, card): """Called when a card is selected by clicking on the card or reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnSelectCard(self, card) self.feedbacktext.SetLabel('Selected card: ' + repr(card)) def OnSelectReader(self, reader): """Called when a reader is selected by clicking on the reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnSelectReader(self, reader) self.feedbacktext.SetLabel('Selected reader: ' + repr(reader)) def main(argv): app = SimpleSCardApp( appname='A simple card monitoring tool', apppanel=SamplePanel, appstyle=TR_SMARTCARD | TR_READER, appicon=os.path.join( module_path(), 'images', 'mysmartcard.ico'), size=(800, 600)) app.MainLoop() if __name__ == "__main__": import sys main(sys.argv) pyscard-1.6.14/smartcard/Examples/wx/cardmonitor/setup.py0000644000175000017500000000260311747776677025273 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Setup script to build a standalone cardmonitor.exe executable on windows using py2exe. Run: python.exe setup.py py2exe, to build executable file. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from distutils.core import setup import py2exe from smartcard.wx import ICO_SMARTCARD, ICO_READER Mydata_files = [('images', ['images/mysmartcard.ico', ICO_SMARTCARD, ICO_READER])] setup(windows=['cardmonitor.py'], data_files=Mydata_files, options={"py2exe": {"dll_excludes": ["MSVCP90.dll"]}} ) pyscard-1.6.14/smartcard/Examples/wx/pcscdiag/0000755000175000017500000000000011747777125023001 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/Examples/wx/pcscdiag/pcscdiag.py0000755000175000017500000000740111747776677025150 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Example wxPython application that displays readers and inserted cards ATRs. This example displays a snapshot of the readers and cards, there is no automatic refresh of the readers and cards. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 smartcard.Exceptions import smartcard.System import smartcard.util # wxPython GUI modules (http://www.wxpython.org) try: import wx except: print 'You need wxpython (http://www.wxpython.org) ' + \ 'to run this sample from the source code!' print 'press a key to continue' import msvcrt msvcrt.getch() import sys sys.exit() def getATR(reader): """Return the ATR of the card inserted into the reader.""" connection = reader.createConnection() atr = "" try: connection.connect() atr = smartcard.util.toHexString(connection.getATR()) connection.disconnect() except smartcard.Exceptions.NoCardException: atr = "no card inserted" return atr class pcscdiag(wx.Frame): def __init__(self, parent, title): wx.Frame.__init__(self, parent, -1, title, size=(600, 400)) w, h = self.GetClientSizeTuple() self.tree = wx.TreeCtrl( self, wx.NewId(), wx.DefaultPosition, (w, h), wx.TR_HAS_BUTTONS | wx.TR_EDIT_LABELS) self.InitTree() self.OnExpandAll() def InitTree(self): self.tree.AddRoot("Readers and ReaderGroups") readerNode = self.tree.AppendItem(self.tree.GetRootItem(), "Readers") for reader in smartcard.System.readers(): childReader = self.tree.AppendItem(readerNode, repr(reader)) childCard = self.tree.AppendItem(childReader, getATR(reader)) readerGroupNode = self.tree.AppendItem( self.tree.GetRootItem(), "Readers Groups") for readergroup in smartcard.System.readergroups(): childReaderGroup = self.tree.AppendItem( readerGroupNode, readergroup) readers = smartcard.System.readers(readergroup) for reader in readers: child = self.tree.AppendItem(childReaderGroup, repr(reader)) def OnExpandAll(self): """ expand all nodes """ root = self.tree.GetRootItem() fn = self.tree.Expand self.traverse(root, fn) self.tree.Expand(root) def traverse(self, traverseroot, function, cookie=0): """ recursivly walk tree control """ if self.tree.ItemHasChildren(traverseroot): firstchild, cookie = self.tree.GetFirstChild(traverseroot) function(firstchild) self.traverse(firstchild, function, cookie) child = self.tree.GetNextSibling(traverseroot) if child: function(child) self.traverse(child, function, cookie) if __name__ == '__main__': app = wx.PySimpleApp() frame = pcscdiag(None, "Smartcard readers and reader groups") frame.Show() app.MainLoop() pyscard-1.6.14/smartcard/Examples/wx/apdumanager/0000755000175000017500000000000011747777125023510 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/Examples/wx/apdumanager/SampleAPDUManagerPanel.py0000755000175000017500000002136511747776677030255 0ustar rousseaurousseau00000000000000# -*- coding: iso-8859-15 -*- """ Simple panel that defines a dialog to send APDUs to a card. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 wx from smartcard.wx.APDUHexValidator import APDUHexValidator from smartcard.wx.SimpleSCardAppEventObserver import \ SimpleSCardAppEventObserver from smartcard.util import toBytes, toHexString [ ID_TEXT_COMMAND, ID_TEXTCTRL_COMMAND, ID_TEXT_RESPONSE, ID_TEXTCTRL_RESPONSE, ID_TEXT_SW, ID_TEXT_SW1, ID_TEXTCTRL_SW1, ID_TEXT_SW2, ID_TEXTCTRL_SW2, ID_CARDSTATE, ID_TRANSMIT] = map(lambda x: wx.NewId(), range(11)) class SampleAPDUManagerPanel(wx.Panel, SimpleSCardAppEventObserver): '''A simple panel that displays activated cards and readers and can send APDU to a connected card.''' def __init__(self, parent): wx.Panel.__init__(self, parent, -1) SimpleSCardAppEventObserver.__init__(self) self.layoutControls() self.Bind(wx.EVT_BUTTON, self.OnTransmit, self.transmitbutton) # callbacks from SimpleSCardAppEventObserver interface def OnActivateCard(self, card): """Called when a card is activated by double-clicking on the card or reader tree control or toolbar. In this sample, we just connect to the card on the first activation.""" SimpleSCardAppEventObserver.OnActivateCard(self, card) self.feedbacktext.SetLabel('Activated card: ' + repr(card)) self.transmitbutton.Enable() def OnActivateReader(self, reader): """Called when a reader is activated by double-clicking on the reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnActivateReader(self, reader) self.feedbacktext.SetLabel('Activated reader: ' + repr(reader)) self.transmitbutton.Disable() def OnDeactivateCard(self, card): """Called when a card is deactivated in the reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnActivateCard(self, card) self.feedbacktext.SetLabel('Deactivated card: ' + repr(card)) self.transmitbutton.Disable() def OnDeselectCard(self, card): """Called when a card is selected by clicking on the card or reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnSelectCard(self, card) self.feedbacktext.SetLabel('Deselected card: ' + repr(card)) self.transmitbutton.Disable() def OnSelectCard(self, card): """Called when a card is selected by clicking on the card or reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnSelectCard(self, card) self.feedbacktext.SetLabel('Selected card: ' + repr(card)) if hasattr(self.selectedcard, 'connection'): self.transmitbutton.Enable() def OnSelectReader(self, reader): """Called when a reader is selected by clicking on the reader tree control or toolbar.""" SimpleSCardAppEventObserver.OnSelectReader(self, reader) self.feedbacktext.SetLabel('Selected reader: ' + repr(reader)) self.transmitbutton.Disable() # callbacks def OnTransmit(self, event): if hasattr(self.selectedcard, 'connection'): apdu = self.commandtextctrl.GetValue() if type(u'') == type(apdu): apdu = apdu.encode('utf8') data, sw1, sw2 = \ self.selectedcard.connection.transmit(toBytes(apdu)) self.SW1textctrl.SetValue("%x" % sw1) self.SW2textctrl.SetValue("%x" % sw2) self.responsetextctrl.SetValue(toHexString(data + [sw1, sw2])) event.Skip() def layoutControls(self): # create controls statictextCommand = wx.StaticText( self, ID_TEXT_COMMAND, "Command", wx.DefaultPosition, wx.DefaultSize, 0) self.commandtextctrl = wx.TextCtrl( self, ID_TEXTCTRL_COMMAND, "", wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE, validator=APDUHexValidator()) statictextResponse = wx.StaticText( self, ID_TEXT_RESPONSE, "Response", wx.DefaultPosition, wx.DefaultSize, 0) self.responsetextctrl = wx.TextCtrl( self, ID_TEXTCTRL_RESPONSE, "", wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE | wx.TE_READONLY) statictextStatusWords = wx.StaticText( self, ID_TEXT_SW, "Status Words", wx.DefaultPosition, wx.DefaultSize, 0) statictextSW1 = wx.StaticText( self, ID_TEXT_SW1, "SW1", wx.DefaultPosition, wx.DefaultSize, 0) self.SW1textctrl = wx.TextCtrl( self, ID_TEXTCTRL_SW1, "", wx.DefaultPosition, wx.DefaultSize, wx.TE_READONLY) statictextSW2 = wx.StaticText( self, ID_TEXT_SW2, "SW2", wx.DefaultPosition, wx.DefaultSize, 0) self.SW2textctrl = wx.TextCtrl( self, ID_TEXTCTRL_SW2, "", wx.DefaultPosition, wx.DefaultSize, wx.TE_READONLY) self.feedbacktext = wx.StaticText( self, ID_CARDSTATE, "", wx.DefaultPosition, wx.DefaultSize, 0) # layout controls boxsizerCommand = wx.BoxSizer(wx.HORIZONTAL) boxsizerCommand.Add(statictextCommand, 1, wx.ALIGN_CENTER | wx.ALL, 5) boxsizerCommand.Add(self.commandtextctrl, 5, wx.EXPAND | wx.ALL, 5) boxsizerResponse = wx.BoxSizer(wx.HORIZONTAL) boxsizerResponse.Add( statictextResponse, 1, wx.ALIGN_CENTER | wx.ALL, 5) boxsizerResponse.Add(self.responsetextctrl, 5, wx.EXPAND | wx.ALL, 5) boxsizerSW = wx.BoxSizer(wx.HORIZONTAL) boxsizerSW.Add(statictextSW1, 0, wx.ALIGN_CENTER | wx.ALL, 5) boxsizerSW.Add(self.SW1textctrl, 0, wx.EXPAND | wx.ALL, 5) boxsizerSW.Add(statictextSW2, 0, wx.ALIGN_CENTER | wx.ALL, 5) boxsizerSW.Add(self.SW2textctrl, 0, wx.EXPAND | wx.ALL, 5) item11 = wx.BoxSizer(wx.HORIZONTAL) item11.Add(statictextStatusWords, 0, wx.ALIGN_CENTER | wx.ALL, 5) item11.Add(boxsizerSW, 0, wx.EXPAND | wx.ALL, 5) boxsizerResponseAndSW = wx.BoxSizer(wx.VERTICAL) boxsizerResponseAndSW.Add(boxsizerResponse, 0, wx.EXPAND | wx.ALL, 5) boxsizerResponseAndSW.Add(item11, 0, wx.EXPAND | wx.ALL, 5) staticboxAPDU = wx.StaticBox(self, -1, "APDU") boxsizerAPDU = wx.StaticBoxSizer(staticboxAPDU, wx.VERTICAL) boxsizerAPDU.Add(boxsizerCommand, 1, wx.EXPAND | wx.ALL, 5) boxsizerAPDU.Add(boxsizerResponseAndSW, 4, wx.EXPAND | wx.ALL, 5) staticboxEvents = wx.StaticBox(self, -1, "Card/Reader Events") boxsizerEvents = wx.StaticBoxSizer(staticboxEvents, wx.HORIZONTAL) boxsizerEvents.Add(self.feedbacktext, 0, wx.ALIGN_CENTER | wx.ALL, 5) sizerboxTransmitButton = wx.BoxSizer(wx.HORIZONTAL) sizerboxTransmitButton.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) self.transmitbutton = wx.Button( self, ID_TRANSMIT, "Transmit", wx.DefaultPosition, wx.DefaultSize, 0) self.transmitbutton.Disable() sizerboxTransmitButton.Add( self.transmitbutton, 0, wx.ALIGN_CENTER | wx.ALL, 5) sizerboxTransmitButton.Add([20, 20], 0, wx.ALIGN_CENTER | wx.ALL, 5) sizerPanel = wx.BoxSizer(wx.VERTICAL) sizerPanel.Add(boxsizerAPDU, 3, wx.EXPAND | wx.ALL, 5) sizerPanel.Add(boxsizerEvents, 1, wx.EXPAND | wx.ALL, 5) sizerPanel.Add(sizerboxTransmitButton, 1, wx.EXPAND | wx.ALL, 5) self.SetSizer(sizerPanel) self.SetAutoLayout(True) sizerPanel.Fit(self) pyscard-1.6.14/smartcard/Examples/wx/apdumanager/images/0000755000175000017500000000000011747777125024755 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/Examples/wx/apdumanager/images/mysmartcard.ico0000644000175000017500000000047610633575650027776 0ustar rousseaurousseau00000000000000(( €€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³333s333»»»»{»»³·wwwwwws·»·»»{»s·»·»»{»s·ww»»wwsw»·»»{»ww»·»»{»w·»·»»{»s·ww»»wws·»·»»{»s·»·»»{»s·ww{wwws»»»»{»»³»»»»{»»»pyscard-1.6.14/smartcard/Examples/wx/apdumanager/setup.py0000644000175000017500000000260511747776677025240 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Setup script to build a standalone apdumanager.exe executable on windows using py2exe. Run: python.exe setup.py py2exe, to build executable file. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from distutils.core import setup import py2exe from smartcard.wx import ICO_SMARTCARD, ICO_READER Mydata_files = [('images', ['images/mysmartcard.ico', ICO_SMARTCARD, ICO_READER])] setup(windows=['apdumanager.py'], data_files=Mydata_files, options={"py2exe": {"dll_excludes": ["MSVCP90.dll"]}} ) pyscard-1.6.14/smartcard/Examples/wx/apdumanager/apdumanager.py0000755000175000017500000000372011747776677026366 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Simple application to send APDUs to a card. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 os import sys import os.path from smartcard.wx.SimpleSCardApp import * from SampleAPDUManagerPanel import SampleAPDUManagerPanel def we_are_frozen(): """Returns whether we are frozen via py2exe. This will affect how we find out where we are located. From WhereAmI page on py2exe wiki.""" return hasattr(sys, "frozen") def module_path(): """ This will get us the program's directory, even if we are frozen using py2exe. From WhereAmI page on py2exe wiki.""" if we_are_frozen(): return os.path.dirname( unicode(sys.executable, sys.getfilesystemencoding())) return os.path.dirname(unicode(__file__, sys.getfilesystemencoding())) def main(argv): app = SimpleSCardApp( appname='A tool to send apdu to a card', apppanel=SampleAPDUManagerPanel, appstyle=TR_SMARTCARD | TR_READER | PANEL_APDUTRACER, appicon=os.path.join(module_path(), 'images', 'mysmartcard.ico'), size=(800, 600)) app.MainLoop() if __name__ == "__main__": import sys main(sys.argv) pyscard-1.6.14/smartcard/Examples/scard-api/0000755000175000017500000000000011747777125022431 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/Examples/scard-api/sample_listInterfaces.py0000755000175000017500000001072011747776676027340 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample for python PCSC wrapper module: List card interfaces __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 platform from smartcard.scard import * import smartcard.guid if 'winscard' == resourceManager: znewcardName = 'dummy-card' znewcardATR = \ [0x3B, 0x77, 0x94, 0x00, 0x00, 0x82, 0x30, 0x00, 0x13, 0x6C, 0x9F, 0x22] znewcardMask = \ [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] znewcardPrimGuid = \ smartcard.guid.strToGUID('{128F3806-4F70-4ccf-977A-60C390664840}') znewcardSecGuid = \ smartcard.guid.strToGUID('{EB7F69EA-BA20-47d0-8C50-11CFDEB63BBE}') try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise scard.error( 'Failed to establish context: ' + \ SCardGetErrorMessage(hresult)) print 'Context established!' try: # list interfaces for a known card if -1 != platform.platform().find('Windows-7'): expectedCard = 'Identity Device (Microsoft Generic Profile)' elif -1 != platform.platform().find('Windows-Vista-6.0'): expectedCard = 'Axalto Cryptoflex .NET' else: expectedCard = 'Schlumberger Cryptoflex 8k v2' hresult, interfaces = SCardListInterfaces( hcontext, expectedCard) if hresult != SCARD_S_SUCCESS: raise scard.error( 'Failed to list interfaces: ' + \ SCardGetErrorMessage(hresult)) print 'Interfaces for ', expectedCard, ':', interfaces # introduce a card (forget first in case it is already present) hresult = SCardForgetCardType(hcontext, znewcardName) print 'Introducing card ' + znewcardName hresult = SCardIntroduceCardType( hcontext, znewcardName, znewcardPrimGuid, znewcardPrimGuid + znewcardSecGuid, znewcardATR, znewcardMask) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to introduce card type: ' + \ SCardGetErrorMessage(hresult)) # list card interfaces hresult, interfaces = SCardListInterfaces(hcontext, znewcardName) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to list interfaces: ' + \ SCardGetErrorMessage(hresult)) for i in interfaces: print 'Interface for ' + znewcardName + ' :', \ smartcard.guid.GUIDToStr(i) print 'Forgeting card ' + znewcardName hresult = SCardForgetCardType(hcontext, znewcardName) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to remove card type: ' + \ SCardGetErrorMessage(hresult)) finally: hresult2 = SCardReleaseContext(hcontext) if hresult2 != SCARD_S_SUCCESS: raise error( 'Failed to release context: ' + \ SCardGetErrorMessage(hresult)) print 'Released context.' except error: import sys print sys.exc_info()[0], ':', sys.exc_info()[1] elif 'pcsclite' == resourceManager: print 'SCardListInterfaces not supported by pcsc lite' import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/scard-api/sample_getAttrib.py0000755000175000017500000001516111747776676026312 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample for python PCSC wrapper module: List card attributes __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 struct from smartcard.scard import * import smartcard.util if 'pcsclite-tiger' == resourceManagerSubType: attributes = {} else: attributes = { SCARD_ATTR_ATR_STRING: 'SCARD_ATTR_ATR_STRING', SCARD_ATTR_CHANNEL_ID: 'SCARD_ATTR_CHANNEL_ID', SCARD_ATTR_CHARACTERISTICS: 'SCARD_ATTR_CHARACTERISTICS', SCARD_ATTR_CURRENT_BWT: 'SCARD_ATTR_CURRENT_BWT', SCARD_ATTR_CURRENT_CLK: 'SCARD_ATTR_CURRENT_CLK', SCARD_ATTR_CURRENT_CWT: 'SCARD_ATTR_CURRENT_CWT', SCARD_ATTR_CURRENT_D: 'SCARD_ATTR_CURRENT_D', SCARD_ATTR_CURRENT_EBC_ENCODING: 'SCARD_ATTR_CURRENT_EBC_ENCODING', SCARD_ATTR_CURRENT_F: 'SCARD_ATTR_CURRENT_F', SCARD_ATTR_CURRENT_IFSC: 'SCARD_ATTR_CURRENT_IFSC', SCARD_ATTR_CURRENT_IFSD: 'SCARD_ATTR_CURRENT_IFSD', SCARD_ATTR_CURRENT_IO_STATE: 'SCARD_ATTR_CURRENT_IO_STATE', SCARD_ATTR_CURRENT_N: 'SCARD_ATTR_CURRENT_N', SCARD_ATTR_CURRENT_PROTOCOL_TYPE: 'SCARD_ATTR_CURRENT_PROTOCOL_TYPE', SCARD_ATTR_CURRENT_W: 'SCARD_ATTR_CURRENT_W', SCARD_ATTR_DEFAULT_CLK: 'SCARD_ATTR_DEFAULT_CLK', SCARD_ATTR_DEFAULT_DATA_RATE: 'SCARD_ATTR_DEFAULT_DATA_RATE', SCARD_ATTR_DEVICE_FRIENDLY_NAME_A: 'SCARD_ATTR_DEVICE_FRIENDLY_NAME_A', SCARD_ATTR_DEVICE_FRIENDLY_NAME_W: 'SCARD_ATTR_DEVICE_FRIENDLY_NAME_W', SCARD_ATTR_DEVICE_IN_USE: 'SCARD_ATTR_DEVICE_IN_USE', SCARD_ATTR_DEVICE_SYSTEM_NAME_A: 'SCARD_ATTR_DEVICE_SYSTEM_NAME_A', SCARD_ATTR_DEVICE_SYSTEM_NAME_W: 'SCARD_ATTR_DEVICE_SYSTEM_NAME_W', SCARD_ATTR_DEVICE_UNIT: 'SCARD_ATTR_DEVICE_UNIT', SCARD_ATTR_ESC_AUTHREQUEST: 'SCARD_ATTR_ESC_AUTHREQUEST', SCARD_ATTR_ESC_CANCEL: 'SCARD_ATTR_ESC_CANCEL', SCARD_ATTR_ESC_RESET: 'SCARD_ATTR_ESC_RESET', SCARD_ATTR_EXTENDED_BWT: 'SCARD_ATTR_EXTENDED_BWT', SCARD_ATTR_ICC_INTERFACE_STATUS: 'SCARD_ATTR_ICC_INTERFACE_STATUS', SCARD_ATTR_ICC_PRESENCE: 'SCARD_ATTR_ICC_PRESENCE', SCARD_ATTR_ICC_TYPE_PER_ATR: 'SCARD_ATTR_ICC_TYPE_PER_ATR', SCARD_ATTR_MAXINPUT: 'SCARD_ATTR_MAXINPUT', SCARD_ATTR_MAX_CLK: 'SCARD_ATTR_MAX_CLK', SCARD_ATTR_MAX_DATA_RATE: 'SCARD_ATTR_MAX_DATA_RATE', SCARD_ATTR_MAX_IFSD: 'SCARD_ATTR_MAX_IFSD', SCARD_ATTR_POWER_MGMT_SUPPORT: 'SCARD_ATTR_POWER_MGMT_SUPPORT', SCARD_ATTR_SUPRESS_T1_IFS_REQUEST: 'SCARD_ATTR_SUPRESS_T1_IFS_REQUEST', SCARD_ATTR_USER_AUTH_INPUT_DEVICE: 'SCARD_ATTR_USER_AUTH_INPUT_DEVICE', SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE: \ 'SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE', SCARD_ATTR_VENDOR_IFD_SERIAL_NO: 'SCARD_ATTR_VENDOR_IFD_SERIAL_NO', SCARD_ATTR_VENDOR_IFD_TYPE: 'SCARD_ATTR_VENDOR_IFD_TYPE', SCARD_ATTR_VENDOR_IFD_VERSION: 'SCARD_ATTR_VENDOR_IFD_VERSION', SCARD_ATTR_VENDOR_NAME: 'SCARD_ATTR_VENDOR_NAME'} if 'pcsclite' == resourceManager: extra_attributes = { SCARD_ATTR_ASYNC_PROTOCOL_TYPES: 'SCARD_ATTR_ASYNC_PROTOCOL_TYPES', SCARD_ATTR_SYNC_PROTOCOL_TYPES: 'SCARD_ATTR_SYNC_PROTOCOL_TYPES'} attributes.update(extra_attributes) def printAttribute(attrib, value): print '-----------------', attributes[attrib], '-----------------' print value print smartcard.util.toHexString(value, smartcard.util.HEX) print apply(struct.pack, ['<' + 'B' * len(value)] + value) try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to establish context: ' + \ SCardGetErrorMessage(hresult)) print 'Context established!' try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to list readers: ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Readers:', readers if len(readers) < 1: raise error('No smart card readers') print 'Trying to retreive attributes of', readers[0] for reader in readers: hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) if hresult != SCARD_S_SUCCESS: print error, \ 'Unable to connect: ' + SCardGetErrorMessage(hresult) else: print 'Connected with active protocol', dwActiveProtocol try: for i in attributes.keys(): hresult, attrib = SCardGetAttrib(hcard, i) if hresult == SCARD_S_SUCCESS: printAttribute(i, attrib) else: print '-----------------', \ attributes[i], \ '-----------------' print 'unsupported' finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to disconnect: ' + \ SCardGetErrorMessage(hresult)) print 'Disconnected' finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to release context: ' + \ SCardGetErrorMessage(hresult)) print 'Released context.' except Exception, e: print e import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/scard-api/sample_readerGroups.py0000755000175000017500000001357311747776676027034 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample for python PCSC wrapper module: illustrate reader groups functions __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from smartcard.scard import * newgroup = 'MyReaderGroup' try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to establish context: ' + \ SCardGetErrorMessage(hresult)) print 'Context established!' try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to list readers: ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Readers in all groups:', readers hresult, readerGroups = SCardListReaderGroups(hcontext) if hresult != SCARD_S_SUCCESS: raise error( 'Unable to list reader groups: ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Reader groups:', readerGroups if 'winscard' == resourceManager: hresult = SCardIntroduceReaderGroup(hcontext, newgroup) if hresult != SCARD_S_SUCCESS: raise error( 'Unable to introduce reader group: ' + \ SCardGetErrorMessage(hresult)) dummyreader = readers[0] + ' dummy' hresult = SCardIntroduceReader(hcontext, dummyreader, readers[0]) if hresult != SCARD_S_SUCCESS: raise error( 'Unable to introduce reader: ' + \ dummyreader + ' : ' + \ SCardGetErrorMessage(hresult)) hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to list readers: ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Readers in all groups:', readers hresult = SCardAddReaderToGroup(hcontext, dummyreader, newgroup) if hresult != SCARD_S_SUCCESS: raise error( 'Unable to add reader to group: ' + \ SCardGetErrorMessage(hresult)) hresult, readerGroups = SCardListReaderGroups(hcontext) if hresult != SCARD_S_SUCCESS: raise error( 'Unable to list reader groups: ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Reader groups:', readerGroups hresult, readers = SCardListReaders(hcontext, [newgroup]) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to list readers in group ' + \ newgroup + ' : ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Readers in reader group', newgroup, ':', readers hresult = SCardRemoveReaderFromGroup( hcontext, dummyreader, newgroup) if hresult != SCARD_S_SUCCESS: raise error( 'Unable to remove reader from group: ' + \ SCardGetErrorMessage(hresult)) hresult, readerGroups = SCardListReaderGroups(hcontext) if hresult != SCARD_S_SUCCESS: raise error( 'Unable to list reader groups: ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Reader groups:', readerGroups hresult = SCardForgetReaderGroup(hcontext, newgroup) if hresult != SCARD_S_SUCCESS: raise error( 'Unable to forget reader group: ' + \ SCardGetErrorMessage(hresult)) hresult = SCardForgetReader(hcontext, dummyreader) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to forget readers ' + \ SCardGetErrorMessage(hresult)) hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to list readers: ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Readers in all groups:', readers elif 'pcsclite' == resourceManager: hresult, readers = SCardListReaders(hcontext, readerGroups) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to list readers in groups ' + \ repr(readerGroups) + ' : ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Readers in reader group', readerGroups, ':', readers finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to release context: ' + \ SCardGetErrorMessage(hresult)) print 'Released context.' import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) except error, e: print e pyscard-1.6.14/smartcard/Examples/scard-api/sample_listCards.py0000755000175000017500000000613611747776676026317 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample for python PCSC wrapper module: List cards introduced in the system __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from smartcard.scard import * if 'winscard' == resourceManager: # Cryptoflex 8k v2 is introduced in standard Windows 2000 slbCryptoFlex8kv2ATR = \ [0x3B, 0x95, 0x15, 0x40, 0x00, 0x68, 0x01, 0x02, 0x00, 0x00] try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to establish context: ' + \ SCardGetErrorMessage(hresult)) print 'Context established!' try: hresult, card = SCardListCards(hcontext, slbCryptoFlex8kv2ATR, []) if hresult != SCARD_S_SUCCESS: raise error( 'Failure to locate Schlumberger Cryptoflex 8k v2 card: ' +\ SCardGetErrorMessage(hresult)) print 'Located by ATR:', card hresult, cards = SCardListCards(hcontext, [], []) if hresult != SCARD_S_SUCCESS: raise error( 'Failure to list cards: ' + \ SCardGetErrorMessage(hresult)) print 'Cards:', cards for i in cards: hresult, providerguid = SCardGetCardTypeProviderName( hcontext, i, SCARD_PROVIDER_PRIMARY) if hresult == SCARD_S_SUCCESS: print i, 'Primary provider:', providername hresult, providername = SCardGetCardTypeProviderName( hcontext, i, SCARD_PROVIDER_CSP) if hresult == SCARD_S_SUCCESS: print i, 'CSP Provider:', providername finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to release context: ' + \ SCardGetErrorMessage(hresult)) print 'Released context.' except error, e: print e elif 'pcsclite' == resourceManager: print 'SCardListCards not supported by pcsc lite' import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/scard-api/sample_readers.py0000755000175000017500000000431711747776676026013 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample for python PCSC wrapper module: List PCSC readers __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from smartcard.scard import * try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to establish context: ' + \ SCardGetErrorMessage(hresult)) print 'Context established!' try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to list readers: ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Readers:', readers hresult, readerGroups = SCardListReaderGroups(hcontext) if hresult != SCARD_S_SUCCESS: raise error( 'Unable to list reader groups: ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Reader groups:', readerGroups finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to release context: ' + \ SCardGetErrorMessage(hresult)) print 'Released context.' import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) except error, e: print e pyscard-1.6.14/smartcard/Examples/scard-api/sample_getATR.py0000755000175000017500000000660011747776676025511 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample for python PCSC wrapper module: get card ATR in first pcsc reader __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from smartcard.scard import * import smartcard.util try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to establish context: ' + \ SCardGetErrorMessage(hresult)) print 'Context established!' try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to list readers: ' + \ SCardGetErrorMessage(hresult)) if len(readers) < 1: raise Exception('No smart card readers') print 'PCSC Readers:', readers for reader in readers: print 'Trying to retreive ATR of card in', reader hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) if hresult != SCARD_S_SUCCESS: print 'Unable to connect: ' + SCardGetErrorMessage(hresult) else: print 'Connected with active protocol', dwActiveProtocol try: hresult, reader, state, protocol, atr = SCardStatus(hcard) if hresult != SCARD_S_SUCCESS: print 'failed to get status: ' + \ SCardGetErrorMessage(hresult) print 'Reader:', reader print 'State:', hex(state) print 'Protocol:', protocol print 'ATR:', smartcard.util.toHexString( atr, smartcard.util.HEX) finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: print 'Failed to disconnect: ' + \ SCardGetErrorMessage(hresult) print 'Disconnected' finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error('Failed to release context: ' + \ SCardGetErrorMessage(hresult)) print 'Released context.' except Exception, e: print e import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/scard-api/sample_selectDFTelecom.py0000755000175000017500000001026411747776676027366 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample for python PCSC wrapper module: Select DF_TELECOM on a SIM card __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from smartcard.scard import * import smartcard.util SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] GET_RESPONSE = [0xA0, 0xC0, 0x00, 0x00] try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to establish context : ' + \ SCardGetErrorMessage(hresult)) print 'Context established!' try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to list readers: ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Readers:', readers if len(readers) < 1: raise error('No smart card readers') for zreader in readers: print 'Trying to select DF_TELECOM of card in', zreader try: hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, zreader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) if hresult != SCARD_S_SUCCESS: raise error( 'Unable to connect: ' + \ SCardGetErrorMessage(hresult)) print 'Connected with active protocol', dwActiveProtocol try: hresult, response = SCardTransmit( hcard, dwActiveProtocol, SELECT + DF_TELECOM) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to transmit: ' + \ SCardGetErrorMessage(hresult)) print 'Selected DF_TELECOM: ' + \ smartcard.util.toHexString( response, smartcard.util.HEX) hresult, response = SCardTransmit( hcard, dwActiveProtocol, GET_RESPONSE + [response[1]]) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to transmit: ' + \ SCardGetErrorMessage(hresult)) print 'GET_RESPONSE after SELECT DF_TELECOM: ' + \ smartcard.util.toHexString( response, smartcard.util.HEX) finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to disconnect: ' + \ SCardGetErrorMessage(hresult)) print 'Disconnected' except error, (message): print error, message finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to release context: ' + \ SCardGetErrorMessage(hresult)) print 'Released context.' except error, e: print e import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/scard-api/sample_control.py0000755000175000017500000001050311747776676026040 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample for python PCSC wrapper module: send a Control Code to a card or reader __author__ = "Ludovic Rousseau" Copyright 2007-2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from smartcard.scard import * from smartcard.util import toBytes try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to establish context: ' + SCardGetErrorMessage(hresult)) print 'Context established!' try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to list readers: ' + SCardGetErrorMessage(hresult)) print 'PCSC Readers:', readers if len(readers) < 1: raise error('No smart card readers') for zreader in readers: print 'Trying to Control reader:', zreader try: hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, zreader, SCARD_SHARE_DIRECT, SCARD_PROTOCOL_T0) if hresult != SCARD_S_SUCCESS: raise error( 'Unable to connect: ' + SCardGetErrorMessage(hresult)) print 'Connected with active protocol', dwActiveProtocol try: if 'winscard' == resourceManager: # IOCTL_SMARTCARD_GET_ATTRIBUTE = SCARD_CTL_CODE(2) hresult, response = SCardControl( hcard, SCARD_CTL_CODE(2), toBytes("%.8lx" % SCARD_ATTR_VENDOR_NAME)) if hresult != SCARD_S_SUCCESS: raise error( 'SCardControl failed: ' +\ SCardGetErrorMessage(hresult)) r = "" for i in xrange(len(response)): r += "%c" % response[i] print 'SCARD_ATTR_VENDOR_NAME:', r elif 'pcsclite' == resourceManager and \ not 'pcsclite-tiger' == resourceManagerSubType: # get firmware on Gemplus readers hresult, response = SCardControl( hcard, SCARD_CTL_CODE(1), [0x02]) if hresult != SCARD_S_SUCCESS: raise error( 'SCardControl failed: ' + \ SCardGetErrorMessage(hresult)) r = "" for i in xrange(len(response)): r += "%c" % response[i] print 'Control:', r finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to disconnect: ' + \ SCardGetErrorMessage(hresult)) print 'Disconnected' except error, (message): print error, message finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to release context: ' + \ SCardGetErrorMessage(hresult)) print 'Released context.' except error, e: print e import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/scard-api/sample_locateCards.py0000755000175000017500000001146611747776676026615 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample for python PCSC wrapper module: Locate cards in the system __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from smartcard.scard import * if 'winscard' == resourceManager: znewcardName = 'dummy-card' znewcardATR = \ [0x3B, 0x77, 0x94, 0x00, 0x00, 0x82, 0x30, 0x00, 0x13, 0x6C, 0x9F, 0x22] znewcardMask = \ [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise scard.error( 'Failed to establish context: ' + \ SCardGetErrorMessage(hresult)) print 'Context established!' try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise scard.error( 'Failed to list readers: ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Readers:', readers # introduce a card (forget first in case it is already present) hresult = SCardForgetCardType(hcontext, znewcardName) print 'Introducing card ' + znewcardName hresult = SCardIntroduceCardType(hcontext, znewcardName, [], [], znewcardATR, znewcardMask) if hresult != SCARD_S_SUCCESS: if hresult == ERROR_ALREADY_EXISTS: print 'Card already exists' else: raise error( 'Failed to introduce card type: ' + \ SCardGetErrorMessage(hresult)) hresult, cards = SCardListCards(hcontext, [], []) if hresult != SCARD_S_SUCCESS: raise error('Failure to list cards') print 'Cards:', cards readerstates = [] for i in xrange(len(readers)): readerstates += [(readers[i], SCARD_STATE_UNAWARE)] print readerstates hresult, newstates = SCardLocateCards( hcontext, cards, readerstates) for i in newstates: reader, eventstate, atr = i print reader, for b in atr: print "0x%.2X" % b, print "" if eventstate & SCARD_STATE_ATRMATCH: print 'Card found' if eventstate & SCARD_STATE_UNAWARE: print 'State unware' if eventstate & SCARD_STATE_IGNORE: print 'Ignore reader' if eventstate & SCARD_STATE_UNAVAILABLE: print 'Reader unavailable' if eventstate & SCARD_STATE_EMPTY: print 'Reader empty' if eventstate & SCARD_STATE_PRESENT: print 'Card present in reader' if eventstate & SCARD_STATE_EXCLUSIVE: print 'Card allocated for exclusive use' if eventstate & SCARD_STATE_INUSE: print 'Card in use but can be shared' if eventstate & SCARD_STATE_MUTE: print 'Card is mute' if eventstate & SCARD_STATE_CHANGED: print 'State changed' if eventstate & SCARD_STATE_UNKNOWN: print 'State unknowned' finally: hresult = SCardForgetCardType(hcontext, znewcardName) hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to release context: ' + \ SCardGetErrorMessage(hresult)) print 'Released context.' except error, e: print e elif 'pcsclite' == resourceManager: print 'SCardLocateCards not supported by pcsc lite' import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/scard-api/sample_getStatusChange.py0000755000175000017500000000752111747776676027457 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample for python PCSC wrapper module: Detect card insertion/removal __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from smartcard.scard import * import smartcard.util srTreeATR = \ [0x3B, 0x77, 0x94, 0x00, 0x00, 0x82, 0x30, 0x00, 0x13, 0x6C, 0x9F, 0x22] srTreeMask = \ [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] def printstate(state): reader, eventstate, atr = state print reader + " " + smartcard.util.toHexString(atr, smartcard.util.HEX) if eventstate & SCARD_STATE_ATRMATCH: print '\tCard found' if eventstate & SCARD_STATE_UNAWARE: print '\tState unware' if eventstate & SCARD_STATE_IGNORE: print '\tIgnore reader' if eventstate & SCARD_STATE_UNAVAILABLE: print '\tReader unavailable' if eventstate & SCARD_STATE_EMPTY: print '\tReader empty' if eventstate & SCARD_STATE_PRESENT: print '\tCard present in reader' if eventstate & SCARD_STATE_EXCLUSIVE: print '\tCard allocated for exclusive use by another application' if eventstate & SCARD_STATE_INUSE: print '\tCard in used by another application but can be shared' if eventstate & SCARD_STATE_MUTE: print '\tCard is mute' if eventstate & SCARD_STATE_CHANGED: print '\tState changed' if eventstate & SCARD_STATE_UNKNOWN: print '\tState unknowned' try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to establish context: ' + \ SCardGetErrorMessage(hresult)) print 'Context established!' try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to list readers: ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Readers:', readers readerstates = [] for i in xrange(len(readers)): readerstates += [(readers[i], SCARD_STATE_UNAWARE)] print '----- Current reader and card states are: -------' hresult, newstates = SCardGetStatusChange(hcontext, 0, readerstates) for i in newstates: printstate(i) print '----- Please insert or remove a card ------------' hresult, newstates = SCardGetStatusChange( hcontext, INFINITE, newstates) print '----- New reader and card states are: -----------' for i in newstates: printstate(i) finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to release context: ' + \ SCardGetErrorMessage(hresult)) print 'Released context.' import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) except error, e: print e pyscard-1.6.14/smartcard/Examples/scard-api/sample_transaction.py0000755000175000017500000001013311747776676026704 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample for python PCSC wrapper module: perform a simple transaction __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from smartcard.scard import * try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to establish context: ' + \ SCardGetErrorMessage(hresult)) print 'Context established!' try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error( 'Failed to list readers:: ' + \ SCardGetErrorMessage(hresult)) print 'PCSC Readers:', readers if len(readers) < 1: raise error('No smart card readers') for zreader in readers: print 'Trying to perform transaction on card in', zreader try: hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, zreader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) if hresult != SCARD_S_SUCCESS: raise error( 'unable to connect: ' + \ SCardGetErrorMessage(hresult)) print 'Connected with active protocol', dwActiveProtocol try: hresult = SCardBeginTransaction(hcard) if hresult != SCARD_S_SUCCESS: raise error( 'failed to begin transaction: ' + \ SCardGetErrorMessage(hresult)) print 'Beginning transaction' hresult, reader, state, protocol, atr = SCardStatus(hcard) if hresult != SCARD_S_SUCCESS: raise error( 'failed to get status: ' + \ SCardGetErrorMessage(hresult)) print 'ATR:', for i in xrange(len(atr)): print "0x%.2X" % atr[i], print "" finally: hresult = SCardEndTransaction(hcard, SCARD_LEAVE_CARD) if hresult != SCARD_S_SUCCESS: raise error( 'failed to end transaction: ' + \ SCardGetErrorMessage(hresult)) print 'Transaction ended' hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: raise error( 'failed to disconnect: ' + \ SCardGetErrorMessage(hresult)) print 'Disconnected' except error, (message): print error, message finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error( 'failed to release context: ' + \ SCardGetErrorMessage(hresult)) print 'Released context.' except error, e: print e import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/scard-api/sample_pinpad.py0000755000175000017500000001226611747776676025643 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample for python PCSC wrapper module: send a Control Code to a card or reader __author__ = "Ludovic Rousseau" Copyright 2009-2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from smartcard.scard import * from smartcard.util import toASCIIBytes from smartcard.pcsc.PCSCExceptions import * def can_do_verify_pin(hCard): FEATURE_VERIFY_PIN_DIRECT = 6 return parse_get_feature_request(hCard, FEATURE_VERIFY_PIN_DIRECT) def can_do_modify_pin(hCard): FEATURE_MODIFY_PIN_DIRECT = 7 return parse_get_feature_request(hCard, FEATURE_MODIFY_PIN_DIRECT) def parse_get_feature_request(hCard, feature): # check the reader can do a verify pin CM_IOCTL_GET_FEATURE_REQUEST = SCARD_CTL_CODE(3400) hresult, response = SCardControl(hcard, CM_IOCTL_GET_FEATURE_REQUEST, []) if hresult != SCARD_S_SUCCESS: raise BaseSCardException(hresult) print response while len(response) > 0: tag = response[0] if feature == tag: return (((((response[2] << 8) + \ response[3]) << 8) + \ response[4]) << 8) + \ response[5] response = response[6:] def verifypin(hCard, control=None): if None == control: control = can_do_verify_pin(hCard) if None == control: raise Exception("Not a pinpad") command = [0x00, # bTimerOut 0x00, # bTimerOut2 0x82, # bmFormatString 0x04, # bmPINBlockString 0x00, # bmPINLengthFormat 0x08, 0x04, # wPINMaxExtraDigit 0x02, # bEntryValidationCondition 0x01, # bNumberMessage 0x04, 0x09, # wLangId 0x00, # bMsgIndex 0x00, 0x00, 0x00, # bTeoPrologue 13, 0, 0, 0, # ulDataLength 0x00, 0x20, 0x00, 0x00, 0x08, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30] # abData hresult, response = SCardControl(hcard, control, command) if hresult != SCARD_S_SUCCESS: raise BaseSCardException(hresult) return hresult, response try: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise EstablishContextException(hresult) print 'Context established!' try: hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise ListReadersException(hresult) print 'PCSC Readers:', readers if len(readers) < 1: raise Exception("No smart card readers") for zreader in readers: print 'Trying to Control reader:', zreader try: hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, zreader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) if hresult != SCARD_S_SUCCESS: raise BaseSCardException(hresult) print 'Connected with active protocol', dwActiveProtocol try: SELECT = [0x00, 0xA4, 0x04, 0x00, 0x06, 0xA0, 0x00, 0x00, 0x00, 0x18, 0xFF] hresult, response = SCardTransmit( hcard, dwActiveProtocol, SELECT) if hresult != SCARD_S_SUCCESS: raise BaseSCardException(hresult) cmd_verify = can_do_verify_pin(hcard) if (cmd_verify): print "can do verify pin: 0x%08X" % cmd_verify cmd_modify = can_do_modify_pin(hcard) if (cmd_modify): print "can do modify pin: 0x%08X" % cmd_modify hresult, response = verifypin(hcard, cmd_verify) print 'Control:', response finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: raise BaseSCardException(hresult) print 'Disconnected' except error, (message): print error, message finally: hresult = SCardReleaseContext(hcontext) if hresult != SCARD_S_SUCCESS: raise ReleaseContextException(hresult) print 'Released context.' except error, e: print e import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/simple/0000755000175000017500000000000011747777125022057 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/Examples/simple/simpleAPDU.py0000755000175000017500000000314711152535001024353 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script to send 2 APDU __author__ = "Ludovic Rousseau" Copyright 2009 Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 sys from smartcard.System import readers # define the APDUs used in this script SELECT_APPLET = [0x00, 0xA4, 0x04, 0x00, 0x06, 0xA0, 0x00, 0x00, 0x00, 0x18, 0xFF] GET_TIME = [0x80, 0x38, 0x00, 0xA0] try: # get all the available readers r = readers() print "Available readers: ", r # by default we use the first reader i = 0 if len(sys.argv) > 1: i = int(sys.argv[1]) print "Using: %s" % r[i] connection = r[i].createConnection() connection.connect() data, sw1, sw2 = connection.transmit(SELECT_APPLET) print "Select Applet: %02X %02X" % (sw1, sw2) data, sw1, sw2 = connection.transmit(GET_TIME) print "Get Time: %02X %02X" % (sw1, sw2) except: print sys.exc_info()[1] pyscard-1.6.14/smartcard/Examples/simple/getATR.py0000755000175000017500000000271511747776676023601 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script that displays the ATR of inserted cards. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from smartcard.Exceptions import NoCardException from smartcard.System import readers from smartcard.util import toHexString for reader in readers(): try: connection = reader.createConnection() connection.connect() print reader, toHexString(connection.getATR()) except NoCardException: print reader, 'no card inserted' import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/Examples/simple/selectDF_TELECOM.py0000755000175000017500000000455511747776676025320 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """ Sample script that tries to select the DF_TELECOM on all inserted cards. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Copyright 2010 Ludovic Rousseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from smartcard.CardType import AnyCardType from smartcard.CardRequest import CardRequest from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.Exceptions import CardRequestTimeoutException # define the apdus used in this script GET_RESPONSE = [0XA0, 0XC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] # request any card type cardtype = AnyCardType() try: # request card insertion print 'insert a card (SIM card if possible) within 10s' cardrequest = CardRequest(timeout=10, cardType=cardtype) cardservice = cardrequest.waitforcard() # attach the console tracer observer = ConsoleCardConnectionObserver() cardservice.connection.addObserver(observer) # connect to the card and perform a few transmits cardservice.connection.connect() apdu = SELECT + DF_TELECOM response, sw1, sw2 = cardservice.connection.transmit(apdu) # there is a DF_TELECOM if sw1 == 0x9F: apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = cardservice.connection.transmit(apdu) else: print 'no DF_TELECOM' except CardRequestTimeoutException: print 'time-out: no card inserted during last 10s' except: import sys print sys.exc_info()[1] import sys if 'win32' == sys.platform: print 'press Enter to continue' sys.stdin.read(1) pyscard-1.6.14/smartcard/README0000644000175000017500000003615711747776700017702 0ustar rousseaurousseau00000000000000------------------------------------------------------------------------------- pyscard smartcard library for python ------------------------------------------------------------------------------- http://pyscard.sourceforge.net/ ------------------------------------------------------------------------------- Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 ------------------------------------------------------------------------------- Last update : pyscard 1.6.14 (April 2012) ------------------------------------------------------------------------------- pyscard is a python module adding smart cards support to python. It consists of the smartcard.scard module, an extension module wrapping Windows smart card base components (also known as PCSC) on Windows, and PCSC lite on linux and Mac OS X Tiger, and of the smartcard module, a python framework with objects wrapping PCSC API. ------------------------------------------------------------------------------- Documentation ------------------------------------------------------------------------------- All documentation is provided in the smartcard/doc directory of the source distribution. Examples are provided in the smartcard/Examples directory of the source distribution. The binary distribution does not include any documentation, tests scripts or examples. ------------------------------------------------------------------------------- Installation ------------------------------------------------------------------------------- The pyscard library is packaged using the standard distutils python module. Installation on windows ----------------------- Installing on windows from the binary distribution -------------------------------------------------- 1. download the binary msi installer or self-executable installer 2. execute the installer The binary msi installer and self-executable installer are packaged for a specific version of python, and have name similar to pyscard-1.6.14.win32-py2.5.msi and pyscard-1.6.14.win32-py2.5.exe for python 2.5. Installing on windows from the source distribution --------------------------------------------------- 1. you will need swig 1.3.31 from http://www.swig.org, and a C compiler. By default, Visual Studio 2003 is required for building the c language wrapper for python 2.5, and Visual Studio .Net or VisualC++ 6 for python 2.4. You might use another release by fiddling with the python/Lib/distutils/msvccompiler.py file that detects the compiler. 2. download the source distribution The source distribution is available as pyscard-1.6.14.zip for windows, and pyscard-1.6.14.tar.gz for linux. 3. unzip the source distribution, open a console and type the following: setup.py build_ext install This will build pyscard and install it in the site-packages directory of your python distribution, e.g. c:\python25\Lib\site-packages\smartcard. This install procedure does not install the documentation, examples or test files. Installation on linux: ---------------------- Installing on linux from the binary distribution: ------------------------------------------------- 1. download the binary distribution The binary distribution is either an archive file or a rpm file, with names similar to pyscard-1.6.14-1.i386.rpm for the rpm distribution, or pyscard-1.6.14.linux-i686.tar.gz for the archive distribution. 2. untar the binary distribution With root privilege from a terminal, extract the archive from /, or install the rpm. Installing on linux from the source distribution ------------------------------------------------ 1. you will need gcc, swig 1.3.31 (http://www.swig.org), and pcsc-lite (http://pcsclite.alioth.debian.org/) 2. download the source distribution The source distribution is available as pyscard-1.6.14.zip or pyscard-1.6.14.tar.gz. 3. untar the source distribution 4. from a terminal with root privileges, type the following: /usr/bin/python setup.py build_ext install This will build pyscard and install it in the site-packages directory of your python distribution, e.g. /usr/lib/python2.4/site-packages/smartcard. Installation on Max OS X Tiger: -------------------------------- The Mac OS X Tiger support is experimental on pyscard 1.6.14. It was developed and tested on a i386 MacBook Pro. Please drop me a mail if you succeed on a ppc MacBook. Installing on Mac OS X Tiger from the binary distribution: ---------------------------------------------------- 1. download the binary distribution The binary distribution is an archive file, with a name similar to pyscard-1.6.14-py-2.3-macosx10.4.mpkg or pyscard-1.6.14-py-2.5-macosx10.4.mpkg. 2. Open the package and proceed with installation. Python 2.3 is pre-installed, so install pyscard-1.6.14-py-2.3-macosx10.4.mpkg if you did not install another release of python. Install pyscard-1.6.14-py-2.5-macosx10.4.mpkg if you installed python 2.5. Installing on Mac OS X Tiger from the source distribution ---------------------------------------------------------- 1. you will need swig 1.3.31 (http://www.swig.org); gcc and pcsc-lite are available out of the box on Max OS X Tiger 2. download the source distribution The source distribution is available as pyscard-1.6.14.zip or pyscard-1.6.14.tar.gz. 3. untar or unzip the source distribution 4. from a terminal, type the following: sudo python setup.py build_ext install This will build pyscard and install it in the site-packages directory of your python distribution, e.g. /System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/lib/site-packages/smartcard Installation on Max OS X Leopard: --------------------------------- Installing on Mac OS X Leopard from the binary distribution: ---------------------------------------------------- 1. download the binary distribution The binary distribution is an archive file, with a name similar to pyscard-1.6.14-py-2.5-macosx10.5.mpkg. 2. Open the package and proceed with installation. Installing on Mac OS X Leopard from the source distribution ------------------------------------------------------------ 1. you will need swig 1.3.31 (http://www.swig.org); gcc and pcsc-lite are available out of the box on Max OS X Leopard 2. download the source distribution The source distribution is available as pyscard-1.6.14.zip or pyscard-1.6.14.tar.gz. 3. untar or unzip the source distribution 4. from a terminal, type the following: sudo python setup.py build_ext install This will build pyscard and install it in the site-packages directory of your python distribution, e.g. /System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.3/lib/site-packages/smartcard Installation on Max OS X Lion: ------------------------------ Installing on Mac OS X Lion from the binary distribution: ---------------------------=====------------------------- 1. download the binary distribution The binary distribution is an archive file, with a name similar to pyscard-1.6.14-py-2.7-macosx10.7.mpkg. 2. Open the package and proceed with installation. Installing on Mac OS X Lion from the source distribution -------------------------------------------------------- 1. you will need swig 2.0.4 (http://www.swig.org) and Xcode (http://developer.apple.com/xcode/); pcsc-lite is available out of the box on Max OS X Leopard 2. download the source distribution The source distribution is available as pyscard-1.6.14.zip or pyscard-1.6.14.tar.gz. 3. untar or unzip the source distribution 4. from a terminal, type the following: sudo python setup.py build_ext install This will build pyscard and install it in the site-packages directory of your python distribution, e.g. /Library/Python/2.7/lib/site-packages/smartcard ------------------------------------------------------------------------------- Developer documentation, unit tests and examples ------------------------------------------------------------------------------- The developer documentation is in the smartcard/doc directory of the source distribution. Examples are located in the smartcard/Examples directory, and the pyunit unit tests in the smartcard/test directory. ------------------------------------------------------------------------------- Build instructions for packagers ------------------------------------------------------------------------------- Building a binary distribution for Windows ------------------------------------------ To build a binary distribution from the source distribution, you will need a C compiler and swig 1.3.31 (same requirements as for installing from the source distribution). In the root directory of the source distribution, execute the following command in a console: setup.py build_ext bdist_msi setup.py build_ext bdist_wininst This will build the msi installer and self-executable installer in the dist directory, with names similar to pyscard-1.6.14.win32-py2.5.msi and pyscard-1.6.14.win32-py2.5.exe for python 2.5, and pyscard-1.6.14.win32-py2.4.msi and pyscard-1.6.14.win32-py2.4.exe for python 2.4. Building a binary distribution for linux ---------------------------------------- To build a binary distribution from the source distribution, you will need gcc, swig 1.3.31 and pcsc-lite (same requirements as for installing from the source distribution). In the root directory of the source distribution, execute the following command in a terminal: /usr/bin/python setup.py build_ext bdist This will build a package similar to pyscard-1.6.14.linux-i686.tar.gz containing a tree Building a rpm distribution for linux ---------------------------------------- To build a rpm distribution from the source distribution, you will need gcc, swig 1.3.31 and pcsc-lite (same requirements as for installing from the source distribution). In the root directory of the source distribution, execute the following command in a terminal: /usr/bin/python setup.py build bdist_rpm If you have rpm 4.1 or above, you will need to add the %_unpackaged_files_terminate_build 0 options to the /etc/rpm/macros file, e.g.: echo "%_unpackaged_files_terminate_build 0" >> /etc/rpm/macros This will build in the dist directory a binary distribution with a name similar to pyscard-1.6.14-1.i386.rpm. Building a binary distribution for Mac OS X Tiger ------------------------------------------------- To build a binary distribution from the source distribution, you will need swig 1.3.31 (same requirements as for installing from the source distribution) and bdist_mpkg 0.4.3 (http://cheeseshop.python.org/pypi/bdist_mpkg/). If you are using the pre-installed python 2.3 distribution, in the root directory of the source distribution, i.e. in the src directory, execute the following commands in a terminal: python setup.py build_ext /System/Library/Frameworks/Python.Framework/Versions/2.3/bin/bdist_mpkg setup.py This will build package pyscard-1.6.14-py-2.3-macosx10.4.mpkg. If you are using python 2.5, in the root directory of the source distribution, i.e. in the src directory, execute the following commands in a terminal: python setup.py build_ext /Library/Frameworks/Python.Framework/Versions/2.5/bin/bdist_mpkg setup.py This will build package pyscard-1.6.14-py-2.6-macosx10.4.mpkg. Building a binary distribution for Mac OS X Lion ------------------------------------------------- To build a binary distribution from the source distribution, you will need swig 2.0.4 and Xcode (same requirements as for installing from the source distribution) and bdist_mpkg 0.4.4 (http://pypi.python.org/pypi/bdist_mpkg/). Install bdist_mpkg by executing the bdist_mpkg setup.py script with build and install as arguments, i.e. from the root directory of the bdist_mpkg source distribution enter: python setup.py build install. From the root directory of the pyscard source distribution, i.e. in the src directory, execute the following commands in a terminal: python setup.py build_ext bdist_mpkg setup.py This will build package pyscard-1.6.14-py-2.7-macosx10.7.mpkg in the dist directory. Building a binary distribution for Mac OS X Leopard --------------------------------------------------- To build a binary distribution from the source distribution, you will need swig 1.3.31 (same requirements as for installing from the source distribution) and bdist_mpkg 0.4.3 (http://cheeseshop.python.org/pypi/bdist_mpkg/). Apply the following patch to tools.py of bdist_mpkg package: ===== patch start === diff -rNu bdist_mpkg-0.4.3/bdist_mpkg/tools.py bdist_mpkg-0.4.3.leopard/bdist_mpkg/tools.py --- bdist_mpkg-0.4.3/bdist_mpkg/tools.py 2006-07-09 00:39:00.000000000 -0400 +++ bdist_mpkg-0.4.3.leopard/bdist_mpkg/tools.py 2008-08-21 07:43:35.000000000 -0400 @@ -79,15 +79,12 @@ yield os.path.join(root, fn) def get_gid(name, _cache={}): - if not _cache: - for line in os.popen('/usr/bin/nidump group .'): - fields = line.split(':') - if len(fields) >= 3: - _cache[fields[0]] = int(fields[2]) - try: - return _cache[name] - except KeyError: - raise ValueError('group %s not found' % (name,)) + for line in os.popen("dscl . -read /Groups/" + name + " PrimaryGroupID"): + fields = [f.strip() for f in line.split(':')] + if fields[0] == "PrimaryGroupID": + return fields[1] + + raise ValueError('group %s not found' % (name,)) ===== patch end ======== This patch is required since Mac OS X Leopard does not have the nidump command any more. Install bdist_mpkg by executing the bdist_mpkg setup.py script with build and install as arguments, i.e. from the root directory of the bdist_mpkg source distribution enter: python setup.py build install. For python 2.5, from the root directory of the pyscard source distribution, i.e. in the src directory, execute the following commands in a terminal: python setup.py build_ext /Library/Frameworks/Python.Framework/Versions/2.5/Extras/bin/bdist_mpkg setup.py This will build package pyscard-1.6.14-py-2.5-macosx10.5.mpkg. For python 2.6, from the root directory of the pyscard source distribution, i.e. in the src directory, execute the following commands in a terminal: python setup.py build_ext /Library/Frameworks/Python.framework/Versions/2.6/bin/bdist_mpkg setup.py This will build package pyscard-1.6.14-py-2.6-macosx10.5.mpkg. ------------------------------------------------------------------------------- Issue Tracking ------------------------------------------------------------------------------- If you encounter a bug, please report it in the SourceForge bug tracker at http://sourceforge.net/tracker/?group_id=196342&atid=957072 https://sourceforge.net/tracker/?group_id=196342&atid=957072 -jda pyscard-1.6.14/smartcard/CardType.py0000644000175000017500000000664511747776700021106 0ustar rousseaurousseau00000000000000"""Abstract CarType. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.System import readers from smartcard.util import toHexString class CardType(object): """Abstract base class for CardTypes. Known sub-classes: smartcard.CardType.AnyCardType smartcard.CardType.ATRCardType.""" def __init__(self): """CardType constructor.""" pass def matches(self, atr, reader=None): """Returns true if atr and card connected match the CardType. atr: the atr to chek for matching reader: the reader (optional); default is None The reader can be use in some sub-classes to do advanced matching that require connecting to the card.""" pass class AnyCardType(CardType): """The AnyCardType matches any card.""" def matches(self, atr, reader=None): """Always returns true, i.e. AnyCardType matches any card. atr: the atr to chek for matching reader: the reader (optional); default is None""" return True class ATRCardType(CardType): """The ATRCardType defines a card from an ATR and a mask.""" def __init__(self, atr, mask=None): """ATRCardType constructor. atr: the ATR of the CardType mask: an optional mask to be applied to the ATR for CardType matching default is None """ self.atr = list(atr) self.mask = mask if None == mask: self.maskedatr = self.atr else: if len(self.atr) != len(self.mask): raise InvalidATRMaskLengthException(toHexString(mask)) self.maskedatr = map(lambda x, y: x & y, self.atr, self.mask) def matches(self, atr, reader=None): """Returns true if the atr matches the masked CardType atr. atr: the atr to chek for matching reader: the reader (optional); default is None When atr is compared to the CardType ATR, matches returns true if and only if CardType.atr & CardType.mask = atr & CardType.mask, where & is the bitwise logical AND.""" if len(atr) != len(self.atr): return not True if None != self.mask: maskedatr = map(lambda x, y: x & y, list(atr), self.mask) else: maskedatr = atr return self.maskedatr == maskedatr if __name__ == '__main__': """Small sample illustrating the use of CardType.py.""" r = readers() print r connection = r[0].createConnection() connection.connect() atrct = ATRCardType([0x3B, 0x16, 0x94, 0x20, 0x02, 0x01, 0x00, 0x00, 0x0D]) print atrct.matches(connection.getATR()) pyscard-1.6.14/smartcard/CardConnection.py0000644000175000017500000001711211747776700022253 0ustar rousseaurousseau00000000000000"""The CardConnection abstract class manages connections with a card and apdu transmission. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardConnectionEvent import CardConnectionEvent from smartcard.Exceptions import SmartcardException from smartcard.Observer import Observer from smartcard.Observer import Observable class CardConnection(Observable): """Card connection abstract class. Known subclasses: smartcard.pcsc.PCSCCardConnection """ T0_protocol = 0x00000001 T1_protocol = 0x00000002 RAW_protocol = 0x00010000 T15_protocol = 0x00000008 def __init__(self, reader): """Construct a new card connection. readerName: name of the reader in which the smartcard to connect to is located. """ Observable.__init__(self) self.reader = reader self.errorcheckingchain = None self.defaultprotocol = CardConnection.T0_protocol |\ CardConnection.T1_protocol def __del__(self): """Connect to card.""" pass def addSWExceptionToFilter(self, exClass): """Add a status word exception class to be filtered. exClass: the class to filter, e.g. smartcard.sw.SWException.WarningProcessingException Filtered exceptions will not be raised when encountered in the error checking chain.""" if None != self.errorcheckingchain: self.errorcheckingchain[0].addFilterException(exClass) def addObserver(self, observer): """Add a CardConnection observer.""" Observable.addObserver(self, observer) def deleteObserver(self, observer): """Remove a CardConnection observer.""" Observable.deleteObserver(self, observer) def connect(self, protocol=None, mode=None, disposition=None): """Connect to card. protocol: a bit mask of the protocols to use, from CardConnection.T0_protocol, CardConnection.T1_protocol, CardConnection.RAW_protocol, CardConnection.T15_protocol mode: passed as-is to the PC/SC layer """ Observable.setChanged(self) Observable.notifyObservers(self, CardConnectionEvent('connect')) def disconnect(self): """Disconnect from card.""" Observable.setChanged(self) Observable.notifyObservers(self, CardConnectionEvent('disconnect')) def getATR(self): """Return card ATR""" pass def getProtocol(self): """Return bit mask for the protocol of connection, or None if no protocol set. The return value is a bit mask of CardConnection.T0_protocol, CardConnection.T1_protocol, CardConnection.RAW_protocol, CardConnection.T15_protocol """ return self.defaultprotocol def getReader(self): """Return card connection reader""" return self.reader def setErrorCheckingChain(self, errorcheckingchain): """Add an error checking chain. errorcheckingchain: a smartcard.sw.ErrorCheckingChain object The error checking strategies in errorchecking chain will be tested with each received response APDU, and a smartcard.sw.SWException.SWException will be raised upon error.""" self.errorcheckingchain = errorcheckingchain def setProtocol(self, protocol): """Set protocol for card connection. protocol: a bit mask of CardConnection.T0_protocol, CardConnection.T1_protocol, CardConnection.RAW_protocol, CardConnection.T15_protocol e.g. setProtocol(CardConnection.T1_protocol | CardConnection.T0_protocol) """ self.defaultprotocol = protocol def transmit(self, bytes, protocol=None): """Transmit an apdu. Internally calls doTransmit() class method and notify observers upon command/response APDU events. Subclasses must override the doTransmit() class method. bytes: list of bytes to transmit protocol: the transmission protocol, from CardConnection.T0_protocol, CardConnection.T1_protocol, or CardConnection.RAW_protocol """ Observable.setChanged(self) Observable.notifyObservers(self, CardConnectionEvent( 'command', [bytes, protocol])) data, sw1, sw2 = self.doTransmit(bytes, protocol) Observable.setChanged(self) Observable.notifyObservers(self, CardConnectionEvent( 'response', [data, sw1, sw2])) if None != self.errorcheckingchain: self.errorcheckingchain[0](data, sw1, sw2) return data, sw1, sw2 def doTransmit(self, bytes, protocol): """Performs the command APDU transmission. Subclasses must override this method for implementing apdu transmission.""" pass def control(self, controlCode, bytes=[]): """Send a control command and buffer. Internally calls doControl() class method and notify observers upon command/response events. Subclasses must override the doControl() class method. controlCode: command code bytes: list of bytes to transmit """ Observable.setChanged(self) Observable.notifyObservers(self, CardConnectionEvent( 'command', [controlCode, bytes])) data = self.doControl(controlCode, bytes) Observable.setChanged(self) Observable.notifyObservers(self, CardConnectionEvent( 'response', data)) if None != self.errorcheckingchain: self.errorcheckingchain[0](data) return data def doControl(self, controlCode, bytes): """Performs the command control. Subclasses must override this method for implementing control.""" pass def getAttrib(self, attribId): """return the requested attribute attribId: attribute id like SCARD_ATTR_VENDOR_NAME """ Observable.setChanged(self) Observable.notifyObservers(self, CardConnectionEvent( 'attrib', [attribId])) data = self.doGetAttrib(attribId) if None != self.errorcheckingchain: self.errorcheckingchain[0](data) return data def doGetAttrib(self, attribId): """Performs the command get attrib. Subclasses must override this method for implementing get attrib.""" pass pyscard-1.6.14/smartcard/reader/0000755000175000017500000000000011747777125020252 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/reader/ReaderGroups.py0000644000175000017500000000714611747776700023234 0ustar rousseaurousseau00000000000000"""ReaderGroups manages smart card reader in groups. __author__ = "gemalto http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.Exceptions import SmartcardException from smartcard.ulist import ulist class BadReaderGroupException(SmartcardException): """Raised when trying to add an invalid reader group.""" def __init__(self): SmartcardException.__init__(self, 'Invalid reader group') class DeleteSCardDefaultReaderGroupException(SmartcardException): """Raised when trying to delete SCard$DefaultReaders reader group.""" def __init__(self): SmartcardException.__init__( self, 'SCard$DefaultReaders cannot be deleted') class innerreadergroups(ulist): """Smartcard readers groups private class. The readergroups singleton manages the creation of the unique instance of this class. """ def __init__(self, initlist=None): """Retrieve and store list of reader groups""" if None == initlist: initlist = self.getreadergroups() if None != initlist: ulist.__init__(self, initlist) self.unremovablegroups = [] def __onadditem__(self, item): """Called when a reader group is added.""" self.addreadergroup(item) def __onremoveitem__(self, item): """Called when a reader group is added.""" self.removereadergroup(item) def __iter__(self): return ulist.__iter__(self) def next(self): return ulist.__next__(self) # # abstract methods implemented in subclasses # def getreadergroups(self): """Returns the list of smartcard reader groups.""" return [] def addreadergroup(self, newgroup): """Add a reader group""" if not isinstance(newgroup, type("")): raise BadReaderGroupException self += newgroup def removereadergroup(self, group): """Remove a reader group""" if not isinstance(group, type("")): raise BadReaderGroupException self.remove(group) def addreadertogroup(self, readername, groupname): """Add a reader to a reader group""" pass def removereaderfromgroup(self, readername, groupname): """Remove a reader from a reader group""" pass class readergroups(object): """ReadersGroups organizes smart card reader as groups.""" """The single instance of __readergroups""" instance = None innerclazz = innerreadergroups def __init__(self, initlist=None): """Create a single instance of innerreadergroups on first call""" if None == readergroups.instance: readergroups.instance = self.innerclazz(initlist) """All operators redirected to inner class.""" def __getattr__(self, name): return getattr(self.instance, name) if __name__ == '__main__': print readergroups() pyscard-1.6.14/smartcard/reader/__init__.py0000644000175000017500000000000011404463363022333 0ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/reader/Reader.py0000644000175000017500000000405411747776700022027 0ustar rousseaurousseau00000000000000"""Smart card Reader abstract class. __author__ = "gemalto http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ class Reader(object): """Reader abstract class. The reader class is responsible for creating connections with a card. Known subclasses: PCSCReader """ def __init__(self, readername): """Constructs a new reader and store readername.""" self.name = readername def addtoreadergroup(self, groupname): """Add reader to a reader group.""" pass def removefromreadergroup(self, groupname): """Remove reader from a reader group.""" pass def createConnection(self): """Returns a card connection thru reader.""" pass def __eq__(self, other): """Returns True if self==other (same name).""" if type(other) == type(self): return self.name == other.name else: return False def __hash__(self): """Returns a hash value for this object (self.name is unique).""" return hash(self.name) def __repr__(self): """Returns card reader name string for `object` calls.""" return "'%s'" % self.name def __str__(self): """Returns card reader name string for str(object) calls.""" return self.name pyscard-1.6.14/smartcard/reader/ReaderFactory.py0000644000175000017500000000412411747776700023355 0ustar rousseaurousseau00000000000000"""ReaderFactory: creates smartcard readers. __author__ = "gemalto http://www.gemalto.com" Factory pattern implementation borrowed from Thinking in Python, Bruce Eckel, http://mindview.net/Books/TIPython The code to instanciate the reader Factory() has been updated to dynamically load the module with Robert Brewer ClassLoader.py. Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.ClassLoader import get_class from smartcard.pcsc.PCSCReader import PCSCReader class ReaderFactory(object): """Class to create readers from reader type id.""" factories = {} factorymethods = [PCSCReader.readers] # A Template Method: def createReader(clazz, readername): """Static method to create a reader from a reader clazz. @param module: the python module that contains the reader class @param clazz: the reader class name @param readername: the reader name """ if not clazz in ReaderFactory.factories: ReaderFactory.factories[clazz] = get_class(clazz).Factory() return ReaderFactory.factories[clazz].create(readername) createReader = staticmethod(createReader) def readers(groups=[]): zreaders = [] for fm in ReaderFactory.factorymethods: zreaders += fm(groups) return zreaders readers = staticmethod(readers) pyscard-1.6.14/smartcard/__init__.py0000644000175000017500000000223511747776700021121 0ustar rousseaurousseau00000000000000"""Smartcard utility module. The smartcard utility module provides classes and functions to access smartcards and readers. __author__ = "gemalto http://www.gemalto.com" __date__ = "May 2010" __version__ = "1.6.14" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ __all__ = ['listReaders', 'Session'] # for legacy only from smartcard.System import listReaders from smartcard.Session import Session pyscard-1.6.14/smartcard/CardService.py0000644000175000017500000000457311747776700021563 0ustar rousseaurousseau00000000000000"""Card service abstract class. A card service is a class providings specific smart card functionality, e.g. a GSM file system or an Open Platform loader. CardService is an abstract class from which concrete card services are derived. A concrete card service is almost always smart card operating system specific. The card service performs its specific smart card functionnality by accessing the smartcard with a CardConnection. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.Exceptions import SmartcardException from smartcard.scard import * class CardService(object): """Card service abstract class. Known subclasses: smartcard.PassThruCardService """ def __init__(self, connection, cardname=None): """Construct a new card service and bind to a smart card in a reader. connection: the CardConnection used to access the smart card """ self.connection = connection self.cardname = cardname def __del__(self): """Destructor. Disconnect card and destroy card service resources.""" self.connection.disconnect() def supports(cardname): pass supports = staticmethod(supports) if __name__ == '__main__': """Small sample illustrating the use of CardService.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] from smartcard.System import readers cc = readers()[0].createConnection() cs = CardService(cc) cs.connection.connect() data, sw1, sw2 = cs.connection.transmit(SELECT + DF_TELECOM) print "%X %X" % (sw1, sw2) cs.connection.disconnect() pyscard-1.6.14/smartcard/Synchronization.py0000644000175000017500000000216011747776700022560 0ustar rousseaurousseau00000000000000""" from Thinking in Python, Bruce Eckel http://mindview.net/Books/TIPython Simple emulation of Java's 'synchronized' keyword, from Peter Norvig. """ from threading import RLock def synchronized(method): def f(*args): self = args[0] self.mutex.acquire() # print method.__name__, 'acquired' try: return apply(method, args) finally: self.mutex.release() # print method.__name__, 'released' return f def synchronize(klass, names=None): """Synchronize methods in the given class. Only synchronize the methods whose names are given, or all methods if names=None.""" if type(names) == type(''): names = names.split() for (name, val) in klass.__dict__.items(): if callable(val) and name != '__init__' and \ (names == None or name in names): # print "synchronizing", name setattr(klass, name, synchronized(val)) class Synchronization(object): # You can create your own self.mutex, or inherit from this class: def __init__(self): self.mutex = RLock() pyscard-1.6.14/smartcard/Observer.py0000644000175000017500000000377311747776700021161 0ustar rousseaurousseau00000000000000""" from Thinking in Python, Bruce Eckel http://mindview.net/Books/TIPython Class support for "observer" pattern. The observer class is the base class for all smartcard package observers. Known subclasses: smartcard.ReaderObserver """ from smartcard.Synchronization import * class Observer(object): def update(observable, arg): '''Called when the observed object is modified. You call an Observable object's notifyObservers method to notify all the object's observers of the change.''' pass class Observable(Synchronization): def __init__(self): self.obs = [] self.changed = 0 Synchronization.__init__(self) def addObserver(self, observer): if observer not in self.obs: self.obs.append(observer) def deleteObserver(self, observer): self.obs.remove(observer) def notifyObservers(self, arg=None): '''If 'changed' indicates that this object has changed, notify all its observers, then call clearChanged(). Each observer has its update() called with two arguments: this observable object and the generic 'arg'.''' self.mutex.acquire() try: if not self.changed: return # Make a local copy in case of synchronous # additions of observers: localArray = self.obs[:] self.clearChanged() finally: self.mutex.release() # Update observers for observer in localArray: observer.update(self, arg) def deleteObservers(self): self.obs = [] def setChanged(self): self.changed = 1 def clearChanged(self): self.changed = 0 def hasChanged(self): return self.changed def countObservers(self): return len(self.obs) synchronize(Observable, "addObserver deleteObserver deleteObservers " + "setChanged clearChanged hasChanged " + "countObservers") #:~ pyscard-1.6.14/smartcard/util/0000755000175000017500000000000011747777125017765 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/util/__init__.py0000644000175000017500000001764211747776700022106 0ustar rousseaurousseau00000000000000# -*- coding: iso-8859-1 -*- """smartcard.util package __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ PACK = 1 HEX = 2 UPPERCASE = 4 COMMA = 8 def padd(bytelist, length, padding='FF'): """ Padds a byte list with a constant byte value (default is x0FF) bytelist: the byte list to padd length: the total length of the resulting byte list; no padding if length is smaller than the byte list length padding: padding value (default is 0xff) returns the padded bytelist example: padd(toBytes(\"3B 65 00 00 9C 11 01 01 03\"), 16) returns [0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] padd(toBytes(\"3B 65 00 00 9C 11 01 01 03\"), 8) returns [ 0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3 ] """ if len(bytelist) < length: for index in range(length - len(bytelist)): bytelist.append(eval('0x' + padding)) return bytelist def toASCIIBytes(stringtoconvert): """Returns a list of ASCII bytes from a string. stringtoconvert: the string to convert into a byte list returns a byte list of the ASCII codes of the string characters toASCIIBytes() is the reverse of toASCIIString() example: toASCIIBytes("Number 101") returns [ 0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x20, 0x31, 0x30, 0x31 ] """ return map(ord, list(stringtoconvert)) def toASCIIString(bytelist): """Returns a string representing a list of ASCII bytes. bytelist: list of ASCII bytes to convert into a string returns a string from the ASCII code list toASCIIString() is the reverse of toASCIIBytes() example: toASCIIString([0x4E,0x75,0x6D,0x62,0x65,0x72,0x20,0x31,0x30,0x31]) returns "Number 101") """ return ''.join(map(chr, bytelist)) def toBytes(bytestring): """Returns a list of bytes from a byte string bytestring: a byte string such as \"3B 65 00 00 9C 11 01 01 03\" or \"3B6500009C11010103\" or \"3B6500 009C1101 0103\" """ from struct import unpack import re packedstring = ''.join(re.split('\W+', bytestring)) try: return reduce(lambda x, y: x + [int(y, 16)], unpack('2s' * (len(packedstring) / 2), packedstring), []) except: raise TypeError('not a string representing a list of bytes') """GSM3.38 character conversion table.""" __dic_GSM_3_38__ = { '@': 0x00, # @ At symbol '£': 0x01, # £ Britain pound symbol '$': 0x02, # $ Dollar symbol chr(0xA5): 0x03, # ¥ Yen symbol 'è': 0x04, # è e accent grave 'é': 0x05, # é e accent aigu 'ù': 0x06, # ù u accent grave chr(0xEC): 0x07, # ì i accent grave chr(0xF2): 0x08, # ò o accent grave chr(0xC7): 0x09, # Ç C majuscule cedille chr(0x0A): 0x0A, # LF Line Feed chr(0xD8): 0x0B, # Ø O majuscule barré chr(0xF8): 0x0C, # ø o minuscule barré chr(0x0D): 0x0D, # CR Carriage Return chr(0xC5): 0x0E, # Å Angstroem majuscule chr(0xE5): 0x0F, # å Angstroem minuscule '_': 0x11, # underscore chr(0xC6): 0x1C, # Æ majuscule ae chr(0xE6): 0x1D, # æ minuscule ae chr(0xDF): 0x1E, # ß s dur allemand chr(0xC9): 0x1F, # É majuscule é ' ': 0x20, '!': 0x21, '\"': 0x22, # guillemet '#': 0x23, '¤': 0x24, # ¤ carré chr(0xA1): 0x40, # ¡ point d'exclamation renversé chr(0xC4): 0x5B, # Ä majuscule A trema chr(0xE4): 0x7B, # ä minuscule a trema chr(0xD6): 0x5C, # Ö majuscule O trema chr(0xF6): 0x7C, # ö minuscule o trema chr(0xD1): 0x5D, # Ñ majuscule N tilda espagnol chr(0xF1): 0x7D, # ñ minuscule n tilda espagnol chr(0xDC): 0x5E, # Ü majuscule U trema chr(0xFC): 0x7E, # ü minuscule u trema chr(0xA7): 0x5F, # § signe paragraphe chr(0xBF): 0x60, # ¿ point interrogation renversé 'à': 0x7F # a accent grave } def toGSM3_38Bytes(stringtoconvert): """Returns a list of bytes from a string using GSM 3.38 conversion table. stringtoconvert: string to convert returns a list of bytes example: toGSM3_38Bytes("@ùPascal") returns [ 0x00, 0x06, 0x50, 0x61, 0x73, 0x63, 0x61, 0x6C ] """ bytes = [] for char in stringtoconvert: if ((char >= "%") and (char <= "?")): bytes.append(ord(char)) elif ((char >= "A") and (char <= "Z")): bytes.append(ord(char)) elif ((char >= "a") and (char <= "z")): bytes.append(ord(char)) else: bytes.append(int(__dic_GSM_3_38__[char])) return bytes def toHexString(bytes=[], format=0): """Returns an hex string representing bytes bytes: a list of bytes to stringify, e.g. [59, 22, 148, 32, 2, 1, 0, 0, 13] format: a logical OR of COMMA: add a comma between bytes HEX: add the 0x chars before bytes UPPERCASE: use 0X before bytes (need HEX) PACK: remove blanks example: bytes = [ 0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03 ] toHexString(bytes) returns 3B 65 00 00 9C 11 01 01 03 toHexString(bytes, COMMA) returns 3B, 65, 00, 00, 9C, 11, 01, 01, 03 toHexString(bytes, HEX) returns 0x3B 0x65 0x00 0x00 0x9C 0x11 0x01 0x01 0x03 toHexString(bytes, HEX | COMMA) returns 0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03 toHexString(bytes, PACK) returns 3B6500009C11010103 toHexString(bytes, HEX | UPPERCASE) returns 0X3B 0X65 0X00 0X00 0X9C 0X11 0X01 0X01 0X03 toHexString(bytes, HEX | UPPERCASE | COMMA) returns 0X3B, 0X65, 0X00, 0X00, 0X9C, 0X11, 0X01, 0X01, 0X03 """ from string import rstrip for byte in tuple(bytes): pass if type(bytes) is not list: raise TypeError('not a list of bytes') if bytes == None or bytes == []: return "" else: pformat = "%-0.2X" if COMMA & format: pformat = pformat + "," pformat = pformat + " " if PACK & format: pformat = rstrip(pformat) if HEX & format: if UPPERCASE & format: pformat = "0X" + pformat else: pformat = "0x" + pformat return rstrip(rstrip( reduce(lambda a, b: a + pformat % ((b + 256) % 256), [""] + bytes)), ',') def HexListToBinString(hexlist): binstring = "" for byte in hexlist: binstring = binstring + chr(eval('0x%x' % byte)) return binstring def BinStringToHexList(binstring): hexlist = [] for byte in binstring: hexlist = hexlist + [ord(byte)] return hexlist def hl2bs(hexlist): return HexListToBinString(hexlist) def bs2hl(binstring): return BinStringToHexList(binstring) pyscard-1.6.14/smartcard/Card.py0000644000175000017500000000520711747776700020235 0ustar rousseaurousseau00000000000000"""Card class. __author__ = "gemalto http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.Exceptions import CardConnectionException, NoCardException from smartcard.reader.Reader import Reader from smartcard.System import readers from smartcard.util import toHexString class Card(object): """Card class.""" def __init__(self, reader, atr): """Card constructor. reader: reader in which the card is inserted atr: ATR of the card""" self.reader = reader self.atr = atr def __repr__(self): """Return a string representing the Card (atr and reader concatenation).""" return toHexString(self.atr) + ' / ' + str(self.reader) def __eq__(self, other): """Return True if self==other (same reader and same atr). Return False otherwise.""" if isinstance(other, Card): return (self.atr == other.atr and repr(self.reader) == repr(other.reader)) else: return False def __ne__(self, other): """Return True if self!=other (same reader and same atr).Returns False otherwise.""" return not self.__eq__(other) def __hash__(self): """Returns a hash value for this object (str(self) is unique).""" return hash(str(self)) def createConnection(self): """Return a CardConnection to the Card object.""" readerobj = None if isinstance(self.reader, Reader): readerobj = self.reader elif type(self.reader) == str: for reader in readers(): if self.reader == str(reader): readerobj = reader if readerobj: return readerobj.createConnection() else: #raise CardConnectionException( # 'not a valid reader: ' + str(self.reader)) return None pyscard-1.6.14/smartcard/scard/0000755000175000017500000000000011747777125020104 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/scard/helpers.h0000644000175000017500000000731011747776700021716 0ustar rousseaurousseau00000000000000/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 ================================================================================ ==============================================================================*/ typedef struct { int bAllocated; unsigned char* ab; SCARDDWORDARG cBytes; } BYTELIST ; typedef char* ERRORSTRING; #ifdef PCSCLITE typedef struct { unsigned long Data1; unsigned short Data2; unsigned short Data3; unsigned char Data4[ 8 ]; } GUID; #endif typedef struct { int bAllocated; GUID* aguid; unsigned long cGuids; SCARDCONTEXT hcontext; } GUIDLIST ; typedef struct { SCARD_READERSTATE* ars; char** aszReaderNames; int cRStates; } READERSTATELIST ; typedef struct { int bAllocated; SCARDCONTEXT hcontext; char* sz; } STRING; typedef struct { int bAllocated; SCARDCONTEXT hcontext; char* ac; } STRINGLIST ; /**============================================================================= F U N C T I O N P R O T O T Y P E S ==============================================================================*/ // BYTELIST helpers void SCardHelper_AppendByteListToPyObject( BYTELIST* source, PyObject** ptarget ); BYTELIST* SCardHelper_PyByteListToBYTELIST(PyObject* source); void SCardHelper_PrintByteList( BYTELIST* apsz ); // ERRORSTRING helpers void SCardHelper_OutErrorStringAsPyObject( ERRORSTRING* source, PyObject** ptarget ); // GUIDLIST helpers void SCardHelper_AppendGuidListToPyObject( GUIDLIST* source, PyObject** ptarget ); GUIDLIST* SCardHelper_PyGuidListToGUIDLIST(PyObject* source); void SCardHelper_PrintGuidList( GUIDLIST* apsz ); // READERSTATELIST helpers void SCardHelper_AppendReaderStateListToPyObject( READERSTATELIST* source, PyObject** ptarget ); READERSTATELIST* SCardHelper_PyReaderStateListToREADERSTATELIST(PyObject* source); void SCardHelper_PrintReaderStateList( READERSTATELIST* apsz ); // SCARDCONTEXT helpers void SCardHelper_AppendSCardContextToPyObject( SCARDCONTEXT source, PyObject** ptarget ); SCARDCONTEXT SCardHelper_PyScardContextToSCARDCONTEXT( PyObject* source ); // SCARDHANDLE helpers void SCardHelper_AppendSCardHandleToPyObject( SCARDHANDLE source, PyObject** ptarget ); SCARDHANDLE SCardHelper_PyScardHandleToSCARDHANDLE( PyObject* source ); // SCARDDWORDARG helpers void SCardHelper_AppendSCardDwordArgToPyObject( SCARDDWORDARG source, PyObject** ptarget ); SCARDDWORDARG SCardHelper_PySCardDwordArgToSCARDDWORDARG( PyObject* source ); // STRING helpers void SCardHelper_AppendStringToPyObject( STRING* source, PyObject** ptarget ); STRING* SCardHelper_PyStringToString( PyObject* source ); void SCardHelper_PrintString( STRING* str ); // STRINGLIST helpers void SCardHelper_AppendStringListToPyObject( STRINGLIST* source, PyObject** ptarget ); STRINGLIST* SCardHelper_PyStringListToStringList(PyObject* source); void SCardHelper_PrintStringList( STRINGLIST* apsz ); pyscard-1.6.14/smartcard/scard/scard.i0000644000175000017500000021526011747776700021356 0ustar rousseaurousseau00000000000000/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 ==============================================================================*/ %define DOCSTRING "The smartcard.scard module is a simple wrapper on top of the C language PCSC SCardXXX API. The smartcard.scard module is the lower layer of the pyscard framework that provides a higher level interface. You should avoid using the smartcard.scard package directly, and use the pyscard directly because: - smartcard.scard being a C wrapper, the code tends to look like C code written in python syntax - the smartcard package provides higher level abstractions (e.g. CardType, CardConnection), and makes programming easier since it is totally written in Python You can still use the smartcard.scard package if you want to write your own framework, or if you want to perform quick-and-dirty port of C language programs using SCardXXX calls, or if there are features of SCardXXX API that you want to use and that are not available in the pyscard library. Introduction The smartcard.scard module is a Python wrapper around PCSC smart card base services. On Windows, the wrapper is performed around the smart card base components winscard library. On linux, the wrapper is performed around PCSC-lite library. On Windows using the smart card base components, the smartcard.scard module provides mapping for the following API functions: - SCardAddReaderToGroup - SCardBeginTransaction - SCardCancel - SCardConnect - SCardControl - SCardDisconnect - SCardEndTransaction - SCardEstablishContext - SCardForgetCardType - SCardForgetReader - SCardForgetReaderGroup - SCardGetAttrib - SCardGetCardTypeProviderName - SCardGetErrorMessage - SCardGetStatusChange - SCardIntroduceCardType - SCardIntroduceReader - SCardIntroduceReaderGroup - SCardIsValidContext - SCardListInterfaces - SCardListCards - SCardListReaders - SCardListReaderGroups - SCardLocateCards - SCardReconnect - SCardReleaseContext - SCardRemoveReaderFromGroup - SCardSetAttrib - SCardStatus - SCardTransmit On linux or Mac OS X Leopard with PCSC lite, the smartcard.scard module provides mapping for the following API functions: - SCardBeginTransaction - SCardCancel - SCardConnect - SCardControl - SCardDisconnect - SCardEndTransaction - SCardEstablishContext - SCardGetAttrib - SCardGetStatusChange - SCardIsValidContext - SCardListReaders - SCardListReaderGroups - SCardReconnect - SCardReleaseContext - SCardSetAttrib - SCardStatus - SCardTransmit On Mac OS X Tiger with PCSC lite, the smartcard.scard module provides mapping for the following API functions: - SCardBeginTransaction - SCardCancel - SCardConnect - SCardControl - SCardDisconnect - SCardEndTransaction - SCardEstablishContext - SCardGetStatusChange - SCardListReaders - SCardListReaderGroups - SCardReconnect - SCardReleaseContext - SCardStatus - SCardTransmit The following PCSC smart card functions are not wrapped by the scard module on any platform: - GetOpenCardName - SCardFreeMemory - SCardGetProviderId - SCardSetCartTypeProviderName - SCardUIDlgSelectCard Comments, bug reports, improvements welcome. ------------------------------------------------------------------------------- Copyright 2001-2012 gemalto @Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com @Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 " %enddef %module(docstring=DOCSTRING, package="smartcard.scard") scard %feature("autodoc", "3"); %{ #ifdef WIN32 #include #endif #ifdef __APPLE__ #include #else #include #endif #ifdef PCSCLITE #ifdef __APPLE__ #include "pyscard-reader.h" #ifndef SCARD_CTL_CODE #define SCARD_CTL_CODE(code) (0x42000000 + (code)) #endif #else #include #endif // undefined on older releases #ifndef MAX_BUFFER_SIZE_EXTENDED #define MAX_BUFFER_SIZE_EXTENDED (4 + 3 + (1<<16) + 3 + 2) #endif #else // !PCSCLITE // SCARD_CTL_CODE defined in WinSmCrd.h included by Win32 winscard.h // MAX_BUFFER_SIZE_EXTENDED is pcsc-lite specific #define MAX_BUFFER_SIZE_EXTENDED (4 + 3 + (1<<16) + 3 + 2) #endif //PCSCLITE #include "pcsctypes.h" #include "helpers.h" #include "memlog.h" #include "winscarddll.h" typedef STRING PROVIDERNAME_t; %} %include typemaps.i %include PcscTypemaps.i %{ // // these functions are only available on win32 PCSC // #ifdef WIN32 /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _AddReaderToGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName) { return (mySCardAddReaderToGroupA)( hcontext, szReaderName, szGroupName); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _ForgetCardType(SCARDCONTEXT hcontext, char* pszCardName) { return (mySCardForgetCardTypeA)(hcontext, pszCardName); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _ForgetReader(SCARDCONTEXT hcontext, char* szReaderName) { return (mySCardForgetReaderA)(hcontext, szReaderName); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _ForgetReaderGroup(SCARDCONTEXT hcontext, char* szGroupName) { return (mySCardForgetReaderGroupA)(hcontext, szGroupName); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _GetCardTypeProviderName( SCARDCONTEXT hcontext, char* pszCardName, SCARDDWORDARG dwProviderId, PROVIDERNAME_t* psl) { long lRetCode; unsigned long cchProviderName=SCARD_AUTOALLOCATE; // autoallocate memory; will be freed on output typemap psl->hcontext=hcontext; psl->sz=NULL; lRetCode=(mySCardGetCardTypeProviderNameA)( hcontext, pszCardName, dwProviderId, (LPTSTR)&psl->sz, &cchProviderName); return lRetCode; }; /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _IntroduceCardType( SCARDCONTEXT hcontext, char* pszCardName, GUIDLIST* pguidPrimaryProvider, GUIDLIST* rgguidInterfaces, BYTELIST* pbAtr, BYTELIST* pbAtrMask ) { return (mySCardIntroduceCardTypeA)( hcontext, pszCardName, pguidPrimaryProvider ? pguidPrimaryProvider->aguid : NULL, rgguidInterfaces ? rgguidInterfaces->aguid : NULL, rgguidInterfaces ? rgguidInterfaces->cGuids : 0, pbAtr->ab, pbAtrMask->ab, pbAtr->cBytes); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _IntroduceReader(SCARDCONTEXT hcontext, char* szReaderName, char* szDeviceName) { return (mySCardIntroduceReaderA)(hcontext, szReaderName, szDeviceName); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _IntroduceReaderGroup(SCARDCONTEXT hcontext, char* szGroupName) { return (mySCardIntroduceReaderGroupA)(hcontext, szGroupName); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _ListCards(SCARDCONTEXT hcontext, BYTELIST* pbl, GUIDLIST* guidlist, STRINGLIST* pmszCards) { // autoallocate memory; will be freed on output typemap unsigned long cchCards=SCARD_AUTOALLOCATE; pmszCards->ac=NULL; pmszCards->hcontext=hcontext; //SCardHelper_PrintByteList(pbl); return (mySCardListCardsA)( hcontext, pbl->ab, (NULL==guidlist) ? NULL : guidlist->aguid, (NULL==guidlist) ? 0 : guidlist->cGuids, (LPTSTR)&pmszCards->ac, &cchCards); }; /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _ListInterfaces( SCARDCONTEXT hcontext, char* pszCard, GUIDLIST* pgl ) { long lRetCode; pgl->cGuids = SCARD_AUTOALLOCATE; pgl->hcontext = hcontext; pgl->aguid = NULL; lRetCode = (mySCardListInterfacesA)(hcontext, pszCard, (LPGUID)&pgl->aguid, &pgl->cGuids); if (lRetCode!=SCARD_S_SUCCESS) { pgl->cGuids=0; } return lRetCode; } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _LocateCards( SCARDCONTEXT hcontext, STRINGLIST* mszCards, READERSTATELIST* prl ) { LPCSTR pcstr=(0==strlen((LPCTSTR)mszCards->ac)) ? NULL : (LPCTSTR)mszCards->ac; return (mySCardLocateCardsA)( hcontext, pcstr, prl->ars, prl->cRStates); } /////////////////////////////////////////////////////////////////////////////// SCARDRETCODE _RemoveReaderFromGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName) { return (mySCardRemoveReaderFromGroupA)( hcontext, szReaderName, szGroupName); } #endif // WIN32 // // These functions are not available on Max OS X Tiger // #ifndef __TIGER__ /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _IsValidContext(SCARDCONTEXT hcontext) { return (mySCardIsValidContext)(hcontext); } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _GetAttrib(SCARDHANDLE hcard, SCARDDWORDARG dwAttrId, BYTELIST* pbl) { long lRetCode; pbl->cBytes = 0; pbl->ab = NULL; lRetCode = (mySCardGetAttrib)(hcard, dwAttrId, pbl->ab, &pbl->cBytes); if ((lRetCode!=SCARD_S_SUCCESS) || (pbl->cBytes<1)) { return lRetCode; } pbl->ab = (unsigned char*)mem_Malloc(pbl->cBytes*sizeof(unsigned char)); if (pbl->ab==NULL) { return SCARD_E_NO_MEMORY; } lRetCode = (mySCardGetAttrib)(hcard, dwAttrId, pbl->ab, &pbl->cBytes); return lRetCode; } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _SetAttrib(SCARDHANDLE hcard, SCARDDWORDARG dwAttrId, BYTELIST* pbl) { long lRetCode; lRetCode = (mySCardSetAttrib)(hcard, dwAttrId, pbl->ab, pbl->cBytes); return lRetCode; } #endif // !__TIGER__ // // SCardControl does not have the same prototype on Mac OS X Tiger // #ifdef __TIGER__ /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Control( SCARDHANDLE hcard, BYTELIST* pblSendBuffer, BYTELIST* pblRecvBuffer ) { SCARDRETCODE lRet; pblRecvBuffer->ab = (unsigned char*)mem_Malloc(MAX_BUFFER_SIZE_EXTENDED*sizeof(unsigned char)); pblRecvBuffer->cBytes = MAX_BUFFER_SIZE_EXTENDED; lRet = (mySCardControl)( hcard, pblSendBuffer->ab, pblSendBuffer->cBytes, pblRecvBuffer->ab, &pblRecvBuffer->cBytes); return lRet; } #else // !__TIGER__ /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Control( SCARDHANDLE hcard, SCARDDWORDARG controlCode, BYTELIST* pblSendBuffer, BYTELIST* pblRecvBuffer ) { SCARDRETCODE lRet; pblRecvBuffer->ab = (unsigned char*)mem_Malloc(MAX_BUFFER_SIZE_EXTENDED*sizeof(unsigned char)); pblRecvBuffer->cBytes = MAX_BUFFER_SIZE_EXTENDED; lRet = (mySCardControl)( hcard, controlCode, pblSendBuffer->ab, pblSendBuffer->cBytes, pblRecvBuffer->ab, pblRecvBuffer->cBytes, &pblRecvBuffer->cBytes); return lRet; } #endif // __TIGER__ /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _BeginTransaction(SCARDHANDLE hcard) { return (mySCardBeginTransaction)(hcard); } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Cancel(SCARDCONTEXT hcontext) { return (mySCardCancel)(hcontext); } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Connect( SCARDCONTEXT hcontext, char* szReader, SCARDDWORDARG dwShareMode, SCARDDWORDARG dwPreferredProtocols, LPSCARDHANDLE phCard, SCARDDWORDARG* pdwActiveProtocol ) { SCARDRETCODE lRet; lRet = (mySCardConnectA)( hcontext, (LPCTSTR)szReader, dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol); return lRet; } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Disconnect(SCARDHANDLE hcard, SCARDDWORDARG dwDisposition) { return (mySCardDisconnect)(hcard, dwDisposition); } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _EndTransaction(SCARDHANDLE hcard, SCARDDWORDARG dwDisposition) { return (mySCardEndTransaction)(hcard, dwDisposition); } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _EstablishContext(SCARDDWORDARG dwScope, SCARDCONTEXT* phContext) { long lRet; lRet = (mySCardEstablishContext)(dwScope, NULL, NULL, phContext); #ifdef __TIGER__ // SCardReleaseContext on Mac OS X Tiger fails if SCardConnect is not called with an established // context, even on a dummy reader if (SCARD_S_SUCCESS==lRet) { SCARDHANDLE hcard; SCARDDWORDARG dwarg; (mySCardConnectA)(*phContext, "dummy-reader", SCARD_SHARE_SHARED, SCARD_PROTOCOL_ANY, &hcard, &dwarg); } #endif // __TIGER__ return lRet; } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _GetStatusChange( SCARDCONTEXT hcontext, SCARDDWORDARG dwTimeout, READERSTATELIST* prsl) { SCARDRETCODE hresult; int i; // bad reader state list if (NULL==prsl) { return SCARD_E_INVALID_PARAMETER; } // remove changed bit for(i=0; icRStates; i++) { // remove changed bit prsl->ars[i].dwCurrentState = prsl->ars[i].dwCurrentState & (0xFFFFFFFF ^ SCARD_STATE_CHANGED); } hresult = (mySCardGetStatusChangeA)(hcontext, dwTimeout, prsl->ars, prsl->cRStates); //printf("\n%.8lx ", hresult); //for(i=0; icRStates; i++) //{ // printf("%.8lx %.8lx ", prsl->ars[i].dwCurrentState, prsl->ars[i].dwEventState); //} return hresult; } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _ListReaders( SCARDCONTEXT hcontext, STRINGLIST* pmszGroups, STRINGLIST* pmszReaders) { LPCTSTR mszGroups; SCARDDWORDARG cchReaders; LONG lRetCode; if (pmszGroups) { mszGroups=pmszGroups->ac; } else { mszGroups=NULL; } #ifdef NOAUTOALLOCATE // autoallocate memory; will be freed on output typemap cchReaders=SCARD_AUTOALLOCATE; pmszReaders->ac=NULL; pmszReaders->hcontext=hcontext; return (mySCardListReadersA)(hcontext, mszGroups, (LPTSTR)&pmszReaders->ac, &cchReaders); #endif //AUTOALLOCATE // no autoallocate on pcsc-lite; do a first call to get length // then allocate memory and do a final call #ifndef NOAUTOALLOCATE // set hcontext to 0 so that mem_Free will // be called instead of SCardFreeMemory pmszReaders->hcontext=0; pmszReaders->ac=NULL; cchReaders=0; lRetCode = (mySCardListReadersA)(hcontext, mszGroups, NULL, &cchReaders); if (SCARD_S_SUCCESS!=lRetCode) { return lRetCode; } if (0==cchReaders) { return SCARD_S_SUCCESS; } pmszReaders->ac=mem_Malloc(cchReaders*sizeof(char)); if (NULL==pmszReaders->ac) { return SCARD_E_NO_MEMORY; } return (mySCardListReadersA)(hcontext, mszGroups, (LPTSTR)pmszReaders->ac, &cchReaders); #endif // !NOAUTOALLOCATE } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _ListReaderGroups(SCARDCONTEXT hcontext, STRINGLIST* pmszReaderGroups) { DWORD cchReaderGroups; LONG lRetCode; #ifdef NOAUTOALLOCATE cchReaderGroups = SCARD_AUTOALLOCATE; pmszReaderGroups->ac=NULL; pmszReaderGroups->hcontext=hcontext; return (mySCardListReaderGroupsA)(hcontext, (LPTSTR)&pmszReaderGroups->ac, &cchReaderGroups); #endif // NOAUTOALLOCATE // no autoallocate on pcsc-lite; do a first call to get length // then allocate memory and do a final call #ifndef NOAUTOALLOCATE // set hcontext to 0 so that mem_Free will // be called instead of SCardFreeMemory pmszReaderGroups->hcontext=0; cchReaderGroups = 0; pmszReaderGroups->ac=NULL; lRetCode = (mySCardListReaderGroupsA)(hcontext, (LPTSTR)pmszReaderGroups->ac, &cchReaderGroups); if (SCARD_S_SUCCESS!=lRetCode) { return lRetCode; } if (0==cchReaderGroups) { return SCARD_S_SUCCESS; } pmszReaderGroups->ac=mem_Malloc(cchReaderGroups*sizeof(char)); if (NULL==pmszReaderGroups->ac) { return SCARD_E_NO_MEMORY; } return (mySCardListReaderGroupsA)(hcontext, (LPTSTR)pmszReaderGroups->ac, &cchReaderGroups); #endif // !NOAUTOALLOCATE }; /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Reconnect( SCARDHANDLE hcard, SCARDDWORDARG dwShareMode, SCARDDWORDARG dwPreferredProtocols, SCARDDWORDARG dwInitialization, SCARDDWORDARG* pdwActiveProtocol ) { return (mySCardReconnect)( hcard, dwShareMode, dwPreferredProtocols, dwInitialization, pdwActiveProtocol); } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _ReleaseContext(SCARDCONTEXT hcontext) { SCARDRETCODE lRet; lRet = (mySCardReleaseContext)(hcontext); return lRet; } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Status( SCARDHANDLE hcard, STRING* pszReaderName, SCARDDWORDARG* pdwState, SCARDDWORDARG* pdwProtocol, BYTELIST* pbl ) { long lRetCode; SCARDDWORDARG dwReaderLen=256; SCARDDWORDARG dwAtrLen=36; for(;;) { pbl->ab = (unsigned char*)mem_Malloc(dwAtrLen*sizeof(unsigned char)); if (pbl->ab == NULL) { lRetCode=SCARD_E_NO_MEMORY; break; } pbl->cBytes = dwAtrLen; pszReaderName->sz = mem_Malloc(dwReaderLen*sizeof(char)); pszReaderName->hcontext = 0; if (NULL == pszReaderName->sz) { lRetCode=SCARD_E_NO_MEMORY; break; } lRetCode = (mySCardStatusA)( hcard, (LPTSTR)pszReaderName->sz, &dwReaderLen, pdwState, pdwProtocol, pbl->ab, &pbl->cBytes); break; } return lRetCode; } /////////////////////////////////////////////////////////////////////////////// static SCARDRETCODE _Transmit( SCARDHANDLE hcard, unsigned long pioSendPci, BYTELIST* pblSendBuffer, BYTELIST* pblRecvBuffer ) { PSCARD_IO_REQUEST piorequest=NULL; long ret; pblRecvBuffer->ab = (unsigned char*)mem_Malloc(MAX_BUFFER_SIZE_EXTENDED*sizeof(unsigned char)); pblRecvBuffer->cBytes = MAX_BUFFER_SIZE_EXTENDED; // keep in sync with redefinition in PcscDefs.i switch(pioSendPci) { case 0x01: piorequest=(PSCARD_IO_REQUEST)myg_prgSCardT0Pci; break; case 0x02: piorequest=(PSCARD_IO_REQUEST)myg_prgSCardT1Pci; break; case 0x04: piorequest=(PSCARD_IO_REQUEST)myg_prgSCardRawPci; break; default: return SCARD_E_INVALID_PARAMETER; } ret = (mySCardTransmit)( hcard, (PSCARD_IO_REQUEST)piorequest, pblSendBuffer->ab, pblSendBuffer->cBytes, NULL, pblRecvBuffer->ab, &pblRecvBuffer->cBytes); return ret; } /////////////////////////////////////////////////////////////////////////////// static long _SCARD_CTL_CODE(long code) { return SCARD_CTL_CODE(code); } /////////////////////////////////////////////////////////////////////////////// static ERRORSTRING* _GetErrorMessage(long lErrCode) { #ifdef WIN32 #define _NO_SERVICE_MSG "The Smart card resource manager is not running." DWORD dwRetCode; LPVOID ppszError; dwRetCode=FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, lErrCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&ppszError, 0, NULL); if (0L==dwRetCode) { ppszError=NULL; if (SCARD_E_NO_SERVICE==lErrCode) { ppszError=(LPVOID)LocalAlloc(LPTR, sizeof(_NO_SERVICE_MSG)+1); if (NULL!=ppszError) { strncpy(ppszError, _NO_SERVICE_MSG, sizeof(_NO_SERVICE_MSG)+1); } } } return ppszError; #endif // WIN32 #ifdef PCSCLITE return (ERRORSTRING*)myPcscStringifyError(lErrCode); #endif // PCSCLITE } %} // // a few documentation typemaps // %typemap(doc, name="hcard", type="") (SCARDHANDLE hcard) "hcard: card handle return from SCardConnect()"; %typemap(doc, name="hcard", type="") (SCARDHANDLE* phcard) "hcard: on output, a card handle"; %typemap(doc, name="hcontext", type="") (SCARDCONTEXT hcontext) "hcontext: context handle return from SCardEstablishContext()"; %typemap(doc, name="hcontext", type="") (SCARDCONTEXT* phcontext) "hcontext: on output, a valid context handle if successful"; %typemap(doc, name="readerstatelist", type="tuple[]") (READERSTATELIST *prsl) "readerstatelist: in input/output, a list of reader state tuple (readername, state, atr)"; %typemap(doc, name="groupname", type="") (char* szGroupName) "groupname: card reader group name"; %typemap(doc, name="readername", type="") (char* szReaderName) "readername: card reader name"; %typemap(doc, name="cardname", type="") (char* szCardName) "cardname: friendly name of a card"; %typemap(doc, name="devicename", type="") (char* szDeviceName) "devicename: card reader device name"; %typemap(doc, name="providername", type="") (PROVIDERNAME_t* pszProviderName) "providername: on output, provider name"; %typemap(doc, name="readername", type="") (STRING* pszReaderNameOut) "readername: on output, reader name"; %typemap(doc, name="apducommand", type="byte[]") (BYTELIST* APDUCOMMAND) "apducommand: list of APDU bytes to transmit"; %typemap(doc, name="apduresponse", type="byte[]") (BYTELIST* APDURESPONSE) "apduresponse: on output, the list of APDU response bytes"; %typemap(doc, name="atr", type="byte[]") (BYTELIST* ATR) "atr: card ATR"; %typemap(doc, name="atr", type="byte[]") (BYTELIST* ATROUT) "atr: on output, the card ATR"; %typemap(doc, name="attributes", type="byte[]") (BYTELIST* ATTRIBUTES) "attributes: on output, a list of attributes"; %typemap(doc, name="mask", type="byte[]") (BYTELIST* MASK) "mask: mask to apply to card ATR"; %typemap(doc, name="inbuffer", type="byte[]") (BYTELIST* INBUFFER) "inbuffer: list of bytes to send with the control code"; %typemap(doc, name="outbuffer", type="byte[]") (BYTELIST* OUTBUFFER) "outbuffer: on output, the bytes returned by execution of the control code"; %typemap(doc, name="primaryprovider", type="GUID") (GUIDLIST* PRIMARYPROVIDER) "primaryprovidername: GUID of the smart card primary service provider"; %typemap(doc, name="providerlist", type="GUID[]") (GUIDLIST* PROVIDERLIST) "providerlist: list of GUIDs of interfaces supported by smart card"; %typemap(doc, name="interfaces", type="GUID[]") (GUIDLIST* GUIDINTERFACES) "interfaces: on output, a list of GUIDs of the interfaces supported by the smart card"; %typemap(doc, name="cards", type="") (STRINGLIST* CARDSTOLOCATE) "cards: a list of cards to locate"; %typemap(doc, name="matchingcards", type="[]") (STRINGLIST* MATCHINGCARDS) "matchingcards: on output, a list of matching cards"; %typemap(doc, name="readergroups", type="[]") (STRINGLIST* READERGROUPSIN) "readergroups: a list of reader groups to search for readers"; %typemap(doc, name="readergroups", type="[]") (STRINGLIST* READERGROUPSOUT) "readergroups: on output, the list of reader groups"; %typemap(doc, name="readers", type="[]") (STRINGLIST* READERSFOUND) "matchingcards: on output, a list of readers found"; %typemap(doc, name="readername", type="") (STRINGLIST* pszReaderName) "readername: on output, the name of the reader in which the card is inserted"; %typemap(doc, name="dwActiveProtocol", type="") (SCARDDWORDARG* pdwActiveProtocol) "dwActiveProtocol: on output, active protocol of card connection"; %typemap(doc, name="dwState", type="") (SCARDDWORDARG* pdwState) "dwState: on output, current state of the smart card"; %typemap(doc, name="dwProtocol", type="") (SCARDDWORDARG* pdwProtocol) "dwProtocol: on output, the current protocol"; %typemap(doc, name="dwScope", type="") (SCARDDWORDARG dwScope) "dwScope: context scope"; %typemap(doc, name="dwProviderId", type="") (SCARDDWORDARG dwProviderId) "dwProviderId: provider type, SCARD_PROVIDER_PRIMARY or SCARD_PROVIDER_CSP"; %typemap(doc, name="dwPreferredProtocols", type="") (SCARDDWORDARG dwPreferredProtocols) "dwPreferredProtocols: preferred protocols"; %typemap(doc, name="dwShareMode", type="") (SCARDDWORDARG dwShareMode) "dwShareMode: share mode"; %typemap(doc, name="dwDisposition", type="") (SCARDDWORDARG dwDisposition) "dwDisposition: card disposition on return"; %typemap(doc, name="dwAttrId", type="") (SCARDDWORDARG dwAttrId) "dwAttrId: value of attribute to get"; %typemap(doc, name="dwTimeout", type="") (SCARDDWORDARG dwTimeout) "dwTimeout: timeout value, INFINITE for infinite time-out"; %typemap(doc, name="dwInitialization", type="") (SCARDDWORDARG dwInitialization) "dwInitialization: the type of initialization that should be performed on the card"; %typemap(doc, name="dwControlCode", type="") (SCARDDWORDARG dwControlCode) "dwControlCode: the control code to send"; // // these functions are only available on win32 PCSC // #ifdef WIN32 /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_ADDREADERTOGROUP " adds a reader to a reader group Windows only, not supported by PCSC lite wrapper. example: from smartcard.scard import * ... establish context ... newgroup = 'SCard$MyOwnGroup' reader = 'SchlumbergerSema Reflex USB v.2 0' readeralias = 'SchlumbergerSema Reflex USB v.2 0 alias' hresult = SCardIntroduceReader(hcontext, readeralias, reader]) if hresult != SCARD_S_SUCCESS: raise error, 'Unable to introduce reader: ' + SCardGetErrorMessage(hresult) hresult = SCardAddReaderToGroup(hcontext, readeralias, newgroup) if hresult!=0: raise error, 'Unable to add reader to group: ' + SCardGetErrorMessage(hresult) ... " %enddef %feature("docstring") DOCSTRING_ADDREADERTOGROUP; %rename(SCardAddReaderToGroup) _AddReaderToGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName); SCARDRETCODE _AddReaderToGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_FORGETCARDTYPE " removes an introduced smart card from the smart card subsystem. Windows only, not supported by PCSC lite wrapper. from smartcard.scard import * ... establish context ... hresult = SCardForgetCardType(hcontext, 'myCardName') if hresult != SCARD_S_SUCCESS: raise error, 'Failed to remove card type: ' + SCardGetErrorMessage(hresult) ... " %enddef %feature("docstring") DOCSTRING_FORGETCARDTYPE; %rename(SCardForgetCardType) _ForgetCardType(SCARDCONTEXT hcontext, char* szCardName); SCARDRETCODE _ForgetCardType(SCARDCONTEXT hcontext, char* szCardName); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_FORGETREADER " Removes a previously introduced smart card reader from the smart card subsystem. Windows only, not supported by PCSC lite wrapper. from smartcard.scard import * ... establish context ... ... hresult = SCardForgetReader(hcontext, dummyreader) if hresult != SCARD_S_SUCCESS: raise error, 'Failed to forget readers ' + SCardGetErrorMessage(hresult) ... " %enddef %feature("docstring") DOCSTRING_FORGETREADER; %rename(SCardForgetReader) _ForgetReader(SCARDCONTEXT hcontext, char* szReaderName); SCARDRETCODE _ForgetReader(SCARDCONTEXT hcontext, char* szReaderName); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_FORGETREADERGROUP " Removes a previously introduced smart card reader group from the smart card subsystem. Although this function automatically clears all readers from the group, it does not affect the existence of the individual readers in the database. Windows only, not supported by PCSC lite wrapper. from smartcard.scard import * ... establish context ... ... hresult = SCardForgetReaderGroup(hcontext, newgroup) if hresult != SCARD_S_SUCCESS: raise error, 'Unable to forget reader group: ' + SCardGetErrorMessage(hresult) ... " %enddef %feature("docstring") DOCSTRING_FORGETREADERGROUP; %rename(SCardForgetReaderGroup) _ForgetReaderGroup(SCARDCONTEXT hcontext, char* szGroupName); SCARDRETCODE _ForgetReaderGroup(SCARDCONTEXT hcontext, char* szGroupName); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_GETCARDTYPEPROVIDERNAME " Returns the name of the module (dynamic link library) containing the provider for a given card name and provider type. Windows only, not supported by PCSC lite wrapper. from smartcard.scard import * ... establish context ... hresult, cards = SCardListCards(hcontext, [], []) if hresult != SCARD_S_SUCCESS: raise error, 'Failure to list cards: ' + SCardGetErrorMessage(hresult) for i in cards: hresult, providername = SCardGetCardTypeProviderName(hcontext, i, SCARD_PROVIDER_PRIMARY) if hresult == SCARD_S_SUCCESS: print providername hresult, providername = SCardGetCardTypeProviderName(hcontext, i, SCARD_PROVIDER_CSP) if hresult == SCARD_S_SUCCESS: print providername ... " %enddef %feature("docstring") DOCSTRING_GETCARDTYPEPROVIDERNAME; %rename(SCardGetCardTypeProviderName) _GetCardTypeProviderName( SCARDCONTEXT hcontext, char* szCardName, SCARDDWORDARG dwProviderId, PROVIDERNAME_t* pszProviderName ); SCARDRETCODE _GetCardTypeProviderName( SCARDCONTEXT hcontext, char* szCardName, SCARDDWORDARG dwProviderId, PROVIDERNAME_t* pszProviderName ); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_INTRODUCECARDTYPE " Introduces a smart card to the smart card subsystem (for the active user) by adding it to the smart card database. Windows only, not supported by PCSC lite wrapper. from smartcard.scard import * ... znewcardName = 'dummy-card' znewcardATR = [0x3B, 0x77, 0x94, 0x00, 0x00, 0x82, 0x30, 0x00, 0x13, 0x6C, 0x9F, 0x22] znewcardMask = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] znewcardPrimGuid = smartcard.guid.strToGUID('{128F3806-4F70-4ccf-977A-60C390664840}') znewcardSecGuid = smartcard.guid.strToGUID('{EB7F69EA-BA20-47d0-8C50-11CFDEB63BBE}') ... hresult = SCardIntroduceCardType(hcontext, znewcardName, znewcardPrimGuid, znewcardPrimGuid + znewcardSecGuid, znewcardATR, znewcardMask) if hresult != SCARD_S_SUCCESS: raise error, 'Failed to introduce card type: ' + SCardGetErrorMessage(hresult) ... " %enddef %feature("docstring") DOCSTRING_INTRODUCECARDTYPE; %rename(SCardIntroduceCardType) _IntroduceCardType( SCARDCONTEXT hcontext, char* szCardName, GUIDLIST* PRIMARYPROVIDER, GUIDLIST* PROVIDERLIST, BYTELIST* ATR, BYTELIST* MASK ); SCARDRETCODE _IntroduceCardType( SCARDCONTEXT hcontext, char* szCardName, GUIDLIST* PRIMARYPROVIDER, GUIDLIST* PROVIDERLIST, BYTELIST* ATR, BYTELIST* MASK ); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_INTRODUCEREADER " Introduces a reader to the smart card subsystem. Windows only, not supported by PCSC lite wrapper. from smartcard.scard import * ... dummyreader = readers[0] + ' dummy' hresult = SCardIntroduceReader(hcontext, dummyreader, readers[0]) if hresult != SCARD_S_SUCCESS: raise error, 'Unable to introduce reader: ' + dummyreader + ' : ' + SCardGetErrorMessage(hresult) ... " %enddef %feature("docstring") DOCSTRING_INTRODUCEREADER; %rename(SCardIntroduceReader) _IntroduceReader(SCARDCONTEXT hcontext, char* szReaderName, char* szDeviceName); SCARDRETCODE _IntroduceReader(SCARDCONTEXT hcontext, char* szReaderName, char* szDeviceName); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_INTRODUCEREADERGROUP " Introduces a reader group to the smart card subsystem. However, the reader group is not created until the group is specified when adding a reader to the smart card database. Windows only, not supported by PCSC lite wrapper. from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult = SCardIntroduceReaderGroup(hcontext, 'SCard$MyOwnGroup') if hresult != SCARD_S_SUCCESS: raise error, 'Unable to introduce reader group: ' + SCardGetErrorMessage(hresult) hresult = SCardAddReaderToGroup(hcontext, 'SchlumbergerSema Reflex USB v.2 0', 'SCard$MyOwnGroup') if hresult != SCARD_S_SUCCESS: raise error, 'Unable to add reader to group: ' + SCardGetErrorMessage(hresult) " %enddef %feature("docstring") DOCSTRING_INTRODUCEREADERGROUP; %rename(SCardIntroduceReaderGroup) _IntroduceReaderGroup(SCARDCONTEXT hcontext, char* szGroupName); SCARDRETCODE _IntroduceReaderGroup(SCARDCONTEXT hcontext, char* szGroupName); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_LISTINTERFACES " Provides a list of interfaces supplied by a given card. The caller supplies the name of a smart card previously introduced to the subsystem, and receives the list of interfaces supported by the card Windows only, not supported by PCSC lite wrapper. from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, interfaces = SCardListInterfaces(hcontext, 'Schlumberger Cryptoflex 8k v2') if hresult != SCARD_S_SUCCESS: raise error, 'Failed to list interfaces: ' + SCardGetErrorMessage(hresult) ... " %enddef %feature("docstring") DOCSTRING_LISTINTERFACES; %rename(SCardListInterfaces) _ListInterfaces(SCARDCONTEXT hcontext, char* szCardName, GUIDLIST* GUIDINTERFACES); SCARDRETCODE _ListInterfaces(SCARDCONTEXT hcontext, char* szCardName, GUIDLIST* GUIDINTERFACES); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_LISTCARDS " Searches the smart card database and provides a list of named cards previously introduced to the system by the user. The caller specifies an ATR string, a set of interface identifiers (GUIDs), or both. If both an ATR string and an identifier array are supplied, the cards returned will match the ATR string supplied and support the interfaces specified. Windows only, not supported by PCSC lite wrapper. from smartcard.scard import * ... slbCryptoFlex8kv2ATR = [ 0x3B, 0x95, 0x15, 0x40, 0x00, 0x68, 0x01, 0x02, 0x00, 0x00 ] hresult, card = SCardListCards(hcontext, slbCryptoFlex8kv2ATR, []) if hresult ! =SCARD_S_SUCCESS: raise error, 'Failure to locate Schlumberger Cryptoflex 8k v2 card: ' + SCardGetErrorMessage(hresult) hresult, cards = SCardListCards(hcontext, [], []) if hresult != SCARD_S_SUCCESS: raise error, 'Failure to list cards: ' + SCardGetErrorMessage(hresult) print 'Cards: ', cards ... " %enddef %feature("docstring") DOCSTRING_LISTCARDS; %rename (SCardListCards) _ListCards( SCARDCONTEXT hcontext, BYTELIST* ATR, GUIDLIST* PROVIDERLIST, STRINGLIST* MATCHINGCARDS); SCARDRETCODE _ListCards( SCARDCONTEXT hcontext, BYTELIST* ATR, GUIDLIST* PROVIDERLIST, STRINGLIST* MATCHINGCARDS); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_LOCATECARDS " Searches the readers listed in the readerstate parameter for a card with an ATR string that matches one of the card names specified in mszCards, returning immediately with the result. Windows only, not supported by PCSC lite wrapper. from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, readers = SCardListReaders(hcontext, []) readerstates = [] cards = ['Schlumberger Cryptoflex 4k', 'Schlumberger Cryptoflex 8k', 'Schlumberger Cryptoflex 8k v2'] for i in xrange(len(readers)): readerstates += [(readers[i], SCARD_STATE_UNAWARE)] hresult, newstates = SCardLocateCards(hcontext, cards, readerstates) for i in newstates: reader, eventstate, atr = i print reader, for b in atr: print '0x%.2X' % b, print "" if eventstate & SCARD_STATE_ATRMATCH: print 'Card found' if eventstate & SCARD_STATE_EMPTY: print 'Reader empty' if eventstate & SCARD_STATE_PRESENT: print 'Card present in reader' ... " %enddef %feature("docstring") DOCSTRING_LOCATECARDS; %rename(SCardLocateCards) _LocateCards( SCARDCONTEXT hcontext, STRINGLIST* CARDSTOLOCATE, READERSTATELIST *prsl); SCARDRETCODE _LocateCards( SCARDCONTEXT hcontext, STRINGLIST* CARDSTOLOCATE, READERSTATELIST *prsl); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_REMOVEREADERFROMGROUP " Removes a reader from an existing reader group. This function has no affect on the reader. Windows only, not supported by PCSC lite wrapper. from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult = SCardRemoveReaderFromGroup(hcontext, 'SchlumbergerSema Reflex USB v.2 0', 'SCard$MyOwnGroup') if hresult != SCARD_S_SUCCESS: raise error, 'Unable to remove reader from group: ' + SCardGetErrorMessage(hresult) ... " %enddef %feature("docstring") DOCSTRING_REMOVEREADERFROMGROUP; %rename(SCardRemoveReaderFromGroup) _RemoveReaderFromGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName); SCARDRETCODE _RemoveReaderFromGroup( SCARDCONTEXT hcontext, char* szReaderName, char* szGroupName); #endif // WIN32 // // These functions are not available on Max OS X Tiger // // #ifndef __TIGER__ /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_ISVALIDCONTEXT " This function determines whether a smart card context handle is still valid. After a smart card context handle has been set by SCardEstablishContext(), it may become not valid if the resource manager service has been shut down. from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult = SCardIsValidContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error, 'Invalid context: ' + SCardGetErrorMessage(hresult) ... " %enddef %feature("docstring") DOCSTRING_ISVALIDCONTEXT; %rename(SCardIsValidContext) _IsValidContext(SCARDCONTEXT hcontext); SCARDRETCODE _IsValidContext(SCARDCONTEXT hcontext); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_GETATTRIB " This function get an attribute from the IFD Handler. For PCSC lite, the list of possible attributes is: * SCARD_ATTR_ASYNC_PROTOCOL_TYPES * SCARD_ATTR_ATR_STRING * SCARD_ATTR_CHANNEL_ID * SCARD_ATTR_CHARACTERISTICS * SCARD_ATTR_CURRENT_BWT * SCARD_ATTR_CURRENT_CLK * SCARD_ATTR_CURRENT_CWT * SCARD_ATTR_CURRENT_D * SCARD_ATTR_CURRENT_EBC_ENCODING * SCARD_ATTR_CURRENT_F * SCARD_ATTR_CURRENT_IFSC * SCARD_ATTR_CURRENT_IFSD * SCARD_ATTR_CURRENT_IO_STATE * SCARD_ATTR_CURRENT_N * SCARD_ATTR_CURRENT_PROTOCOL_TYPE * SCARD_ATTR_CURRENT_W * SCARD_ATTR_DEFAULT_CLK * SCARD_ATTR_DEFAULT_DATA_RATE * SCARD_ATTR_DEVICE_FRIENDLY_NAME_A * SCARD_ATTR_DEVICE_FRIENDLY_NAME_W * SCARD_ATTR_DEVICE_IN_USE * SCARD_ATTR_DEVICE_SYSTEM_NAME_A * SCARD_ATTR_DEVICE_SYSTEM_NAME_W * SCARD_ATTR_DEVICE_UNIT * SCARD_ATTR_ESC_AUTHREQUEST * SCARD_ATTR_ESC_CANCEL * SCARD_ATTR_ESC_RESET * SCARD_ATTR_EXTENDED_BWT * SCARD_ATTR_ICC_INTERFACE_STATUS * SCARD_ATTR_ICC_PRESENCE * SCARD_ATTR_ICC_TYPE_PER_ATR * SCARD_ATTR_MAX_CLK * SCARD_ATTR_MAX_DATA_RATE * SCARD_ATTR_MAX_IFSD * SCARD_ATTR_MAXINPUT * SCARD_ATTR_POWER_MGMT_SUPPORT * SCARD_ATTR_SUPRESS_T1_IFS_REQUEST * SCARD_ATTR_SYNC_PROTOCOL_TYPES * SCARD_ATTR_USER_AUTH_INPUT_DEVICE * SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE * SCARD_ATTR_VENDOR_IFD_SERIAL_NO * SCARD_ATTR_VENDOR_IFD_TYPE * SCARD_ATTR_VENDOR_IFD_VERSION * SCARD_ATTR_VENDOR_NAME For Windows Resource Manager, the list of possible attributes is: * SCARD_ATTR_VENDOR_NAME * SCARD_ATTR_VENDOR_IFD_TYPE * SCARD_ATTR_VENDOR_IFD_VERSION * SCARD_ATTR_VENDOR_IFD_SERIAL_NO * SCARD_ATTR_CHANNEL_ID * SCARD_ATTR_DEFAULT_CLK * SCARD_ATTR_MAX_CLK * SCARD_ATTR_DEFAULT_DATA_RATE * SCARD_ATTR_MAX_DATA_RATE * SCARD_ATTR_MAX_IFSD * SCARD_ATTR_POWER_MGMT_SUPPORT * SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE * SCARD_ATTR_USER_AUTH_INPUT_DEVICE * SCARD_ATTR_CHARACTERISTICS * SCARD_ATTR_CURRENT_PROTOCOL_TYPE * SCARD_ATTR_CURRENT_CLK * SCARD_ATTR_CURRENT_F * SCARD_ATTR_CURRENT_D * SCARD_ATTR_CURRENT_N * SCARD_ATTR_CURRENT_W * SCARD_ATTR_CURRENT_IFSC * SCARD_ATTR_CURRENT_IFSD * SCARD_ATTR_CURRENT_BWT * SCARD_ATTR_CURRENT_CWT * SCARD_ATTR_CURRENT_EBC_ENCODING * SCARD_ATTR_EXTENDED_BWT * SCARD_ATTR_ICC_PRESENCE * SCARD_ATTR_ICC_INTERFACE_STATUS * SCARD_ATTR_CURRENT_IO_STATE * SCARD_ATTR_ATR_STRING * SCARD_ATTR_ICC_TYPE_PER_ATR * SCARD_ATTR_ESC_RESET * SCARD_ATTR_ESC_CANCEL * SCARD_ATTR_ESC_AUTHREQUEST * SCARD_ATTR_MAXINPUT * SCARD_ATTR_DEVICE_UNIT * SCARD_ATTR_DEVICE_IN_USE * SCARD_ATTR_DEVICE_FRIENDLY_NAME_A * SCARD_ATTR_DEVICE_SYSTEM_NAME_A * SCARD_ATTR_DEVICE_FRIENDLY_NAME_W * SCARD_ATTR_DEVICE_SYSTEM_NAME_W * SCARD_ATTR_SUPRESS_T1_IFS_REQUEST Not all the dwAttrId values listed above may be implemented in the IFD Handler you are using. And some dwAttrId values not listed here may be implemented. from smartcard.scard import * ... establish context and connect to card ... hresult, attrib = SCardGetAttrib(hcard, SCARD_ATTR_ATR_STRING) if hresult == SCARD_S_SUCCESS: for j in attrib: print '0x%.2X' % attrib, ... " %enddef %feature("docstring") DOCSTRING_GETATTRIB; %rename(SCardGetAttrib) _GetAttrib(SCARDHANDLE hcard, SCARDDWORDARG dwAttrId, BYTELIST* ATTRIBUTES); SCARDRETCODE _GetAttrib(SCARDHANDLE hcard, SCARDDWORDARG dwAttrId, BYTELIST* ATTRIBUTES); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_SETATTRIB " This function sets an attribute from the IFD Handler. Not all attributes are supported by all readers nor can they be set at all times. For PCSC lite, the list of possible attributes is: * SCARD_ATTR_ASYNC_PROTOCOL_TYPES * SCARD_ATTR_ATR_STRING * SCARD_ATTR_CHANNEL_ID * SCARD_ATTR_CHARACTERISTICS * SCARD_ATTR_CURRENT_BWT * SCARD_ATTR_CURRENT_CLK * SCARD_ATTR_CURRENT_CWT * SCARD_ATTR_CURRENT_D * SCARD_ATTR_CURRENT_EBC_ENCODING * SCARD_ATTR_CURRENT_F * SCARD_ATTR_CURRENT_IFSC * SCARD_ATTR_CURRENT_IFSD * SCARD_ATTR_CURRENT_IO_STATE * SCARD_ATTR_CURRENT_N * SCARD_ATTR_CURRENT_PROTOCOL_TYPE * SCARD_ATTR_CURRENT_W * SCARD_ATTR_DEFAULT_CLK * SCARD_ATTR_DEFAULT_DATA_RATE * SCARD_ATTR_DEVICE_FRIENDLY_NAME_A * SCARD_ATTR_DEVICE_FRIENDLY_NAME_W * SCARD_ATTR_DEVICE_IN_USE * SCARD_ATTR_DEVICE_SYSTEM_NAME_A * SCARD_ATTR_DEVICE_SYSTEM_NAME_W * SCARD_ATTR_DEVICE_UNIT * SCARD_ATTR_ESC_AUTHREQUEST * SCARD_ATTR_ESC_CANCEL * SCARD_ATTR_ESC_RESET * SCARD_ATTR_EXTENDED_BWT * SCARD_ATTR_ICC_INTERFACE_STATUS * SCARD_ATTR_ICC_PRESENCE * SCARD_ATTR_ICC_TYPE_PER_ATR * SCARD_ATTR_MAX_CLK * SCARD_ATTR_MAX_DATA_RATE * SCARD_ATTR_MAX_IFSD * SCARD_ATTR_MAXINPUT * SCARD_ATTR_POWER_MGMT_SUPPORT * SCARD_ATTR_SUPRESS_T1_IFS_REQUEST * SCARD_ATTR_SYNC_PROTOCOL_TYPES * SCARD_ATTR_USER_AUTH_INPUT_DEVICE * SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE * SCARD_ATTR_VENDOR_IFD_SERIAL_NO * SCARD_ATTR_VENDOR_IFD_TYPE * SCARD_ATTR_VENDOR_IFD_VERSION * SCARD_ATTR_VENDOR_NAME For Windows Resource Manager, the list of possible attributes is: * SCARD_ATTR_VENDOR_NAME * SCARD_ATTR_VENDOR_IFD_TYPE * SCARD_ATTR_VENDOR_IFD_VERSION * SCARD_ATTR_VENDOR_IFD_SERIAL_NO * SCARD_ATTR_CHANNEL_ID * SCARD_ATTR_DEFAULT_CLK * SCARD_ATTR_MAX_CLK * SCARD_ATTR_DEFAULT_DATA_RATE * SCARD_ATTR_MAX_DATA_RATE * SCARD_ATTR_MAX_IFSD * SCARD_ATTR_POWER_MGMT_SUPPORT * SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE * SCARD_ATTR_USER_AUTH_INPUT_DEVICE * SCARD_ATTR_CHARACTERISTICS * SCARD_ATTR_CURRENT_PROTOCOL_TYPE * SCARD_ATTR_CURRENT_CLK * SCARD_ATTR_CURRENT_F * SCARD_ATTR_CURRENT_D * SCARD_ATTR_CURRENT_N * SCARD_ATTR_CURRENT_W * SCARD_ATTR_CURRENT_IFSC * SCARD_ATTR_CURRENT_IFSD * SCARD_ATTR_CURRENT_BWT * SCARD_ATTR_CURRENT_CWT * SCARD_ATTR_CURRENT_EBC_ENCODING * SCARD_ATTR_EXTENDED_BWT * SCARD_ATTR_ICC_PRESENCE * SCARD_ATTR_ICC_INTERFACE_STATUS * SCARD_ATTR_CURRENT_IO_STATE * SCARD_ATTR_ATR_STRING * SCARD_ATTR_ICC_TYPE_PER_ATR * SCARD_ATTR_ESC_RESET * SCARD_ATTR_ESC_CANCEL * SCARD_ATTR_ESC_AUTHREQUEST * SCARD_ATTR_MAXINPUT * SCARD_ATTR_DEVICE_UNIT * SCARD_ATTR_DEVICE_IN_USE * SCARD_ATTR_DEVICE_FRIENDLY_NAME_A * SCARD_ATTR_DEVICE_SYSTEM_NAME_A * SCARD_ATTR_DEVICE_FRIENDLY_NAME_W * SCARD_ATTR_DEVICE_SYSTEM_NAME_W * SCARD_ATTR_SUPRESS_T1_IFS_REQUEST Not all the dwAttrId values listed above may be implemented in the IFD Handler you are using. And some dwAttrId values not listed here may be implemented. from smartcard.scard import * ... establish context and connect to card ... hresult, attrib = SCardSetAttrib(hcard, SCARD_ATTR_VENDOR_NAME, ['G', 'e', 'm', 'a', 'l', 't', 'o']) if hresult != SCARD_S_SUCCESS: print 'Failed to set attribute' ... " %enddef %feature("docstring") DOCSTRING_SETATTRIB; %rename(SCardSetAttrib) _SetAttrib(SCARDHANDLE hcard, SCARDDWORDARG dwAttrId, BYTELIST* ATTRIBUTESIN); SCARDRETCODE _SetAttrib(SCARDHANDLE hcard, SCARDDWORDARG dwAttrId, BYTELIST* ATTRIBUTESIN); #endif // !__TIGER__ // // SCardControl does not have the same prototype on Mac OS X Tiger // #ifdef __TIGER__ /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_CONTROL " This function sends a control command to the reader connected to by SCardConnect(). It returns a result and the control response. from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, 'SchlumbergerSema Reflex USB v.2 0', SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) CMD = [ 42, 0x12, 0x34] hresult, response = SCardControl(hcard, CMD) if hresult != SCARD_S_SUCCESS: raise error, 'Failed to control: ' + SCardGetErrorMessage(hresult) " %enddef %feature("docstring") DOCSTRING_CONTROL; %rename(SCardControl) _Control( SCARDHANDLE hcard, BYTELIST* INBUFFER, BYTELIST* OUTBUFFER ); SCARDRETCODE _Control( SCARDHANDLE hcard, BYTELIST* INBUFFER, BYTELIST* OUTBUFFER ); #else // !__TIGER__ /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_CONTROL " This function sends a control command to the reader connected to by SCardConnect(). It returns a result and the control response. from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, 'SchlumbergerSema Reflex USB v.2 0', SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) CMD = [0x12, 0x34] hresult, response = SCardControl(hcard, 42, CMD) if hresult != SCARD_S_SUCCESS: raise error, 'Failed to control: ' + SCardGetErrorMessage(hresult) " %enddef %feature("docstring") DOCSTRING_CONTROL; %rename(SCardControl) _Control( SCARDHANDLE hcard, SCARDDWORDARG dwControlCode, BYTELIST* INBUFFER, BYTELIST* OUTBUFFER ); SCARDRETCODE _Control( SCARDHANDLE hcard, SCARDDWORDARG dwControlCode, BYTELIST* INBUFFER, BYTELIST* OUTBUFFER ); #endif // __TIGER__ /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_BEGINTRANSACTION " This function establishes a temporary exclusive access mode for doing a series of commands or transaction. You might want to use this when you are selecting a few files and then writing a large file so you can make sure that another application will not change the current file. If another application has a lock on this reader or this application is in SCARD_SHARE_EXCLUSIVE there will be no action taken. from smartcard.scard import * ... establish context ... hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, 'SchlumbergerSema Reflex USB v.2 0', SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) if hresult!=SCARD_S_SUCCESS: raise error, 'unable to connect: ' + SCardGetErrorMessage(hresult) hresult = SCardBeginTransaction(hcard) if hresult != SCARD_S_SUCCESS: raise error, 'failed to begin transaction: ' + SCardGetErrorMessage(hresult) ... " %enddef %feature("docstring") DOCSTRING_BEGINTRANSACTION; %rename(SCardBeginTransaction) _BeginTransaction(SCARDHANDLE hcard); SCARDRETCODE _BeginTransaction(SCARDHANDLE hcard); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_CANCEL " This function cancels all pending blocking requests on the ScardGetStatusChange() function. from smartcard.scard import * ... establish context ... hresult = SCardCancel(hcard) if hresult != SCARD_S_SUCCESS: raise error, 'failed to cancel pending actions: ' + SCardGetErrorMessage(hresult) ..." %enddef %feature("docstring") DOCSTRING_CANCEL; %rename(SCardCancel) _Cancel(SCARDCONTEXT hcontext); SCARDRETCODE _Cancel(SCARDCONTEXT hcontext); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_CONNECT " This function establishes a connection to the friendly name of the reader specified in szReader. The first connection will power up and perform a reset on the card. Value of dwShareMode Meaning SCARD_SHARE_SHARED This application will allow others to share the reader SCARD_SHARE_EXCLUSIVE This application will NOT allow others to share the reader SCARD_SHARE_DIRECT Direct control of the reader, even without a card SCARD_SHARE_DIRECT can be used before using SCardControl() to send control commands to the reader even if a card is not present in the reader. Value of dwPreferredProtocols Meaning SCARD_PROTOCOL_T0 Use the T=0 protocol SCARD_PROTOCOL_T1 Use the T=1 protocol SCARD_PROTOCOL_RAW Use with memory type cards from smartcard.scard import * ... establish context ... hresult, readers = SCardListReaders(hcontext, 'NULL') if hresult != SCARD_S_SUCCESS: raise error, 'Failed to list readers:: ' + SCardGetErrorMessage(hresult) hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, readers[0], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) if hresult != SCARD_S_SUCCESS: raise error, 'unable to connect: ' + SCardGetErrorMessage(hresult) ... " %enddef %feature("docstring") DOCSTRING_CONNECT; %rename(SCardConnect) _Connect( SCARDCONTEXT hcontext, char* szReaderName, SCARDDWORDARG dwShareMode, SCARDDWORDARG dwPreferredProtocols, SCARDHANDLE* phcard, SCARDDWORDARG* pdwActiveProtocol ); SCARDRETCODE _Connect( SCARDCONTEXT hcontext, char* szReaderName, SCARDDWORDARG dwShareMode, SCARDDWORDARG dwPreferredProtocols, SCARDHANDLE* phcard, SCARDDWORDARG* pdwActiveProtocol ); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_DISCONNECT " This function terminates a connection to the connection made through SCardConnect. disposition can have the following values: Value of disposition Meaning SCARD_LEAVE_CARD Do nothing SCARD_RESET_CARD Reset the card (warm reset) SCARD_UNPOWER_CARD Unpower the card (cold reset) SCARD_EJECT_CARD Eject the card from smartcard.scard import * ... establish context and connect to card ... hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: raise error, 'failed to disconnect: ' + SCardGetErrorMessage(hresult) ... " %enddef %feature("docstring") DOCSTRING_DISCONNECT; %rename(SCardDisconnect) _Disconnect(SCARDHANDLE hcard, SCARDDWORDARG dwDisposition); SCARDRETCODE _Disconnect(SCARDHANDLE hcard, SCARDDWORDARG dwDisposition); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_ENDTRANSACTION " This function ends a previously begun transaction. The calling application must be the owner of the previously begun transaction or an error will occur. disposition can have the following values: The disposition action is not currently used in this release. Value of disposition Meaning SCARD_LEAVE_CARD Do nothing SCARD_RESET_CARD Reset the card SCARD_UNPOWER_CARD Unpower the card SCARD_EJECT_CARD Eject the card from smartcard.scard import * ... establish context, connect to card, begin transaction ... hresult = SCardEndTransaction(hcard, SCARD_LEAVE_CARD) if hresult != SCARD_S_SUCCESS: raise error, 'failed to end transaction: ' + SCardGetErrorMessage(hresult) " %enddef %feature("docstring") DOCSTRING_ENDTRANSACTION; %rename(SCardEndTransaction) _EndTransaction(SCARDHANDLE hcard, SCARDDWORDARG dwDisposition); SCARDRETCODE _EndTransaction(SCARDHANDLE hcard, SCARDDWORDARG dwDisposition); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_ESTABLISHCONTEXT " This function creates a communication context to the PC/SC Resource Manager. This must be the first function called in a PC/SC application. Value of dwScope Meaning SCARD_SCOPE_USER Operations performed within the scope of the User SCARD_SCOPE_TERMINAL Not used SCARD_SCOPE_GLOBAL Not used SCARD_SCOPE_SYSTEM Operations performed within the scope of the system from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error, 'Failed to establish context: ' + SCardGetErrorMessage(hresult) " %enddef %feature("docstring") DOCSTRING_ESTABLISHCONTEXT; %rename(SCardEstablishContext) _EstablishContext(SCARDDWORDARG dwScope, SCARDCONTEXT* phcontext); SCARDRETCODE _EstablishContext(SCARDDWORDARG dwScope, SCARDCONTEXT* phcontext); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_GETSTATUSCHANGE " This function receives a structure or list of tuples containing reader states. A READERSTATE hast three fields (readername, state, atr). It then blocks for a change in state to occur on any of the OR'd values contained in the current state for a maximum blocking time of dwTimeout or forever if INFINITE is used. The new event state will be contained in state. A status change might be a card insertion or removal event, a change in ATR, etc. Value of state Meaning SCARD_STATE_UNAWARE The application is unaware of the current state, and would like to know. The use of this value results in an immediate return from state transition monitoring services. This is represented by all bits set to zero SCARD_STATE_IGNORE This reader should be ignored SCARD_STATE_CHANGED There is a difference between the state believed by the application, and the state known by the resource manager. When this bit is set, the application may assume a significant state change has occurred on this reader SCARD_STATE_UNKNOWN The given reader name is not recognized by the resource manager. If this bit is set, then SCARD_STATE_CHANGED and SCARD_STATE_IGNORE will also be set SCARD_STATE_UNAVAILABLE The actual state of this reader is not available. If this bit is set, then all the following bits are clear SCARD_STATE_EMPTY There is no card in the reader. If this bit is set, all the following bits will be clear SCARD_STATE_PRESENT There is a card in the reader SCARD_STATE_ATRMATCH There is a card in the reader with an ATR matching one of the target cards. If this bit is set, SCARD_STATE_PRESENT will also be set. This bit is only returned on the SCardLocateCards function SCARD_STATE_EXCLUSIVE The card in the reader is allocated for exclusive use by another application. If this bit is set, SCARD_STATE_PRESENT will also be set SCARD_STATE_INUSE The card in the reader is in use by one or more other applications, but may be connected to in shared mode. If this bit is set, SCARD_STATE_PRESENT will also be set SCARD_STATE_MUTE There is an unresponsive card in the reader from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, readers = SCardListReaders(hcontext, []) readerstates = [] cards = [ 'Schlumberger Cryptoflex 4k', 'Schlumberger Cryptoflex 8k', 'Schlumberger Cryptoflex 8k v2' ] for i in xrange(len(readers)): readerstates += [ (readers[i], SCARD_STATE_UNAWARE) ] hresult, newstates = SCardLocateCards(hcontext, cards, readerstates) print '----- Please insert or remove a card ------------' hresult, newstates = SCardGetStatusChange(hcontext, INFINITE, newstates) for i in newstates reader, eventstate, atr = i if eventstate & SCARD_STATE_ATRMATCH: print '\tCard found' if eventstate & SCARD_STATE_EMPTY: print '\tReader empty' " %enddef %feature("docstring") DOCSTRING_GETSTATUSCHANGE; %rename(SCardGetStatusChange) _GetStatusChange( SCARDCONTEXT hcontext, SCARDDWORDARG dwTimeout, READERSTATELIST* prsl); SCARDRETCODE _GetStatusChange( SCARDCONTEXT hcontext, SCARDDWORDARG dwTimeout, READERSTATELIST* prsl); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_LISTREADERS " This function returns a list of currently available readers on the system. A list of group can be provided in input to list readers in a given group only. from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error, 'Failed to list readers: ' + SCardGetErrorMessage(hresult) print 'PCSC Readers: ', readers hresult, readers = SCardListReaders(hcontext, ['SCard$T1ProtocolReaders', 'SCard$MyOwnGroup'] ... " %enddef %feature("docstring") DOCSTRING_LISTREADERS; %rename(SCardListReaders) _ListReaders( SCARDCONTEXT hcontext, STRINGLIST* READERGROUPSIN, STRINGLIST* READERSFOUND); SCARDRETCODE _ListReaders( SCARDCONTEXT hcontext, STRINGLIST* READERGROUPSIN, STRINGLIST* READERSFOUND); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_LISTREADERGROUPS " This function returns a list of currently available reader groups on the system. from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, readerGroups = SCardListReaderGroups(hcontext) if hresult != SCARD_S_SUCCESS: raise error, 'Unable to list reader groups: ' + SCardGetErrorMessage(hresult) print 'PCSC Reader groups: ', readerGroups " %enddef %feature("docstring") DOCSTRING_LISTREADERGROUPS; %rename(SCardListReaderGroups) _ListReaderGroups(SCARDCONTEXT hcontext, STRINGLIST* READERGROUPSOUT); SCARDRETCODE _ListReaderGroups(SCARDCONTEXT hcontext, STRINGLIST* READERGROUPSOUT); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_RECONNECT " This function reestablishes a connection to a reader that was previously connected to using SCardConnect(). In a multi application environment it is possible for an application to reset the card in shared mode. When this occurs any other application trying to access certain commands will be returned the value SCARD_W_RESET_CARD. When this occurs SCardReconnect() must be called in order to acknowledge that the card was reset and allow it to change it's state accordingly. Value of dwShareMode Meaning SCARD_SHARE_SHARED This application will allow others to share the reader SCARD_SHARE_EXCLUSIVE This application will NOT allow others to share the reader Value of dwPreferredProtocols Meaning SCARD_PROTOCOL_T0 Use the T=0 protocol SCARD_PROTOCOL_T1 Use the T=1 protocol SCARD_PROTOCOL_RAW Use with memory type cards dwPreferredProtocols is a bit mask of acceptable protocols for the connection. You can use (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) if you do not have a preferred protocol. Value of dwInitialization Meaning SCARD_LEAVE_CARD Do nothing SCARD_RESET_CARD Reset the card (warm reset) SCARD_UNPOWER_CARD Unpower the card (cold reset) SCARD_EJECT_CARD Eject the card from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, 'SchlumbergerSema Reflex USB v.2 0', SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) hresult, activeProtocol = SCardReconnect(hcard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0, SCARD_RESET_CARD) ... " %enddef %feature("docstring") DOCSTRING_RECONNECT; %rename(SCardReconnect) _Reconnect( SCARDHANDLE hcard, SCARDDWORDARG dwShareMode, SCARDDWORDARG dwPreferredProtocols, SCARDDWORDARG dwInitialization, SCARDDWORDARG* pdwActiveProtocol ); SCARDRETCODE _Reconnect( SCARDHANDLE hcard, SCARDDWORDARG dwShareMode, SCARDDWORDARG dwPreferredProtocols, SCARDDWORDARG dwInitialization, SCARDDWORDARG* pdwActiveProtocol ); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_RELEASECONTEXT " " %enddef %feature("docstring") DOCSTRING_RELEASECONTEXT; %rename(SCardReleaseContext) _ReleaseContext(SCARDCONTEXT hcontext); SCARDRETCODE _ReleaseContext(SCARDCONTEXT hcontext); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_STATUS " This function returns the current status of the reader connected to by hcard. The reader friendly name is returned, as well as the state, protocol and ATR. The state is a DWORD possibly OR'd with the following values: Value of pdwState Meaning SCARD_ABSENT There is no card in the reader SCARD_PRESENT There is a card in the reader, but it has not been moved into position for use SCARD_SWALLOWED There is a card in the reader in position for use. The card is not powered SCARD_POWERED Power is being provided to the card, but the reader driver is unaware of the mode of the card SCARD_NEGOTIABLE The card has been reset and is awaiting PTS negotiation SCARD_SPECIFIC The card has been reset and specific communication protocols have been established Value of pdwProtocol Meaning SCARD_PROTOCOL_T0 Use the T=0 protocol SCARD_PROTOCOL_T1 Use the T=1 protocol from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, 'SchlumbergerSema Reflex USB v.2 0', SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) hresult, reader, state, protocol, atr = SCardStatus(hcard) if hresult != SCARD_S_SUCCESS: raise error, 'failed to get status: ' + SCardGetErrorMessage(hresult) print 'Reader: ', reader print 'State: ', state print 'Protocol: ', protocol print 'ATR: ', for i in xrange(len(atr)): print '0x%.2X' % i, print "" ... " %enddef %feature("docstring") DOCSTRING_STATUS; %rename(SCardStatus) _Status( SCARDHANDLE hcard, STRING* pszReaderNameOut, SCARDDWORDARG* pdwState, SCARDDWORDARG* pdwProtocol, BYTELIST* ATROUT ); SCARDRETCODE _Status( SCARDHANDLE hcard, STRING* pszReaderNameOut, SCARDDWORDARG* pdwState, SCARDDWORDARG* pdwProtocol, BYTELIST* ATROUT ); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_TRANSMIT " This function sends an APDU to the smart card contained in the reader connected to by SCardConnect(). It returns a result and the card APDU response. Value of pioSendPci Meaning SCARD_PCI_T0 Pre-defined T=0 PCI structure SCARD_PCI_T1 Pre-defined T=1 PCI structure from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, 'SchlumbergerSema Reflex USB v.2 0', SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] hresult, response = SCardTransmit(hcard, SCARD_PCI_T0, SELECT + DF_TELECOM) if hresult != SCARD_S_SUCCESS: raise error, 'Failed to transmit: ' + SCardGetErrorMessage(hresult) " %enddef %feature("docstring") DOCSTRING_TRANSMIT; %rename(SCardTransmit) _Transmit( SCARDHANDLE hcard, unsigned long pioSendPci, BYTELIST* APDUCOMMAND, BYTELIST* APDURESPONSE ); SCARDRETCODE _Transmit( SCARDHANDLE hcard, unsigned long pioSendPci, BYTELIST* APDUCOMMAND, BYTELIST* APDURESPONSE ); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_SCARD_CTL_CODE " This function returns the value of a control code from smartcard.scard import * ... CM_IOCTL_GET_FEATURE_REQUEST = SCARD_CTL_CODE(3400) ... " %enddef %feature("docstring") DOCSTRING_SCARD_CTL_CODE; %rename(SCARD_CTL_CODE) _SCARD_CTL_CODE(long code); long _SCARD_CTL_CODE(long code); /////////////////////////////////////////////////////////////////////////////// %define DOCSTRING_GETERRORMESSAGE " This function return a human readable text for the given PC/SC error code. from smartcard.scard import * ... hresult, response = SCardTransmit(hcard, SCARD_PCI_T0, SELECT + DF_TELECOM) if hresult != SCARD_S_SUCCESS: raise error, 'Failed to transmit: ' + SCardGetErrorMessage(hresult) ... " %enddef %feature("docstring") DOCSTRING_GETERRORMESSAGE; %rename(SCardGetErrorMessage) _GetErrorMessage(long lErrCode); ERRORSTRING* _GetErrorMessage(long lErrCode); %inline %{ %} %{ PyObject *PyExc_SCardError=NULL; %} //---------------------------------------------------------------------- // This code gets added to the module initialization function //---------------------------------------------------------------------- %init %{ PyExc_SCardError = PyErr_NewException("scard.error", NULL, NULL); if (PyExc_SCardError != NULL) PyDict_SetItemString(d, "error", PyExc_SCardError); /* load the PCSC library */ winscard_init(); %} //---------------------------------------------------------------------- // This code is added to the scard.py python module //---------------------------------------------------------------------- %pythoncode %{ error = _scard.error %} %include PcscDefs.i #ifdef PCSCLITEyy %pythoncode %{ def SCardListCards(hcontext, atr, guidlist): return (SCARD_S_SUCCESS, []) def SCardLocateCards(hcontext, cardnames, readerstates): newreaderstates=[] for state in readerstates: newreaderstates.append((state[0], state[1], [])) return (SCARD_S_SUCCESS, newreaderstates) %} #endif #ifdef PCSCLITE %constant char* resourceManager = "pcsclite" ; #ifdef __APPLE__ #ifdef __TIGER__ %constant char* resourceManagerSubType = "pcsclite-tiger" ; #endif //__TIGER__ #ifdef __LEOPARD__ %constant char* resourceManagerSubType = "pcsclite-leopard" ; #endif //__LEOPARD__ #ifdef __LION__ %constant char* resourceManagerSubType = "pcsclite-lion" ; #endif //__LION_ #else // !__APPLE__ %constant char* resourceManagerSubType = "pcsclite-linux" ; #endif // __APPLE__ #endif // PCSCLITE #ifdef WIN32 %constant char* resourceManager = "winscard" ; %constant char* resourceManagerSubType = "winscard-win32" ; #endif // WIN32 pyscard-1.6.14/smartcard/scard/__init__.py0000644000175000017500000000012210633575651022201 0ustar rousseaurousseau00000000000000try: from scard import * except: from smartcard.scard._scard import * pyscard-1.6.14/smartcard/scard/helpers.c0000644000175000017500000010477111747776700021722 0ustar rousseaurousseau00000000000000/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 ==============================================================================*/ #ifdef WIN32 #include #endif #ifdef __APPLE__ #include #else #include #endif #include #include #include "pcsctypes.h" #include "helpers.h" #include "memlog.h" extern PyObject* PyExc_SCardError; #ifdef PCSCLITE #define FALSE (0==1) #define TRUE (1==1) #define lstrlen strlen #endif // PCSCLITE /**==========================================================================**/ static int _IsAReaderState( PyObject* o) /*============================================================================== ==============================================================================*/ { PyObject* o2; // expecting at least 2 items: reader name and current state if( (PyTuple_Size(o)!=2) && (PyTuple_Size(o)!=3) ) { PyErr_SetString( PyExc_TypeError, "Expecting two or three items in tuple." ); return 0; } o2 = PyTuple_GetItem(o, 0); if(!PyString_Check(o2)) { PyErr_SetString( PyExc_TypeError, "Expected a string as reader name." ); return 0; } o2 = PyTuple_GetItem(o, 1); if(!PyInt_Check(o2) && !PyLong_Check(o2) ) { PyErr_SetString( PyExc_TypeError, "Expected an Int as second tuple item." ); return 0; } if(PyTuple_Size(o)==3) { o2 = PyTuple_GetItem(o, 2); if(!PyList_Check(o2)) { PyErr_SetString( PyExc_TypeError, "Expected a list as third tuple item." ); return 0; } } return 1; } /**==========================================================================**/ static int _ReaderStateFromTuple( PyObject* o, READERSTATELIST* prl, unsigned int x ) /*============================================================================== ==============================================================================*/ { char* psz; PyObject* o2; // first tuple item is reader name o2=PyTuple_GetItem(o, 0); psz = PyString_AsString(o2); prl->aszReaderNames[x] = mem_Malloc(strlen(psz)+1); if (!prl->aszReaderNames[x]) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); return 0; } prl->ars[x].szReader = prl->aszReaderNames[x]; strcpy( prl->aszReaderNames[x], psz ); // second tuple item is current state o2=PyTuple_GetItem(o, 1); prl->ars[x].dwCurrentState = (SCARDDWORDARG)PyInt_AsLong(o2); // third tuple item is the ATR (optionally) if(PyTuple_Size(o)==3) { BYTELIST* ATR = mem_Malloc(sizeof(BYTELIST)); if( !ATR ) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); return 0; } o2 = PyTuple_GetItem(o, 2); ATR = SCardHelper_PyByteListToBYTELIST(o2); memcpy(prl->ars[x].rgbAtr, ATR->ab, ATR->cBytes); prl->ars[x].cbAtr = ATR->cBytes; mem_Free(ATR); } return 1; } /**============================================================================= BYTELIST Helpers ==============================================================================*/ /**==========================================================================**/ void SCardHelper_AppendByteListToPyObject( BYTELIST* source, PyObject** ptarget ) /*============================================================================== builds a Python list from a byte list ==============================================================================*/ { PyObject* oByteList; // create byte list... if( (NULL!=source) && (NULL!=source->ab) ) { unsigned int i; oByteList = PyList_New( source->cBytes ); for(i=0; icBytes; i++) { PyObject* pyby; pyby = Py_BuildValue( "b", source->ab[i] ); PyList_SetItem( oByteList, i, pyby ); } } else { oByteList = PyList_New( 0 ); } // append list to target if( !*ptarget ) { *ptarget = oByteList; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = oByteList; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append(*ptarget,oByteList); Py_XDECREF(oByteList); } } /**==========================================================================**/ BYTELIST* SCardHelper_PyByteListToBYTELIST(PyObject* source) /*============================================================================== build a Python byte list from a BYTELIST ==============================================================================*/ { Py_ssize_t cBytes, x; BYTELIST* pbl; // sanity check if (!PyList_Check(source)) { PyErr_SetString( PyExc_TypeError, "Expected a list object." ); return NULL; } cBytes = PyList_Size(source); for( x=0; x0) { pbl->ab = mem_Malloc( cBytes*sizeof(unsigned char) ); if( !pbl->ab ) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); mem_Free( pbl ); return NULL; } } else { pbl->ab=NULL; } pbl->bAllocated=TRUE; pbl->cBytes=(SCARDDWORDARG)cBytes; for( x=0; xab[x] = (unsigned char)PyInt_AsLong(o); } return (BYTELIST*)pbl; } /**==========================================================================**/ void SCardHelper_PrintByteList( BYTELIST* apsz ) /*============================================================================== dump a byte list ==============================================================================*/ { unsigned long i; for(i=0; icBytes; i++) { printf("0x%.2X ", apsz->ab[i] ); } printf("\n"); } /**============================================================================= ERRORSTRING Helpers ==============================================================================*/ /**==========================================================================**/ void SCardHelper_OutErrorStringAsPyObject( ERRORSTRING* source, PyObject** ptarget ) /*============================================================================== Builds a Python string from an ERRORSTRING ==============================================================================*/ { PyObject* pystr; if( NULL!=source ) { pystr = PyString_FromString( (char*)source ); *ptarget = pystr; } else { *ptarget = Py_None; Py_INCREF(Py_None); } } /**============================================================================= GUIDLIST Helpers ==============================================================================*/ /**==========================================================================**/ void SCardHelper_AppendGuidListToPyObject( GUIDLIST* source, PyObject** ptarget ) /*============================================================================== build a Python GUID list from a C GUID list ==============================================================================*/ { PyObject* oByte; PyObject* oGuildItem; PyObject* oGuidList; unsigned char* pc; unsigned int i, j; // create GUID list... for(;;) { if (source!=NULL) { // create GUID list oGuidList = PyList_New( source->cGuids ); if(NULL==oGuidList) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate GUID list" ); break; } for( i=0; icGuids; i++) { oGuildItem=PyList_New( sizeof(GUID) ); if(NULL==oGuildItem) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate GUID item list" ); break; } pc=(unsigned char*)&source->aguid[i]; for (j=0; jbAllocated=TRUE; pgl->cGuids=(unsigned long)cGuids; pgl->hcontext=(unsigned long)NULL; // allocate GUIDs in GUID list if (cGuids>0) { pgl->aguid = mem_Malloc( cGuids*sizeof(GUID) ); if( NULL==pgl->aguid ) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); mem_Free( pgl ); return NULL; } } else { pgl->aguid=NULL; } // fill individual GUIDs /* for( iGuid=0; iGuidxaguid+iGuid*sizeof(GUID); for( x=0; xaguid; for( x=0; xcGuids; i++) { unsigned char* pc=(unsigned char*)&apsz->aguid[i]; for (j=0; jcRStates ); for( i=0; icRStates; i++ ) { PyObject* oReader; PyObject* oEventState; PyObject* oAtr; PyObject* oByte; SCARDDWORDARG j; // reader, event state, atr PyObject* ot = PyTuple_New( 3 ); oReader = PyString_FromString( source->ars[i].szReader ); oEventState = PyInt_FromLong( (SCARDDWORDARG)source->ars[i].dwEventState ); // ATR visibly not initialised if ( source->ars[i].cbAtr > SCARD_ATR_LENGTH) source->ars[i].cbAtr = 0; oAtr = PyList_New( source->ars[i].cbAtr ); for(j=0; jars[i].cbAtr; j++) { oByte = PyInt_FromLong( source->ars[i].rgbAtr[j] ); PyList_SetItem( oAtr, j, oByte ); } PyTuple_SetItem( ot, 0, oReader ); PyTuple_SetItem( ot, 1, oEventState ); PyTuple_SetItem( ot, 2, oAtr ); PyList_SetItem( oRStateList, i, ot ); } } else { oRStateList = PyList_New( 0 ); } if( !*ptarget ) { *ptarget = oRStateList; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = oRStateList; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append(*ptarget,oRStateList); Py_XDECREF(oRStateList); } } /**==========================================================================**/ READERSTATELIST* SCardHelper_PyReaderStateListToREADERSTATELIST(PyObject* source) /*============================================================================== build a READERSTATELIST from a Python list of reader states ==============================================================================*/ { SCARDDWORDARG cRStates, x; READERSTATELIST* prl; // sanity check if (!PyList_Check(source)) { PyErr_SetString( PyExc_TypeError, "Expected a list object." ); return NULL; } cRStates = (SCARDDWORDARG)PyList_Size(source); for( x=0; xcRStates = cRStates; prl->ars = mem_Malloc( cRStates*sizeof(SCARD_READERSTATE) ); if (!prl->ars) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); mem_Free( prl ); return NULL; } prl->aszReaderNames = mem_Malloc( cRStates*sizeof(char*) ); if (!prl->aszReaderNames) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); mem_Free( prl->ars ); mem_Free( prl ); return NULL; } for( x=0; xaszReaderNames[x] ); } mem_Free( prl->ars ); mem_Free( prl ); return NULL; } } return (READERSTATELIST*)prl; } /**==========================================================================**/ void SCardHelper_PrintReaderStateList( READERSTATELIST* prl ) /*============================================================================== dump a reader state list ==============================================================================*/ { int i; SCARDDWORDARG j; for( i=0; prl && icRStates; i++ ) { printf("%s userdata: %p current: %lx event: %lx \n", prl->ars[i].szReader, prl->ars[i].pvUserData, (long)prl->ars[i].dwCurrentState, (long)prl->ars[i].dwEventState ); for(j=0; jars[i].cbAtr; j++ ) { printf("0x%.2X ", prl->ars[i].rgbAtr[j] ); } printf("\n"); if(prl->ars[i].dwEventState & SCARD_STATE_UNAWARE) { printf("Card state unaware\n"); } if(prl->ars[i].dwEventState & SCARD_STATE_IGNORE) { printf("Card state ignore\n"); } if(prl->ars[i].dwEventState & SCARD_STATE_CHANGED) { printf("Card state changed\n"); } if(prl->ars[i].dwEventState & SCARD_STATE_UNKNOWN) { printf("Card state unknown\n"); } if(prl->ars[i].dwEventState & SCARD_STATE_UNAVAILABLE) { printf("Card state unavailable\n"); } if(prl->ars[i].dwEventState & SCARD_STATE_EMPTY) { printf("No card in reader\n"); } if(prl->ars[i].dwEventState & SCARD_STATE_PRESENT) { printf("Card in reader\n"); } if(prl->ars[i].dwEventState & SCARD_STATE_ATRMATCH) { printf("Card found\n"); } if(prl->ars[i].dwEventState & SCARD_STATE_EXCLUSIVE) { printf("Card in reader allocated for exclusive use by another application\n"); } if(prl->ars[i].dwEventState & SCARD_STATE_INUSE) { printf("Card in reader is in use but can be shared\n"); } if(prl->ars[i].dwEventState & SCARD_STATE_MUTE) { printf("Card in reader is mute\n"); } } } /**============================================================================= SCARDCONTEXT Helpers ==============================================================================*/ /**==========================================================================**/ void SCardHelper_AppendSCardContextToPyObject( SCARDCONTEXT source, PyObject** ptarget ) /*============================================================================== builds a Python SCARDCONTEXT from a C SCARDCONTEXT ==============================================================================*/ { PyObject* oScardContext; // create SCARDCONTEXT #ifdef PCSCLITE oScardContext = PyLong_FromLong( (long)source ); #else // !PCSCLITE oScardContext = PyLong_FromVoidPtr( (void*)source ); #endif // PCSCLITE // append list to target if( !*ptarget ) { *ptarget = oScardContext; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = oScardContext; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append(*ptarget,oScardContext); Py_XDECREF(oScardContext); } } /**==========================================================================**/ SCARDCONTEXT SCardHelper_PyScardContextToSCARDCONTEXT(PyObject* source) /*============================================================================== build a SCARDCONTEXT from a python SCARDCONTEXT ==============================================================================*/ { SCARDCONTEXT scRet=0; // sanity check // do we have a python long? if (!PyLong_Check(source)) { PyErr_SetString( PyExc_TypeError, "Expected a python long as SCARDCONTEXT." ); return 0; } #ifdef PCSCLITE scRet = PyLong_AsLong( source ); #else // !PCSCLITE scRet = PyLong_AsVoidPtr( source ); #endif // PCSCLITE return scRet; } /**============================================================================= SCARDHANDLE Helpers ==============================================================================*/ /**==========================================================================**/ void SCardHelper_AppendSCardHandleToPyObject( SCARDHANDLE source, PyObject** ptarget ) /*============================================================================== builds a Python SCARDHANDLE from a C SCARDHANDLE ==============================================================================*/ { PyObject* oScardHandle; // create SCARDHANDLE #ifdef PCSCLITE oScardHandle = PyLong_FromLong( (long)source ); #else // !PCSCLITE oScardHandle = PyLong_FromVoidPtr( (void*)source ); #endif // PCSCLITE // append list to target if( !*ptarget ) { *ptarget = oScardHandle; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = oScardHandle; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append(*ptarget,oScardHandle); Py_XDECREF(oScardHandle); } } /**==========================================================================**/ SCARDCONTEXT SCardHelper_PyScardHandleToSCARDHANDLE(PyObject* source) /*============================================================================== build a SCARDHANDLE from a python SCARDHANDLE ==============================================================================*/ { SCARDHANDLE scRet=0; // sanity check // do we have a python long? if (!PyLong_Check(source)) { PyErr_SetString( PyExc_TypeError, "Expected a python long as SCARDHANDLE." ); return 0; } #ifdef PCSCLITE scRet = PyLong_AsLong( source ); #else // !PCSCLITE scRet = PyLong_AsVoidPtr( source ); #endif // PCSCLITE return scRet; } /**============================================================================= SCARDDWORDARG Helpers ==============================================================================*/ /**==========================================================================**/ void SCardHelper_AppendSCardDwordArgToPyObject( SCARDDWORDARG source, PyObject** ptarget ) /*============================================================================== builds a Python SCARDDWORDARG from a C SCARDDWORDARG ==============================================================================*/ { PyObject* oScardDword; // create SCARDDWORDARG #ifdef PCSCLITE oScardDword = PyLong_FromLong( (long)source ); #else // !PCSCLITE oScardDword = PyLong_FromUnsignedLong( (unsigned long)source ); #endif // PCSCLITE // append list to target if( !*ptarget ) { *ptarget = oScardDword; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = oScardDword; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append(*ptarget,oScardDword); Py_XDECREF(oScardDword); } } /**==========================================================================**/ SCARDDWORDARG SCardHelper_PySCardDwordArgToSCARDDWORDARG(PyObject* source) /*============================================================================== build a SCARDDWORDARG from a python SCARDDWORDARG ==============================================================================*/ { SCARDDWORDARG scRet=0; // sanity check // do we have a python long or int? if( !PyLong_Check(source) && !PyInt_Check(source) ) { PyErr_SetString( PyExc_TypeError, "Expected a python integer or long." ); return -1; } #ifdef PCSCLITE scRet = PyLong_AsLong( source ); #else // !PCSCLITE scRet = PyLong_AsUnsignedLong( source ); #endif // PCSCLITE return scRet; } /**============================================================================= STRING Helpers ==============================================================================*/ /**==========================================================================**/ void SCardHelper_AppendStringToPyObject( STRING* source, PyObject** ptarget ) /*============================================================================== Builds a Python string from a STRING ==============================================================================*/ { PyObject* pystr; if(NULL!=source) { if(NULL!=source->sz) { pystr = PyString_FromString( source->sz ); } else { pystr = Py_None; Py_INCREF(Py_None); } if( !*ptarget ) { *ptarget = pystr; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = pystr; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append( *ptarget, pystr ); Py_XDECREF( pystr ); } } else { if( !*ptarget ) { *ptarget = Py_None; Py_INCREF(Py_None); } } } /**==========================================================================**/ STRING* SCardHelper_PyStringToString( PyObject* source ) /*============================================================================== Build a STRING from a Python string; the string is allocated and will have to be freed externally to the wrapper ==============================================================================*/ { size_t ulLength; STRING* pstr=NULL; for(;;) { // sanity check if( !PyString_Check( source ) ) { PyErr_SetString( PyExc_TypeError, "Expected a string." ); break; } pstr=(STRING*)mem_Malloc( sizeof(STRING) ); if(NULL==pstr) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate STRING" ); break; } ulLength=strlen( PyString_AsString(source)) + 1 ; pstr->sz=(char*)mem_Malloc( ulLength ); if(NULL==pstr->sz) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate STRING buffer" ); break; } strcpy( pstr->sz, PyString_AsString( source ) ); break; } return pstr; } /**==========================================================================**/ void SCardHelper_PrintString( STRING* str ) /*============================================================================== dump a string list ==============================================================================*/ { if(NULL!=str) { char* p=str->sz; if( NULL!=p) { printf("%s ", p ); } } } /**============================================================================= STRINGLIST Helpers ==============================================================================*/ /**==========================================================================**/ void SCardHelper_AppendStringListToPyObject( STRINGLIST* source, PyObject** ptarget ) /*============================================================================== builds a Python list from a STRINGLIST; the multi-string list in the STRINGLIST is stored as series of null-terminated strings terminated by a null, e.g. item0\0item2\0lastitem\0\0) ==============================================================================*/ { unsigned int cStr; char* p=source->ac; PyObject* oStrList; //PyObject* o; // count STRs in STRINGLIST list if( NULL!=p ) { unsigned int i; for( i=0, cStr=0; ; i+=lstrlen( p+i ) + 1 ) { if (lstrlen( p+i ) > 0) { cStr++; } else { break; } } } else { cStr=0; } // create STR list... if( NULL!=p ) { unsigned int i, j; oStrList = PyList_New( cStr ); for( i=0, j=0; ; j++, i+=lstrlen( p+i ) + 1 ) { if (lstrlen( p+i ) > 0) { PyObject* pystr; pystr = PyString_FromString( p+i ); PyList_SetItem( oStrList, j, pystr ); } else { break; } } } else { oStrList = PyList_New( cStr ); } if( !*ptarget ) { *ptarget = oStrList; } else if( *ptarget == Py_None ) { Py_DECREF(Py_None); *ptarget = oStrList; } else { if( !PyList_Check(*ptarget) ) { PyObject* o2 = *ptarget; *ptarget = PyList_New(0); PyList_Append(*ptarget,o2); Py_XDECREF(o2); } PyList_Append(*ptarget,oStrList); Py_XDECREF(oStrList); } } /**==========================================================================**/ STRINGLIST* SCardHelper_PyStringListToStringList(PyObject* source) /*============================================================================== build a Python string list from a STRINGLIST ==============================================================================*/ { Py_ssize_t cStrings, cChars, x; STRINGLIST* psl; char* p; // sanity check if (!PyList_Check(source)) { PyErr_SetString( PyExc_TypeError, "Expected a list object." ); return NULL; } cStrings = PyList_Size(source); for( x=0, cChars=0; xbAllocated=TRUE; psl->hcontext = 0; if ( cChars>1 ) { psl->ac = mem_Malloc( cChars*sizeof(char) ); if (!psl->ac) { PyErr_SetString( PyExc_MemoryError, "Unable to allocate temporary array" ); mem_Free( psl ); return NULL; } for( x=0, p=psl->ac; xac=NULL; } return (STRINGLIST*)psl; } /**==========================================================================**/ void SCardHelper_PrintStringList( STRINGLIST* sl ) /*============================================================================== dump a string list ==============================================================================*/ { char* p=(char*)sl->ac; unsigned int i; for( i=0; ; i+=lstrlen( p+i ) + 1 ) { if (lstrlen( p+i ) > 0) { printf("%s ", p+i ); } else { printf("\n" ); break; } } } #ifdef WIN32 /**==========================================================================**/ BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) /*============================================================================== Initialize and clean-up memory logging on process attach and detach ==============================================================================*/ { switch(fdwReason) { case DLL_PROCESS_ATTACH: if (!mem_Init()) { fprintf( stderr, "Failed to initialize memory logging services!\n" ); } break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: if (!mem_CleanUp()) { fprintf( stderr, "Failed to cleanup memory logging services!\n" ); } break; } return TRUE; return 1; } #endif // WIN32 pyscard-1.6.14/smartcard/scard/gemalto.ver0000644000175000017500000000706111747776700022254 0ustar rousseaurousseau00000000000000#ifndef VER_COMPANYNAME_STR #define VER_COMPANYNAME_STR "gemalto\0" #endif #ifndef VER_LEGALCOPYRIGHT_YEARS #define VER_LEGALCOPYRIGHT_YEARS "2001-2012" #endif #ifndef VER_LEGALCOPYRIGHT_STR #define VER_LEGALCOPYRIGHT_STR "Copyright \251 gemalto" VER_LEGALCOPYRIGHT_YEARS #endif #ifndef VER_PRODUCTNAME_STR #define VER_PRODUCTNAME_STR "Smart Cards Sofware Development Tools" #endif #ifndef VER_PRODUCTVERSION #define VER_PRODUCTVERSION 1,06,14,0010 #endif #ifndef VER_FILEVERSION #define VER_FILEVERSION VER_PRODUCTVERSION #endif #ifndef VER_PRODUCTVERSION_STR #define VER_PRODUCTVERSION_STR "1.6.14" #endif #ifndef VER_FILEFLAGSMASK #define VER_FILEFLAGSMASK (VS_FF_DEBUG | VS_FF_PRERELEASE) #endif #ifndef VER_FILEFLAGS #ifdef DEBUG #define VER_FILEFLAGS (VS_FF_DEBUG) #else #define VER_FILEFLAGS (0) #endif #endif #ifndef VER_FILEOS #ifdef WIN32 #define VER_FILEOS VOS_NT_WINDOWS32 #else #define VER_FILEOS VOS_DOS_WINDOWS16 #endif #endif #ifndef VER_FILEVERSION_STR #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR #endif #ifndef VER_ORIGINALFILENAME_STR #define VER_ORIGINALFILENAME_STR VER_INTERNALNAME_STR #endif #define EXPORT_TAG #ifdef RC_INVOKED VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION PRODUCTVERSION VER_PRODUCTVERSION FILEFLAGSMASK VER_FILEFLAGSMASK FILEFLAGS VER_FILEFLAGS FILEOS VER_FILEOS FILETYPE VER_FILETYPE FILESUBTYPE VER_FILESUBTYPE BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904B0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */ BEGIN VALUE "CompanyName", VER_COMPANYNAME_STR VALUE "FileDescription", VER_FILEDESCRIPTION_STR EXPORT_TAG VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", VER_INTERNALNAME_STR VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR VALUE "OriginalFilename",VER_ORIGINALFILENAME_STR VALUE "ProductName", VER_PRODUCTNAME_STR VALUE "ProductVersion", VER_PRODUCTVERSION_STR #ifdef VER_OLESELFREGISTER VALUE "OleSelfRegister", "\0" #endif END BLOCK "040c04b0" /* LANG_FRENCH/SUBLANG_FRENCH */ BEGIN VALUE "CompanyName", VER_COMPANYNAME_STR VALUE "FileDescription", VER_FILEDESCRIPTION_STR EXPORT_TAG VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", VER_INTERNALNAME_STR VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR VALUE "OriginalFilename",VER_ORIGINALFILENAME_STR VALUE "ProductName", VER_PRODUCTNAME_STR VALUE "ProductVersion", VER_PRODUCTVERSION_STR #ifdef VER_OLESELFREGISTER VALUE "OleSelfRegister", "\0" #endif END #ifdef VER_ANSICP /* Some apps are hard coded to look for ANSI CP. */ BLOCK "040904E4" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Ansi CP */ BEGIN VALUE "CompanyName", VER_COMPANYNAME_STR VALUE "FileDescription", VER_FILEDESCRIPTION_STR EXPORT_TAG VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", VER_INTERNALNAME_STR VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR VALUE "OriginalFilename",VER_ORIGINALFILENAME_STR VALUE "ProductName", VER_PRODUCTNAME_STR VALUE "ProductVersion", VER_PRODUCTVERSION_STR #ifdef VER_OLESELFREGISTER VALUE "OleSelfRegister", "\0" #endif END #endif END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 0x04B0 END END #endif pyscard-1.6.14/smartcard/scard/PcscDefs.i0000644000175000017500000003303411747776700021751 0ustar rousseaurousseau00000000000000/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 ==============================================================================*/ typedef enum { SCARD_SCOPE_USER, SCARD_SCOPE_TERMINAL, SCARD_SCOPE_SYSTEM } ScopeType ; typedef enum { SCARD_SHARE_SHARED, SCARD_SHARE_EXCLUSIVE, SCARD_SHARE_DIRECT } ShareType ; typedef enum { SCARD_LEAVE_CARD, SCARD_RESET_CARD, SCARD_UNPOWER_CARD, SCARD_EJECT_CARD } DispositionType ; typedef enum { SCARD_STATE_UNAWARE, SCARD_STATE_IGNORE, SCARD_STATE_CHANGED, SCARD_STATE_UNKNOWN, SCARD_STATE_UNAVAILABLE, SCARD_STATE_EMPTY, SCARD_STATE_PRESENT, SCARD_STATE_ATRMATCH, SCARD_STATE_EXCLUSIVE, SCARD_STATE_INUSE, SCARD_STATE_MUTE } StateType ; // SCARD_STATE_UNPOWERED is not defined on Windows and old Mac OS X %constant unsigned long SCARD_STATE_UNPOWERED = 0x0400 ; // protocols #ifdef WIN32 typedef enum { SCARD_PROTOCOL_UNDEFINED, SCARD_PROTOCOL_T0, SCARD_PROTOCOL_T1, SCARD_PROTOCOL_RAW, SCARD_PROTOCOL_Tx, SCARD_PROTOCOL_DEFAULT, SCARD_PROTOCOL_OPTIMAL } ProtocolType ; // define pcsc lite constants for winscard %constant unsigned long SCARD_PROTOCOL_UNSET = SCARD_PROTOCOL_UNDEFINED ; %constant unsigned long SCARD_PROTOCOL_ANY = SCARD_PROTOCOL_Tx ; %constant unsigned long SCARD_PROTOCOL_T15 = 0x00000008 ; #endif #ifdef PCSCLITE #ifdef __APPLE__ typedef enum { SCARD_PROTOCOL_T0, SCARD_PROTOCOL_T1, SCARD_PROTOCOL_RAW, SCARD_PROTOCOL_ANY } ProtocolType ; %constant unsigned long SCARD_PROTOCOL_UNSET = SCARD_PROTOCOL_ANY ; %constant unsigned long SCARD_PROTOCOL_T15 = 0x00000008 ; %constant unsigned long SCARD_PROTOCOL_UNDEFINED = 0 ; %constant unsigned long SCARD_PROTOCOL_OPTIMAL = SCARD_PROTOCOL_ANY ; #else //__APPLE__ typedef enum { SCARD_PROTOCOL_UNSET, SCARD_PROTOCOL_T0, SCARD_PROTOCOL_T1, SCARD_PROTOCOL_RAW, SCARD_PROTOCOL_T15, SCARD_PROTOCOL_ANY } ProtocolType ; %constant unsigned long SCARD_PROTOCOL_UNDEFINED = SCARD_PROTOCOL_UNSET ; %constant unsigned long SCARD_PROTOCOL_OPTIMAL = SCARD_PROTOCOL_UNSET ; #endif //!__APPLE__ // define winscard constants for pcsc lite %constant unsigned long SCARD_PROTOCOL_Tx = SCARD_PROTOCOL_ANY ; %constant unsigned long SCARD_PROTOCOL_DEFAULT = SCARD_PROTOCOL_ANY ; #endif //PCSCLITE %constant unsigned long SCARD_PCI_T0 = 0x01 ; %constant unsigned long SCARD_PCI_T1 = 0x02 ; %constant unsigned long SCARD_PCI_RAW = 0x04 ; #ifdef WIN32 typedef enum { SCARD_PROVIDER_PRIMARY, SCARD_PROVIDER_CSP } ProviderType ; typedef enum { SCARD_ATTR_VENDOR_NAME, SCARD_ATTR_VENDOR_IFD_TYPE, SCARD_ATTR_VENDOR_IFD_VERSION, SCARD_ATTR_VENDOR_IFD_SERIAL_NO, SCARD_ATTR_CHANNEL_ID, SCARD_ATTR_DEFAULT_CLK, SCARD_ATTR_MAX_CLK, SCARD_ATTR_DEFAULT_DATA_RATE, SCARD_ATTR_MAX_DATA_RATE, SCARD_ATTR_MAX_IFSD, SCARD_ATTR_POWER_MGMT_SUPPORT, SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE, SCARD_ATTR_USER_AUTH_INPUT_DEVICE, SCARD_ATTR_CHARACTERISTICS, SCARD_ATTR_CURRENT_PROTOCOL_TYPE, SCARD_ATTR_CURRENT_CLK, SCARD_ATTR_CURRENT_F, SCARD_ATTR_CURRENT_D, SCARD_ATTR_CURRENT_N, SCARD_ATTR_CURRENT_W, SCARD_ATTR_CURRENT_IFSC, SCARD_ATTR_CURRENT_IFSD, SCARD_ATTR_CURRENT_BWT, SCARD_ATTR_CURRENT_CWT, SCARD_ATTR_CURRENT_EBC_ENCODING, SCARD_ATTR_EXTENDED_BWT, SCARD_ATTR_ICC_PRESENCE, SCARD_ATTR_ICC_INTERFACE_STATUS, SCARD_ATTR_CURRENT_IO_STATE, SCARD_ATTR_ATR_STRING, SCARD_ATTR_ICC_TYPE_PER_ATR, SCARD_ATTR_ESC_RESET, SCARD_ATTR_ESC_CANCEL, SCARD_ATTR_ESC_AUTHREQUEST, SCARD_ATTR_MAXINPUT, SCARD_ATTR_DEVICE_UNIT, SCARD_ATTR_DEVICE_IN_USE, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A, SCARD_ATTR_DEVICE_SYSTEM_NAME_A, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W, SCARD_ATTR_DEVICE_SYSTEM_NAME_W, SCARD_ATTR_SUPRESS_T1_IFS_REQUEST } AttributeType ; typedef enum { // from winerror.h ERROR_ALREADY_EXISTS } ErrorTypeWin32Only; #endif // WIN32 #ifdef PCSCLITE typedef enum { SCARD_ATTR_VENDOR_NAME , SCARD_ATTR_VENDOR_IFD_TYPE , SCARD_ATTR_VENDOR_IFD_VERSION , SCARD_ATTR_VENDOR_IFD_SERIAL_NO , SCARD_ATTR_CHANNEL_ID , SCARD_ATTR_ASYNC_PROTOCOL_TYPES , SCARD_ATTR_DEFAULT_CLK , SCARD_ATTR_MAX_CLK , SCARD_ATTR_DEFAULT_DATA_RATE , SCARD_ATTR_MAX_DATA_RATE , SCARD_ATTR_MAX_IFSD , SCARD_ATTR_SYNC_PROTOCOL_TYPES , SCARD_ATTR_POWER_MGMT_SUPPORT , SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE , SCARD_ATTR_USER_AUTH_INPUT_DEVICE , SCARD_ATTR_CHARACTERISTICS , SCARD_ATTR_CURRENT_PROTOCOL_TYPE , SCARD_ATTR_CURRENT_CLK , SCARD_ATTR_CURRENT_F , SCARD_ATTR_CURRENT_D , SCARD_ATTR_CURRENT_N , SCARD_ATTR_CURRENT_W , SCARD_ATTR_CURRENT_IFSC , SCARD_ATTR_CURRENT_IFSD , SCARD_ATTR_CURRENT_BWT , SCARD_ATTR_CURRENT_CWT , SCARD_ATTR_CURRENT_EBC_ENCODING , SCARD_ATTR_EXTENDED_BWT , SCARD_ATTR_ICC_PRESENCE , SCARD_ATTR_ICC_INTERFACE_STATUS , SCARD_ATTR_CURRENT_IO_STATE , SCARD_ATTR_ATR_STRING , SCARD_ATTR_ICC_TYPE_PER_ATR , SCARD_ATTR_ESC_RESET , SCARD_ATTR_ESC_CANCEL , SCARD_ATTR_ESC_AUTHREQUEST , SCARD_ATTR_MAXINPUT , SCARD_ATTR_DEVICE_UNIT , SCARD_ATTR_DEVICE_IN_USE , SCARD_ATTR_DEVICE_FRIENDLY_NAME_A , SCARD_ATTR_DEVICE_SYSTEM_NAME_A , SCARD_ATTR_DEVICE_FRIENDLY_NAME_W , SCARD_ATTR_DEVICE_SYSTEM_NAME_W , SCARD_ATTR_SUPRESS_T1_IFS_REQUEST } AttributeType ; %constant unsigned long SCARD_ATTR_DEVICE_FRIENDLY_NAME = SCARD_ATTR_DEVICE_FRIENDLY_NAME_A ; %constant unsigned long SCARD_ATTR_DEVICE_SYSTEM_NAME = SCARD_ATTR_DEVICE_SYSTEM_NAME_A ; #endif //PCSCLITE /* int and unsigned long are different on 64-bits systems */ #ifdef __APPLE__ #define TYPE int #else #define TYPE long #endif %constant TYPE SCARD_S_SUCCESS = SCARD_S_SUCCESS ; %constant TYPE SCARD_F_INTERNAL_ERROR = SCARD_F_INTERNAL_ERROR ; %constant TYPE SCARD_E_CANCELLED = SCARD_E_CANCELLED ; %constant TYPE SCARD_E_INVALID_HANDLE = SCARD_E_INVALID_HANDLE ; %constant TYPE SCARD_E_INVALID_PARAMETER = SCARD_E_INVALID_PARAMETER ; %constant TYPE SCARD_E_INVALID_TARGET = SCARD_E_INVALID_TARGET ; %constant TYPE SCARD_E_NO_MEMORY = SCARD_E_NO_MEMORY ; %constant TYPE SCARD_F_WAITED_TOO_LONG = SCARD_F_WAITED_TOO_LONG ; %constant TYPE SCARD_E_INSUFFICIENT_BUFFER = SCARD_E_INSUFFICIENT_BUFFER ; %constant TYPE SCARD_E_UNKNOWN_READER = SCARD_E_UNKNOWN_READER ; %constant TYPE SCARD_E_TIMEOUT = SCARD_E_TIMEOUT ; %constant TYPE SCARD_E_SHARING_VIOLATION = SCARD_E_SHARING_VIOLATION ; %constant TYPE SCARD_E_NO_SMARTCARD = SCARD_E_NO_SMARTCARD ; %constant TYPE SCARD_E_UNKNOWN_CARD = SCARD_E_UNKNOWN_CARD ; %constant TYPE SCARD_E_CANT_DISPOSE = SCARD_E_CANT_DISPOSE ; %constant TYPE SCARD_E_PROTO_MISMATCH = SCARD_E_PROTO_MISMATCH ; %constant TYPE SCARD_E_NOT_READY = SCARD_E_NOT_READY ; %constant TYPE SCARD_E_INVALID_VALUE = SCARD_E_INVALID_VALUE ; %constant TYPE SCARD_E_SYSTEM_CANCELLED = SCARD_E_SYSTEM_CANCELLED ; %constant TYPE SCARD_F_COMM_ERROR = SCARD_F_COMM_ERROR ; %constant TYPE SCARD_F_UNKNOWN_ERROR = SCARD_F_UNKNOWN_ERROR ; %constant TYPE SCARD_E_INVALID_ATR = SCARD_E_INVALID_ATR ; %constant TYPE SCARD_E_NOT_TRANSACTED = SCARD_E_NOT_TRANSACTED ; %constant TYPE SCARD_E_READER_UNAVAILABLE = SCARD_E_READER_UNAVAILABLE ; %constant TYPE SCARD_E_PCI_TOO_SMALL = SCARD_E_PCI_TOO_SMALL ; %constant TYPE SCARD_E_READER_UNSUPPORTED = SCARD_E_READER_UNSUPPORTED ; %constant TYPE SCARD_E_DUPLICATE_READER = SCARD_E_DUPLICATE_READER ; %constant TYPE SCARD_E_CARD_UNSUPPORTED = SCARD_E_CARD_UNSUPPORTED ; %constant TYPE SCARD_E_NO_SERVICE = SCARD_E_NO_SERVICE ; %constant TYPE SCARD_E_SERVICE_STOPPED = SCARD_E_SERVICE_STOPPED ; #ifdef SCARD_E_NO_READERS_AVAILABLE %constant TYPE SCARD_E_NO_READERS_AVAILABLE = SCARD_E_NO_READERS_AVAILABLE ; #else %constant TYPE SCARD_E_NO_READERS_AVAILABLE = 0x8010002E ; #endif %constant TYPE SCARD_E_UNSUPPORTED_FEATURE = SCARD_E_UNSUPPORTED_FEATURE ; %constant TYPE SCARD_W_UNSUPPORTED_CARD = SCARD_W_UNSUPPORTED_CARD ; %constant TYPE SCARD_W_UNRESPONSIVE_CARD = SCARD_W_UNRESPONSIVE_CARD ; %constant TYPE SCARD_W_UNPOWERED_CARD = SCARD_W_UNPOWERED_CARD ; %constant TYPE SCARD_W_RESET_CARD = SCARD_W_RESET_CARD ; %constant TYPE SCARD_W_REMOVED_CARD = SCARD_W_REMOVED_CARD ; #ifdef SCARD_W_SECURITY_VIOLATION /* introduced in pcsc-lite > 1.5.2 */ %constant TYPE SCARD_W_SECURITY_VIOLATION = SCARD_W_SECURITY_VIOLATION ; %constant TYPE SCARD_W_WRONG_CHV = SCARD_W_WRONG_CHV ; %constant TYPE SCARD_W_CHV_BLOCKED = SCARD_W_CHV_BLOCKED ; %constant TYPE SCARD_W_EOF = SCARD_W_EOF ; %constant TYPE SCARD_W_CANCELLED_BY_USER = SCARD_W_CANCELLED_BY_USER ; %constant TYPE SCARD_W_CARD_NOT_AUTHENTICATED = SCARD_W_CARD_NOT_AUTHENTICATED ; %constant TYPE SCARD_E_UNEXPECTED = SCARD_E_UNEXPECTED ; %constant TYPE SCARD_E_ICC_INSTALLATION = SCARD_E_ICC_INSTALLATION ; %constant TYPE SCARD_E_ICC_CREATEORDER = SCARD_E_ICC_CREATEORDER ; %constant TYPE SCARD_E_DIR_NOT_FOUND = SCARD_E_DIR_NOT_FOUND ; %constant TYPE SCARD_E_FILE_NOT_FOUND = SCARD_E_FILE_NOT_FOUND ; %constant TYPE SCARD_E_NO_DIR = SCARD_E_NO_DIR ; %constant TYPE SCARD_E_NO_FILE = SCARD_E_NO_FILE ; %constant TYPE SCARD_E_NO_ACCESS = SCARD_E_NO_ACCESS ; %constant TYPE SCARD_E_WRITE_TOO_MANY = SCARD_E_WRITE_TOO_MANY ; %constant TYPE SCARD_E_BAD_SEEK = SCARD_E_BAD_SEEK ; %constant TYPE SCARD_E_INVALID_CHV = SCARD_E_INVALID_CHV ; %constant TYPE SCARD_E_UNKNOWN_RES_MNG = SCARD_E_UNKNOWN_RES_MNG ; %constant TYPE SCARD_E_NO_SUCH_CERTIFICATE = SCARD_E_NO_SUCH_CERTIFICATE ; %constant TYPE SCARD_E_CERTIFICATE_UNAVAILABLE = SCARD_E_CERTIFICATE_UNAVAILABLE ; %constant TYPE SCARD_E_COMM_DATA_LOST = SCARD_E_COMM_DATA_LOST ; %constant TYPE SCARD_E_NO_KEY_CONTAINER = SCARD_E_NO_KEY_CONTAINER ; %constant TYPE SCARD_E_SERVER_TOO_BUSY = SCARD_E_SERVER_TOO_BUSY ; #else %constant TYPE SCARD_W_SECURITY_VIOLATION = 0x8010006A ; %constant TYPE SCARD_W_WRONG_CHV = 0x8010006B ; %constant TYPE SCARD_W_CHV_BLOCKED = 0x8010006C ; %constant TYPE SCARD_W_EOF = 0x8010006D ; %constant TYPE SCARD_W_CANCELLED_BY_USER = 0x8010006E ; %constant TYPE SCARD_W_CARD_NOT_AUTHENTICATED = 0x8010006F ; %constant TYPE SCARD_E_UNEXPECTED = 0x8010001F ; %constant TYPE SCARD_E_ICC_INSTALLATION = 0x80100020 ; %constant TYPE SCARD_E_ICC_CREATEORDER = 0x80100021 ; %constant TYPE SCARD_E_DIR_NOT_FOUND = 0x80100023 ; %constant TYPE SCARD_E_FILE_NOT_FOUND = 0x80100024 ; %constant TYPE SCARD_E_NO_DIR = 0x80100025 ; %constant TYPE SCARD_E_NO_FILE = 0x80100026 ; %constant TYPE SCARD_E_NO_ACCESS = 0x80100027 ; %constant TYPE SCARD_E_WRITE_TOO_MANY = 0x80100028 ; %constant TYPE SCARD_E_BAD_SEEK = 0x80100029 ; %constant TYPE SCARD_E_INVALID_CHV = 0x8010002A ; %constant TYPE SCARD_E_UNKNOWN_RES_MNG = 0x8010002B ; %constant TYPE SCARD_E_NO_SUCH_CERTIFICATE = 0x8010002C ; %constant TYPE SCARD_E_CERTIFICATE_UNAVAILABLE = 0x8010002D ; %constant TYPE SCARD_E_COMM_DATA_LOST = 0x8010002F ; %constant TYPE SCARD_E_NO_KEY_CONTAINER = 0x80100030 ; %constant TYPE SCARD_E_SERVER_TOO_BUSY = 0x80100031 ; #endif #ifdef WIN32 typedef enum { ERROR_INVALID_HANDLE } Win32ErrorType ; #endif //WIN32 #ifdef PCSCLITE %constant unsigned long INVALID_HANDLE = SCARD_E_INVALID_HANDLE ; #endif //PCSCLITE // this error code is defined outside the enum, since it is available // on winscard only (e.g. not in pcsc lite) %constant unsigned long SCARD_P_SHUTDOWN = 0x80100018 ; // Infinite timeout // on Mac OS X Tiger, a 0xffffffff infinite time-out causes a random crash upon SCardGetStatusChange return #ifdef __TIGER__ %constant unsigned long INFINITE = 4320000 ; #else // !__TIGER__ %constant unsigned long INFINITE = 0x7FFFFFFF ; #endif // __TIGER__ pyscard-1.6.14/smartcard/scard/memlog.h0000644000175000017500000000403211747776700021532 0ustar rousseaurousseau00000000000000/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 ==============================================================================*/ #ifndef __MEMLOG_H__ #define __MEMLOG_H__ #ifdef __cplusplus extern "C" { #endif // __cplusplus // // define __ENABLE_MEMLOG__ and write your own version // of mem_XXX functions to enable memory logging; this // is useful to track memory leaks when fiddling with // the swig typemaps. #ifdef __ENABLE_MEMLOG__ int mem_CleanUp( void ); void __cdecl mem_Free( void* pv ); void mem_HeapCheck( void ); int mem_Init( void ); void* __cdecl mem_Malloc( size_t ulSize ); void* __cdecl mem_MallocWithCaller( size_t ulSize, void* pvCaller ); void mem_HeapPrint( void ); // // defaults to free/malloc // #else // !__ENABLE_MEMLOG__ #define mem_CleanUp() (1) #define mem_Free free #define mem_HeapCheck() #define mem_Init() (1) #define mem_Malloc malloc #define mem_MallocWithCaller( x, y ) malloc( x ) #define mem_HeapPrint() #endif // __ENABLE_MEMLOG__ #ifdef __cplusplus } #endif // __cplusplus #endif // __MEMLOG_H__ pyscard-1.6.14/smartcard/scard/pyscard-reader.h0000644000175000017500000001347011747776700023165 0ustar rousseaurousseau00000000000000/*============================================================================== This file contains SCARD_ATTR attributes definitions taken from reader.h, in MUSCLE SmartCard Development ( http://www.linuxnet.com ). It allows to build pyscard on Mac OS X without any dependency on the muscle source code. Indeed, default Mac OS X does not containt reader.h as part of the PCSC.framework. Copyright (C) 1999-2005 David Corcoran Copyright (C) 1999-2009 Ludovic Rousseau The licence of reader.h pcsc-lite is 3-clauses BSD and can be relicenced in LGPL v2+ for pyscard. 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 ==============================================================================*/ #define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) #define SCARD_CLASS_VENDOR_INFO 1 #define SCARD_CLASS_COMMUNICATIONS 2 #define SCARD_CLASS_PROTOCOL 3 #define SCARD_CLASS_POWER_MGMT 4 #define SCARD_CLASS_SECURITY 5 #define SCARD_CLASS_MECHANICAL 6 #define SCARD_CLASS_VENDOR_DEFINED 7 #define SCARD_CLASS_IFD_PROTOCOL 8 #define SCARD_CLASS_ICC_STATE 9 #define SCARD_CLASS_SYSTEM 0x7fff #define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100) #define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101) #define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102) #define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103) #define SCARD_ATTR_CHANNEL_ID SCARD_ATTR_VALUE(SCARD_CLASS_COMMUNICATIONS, 0x0110) #define SCARD_ATTR_ASYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0120) #define SCARD_ATTR_DEFAULT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0121) #define SCARD_ATTR_MAX_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0122) #define SCARD_ATTR_DEFAULT_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0123) #define SCARD_ATTR_MAX_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0124) #define SCARD_ATTR_MAX_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0125) #define SCARD_ATTR_SYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0126) #define SCARD_ATTR_POWER_MGMT_SUPPORT SCARD_ATTR_VALUE(SCARD_CLASS_POWER_MGMT, 0x0131) #define SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0140) #define SCARD_ATTR_USER_AUTH_INPUT_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0142) #define SCARD_ATTR_CHARACTERISTICS SCARD_ATTR_VALUE(SCARD_CLASS_MECHANICAL, 0x0150) #define SCARD_ATTR_CURRENT_PROTOCOL_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0201) #define SCARD_ATTR_CURRENT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0202) #define SCARD_ATTR_CURRENT_F SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0203) #define SCARD_ATTR_CURRENT_D SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0204) #define SCARD_ATTR_CURRENT_N SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0205) #define SCARD_ATTR_CURRENT_W SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0206) #define SCARD_ATTR_CURRENT_IFSC SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0207) #define SCARD_ATTR_CURRENT_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0208) #define SCARD_ATTR_CURRENT_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0209) #define SCARD_ATTR_CURRENT_CWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020a) #define SCARD_ATTR_CURRENT_EBC_ENCODING SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020b) #define SCARD_ATTR_EXTENDED_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020c) #define SCARD_ATTR_ICC_PRESENCE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0300) #define SCARD_ATTR_ICC_INTERFACE_STATUS SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0301) #define SCARD_ATTR_CURRENT_IO_STATE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0302) #define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303) #define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304) #define SCARD_ATTR_ESC_RESET SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA000) #define SCARD_ATTR_ESC_CANCEL SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA003) #define SCARD_ATTR_ESC_AUTHREQUEST SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA005) #define SCARD_ATTR_MAXINPUT SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA007) #define SCARD_ATTR_DEVICE_UNIT SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0001) #define SCARD_ATTR_DEVICE_IN_USE SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0002) #define SCARD_ATTR_DEVICE_FRIENDLY_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0003) #define SCARD_ATTR_DEVICE_SYSTEM_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0004) #define SCARD_ATTR_DEVICE_FRIENDLY_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0005) #define SCARD_ATTR_DEVICE_SYSTEM_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0006) #define SCARD_ATTR_SUPRESS_T1_IFS_REQUEST SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0007) #ifdef UNICODE #define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_W #define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_W #else #define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_A #define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_A #endif pyscard-1.6.14/smartcard/scard/pcsctypes.h0000644000175000017500000000266111747776700022275 0ustar rousseaurousseau00000000000000/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 ================================================================================ ==============================================================================*/ #ifndef __PCSCTYPES_H__ #define __PCSCTYPES_H__ #ifdef PCSCLITE #ifdef __APPLE__ typedef uint32_t SCARDDWORDARG; typedef int32_t SCARDRETCODE; #else //!__APPLE__ typedef unsigned long SCARDDWORDARG; typedef long SCARDRETCODE; #endif #else // !PCSCLITE typedef unsigned long SCARDDWORDARG; typedef long SCARDRETCODE; #endif #endif //__PCSCTYPES_H__ pyscard-1.6.14/smartcard/scard/winscarddll.h0000644000175000017500000002732411747776700022571 0ustar rousseaurousseau00000000000000/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 ==============================================================================*/ #ifndef __WINSCARDDLL_H__ #define __WINSCARDDLL_H__ #ifdef WIN32 #include #endif #ifdef __APPLE__ #include #include #define LPCTSTR char* #else // !__APPLE__ #include #endif #ifdef PCSCLITE #define WINSCARDAPI #define WINAPI #define IN #define OUT #define LPSCARD_READERSTATEA SCARD_READERSTATE * #define SCARD_AUTOALLOCATE (DWORD)(-1) #ifndef FALSE #define FALSE (0==1) #endif // FALSE #ifndef TRUE #define TRUE (1==1) #endif #endif // PCSCLITE // // these functions are only available on win32 PCSC // #ifdef WIN32 typedef WINSCARDAPI HANDLE (WINAPI *SCARDACCESSSTARTEDEVENT)(void); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDADDREADERTOGROUPA)( IN SCARDCONTEXT hContext, IN LPCTSTR szReaderName, IN LPCTSTR szGroupName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDFORGETCARDTYPEA)( IN SCARDCONTEXT hContext, IN LPCSTR szCardName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDFORGETREADERA)( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDFORGETREADERGROUPA)( IN SCARDCONTEXT hContext, IN LPCSTR szGroupName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDGETCARDTYPEPROVIDERNAMEA)( IN SCARDCONTEXT hContext, IN LPCSTR szCardName, IN SCARDDWORDARG dwProviderId, OUT LPTSTR szProvider, IN OUT SCARDDWORDARG* pcchProvider); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDGETPROVIDERIDA)( IN SCARDCONTEXT hContext, IN LPCSTR szCard, OUT LPGUID pguidProviderId); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDINTRODUCECARDTYPEA)( IN SCARDCONTEXT hContext, IN LPCSTR szCardName, IN LPCGUID pguidPrimaryProvider, IN LPCGUID rgguidInterfaces, IN SCARDDWORDARG dwInterfaceCount, IN LPCBYTE pbAtr, IN LPCBYTE pbAtrMask, IN SCARDDWORDARG cbAtrLen); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDINTRODUCEREADERA)( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName, IN LPCSTR szDeviceName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDINTRODUCEREADERGROUPA)( IN SCARDCONTEXT hContext, IN LPCSTR szGroupName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDLISTCARDSA)( IN SCARDCONTEXT hContext, IN LPCBYTE pbAtr, IN LPCGUID rgquidInterfaces, IN SCARDDWORDARG cguidInterfaceCount, OUT LPTSTR mszCards, IN OUT SCARDDWORDARG* pcchCards); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDLISTINTERFACESA)( IN SCARDCONTEXT hContext, IN LPCSTR szCard, OUT LPGUID pguidInterfaces, IN OUT SCARDDWORDARG* pcguidInterfaces); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDLOCATECARDSA)( IN SCARDCONTEXT hContext, IN LPCSTR mszCards, IN OUT LPSCARD_READERSTATEA rgReaderStates, IN SCARDDWORDARG cReaders); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDLOCATECARDSBYATRA)( IN SCARDCONTEXT hContext, IN LPSCARD_ATRMASK rgAtrMasks, IN SCARDDWORDARG cAtrs, IN OUT LPSCARD_READERSTATEA rgReaderStates, IN SCARDDWORDARG cReaders); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDSETCARDTYPEPROVIDERNAMEA)( IN SCARDCONTEXT hContext, IN LPCSTR szCardName, IN SCARDDWORDARG dwProviderId, IN LPCSTR szProvider); typedef WINSCARDAPI void (WINAPI *SCARDRELEASESTARTEDEVENT)(void); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDREMOVEREADERFROMGROUPA)( IN SCARDCONTEXT hContext, IN LPCTSTR szReaderName, IN LPCTSTR szGroupName); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDSTATE)( IN SCARDHANDLE hCard, OUT SCARDDWORDARG* pdwState, OUT SCARDDWORDARG* pdwProtocol, OUT LPBYTE pbAtr, IN OUT SCARDDWORDARG* pcbAtrLen); extern SCARDACCESSSTARTEDEVENT mySCardAccessStartedEvent; extern SCARDADDREADERTOGROUPA mySCardAddReaderToGroupA; extern SCARDFORGETCARDTYPEA mySCardForgetCardTypeA; extern SCARDFORGETREADERA mySCardForgetReaderA; extern SCARDFORGETREADERGROUPA mySCardForgetReaderGroupA; extern SCARDGETCARDTYPEPROVIDERNAMEA mySCardGetCardTypeProviderNameA; extern SCARDGETPROVIDERIDA mySCardGetProviderIdA; extern SCARDINTRODUCECARDTYPEA mySCardIntroduceCardTypeA; extern SCARDINTRODUCEREADERA mySCardIntroduceReaderA; extern SCARDINTRODUCEREADERGROUPA mySCardIntroduceReaderGroupA; extern SCARDLISTCARDSA mySCardListCardsA; extern SCARDLISTINTERFACESA mySCardListInterfacesA; extern SCARDLOCATECARDSA mySCardLocateCardsA; extern SCARDLOCATECARDSBYATRA mySCardLocateCardsByATRA; extern SCARDRELEASESTARTEDEVENT mySCardReleaseStartedEvent; extern SCARDREMOVEREADERFROMGROUPA mySCardRemoveReaderFromGroupA; extern SCARDSETCARDTYPEPROVIDERNAMEA mySCardSetCardTypeProviderNameA; extern SCARDSTATE mySCardState; #endif // WIN32 // // These functions are not available on Max OS X Tiger // #ifndef __TIGER__ typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDISVALIDCONTEXT)( IN SCARDCONTEXT hContext); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDGETATTRIB)( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwAttrId, OUT LPBYTE pbAttr, IN OUT SCARDDWORDARG* pcbAttrLen); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDSETATTRIB)( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwAttrId, IN LPCBYTE pbAttr, IN SCARDDWORDARG cbAttrLen); extern SCARDISVALIDCONTEXT mySCardIsValidContext; extern SCARDGETATTRIB mySCardGetAttrib; extern SCARDSETATTRIB mySCardSetAttrib; #endif // !__TIGER__ // // SCardControl does not have the same prototype on Mac OS X Tiger // #ifdef __TIGER__ typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDCONTROL)( IN SCARDHANDLE hCard, IN const unsigned char* lpInBuffer, IN SCARDDWORDARG nInBufferSize, OUT unsigned char* lpOutBuffer, IN OUT SCARDDWORDARG* lpBytesReturned); #else // !__TIGER__ typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDCONTROL)( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwControlCode, IN LPCVOID lpInBuffer, IN SCARDDWORDARG nInBufferSize, OUT LPVOID lpOutBuffer, IN SCARDDWORDARG nOutBufferSize, OUT SCARDDWORDARG* lpBytesReturned); #endif // __TIGER__ typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDBEGINTRANSACTION)( IN SCARDHANDLE hCard); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDCANCEL)( IN SCARDCONTEXT hContext); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDCANCELTRANSACTION)( IN SCARDHANDLE hCard); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDCONNECTA)( IN SCARDCONTEXT hContext, IN LPCTSTR szReader, IN SCARDDWORDARG dwShareMode, IN SCARDDWORDARG dwPreferredProtocols, OUT LPSCARDHANDLE phCard, OUT SCARDDWORDARG* pdwActiveProtocol); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDDISCONNECT)( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwDisposition); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDENDTRANSACTION)( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwDisposition); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDESTABLISHCONTEXT)( IN SCARDDWORDARG dwScope, IN LPCVOID pvReserved1, IN LPCVOID pvReserved2, OUT LPSCARDCONTEXT phContext); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDFREEMEMORY)( IN SCARDCONTEXT hContext, IN LPCVOID pvMem); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDGETSTATUSCHANGEA)( IN SCARDCONTEXT hContext, IN SCARDDWORDARG dwTimeout, IN OUT LPSCARD_READERSTATEA rgReaderStates, IN SCARDDWORDARG cReaders); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDLISTREADERSA)( IN SCARDCONTEXT hContext, IN LPCTSTR mszGroups, OUT LPTSTR mszReaders, IN OUT SCARDDWORDARG* pcchReaders); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDLISTREADERGROUPSA)( IN SCARDCONTEXT hContext, OUT LPTSTR mszGroups, IN OUT SCARDDWORDARG* pcchGroups); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDRECONNECT)( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwShareMode, IN SCARDDWORDARG dwPreferredProtocols, IN SCARDDWORDARG dwInitialization, OUT SCARDDWORDARG* pdwActiveProtocol); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDRELEASECONTEXT)( IN SCARDCONTEXT hContext); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDSTATUSA)( IN SCARDHANDLE hCard, OUT LPTSTR szReaderName, IN OUT SCARDDWORDARG* pcchReaderLen, OUT SCARDDWORDARG* pdwState, OUT SCARDDWORDARG* pdwProtocol, OUT LPBYTE pbAtr, IN OUT SCARDDWORDARG* pcbAtrLen); typedef WINSCARDAPI SCARDRETCODE (WINAPI *SCARDTRANSMIT)( IN SCARDHANDLE hCard, IN LPCSCARD_IO_REQUEST pioSendPci, IN LPCBYTE pbSendBuffer, IN SCARDDWORDARG cbSendLength, IN OUT LPSCARD_IO_REQUEST pioRecvPci, OUT LPBYTE pbRecvBuffer, IN OUT SCARDDWORDARG* pcbRecvLength); #ifdef PCSCLITE typedef WINSCARDAPI char* (WINAPI *PCSCSTRINGIFYERROR)( IN SCARDRETCODE pcscError); extern PCSCSTRINGIFYERROR myPcscStringifyError; #endif // PCSCLITE extern SCARDBEGINTRANSACTION mySCardBeginTransaction; extern SCARDCANCEL mySCardCancel; extern SCARDCONNECTA mySCardConnectA; extern SCARDCONTROL mySCardControl; extern SCARDDISCONNECT mySCardDisconnect; extern SCARDENDTRANSACTION mySCardEndTransaction; extern SCARDESTABLISHCONTEXT mySCardEstablishContext; extern SCARDFREEMEMORY mySCardFreeMemory; extern SCARDGETSTATUSCHANGEA mySCardGetStatusChangeA; extern SCARDLISTREADERSA mySCardListReadersA; extern SCARDLISTREADERGROUPSA mySCardListReaderGroupsA; extern SCARDRECONNECT mySCardReconnect; extern SCARDRELEASECONTEXT mySCardReleaseContext; extern SCARDSTATUSA mySCardStatusA; extern SCARDTRANSMIT mySCardTransmit; extern void * myg_prgSCardT0Pci; extern void * myg_prgSCardT1Pci; extern void * myg_prgSCardRawPci; long winscard_init(void); #endif // __WINSCARDDLL_H__ pyscard-1.6.14/smartcard/scard/PcscTypemaps.i0000644000175000017500000003461511747776700022700 0ustar rousseaurousseau00000000000000/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 ==============================================================================*/ // Tell SWIG to wrap all the wrappers with Python's thread macros %exception { Py_BEGIN_ALLOW_THREADS; $function Py_END_ALLOW_THREADS; } /*============================================================================== // // support for list of BYTEs, aka BYTELIST // ==============================================================================*/ #ifdef SWIG(python) #endif %typemap(in,numinputs=0) BYTELIST *OUTPUT(BYTELIST temp) { $1 = &temp; $1->ab = NULL; $1->bAllocated=FALSE; } // builds a byte list from a Python list %typemap(in) BYTELIST* INPUT(BYTELIST*) { $1 = SCardHelper_PyByteListToBYTELIST( $input ); if (NULL == $1) goto fail; } // release bytelist arg %typemap(freearg) BYTELIST* { if(NULL!=$1) { if(NULL!=$1->ab) { mem_Free( $1->ab ); } if($1->bAllocated==TRUE) { mem_Free( $1 ); } } } // builds a Python list from a byte list %typemap(argout) BYTELIST *OUTPUT { SCardHelper_AppendByteListToPyObject( $1, &$result ); } // other names for BYTELIST as INPUT parameter %apply BYTELIST* INPUT { BYTELIST* ATR }; %apply BYTELIST* INPUT { BYTELIST* ATTRIBUTESIN }; %apply BYTELIST* INPUT { BYTELIST* MASK }; %apply BYTELIST* INPUT { BYTELIST* APDUCOMMAND }; %apply BYTELIST* INPUT { BYTELIST* INBUFFER }; // other names for BYTELIST as OUTPUT parameter %apply BYTELIST* OUTPUT { BYTELIST* ATROUT }; %apply BYTELIST* OUTPUT { BYTELIST* ATTRIBUTES }; %apply BYTELIST* OUTPUT { BYTELIST* APDURESPONSE }; %apply BYTELIST* OUTPUT { BYTELIST* OUTBUFFER }; /*============================================================================== // // support for ERRORSTRING // ==============================================================================*/ // on win32, the ERRORSTRING is allocated and // must be free'd with Local Free // release ERRORSTRING OUTPUT argument. // on pcsc-lite, the error string is not allocated, // i.e. nothing to do. %typemap(ret) ERRORSTRING* { #ifdef WIN32 if(NULL!=$1) { HLOCAL hlocal = LocalFree( $1 ); if(NULL!=hlocal) { fprintf( stderr, "Failed to free error message string!\n" ); } } #endif // WIN32 } // builds a Python string from a STRING %typemap(out) ERRORSTRING* { SCardHelper_OutErrorStringAsPyObject( $1, &$result ); } /*============================================================================== // // support for GUIDLIST // ==============================================================================*/ %typemap(in,numinputs=0) GUIDLIST *OUTPUT(GUIDLIST temp) { $1 = &temp; $1->bAllocated=FALSE; } // release GUIDLIST INPUT argument // for input arg, GUIDLIST was allocated from the heap // i.e. $1 has to be freed %typemap(freearg) GUIDLIST* INPUT { if(NULL!=$1) { if(NULL!=$1->aguid) { if($1->hcontext) { unsigned long lRes=(mySCardFreeMemory)( $1->hcontext, $1->aguid ); if (lRes!=SCARD_S_SUCCESS) { fprintf( stderr, "kaboom!\n" ); } } else { mem_Free( $1->aguid ); } } mem_Free( $1 ); } } // release GUIDLIST OUTPUT argument // for output arg, GUIDLIST was not allocated // from the heap, but from the stack // i.e. $1 must not be freed %typemap(freearg) GUIDLIST* OUTPUT { if(NULL!=$1) { if(NULL!=$1->aguid) { if($1->hcontext) { unsigned long lRes=(mySCardFreeMemory)( $1->hcontext, $1->aguid ); if (lRes!=SCARD_S_SUCCESS) { fprintf( stderr, "kaboom!\n" ); } } else { mem_Free( $1->aguid ); } } } } // builds a win32 string list from a Python list %typemap(in) GUIDLIST* INPUT(GUIDLIST*) { $1 = SCardHelper_PyGuidListToGUIDLIST( $input ); if (NULL == $1) goto fail; } // builds a Python list from a GUID list %typemap(argout) GUIDLIST *OUTPUT { SCardHelper_AppendGuidListToPyObject( $1, &$result ); } // other names for GUIDLIST as INPUT parameter %apply GUIDLIST* INPUT { GUIDLIST* PRIMARYPROVIDER }; %apply GUIDLIST* INPUT { GUIDLIST* PROVIDERLIST }; // other names for GUIDLIST as OUTPUT parameter %apply GUIDLIST* OUTPUT { GUIDLIST* GUIDINTERFACES }; /*============================================================================== // // support for READERSTATELIST* // ==============================================================================*/ %typemap(in,numinputs=0) READERSTATELIST *OUTPUT(READERSTATELIST temp) { $1 = &temp; } // release READERSTATELIST INPUT/OUTPUT argument // for input arg, READERSTATELIST was allocated from the heap // i.e. $1 has to be freed %typemap(freearg) READERSTATELIST* BOTH { if(NULL!=$1) { int i; for(i=0; i<$1->cRStates; i++ ) { if($1->aszReaderNames[i]) { mem_Free( $1->aszReaderNames[i] ); } } if(NULL!=$1->ars) { mem_Free( $1->ars ); } if(NULL!=$1->aszReaderNames) { mem_Free( $1->aszReaderNames ); } mem_Free( $1 ); } } // release READERSTATELIST OUTPUT argument // for output arg, READERSTATELIST was not allocated // from the heap, but from the stack // i.e. $1 must not be freed %typemap(freearg) READERSTATELIST* OUTPUT { if(NULL!=$1) { int i; for(i=0; i<$1->cRStates; i++ ) { if($1->aszReaderNames[i]) { mem_Free( $1->aszReaderNames[i] ); } } if(NULL!=$1->ars) { mem_Free( $1->ars ); } if(NULL!=$1->aszReaderNames) { mem_Free( $1->aszReaderNames ); } } } // builds a READERSTATE list string list from a Python list %typemap(in) READERSTATELIST *prsl(READERSTATELIST*) { $1 = SCardHelper_PyReaderStateListToREADERSTATELIST( $input ); if (NULL == $1) goto fail; } // builds a Python list from a win32 string list %typemap(argout) READERSTATELIST *prsl { SCardHelper_AppendReaderStateListToPyObject( $1, &$result ); } // reader state list as input and output //%typemap(in) READERSTATELIST *BOTH = READERSTATELIST *prsl; //%typemap(argout) READERSTATELIST *BOTH = READERSTATELIST *prsl; // other names for READERSTATELIST as inpu/output parameter %apply READERSTATELIST *BOTH {READERSTATELIST* prsl}; /*============================================================================== // // support for SCARDCONTEXT // ==============================================================================*/ %typemap(in,numinputs=0) SCARDCONTEXT *OUTPUT(SCARDCONTEXT temp) { $1 = &temp; } %typemap(in) SCARDCONTEXT hcontext(SCARDCONTEXT) { $1 = SCardHelper_PyScardContextToSCARDCONTEXT( $input ); if (0 == $1) goto fail; } %typemap(argout) SCARDCONTEXT *OUTPUT { SCardHelper_AppendSCardContextToPyObject( *$1, &$result ); } // different names for SCARDCONTEXT OUTPUT parameters %apply SCARDCONTEXT* OUTPUT { SCARDCONTEXT* phcontext }; /*============================================================================== // // support for SCARDDWORDARG // ==============================================================================*/ %typemap(in,numinputs=0) SCARDDWORDARG *OUTPUT(SCARDDWORDARG temp) { $1 = &temp; } %typemap(in) SCARDDWORDARG INPUT(SCARDDWORDARG) { $1 = SCardHelper_PySCardDwordArgToSCARDDWORDARG( $input ); if (-1 == $1) goto fail; } %typemap(argout) SCARDDWORDARG* OUTPUT { SCardHelper_AppendSCardDwordArgToPyObject( *$1, &$result ); } // different names for SCARDWORDARG INPUT parameters %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwProviderId }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwShareMode }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwPreferredProtocols }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwDisposition }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwScope }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwAttrId }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwTimeout }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwInitialization }; %apply SCARDDWORDARG INPUT { SCARDDWORDARG dwControlCode }; // different names for SCARDWORDARG OUTPUT parameters %apply SCARDDWORDARG* OUTPUT { SCARDDWORDARG* pdwActiveProtocol }; %apply SCARDDWORDARG* OUTPUT { SCARDDWORDARG* pdwProtocol }; %apply SCARDDWORDARG* OUTPUT { SCARDDWORDARG* pdwState }; /*============================================================================== // // support for SCARDHANDLE // ==============================================================================*/ %typemap(in,numinputs=0) SCARDHANDLE *OUTPUT(SCARDHANDLE temp) { $1 = &temp; } %typemap(in) SCARDHANDLE hcard(SCARDHANDLE) { $1 = SCardHelper_PyScardHandleToSCARDHANDLE( $input ); if (0 == $1) goto fail; } %typemap(argout) SCARDHANDLE* OUTPUT { SCardHelper_AppendSCardHandleToPyObject( *$1, &$result ); } // different names for SCARDHANDLE OUTPUT parameters %apply SCARDHANDLE* OUTPUT { SCARDHANDLE* phcard }; /*============================================================================== // // support for SCARDRETCODE // ==============================================================================*/ %typemap(out) SCARDRETCODE { $result = PyLong_FromLong((long)$1); } /*============================================================================== // // support for STRING // ==============================================================================*/ // release STRING INPUT argument. // string is allocated in SCardHelper_PyStringToString // string->sz is always allocated %typemap(freearg) STRING* INPUT { if(NULL!=$1) { if(NULL!=$1->sz) { if($1->hcontext) { unsigned long lRes=(mySCardFreeMemory)( $1->hcontext, $1->sz ); if (lRes!=SCARD_S_SUCCESS) { fprintf( stderr, "kaboom!\n" ); } } else { mem_Free( $1->sz ); } $1->sz=NULL; } mem_Free( $1 ); } } // release STRING OUTPUT argument. // string is not allocated // string->sz is always allocated %typemap(freearg) STRING* OUTPUT { if(NULL!=$1) { if(NULL!=$1->sz) { if($1->hcontext) { unsigned long lRes=(mySCardFreeMemory)( $1->hcontext, $1->sz ); if (lRes!=SCARD_S_SUCCESS) { fprintf( stderr, "kaboom!\n" ); } } else { mem_Free( $1->sz ); } $1->sz=NULL; } } } // force the argument to be ignored %typemap(in,numinputs=0) STRING *OUTPUT(STRING temp) { $1 = &temp; $1->bAllocated=FALSE; } // builds a string from a Python string %typemap(in) STRING *INPUT( STRING ) { $1 = SCardHelper_PyStringToString( $input ); if (NULL == $1) goto fail; } // builds a Python string from a STRING %typemap(argout) STRING *OUTPUT { SCardHelper_AppendStringToPyObject( $1, &$result ); } // other names for STRING as output parameter %apply STRING* OUTPUT { PROVIDERNAME_t* pszProviderName }; %apply STRING* OUTPUT { STRING* pszReaderNameOut }; /*============================================================================== // // support for STRINGLIST // SCardxxx API stores multi-strings as a concatenation // of strings terminated by a null, e.g. // item0\0item2\0lastitem\0\0 // ==============================================================================*/ // for OUTPUT STRINGLIST, free the allocated buffer // for winscard, the buffer is automatically allocated and // has to be freed by SCardFreeMemory. // for pcsclite, the buffer is allocated with mem_Malloc and // has to be freed by mem_Free. %typemap(freearg) STRINGLIST* { if(NULL!=$1) { if(NULL!=$1->ac) { if($1->hcontext) { unsigned long lRes=(mySCardFreeMemory)( $1->hcontext, $1->ac ); if (lRes!=SCARD_S_SUCCESS) { fprintf( stderr, "Failed to SCardFreeMemory!\n" ); } } else { if( NULL!=$1->ac ) { mem_Free( $1->ac ); } } } if($1->bAllocated==TRUE) { mem_Free( $1 ); } } } %typemap(in,numinputs=0) STRINGLIST *OUTPUT(STRINGLIST temp) { $1 = &temp; $1->bAllocated=FALSE; } // builds a win32 string list from a Python list %typemap(in) STRINGLIST* INPUT(STRINGLIST*) { $1 = SCardHelper_PyStringListToStringList( $input ); if (NULL == $1) goto fail; } // builds a Python list from a win32 string list %typemap(argout) STRINGLIST *OUTPUT { SCardHelper_AppendStringListToPyObject( $1, &$result ); } // other names for STRINGLIST as input parameter %apply STRINGLIST* INPUT { STRINGLIST* CARDSTOLOCATE }; %apply STRINGLIST* INPUT { STRINGLIST* psl }; %apply STRINGLIST* INPUT { STRINGLIST* READERGROUPSIN }; // other names for STRINGLIST as output parameter %apply STRINGLIST* OUTPUT { STRINGLIST* MATCHINGCARDS }; %apply STRINGLIST* OUTPUT { STRINGLIST* READERSFOUND }; %apply STRINGLIST* OUTPUT { STRINGLIST* READERGROUPSOUT }; %apply STRINGLIST* OUTPUT { STRINGLIST* pszReaderName }; //#endif pyscard-1.6.14/smartcard/scard/scard.def0000644000175000017500000000017010633575651021647 0ustar rousseaurousseau00000000000000LIBRARY "_scard.pyd" DESCRIPTION 'Python PCSC scard module Dynamic Link Library' EXPORTS init_scard pyscard-1.6.14/smartcard/scard/winscarddll.c0000644000175000017500000007165011747776700022565 0ustar rousseaurousseau00000000000000/*============================================================================== Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 ==============================================================================*/ #include #ifdef __APPLE__ #include #endif #include "pcsctypes.h" #include "winscarddll.h" #ifdef PCSCLITE #include #include #endif // PCSCLITE #ifndef NULL #define NULL ((void*)0) #endif //NULL // // these functions are only available on win32 PCSC // #ifdef WIN32 WINSCARDAPI HANDLE WINAPI _defaultSCARDACCESSSTARTEDEVENT(void) { return NULL; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDADDREADERTOGROUPA( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName, IN LPCSTR szGroupName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDFORGETCARDTYPEA( IN SCARDCONTEXT hContext, IN LPCSTR szCardName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDFORGETREADERA( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDFORGETREADERGROUPA( IN SCARDCONTEXT hContext, IN LPCSTR szGroupName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDGETPROVIDERIDA( IN SCARDCONTEXT hContext, IN LPCSTR szCard, OUT LPGUID pguidProviderId) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDGETCARDTYPEPROVIDERNAMEA( IN SCARDCONTEXT hContext, IN LPCSTR szCardName, IN SCARDDWORDARG dwProviderId, OUT LPTSTR szProvider, IN OUT SCARDDWORDARG* pcchProvider) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDINTRODUCECARDTYPEA( IN SCARDCONTEXT hContext, IN LPCSTR szCardName, IN LPCGUID pguidPrimaryProvider, IN LPCGUID rgguidInterfaces, IN SCARDDWORDARG dwInterfaceCount, IN LPCBYTE pbAtr, IN LPCBYTE pbAtrMask, IN SCARDDWORDARG cbAtrLen) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDINTRODUCEREADERA( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName, IN LPCSTR szDeviceName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDINTRODUCEREADERGROUPA( IN SCARDCONTEXT hContext, IN LPCSTR szGroupName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDLISTCARDSA( IN SCARDCONTEXT hContext, IN LPCBYTE pbAtr, IN LPCGUID rgquidInterfaces, IN SCARDDWORDARG cguidInterfaceCount, OUT LPTSTR mszCards, IN OUT SCARDDWORDARG* pcchCards) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDLISTINTERFACESA( IN SCARDCONTEXT hContext, IN LPCSTR szCard, OUT LPGUID pguidInterfaces, IN OUT SCARDDWORDARG* pcguidInterfaces) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDLOCATECARDSA( IN SCARDCONTEXT hContext, IN LPCSTR mszCards, IN OUT LPSCARD_READERSTATEA rgReaderStates, IN SCARDDWORDARG cReaders) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDLOCATECARDSBYATRA( IN SCARDCONTEXT hContext, IN LPSCARD_ATRMASK rgAtrMasks, IN SCARDDWORDARG cAtrs, IN OUT LPSCARD_READERSTATEA rgReaderStates, IN SCARDDWORDARG cReaders) { return SCARD_E_NO_SERVICE; } WINSCARDAPI void WINAPI _defaultSCARDRELEASESTARTEDEVENT(void) { return; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDREMOVEREADERFROMGROUPA( IN SCARDCONTEXT hContext, IN LPCSTR szReaderName, IN LPCSTR szGroupName) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDSETCARDTYPEPROVIDERNAMEA( IN SCARDCONTEXT hContext, IN LPCSTR szCardName, IN SCARDDWORDARG dwProviderId, IN LPCSTR szProvider) { return SCARD_E_NO_SERVICE; } WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDSTATE( IN SCARDHANDLE hCard, OUT SCARDDWORDARG* pdwState, OUT SCARDDWORDARG* pdwProtocol, OUT LPBYTE pbAtr, IN OUT SCARDDWORDARG* pcbAtrLen) { return SCARD_E_NO_SERVICE; } SCARDACCESSSTARTEDEVENT mySCardAccessStartedEvent = _defaultSCARDACCESSSTARTEDEVENT; SCARDADDREADERTOGROUPA mySCardAddReaderToGroupA = _defaultSCARDADDREADERTOGROUPA; SCARDFORGETCARDTYPEA mySCardForgetCardTypeA = _defaultSCARDFORGETCARDTYPEA; SCARDFORGETREADERA mySCardForgetReaderA = _defaultSCARDFORGETREADERA; SCARDFORGETREADERGROUPA mySCardForgetReaderGroupA = _defaultSCARDFORGETREADERGROUPA; SCARDGETPROVIDERIDA mySCardGetProviderIdA = _defaultSCARDGETPROVIDERIDA; SCARDGETCARDTYPEPROVIDERNAMEA mySCardGetCardTypeProviderNameA = _defaultSCARDGETCARDTYPEPROVIDERNAMEA; SCARDINTRODUCECARDTYPEA mySCardIntroduceCardTypeA = _defaultSCARDINTRODUCECARDTYPEA; SCARDINTRODUCEREADERA mySCardIntroduceReaderA = _defaultSCARDINTRODUCEREADERA; SCARDINTRODUCEREADERGROUPA mySCardIntroduceReaderGroupA = _defaultSCARDINTRODUCEREADERGROUPA; SCARDLISTCARDSA mySCardListCardsA = _defaultSCARDLISTCARDSA; SCARDLISTINTERFACESA mySCardListInterfacesA = _defaultSCARDLISTINTERFACESA; SCARDLOCATECARDSA mySCardLocateCardsA = _defaultSCARDLOCATECARDSA; SCARDLOCATECARDSBYATRA mySCardLocateCardsByATRA = _defaultSCARDLOCATECARDSBYATRA; SCARDRELEASESTARTEDEVENT mySCardReleaseStartedEvent = _defaultSCARDRELEASESTARTEDEVENT; SCARDREMOVEREADERFROMGROUPA mySCardRemoveReaderFromGroupA = _defaultSCARDREMOVEREADERFROMGROUPA; SCARDSETCARDTYPEPROVIDERNAMEA mySCardSetCardTypeProviderNameA = _defaultSCARDSETCARDTYPEPROVIDERNAMEA; SCARDSTATE mySCardState = _defaultSCARDSTATE; #endif // WIN32 // // These functions are not available on Max OS X Tiger // #ifndef __TIGER__ static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDISVALIDCONTEXT( IN SCARDCONTEXT hContext) { (void)hContext; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDGETATTRIB( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwAttrId, OUT LPBYTE pbAttr, IN OUT SCARDDWORDARG* pcbAttrLen) { (void)hCard; (void)dwAttrId; (void)pbAttr; (void)pcbAttrLen; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDSETATTRIB( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwAttrId, IN LPCBYTE pbAttr, IN SCARDDWORDARG cbAttrLen) { (void)hCard; (void)dwAttrId; (void)pbAttr; (void)cbAttrLen; return SCARD_E_NO_SERVICE; } SCARDISVALIDCONTEXT mySCardIsValidContext = _defaultSCARDISVALIDCONTEXT; SCARDGETATTRIB mySCardGetAttrib = _defaultSCARDGETATTRIB; SCARDSETATTRIB mySCardSetAttrib = _defaultSCARDSETATTRIB; #endif // !__TIGER__ // // SCardControl does not have the same prototype on Mac OS X Tiger // #ifdef __TIGER__ static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDCONTROL( IN SCARDHANDLE hCard, IN const unsigned char* lpInBuffer, IN SCARDDWORDARG nInBufferSize, OUT unsigned char* lpOutBuffer, IN OUT SCARDDWORDARG* lpBytesReturned) { return SCARD_E_NO_SERVICE; } #else // !__TIGER__ static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDCONTROL( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwControlCode, IN LPCVOID lpInBuffer, IN SCARDDWORDARG nInBufferSize, OUT LPVOID lpOutBuffer, IN SCARDDWORDARG nOutBufferSize, OUT SCARDDWORDARG* lpBytesReturned) { (void)hCard; (void)dwControlCode; (void)lpInBuffer; (void)nInBufferSize; (void)lpOutBuffer; (void)nOutBufferSize; (void)lpBytesReturned; return SCARD_E_NO_SERVICE; } #endif // __TIGER__ #ifdef PCSCLITE /////////////////////////////////////////////////////////////////////////////// // some pcsclite versions (e.g. on Max OS X Tiger) have no pcsc_stringify // this function was taken from pcsclite // static char* _defaultPCSCSTRINGIFYERROR( SCARDRETCODE pcscError ) { static char strError[75]; switch(pcscError ) { case SCARD_S_SUCCESS: strncpy( strError, "Command successful.", sizeof( strError ) ); break; case SCARD_E_CANCELLED: strncpy( strError, "Command cancelled.", sizeof( strError ) ); break; case SCARD_E_CANT_DISPOSE: strncpy( strError, "Cannot dispose handle.", sizeof( strError ) ); break; case SCARD_E_INSUFFICIENT_BUFFER: strncpy( strError, "Insufficient buffer.", sizeof( strError ) ); break; case SCARD_E_INVALID_ATR: strncpy( strError, "Invalid ATR.", sizeof( strError ) ); break; case SCARD_E_INVALID_HANDLE: strncpy( strError, "Invalid handle.", sizeof( strError ) ); break; case SCARD_E_INVALID_PARAMETER: strncpy( strError, "Invalid parameter given.", sizeof( strError ) ); break; case SCARD_E_INVALID_TARGET: strncpy( strError, "Invalid target given.", sizeof( strError ) ); break; case SCARD_E_INVALID_VALUE: strncpy( strError, "Invalid value given.", sizeof( strError ) ); break; case SCARD_E_NO_MEMORY: strncpy( strError, "Not enough memory.", sizeof( strError ) ); break; case SCARD_F_COMM_ERROR: strncpy( strError, "RPC transport error.", sizeof( strError ) ); break; case SCARD_F_INTERNAL_ERROR: strncpy( strError, "Internal error.", sizeof( strError ) ); break; case SCARD_F_UNKNOWN_ERROR: strncpy( strError, "Unknown error.", sizeof( strError ) ); break; case SCARD_F_WAITED_TOO_LONG: strncpy( strError, "Waited too long.", sizeof( strError ) ); break; case SCARD_E_UNKNOWN_READER: strncpy( strError, "Unknown reader specified.", sizeof( strError ) ); break; case SCARD_E_TIMEOUT: strncpy( strError, "Command timeout.", sizeof( strError ) ); break; case SCARD_E_SHARING_VIOLATION: strncpy( strError, "Sharing violation.", sizeof( strError ) ); break; case SCARD_E_NO_SMARTCARD: strncpy( strError, "No smart card inserted.", sizeof( strError ) ); break; case SCARD_E_UNKNOWN_CARD: strncpy( strError, "Unknown card.", sizeof( strError ) ); break; case SCARD_E_PROTO_MISMATCH: strncpy( strError, "Card protocol mismatch.", sizeof( strError ) ); break; case SCARD_E_NOT_READY: strncpy( strError, "Subsystem not ready.", sizeof( strError ) ); break; case SCARD_E_SYSTEM_CANCELLED: strncpy( strError, "System cancelled.", sizeof( strError ) ); break; case SCARD_E_NOT_TRANSACTED: strncpy( strError, "Transaction failed.", sizeof( strError ) ); break; case SCARD_E_READER_UNAVAILABLE: strncpy( strError, "Reader is unavailable.", sizeof( strError ) ); break; case SCARD_W_UNSUPPORTED_CARD: strncpy( strError, "Card is not supported.", sizeof( strError ) ); break; case SCARD_W_UNRESPONSIVE_CARD: strncpy( strError, "Card is unresponsive.", sizeof( strError ) ); break; case SCARD_W_UNPOWERED_CARD: strncpy( strError, "Card is unpowered.", sizeof( strError ) ); break; case SCARD_W_RESET_CARD: strncpy( strError, "Card was reset.", sizeof( strError ) ); break; case SCARD_W_REMOVED_CARD: strncpy( strError, "Card was removed.", sizeof( strError ) ); break; case SCARD_E_UNSUPPORTED_FEATURE: strncpy( strError, "Feature not supported.", sizeof( strError ) ); break; case SCARD_E_PCI_TOO_SMALL: strncpy( strError, "PCI struct too small.", sizeof( strError ) ); break; case SCARD_E_READER_UNSUPPORTED: strncpy( strError, "Reader is unsupported.", sizeof( strError ) ); break; case SCARD_E_DUPLICATE_READER: strncpy( strError, "Reader already exists.", sizeof( strError ) ); break; case SCARD_E_CARD_UNSUPPORTED: strncpy( strError, "Card is unsupported.", sizeof( strError ) ); break; case SCARD_E_NO_SERVICE: strncpy( strError, "Service not available.", sizeof( strError ) ); break; case SCARD_E_SERVICE_STOPPED: strncpy( strError, "Service was stopped.", sizeof( strError ) ); break; default: snprintf(strError, sizeof(strError)-1, "Unknown error: %ld, 0x%08lx", (long)pcscError, (long unsigned int)pcscError); }; // zero terminates string strError[sizeof(strError)-1] = '\0'; return strError; } #endif static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDBEGINTRANSACTION( IN SCARDHANDLE hCard) { (void)hCard; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDCANCEL( IN SCARDCONTEXT hContext) { (void)hContext; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDCONNECTA( IN SCARDCONTEXT hContext, IN LPCTSTR szReader, IN SCARDDWORDARG dwShareMode, IN SCARDDWORDARG dwPreferredProtocols, OUT LPSCARDHANDLE phCard, OUT SCARDDWORDARG* pdwActiveProtocol) { (void)hContext; (void)szReader; (void)dwShareMode; (void)dwPreferredProtocols; (void)phCard; (void)pdwActiveProtocol; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDDISCONNECT( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwDisposition) { (void)hCard; (void)dwDisposition; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDENDTRANSACTION( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwDisposition) { (void)hCard; (void)dwDisposition; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDESTABLISHCONTEXT( IN SCARDDWORDARG dwScope, IN LPCVOID pvReserved1, IN LPCVOID pvReserved2, OUT LPSCARDCONTEXT phContext) { (void)dwScope; (void)pvReserved1; (void)pvReserved2; (void)phContext; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDFREEMEMORY( IN SCARDCONTEXT hContext, IN LPCVOID pvMem) { (void)hContext; (void)pvMem; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDGETSTATUSCHANGEA( IN SCARDCONTEXT hContext, IN SCARDDWORDARG dwTimeout, IN OUT LPSCARD_READERSTATEA rgReaderStates, IN SCARDDWORDARG cReaders) { (void)hContext; (void)dwTimeout; (void)rgReaderStates; (void)cReaders; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDLISTREADERSA( IN SCARDCONTEXT hContext, IN LPCTSTR mszGroups, OUT LPTSTR mszReaders, IN OUT SCARDDWORDARG* pcchReaders) { (void)hContext; (void)mszGroups; (void)mszReaders; (void)pcchReaders; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDLISTREADERGROUPSA( IN SCARDCONTEXT hContext, OUT LPTSTR mszGroups, IN OUT SCARDDWORDARG* pcchGroups) { (void)hContext; (void)mszGroups; (void)pcchGroups; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDRECONNECT( IN SCARDHANDLE hCard, IN SCARDDWORDARG dwShareMode, IN SCARDDWORDARG dwPreferredProtocols, IN SCARDDWORDARG dwInitialization, OUT SCARDDWORDARG* pdwActiveProtocol) { (void)hCard; (void)dwShareMode; (void)dwPreferredProtocols; (void)dwInitialization; (void)pdwActiveProtocol; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDRELEASECONTEXT( IN SCARDCONTEXT hContext) { (void)hContext; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDSTATUSA( IN SCARDHANDLE hCard, OUT LPTSTR szReaderName, IN OUT SCARDDWORDARG* pcchReaderLen, OUT SCARDDWORDARG* pdwState, OUT SCARDDWORDARG* pdwProtocol, OUT LPBYTE pbAtr, IN OUT SCARDDWORDARG* pcbAtrLen) { (void)hCard; (void)szReaderName; (void)pcchReaderLen; (void)pdwState; (void)pdwProtocol; (void)pbAtr; (void)pcbAtrLen; return SCARD_E_NO_SERVICE; } static WINSCARDAPI SCARDRETCODE WINAPI _defaultSCARDTRANSMIT( IN SCARDHANDLE hCard, IN LPCSCARD_IO_REQUEST pioSendPci, IN LPCBYTE pbSendBuffer, IN SCARDDWORDARG cbSendLength, IN OUT LPSCARD_IO_REQUEST pioRecvPci, OUT LPBYTE pbRecvBuffer, IN OUT SCARDDWORDARG* pcbRecvLength) { (void)hCard; (void)pioSendPci; (void)pbSendBuffer; (void)cbSendLength; (void)pioRecvPci; (void)pbRecvBuffer; (void)pcbRecvLength; return SCARD_E_NO_SERVICE; } SCARDBEGINTRANSACTION mySCardBeginTransaction = _defaultSCARDBEGINTRANSACTION; SCARDCANCEL mySCardCancel = _defaultSCARDCANCEL; SCARDCONNECTA mySCardConnectA = _defaultSCARDCONNECTA; SCARDCONTROL mySCardControl = _defaultSCARDCONTROL; SCARDDISCONNECT mySCardDisconnect = _defaultSCARDDISCONNECT; SCARDENDTRANSACTION mySCardEndTransaction = _defaultSCARDENDTRANSACTION; SCARDESTABLISHCONTEXT mySCardEstablishContext = _defaultSCARDESTABLISHCONTEXT; SCARDFREEMEMORY mySCardFreeMemory = _defaultSCARDFREEMEMORY; SCARDGETSTATUSCHANGEA mySCardGetStatusChangeA = _defaultSCARDGETSTATUSCHANGEA; SCARDLISTREADERSA mySCardListReadersA = _defaultSCARDLISTREADERSA; SCARDLISTREADERGROUPSA mySCardListReaderGroupsA = _defaultSCARDLISTREADERGROUPSA; SCARDRECONNECT mySCardReconnect = _defaultSCARDRECONNECT; SCARDRELEASECONTEXT mySCardReleaseContext = _defaultSCARDRELEASECONTEXT; SCARDSTATUSA mySCardStatusA = _defaultSCARDSTATUSA; SCARDTRANSMIT mySCardTransmit = _defaultSCARDTRANSMIT; #ifdef PCSCLITE PCSCSTRINGIFYERROR myPcscStringifyError = _defaultPCSCSTRINGIFYERROR; #endif // PCSCLITE void * myg_prgSCardT0Pci=NULL; void * myg_prgSCardT1Pci=NULL; void * myg_prgSCardRawPci=NULL; long winscard_init(void) { static BOOL bFirstCall=TRUE; static long lRetCode=SCARD_E_NO_SERVICE; #ifdef WIN32 #define GETPROCADDRESS(type,name) my##name=(type)GetProcAddress(hinstDLL, #name ); HINSTANCE hinstDLL=NULL; if( bFirstCall ) { bFirstCall=FALSE; hinstDLL = LoadLibrary( "winscard.dll" ); if( NULL!=hinstDLL ) { lRetCode=SCARD_S_SUCCESS; GETPROCADDRESS( SCARDADDREADERTOGROUPA , SCardAddReaderToGroupA ); GETPROCADDRESS( SCARDACCESSSTARTEDEVENT , SCardAccessStartedEvent ); GETPROCADDRESS( SCARDBEGINTRANSACTION , SCardBeginTransaction ); GETPROCADDRESS( SCARDCANCEL , SCardCancel ); GETPROCADDRESS( SCARDCONNECTA , SCardConnectA ); GETPROCADDRESS( SCARDCONTROL , SCardControl ); GETPROCADDRESS( SCARDDISCONNECT , SCardDisconnect ); GETPROCADDRESS( SCARDENDTRANSACTION , SCardEndTransaction ); GETPROCADDRESS( SCARDESTABLISHCONTEXT , SCardEstablishContext ); GETPROCADDRESS( SCARDFORGETCARDTYPEA , SCardForgetCardTypeA ); GETPROCADDRESS( SCARDFORGETREADERA , SCardForgetReaderA ); GETPROCADDRESS( SCARDFORGETREADERGROUPA , SCardForgetReaderGroupA ); GETPROCADDRESS( SCARDFREEMEMORY , SCardFreeMemory ); GETPROCADDRESS( SCARDGETCARDTYPEPROVIDERNAMEA , SCardGetCardTypeProviderNameA ); GETPROCADDRESS( SCARDGETATTRIB , SCardGetAttrib ); GETPROCADDRESS( SCARDGETPROVIDERIDA , SCardGetProviderIdA ); GETPROCADDRESS( SCARDGETSTATUSCHANGEA , SCardGetStatusChangeA ); GETPROCADDRESS( SCARDINTRODUCECARDTYPEA , SCardIntroduceCardTypeA ); GETPROCADDRESS( SCARDINTRODUCEREADERA , SCardIntroduceReaderA ); GETPROCADDRESS( SCARDINTRODUCEREADERGROUPA , SCardIntroduceReaderGroupA ); GETPROCADDRESS( SCARDISVALIDCONTEXT , SCardIsValidContext ); GETPROCADDRESS( SCARDLISTCARDSA , SCardListCardsA ); GETPROCADDRESS( SCARDLISTINTERFACESA , SCardListInterfacesA ); GETPROCADDRESS( SCARDLISTREADERSA , SCardListReadersA ); GETPROCADDRESS( SCARDLISTREADERGROUPSA , SCardListReaderGroupsA ); GETPROCADDRESS( SCARDLOCATECARDSA , SCardLocateCardsA ); GETPROCADDRESS( SCARDLOCATECARDSBYATRA , SCardLocateCardsByATRA ); GETPROCADDRESS( SCARDRECONNECT , SCardReconnect ); GETPROCADDRESS( SCARDRELEASECONTEXT , SCardReleaseContext ); GETPROCADDRESS( SCARDRELEASESTARTEDEVENT , SCardReleaseStartedEvent ); GETPROCADDRESS( SCARDREMOVEREADERFROMGROUPA , SCardRemoveReaderFromGroupA ); GETPROCADDRESS( SCARDSETATTRIB , SCardSetAttrib ); GETPROCADDRESS( SCARDSETCARDTYPEPROVIDERNAMEA , SCardSetCardTypeProviderNameA ); GETPROCADDRESS( SCARDSTATE , SCardState ); GETPROCADDRESS( SCARDSTATUSA , SCardStatusA ); GETPROCADDRESS( SCARDTRANSMIT , SCardTransmit ); myg_prgSCardT0Pci = GetProcAddress( hinstDLL, "g_rgSCardT0Pci" ); myg_prgSCardT1Pci = GetProcAddress( hinstDLL, "g_rgSCardT1Pci" ); myg_prgSCardRawPci = GetProcAddress( hinstDLL, "g_rgSCardRawPci" ); } } #endif // WIN32 #ifdef PCSCLITE #define GETPROCADDRESS( type, name, realname ) my##name=(type)dlsym( handle, #realname ); \ dlsym_error = dlerror(); \ if (NULL!=dlsym_error) \ { \ printf( "Failed to load symbol for: %s, %s!\n", #realname, (char*)dlsym_error ); \ } // some functions are not available on older releases of pcsc-lite, such // as SCardIsValidContext; don't complain if they are not located #define SILENTGETPROCADDRESS( type, name, realname ) my##name=(type)dlsym( handle, #realname ); \ dlsym_error = dlerror(); void* handle=NULL; char* dlsym_error; const char *lib = NULL; #ifdef __APPLE__ lib = "/System/Library/Frameworks/PCSC.framework/PCSC"; #else lib = "libpcsclite.so.1"; #endif if( bFirstCall ) { dlerror(); handle = dlopen( lib, RTLD_NOW ); if( NULL!=handle ) { lRetCode=SCARD_S_SUCCESS; GETPROCADDRESS( SCARDBEGINTRANSACTION , SCardBeginTransaction , SCardBeginTransaction ); GETPROCADDRESS( SCARDCANCEL , SCardCancel , SCardCancel ); GETPROCADDRESS( SCARDCONNECTA , SCardConnectA , SCardConnect ); GETPROCADDRESS( SCARDDISCONNECT , SCardDisconnect , SCardDisconnect ); GETPROCADDRESS( SCARDENDTRANSACTION , SCardEndTransaction , SCardEndTransaction ); GETPROCADDRESS( SCARDESTABLISHCONTEXT , SCardEstablishContext , SCardEstablishContext ); GETPROCADDRESS( SCARDGETSTATUSCHANGEA , SCardGetStatusChangeA , SCardGetStatusChange ); GETPROCADDRESS( SCARDLISTREADERSA , SCardListReadersA , SCardListReaders ); GETPROCADDRESS( SCARDLISTREADERGROUPSA , SCardListReaderGroupsA , SCardListReaderGroups ); GETPROCADDRESS( SCARDRECONNECT , SCardReconnect , SCardReconnect ); GETPROCADDRESS( SCARDRELEASECONTEXT , SCardReleaseContext , SCardReleaseContext ); GETPROCADDRESS( SCARDSTATUSA , SCardStatusA , SCardStatus ); GETPROCADDRESS( SCARDTRANSMIT , SCardTransmit , SCardTransmit ); SILENTGETPROCADDRESS( PCSCSTRINGIFYERROR , PcscStringifyError , pcsc_stringify_error ); #ifndef __APPLE__ GETPROCADDRESS( SCARDCONTROL, SCardControl, SCardControl ); #else // !__APPLE__ #ifdef __TIGER__ GETPROCADDRESS( SCARDCONTROL, SCardControl, SCardControl ); #else // ! __TIGER__ GETPROCADDRESS( SCARDCONTROL, SCardControl, SCardControl132 ); #endif // __TIGER__ #endif // __APPLE__ #ifndef __TIGER__ SILENTGETPROCADDRESS( SCARDISVALIDCONTEXT , SCardIsValidContext , SCardIsValidContext ); GETPROCADDRESS( SCARDGETATTRIB , SCardGetAttrib , SCardGetAttrib ); GETPROCADDRESS( SCARDSETATTRIB , SCardSetAttrib , SCardSetAttrib ); #endif myg_prgSCardT0Pci = dlsym( handle, "g_rgSCardT0Pci" ); myg_prgSCardT1Pci = dlsym( handle, "g_rgSCardT1Pci" ); myg_prgSCardRawPci = dlsym( handle, "g_rgSCardRawPci" ); dlsym_error = dlerror(); if( NULL!= dlsym_error ) { printf( "Failed to load symbol address from %s: %s!", lib, (char*)dlsym_error ); } } else { dlsym_error = dlerror(); if( NULL!= dlsym_error ) { printf( "Failed to dlopen %s: %s!", lib, (dlsym_error==NULL) ? "" : (char*)dlsym_error ); } } bFirstCall=FALSE; } #endif // PCSCLITE return lRetCode; }; pyscard-1.6.14/smartcard/scard/scard.py0000644000175000017500000012430311630517266021542 0ustar rousseaurousseau00000000000000# This file was automatically generated by SWIG (http://www.swig.org). # Version 1.3.40 # # Do not make changes to this file unless you know what you are doing--modify # the SWIG interface file instead. # This file is compatible with both classic and new-style classes. """ The smartcard.scard module is a simple wrapper on top of the C language PCSC SCardXXX API. The smartcard.scard module is the lower layer of the pyscard framework that provides a higher level interface. You should avoid using the smartcard.scard package directly, and use the pyscard directly because: - smartcard.scard being a C wrapper, the code tends to look like C code written in python syntax - the smartcard package provides higher level abstractions (e.g. CardType, CardConnection), and makes programming easier since it is totally written in Python You can still use the smartcard.scard package if you want to write your own framework, or if you want to perform quick-and-dirty port of C language programs using SCardXXX calls, or if there are features of SCardXXX API that you want to use and that are not available in the pyscard library. Introduction The smartcard.scard module is a Python wrapper around PCSC smart card base services. On Windows, the wrapper is performed around the smart card base components winscard library. On linux, the wrapper is performed around PCSC-lite library. On Windows using the smart card base components, the smartcard.scard module provides mapping for the following API functions: - SCardAddReaderToGroup - SCardBeginTransaction - SCardCancel - SCardConnect - SCardControl - SCardDisconnect - SCardEndTransaction - SCardEstablishContext - SCardForgetCardType - SCardForgetReader - SCardForgetReaderGroup - SCardGetAttrib - SCardGetCardTypeProviderName - SCardGetErrorMessage - SCardGetStatusChange - SCardIntroduceCardType - SCardIntroduceReader - SCardIntroduceReaderGroup - SCardIsValidContext - SCardListInterfaces - SCardListCards - SCardListReaders - SCardListReaderGroups - SCardLocateCards - SCardReconnect - SCardReleaseContext - SCardRemoveReaderFromGroup - SCardSetAttrib - SCardStatus - SCardTransmit On linux or Mac OS X Leopard with PCSC lite, the smartcard.scard module provides mapping for the following API functions: - SCardBeginTransaction - SCardCancel - SCardConnect - SCardControl - SCardDisconnect - SCardEndTransaction - SCardEstablishContext - SCardGetAttrib - SCardGetStatusChange - SCardIsValidContext - SCardListReaders - SCardListReaderGroups - SCardReconnect - SCardReleaseContext - SCardSetAttrib - SCardStatus - SCardTransmit On Mac OS X Tiger with PCSC lite, the smartcard.scard module provides mapping for the following API functions: - SCardBeginTransaction - SCardCancel - SCardConnect - SCardControl - SCardDisconnect - SCardEndTransaction - SCardEstablishContext - SCardGetStatusChange - SCardListReaders - SCardListReaderGroups - SCardReconnect - SCardReleaseContext - SCardStatus - SCardTransmit The following PCSC smart card functions are not wrapped by the scard module on any platform: - GetOpenCardName - SCardFreeMemory - SCardGetProviderId - SCardSetCartTypeProviderName - SCardUIDlgSelectCard Comments, bug reports, improvements welcome. ------------------------------------------------------------------------------- Copyright 2001-2011 gemalto @Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com @Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from sys import version_info if version_info >= (2,6,0): def swig_import_helper(): from os.path import dirname import imp fp = None try: fp, pathname, description = imp.find_module('_scard', [dirname(__file__)]) except ImportError: import _scard return _scard if fp is not None: try: _mod = imp.load_module('_scard', fp, pathname, description) finally: fp.close() return _mod _scard = swig_import_helper() del swig_import_helper else: import _scard del version_info try: _swig_property = property except NameError: pass # Python < 2.2 doesn't have 'property'. def _swig_setattr_nondynamic(self,class_type,name,value,static=1): if (name == "thisown"): return self.this.own(value) if (name == "this"): if type(value).__name__ == 'SwigPyObject': self.__dict__[name] = value return method = class_type.__swig_setmethods__.get(name,None) if method: return method(self,value) if (not static) or hasattr(self,name): self.__dict__[name] = value else: raise AttributeError("You cannot add attributes to %s" % self) def _swig_setattr(self,class_type,name,value): return _swig_setattr_nondynamic(self,class_type,name,value,0) def _swig_getattr(self,class_type,name): if (name == "thisown"): return self.this.own() method = class_type.__swig_getmethods__.get(name,None) if method: return method(self) raise AttributeError(name) def _swig_repr(self): try: strthis = "proxy of " + self.this.__repr__() except: strthis = "" return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) try: _object = object _newclass = 1 except AttributeError: class _object : pass _newclass = 0 def SCardIsValidContext(*args): """ SCardIsValidContext( hcontext) -> SCARDRETCODE Parameters: hcontext: context handle return from SCardEstablishContext() hcontext: context handle return from SCardEstablishContext() This function determines whether a smart card context handle is still valid. After a smart card context handle has been set by SCardEstablishContext(), it may become not valid if the resource manager service has been shut down. from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult = SCardIsValidContext(hcontext) if hresult != SCARD_S_SUCCESS: raise error, 'Invalid context: ' + SCardGetErrorMessage(hresult) ... """ return _scard.SCardIsValidContext(*args) def SCardGetAttrib(*args): """ SCardGetAttrib( hcard, dwAttrId) -> SCARDRETCODE Parameters: hcard: card handle return from SCardConnect() dwAttrId: value of attribute to get hcard: card handle return from SCardConnect() dwAttrId: value of attribute to get This function get an attribute from the IFD Handler. For PCSC lite, the list of possible attributes is: * SCARD_ATTR_ASYNC_PROTOCOL_TYPES * SCARD_ATTR_ATR_STRING * SCARD_ATTR_CHANNEL_ID * SCARD_ATTR_CHARACTERISTICS * SCARD_ATTR_CURRENT_BWT * SCARD_ATTR_CURRENT_CLK * SCARD_ATTR_CURRENT_CWT * SCARD_ATTR_CURRENT_D * SCARD_ATTR_CURRENT_EBC_ENCODING * SCARD_ATTR_CURRENT_F * SCARD_ATTR_CURRENT_IFSC * SCARD_ATTR_CURRENT_IFSD * SCARD_ATTR_CURRENT_IO_STATE * SCARD_ATTR_CURRENT_N * SCARD_ATTR_CURRENT_PROTOCOL_TYPE * SCARD_ATTR_CURRENT_W * SCARD_ATTR_DEFAULT_CLK * SCARD_ATTR_DEFAULT_DATA_RATE * SCARD_ATTR_DEVICE_FRIENDLY_NAME_A * SCARD_ATTR_DEVICE_FRIENDLY_NAME_W * SCARD_ATTR_DEVICE_IN_USE * SCARD_ATTR_DEVICE_SYSTEM_NAME_A * SCARD_ATTR_DEVICE_SYSTEM_NAME_W * SCARD_ATTR_DEVICE_UNIT * SCARD_ATTR_ESC_AUTHREQUEST * SCARD_ATTR_ESC_CANCEL * SCARD_ATTR_ESC_RESET * SCARD_ATTR_EXTENDED_BWT * SCARD_ATTR_ICC_INTERFACE_STATUS * SCARD_ATTR_ICC_PRESENCE * SCARD_ATTR_ICC_TYPE_PER_ATR * SCARD_ATTR_MAX_CLK * SCARD_ATTR_MAX_DATA_RATE * SCARD_ATTR_MAX_IFSD * SCARD_ATTR_MAXINPUT * SCARD_ATTR_POWER_MGMT_SUPPORT * SCARD_ATTR_SUPRESS_T1_IFS_REQUEST * SCARD_ATTR_SYNC_PROTOCOL_TYPES * SCARD_ATTR_USER_AUTH_INPUT_DEVICE * SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE * SCARD_ATTR_VENDOR_IFD_SERIAL_NO * SCARD_ATTR_VENDOR_IFD_TYPE * SCARD_ATTR_VENDOR_IFD_VERSION * SCARD_ATTR_VENDOR_NAME For Windows Resource Manager, the list of possible attributes is: * SCARD_ATTR_VENDOR_NAME * SCARD_ATTR_VENDOR_IFD_TYPE * SCARD_ATTR_VENDOR_IFD_VERSION * SCARD_ATTR_VENDOR_IFD_SERIAL_NO * SCARD_ATTR_CHANNEL_ID * SCARD_ATTR_DEFAULT_CLK * SCARD_ATTR_MAX_CLK * SCARD_ATTR_DEFAULT_DATA_RATE * SCARD_ATTR_MAX_DATA_RATE * SCARD_ATTR_MAX_IFSD * SCARD_ATTR_POWER_MGMT_SUPPORT * SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE * SCARD_ATTR_USER_AUTH_INPUT_DEVICE * SCARD_ATTR_CHARACTERISTICS * SCARD_ATTR_CURRENT_PROTOCOL_TYPE * SCARD_ATTR_CURRENT_CLK * SCARD_ATTR_CURRENT_F * SCARD_ATTR_CURRENT_D * SCARD_ATTR_CURRENT_N * SCARD_ATTR_CURRENT_W * SCARD_ATTR_CURRENT_IFSC * SCARD_ATTR_CURRENT_IFSD * SCARD_ATTR_CURRENT_BWT * SCARD_ATTR_CURRENT_CWT * SCARD_ATTR_CURRENT_EBC_ENCODING * SCARD_ATTR_EXTENDED_BWT * SCARD_ATTR_ICC_PRESENCE * SCARD_ATTR_ICC_INTERFACE_STATUS * SCARD_ATTR_CURRENT_IO_STATE * SCARD_ATTR_ATR_STRING * SCARD_ATTR_ICC_TYPE_PER_ATR * SCARD_ATTR_ESC_RESET * SCARD_ATTR_ESC_CANCEL * SCARD_ATTR_ESC_AUTHREQUEST * SCARD_ATTR_MAXINPUT * SCARD_ATTR_DEVICE_UNIT * SCARD_ATTR_DEVICE_IN_USE * SCARD_ATTR_DEVICE_FRIENDLY_NAME_A * SCARD_ATTR_DEVICE_SYSTEM_NAME_A * SCARD_ATTR_DEVICE_FRIENDLY_NAME_W * SCARD_ATTR_DEVICE_SYSTEM_NAME_W * SCARD_ATTR_SUPRESS_T1_IFS_REQUEST Not all the dwAttrId values listed above may be implemented in the IFD Handler you are using. And some dwAttrId values not listed here may be implemented. from smartcard.scard import * ... establish context and connect to card ... hresult, attrib = SCardGetAttrib(hcard, SCARD_ATTR_ATR_STRING) if hresult == SCARD_S_SUCCESS: for j in attrib: print '0x%.2X' % attrib, ... """ return _scard.SCardGetAttrib(*args) def SCardSetAttrib(*args): """ SCardSetAttrib( hcard, dwAttrId, BYTELIST ATTRIBUTESIN) -> SCARDRETCODE Parameters: hcard: card handle return from SCardConnect() dwAttrId: value of attribute to get ATTRIBUTESIN: BYTELIST * value hcard: card handle return from SCardConnect() dwAttrId: value of attribute to get ATTRIBUTESIN: BYTELIST * value This function sets an attribute from the IFD Handler. Not all attributes are supported by all readers nor can they be set at all times. For PCSC lite, the list of possible attributes is: * SCARD_ATTR_ASYNC_PROTOCOL_TYPES * SCARD_ATTR_ATR_STRING * SCARD_ATTR_CHANNEL_ID * SCARD_ATTR_CHARACTERISTICS * SCARD_ATTR_CURRENT_BWT * SCARD_ATTR_CURRENT_CLK * SCARD_ATTR_CURRENT_CWT * SCARD_ATTR_CURRENT_D * SCARD_ATTR_CURRENT_EBC_ENCODING * SCARD_ATTR_CURRENT_F * SCARD_ATTR_CURRENT_IFSC * SCARD_ATTR_CURRENT_IFSD * SCARD_ATTR_CURRENT_IO_STATE * SCARD_ATTR_CURRENT_N * SCARD_ATTR_CURRENT_PROTOCOL_TYPE * SCARD_ATTR_CURRENT_W * SCARD_ATTR_DEFAULT_CLK * SCARD_ATTR_DEFAULT_DATA_RATE * SCARD_ATTR_DEVICE_FRIENDLY_NAME_A * SCARD_ATTR_DEVICE_FRIENDLY_NAME_W * SCARD_ATTR_DEVICE_IN_USE * SCARD_ATTR_DEVICE_SYSTEM_NAME_A * SCARD_ATTR_DEVICE_SYSTEM_NAME_W * SCARD_ATTR_DEVICE_UNIT * SCARD_ATTR_ESC_AUTHREQUEST * SCARD_ATTR_ESC_CANCEL * SCARD_ATTR_ESC_RESET * SCARD_ATTR_EXTENDED_BWT * SCARD_ATTR_ICC_INTERFACE_STATUS * SCARD_ATTR_ICC_PRESENCE * SCARD_ATTR_ICC_TYPE_PER_ATR * SCARD_ATTR_MAX_CLK * SCARD_ATTR_MAX_DATA_RATE * SCARD_ATTR_MAX_IFSD * SCARD_ATTR_MAXINPUT * SCARD_ATTR_POWER_MGMT_SUPPORT * SCARD_ATTR_SUPRESS_T1_IFS_REQUEST * SCARD_ATTR_SYNC_PROTOCOL_TYPES * SCARD_ATTR_USER_AUTH_INPUT_DEVICE * SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE * SCARD_ATTR_VENDOR_IFD_SERIAL_NO * SCARD_ATTR_VENDOR_IFD_TYPE * SCARD_ATTR_VENDOR_IFD_VERSION * SCARD_ATTR_VENDOR_NAME For Windows Resource Manager, the list of possible attributes is: * SCARD_ATTR_VENDOR_NAME * SCARD_ATTR_VENDOR_IFD_TYPE * SCARD_ATTR_VENDOR_IFD_VERSION * SCARD_ATTR_VENDOR_IFD_SERIAL_NO * SCARD_ATTR_CHANNEL_ID * SCARD_ATTR_DEFAULT_CLK * SCARD_ATTR_MAX_CLK * SCARD_ATTR_DEFAULT_DATA_RATE * SCARD_ATTR_MAX_DATA_RATE * SCARD_ATTR_MAX_IFSD * SCARD_ATTR_POWER_MGMT_SUPPORT * SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE * SCARD_ATTR_USER_AUTH_INPUT_DEVICE * SCARD_ATTR_CHARACTERISTICS * SCARD_ATTR_CURRENT_PROTOCOL_TYPE * SCARD_ATTR_CURRENT_CLK * SCARD_ATTR_CURRENT_F * SCARD_ATTR_CURRENT_D * SCARD_ATTR_CURRENT_N * SCARD_ATTR_CURRENT_W * SCARD_ATTR_CURRENT_IFSC * SCARD_ATTR_CURRENT_IFSD * SCARD_ATTR_CURRENT_BWT * SCARD_ATTR_CURRENT_CWT * SCARD_ATTR_CURRENT_EBC_ENCODING * SCARD_ATTR_EXTENDED_BWT * SCARD_ATTR_ICC_PRESENCE * SCARD_ATTR_ICC_INTERFACE_STATUS * SCARD_ATTR_CURRENT_IO_STATE * SCARD_ATTR_ATR_STRING * SCARD_ATTR_ICC_TYPE_PER_ATR * SCARD_ATTR_ESC_RESET * SCARD_ATTR_ESC_CANCEL * SCARD_ATTR_ESC_AUTHREQUEST * SCARD_ATTR_MAXINPUT * SCARD_ATTR_DEVICE_UNIT * SCARD_ATTR_DEVICE_IN_USE * SCARD_ATTR_DEVICE_FRIENDLY_NAME_A * SCARD_ATTR_DEVICE_SYSTEM_NAME_A * SCARD_ATTR_DEVICE_FRIENDLY_NAME_W * SCARD_ATTR_DEVICE_SYSTEM_NAME_W * SCARD_ATTR_SUPRESS_T1_IFS_REQUEST Not all the dwAttrId values listed above may be implemented in the IFD Handler you are using. And some dwAttrId values not listed here may be implemented. from smartcard.scard import * ... establish context and connect to card ... hresult, attrib = SCardSetAttrib(hcard, SCARD_ATTR_VENDOR_NAME, ['G', 'e', 'm', 'a', 'l', 't', 'o']) if hresult != SCARD_S_SUCCESS: print 'Failed to set attribute' ... """ return _scard.SCardSetAttrib(*args) def SCardControl(*args): """ SCardControl( hcard, dwControlCode, byte[] INBUFFER) -> SCARDRETCODE Parameters: hcard: card handle return from SCardConnect() dwControlCode: the control code to send inbuffer: list of bytes to send with the control code hcard: card handle return from SCardConnect() dwControlCode: the control code to send inbuffer: list of bytes to send with the control code This function sends a control command to the reader connected to by SCardConnect(). It returns a result and the control response. from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, 'SchlumbergerSema Reflex USB v.2 0', SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) CMD = [0x12, 0x34] hresult, response = SCardControl(hcard, 42, CMD) if hresult != SCARD_S_SUCCESS: raise error, 'Failed to control: ' + SCardGetErrorMessage(hresult) """ return _scard.SCardControl(*args) def SCardBeginTransaction(*args): """ SCardBeginTransaction( hcard) -> SCARDRETCODE Parameters: hcard: card handle return from SCardConnect() hcard: card handle return from SCardConnect() This function establishes a temporary exclusive access mode for doing a series of commands or transaction. You might want to use this when you are selecting a few files and then writing a large file so you can make sure that another application will not change the current file. If another application has a lock on this reader or this application is in SCARD_SHARE_EXCLUSIVE there will be no action taken. from smartcard.scard import * ... establish context ... hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, 'SchlumbergerSema Reflex USB v.2 0', SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) if hresult!=SCARD_S_SUCCESS: raise error, 'unable to connect: ' + SCardGetErrorMessage(hresult) hresult = SCardBeginTransaction(hcard) if hresult != SCARD_S_SUCCESS: raise error, 'failed to begin transaction: ' + SCardGetErrorMessage(hresult) ... """ return _scard.SCardBeginTransaction(*args) def SCardCancel(*args): """ SCardCancel( hcontext) -> SCARDRETCODE Parameters: hcontext: context handle return from SCardEstablishContext() hcontext: context handle return from SCardEstablishContext() This function cancels all pending blocking requests on the ScardGetStatusChange() function. from smartcard.scard import * ... establish context ... hresult = SCardCancel(hcard) if hresult != SCARD_S_SUCCESS: raise error, 'failed to cancel pending actions: ' + SCardGetErrorMessage(hresult) ... """ return _scard.SCardCancel(*args) def SCardConnect(*args): """ SCardConnect( hcontext, szReaderName, dwShareMode, dwPreferredProtocols) -> SCARDRETCODE Parameters: hcontext: context handle return from SCardEstablishContext() readername: card reader name dwShareMode: share mode dwPreferredProtocols: preferred protocols hcontext: context handle return from SCardEstablishContext() readername: card reader name dwShareMode: share mode dwPreferredProtocols: preferred protocols This function establishes a connection to the friendly name of the reader specified in szReader. The first connection will power up and perform a reset on the card. Value of dwShareMode Meaning SCARD_SHARE_SHARED This application will allow others to share the reader SCARD_SHARE_EXCLUSIVE This application will NOT allow others to share the reader SCARD_SHARE_DIRECT Direct control of the reader, even without a card SCARD_SHARE_DIRECT can be used before using SCardControl() to send control commands to the reader even if a card is not present in the reader. Value of dwPreferredProtocols Meaning SCARD_PROTOCOL_T0 Use the T=0 protocol SCARD_PROTOCOL_T1 Use the T=1 protocol SCARD_PROTOCOL_RAW Use with memory type cards from smartcard.scard import * ... establish context ... hresult, readers = SCardListReaders(hcontext, 'NULL') if hresult != SCARD_S_SUCCESS: raise error, 'Failed to list readers:: ' + SCardGetErrorMessage(hresult) hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, readers[0], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) if hresult != SCARD_S_SUCCESS: raise error, 'unable to connect: ' + SCardGetErrorMessage(hresult) ... """ return _scard.SCardConnect(*args) def SCardDisconnect(*args): """ SCardDisconnect( hcard, dwDisposition) -> SCARDRETCODE Parameters: hcard: card handle return from SCardConnect() dwDisposition: card disposition on return hcard: card handle return from SCardConnect() dwDisposition: card disposition on return This function terminates a connection to the connection made through SCardConnect. disposition can have the following values: Value of disposition Meaning SCARD_LEAVE_CARD Do nothing SCARD_RESET_CARD Reset the card (warm reset) SCARD_UNPOWER_CARD Unpower the card (cold reset) SCARD_EJECT_CARD Eject the card from smartcard.scard import * ... establish context and connect to card ... hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) if hresult != SCARD_S_SUCCESS: raise error, 'failed to disconnect: ' + SCardGetErrorMessage(hresult) ... """ return _scard.SCardDisconnect(*args) def SCardEndTransaction(*args): """ SCardEndTransaction( hcard, dwDisposition) -> SCARDRETCODE Parameters: hcard: card handle return from SCardConnect() dwDisposition: card disposition on return hcard: card handle return from SCardConnect() dwDisposition: card disposition on return This function ends a previously begun transaction. The calling application must be the owner of the previously begun transaction or an error will occur. disposition can have the following values: The disposition action is not currently used in this release. Value of disposition Meaning SCARD_LEAVE_CARD Do nothing SCARD_RESET_CARD Reset the card SCARD_UNPOWER_CARD Unpower the card SCARD_EJECT_CARD Eject the card from smartcard.scard import * ... establish context, connect to card, begin transaction ... hresult = SCardEndTransaction(hcard, SCARD_LEAVE_CARD) if hresult != SCARD_S_SUCCESS: raise error, 'failed to end transaction: ' + SCardGetErrorMessage(hresult) """ return _scard.SCardEndTransaction(*args) def SCardEstablishContext(*args): """ SCardEstablishContext( dwScope) -> SCARDRETCODE Parameters: dwScope: context scope dwScope: context scope This function creates a communication context to the PC/SC Resource Manager. This must be the first function called in a PC/SC application. Value of dwScope Meaning SCARD_SCOPE_USER Operations performed within the scope of the User SCARD_SCOPE_TERMINAL Not used SCARD_SCOPE_GLOBAL Not used SCARD_SCOPE_SYSTEM Operations performed within the scope of the system from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise error, 'Failed to establish context: ' + SCardGetErrorMessage(hresult) """ return _scard.SCardEstablishContext(*args) def SCardGetStatusChange(*args): """ SCardGetStatusChange( hcontext, dwTimeout, tuple[] prsl) -> SCARDRETCODE Parameters: hcontext: context handle return from SCardEstablishContext() dwTimeout: timeout value, INFINITE for infinite time-out readerstatelist: in input/output, a list of reader state tuple (readername, state, atr) hcontext: context handle return from SCardEstablishContext() dwTimeout: timeout value, INFINITE for infinite time-out readerstatelist: in input/output, a list of reader state tuple (readername, state, atr) This function receives a structure or list of tuples containing reader states. A READERSTATE hast three fields (readername, state, atr). It then blocks for a change in state to occur on any of the OR'd values contained in the current state for a maximum blocking time of dwTimeout or forever if INFINITE is used. The new event state will be contained in state. A status change might be a card insertion or removal event, a change in ATR, etc. Value of state Meaning SCARD_STATE_UNAWARE The application is unaware of the current state, and would like to know. The use of this value results in an immediate return from state transition monitoring services. This is represented by all bits set to zero SCARD_STATE_IGNORE This reader should be ignored SCARD_STATE_CHANGED There is a difference between the state believed by the application, and the state known by the resource manager. When this bit is set, the application may assume a significant state change has occurred on this reader SCARD_STATE_UNKNOWN The given reader name is not recognized by the resource manager. If this bit is set, then SCARD_STATE_CHANGED and SCARD_STATE_IGNORE will also be set SCARD_STATE_UNAVAILABLE The actual state of this reader is not available. If this bit is set, then all the following bits are clear SCARD_STATE_EMPTY There is no card in the reader. If this bit is set, all the following bits will be clear SCARD_STATE_PRESENT There is a card in the reader SCARD_STATE_ATRMATCH There is a card in the reader with an ATR matching one of the target cards. If this bit is set, SCARD_STATE_PRESENT will also be set. This bit is only returned on the SCardLocateCards function SCARD_STATE_EXCLUSIVE The card in the reader is allocated for exclusive use by another application. If this bit is set, SCARD_STATE_PRESENT will also be set SCARD_STATE_INUSE The card in the reader is in use by one or more other applications, but may be connected to in shared mode. If this bit is set, SCARD_STATE_PRESENT will also be set SCARD_STATE_MUTE There is an unresponsive card in the reader from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, readers = SCardListReaders(hcontext, []) readerstates = [] cards = [ 'Schlumberger Cryptoflex 4k', 'Schlumberger Cryptoflex 8k', 'Schlumberger Cryptoflex 8k v2' ] for i in xrange(len(readers)): readerstates += [ (readers[i], SCARD_STATE_UNAWARE) ] hresult, newstates = SCardLocateCards(hcontext, cards, readerstates) print '----- Please insert or remove a card ------------' hresult, newstates = SCardGetStatusChange(hcontext, INFINITE, newstates) for i in newstates reader, eventstate, atr = i if eventstate & SCARD_STATE_ATRMATCH: print ' Card found' if eventstate & SCARD_STATE_EMPTY: print ' Reader empty' """ return _scard.SCardGetStatusChange(*args) def SCardListReaders(*args): """ SCardListReaders( hcontext, [] READERGROUPSIN) -> SCARDRETCODE Parameters: hcontext: context handle return from SCardEstablishContext() readergroups: a list of reader groups to search for readers hcontext: context handle return from SCardEstablishContext() readergroups: a list of reader groups to search for readers This function returns a list of currently available readers on the system. A list of group can be provided in input to list readers in a given group only. from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, readers = SCardListReaders(hcontext, []) if hresult != SCARD_S_SUCCESS: raise error, 'Failed to list readers: ' + SCardGetErrorMessage(hresult) print 'PCSC Readers: ', readers hresult, readers = SCardListReaders(hcontext, ['SCard$T1ProtocolReaders', 'SCard$MyOwnGroup'] ... """ return _scard.SCardListReaders(*args) def SCardListReaderGroups(*args): """ SCardListReaderGroups( hcontext) -> SCARDRETCODE Parameters: hcontext: context handle return from SCardEstablishContext() hcontext: context handle return from SCardEstablishContext() This function returns a list of currently available reader groups on the system. from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, readerGroups = SCardListReaderGroups(hcontext) if hresult != SCARD_S_SUCCESS: raise error, 'Unable to list reader groups: ' + SCardGetErrorMessage(hresult) print 'PCSC Reader groups: ', readerGroups """ return _scard.SCardListReaderGroups(*args) def SCardReconnect(*args): """ SCardReconnect( hcard, dwShareMode, dwPreferredProtocols, dwInitialization) -> SCARDRETCODE Parameters: hcard: card handle return from SCardConnect() dwShareMode: share mode dwPreferredProtocols: preferred protocols dwInitialization: the type of initialization that should be performed on the card hcard: card handle return from SCardConnect() dwShareMode: share mode dwPreferredProtocols: preferred protocols dwInitialization: the type of initialization that should be performed on the card This function reestablishes a connection to a reader that was previously connected to using SCardConnect(). In a multi application environment it is possible for an application to reset the card in shared mode. When this occurs any other application trying to access certain commands will be returned the value SCARD_W_RESET_CARD. When this occurs SCardReconnect() must be called in order to acknowledge that the card was reset and allow it to change it's state accordingly. Value of dwShareMode Meaning SCARD_SHARE_SHARED This application will allow others to share the reader SCARD_SHARE_EXCLUSIVE This application will NOT allow others to share the reader Value of dwPreferredProtocols Meaning SCARD_PROTOCOL_T0 Use the T=0 protocol SCARD_PROTOCOL_T1 Use the T=1 protocol SCARD_PROTOCOL_RAW Use with memory type cards dwPreferredProtocols is a bit mask of acceptable protocols for the connection. You can use (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) if you do not have a preferred protocol. Value of dwInitialization Meaning SCARD_LEAVE_CARD Do nothing SCARD_RESET_CARD Reset the card (warm reset) SCARD_UNPOWER_CARD Unpower the card (cold reset) SCARD_EJECT_CARD Eject the card from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, 'SchlumbergerSema Reflex USB v.2 0', SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) hresult, activeProtocol = SCardReconnect(hcard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0, SCARD_RESET_CARD) ... """ return _scard.SCardReconnect(*args) def SCardReleaseContext(*args): """ SCardReleaseContext( hcontext) -> SCARDRETCODE Parameters: hcontext: context handle return from SCardEstablishContext() hcontext: context handle return from SCardEstablishContext() """ return _scard.SCardReleaseContext(*args) def SCardStatus(*args): """ SCardStatus( hcard) -> SCARDRETCODE Parameters: hcard: card handle return from SCardConnect() hcard: card handle return from SCardConnect() This function returns the current status of the reader connected to by hcard. The reader friendly name is returned, as well as the state, protocol and ATR. The state is a DWORD possibly OR'd with the following values: Value of pdwState Meaning SCARD_ABSENT There is no card in the reader SCARD_PRESENT There is a card in the reader, but it has not been moved into position for use SCARD_SWALLOWED There is a card in the reader in position for use. The card is not powered SCARD_POWERED Power is being provided to the card, but the reader driver is unaware of the mode of the card SCARD_NEGOTIABLE The card has been reset and is awaiting PTS negotiation SCARD_SPECIFIC The card has been reset and specific communication protocols have been established Value of pdwProtocol Meaning SCARD_PROTOCOL_T0 Use the T=0 protocol SCARD_PROTOCOL_T1 Use the T=1 protocol from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, 'SchlumbergerSema Reflex USB v.2 0', SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) hresult, reader, state, protocol, atr = SCardStatus(hcard) if hresult != SCARD_S_SUCCESS: raise error, 'failed to get status: ' + SCardGetErrorMessage(hresult) print 'Reader: ', reader print 'State: ', state print 'Protocol: ', protocol print 'ATR: ', for i in xrange(len(atr)): print '0x%.2X' % i, print ... """ return _scard.SCardStatus(*args) def SCardTransmit(*args): """ SCardTransmit( hcard, unsigned long pioSendPci, byte[] APDUCOMMAND) -> SCARDRETCODE Parameters: hcard: card handle return from SCardConnect() pioSendPci: unsigned long value apducommand: list of APDU bytes to transmit hcard: card handle return from SCardConnect() pioSendPci: unsigned long value apducommand: list of APDU bytes to transmit This function sends an APDU to the smart card contained in the reader connected to by SCardConnect(). It returns a result and the card APDU response. Value of pioSendPci Meaning SCARD_PCI_T0 Pre-defined T=0 PCI structure SCARD_PCI_T1 Pre-defined T=1 PCI structure from smartcard.scard import * hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) hresult, hcard, dwActiveProtocol = SCardConnect( hcontext, 'SchlumbergerSema Reflex USB v.2 0', SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0) SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] hresult, response = SCardTransmit(hcard, SCARD_PCI_T0, SELECT + DF_TELECOM) if hresult != SCARD_S_SUCCESS: raise error, 'Failed to transmit: ' + SCardGetErrorMessage(hresult) """ return _scard.SCardTransmit(*args) def SCARD_CTL_CODE(*args): """ SCARD_CTL_CODE(long code) -> long Parameters: code: long value code: long value This function returns the value of a control code from smartcard.scard import * ... CM_IOCTL_GET_FEATURE_REQUEST = SCARD_CTL_CODE(3400) ... """ return _scard.SCARD_CTL_CODE(*args) def SCardGetErrorMessage(*args): """ SCardGetErrorMessage(long lErrCode) -> ERRORSTRING Parameters: lErrCode: long value lErrCode: long value This function return a human readable text for the given PC/SC error code. from smartcard.scard import * ... hresult, response = SCardTransmit(hcard, SCARD_PCI_T0, SELECT + DF_TELECOM) if hresult != SCARD_S_SUCCESS: raise error, 'Failed to transmit: ' + SCardGetErrorMessage(hresult) ... """ return _scard.SCardGetErrorMessage(*args) error = _scard.error SCARD_SCOPE_USER = _scard.SCARD_SCOPE_USER SCARD_SCOPE_TERMINAL = _scard.SCARD_SCOPE_TERMINAL SCARD_SCOPE_SYSTEM = _scard.SCARD_SCOPE_SYSTEM SCARD_SHARE_SHARED = _scard.SCARD_SHARE_SHARED SCARD_SHARE_EXCLUSIVE = _scard.SCARD_SHARE_EXCLUSIVE SCARD_SHARE_DIRECT = _scard.SCARD_SHARE_DIRECT SCARD_LEAVE_CARD = _scard.SCARD_LEAVE_CARD SCARD_RESET_CARD = _scard.SCARD_RESET_CARD SCARD_UNPOWER_CARD = _scard.SCARD_UNPOWER_CARD SCARD_EJECT_CARD = _scard.SCARD_EJECT_CARD SCARD_STATE_UNAWARE = _scard.SCARD_STATE_UNAWARE SCARD_STATE_IGNORE = _scard.SCARD_STATE_IGNORE SCARD_STATE_CHANGED = _scard.SCARD_STATE_CHANGED SCARD_STATE_UNKNOWN = _scard.SCARD_STATE_UNKNOWN SCARD_STATE_UNAVAILABLE = _scard.SCARD_STATE_UNAVAILABLE SCARD_STATE_EMPTY = _scard.SCARD_STATE_EMPTY SCARD_STATE_PRESENT = _scard.SCARD_STATE_PRESENT SCARD_STATE_ATRMATCH = _scard.SCARD_STATE_ATRMATCH SCARD_STATE_EXCLUSIVE = _scard.SCARD_STATE_EXCLUSIVE SCARD_STATE_INUSE = _scard.SCARD_STATE_INUSE SCARD_STATE_MUTE = _scard.SCARD_STATE_MUTE SCARD_STATE_UNPOWERED = _scard.SCARD_STATE_UNPOWERED SCARD_PROTOCOL_UNSET = _scard.SCARD_PROTOCOL_UNSET SCARD_PROTOCOL_T0 = _scard.SCARD_PROTOCOL_T0 SCARD_PROTOCOL_T1 = _scard.SCARD_PROTOCOL_T1 SCARD_PROTOCOL_RAW = _scard.SCARD_PROTOCOL_RAW SCARD_PROTOCOL_T15 = _scard.SCARD_PROTOCOL_T15 SCARD_PROTOCOL_ANY = _scard.SCARD_PROTOCOL_ANY SCARD_PROTOCOL_UNDEFINED = _scard.SCARD_PROTOCOL_UNDEFINED SCARD_PROTOCOL_OPTIMAL = _scard.SCARD_PROTOCOL_OPTIMAL SCARD_PROTOCOL_Tx = _scard.SCARD_PROTOCOL_Tx SCARD_PROTOCOL_DEFAULT = _scard.SCARD_PROTOCOL_DEFAULT SCARD_PCI_T0 = _scard.SCARD_PCI_T0 SCARD_PCI_T1 = _scard.SCARD_PCI_T1 SCARD_PCI_RAW = _scard.SCARD_PCI_RAW SCARD_ATTR_VENDOR_NAME = _scard.SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VENDOR_IFD_TYPE = _scard.SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VENDOR_IFD_VERSION = _scard.SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VENDOR_IFD_SERIAL_NO = _scard.SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_CHANNEL_ID = _scard.SCARD_ATTR_CHANNEL_ID SCARD_ATTR_ASYNC_PROTOCOL_TYPES = _scard.SCARD_ATTR_ASYNC_PROTOCOL_TYPES SCARD_ATTR_DEFAULT_CLK = _scard.SCARD_ATTR_DEFAULT_CLK SCARD_ATTR_MAX_CLK = _scard.SCARD_ATTR_MAX_CLK SCARD_ATTR_DEFAULT_DATA_RATE = _scard.SCARD_ATTR_DEFAULT_DATA_RATE SCARD_ATTR_MAX_DATA_RATE = _scard.SCARD_ATTR_MAX_DATA_RATE SCARD_ATTR_MAX_IFSD = _scard.SCARD_ATTR_MAX_IFSD SCARD_ATTR_SYNC_PROTOCOL_TYPES = _scard.SCARD_ATTR_SYNC_PROTOCOL_TYPES SCARD_ATTR_POWER_MGMT_SUPPORT = _scard.SCARD_ATTR_POWER_MGMT_SUPPORT SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE = _scard.SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE SCARD_ATTR_USER_AUTH_INPUT_DEVICE = _scard.SCARD_ATTR_USER_AUTH_INPUT_DEVICE SCARD_ATTR_CHARACTERISTICS = _scard.SCARD_ATTR_CHARACTERISTICS SCARD_ATTR_CURRENT_PROTOCOL_TYPE = _scard.SCARD_ATTR_CURRENT_PROTOCOL_TYPE SCARD_ATTR_CURRENT_CLK = _scard.SCARD_ATTR_CURRENT_CLK SCARD_ATTR_CURRENT_F = _scard.SCARD_ATTR_CURRENT_F SCARD_ATTR_CURRENT_D = _scard.SCARD_ATTR_CURRENT_D SCARD_ATTR_CURRENT_N = _scard.SCARD_ATTR_CURRENT_N SCARD_ATTR_CURRENT_W = _scard.SCARD_ATTR_CURRENT_W SCARD_ATTR_CURRENT_IFSC = _scard.SCARD_ATTR_CURRENT_IFSC SCARD_ATTR_CURRENT_IFSD = _scard.SCARD_ATTR_CURRENT_IFSD SCARD_ATTR_CURRENT_BWT = _scard.SCARD_ATTR_CURRENT_BWT SCARD_ATTR_CURRENT_CWT = _scard.SCARD_ATTR_CURRENT_CWT SCARD_ATTR_CURRENT_EBC_ENCODING = _scard.SCARD_ATTR_CURRENT_EBC_ENCODING SCARD_ATTR_EXTENDED_BWT = _scard.SCARD_ATTR_EXTENDED_BWT SCARD_ATTR_ICC_PRESENCE = _scard.SCARD_ATTR_ICC_PRESENCE SCARD_ATTR_ICC_INTERFACE_STATUS = _scard.SCARD_ATTR_ICC_INTERFACE_STATUS SCARD_ATTR_CURRENT_IO_STATE = _scard.SCARD_ATTR_CURRENT_IO_STATE SCARD_ATTR_ATR_STRING = _scard.SCARD_ATTR_ATR_STRING SCARD_ATTR_ICC_TYPE_PER_ATR = _scard.SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_ESC_RESET = _scard.SCARD_ATTR_ESC_RESET SCARD_ATTR_ESC_CANCEL = _scard.SCARD_ATTR_ESC_CANCEL SCARD_ATTR_ESC_AUTHREQUEST = _scard.SCARD_ATTR_ESC_AUTHREQUEST SCARD_ATTR_MAXINPUT = _scard.SCARD_ATTR_MAXINPUT SCARD_ATTR_DEVICE_UNIT = _scard.SCARD_ATTR_DEVICE_UNIT SCARD_ATTR_DEVICE_IN_USE = _scard.SCARD_ATTR_DEVICE_IN_USE SCARD_ATTR_DEVICE_FRIENDLY_NAME_A = _scard.SCARD_ATTR_DEVICE_FRIENDLY_NAME_A SCARD_ATTR_DEVICE_SYSTEM_NAME_A = _scard.SCARD_ATTR_DEVICE_SYSTEM_NAME_A SCARD_ATTR_DEVICE_FRIENDLY_NAME_W = _scard.SCARD_ATTR_DEVICE_FRIENDLY_NAME_W SCARD_ATTR_DEVICE_SYSTEM_NAME_W = _scard.SCARD_ATTR_DEVICE_SYSTEM_NAME_W SCARD_ATTR_SUPRESS_T1_IFS_REQUEST = _scard.SCARD_ATTR_SUPRESS_T1_IFS_REQUEST SCARD_ATTR_DEVICE_FRIENDLY_NAME = _scard.SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME = _scard.SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_S_SUCCESS = _scard.SCARD_S_SUCCESS SCARD_F_INTERNAL_ERROR = _scard.SCARD_F_INTERNAL_ERROR SCARD_E_CANCELLED = _scard.SCARD_E_CANCELLED SCARD_E_INVALID_HANDLE = _scard.SCARD_E_INVALID_HANDLE SCARD_E_INVALID_PARAMETER = _scard.SCARD_E_INVALID_PARAMETER SCARD_E_INVALID_TARGET = _scard.SCARD_E_INVALID_TARGET SCARD_E_NO_MEMORY = _scard.SCARD_E_NO_MEMORY SCARD_F_WAITED_TOO_LONG = _scard.SCARD_F_WAITED_TOO_LONG SCARD_E_INSUFFICIENT_BUFFER = _scard.SCARD_E_INSUFFICIENT_BUFFER SCARD_E_UNKNOWN_READER = _scard.SCARD_E_UNKNOWN_READER SCARD_E_TIMEOUT = _scard.SCARD_E_TIMEOUT SCARD_E_SHARING_VIOLATION = _scard.SCARD_E_SHARING_VIOLATION SCARD_E_NO_SMARTCARD = _scard.SCARD_E_NO_SMARTCARD SCARD_E_UNKNOWN_CARD = _scard.SCARD_E_UNKNOWN_CARD SCARD_E_CANT_DISPOSE = _scard.SCARD_E_CANT_DISPOSE SCARD_E_PROTO_MISMATCH = _scard.SCARD_E_PROTO_MISMATCH SCARD_E_NOT_READY = _scard.SCARD_E_NOT_READY SCARD_E_INVALID_VALUE = _scard.SCARD_E_INVALID_VALUE SCARD_E_SYSTEM_CANCELLED = _scard.SCARD_E_SYSTEM_CANCELLED SCARD_F_COMM_ERROR = _scard.SCARD_F_COMM_ERROR SCARD_F_UNKNOWN_ERROR = _scard.SCARD_F_UNKNOWN_ERROR SCARD_E_INVALID_ATR = _scard.SCARD_E_INVALID_ATR SCARD_E_NOT_TRANSACTED = _scard.SCARD_E_NOT_TRANSACTED SCARD_E_READER_UNAVAILABLE = _scard.SCARD_E_READER_UNAVAILABLE SCARD_E_PCI_TOO_SMALL = _scard.SCARD_E_PCI_TOO_SMALL SCARD_E_READER_UNSUPPORTED = _scard.SCARD_E_READER_UNSUPPORTED SCARD_E_DUPLICATE_READER = _scard.SCARD_E_DUPLICATE_READER SCARD_E_CARD_UNSUPPORTED = _scard.SCARD_E_CARD_UNSUPPORTED SCARD_E_NO_SERVICE = _scard.SCARD_E_NO_SERVICE SCARD_E_SERVICE_STOPPED = _scard.SCARD_E_SERVICE_STOPPED SCARD_E_NO_READERS_AVAILABLE = _scard.SCARD_E_NO_READERS_AVAILABLE SCARD_E_UNSUPPORTED_FEATURE = _scard.SCARD_E_UNSUPPORTED_FEATURE SCARD_W_UNSUPPORTED_CARD = _scard.SCARD_W_UNSUPPORTED_CARD SCARD_W_UNRESPONSIVE_CARD = _scard.SCARD_W_UNRESPONSIVE_CARD SCARD_W_UNPOWERED_CARD = _scard.SCARD_W_UNPOWERED_CARD SCARD_W_RESET_CARD = _scard.SCARD_W_RESET_CARD SCARD_W_REMOVED_CARD = _scard.SCARD_W_REMOVED_CARD SCARD_W_SECURITY_VIOLATION = _scard.SCARD_W_SECURITY_VIOLATION SCARD_W_WRONG_CHV = _scard.SCARD_W_WRONG_CHV SCARD_W_CHV_BLOCKED = _scard.SCARD_W_CHV_BLOCKED SCARD_W_EOF = _scard.SCARD_W_EOF SCARD_W_CANCELLED_BY_USER = _scard.SCARD_W_CANCELLED_BY_USER SCARD_W_CARD_NOT_AUTHENTICATED = _scard.SCARD_W_CARD_NOT_AUTHENTICATED SCARD_E_UNEXPECTED = _scard.SCARD_E_UNEXPECTED SCARD_E_ICC_INSTALLATION = _scard.SCARD_E_ICC_INSTALLATION SCARD_E_ICC_CREATEORDER = _scard.SCARD_E_ICC_CREATEORDER SCARD_E_DIR_NOT_FOUND = _scard.SCARD_E_DIR_NOT_FOUND SCARD_E_FILE_NOT_FOUND = _scard.SCARD_E_FILE_NOT_FOUND SCARD_E_NO_DIR = _scard.SCARD_E_NO_DIR SCARD_E_NO_FILE = _scard.SCARD_E_NO_FILE SCARD_E_NO_ACCESS = _scard.SCARD_E_NO_ACCESS SCARD_E_WRITE_TOO_MANY = _scard.SCARD_E_WRITE_TOO_MANY SCARD_E_BAD_SEEK = _scard.SCARD_E_BAD_SEEK SCARD_E_INVALID_CHV = _scard.SCARD_E_INVALID_CHV SCARD_E_UNKNOWN_RES_MNG = _scard.SCARD_E_UNKNOWN_RES_MNG SCARD_E_NO_SUCH_CERTIFICATE = _scard.SCARD_E_NO_SUCH_CERTIFICATE SCARD_E_CERTIFICATE_UNAVAILABLE = _scard.SCARD_E_CERTIFICATE_UNAVAILABLE SCARD_E_COMM_DATA_LOST = _scard.SCARD_E_COMM_DATA_LOST SCARD_E_NO_KEY_CONTAINER = _scard.SCARD_E_NO_KEY_CONTAINER SCARD_E_SERVER_TOO_BUSY = _scard.SCARD_E_SERVER_TOO_BUSY INVALID_HANDLE = _scard.INVALID_HANDLE SCARD_P_SHUTDOWN = _scard.SCARD_P_SHUTDOWN INFINITE = _scard.INFINITE resourceManager = _scard.resourceManager resourceManagerSubType = _scard.resourceManagerSubType pyscard-1.6.14/smartcard/scard/scard.rc0000644000175000017500000000047510633575651021525 0ustar rousseaurousseau00000000000000#include #define VER_FILEDESCRIPTION_STR "Python PCSC Module\0" #define VER_INTERNALNAME_STR "_scard.pyd" #define VER_ORIGINALFILENAME_STR "_scard.pyd" #define VER_FILETYPE VFT_DLL #define VER_FILESUBTYPE (0) #include "gemalto.ver" pyscard-1.6.14/smartcard/Session.py0000644000175000017500000000741711747776700021014 0ustar rousseaurousseau00000000000000""" Smartcard Session. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.Exceptions import InvalidReaderException, NoReadersException from smartcard.CardConnection import CardConnection from smartcard.PassThruCardService import PassThruCardService from smartcard.System import readers class Session(object): """The Session object enables programmers to transmit APDU to smartcards. This is an example of use of the Session object: import smartcard reader=smartcard.listReaders() s = smartcard.Session(reader[0]) SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] data, sw1, sw2 = s.sendCommandAPDU(SELECT+DF_TELECOM) print data, sw1, sw2 s.close() print `s` """ def __init__(self, readerName=None, cardServiceClass=None): """Session constructor. Initializes a smart card session and connect to the card. readerName: reader to connect to; default is first PCSC reader cardServiceClass: card service to bind the session to; default is None """ # if reader name not given, select first reader if readerName == None: if len(readers()) > 0: self.reader = readers()[0] self.readerName = repr(self.reader) else: raise NoReadersException() # otherwise select reader from name else: self.readerName = readerName for reader in readers(): if readerName == str(reader): self.reader = reader self.readerName = repr(self.reader) try: self.reader except AttributeError: raise InvalidReaderException(self.readerName) # open card connection and bind PassThruCardService cc = self.reader.createConnection() self.cs = PassThruCardService(cc) self.cs.connection.connect() def close(self): """Close the smartcard session. Closing a session will disconnect from the card.""" self.cs.connection.disconnect() def sendCommandAPDU(self, command): """Send an APDU command to the connected smartcard. command: list of APDU bytes, e.g. [0xA0, 0xA4, 0x00, 0x00, 0x02] returns a tuple (response, sw1, sw2) where response is the APDU response sw1, sw2 are the two status words """ response, sw1, sw2 = self.cs.connection.transmit(command) if len(response) > 2: response.append(sw1) response.append(sw2) return response, sw1, sw2 def getATR(self): """Returns the ATR of the connected card.""" return self.cs.connection.getATR() def __repr__(self): """Returns a string representation of the session.""" return "" % self.readerName if __name__ == '__main__': """Small sample illustrating the use of Session.py.""" pass pyscard-1.6.14/smartcard/ulist.py0000644000175000017500000000745611747776700020534 0ustar rousseaurousseau00000000000000"""ulist is a subclass of list where items cannot appear twice in the list. [1,2,2,3,3,4] is a valid list, whereas in ulist we can only have [1,2,3,4]. __author__ = "gemalto http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ class ulist(list): """ulist ensures that all items are unique and provides an __onadditem__ hook to perform custom action in subclasses.""" # # override list methods # def __init__(self, initlist=None): if initlist is not None and initlist != []: list.__init__(self, [initlist[0]]) for item in initlist[1:]: if not list.__contains__(self, item): list.append(self, item) else: list.__init__(self, initlist) def __add__(self, other): newother = self.__remove_duplicates(other) self.__appendother__(newother) return self.__class__(list(self) + list(newother)) def __iadd__(self, other): newother = self.__remove_duplicates(other) self.__appendother__(newother) list.__iadd__(self, newother) return self def __radd__(self, other): newother = self.__remove_duplicates(other) return list.__add__(self, newother) def append(self, item): if not list.__contains__(self, item): list.append(self, item) self.__onadditem__(item) def insert(self, i, item): if not list.__contains__(self, item): list.insert(self, i, item) self.__onadditem__(item) def pop(self, i=-1): item = list.pop(self, i) self.__onremoveitem__(item) return item def remove(self, item): list.remove(self, item) self.__onremoveitem__(item) # # non list methods # def __remove_duplicates(self, _other): """Remove from other items already in list.""" if not isinstance(_other, type(self)) \ and not isinstance(_other, type(list)) \ and not isinstance(_other, type([])): other = [_other] else: other = list(_other) # remove items already in self newother = [] for i in range(0, len(other)): item = other.pop(0) if not list.__contains__(self, item): newother.append(item) # remove duplicate items in other other = [] if newother != []: other.append(newother[0]) for i in range(1, len(newother)): item = newother.pop() if not other.__contains__(item): other.append(item) return other def __appendother__(self, other): """Append other to object.""" for item in other: self.__onadditem__(item) def __onadditem__(self, item): """Called for each item added. Override in subclasses for adding custom action.""" pass def __onremoveitem__(self, item): """Called for each item removed. Override in subclasses for adding custom action.""" pass pyscard-1.6.14/smartcard/LICENSE0000644000175000017500000006037310633575651020017 0ustar rousseaurousseau00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. pyscard-1.6.14/smartcard/CardRequest.py0000644000175000017500000000625111747776700021606 0ustar rousseaurousseau00000000000000"""Smartcard CardRequest. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.pcsc.PCSCCardRequest import PCSCCardRequest class CardRequest(object): """A CardRequest is used for waitForCard() invocations and specifies what kind of smart card an application is waited for. """ def __init__(self, newcardonly=False, readers=None, cardType=None, cardServiceClass=None, timeout=1): """Construct new CardRequest. newcardonly: if True, request a new card default is False, i.e. accepts cards already inserted readers: the list of readers to consider for requesting a card default is to consider all readers cardType: the smartcard.CardType.CardType to wait for; default is smartcard.CardType.AnyCardType, i.e. the request will succeed with any card cardServiceClass: the specific card service class to create and bind to the card default is to create and bind a smartcard.PassThruCardService timeout: the time in seconds we are ready to wait for connecting to the requested card. default is to wait one second to wait forever, set timeout to None """ self.pcsccardrequest = PCSCCardRequest(newcardonly, readers, cardType, cardServiceClass, timeout) def getReaders(self): """Returns the list or readers on which to wait for cards.""" return self.pcsccardrequest.getReaders() def waitforcard(self): """Wait for card insertion and returns a card service.""" return self.pcsccardrequest.waitforcard() def waitforcardevent(self): """Wait for card insertion or removal.""" return self.pcsccardrequest.waitforcardevent() if __name__ == '__main__': """Small sample illustrating the use of CardRequest.py.""" from smartcard.util import toHexString print 'Insert a new card within 10 seconds' cr = CardRequest(timeout=10, newcardonly=True) cs = cr.waitforcard() cs.connection.connect() print cs.connection.getReader(), toHexString(cs.connection.getATR()) cs.connection.disconnect() pyscard-1.6.14/smartcard/wx/0000755000175000017500000000000011747777125017446 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/wx/SimpleSCardApp.py0000644000175000017500000000610311747776676022641 0ustar rousseaurousseau00000000000000"""Simple wxPython wxApp for smartcard. __author__ = "gemalto http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 wx from smartcard.wx.SimpleSCardAppFrame import SimpleSCardAppFrame TR_SMARTCARD = 0x001 TR_READER = 0x002 TB_SMARTCARD = 0x004 TB_READER = 0x008 PANEL_APDUTRACER = 0x010 TR_DEFAULT = TR_SMARTCARD class SimpleSCardApp(wx.App): """The SimpleSCardApp class represents the smart card application. SimpleSCardApp is a subclass of wx.App. """ def __init__(self, appname='', apppanel=None, appstyle=TR_DEFAULT, appicon=None, pos=(-1, -1), size=(-1, -1)): """Constructor for simple smart card application. appname: the application name apppanel: the application panel to display in the application frame appicon: the application icon file; the default is no icon appstyle: a combination of the following styles (bitwise or |) TR_SMARTCARD: display a smartcard tree panel TR_READER: display a reader tree panel TB_SMARTCARD: display a smartcard toolbar TB_SMARTCARD: display a reader toolbar PANEL_APDUTRACER: display an APDU tracer panel default is TR_DEFAULT = TR_SMARTCARD pos: the application position as a (x,y) tupple; default is (-1,-1) size: the application window size as a (x,y) tuple; default is (-1,-1) example: app = SimpleSCardApp( appname = 'A simple smartcard application', apppanel = testpanel.MyPanel, appstyle = TR_READER | TR_SMARTCARD, appicon = 'resources\mysmartcard.ico') """ self.appname = appname self.apppanel = apppanel self.appstyle = appstyle self.appicon = appicon self.pos = pos self.size = size wx.App.__init__(self, False) def OnInit(self): """Create and display application frame.""" self.frame = SimpleSCardAppFrame( self.appname, self.apppanel, self.appstyle, self.appicon, self.pos, self.size) self.frame.Show(True) self.SetTopWindow(self.frame) return True pyscard-1.6.14/smartcard/wx/ReaderToolbar.py0000644000175000017500000000706611747776676022570 0ustar rousseaurousseau00000000000000"""wxPython toolbar with reader icons implementing ReaderObserver. __author__ = "gemalto http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 wx from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver from smartcard.wx import ICO_SMARTCARD, ICO_READER class ReaderComboBox(wx.ComboBox, ReaderObserver): def __init__(self, parent): """Constructor. Registers as ReaderObserver to get notifications of reader insertion/removal.""" wx.ComboBox.__init__(self, parent, wx.NewId(), size=(170, -1), style=wx.CB_DROPDOWN | wx.CB_SORT, choices=[]) # register as a ReaderObserver; we will get # notified of added/removed readers self.readermonitor = ReaderMonitor() self.readermonitor.addObserver(self) def update(self, observable, (addedreaders, removedreaders)): """Toolbar ReaderObserver callback that is notified when readers are added or removed.""" for reader in addedreaders: item = self.Append(str(reader)) self.SetClientData(item, reader) for reader in removedreaders: item = self.FindString(str(reader)) if wx.NOT_FOUND != item: self.Delete(item) selection = self.GetSelection() #if wx.NOT_FOUND == selection: # self.SetSelection(0) class ReaderToolbar(wx.ToolBar): """ReaderToolbar. Contains controls to select a reader from a listbox and connect to the cards.""" def __init__(self, parent): """Constructor, creating the reader toolbar.""" wx.ToolBar.__init__( self, parent, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.SIMPLE_BORDER | wx.TB_HORIZONTAL | wx.TB_FLAT | wx.TB_TEXT, name='Reader Toolbar') # create bitmaps for toolbar tsize = (16, 16) if None != ICO_READER: bmpReader = wx.Bitmap(ICO_READER, wx.BITMAP_TYPE_ICO) else: bmpReader = wx.ArtProvider_GetBitmap( wx.ART_HELP_BOOK, wx.ART_OTHER, isz) if None != ICO_SMARTCARD: bmpCard = wx.Bitmap(ICO_SMARTCARD, wx.BITMAP_TYPE_ICO) else: bmpCard = wx.ArtProvider_GetBitmap( wx.ART_HELP_BOOK, wx.ART_OTHER, isz) self.readercombobox = ReaderComboBox(self) # create and add controls self.AddSimpleTool( 10, bmpReader, "Select smart card reader", "Select smart card reader") self.AddControl(self.readercombobox) self.AddSeparator() self.AddSimpleTool( 20, bmpCard, "Connect to smartcard", "Connect to smart card") self.AddSeparator() self.Realize() pyscard-1.6.14/smartcard/wx/APDUHexValidator.py0000644000175000017500000000405011747776676023075 0ustar rousseaurousseau00000000000000# -*- coding: iso-8859-15 -*- """ A wxValidator that matches APDU in hexadecimal such as: A4 A0 00 00 02 A4A0000002 __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 re import string import wx # a regexp to match ATRs and APDUs hexbyte = "[0-9a-fA-F]{1,2}" apduregexp = re.compile("((%s)[ ]*)*" % hexbyte) class APDUHexValidator(wx.PyValidator): '''A wxValidator that matches APDU in hexadecimal such as: A4 A0 00 00 02 A4A0000002''' def __init__(self): wx.PyValidator.__init__(self) self.Bind(wx.EVT_CHAR, self.OnChar) def Clone(self): return APDUHexValidator() def Validate(self, win): tc = self.GetWindow() val = tc.GetValue() if not apduregexp.match(value): return False return True def OnChar(self, event): key = event.GetKeyCode() if wx.WXK_SPACE == key or chr(key) in string.hexdigits: value = event.GetEventObject().GetValue() + chr(key) if apduregexp.match(value): event.Skip() return if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255: event.Skip() return if not wx.Validator_IsSilent(): wx.Bell() return pyscard-1.6.14/smartcard/wx/__init__.py0000644000175000017500000000337211747776676021576 0ustar rousseaurousseau00000000000000"""wxpython smartcard utility module. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 imp import os.path import sys def main_is_frozen(): return(hasattr(sys, "frozen") or \ hasattr(sys, "importers") or \ imp.is_frozen("__main__")) ICO_SMARTCARD = None ICO_READER = None # running from a script, i.e. not running from standalone exe built with py2exe if not main_is_frozen(): ICO_SMARTCARD = os.path.join( os.path.dirname(__file__), 'resources', 'smartcard.ico') ICO_READER = os.path.join( os.path.dirname(__file__), 'resources', 'reader.ico') # runing from a standalone exe built with py2exe # resources expected images directory else: if os.path.exists(os.path.join("images", 'smartcard.ico')): ICO_SMARTCARD = os.path.join("images", 'smartcard.ico') if os.path.exists(os.path.join("images", 'reader.ico')): ICO_READER = os.path.join("images", 'reader.ico') pyscard-1.6.14/smartcard/wx/SimpleSCardAppFrame.py0000644000175000017500000003146311747776676023623 0ustar rousseaurousseau00000000000000"""Simple wxpython frame for smart card application. __author__ = "gemalto http://www.gemalto.com" __date__ = "November 2006" __version__ = "1.4.0" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 os.path import wx import smartcard.wx import APDUTracerPanel import CardAndReaderTreePanel import ReaderToolbar import smartcard from smartcard.wx.SimpleSCardAppEventObserver import \ SimpleSCardAppEventObserver [ wxID_SIMPLESCARDAPP_FRAME, ] = map(lambda x: wx.NewId(), range(1)) class BlankPanel(wx.Panel, SimpleSCardAppEventObserver): '''A blank panel in case no panel is provided to SimpleSCardApp.''' def __init__(self, parent): wx.Panel.__init__(self, parent, -1) sizer = wx.GridSizer(1, 1) self.SetSizer(sizer) self.SetAutoLayout(True) class TreeAndUserPanelPanel(wx.Panel): '''The panel that contains the Card/Reader TreeCtrl and the user provided Panel.''' def __init__(self, parent, apppanelclass, appstyle): """ Constructor. Creates the panel with two panels: the left-hand panel is holding the smartcard and/or reader tree the right-hand panel is holding the application dialog apppanelclass: the class of the panel to instantiate in the SimpleSCardAppFrame appstyle: a combination of the following styles (bitwise or |) TR_SMARTCARD: display a smartcard tree panel TR_READER: display a reader tree panel TB_SMARTCARD: display a smartcard toolbar TB_SMARTCARD: display a reader toolbar default is TR_DEFAULT = TR_SMARTCARD """ wx.Panel.__init__(self, parent, -1) self.parent = parent self.selectedcard = None boxsizer = wx.BoxSizer(wx.HORIZONTAL) # create user dialog if None != apppanelclass: self.dialogpanel = apppanelclass(self) else: self.dialogpanel = BlankPanel(self) # create card/reader tree control if appstyle & smartcard.wx.SimpleSCardApp.TR_SMARTCARD or \ appstyle & smartcard.wx.SimpleSCardApp.TR_READER: self.readertreepanel = \ CardAndReaderTreePanel.CardAndReaderTreePanel( self, appstyle, self.dialogpanel) boxsizer.Add(self.readertreepanel, 1, wx.EXPAND | wx.ALL, 5) boxsizer.Add(self.dialogpanel, 2, wx.EXPAND | wx.ALL) if appstyle & smartcard.wx.SimpleSCardApp.TR_READER: self.Bind( wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivateReader, self.readertreepanel.readertreectrl) self.Bind( wx.EVT_TREE_SEL_CHANGED, self.OnSelectReader, self.readertreepanel.readertreectrl) self.Bind( wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnReaderRightClick, self.readertreepanel.readertreectrl) self.Bind( wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, self.readertreepanel.readertreectrl) if appstyle & smartcard.wx.SimpleSCardApp.TR_SMARTCARD: self.Bind( wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivateCard, self.readertreepanel.cardtreectrl) self.Bind( wx.EVT_TREE_SEL_CHANGED, self.OnSelectCard, self.readertreepanel.cardtreectrl) self.Bind( wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnCardRightClick, self.readertreepanel.cardtreectrl) self.SetSizer(boxsizer) self.SetAutoLayout(True) def ActivateCard(self, card): """Activate a card.""" if not hasattr(card, 'connection'): card.connection = card.createConnection() if None != self.parent.apdutracerpanel: card.connection.addObserver(self.parent.apdutracerpanel) card.connection.connect() self.dialogpanel.OnActivateCard(card) def DeactivateCard(self, card): """Deactivate a card.""" if hasattr(card, 'connection'): card.connection.disconnect() if None != self.parent.apdutracerpanel: card.connection.deleteObserver(self.parent.apdutracerpanel) delattr(card, 'connection') self.dialogpanel.OnDeactivateCard(card) def OnActivateCard(self, event): """Called when the user activates a card in the tree.""" item = event.GetItem() if item: itemdata = self.readertreepanel.cardtreectrl.GetItemPyData(item) if isinstance(itemdata, smartcard.Card.Card): self.ActivateCard(itemdata) else: self.dialogpanel.OnDeselectCard(itemdata) def OnActivateReader(self, event): """Called when the user activates a reader in the tree.""" item = event.GetItem() if item: itemdata = self.readertreepanel.readertreectrl.GetItemPyData(item) if isinstance(itemdata, smartcard.Card.Card): self.ActivateCard(itemdata) elif isinstance(itemdata, smartcard.reader.Reader.Reader): self.dialogpanel.OnActivateReader(itemdata) event.Skip() def OnItemCollapsed(self, event): item = event.GetItem() self.readertreepanel.readertreectrl.Expand(item) def OnCardRightClick(self, event): """Called when user right-clicks a node in the card tree control.""" item = event.GetItem() if item: itemdata = self.readertreepanel.cardtreectrl.GetItemPyData(item) if isinstance(itemdata, smartcard.Card.Card): self.selectedcard = itemdata if not hasattr(self, "connectID"): self.connectID = wx.NewId() self.disconnectID = wx.NewId() self.Bind(wx.EVT_MENU, self.OnConnect, id=self.connectID) self.Bind( wx.EVT_MENU, self.OnDisconnect, id=self.disconnectID) menu = wx.Menu() if not hasattr(self.selectedcard, 'connection'): menu.Append(self.connectID, "Connect") else: menu.Append(self.disconnectID, "Disconnect") self.PopupMenu(menu) menu.Destroy() def OnReaderRightClick(self, event): """Called when user right-clicks a node in the reader tree control.""" item = event.GetItem() if item: itemdata = self.readertreepanel.readertreectrl.GetItemPyData(item) if isinstance(itemdata, smartcard.Card.Card): self.selectedcard = itemdata if not hasattr(self, "connectID"): self.connectID = wx.NewId() self.disconnectID = wx.NewId() self.Bind(wx.EVT_MENU, self.OnConnect, id=self.connectID) self.Bind( wx.EVT_MENU, self.OnDisconnect, id=self.disconnectID) menu = wx.Menu() if not hasattr(self.selectedcard, 'connection'): menu.Append(self.connectID, "Connect") else: menu.Append(self.disconnectID, "Disconnect") self.PopupMenu(menu) menu.Destroy() def OnConnect(self, event): if isinstance(self.selectedcard, smartcard.Card.Card): self.ActivateCard(self.selectedcard) def OnDisconnect(self, event): if isinstance(self.selectedcard, smartcard.Card.Card): self.DeactivateCard(self.selectedcard) def OnSelectCard(self, event): """Called when the user selects a card in the tree.""" item = event.GetItem() if item: itemdata = self.readertreepanel.cardtreectrl.GetItemPyData(item) if isinstance(itemdata, smartcard.Card.Card): self.dialogpanel.OnSelectCard(itemdata) else: self.dialogpanel.OnDeselectCard(itemdata) def OnSelectReader(self, event): """Called when the user selects a reader in the tree.""" item = event.GetItem() if item: itemdata = self.readertreepanel.readertreectrl.GetItemPyData(item) if isinstance(itemdata, smartcard.Card.Card): self.dialogpanel.OnSelectCard(itemdata) elif isinstance(itemdata, smartcard.reader.Reader.Reader): self.dialogpanel.OnSelectReader(itemdata) else: self.dialogpanel.OnDeselectCard(itemdata) class SimpleSCardAppFrame(wx.Frame): """The main frame of the simple smartcard application.""" def __init__(self, appname, apppanelclass, appstyle, appicon, pos=(-1, -1), size=(-1, -1), ): """ Constructor. Creates the frame with two panels: the left-hand panel is holding the smartcard and/or reader tree the right-hand panel is holding the application dialog appname: name of the application apppanelclass: the class of the panel to instantiate in the SimpleSCardAppFrame appstyle: a combination of the following styles (bitwise or |) TR_SMARTCARD: display a smartcard tree panel TR_READER: display a reader tree panel TB_SMARTCARD: display a smartcard toolbar TB_SMARTCARD: display a reader toolbar PANEL_APDUTRACER: display an APDU tracer panel default is TR_DEFAULT = TR_SMARTCARD pos: the application position as a (x,y) tupple; default is (-1,-1) size: the application window size as a (x,y) tuple; default is (-1,-1) style: the frame wx.Frame style """ wx.Frame.__init__(self, None, wxID_SIMPLESCARDAPP_FRAME, appname, pos=pos, size=size, style=wx.DEFAULT_FRAME_STYLE) if appicon: _icon = wx.Icon(appicon, wx.BITMAP_TYPE_ICO) self.SetIcon(_icon) elif os.path.exists(smartcard.wx.ICO_SMARTCARD): _icon = wx.Icon(smartcard.wx.ICO_SMARTCARD, wx.BITMAP_TYPE_ICO) self.SetIcon(_icon) boxsizer = wx.BoxSizer(wx.VERTICAL) self.treeuserpanel = TreeAndUserPanelPanel( self, apppanelclass, appstyle) boxsizer.Add(self.treeuserpanel, 3, wx.EXPAND | wx.ALL) # create a toolbar if required if appstyle & smartcard.wx.SimpleSCardApp.TB_SMARTCARD: self.toolbar = ReaderToolbar.ReaderToolbar(self) self.SetToolBar(self.toolbar) else: self.toolbar = None # create an apdu tracer console if required if appstyle & smartcard.wx.SimpleSCardApp.PANEL_APDUTRACER: self.apdutracerpanel = APDUTracerPanel.APDUTracerPanel(self) boxsizer.Add(self.apdutracerpanel, 1, wx.EXPAND | wx.ALL) else: self.apdutracerpanel = None self.SetSizer(boxsizer) self.SetAutoLayout(True) self.Bind(wx.EVT_CLOSE, self.OnCloseFrame) if appstyle & smartcard.wx.SimpleSCardApp.TB_SMARTCARD: self.Bind( wx.EVT_COMBOBOX, self.OnReaderComboBox, self.toolbar.readercombobox) def OnCloseFrame(self, evt): """Called when frame is closed, i.e. on wx.EVT_CLOSE""" evt.Skip() def OnExit(self, evt): """Called when frame application exits.""" self.Close(True) evt.Skip() def OnReaderComboBox(self, event): """Called when the user activates a reader in the toolbar combo box.""" cb = event.GetEventObject() reader = cb.GetClientData(cb.GetSelection()) if isinstance(reader, smartcard.reader.Reader.Reader): self.treeuserpanel.dialogpanel.OnActivateReader(reader) pyscard-1.6.14/smartcard/wx/SimpleSCardAppEventObserver.py0000644000175000017500000000413411747776676025355 0ustar rousseaurousseau00000000000000"""Smartcard event observer. __author__ = "gemalto http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ class SimpleSCardAppEventObserver(object): """This interface defines the event handlers called by the SimpleSCardApp.""" def __init__(self): self.selectedcard = None self.selectedreader = None # callbacks from SimpleCardAppFrame controls def OnActivateCard(self, card): """Called when a card is activated in the reader tree control or toolbar.""" self.selectedcard = card def OnActivateReader(self, reader): """Called when a reader is activated in the reader tree control or toolbar.""" self.selectedreader = reader def OnDeactivateCard(self, card): """Called when a card is deactivated in the reader tree control or toolbar.""" pass def OnDeselectCard(self, card): """Called when a card is selected in the reader tree control or toolbar.""" self.selectedcard = None def OnSelectCard(self, card): """Called when a card is selected in the reader tree control or toolbar.""" self.selectedcard = card def OnSelectReader(self, reader): """Called when a reader is selected in the reader tree control or toolbar.""" self.selectedreader = reader pyscard-1.6.14/smartcard/wx/resources/0000755000175000017500000000000011747777125021460 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/wx/resources/reader.ico0000644000175000017500000000047610633575647023423 0ustar rousseaurousseau00000000000000(( €€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿ`ff`p38†`x ³€€ˆp€`xˆˆp€ˆˆˆ‡pxxˆˆˆ‡ppˆ‡xˆˆˆpxˆ‡xˆ‡xˆ‡xpxˆ‡pxpÿŸÿøðâĈ @€àÈž?¿ÿÿpyscard-1.6.14/smartcard/wx/resources/smartcard.ico0000644000175000017500000000047610633575647024141 0ustar rousseaurousseau00000000000000(( €€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³333s333»»»»{»»³·wwwwwws·»·»»{»s·»·»»{»s·ww»»wwsw»·»»{»ww»·»»{»w·»·»»{»s·ww»»wws·»·»»{»s·»·»»{»s·ww{wwws»»»»{»»³»»»»{»»»pyscard-1.6.14/smartcard/wx/APDUTracerPanel.py0000644000175000017500000000512511747776676022707 0ustar rousseaurousseau00000000000000"""Graphical APDU Tracer. __author__ = "gemalto http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ # wxPython GUI modules (http://www.wxpython.org) import wx from smartcard.CardConnectionObserver import CardConnectionObserver from smartcard.util import toHexString [ wxID_APDUTEXTCTRL, ] = map(lambda x: wx.NewId(), range(1)) class APDUTracerPanel(wx.Panel, CardConnectionObserver): def __init__(self, parent): wx.Panel.__init__(self, parent, -1) boxsizer = wx.BoxSizer(wx.HORIZONTAL) self.apdutextctrl = wx.TextCtrl( self, wxID_APDUTEXTCTRL, "", pos=wx.DefaultPosition, style=wx.TE_MULTILINE | wx.TE_READONLY) boxsizer.Add(self.apdutextctrl, 1, wx.EXPAND | wx.ALL, 5) self.SetSizer(boxsizer) self.SetAutoLayout(True) self.Bind(wx.EVT_TEXT_MAXLEN, self.OnMaxLength, self.apdutextctrl) def OnMaxLength(self, evt): '''Reset text buffer when max length is reached.''' self.apdutextctrl.SetValue("") evt.Skip() def update(self, cardconnection, ccevent): '''CardConnectionObserver callback.''' apduline = "" if 'connect' == ccevent.type: apduline += 'connecting to ' + cardconnection.getReader() elif 'disconnect' == ccevent.type: apduline += 'disconnecting from ' + cardconnection.getReader() elif 'command' == ccevent.type: apduline += '> ' + toHexString(ccevent.args[0]) elif 'response' == ccevent.type: if [] == ccevent.args[0]: apduline += "< %-2X %-2X" % tuple(ccevent.args[-2:]) else: apduline += "< " + toHexString(ccevent.args[0]) + \ "%-2X %-2X" % tuple(ccevent.args[-2:]) self.apdutextctrl.AppendText(apduline + "\n") pyscard-1.6.14/smartcard/wx/CardAndReaderTreePanel.py0000644000175000017500000004006511747776676024256 0ustar rousseaurousseau00000000000000"""wxPython panel display cards/readers as a TreeCtrl. __author__ = "gemalto http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ # smartcard imports from threading import RLock from smartcard.Exceptions import CardConnectionException, NoCardException from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver from smartcard.CardMonitoring import CardMonitor, CardObserver from smartcard.util import toHexString import smartcard.wx.SimpleSCardApp from smartcard.wx import ICO_SMARTCARD, ICO_READER # wxPython GUI modules (http://www.wxpython.org) import wx class BaseCardTreeCtrl(wx.TreeCtrl): """Base class for the smart card and reader tree controls.""" def __init__(self, parent, ID=wx.NewId(), pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, clientpanel=None): """Constructor. Initializes a smartcard or reader tree control.""" wx.TreeCtrl.__init__( self, parent, ID, pos, size, wx.TR_SINGLE | wx.TR_NO_BUTTONS) self.clientpanel = clientpanel self.parent = parent isz = (16, 16) il = wx.ImageList(isz[0], isz[1]) self.capindex = il.Add( wx.ArtProvider_GetBitmap(wx.ART_HELP_BOOK, wx.ART_OTHER, isz)) self.fldrindex = il.Add( wx.ArtProvider_GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz)) self.fldropenindex = il.Add( wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, isz)) if None != ICO_SMARTCARD: self.cardimageindex = il.Add( wx.Bitmap(ICO_SMARTCARD, wx.BITMAP_TYPE_ICO)) if None != ICO_READER: self.readerimageindex = il.Add( wx.Bitmap(ICO_READER, wx.BITMAP_TYPE_ICO)) self.il = il self.SetImageList(self.il) def Repaint(self): self.Refresh() wx.PostEvent(self, wx.PaintEvent()) class CardTreeCtrl(BaseCardTreeCtrl): """The CardTreeCtrl monitors inserted cards and notifies the application client dialog of any card activation.""" def __init__(self, parent, ID=wx.NewId(), pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, clientpanel=None): """Constructor. Create a smartcard tree control.""" BaseCardTreeCtrl.__init__(self, parent, ID, pos, size, wx.TR_SINGLE | wx.TR_NO_BUTTONS, clientpanel) self.root = self.AddRoot("Smartcards") self.SetPyData(self.root, None) self.SetItemImage(self.root, self.fldrindex, wx.TreeItemIcon_Normal) self.SetItemImage( self.root, self.fldropenindex, wx.TreeItemIcon_Expanded) self.Expand(self.root) def OnAddCards(self, addedcards): """Called when a card is inserted. Adds a smart card to the smartcards tree.""" parentnode = self.root for cardtoadd in addedcards: childCard = self.AppendItem(parentnode, toHexString(cardtoadd.atr)) self.SetItemText(childCard, toHexString(cardtoadd.atr)) self.SetPyData(childCard, cardtoadd) self.SetItemImage( childCard, self.cardimageindex, wx.TreeItemIcon_Normal) self.SetItemImage( childCard, self.cardimageindex, wx.TreeItemIcon_Expanded) self.Expand(childCard) self.Expand(self.root) self.EnsureVisible(self.root) self.Repaint() def OnRemoveCards(self, removedcards): """Called when a card is removed. Removes a card from the tree.""" parentnode = self.root for cardtoremove in removedcards: (childCard, cookie) = self.GetFirstChild(parentnode) while childCard.IsOk(): if self.GetItemText(childCard) == \ toHexString(cardtoremove.atr): self.Delete(childCard) (childCard, cookie) = self.GetNextChild(parentnode, cookie) self.Expand(self.root) self.EnsureVisible(self.root) self.Repaint() class ReaderTreeCtrl(BaseCardTreeCtrl): """The ReaderTreeCtrl monitors inserted cards and readers and notifies the application client dialog of any card activation.""" def __init__(self, parent, ID=wx.NewId(), pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, clientpanel=None): """Constructor. Create a reader tree control.""" BaseCardTreeCtrl.__init__( self, parent, ID, pos, size, wx.TR_SINGLE | wx.TR_NO_BUTTONS, clientpanel) self.mutex = RLock() self.root = self.AddRoot("Smartcard Readers") self.SetPyData(self.root, None) self.SetItemImage( self.root, self.fldrindex, wx.TreeItemIcon_Normal) self.SetItemImage( self.root, self.fldropenindex, wx.TreeItemIcon_Expanded) self.Expand(self.root) def AddATR(self, readernode, atr): """Add an ATR to a reader node.""" capchild = self.AppendItem(readernode, atr) self.SetPyData(capchild, None) self.SetItemImage( capchild, self.cardimageindex, wx.TreeItemIcon_Normal) self.SetItemImage( capchild, self.cardimageindex, wx.TreeItemIcon_Expanded) self.Expand(capchild) return capchild def GetATR(self, reader): """Return the ATR of the card inserted into the reader.""" atr = "no card inserted" try: if not type(reader) is str: connection = reader.createConnection() connection.connect() atr = toHexString(connection.getATR()) connection.disconnect() except NoCardException: pass except CardConnectionException: pass return atr def OnAddCards(self, addedcards): """Called when a card is inserted. Adds the smart card child to the reader node.""" self.mutex.acquire() try: parentnode = self.root for cardtoadd in addedcards: (childReader, cookie) = self.GetFirstChild(parentnode) found = False while childReader.IsOk() and not found: if self.GetItemText(childReader) == str(cardtoadd.reader): (childCard, cookie2) = self.GetFirstChild(childReader) self.SetItemText(childCard, toHexString(cardtoadd.atr)) self.SetPyData(childCard, cardtoadd) found = True else: (childReader, cookie) = self.GetNextChild( parentnode, cookie) # reader was not found, add reader node # this happens when card monitoring thread signals # added cards before reader monitoring thread signals # added readers if not found: childReader = self.AppendItem( parentnode, str(cardtoadd.reader)) self.SetPyData(childReader, cardtoadd.reader) self.SetItemImage( childReader, self.readerimageindex, wx.TreeItemIcon_Normal) self.SetItemImage( childReader, self.readerimageindex, wx.TreeItemIcon_Expanded) childCard = self.AddATR( childReader, toHexString(cardtoadd.atr)) self.SetPyData(childCard, cardtoadd) self.Expand(childReader) self.Expand(self.root) finally: self.mutex.release() self.EnsureVisible(self.root) self.Repaint() def OnAddReaders(self, addedreaders): """Called when a reader is inserted. Adds the smart card reader to the smartcard readers tree.""" self.mutex.acquire() try: parentnode = self.root for readertoadd in addedreaders: # is the reader already here? found = False (childReader, cookie) = self.GetFirstChild(parentnode) while childReader.IsOk() and not found: if self.GetItemText(childReader) == str(readertoadd): found = True else: (childReader, cookie) = self.GetNextChild( parentnode, cookie) if not found: childReader = self.AppendItem(parentnode, str(readertoadd)) self.SetPyData(childReader, readertoadd) self.SetItemImage( childReader, self.readerimageindex, wx.TreeItemIcon_Normal) self.SetItemImage( childReader, self.readerimageindex, wx.TreeItemIcon_Expanded) self.AddATR( childReader, self.GetATR(readertoadd)) self.Expand(childReader) self.Expand(self.root) finally: self.mutex.release() self.EnsureVisible(self.root) self.Repaint() def OnRemoveCards(self, removedcards): """Called when a card is removed. Removes the card from the tree.""" self.mutex.acquire() try: parentnode = self.root for cardtoremove in removedcards: (childReader, cookie) = self.GetFirstChild(parentnode) found = False while childReader.IsOk() and not found: if self.GetItemText(childReader) == \ str(cardtoremove.reader): (childCard, cookie2) = self.GetFirstChild(childReader) self.SetItemText(childCard, 'no card inserted') found = True else: (childReader, cookie) = \ self.GetNextChild(parentnode, cookie) self.Expand(self.root) finally: self.mutex.release() self.EnsureVisible(self.root) self.Repaint() def OnRemoveReaders(self, removedreaders): """Called when a reader is removed. Removes the reader from the smartcard readers tree.""" self.mutex.acquire() try: parentnode = self.root for readertoremove in removedreaders: (childReader, cookie) = self.GetFirstChild(parentnode) while childReader.IsOk(): if self.GetItemText(childReader) == str(readertoremove): self.Delete(childReader) else: (childReader, cookie) = \ self.GetNextChild(parentnode, cookie) self.Expand(self.root) finally: self.mutex.release() self.EnsureVisible(self.root) self.Repaint() class CardAndReaderTreePanel(wx.Panel): """Panel containing the smart card and reader tree controls.""" class _CardObserver(CardObserver): """Inner CardObserver. Gets notified of card insertion removal by the CardMonitor.""" def __init__(self, cardtreectrl): self.cardtreectrl = cardtreectrl def update(self, observable, (addedcards, removedcards)): """CardObserver callback that is notified when cards are added or removed.""" self.cardtreectrl.OnRemoveCards(removedcards) self.cardtreectrl.OnAddCards(addedcards) class _ReaderObserver(ReaderObserver): """Inner ReaderObserver. Gets notified of reader insertion/removal by the ReaderMonitor.""" def __init__(self, readertreectrl): self.readertreectrl = readertreectrl def update(self, observable, (addedreaders, removedreaders)): """ReaderObserver callback that is notified when readers are added or removed.""" self.readertreectrl.OnRemoveReaders(removedreaders) self.readertreectrl.OnAddReaders(addedreaders) def __init__(self, parent, appstyle, clientpanel): """Constructor. Create a smartcard and reader tree control on the left-hand side of the application main frame. parent: the tree panel parent appstyle: a combination of the following styles (bitwise or |) TR_SMARTCARD: display a smartcard tree panel TR_READER: display a reader tree panel default is TR_DEFAULT = TR_SMARTCARD clientpanel: the client panel to notify of smartcard and reader events """ wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS) sizer = wx.BoxSizer(wx.VERTICAL) # create the smartcard tree if appstyle & smartcard.wx.SimpleSCardApp.TR_SMARTCARD: self.cardtreectrl = CardTreeCtrl(self, clientpanel=clientpanel) # create the smartcard insertion observer self.cardtreecardobserver = self._CardObserver(self.cardtreectrl) # register as a CardObserver; we will ge # notified of added/removed cards self.cardmonitor = CardMonitor() self.cardmonitor.addObserver(self.cardtreecardobserver) sizer.Add( self.cardtreectrl, flag=wx.EXPAND | wx.ALL, proportion=1) # create the reader tree if appstyle & smartcard.wx.SimpleSCardApp.TR_READER: self.readertreectrl = ReaderTreeCtrl( self, clientpanel=clientpanel) # create the reader insertion observer self.readertreereaderobserver = self._ReaderObserver( self.readertreectrl) # register as a ReaderObserver; we will ge # notified of added/removed readers self.readermonitor = ReaderMonitor() self.readermonitor.addObserver(self.readertreereaderobserver) # create the smartcard insertion observer self.readertreecardobserver = self._CardObserver( self.readertreectrl) # register as a CardObserver; we will get # notified of added/removed cards self.cardmonitor = CardMonitor() self.cardmonitor.addObserver(self.readertreecardobserver) sizer.Add( self.readertreectrl, flag=wx.EXPAND | wx.ALL, proportion=1) self.SetSizer(sizer) self.SetAutoLayout(True) def OnDestroy(self, event): """Called on panel destruction.""" # deregister observers if hasattr(self, cardmonitor): self.cardmonitor.deleteObserver(self.cardtreecardobserver) if hasattr(self, readermonitor): self.readermonitor.deleteObserver(self.readertreereaderobserver) self.cardmonitor.deleteObserver(self.readertreecardobserver) event.Skip() pyscard-1.6.14/smartcard/ExclusiveConnectCardConnection.py0000644000175000017500000000621111747776700025453 0ustar rousseaurousseau00000000000000"""CardConnectionDecorator that provides exclusive use of a card. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardConnection import CardConnection from smartcard.CardConnectionDecorator import CardConnectionDecorator from smartcard.Exceptions import CardConnectionException from smartcard.scard import SCardConnect, SCardDisconnect from smartcard.scard import SCARD_LEAVE_CARD, SCARD_SHARE_EXCLUSIVE from smartcard.scard import SCardGetErrorMessage from smartcard.pcsc import PCSCCardConnection import smartcard.pcsc class ExclusiveConnectCardConnection(CardConnectionDecorator): '''This decorator uses exclusive access to the card during connection to prevent other processes to connect to this card.''' def __init__(self, cardconnection): CardConnectionDecorator.__init__(self, cardconnection) def connect(self, protocol=None, mode=None, disposition=None): '''Disconnect and reconnect in exclusive mode PCSCCardconnections.''' CardConnectionDecorator.connect(self, protocol, mode, disposition) component = self.component while True: if isinstance( component, smartcard.pcsc.PCSCCardConnection.PCSCCardConnection): pcscprotocol = PCSCCardConnection.translateprotocolmask( protocol) if 0 == pcscprotocol: pcscprotocol = component.getProtocol() if None != component.hcard: hresult = SCardDisconnect(component.hcard, SCARD_LEAVE_CARD) if hresult != 0: raise CardConnectionException('Failed to disconnect: ' + SCardGetErrorMessage(hresult)) hresult, component.hcard, dwActiveProtocol = SCardConnect( component.hcontext, str(component.reader), SCARD_SHARE_EXCLUSIVE, pcscprotocol) if hresult != 0: raise CardConnectionException( 'Failed to connect with SCARD_SHARE_EXCLUSIVE' +\ SCardGetErrorMessage(hresult)) # print 'reconnected exclusive' break if hasattr(component, 'component'): component = component.component else: break pyscard-1.6.14/smartcard/Exceptions.py0000644000175000017500000000562611747776700021512 0ustar rousseaurousseau00000000000000"""Smartcard module exceptions. This module defines the exceptions raised by the smartcard module. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ class SmartcardException(Exception): """Base class for smartcard exceptions. smartcard exceptions are generated by the smartcard module and shield scard (i.e. PCSC) exceptions raised by the scard module. """ pass class CardConnectionException(SmartcardException): """Raised when a CardConnection class method fails.""" pass class CardRequestException(SmartcardException): """Raised when a CardRequest wait fails.""" pass class CardRequestTimeoutException(SmartcardException): """Raised when a CardRequest times out.""" def __init__(self, *args): SmartcardException.__init__(self, "Time-out during card request", *args) class CardServiceException(SmartcardException): """Raised when a CardService class method fails.""" pass class InvalidATRMaskLengthException(SmartcardException): """Raised when an ATR mask does not match an ATR length.""" def __init__(self, *args): SmartcardException.__init__(self, 'Invalid ATR mask length: ', *args) class InvalidReaderException(SmartcardException): """Raised when trying to acces an invalid smartcard reader.""" def __init__(self, *args): SmartcardException.__init__(self, 'Invalid reader: ', *args) class ListReadersException(SmartcardException): """Raised when smartcard readers cannot be listed.""" def __init__(self, *args): SmartcardException.__init__(self, 'Failed to list readers', *args) class NoCardException(SmartcardException): """Raised when no card in is present in reader.""" def __init__(self, *args): SmartcardException.__init__( self, 'Unable to connect to card or no card in reader', *args) class NoReadersException(SmartcardException): """Raised when the system has no smartcard reader.""" def __init__(self, *args): SmartcardException.__init__(self, 'No reader found', *args) pyscard-1.6.14/smartcard/ATR.py0000644000175000017500000002406711747776700020017 0ustar rousseaurousseau00000000000000"""ATR class managing some of the Answer To Reset content. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.Exceptions import SmartcardException class ATR(object): """ATR class.""" clockrateconversion = [372, 372, 558, 744, 1116, 1488, 1860, 'RFU', 'RFU', 512, 768, 1024, 1536, 2048, 'RFU', 'RFU', 'RFU'] bitratefactor = ['RFU', 1, 2, 4, 8, 16, 32, 'RFU', 12, 20, 'RFU', 'RFU', 'RFU', 'RFU', 'RFU', 'RFU'] currenttable = [25, 50, 100, 'RFU'] def __init__(self, bytes): """Construct a new atr from bytes.""" self.bytes = bytes self.__initInstance__() def __checksyncbyte__(self): """Check validity of TS.""" if not 0x3b == self.bytes[0] and not 0x03f == self.bytes[0]: raise SmartcardException("invalid TS 0x%-0.2x" % self.bytes[0]) def __initInstance__(self): """Parse ATR and initialize members: TS: initial character T0: format character TA[n], TB[n], TC[n], TD[n], for n=0,1,...: protocol parameters note: protocol parameters indices start at 0, e.g. TA[0], TA[1] correspond to the ISO standard TA1, TA2 parameters historicalBytes: the ATR T1, T2, ..., TK historical bytes TCK: checksum byte (only for protocols different from T=0) FI: clock rate conversion factor DI: voltage adjustment factor PI1: programming voltage factor II: maximum programming current factor N: extra guard time """ self.__checksyncbyte__() # initial character self.TS = self.bytes[0] # format character self.T0 = self.bytes[1] # count of historical bytes self.K = self.T0 & 0x0f # initialize optional characters lists self.TA = [] self.TB = [] self.TC = [] self.TD = [] self.Y = [] self.hasTA = [] self.hasTB = [] self.hasTC = [] self.hasTD = [] TD = self.T0 hasTD = 1 n = 0 offset = 1 self.interfaceBytesCount = 0 while hasTD: self.Y += [TD >> 4 & 0x0f] self.hasTD += [(self.Y[n] & 0x08) != 0] self.hasTC += [(self.Y[n] & 0x04) != 0] self.hasTB += [(self.Y[n] & 0x02) != 0] self.hasTA += [(self.Y[n] & 0x01) != 0] self.TA += [None] self.TB += [None] self.TC += [None] self.TD += [None] if self.hasTA[n]: self.TA[n] = self.bytes[offset + self.hasTA[n]] if self.hasTB[n]: self.TB[n] = self.bytes[offset + self.hasTA[n] + self.hasTB[n]] if self.hasTC[n]: self.TC[n] = self.bytes[offset +\ self.hasTA[n] +\ self.hasTB[n] +\ self.hasTC[n]] if self.hasTD[n]: self.TD[n] = self.bytes[offset +\ self.hasTA[n] +\ self.hasTB[n] +\ self.hasTC[n] +\ self.hasTD[n]] self.interfaceBytesCount += self.hasTA[n] +\ self.hasTB[n] +\ self.hasTC[n] +\ self.hasTD[n] TD = self.TD[n] hasTD = self.hasTD[n] offset = offset + self.hasTA[n] + self.hasTB[n] +\ self.hasTC[n] + self.hasTD[n] n = n + 1 # historical bytes self.historicalBytes = self.bytes[offset + 1:offset + 1 + self.K] # checksum self.hasChecksum = (len(self.bytes) == offset + 1 + self.K + 1) if self.hasChecksum: self.TCK = self.bytes[-1] checksum = 0 for b in self.bytes[1:]: checksum = checksum ^ b self.checksumOK = (checksum == 0) else: self.TCK = None # clock-rate conversion factor if self.hasTA[0]: self.FI = self.TA[0] >> 4 & 0x0f else: self.FI = None # bit-rate adjustment factor if self.hasTA[0]: self.DI = self.TA[0] & 0x0f else: self.DI = None # maximum programming current factor if self.hasTB[0]: self.II = self.TB[0] >> 5 & 0x03 else: self.II = None # programming voltage factor if self.hasTB[0]: self.PI1 = self.TB[0] & 0x1f else: self.PI1 = None # extra guard time self.N = self.TC[0] def getChecksum(self): """Return the checksum of the ATR. Checksum is mandatory only for T=1.""" return self.TCK def getHistoricalBytes(self): """Return historical bytes.""" return self.historicalBytes def getHistoricalBytesCount(self): """Return count of historical bytes.""" return len(self.historicalBytes) def getInterfaceBytesCount(self): """Return count of interface bytes.""" return self.interfaceBytesCount def getTA1(self): """Return TA1 byte.""" return self.TA[0] def getTB1(self): """Return TB1 byte.""" return self.TB[0] def getTC1(self): """Return TC1 byte.""" return self.TC[0] def getTD1(self): """Return TD1 byte.""" return self.TD[0] def getBitRateFactor(self): """Return bit rate factor.""" if self.DI != None: return ATR.bitratefactor[self.DI] else: return 1 def getClockRateConversion(self): """Return clock rate conversion.""" if self.FI != None: return ATR.clockrateconversion[self.FI] else: return 372 def getProgrammingCurrent(self): """Return maximum programming current.""" if self.II != None: return ATR.currenttable[self.II] else: return 50 def getProgrammingVoltage(self): """Return programming voltage.""" if self.PI1 != None: return 5 * (1 + self.PI1) else: return 5 def getGuardTime(self): """Return extra guard time.""" return self.N def getSupportedProtocols(self): """Returns a dictionnary of supported protocols.""" protocols = {} for td in self.TD: if td != None: strprotocol = "T=%d" % (td & 0x0F) protocols[strprotocol] = True if not self.hasTD[0]: protocols['T=0'] = True return protocols def isT0Supported(self): """Return True if T=0 is supported.""" protocols = self.getSupportedProtocols() return 'T=0' in protocols def isT1Supported(self): """Return True if T=1 is supported.""" protocols = self.getSupportedProtocols() return 'T=1' in protocols def isT15Supported(self): """Return True if T=15 is supported.""" protocols = self.getSupportedProtocols() return 'T=15' in protocols def dump(self): """Dump the details of an ATR.""" for i in range(0, len(self.TA)): if self.TA[i] != None: print "TA%d: %x" % (i + 1, self.TA[i]) if self.TB[i] != None: print "TB%d: %x" % (i + 1, self.TB[i]) if self.TC[i] != None: print "TC%d: %x" % (i + 1, self.TC[i]) if self.TD[i] != None: print "TD%d: %x" % (i + 1, self.TD[i]) print 'supported protocols', self.getSupportedProtocols() print 'T=0 supported', self.isT0Supported() print 'T=1 supported', self.isT1Supported() print 'checksum:', self.getChecksum() print '\tclock rate conversion factor:', self.getClockRateConversion() print '\tbit rate adjustment factor:', self.getBitRateFactor() print '\tmaximum programming current:', self.getProgrammingCurrent() print '\tprogramming voltage:', self.getProgrammingVoltage() print '\tguard time:', self.getGuardTime() print 'nb of interface bytes:', self.getInterfaceBytesCount() print 'nb of historical bytes:', self.getHistoricalBytesCount() def __str__(self): """Returns a string representation of the ATR as a strem of bytes.""" return reduce(lambda a, b: a + \ "%-0.2X " % ((b + 256) % 256), self.bytes, '') if __name__ == '__main__': """Small sample illustrating the use of ATR.""" atrs = [[0x3F, 0x65, 0x25, 0x00, 0x2C, 0x09, 0x69, 0x90, 0x00], [0x3F, 0x65, 0x25, 0x08, 0x93, 0x04, 0x6C, 0x90, 0x00], [0x3B, 0x16, 0x94, 0x7C, 0x03, 0x01, 0x00, 0x00, 0x0D], [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03], [0x3B, 0xE3, 0x00, 0xFF, 0x81, 0x31, 0x52, 0x45, 0xA1, 0xA2, 0xA3, 0x1B], [0x3B, 0xE5, 0x00, 0x00, 0x81, 0x21, 0x45, 0x9C, 0x10, 0x01, 0x00, 0x80, 0x0D]] for atr in atrs: a = ATR(atr) print 80 * '-' print a a.dump() print reduce(lambda a, b: a + \ "%-0.2X " % ((b + 256) % 256), a.getHistoricalBytes(), '') pyscard-1.6.14/smartcard/System.py0000644000175000017500000000370311747776700020647 0ustar rousseaurousseau00000000000000"""Smartcard system utility functions and classes. Manages smartcard readers and reader groups. __author__ = "gemalto http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 smartcard.reader.ReaderFactory import smartcard.pcsc.PCSCReaderGroups def readers(groups=[]): """Returns the list of smartcard readers in groups. If group is not specified, returns the list of all smartcard readers. import smartcard r=smartcard.readers() r=smartcard.readers(['SCard$DefaultReaders', 'MyReaderGroup']) """ return smartcard.reader.ReaderFactory.ReaderFactory.readers(groups) def readergroups(): """Returns the list of reader groups.""" return smartcard.pcsc.PCSCReaderGroups.PCSCReaderGroups().instance # for legacy only def listReaders(): """Returns the list of smartcard readers. Deprecated - Use smartcard.System.readers() instead. """ zreaders = [] for reader in readers(): zreaders.append(str(reader)) return zreaders if __name__ == '__main__': try: print readers() print readers(['SCard$DefaultReaders']) print readergroups() except: import sys print sys.exc_info()[1] pyscard-1.6.14/smartcard/doc/0000755000175000017500000000000011747777125017555 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/doc/images/0000755000175000017500000000000011747777125021022 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/doc/images/pyscard.jpg0000644000175000017500000006177510736220424023167 0ustar rousseaurousseau00000000000000ÿØÿàJFIF``ÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀŒ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?÷ú(¢€ (¢€ (¢€ (¢€#œ‘o!iþUçÞðžwá-æãHµ–il`’I2YŒjI'ÔšôÿãÞ_÷ò®_Áÿò$è?ö·ÿÑkUXÏøBü5ÿ@K/ûô(ÿ„/Ã_ô²ÿ¿B·h«°Œ/øBü5ÿ@K/ûô(ÿ„/Ã_ô²ÿ¿B·h¢ÀaÂá¯úYß¡Gü!~ÿ %—ýú»E þ¿ ÐËþý ?á ð×ý,¿ïЭÚ(°_ð…økþ€–_÷èQÿ_†¿è eÿ~…nÑE€Âÿ„/Ã_ô²ÿ¿BøBü5ÿ@K/ûô+vŠ,ü!~ÿ %—ýúÂá¯úYß¡[´Q`0¿á ð×ý,¿ïУþ¿ ÐËþý Ý¢‹…ÿ_†¿è eÿ~…ð…økþ€–_÷èVíX /øBü5ÿ@K/ûô(ÿ„/Ã_ô²ÿ¿B·h¢ÀaÂá¯úYß¡Gü!~ÿ %—ýú»E þ¿ ÐËþý ?á ð×ý,¿ïЭÚ(°_ð…økþ€–_÷èQÿ_†¿è eÿ~…nÑE€Âÿ„/Ã_ô²ÿ¿BøBü5ÿ@K/ûô+vŠ,â/ x~Ûôði‘ËœÎޱà«$ïšîìIk bI$Ĥ“ôÏx§þEkþ¼'ÿÑm]‡üƒ­¿ë’!Q"‘bŠ(©QEQEQEQEQEQEQEQEÿñï/û‡ùW/àÿùtû[ÿèµ®¢ø÷—ýÃü«—ðü‰:ýƒ­ÿôZÕD™TQEY!EPEPEPEPEPEPEPEPEPEPEPEPEPOŠäQÖ¿ëÂýÕÐXÈ:Ûþ¹'òÏø§þEkþ¼'ÿÑm]‡üƒ­¿ë’!Q"¢X¢Š*J (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€#Ÿþ=åÿpÿ*åüÿ"Nƒÿ`ëýµÔOÿòÿ¸•rþÿ‘'Aÿ°u¿þ‹Z¨“#jŠ(«$(¢Š(¢Š(¢¸kï‰PÛ_k6–º«|Ú;¶I ¦ÔLXÜô•ÐßøþÎ¥C¥é÷š­ö§l.àµ·Ú ÂFw9' éß‘EÂÇ]EqR|MÒ"ðìz»Ú_ôõÓçµ1: PËžÞÞµ@ñŒzÖ¹¢Üi—šn¡h‹1†çißèÀ©#Óz.MErþ!ñ¤Z&³o£ÛéÓßê3@n1É»Ž ‘’H (ɤÔ|o ž–cÒuµ-SwÙ´ÓŽo—ï—Ü@PsEÀêh®6ëâ5•‡‡áÕ¯´½Jß}ð°’ÙábIÏNpÃŽ óUí|Tóxª{«§Èt‰®ŸM•P  )]Äç;ÈvÁ¢ácº¢¼þÏâµÌeôº.©m¤ê‹xïæDòÖRH€Äãƒótüª–—ñ*æ=kÅòkVWQizI_/dKû 8Úß6K¹ ŽÜv¢è,zmÍøoÅrëó˜¥Ñ/¬”Â'ŠáŠK ŠqÀ‘ ¹û§šé(¢Š(QEQE“âŸùu¯úðŸÿEµtò¶ÿ®Iü…sþ)ÿ‘GZÿ¯ ÿô[WAaÿ ëoúäŸÈTH¨–(¢Š’‚Š( Š( Š( Š( Š( Š( Š( Š( çÿyÜ?ʹÿÈ“ ÿØ:ßÿE­uÿǼ¿îå\¿ƒÿäIÐìoÿ¢Öª$ÈÚ¢Š*É (¢€ (¢€ ñÍ6×Äwž.øƒm É§(¸¹HfûfðSr0¥s’x#Ò½Ž"«3·RZâž<Ñí¼?áß xoI¾'Ä–ù¶·TS¾X§VI[9=xÅuþ#ðEóé^ƒÃÏh%Ðn#‘ë*’\d휌‘ß'šîÌhd]à`69§R°\â“€›ÆÒ´Ö»µèU-ÀfÂ0„ÇóñÀÉíž+6?xƒFêz5Î&¥¦éCM¸‚ç•*Žr¬AϨ¯G¢‚皯ÃHéQ™¯-UŸ^W½uܱáI;Œô•Ôëöúç‹dµ¸ÒþÅ­ªÉ\Fee d#iS–óÔدAUTPª¡Tt`RÒ°\óøQмVÚ¼éºe·ÙÚ´Óf•ÒáÉÎö€¾ÀW¤QE0 (¢Q@Q@>)ÿ‘GZÿ¯ ÿô[WAaÿ ëoúäŸÈW?âŸùu¯úðŸÿEµtò¶ÿ®Iü…DЉbŠ(©((¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠŽø÷—ýÃü«—ðü‰:ýƒ­ÿôZ×Q?ü{ËþáþUËø?þDþÁÖÿú-j¢Lª(¢¬¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š('Å?ò(ë_õá?þ‹jè,?ämÿ\“ù çüSÿ"޵ÿ^ÿè¶®‚ÃþAÖßõÉ?¨‘Q,QE%Q@Q@Q@Q@Q@Q@Q@Q@Ïÿòÿ¸•rþÿ‘'Aÿ°u¿þ‹Zê'ÿyÜ?ʹÿÈ“ ÿØ:ßÿE­TI‘µEU’QEQEQEQEQEQEQEQEQEQEQEQEQEdø§þEkþ¼'ÿÑm]‡üƒ­¿ë’!\ÿŠäQÖ¿ëÂýÕÐXÈ:Ûþ¹'ò*%Š(¢¤ ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š( ‚2+Ÿÿ„Âô*hø.‡ÿ‰®‚Šçÿáðý šþ ¡ÿâhÿ„Áÿô*hø.‡ÿ‰®‚Šçÿáðý šþ ¡ÿâhÿ„Áÿô*hø.‡ÿ‰®‚Šçÿáðý šþ ¡ÿâhÿ„Áÿô*hø.‡ÿ‰®‚Šçÿáðý šþ ¡ÿâkºð—…u«†µ°ðÖŸmžî+•¥`yŽ6 áœ}9+¿yy&»4–vr4zj1K‹”83ÁŽ2:ÌÃè9É[ÑE¤0ƱƊÐØU$&ÎF/ xWC¸+{á­m.WÊÜKc5³ÑØ®JÑÝèxÁü žÿ¡SCÿÁt?üM]tY‘Ô2°ÁR2¬Ûk–ðã­½ÃÑØíŠV96‡²±ÿž~‡øz0A(‰2_øA<ÿB¦‡ÿ‚èøš?áðý šþ ¡ÿâk ¢¤£Ÿÿ„Áÿô*hø.‡ÿ‰£þOÿЩ¡ÿàºþ&º (Ÿÿ„Áÿô*hø.‡ÿ‰£þOÿЩ¡ÿàºþ&º (Ÿÿ„Áÿô*hø.‡ÿ‰£þOÿЩ¡ÿàºþ&º (Ÿÿ„Áÿô*hø.‡ÿ‰£þOÿЩ¡ÿàºþ&º (Ÿÿ„Áÿô*hø.‡ÿ‰£þOÿЩ¡ÿàºþ&º (Ÿÿ„Áÿô*hø.‡ÿ‰ª¯†|¦BŸñHè“ÝLvÛÛ¦Ÿé[þùञ®ƒTÕ"Ó BQ¦¸•¶AnŸ~Vôƒ¹'€95›ce*O%õô‹6¡2ív_»õ¦z(õêǓؕÄÝŽgþƈ#ûXÑôc©oó6$û1ã^͸ Ž7cvyö­/à Ôàr<#¢ÃqlžÝôøwÄÞ‡åäwpG"·*…õŒ’N—Ö2ˆ5—j9û²/_.AÝPyóN=„˜¿ð‚x?þ…MÿÐÿñ4 àÿú4?üCÿÄÖŽ•ªÇ©Âÿ#Au Ûqnçæ‰¿¨=AWê 9ÿøA<ÿB¦‡ÿ‚èøšß*…PÔ´PEPEPEPEPEPEPEPEPEPEPEPEP\ååäšìÒYÙÈÑé¨Å..PàÌG8Èè;3 ç%z>£¹ÿøA| NO…4?üEÿÄЀ·QÁ C kh¡Q`(…>°õ¯xJ- P’? èˆém#+.Ÿ …8 í«Ú)'AÓ‰9&Ö>à"´Nä5bõ#¢ÈŒŽ¡•† ‘E2n “ýÓü«ð—‚ü+uàÍ âãÃ:4³K§Û¼’Ia3±I$•É$÷¡»W4í®[ÃŽ¶÷ [Gc¶)XäÚÊÇþyúáèxÁ-sÿð‚x?þ…MÿÐÿñ5¾ˆ±¢¢(TQ…Uz †X´QE (¢€ (¢€ (¢€ £ªj‘ivêÌ­,ò¶È-ãûò¿ þdžÉ5z³uOéÓÄúžmvð‚#ic Td®å@,¬¥~ë.¡*í%~ä)×ËLöõ=Xò{~¨ÿ á3÷ü7¥KéæÚ#ãé¸VU¾¥è¾;ht­6ÎÂ)4ÀÒ%¬ r%À$(5j] hè袹ËÝLÖ|we©§Z_Bšdî‘Ý@²ª·›È *›°‘«}c$“G{e*Á¨B0’•uîŽ;©üÁäV†•ª¦§«F`»„…¸¶c–»sÝOPÝýˆ gÿ àÿú4?üCÿÄÕý3@Ñ´V‘´­"ÂÁ¥Hmm’"àtÎÐ3ÔÖmܤ¬hÑE†QEQEQEQEQEQEQEQEQEQEQEQEQEgëßò/jõé/þ€k;Dÿÿ^±è"´uïùµ?úô—ÿ@5¢ÈNÿ¯X¿ôUd[Ÿþ=äÿpÿ*‡Áò"x{þÁ–ßú)jiÿãÞO÷ò¨|ÿ"'‡¿ìmÿ¢–œ‚&åQPPQEQEQEQEQEW/uÿ%ìÿµk¨®^ïˆÿµ¥¶? GøÓ[‰ìkVL_òP­ì?þ†µ«">>!Yÿµ¥\cð–ñ«–ĭΦŠ(¬Ë (¢€ (¢€ (¢€ (¢€ (¢€ (¢€<ÛÂðÍß‚´›ŸéO.o$’Ée3±IbJä’yÍlÿÂá?úô_üÅÿÄÖzô¾ø'¦k0À“Ék¤Ú0ɲ‘¯o­Eoã_ëéš¶•ao¹µƒÃ;9ŽP»‚Ë:ätéžõ¦„ü!ÿ¡_EÿÁ|_üMð„xOþ…}ÿññ5ÍÙüE¹Ô4­ìÖ[RÔÊ{mÌV>kg¯Ê6ŸÆ©‰×óx®çMŠ &·½6¦Îò塹‘`ʬÀFsÔ.I¢è5;øB<'ÿB¾‹ÿ‚ø¿øš?áðŸý ú/þ âÿâkóÆ#¾×õ› i67qhÅà]NÉ$îÃ;cÀÀèyoJw‹|g«èf& "Ë6Ÿhjwƒ{¿üò#$’9ù¾í»ÿG„ÿèWÑð_ÿGü!ÿ¡_EÿÁ|_üMr#âN¯©Ÿ[èšE«ÝëvRN«s3*DèHl2Wå>çŠfµâïj±ø›MÓ´Ûo¤Ø˜õ d•ÚGŒ–òxÆŸ½×Fhº±ÿ„#Âô+è¿ø/‹ÿ‰£þ ÿЯ¢ÿà¾/þ&©|4f†ú 1,ÆÔIÉ<šêéƒÿG„ÿèWÑð_ÿGü!ÿ¡_EÿÁ|_üMoQ@?ð„xOþ…}ÿññ4Âá?úô_üÅÿÄÖõƒÿG„ÿèWÑð_ÿGü!ÿ¡_EÿÁ|_üMoW/i­øšòkˆCÒ"žÝ¶Éº´€9ÚÜ[U€È úŽ €ÍcÁž‹D¿’? hÈëm#+-„@‚àƒ¶·4Oùißõëþ‚+&ù¼Yyaský¢§G»ûZSŒ‚3³{ÖæŸnÖzm­³Í )#¡ @Ïÿò¸•qþðw†.|!¢Ï?‡4‰f’ÂyÆ&gc’I+É'½vR.øÙznW/£ÅâÍ'D°Ó²tY~Éogö¬«¿b…Î>ÌqœtÉ  Ÿð„xOþ…}ÿññ4Âá?úô_üÅÿÄÕKíoÄö } H–i›d0E«H^Cì °I$:šéбE.¾à§ cšÃÿ„#Âô+è¿ø/‹ÿ‰£þ ÿЯ¢ÿà¾/þ&·¨  øB<'ÿB¾‹ÿ‚ø¿øš?áðŸý ú/þ âÿâkzŠÁÿ„#Âô+è¿ø/‹ÿ‰£þ ÿЯ¢ÿà¾/þ&·¨  øB<'ÿB¾‹ÿ‚ø¿øš?áðŸý ú/þ âÿâkzŠÁÿ„#Âô+è¿ø/‹ÿ‰£þ ÿЯ¢ÿà¾/þ&·¨  øB<'ÿB¾‹ÿ‚ø¿øš¥a£iz?ŽÕ4Í6ÎÅdÓ¸¶b D©×h®®°_þGèìÿú5(z¹mgJÓµéjv·°®tëÌ+"†ó çóï]M`ÜÈý§Ø.ëÿFÛÐÿG„ÿèWÑð_ÿGü!ÿ¡_EÿÁ|_üMoQ@?ð„xOþ…}ÿññ4Âá?úô_üÅÿÄÖõƒÿG„ÿèWÑð_ÿGü!ÿ¡_EÿÁ|_üMoQ@?ð„xOþ…}ÿññ4Âá?úô_üÅÿÄÖõƒÿG„ÿèWÑð_ÿGü!ÿ¡_EÿÁ|_üMoQ@?ð„xOþ…}ÿññ5“âŸøbÛÂÔðxsHŠh¬'xäŽÆ%daA Aï]¥bøÀãÁùÿ¨uÇþ‹jê æÞ2¸?•I^mÅ=°¢ÿctP?ãëÿ°«üN2.FŽ8ÿ¯þ´úoåüQX§ÜÄÕ쮵ÙîÖÒÊÚ[›™4{0‘D…™Ž#<×Wô?\Ey£êú¶¯u|º]¶,läPÀY;ˆåÈ +wÁò øsþÁvßú)kz²±g—ø/ÃòÞ|GÖüS&™}a`sö(/ã1¸šE_:@¹ã;zÿµíZ¿ÃIu«™#½ñ ÄÚd“‰¼‰í£–hÆAØ“¶YWçë^E;Î#TðÅÆ­ª^é!¹ÒcÕ•Eü1¯¼·r1 ¡Æzg­%ç÷}tê6:õÕ°šÅ,.VH–i$F2®Ü«Ôàõ&»Š(°\â4_‡‹¤j»:£ÎÚ-¬¶Ê !|Ðû¹<ñ€@ïÒ—Rø-Ʊ«^iºìúu¾°u e$¥r¬y\ƒÏ^§Ö»j(°\ÊðÖŠ¾ð冎³™ÖÒ!”®ÒÞøÉÅjÑEQE (¢€ ¡©i¦ìÇqo/ÙïàÏ“>3ת°þ$8B0@"ýGMÔ…è’¢û=ìÛ“¹èÀÿœ7~G/U KM7f;‹y~Ï|™ñž½U‡ñ!ÀÈú‚ ¦êBôI Ñ}žö íÉÎÜô`‰N¿#‚ËÕOQÔSO‰>FšâVÙº}é[ÐzÔ“Àš5E4ø“äi®%m[§Þ•½ I<ɨ´í9á•ïo]fÔ%\;¯ÝzùižŠ=z±äöÓ´ç†W½½u›P•pî¿v5ëå¦z(õêÇ“Ø ( AEPEPEPEPEPX2ñãëO}.lþÅþ&·« _ù¬ÿì?þŠ›µƒuÇ´Ÿ}.÷?„¶¿âkz°nÿä~Ò?ì}ÿ£m(zŠ( AEPEPEPEPXž1ÿ‘_ÿ°mÇþ‹jÛ¬OÿȯÿØ6ãÿEµÿ‘ßö ¶ÿÑK[Õƒàù|9ÿ`»oýµ½_>zÁEP ¢Š(¢Š(®Û#fÆv‚k™Ó5OjºUž£Ÿ£¤WP$è¯y.åVPÀGךé'ÿy?Ü?ʲ|ÿ"Nƒÿ`ëý´ g›âÏùòÑð2_þ5G›âÏùòÑð2_þ5[´P›âÏùòÑð2_þ5G›âÏùòÑð2_þ5[´P›âÏùòÑð2_þ5G›âÏùòÑð2_þ5[´P›âÏùòÑð2_þ5ToìüUw$7[hÐ^Aþªe»”ðz«/æS‘ô#:º(”´³ñ\s^Ïm£Ow/Ëæ¹@3 òøÏry=±{Íñgüùh¿ø/ÿ­Ú( Íñgüùh¿ø/ÿ£Íñgüùh¿ø/ÿ­Ú( Íñgüùh¿ø/ÿ£Íñgüùh¿ø/ÿ­Ú( Íñgüùh¿ø/ÿ£Íñgüùh¿ø/ÿ­Ú(œ»¾ñU”÷/a£2ÃH@¼—$Ÿùç[–W?l°·ºÛ³Î‰dÛœã ~µ_[ÿ£ÿ^²ÿè&þ@wýzÅÿ Š¿EP ¢Š(¬¸ñõ–{éwü%‡?ÌVõ`ÜÈý§Ø.ëÿFÛÐ3z°o8ñîŽOC¦_Ç̵?ÐÖõ`ÞÿÈó¢ÿ×…ïþ‡o@ÔQE (¢€ (¢€ (¢€ (¢€ Äñüˆúÿýƒn?ô[VÝbxÇþD}þÁ·ú-¨ãÉþ­~‚®Úÿª?ïU$ÿV¿AWmÕ÷«è%±ä­ÏQðGüˆ>ÿ°]·þŠZÞ¬ȃáÏûÛ襭êùóÖ (¢Q@Q@Ïÿò¸•dø?þDþÁÖÿú-kZø÷“ýÃü«'Áÿò$è?ö·ÿÑk@ͪ(¢W–x«ÇzæâÛË.-´‹V3g5儲ÃxH÷J‡ä‘À>ô63Ôè® Rñ'ˆ/|ae èwdIw£‹ÿµH2©ßŒ®ÜÏ®}«ŸÓ|}â¹´ë÷m¦}‚ûRM6kX¡mìK2™7ã•´yjyÛwù{†í¹Æq×ïRW—éqk0ükµ‹[¹´¹¹]öÍmŒ2ùê’pAÈàò1Ò½Bš¢Š(C[ÿ£ÿ^²ÿè&þ@wýzÅÿ Š5¿ùj?õë/þ‚hÑ?ä§׬_ú eú(¢Q@`ÜÈý§Ø.ëÿFÛÖõ`Ýqãí+ý­.÷?„¶¿âh½X7¿ò<è¿õá{ÿ¡ÛÖõ`ßñãm÷6—‹øfýoQE(¢Š(¢Š(¢Š(¢Š+Æ?ò#ëÿö ¸ÿÑm[u‰ãùõÿûÜè¶ g'úµú »kþ¨ÿ½T“ýZý]µÿTÞ¯ –Ç’·=GÁò øsþÁvßú)kz°|ÿ"‡?ìmÿ¢–·«çÏX(¢ŠQEQEG?ü{ÉþáþU“àÿùtû[ÿèµ­iÿãÞO÷ò¬ŸÿÈ“ ÿØ:ßÿE­6¨¢ŠÉjÞ³Õoïn­«ZG~¡ní­îŽP½yÆ+­¢˜VÞÓlõë=^2Mi§:·ƒˆŽÙ'§9ªü<Ò ðö™¢¬÷¦ÛN¾ñ1uÞÒfø#,x}k[Yñ.áç¶MVô[µÑa(ͼ¨Éh<ò>½« þ¯ƒ~γX…ó<¹¶—0œã÷ƒoÈ3Üã?£@+Üü*Ò.b¾¶:–­ÝÏÚͤS¨%-’Ã*OaÁÈüy®’Çö–"ÔõȤ®µ‰&Ã`®ÕÚÈ÷äÕ}oÆš‡§†ßP½Û<Éæ$qDò¶Ïï€á}Í-ïŸ4—«n‰ºñ·Ž£õÍYŸÀÚ=σ ð´Æá¬`UIæ*9V 2>•›¢|@´_éz׈n#†æùäDŠ™šB²2ü¨2Ç ÿõë©Ò5?]ÓÒÿLºK›f%C¨#AäcF€bhÞ²Ò5õ×[RÔïµ/³Všòpû“ ô 1Ó·½u4QLŠ( E oþ@ýzËÿ š4Oùißõëþ‚(Öÿä¨ÿ׬¿ú £Dÿÿ^±è"—袊QEƒwÿ#ö‘ÿ`»ïýi[Õƒwÿ#ö‘ÿ`Ëáÿ‘mh½XZ‡üŽºýzÝÿ8kv°uù43ÿN×cÿEPÀÞ¢Š(QEQEQEQEV'ŒäG×ÿìqÿ¢Ú¶ëÆ?ò#ëÿö ¸ÿÑm@ÏOõkôv×ýQÿz©'úµú »kþ¨ÿ½_A-%nz‚?äAðçý‚í¿ôRÖõ`ø#þDØ.ÛÿE-oWÏž°QE(¢Š(¢ŠŽø÷“ýÃü«'Áÿò$è?ö·ÿÑkZÓÿǼŸîåY>ÿ‘'Aÿ°u¿þ‹ZmQE(¢Šâüa¢jŸ‹üyije¶°»–K—Ü F¥W“Ï#µr÷Þ×eðçÄKxôæ3꺀–Íw¦fMàç¯g®+×(¢Ã¹æ)¦xƒÂ¾.}zÛB“V‚÷M·µxà™Ky@Á ySŽ¢²­¼âéžÕN[ë:þæîëN‚EÌk0ldðvã=zž8潎ŠV ž?uá?ë:_Äú@²ŸY6²Ú@ó!ݳ’ ¸ç¶OZÔ²´ñ±ñÃzåׇæÓ¬l쥆C4ÈÌ©€xÀû+Ó(¢ÁsÅ£ðgˆ´ýÂ:‚Ú_™´ÅºŠêÚÊxÒâ5’F!ã-•'‘×ü;ïh÷:Vw%å¥Í¥Åíä—OÍÒÎùl ÌU@ã$ ý}:º(°\(¢Šb (¢€(kòÔëÖ_ýÑ¢ÈNÿ¯X¿ôF·ÿ Gþ½eÿÐM'ü€4ïúõ‹ÿA ¿EP ¢Š(¬ßùt_úð½ÿÐíëz°oäyÑëÂ÷ÿC· fõ`ê_ò8h?õÊëù%oV¥ÿ#†ƒÿ\®¿’PõQ@‚Š( Š( Š( Š( ±¿ÿ`ÛýÕ·Xž1ÿ‘_ÿ°mÇþ‹jxò«_ «¶¿êûÕI?Õ¯ÐUÛ_õGýêú ly+sÔ|ÿ"‡?ìmÿ¢–·«Áò øsþÁvßú)kz¾|õ‚Š( AEPEPsÿǼŸîåY>ÿ‘'Aÿ°u¿þ‹ZØ‘wÆÉœnW1¤Úø¯JѬtå¶Ñ¥[Kxàn¥‚(\ãËã8 gSEay¾,ÿŸ-ÿ%ÿãTy¾,ÿŸ-ÿ%ÿãT»Eay¾,ÿŸ-ÿ%ÿãTy¾,ÿŸ-ÿ%ÿãT»Eay¾,ÿŸ-ÿ%ÿãTy¾,ÿŸ-ÿ%ÿãT»Eay¾,ÿŸ-ÿ%ÿãTy¾,ÿŸ-ÿ%ÿãT»Eay¾,ÿŸ-ÿ%ÿãTy¾,ÿŸ-ÿ%ÿãT»Eay¾,ÿŸ-ÿ%ÿãTy¾,ÿŸ-ÿ%ÿãT»Eay¾,ÿŸ-ÿ%ÿãTy¾,ÿŸ-ÿ%ÿãT»Eay¾,ÿŸ-ÿ%ÿãTy¾,ÿŸ-ÿ%ÿãT{[ÿ£ÿ^²ÿè&þ@wýzÅÿ ŠÊ½OÞXÜZ›MDÑ4{¾×)ÆF3þ¯Þ·,-žkjÌ¡…#,:3úPŠ(¢Q@`ßñã}½lïÿ€ÿJÞ¬-CþG]þ½nÿœ41›µƒªqâíú­Êÿ㊥oV«ÿ#g‡ÿíçÿ@»EP ¢Š(¢Š(¢Š(¢Š(¬OÿȯÿØ6ãÿEµmÖ'ŒäG×ÿìqÿ¢Úž<Ÿê×è*í¯ú£þõROõkôv×ýQÿz¾‚[JÜõȃáÏûÛ襭êÁðGüˆ>ÿ°]·þŠZÞ¯Ÿ=`¢Š(QEQEQEQEQEQEQEQEQEQEQEQEQES$–8T4²"q–`)õ™­èV:ý·½†71°’dW1¸èÀA÷‚84 ¹öëOùúƒþþ żž¼k¢yR£âÖï;Xs A§hú³5÷‡´˜µ—s*Ù¦ÉW§˜™=GU<ÄíYèºV1šËL²¶”®Òð@¨ÄzdœPêçu˘-|Oáùn&Žóp7HÁGÜÍtU ͵ⅺ·†uS%@ÀÆ€+mé?ô²ÿÀ„ÿšßQ±»Çm{o3’±Ê¬që€k;P´Ñ4èßI´’Id0Çn…å~Ê£Žz 8š4] ¤Ô&·¶MBuÚÞBH“9§SÕ<Ú¢Š(QEQEQEV'ŒäG×ÿìqÿ¢Ú¶ëÆ?ò#ëÿö ¸ÿÑm@ÏOõkôv×ýQÿz©'úµú »kþ¨ÿ½_A-%nz‚?äAðçý‚í¿ôRÖõ`ø#þDØ.ÛÿE-oWÏž°QE(¢Š(¢Š(¢¨kJƒ©Ù;yëþ4zŠ¡ý·¤ÿÐRËÿühþÛÒè)eÿ þ4 ¿EPþÛÒè)eÿ þ4mé?ô²ÿÀ„ÿ¿EPþÛÒè)eÿ þ4mé?ô²ÿÀ„ÿ¿EPþÛÒè)eÿ þ4mé?ô²ÿÀ„ÿ¿EPþÛÒè)eÿ þ4mé?ô²ÿÀ„ÿ¿EPþÛÒè)eÿ þ4mé?ô²ÿÀ„ÿ¿EPþÛÒè)eÿ þ4mé?ô²ÿÀ„ÿ¿EPþÛÒè)eÿ þ4mé?ô²ÿÀ„ÿ¿EPþÛÒè)eÿ þ4mé?ô²ÿÀ„ÿ¿EPþÛÒè)eÿ þ4mé?ô²ÿÀ„ÿ¿EPþÛÒè)eÿ þ4mé?ô²ÿÀ„ÿ~£§E¨Â¡âš&ß ñœ¿ÿ`ÛýÕ·Xž1ÿ‘_ÿ°mÇþ‹jxò«_ «¶¿êûÕI?Õ¯ÐUÛ_õGýêú ly+sÔ|ÿ"‡?ìmÿ¢–·«Áò øsþÁvßú)kz¾|õ‚Š( AEPEPsÿǼŸîå\ç„´}.OhNúm›;iöå™ RIòדÅtsÿǼŸîåY>ÿ‘'Aÿ°u¿þ‹Z[þÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EP:H'J±ÈéþŽœ~”bi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþbi?ô ²ÿÀtÿ ¿EPþÄÒèeÿ€éþ—âmKšæ›f¬¶3‡ں:ÉñOüŠ:×ýxOÿ¢Ú€/ØÿÇ…·ýr_ä*z‚Çþ<-¿ë’ÿ!SÐ ¢Š(¬OÿȯÿØ6ãÿEµmÖ'ŒäG×ÿìqÿ¢Úž<Ÿê×è*í¯ú£þõROõkôv×ýQÿz¾‚[JÜõȃáÏûÛ襭êÁðGüˆ>ÿ°]·þŠZÞ¯Ÿ=`¢Š(QEQEÿñï'û‡ùVOƒÿäIÐìoÿ¢Öµ§ÿy?Ü?ʲ|ÿ"Nƒÿ`ëý´ Ú¢Š(QEQEQEQTõ]VËDÒçÔµ „6.é$ œ ã ç©=´éuk ÄyÙ*\ŽpFEKEPE“ x†ÏÄPÞËf“"ÙÞIg'š eÓ#ñÍ5¨¢ŠQESdqO#g {Vo‡uëOè6ºÅŠL–×!Š,ÊpÅy‘Ôô Ô¢Š(QEdø“Ä6~Ñ%Õ¯’g·‰‘J ±,ÁF u#½5¨¢³/uËk sJÒeŽcq©yÞK(WËP͸ç#ƒÆ FQ@Q@dø§þEkþ¼'ÿÑmZÕ“âŸùu¯úðŸÿEµ/ØÿÇ…·ýr_ä*z‚Çþ<-¿ë’ÿ!SÐ ¢Š(¬OÿȯÿØ6ãÿEµmÖ'ŒäG×ÿìqÿ¢Úž<Ÿê×è*í¯ú£þõROõkôv×ýQÿz¾‚[JÜõȃáÏûÛ襭êÁðGüˆ>ÿ°]·þŠZÞ¯Ÿ=`¢Š(QEQEÿñï'û‡ùVOƒÿäIÐìoÿ¢Öµ§ÿy?Ü?ʲ|ÿ"Nƒÿ`ëý´ Ú¢Š(T§m…Áó,DÇÌD,ËÁäÉ#ÐTôPx6x4h9}?V{©ž¿Ó¯¥XœµÄ.r@÷Ï5£§Æ|â}|MtºŸ‰$ŽÖt”À<äÎÐù=zzW½Ã§XÛÝIu •¼W}ùR%Wo©&œlm)"6°åmò!ŒaÛÔŽçÍ+ç‘Þ-—‚|gâX-øi¿ðŽýªh!¸mï/›·~âNüݲMexCìö^>Ò“LžÂ/4™šhl¯d¸ß„È3`y€òp1ï^æÖÐ<­+AHÉå—( +ýÜú{TPi–¢1ocmŒ±ŒG®ÂzãŒ÷¢ÁsÁ£ð¾7À |C*O>¨ð&yÜìQ>ÜÎ0'§rk^uðÛë>±Õ.Ñ<$t‰$ƒuÓ-»Ýï;òû¹#'‚xè=+Ù–ÖÝ-²AÛTÄÁê1Óœš…´5ìRÅôûV´C•·0©O^X.xþ£}áë½Ã:Dyw§M%Ã[O­Þµ½¸1ó²€\BóÇ® dZ½ÅÇÛO·J|`–ÐÉ Ž<¸ˆà!'!~bGÖ½ê}>Êêḳ·š(ˆ1¤‘+*ЀG§+CÖÖõžwú±÷ÿ½þ÷¿Z,<§_Ñü?¦x÷AеBm<1Ÿ4¶ñIpé¹2rùÉ;NFO¥[ø]«išG†u)..Ù-®äiL°’Y¥{f’`Wh”—ãœ{Ñ`¹æwzÝ–ñÇ©©^¥·Ÿ§[›d•ñæŸ(©;œ09¬ï¿ÿ`ÛýÕ·Xž1ÿ‘_ÿ°mÇþ‹jxò«_ «¶¿êûÕI?Õ¯ÐUÛ_õGýêú ly+sÔ|ÿ"‡?ìmÿ¢–·«Áò øsþÁvßú)kz¾|õ‚Š( AEPEPsÿǼŸîåY>ÿ‘'Aÿ°u¿þ‹ZÖŸþ=äÿpÿ*Éðü‰:ýƒ­ÿôZÐ3jŠ( AEPEPEPEPEPEPEPEPEPEPEPEPEPEPY>)ÿ‘GZÿ¯ ÿô[Vµdø§þEkþ¼'ÿÑm@Ëö?ñámÿ\—ù ž ±ÿ oúä¿ÈTô(¢Š+Æ?ò#ëÿö ¸ÿÑm[u‰ãùõÿûÜè¶ g'úµú »kþ¨ÿ½T“ýZý]µÿTÞ¯ –Ç’·=GÁò øsþÁvßú)kz°|ÿ"‡?ìmÿ¢–·«çÏX(¢ŠQEQEG?ü{ÉþáþUÎxKXÒãðf„©Y«®ŸnZu-x<×OT?±4“ÿ0»/üOð aý·¤ÿÐRËÿühþÛÒè)eÿ þ4bi?ô ²ÿÀtÿ ?±4ŸúÙà:…ÛzOý,¿ð!?Æí½'þ‚–_øŸãGö&“ÿ@»/üOð£ûIÿ ]—þ§øPý·¤ÿÐRËÿühþÛÒè)eÿ þ4bi?ô ²ÿÀtÿ ?±4ŸúÙà:…ÛzOý,¿ð!?Æí½'þ‚–_øŸãGö&“ÿ@»/üOð£ûIÿ ]—þ§øPý·¤ÿÐRËÿühþÛÒè)eÿ þ4bi?ô ²ÿÀtÿ ?±4ŸúÙà:…ÛzOý,¿ð!?Æí½'þ‚–_øŸãGö&“ÿ@»/üOð£ûIÿ ]—þ§øPý·¤ÿÐRËÿühþÛÒè)eÿ þ4bi?ô ²ÿÀtÿ ?±4ŸúÙà:…ÛzOý,¿ð!?Æí½'þ‚–_øŸãGö&“ÿ@»/üOð£ûIÿ ]—þ§øPý·¤ÿÐRËÿühþÛÒè)eÿ þ4bi?ô ²ÿÀtÿ ?±4ŸúÙà:…ÛzOý,¿ð!?Æí½'þ‚–_øŸãGö&“ÿ@»/üOð£ûIÿ ]—þ§øPý·¤ÿÐRËÿühþÛÒè)eÿ þ4bi?ô ²ÿÀtÿ ?±4ŸúÙà:…ÛzOý,¿ð!?Æí½'þ‚–_øŸãGö&“ÿ@»/üOð£ûIÿ ]—þ§øPý·¤ÿÐRËÿühþÛÒè)eÿ þ4bi?ô ²ÿÀtÿ ?±4ŸúÙà:…ÛzOý,¿ð!?Æí½'þ‚–_øŸãGö&“ÿ@»/üOð£ûIÿ ]—þ§øPý·¤ÿÐRËÿühþÛÒè)eÿ þ4bi?ô ²ÿÀtÿ ?±4ŸúÙà:…ÛzOý,¿ð!?ƲüM¬érxSXDÔ¬ÙšÆpN¤“°ûÖ§ö&“ÿ@»/üOð£ûIó ²ÿÀtÿ ±cÿßõÉ©è¢Q@bxÇþD}þÁ·ú-«n±¿ÿ`ÛýÔ ñäÿV¿AWmÕ÷ª’«_ «¶¿êûÕôØòVç¨ø#þDØ.ÛÿE-oV‚?äAðçý‚í¿ôRÖõ|ùëQ@‚Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ±¿ÿ`ÛýÕ·Xž1ÿ‘_ÿ°mÇþ‹jxò«_ «¶¿êûÕI?Õ¯ÐUÛ_õGýêú ly+sÔ|ÿ"‡?ìmÿ¢–·«Žðwˆô(< C6µ§G,zmºº=ÒV¨ ‚x5´|UáÑ×^ÒÇý¾Gþ5óç¬kÑYð•øsþƒúWþGþ4ÂWáÏúé_øøÐ½‘ÿ _‡?è?¥àdãGü%~ÿ þ•ÿ‘ÿkÑYð•øsþƒúWþGþ4ÂWáÏúé_øøÐ½‘ÿ _‡?è?¥àdãGü%~ÿ þ•ÿ‘ÿkÑYð•øsþƒúWþGþ4ÂWáÏúé_øøÐ½‘ÿ _‡?è?¥àdãGü%~ÿ þ•ÿ‘ÿkÑYð•øsþƒúWþGþ4ÂWáÏúé_øøÐ½‘ÿ _‡?è?¥àdãGü%~ÿ þ•ÿ‘ÿkÑYð•øsþƒúWþGþ4ÂWáÏúé_øøÐ½‘ÿ _‡?è?¥àdãGü%~ÿ þ•ÿ‘ÿkÑYð•øsþƒúWþGþ4ÂWáÏúé_øøÐ½‘ÿ _‡?è?¥àdãGü%~ÿ þ•ÿ‘ÿkÑYð•øsþƒúWþGþ4ÂWáÏúé_øøÐ½‘ÿ _‡?è?¥àdãGü%~ÿ þ•ÿ‘ÿkÑYð•øsþƒúWþGþ4ÂWáÏúé_øøÐ½‘ÿ _‡?è?¥àdãGü%~ÿ þ•ÿ‘ÿkÑYð•øsþƒúWþGþ4ÂWáÏúé_øøÐ½‘ÿ _‡?è?¥àdãGü%~ÿ þ•ÿ‘ÿkÑYð•øsþƒúWþGþ4ÂWáÏúé_øøÐ½‘ÿ _‡?è?¥àdãGü%~ÿ þ•ÿ‘ÿkÑYð•øsþƒúWþGþ4ÂWáÏúé_øøÐ½‘ÿ _‡?è?¥àdãGü%~ÿ þ•ÿ‘ÿkÖ'ŒäG×ÿìqÿ¢Ú¤ÿ„¯ÃŸôÒ¿ð2?ñ¬x›@ŸÁºäQkšl’>Ÿp¨‰w,Ll<šó$ÿV¿AWmÕ÷ª’«_ «¶¿êûÕôØòVç¼›Brm`'þ¹Šó¿ŠV–Ñÿdì·‰sçg÷+Ó+šño…_ÄßcÙv¶ÿgßÕ7nÝ·Üv¼4ã ªRØõ+EÊ #Å<ˆ¿ç’ß""/ùäŸ÷ȯFÿ…Y?ýcÿ¿'ühÿ…Y?ýcÿ¿'ükÖúÝç°«ØóŸ"/ùäŸ÷ȣȋþy'ýò+Ñ¿áVOÿAXÿïÉÿ?áVOÿAXÿïÉÿ>·C¸{ ½9ò"ÿžIÿ|Š<ˆ¿ç’ß"½þdÿôþüŸñ£þdÿôþüŸñ£ët;‡°«ØóŸ"/ùäŸ÷ȣȋþy'ýò+Ñ¿áVOÿAXÿïÉÿ?áVOÿAXÿïÉÿ>·C¸{ ½9ò"ÿžIÿ|Š<ˆ¿ç’ß"½þdÿôþüŸñ£þdÿôþüŸñ£ët;‡°«ØóŸ"/ùäŸ÷ȣȋþy'ýò+Ñ¿áVOÿAXÿïÉÿ?áVOÿAXÿïÉÿ>·C¸{ ½9ò"ÿžIÿ|Š<ˆ¿ç’ß"½þdÿôþüŸñ£þdÿôþüŸñ£ët;‡°«ØóŸ"/ùäŸ÷ȣȋþy'ýò+Ñ¿áVOÿAXÿïÉÿ?áVOÿAXÿïÉÿ>·C¸{ ½9ò"ÿžIÿ|Š<ˆ¿ç’ß"½þdÿôþüŸñ£þdÿôþüŸñ£ët;‡°«ØóŸ"/ùäŸ÷ȣȋþy'ýò+Ñ¿áVOÿAXÿïÉÿ?áVOÿAXÿïÉÿ>·C¸{ ½9ò"ÿžIÿ|Š<ˆ¿ç’ß"½þdÿôþüŸñ£þdÿôþüŸñ£ët;‡°«ØóŸ"/ùäŸ÷ȣȋþy'ýò+Ñ¿áVOÿAXÿïÉÿ?áVOÿAXÿïÉÿ>·C¸{ ½9ò"ÿžIÿ|Š<ˆ¿ç’ß"½þdÿôþüŸñ£þdÿôþüŸñ£ët;‡°«ØóŸ"/ùäŸ÷ȣȋþy'ýò+Ñ¿áVOÿAXÿïÉÿ?áVOÿAXÿïÉÿ>·C¸{ ½9ò"ÿžIÿ|Š<ˆ¿ç’ß"½þdÿôþüŸñ£þdÿôþüŸñ£ët;‡°«ØóŸ"/ùäŸ÷ȣȋþy'ýò+Ñ¿áVOÿAXÿïÉÿ?áVOÿAXÿïÉÿ>·C¸{ ½9ò"ÿžIÿ|Š<ˆ¿ç’ß"½þdÿôþüŸñ£þdÿôþüŸñ£ët;‡°«ØóŸ"/ùäŸ÷ȣȋþy'ýò+Ñ¿áVOÿAXÿïÉÿ?áVOÿAXÿïÉÿ>·C¸{ ½9ò"ÿžIÿ|Š<ˆ¿ç’ß"½þdÿôþüŸñ£þdÿôþüŸñ£ët;‡°«ØóŸ"/ùäŸ÷ȣȋþy'ýò+Ñ¿áVOÿAXÿïÉÿ?áVOÿAXÿïÉÿ>·C¸{ ½9ò"ÿžIÿ|Š<ˆ¿ç’ß"½þdÿôþüŸñ£þdÿôþüŸñ£ët;‡°«ØóŸ"/ùäŸ÷ȣȋþy'ýò+Ñ¿áVOÿAXÿïÉÿ?áVOÿAXÿïÉÿ>·C¸{ ½9ò"ÿžIÿ|Š<ˆ¿ç’ß"½þdÿôþüŸñ£þdÿôþüŸñ£ët;‡°«ØóÚ·kþ¨ÿ½]¿ü*Éÿè+ýù?ãRÅðÊxÔíXúçýAÿâ¨xº-|_˜,=NÇ¢ÑYÅ~ƒâ (ÔÈÿÆ“þÏ ÿÐÁ¥àlã^êV?ü%žÿ¡ƒJÿÀØÿÆøK<7ÿC•ÿ±ÿlQXÿð–xoþ† +ÿcÿ?á,ðßý WþÇþ4±EcÿÂYá¿ú4¯ü ühÿ„³Ãô0i_øøÐÅÿ g†ÿè`Ò¿ð6?ñ£þÏ ÿÐÁ¥àlã@V?ü%žÿ¡ƒJÿÀØÿÆøK<7ÿC•ÿ±ÿlQXÿð–xoþ† +ÿcÿ?á,ðßý WþÇþ4±EcÿÂYá¿ú4¯ü ühÿ„³Ãô0i_øøÐÅÿ g†ÿè`Ò¿ð6?ñ£þÏ ÿÐÁ¥àlã@V?ü%žÿ¡ƒJÿÀØÿÆøK<7ÿC•ÿ±ÿlQXÿð–xoþ† +ÿcÿ?á,ðßý WþÇþ4±EcÿÂYá¿ú4¯ü ühÿ„³Ãô0i_øøÐÅÿ g†ÿè`Ò¿ð6?ñ£þÏ ÿÐÁ¥àlã@V?ü%žÿ¡ƒJÿÀØÿÆøK<7ÿC•ÿ±ÿlQXÿð–xoþ† +ÿcÿ?á,ðßý WþÇþ4±EcÿÂYá¿ú4¯ü ühÿ„³Ãô0i_øøÐÅÿ g†ÿè`Ò¿ð6?ñ£þÏ ÿÐÁ¥àlã@V?ü%žÿ¡ƒJÿÀØÿÆøK<7ÿC•ÿ±ÿlQXÿð–xoþ† +ÿcÿ?á,ðßý WþÇþ4±EcÿÂYá¿ú4¯ü ühÿ„³Ãô0i_øøÐÅÿ g†ÿè`Ò¿ð6?ñ£þÏ ÿÐÁ¥àlã@V?ü%žÿ¡ƒJÿÀØÿÆøK<7ÿC•ÿ±ÿlQXÿð–xoþ† +ÿcÿ?á,ðßý WþÇþ4±EcÿÂYá¿ú4¯ü ühÿ„³Ã„àxƒJÿÀÈÿÆ€6(¢Šâ|gjÞðë5´%Ž™lI(2tµ»öOùõƒþýŠÈðGüˆ>ÿ°]·þŠZÞ­H û §üúÁÿ~Åa´ÿŸX?ïØ©è Da´ÿŸX?ïØ£ì6Ÿóëýû=Øm?çÖûö(û §üúÁÿ~ÅOEAöOùõƒþýŠ>Ãiÿ>°ß±SÑ@}†Óþ}`ÿ¿b°ÚϬ÷ìTôPa´ÿŸX?ïØ£ì6Ÿóëýû=Øm?çÖûö(û §üúÁÿ~ÅOEAöOùõƒþýŠ>Ãiÿ>°ß±SÑ@}†Óþ}`ÿ¿b°ÚϬ÷ìTôPa´ÿŸX?ïØ£ì6Ÿóëýû=Øm?çÖûö(û §üúÁÿ~ÅOEAöOùõƒþýŠ>Ãiÿ>°ß±SÑ@}†Óþ}`ÿ¿b°ÚϬ÷ìTôPa´ÿŸX?ïØ£ì6Ÿóëýû=Øm?çÖûö(û §üúÁÿ~ÅOEAöOùõƒþýŠ>Ãiÿ>°ß±SÑ@}†Óþ}`ÿ¿b°ÚϬ÷ìTôPa´ÿŸX?ïØ£ì6Ÿóëýû=Øm?çÖûö(û §üúÁÿ~ÅOEAöOùõƒþýŠ>Ãiÿ>°ß±SÑ@}†Óþ}`ÿ¿b°ÚϬ÷ìTôPa´ÿŸX?ïØ£ì6Ÿóëýû=Øm?çÖûö+ÅÖv«à½u–ÚFpA8ýÛWAX¾18ðF¾êqÿ¢ÚDñïûƒùT•å1|NÔÖb´á@þ/ñ«1|IÔäR~Åh9Çñmõ*ÝŒ¾³LÝðGüˆ>ÿ°]·þŠZÞ¬ȃáÏûÛ襭êÄÔ(¢ŠQEQEQEQEQEQEQEQEÈk4Í^“F};V¼¼Ž%™Å•¯šž‡ƒŸÒºúò]BÛ^ºøÛª§‡õ [+¤Äd’â0Ü8×8¡¬=ðìþ—ÄŸnòôè˜Ç#H„:88ØW®îGõ[Gø‹£êÚÄSÛj:uÝÊy–˨[yBqþÁÉÏãŠâÿ‘ßö ¶ÿÑK[Õƒàù|9ÿ`»oýµ½_>zÁEÅjÒ¾­ñCIÑYÇÙ,,ŸS–0ß~BLIŸ÷rHúÐkExÚµ{ÿ Áà;{Ùÿµ“[¹µiRRɈ2O\ÿjÙðö·sâoÁ±™\¦›£Íuz‹1äSäØ=w&yõ¥p±ì”W—è^5›Oð·ƒ Ó4g¹mdÏqMxY£(IÉr¹aÜœpz²>'Íe¡kÓjÚRGªi)jÖðMº9þæŽ9¿ .=Šòa­ë0|X°—ÄVÉ` Ñ&žXí® ±2‚Çv09ŒsÓƒÍhÛüJÕÏO×u ; ê¬1\ ÓDá^DÆ6œ‡æ\,zEæºÇÅc£éw²Ë¥+j𣨽¢ÎrcU.eoM£=?Ÿ[øŸý›ýµ-¦œ·Vš|–öësæ$«¸–¨£©9ÀïNè,zÌx;Ä·^#†í®#Ó™ eÜé÷«Æ‘A¨¬×018V‘W ìh¸ŽÊ®ŒŽ¡•† ‘ES±Ñ´½1Ýôý6ÎÑŸ‡kx2ß\šä,üy©^jºÎ4T]#E¸¸ŠúïÏËK‹ŽOŒÿ®gTñGˆuÉ<}u¦G§é×úÌ[´7eÙ£9ÂȸAÏr+…S¸Ðô‹»Áys¥XÍt0DÒ[£8ÇO˜ŒÕ‹»;[ûv·¼¶†âûÑÌÔþŠá~3ÜKmðýä†I£oµÂ …б¹Šåty"Òþ!xz3þ]"Þå¥[˜õÖqÎåDœ¶OµØììlôë"ÆÖ XAÏ—a>¸UŠóüIÔ<7ªOö7Nû7 Œê*näSÀF3…ç¡çéKªüK¹µñ]þig§±tO*þûìÒÝn“a°žçšw Ep^$ø…6›â 4]6ÖÅî­­Öæäê«n¸<ˆÐó—<{s]7‡|Coâ/ Yë–ñºCq“ËnJHaï‚¢àkÑ^Aá_ ¿Ä? ¿Š5=kTTºšSi$7 ‰fÈP¨8ÀÇ>¿­u:ˆµmëGð­”i¬ë÷æG¸¸>Da‚ïŒòpxé\,vÔW›Ü|R–ÓD’iô]º­¦©›yd.˜:¶9Ù¾ xš+íoLÿ„vÇíúT?k•¾Ú|±]Øû™/ þ¥ÂÇ¥Q^zßï/n|9k£è‰q>·d÷('¹òÄ%G!ŽÓ0yŸJ~(K‰|otbºå¦ ša±Žl¤“>vøáNôíNè,z5ÂÁãNÆ÷PÒüA¤Ák©[éÒj6ÿg¸ß 9\‘• æ~µ,>#j²Üøj{ý+m3^+·;åIà•ÚÓÛ¾9ö¢ácÑh¯.“âò­Ä·©gdÚ$WdboT]Ÿ›i•bÇ)ÏLæ´5_k‘j>$¶Ò´{ˆ´’O4×{7¡y 6ýìgÛ|Qp±è4W–\xÃ\Ôþ x8iÐÓ5 #uöv¸Ú2üž^vp;‘Ú­hßnõ­}- ±Ó–»6Ík-øŠò5aÀ ?ÙRM+…I¢±üSâ øvïX¹‰åX p]Ø…UÏl’9íX>2Ömuë]'ÄÚ,2ßÃ$¶r[ÜùˆYsFÙ q‘NàvôWà_ë0µ‹SŸEŠÇJ–1Ëöîò+í#/^}½ë² ±¿ÿ`ÛýÕ·Xž1ÿ‘_ÿ°mÇþ‹jñäÿV¿AWmÕ÷ª’«_ «¶¿êûÕôØòVç¨ø#þDØ.ÛÿE-oV‚?äAðçý‚í¿ôRÖõ|ùëqÚ¥¤ºwÄíZT-m}g&™;*gcæFI‰ 3ôõ®ÆŠã¬¾ZY|H¼ñ€¹Üו[_+7*ªÏ»<’öz™áŸ‡vž×5íN³!Õ òãò¶‹e,ÌTœŒ°ôûµÚQE‚ç¥ü=M2 F56“þöòqçù€ï|¸Ï½C}ðÎÛQÄÉ>£&u«ˆ®Q’,g;Hçæëí]ÝX.pöÞ¼ŸÄ1k:ö»ý¥0²’ÆH–ÐB­Œa¸ê>ÕRÛá•ÂÁa¥^øŠk¿XN³Á`ÖÈ®J’U^@rÊ ôçÛŒzX.qwßlµÝøŠkÉvÝY½³Ú…ùw4~YpsýÃŒcß5“ðîMÁgB±×®#º7?ikÑ>aãåt$†] 3þÜÑE‚çáÂ5ªê­Åݼח¨‘²ZZ-´(Ñ<žæŸâ/_jôö‡®>“©Ç¶v0,ÑË9ÁRG9ïôô®¶Š,Kð¨]hšµÖ·,ÚŽ¥{åÕë[€¡8U@@“ß½oIàñ'‹5]wíÄý;ì>O•÷?ÚÎyú`}k§¢‹Ï8‹átÖ0øxØkh.txd€=Å•]‹n[åaž¹=¥OeðÇì‘i1¶´ó ;V}IK[€_vÆõî÷é^EAs—Ô¼+uuã­?ÄÖz§ÙŒÿež6-åÈŸ”“š³âÏ Aâ­:æ[;«i–âÒî¿ ‹Ð_¥oÕ{Ëë=:>öê hrÌž@‹“ÐdÐ'¦ø#Q:úk^!ñÚÔ<ë n‘È-…êØ=Àc'LøWu§Ç¤@Úümm¥_­ä(¶ ­. 'Ì`ÙcÉö½»» oJÕeš-?R´»’‰V •Ê}@e+·?(l}*ΣâXá½Ö´9muEµŒÊV)VUå†GC·$~¬ƒSRøo»QŽûFÔÒÊo±Ge7Úmä: _’0à fºíNN‘kaç´æÚee \õ'2sSX_A©éÖ×ö¯¾Þæ%–6õVάS°w7Ã]JÚ í3CñLÚn‡|îòÙý•dh÷ýåÉÏÐzÕû߇Éh÷Z©.™¨iVÆÖäŒN$ˆŽUÔã<ääc©öÇkE ž/ÂøçÑÚÞm^Iu õDÔîïž™s… ¸>§¿á«7‚–mÄZ§ÛÈ:͈³1ù_ê°›wg?7®8®®Š,<ŠëÁÚ®™ãiºeíÄcOÓç‹ûImw"žHG=1žõ½ÿ Â)´+Ë{½^y5{»õÔ_RŽ0¥g_ºU3£$c=ë¿¢•‚çmà;¹îµC\×£©]X>ŸÂÙcKxÛ9!Aäœäò*I<¯aá;_퇥Ž@ÞOúý€ }ï—8÷®ÊŠv ž{Ã'²½xìu„ƒI{³tm¾Ãʹ ˜ÖSÑ=lÿÂÞ,”_ø‚0„y_ê1=~n¹í]MX.p£áìöמ»±Ö|™´;o²³5°a&ðý¯Š<=w£Ý»¤W 1$yU‡ÐX‚5&ÖàÕ|AâÕf²†HlZ¬+ñ†r;˜Ž3]­X OøxxWÂÖZ ¹ûHµÅ6nÜìÝ2q÷±×µmÑE‰ãùõÿûÜè¶­ºÄñüˆúÿýƒn?ô[P'úµú »kþ¨ÿ½T“ýZý]µÿTÞ¯ –Ç’·=GÁò øsþÁvßú)kz°|ÿ"‡?ìmÿ¢–·«çÏX(¢ŠQEQEQEQEQEQEQEç_ oò·ûß7JôZÊñ‡¬Ü4/] ãÒºÿ Û¤pø»\g»63ÚaÌšp²Šm‘¶]$ð2 gÞ½V¨k:M¾»¤Üi—m*ÛܲyM´²ä¹ô8Áö&•‚æÃ+ií~è1\‚$6¡ðºÄ²ÿã¤WYMDH£XãUDPUF LŠ( AEPEPEPEPEPEPEPXž1ÿ‘_ÿ°mÇþ‹jÛ¬OÿȯÿØ6ãÿEµÿ‘ßö ¶ÿÑK[ÕÄxCÅþ´ðVƒmsâ-"âÓ­ã’)/cVF¨*Al‚­ŸøMü'ÿCF‹ÿƒ¿øªùóÖ7¨¬øMü'ÿCF‹ÿƒ¿øª?á7ðŸý /þ "ÿâ¨zŠÁÿ„ßÂô4h¿ø0‹ÿŠ£þ ÿÐÑ¢ÿàÂ/þ*€7¨¬øMü'ÿCF‹ÿƒ¿øª?á7ðŸý /þ "ÿâ¨zŠÁÿ„ßÂô4h¿ø0‹ÿŠ£þ ÿÐÑ¢ÿàÂ/þ*€7¨¬øMü'ÿCF‹ÿƒ¿øª?á7ðŸý /þ "ÿâ¨zŠÁÿ„ßÂô4h¿ø0‹ÿŠ£þ ÿÐÑ¢ÿàÂ/þ*€7¨¬øMü'ÿCF‹ÿƒ¿øª?á7ðŸý /þ "ÿâ¨zŠÁÿ„ßÂô4h¿ø0‹ÿŠ£þ ÿÐÑ¢ÿàÂ/þ*€7¨¬øMü'ÿCF‹ÿƒ¿øª?á7ðŸý /þ "ÿâ¨zŠÁÿ„ßÂô4h¿ø0‹ÿŠ£þ ÿÐÑ¢ÿàÂ/þ*€7¨¬øMü'ÿCF‹ÿƒ¿øª?á7ðŸý /þ "ÿâ¨zŠÁÿ„ßÂô4h¿ø0‹ÿŠ£þ ÿÐÑ¢ÿàÂ/þ*€7¨¬øMü'ÿCF‹ÿƒ¿øª?á7ðŸý /þ "ÿâ¨zŠÁÿ„ßÂô4h¿ø0‹ÿŠ£þ ÿÐÑ¢ÿàÂ/þ*€7¨¬øMü'ÿCF‹ÿƒ¿øª?á7ðŸý /þ "ÿâ¨zŠÁÿ„ßÂô4h¿ø0‹ÿŠ£þ ÿÐÑ¢ÿàÂ/þ*€7¨¬øMü'ÿCF‹ÿƒ¿øª?á7ðŸý /þ "ÿâ¨zŠÁÿ„ßÂô4h¿ø0‹ÿŠ£þ ÿÐÑ¢ÿàÂ/þ*€7¨¬øMü'ÿCF‹ÿƒ¿øª?á7ðŸý /þ "ÿâ¨zŠÁÿ„ßÂô4h¿ø0‹ÿŠ£þ ÿÐÑ¢ÿàÂ/þ*€7¨¬øMü'ÿCF‹ÿƒ¿øª?á7ðŸý /þ "ÿâ¨zŠÁÿ„ßÂô4h¿ø0‹ÿŠ£þ ÿÐÑ¢ÿàÂ/þ*€7«Æ?ò#ëÿö ¸ÿÑmLÿ„ßÂô4h¿ø0‹ÿЬøÃÃ>ÖàƒÄzD³Ka:GwÑ3;Øl’Ojó„ÿV¿AWmÕ÷ª’}Åú »kþ¨ÿ½_A-%n}^sñWþa?öÛÿd¯F¯:ø¨>M(úGþ^&øñùþG¥‰þ<âŠ(¯tòŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ­Úÿª?ïUJž*„ u¥-†ÿÙpyscard-1.6.14/smartcard/doc/images/sflogo.php.png0000644000175000017500000000552110633575650023602 0ustar rousseaurousseau00000000000000‰PNG  IHDR}%à?qègAMA±‹ ‘¥ cHRMnštô$„Ïm_èl<‹XÉGO ÜIDATxœb`ˆˆÿÿÿ?ÐÎY€‘‘ €†g¸ÿÿ‚áälÆWÄäL¸…8ù8%¸ä˜ØH2êéÓ§Ož'Ë2¤=rŸsƨµæ¦_~=´üE9矌1ƱK–ã+€°”3oß¾…W@; Þ†$Cx C0LÀ ÂÆ¦iÈ5ÜL`”< ^ x C0z ÊÐ4ãWbÆåöÆé@‹¤V˜bЧÀÔ Iì@#^„b–fÄ i§N"¨ €°¤wHœS$ÄîrÃŒd Ë€9( Œ*\`uý?Àô0¦±âS¤1‡,²  ºžþÖa``7ÖÂåLŸŸgMæ?d{eyFáJÈ £epÃ@çw Gq ÎáËÃ@(¢bß"i“¦9ÌÎÙú7»Ä ô¤5‘ˆð„(ØD¬æö­çKö’%L]šÕy¦æÂóÑú?Bˆï-,nÞ–±_vE0Ê3²Ó‡ ]Sa)g 1 n`Q /ïðxË?ÖŸÀ"ØDŽVdá@?Üü…;0‹D6Ÿ¿&ÆXpT1€Ë.`äAD€A kx:@ >ˆ2H[¨R¢HÑOLF ìíHH4À| &H±€5!RTOÝZ__Lé@§/$SÃë4¬Ò c€•!>Ÿp±Èÿ¾óàïKÂAt<9Ó8${Ašçð¦Z£ÒW‚°¥Á«É@eÀ 'X–p‡W,À‚¾RRR@òîÝ»˜Š%¤ d£eC\h&P 0q+ k-„5ul$×ɯsçtÃöíÛ‘¹ð$ÌÜ@·Á«\ü™ :rc + ,áL‰ð´¬6ÀE0Ðe@7¡u—€*v@Z‡ÀxFv%Üј]!H3¨h 0qš"¨¡€iÜL4•Ü<¦<¿Ïžüsr?ïØ¾ ^g@D€1 O¿À ö{!9X0âI¹È^ƒ;h&¤;‚ »ìU„8ÞÒ8Tª«[ÁѵàäÖ—ðu|”ή¡[¤4àê$ø fè S1`p-”BÃq¹üï#w9oÇWUÕ7«mÛa’$ñÞ×u¦iQ’Ñ”¡R*ŽcérMÓ0HaFQÄ4!õËq­5¦;çà‡aØu4ó17[´˜h”»ñÄZË*C¶ MÓ$¯*˜È÷}ÏA1uÇeYH 0…³?çëíö¢Ïíñôëîêï7£¯ïËÃN´ƒ Í*•G -˽Œø0çy&ã/ÄæóÇL|Ù(’ „1œ"_³,ûtšÜKaŸ `Â.è‘s7ÐM@qH2JMGnxà ¢ (Ôi$@¸ð”o#E é(1¢h&P.‹€–b&@Ìvç¿«Gõ0ò²1¨»0H2pð10üf`æøþûé«/È*á)h#rÇbÐaÀ$,B¥"°ƒJ"+ÆêN<#—Àô@Cr\ŒXðåÃ·× ,Ì Ì, œ" lTÂ¥ †;@á€G‚AL—AH‹_ž,™á#<¸@ ëp¬,/ÃÛû¬L÷þœYùñÁþªl²D@¤ÐðlÏüÿð‚áÚ:a1wÅh15>^¾_ßwøuáÙÆÓ%Ðð ÷·/1üýÏð÷7ï÷ ?_3üùÎðïßÿ ¾l8Cªiæ lUU@ Ïpÿýôíß·ÿ^žüpJàë)–<ü Ð¥w& <|øM;° aÀ –õë×C´°°X»Žq è@£ yø(PD/°Ý ì Ãí‚€!jõDø²þÔ]Þð‡2aÃî‹„ßfޏÁùaþÁÿ°ñ䀴I4) "ì=Á¥€q{0à}]ˆ ÈÚ àc8p á<ßôíÀµ÷w@*Rvy±þX.Ðj2`"ÅL€ `Y®ŽU Âj&dxz&pÈÊSdTé^XFÁ 8`dd Š=7 Èü'ñq- %IEND®B`‚pyscard-1.6.14/smartcard/doc/framework-samples.html0000644000175000017500000001062611747776676024121 0ustar rousseaurousseau00000000000000 smartcard python framework samples

pyscard library samples

Get pyscard at SourceForge.net. Fast,
secure and Free Open
Source software downloads

 

Last update : pyscard 1.6.14 (April 2012)

pyscard is a python module adding smart cards support to python.

It consists of smartcard.scard, an extension module wrapping Windows smart card base components (also known as PCSC), and smartcard, a python framework library hiding PCSC complexity.

 

Smartcard python framework samples

Display the ATR of inserted cards view source
Selecting the DF_TELECOM of a card view source
A simple apdu tracer and interpreter view source
Tracing connection events view source
Decorating Card Connections to add custom behavior view source
Detecting response apdu errors view source
Implementing a custom ErrorChecker view source
Implementing a custom card type view source
Monitoring smartcard readers view source
Monitoring smartcard insertion/removal view source
APDU/ATR byte to string utilities view source

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

pyscard-1.6.14/smartcard/doc/index.html0000644000175000017500000000660011747776676021566 0ustar rousseaurousseau00000000000000 pyscard - python for smart cards

pyscard Get pyscard at SourceForge.net. Fast, secure and Free Open Source software downloads


Last update : pyscard 1.6.14 (April 2012)

pyscard - python smart card library is a python module adding smart cards support to python.

download pyscard from sourceforge.net.

Report bugs, patches and feature requests using the sourceforge pyscard bug tracking system.

Pyscard consists of smartcard.scard, an extension module wrapping Windows smart card base components (also known as PCSC) on Windows and PCSC lite on linux and Mac OS X Tiger and Leopard, and smartcard, a higher level python framework built on top of the raw PCSC API.

Documentation Index

 

Samples


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

 

pyscard-1.6.14/smartcard/doc/scard-samples.html0000644000175000017500000001060611747776676023216 0ustar rousseaurousseau00000000000000 scard samples

smartcard.scard PCSC wrapper samples

Get pyscard at SourceForge.net. Fast,
secure and Free Open
Source software downloads

 

Last update : pyscard 1.6.14 (April 2012)

Using the smartcard framework is the preferred way to write python smart card application. You can however use the smartcard.scard library to write your python smart card application if you want to write your own python framework, or if you want to access some features of the SCardXXX C API not available in the smartcard framework.

The smartcard.scard module is a native extension module wrapping Windows smart card base components (also known as PCSC) on Windows, and pcsc-lite on linux and Mac OS X, whereas the smartcard framework is a pure python framework hiding scard complexity and PCSC.

smartcard.scard samples

send a Control Code to a card or reader view source
get the ATR of a card view source
get the attributes of a card view source
wait for card insertion/removal view source
list the cards introduced in the system view source
list the interfaces supported by a card view source
locate cards in the system view source
manage readers and reader groups view source
list smart card readers view source
select the DF_TELECOM of a SIM card view source
perform a simple smart card transaction view source

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

pyscard-1.6.14/smartcard/doc/pyscard-usersguide.html0000644000175000017500000032667411255421432024264 0ustar rousseaurousseau00000000000000 pyscard smartcard module

pyscard user's guide

Get pyscard at SourceForge.net. Fast, secure and Free Open Source software downloads
 

Contents


Copyright

Copyright 2001-2009 gemalto
Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com

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


Introduction

The pyscard smartcard library is a framework for building smart card aware applications in Python. The smartcard module is built on top of the PCSC API Python wrapper module.

pyscard supports Windows 2000 and XP by using the Microsoft Smart Card Base components, and linux and Mac OS X by using PCSC-lite.


Smart Cards

Smart cards are plastic cards having generally the size of a credit card and embedding a microprocessor. Smart cards communicate with the outside world thru a serial port interface and an half-duplex protocol. Smartcards usually interface with a dedicated terminal, such as a point-of-sale terminal or a mobile phone. Sometime, smart cards have to be interfaced with personal computers. This is the case for some applications such as secure login, mail cyphering or digital signature, but also for some PC based smart card tools used to personnalize or edit the content of smart cards. Smart cards are interfaced with a personnal computer using a smart card reader. The smart card reader connects on one side to the serial port of the smart card, and on the other side to the PC, often nowadays thru a USB port.

The PCSC workgroup has defined a standard API to interface smart card and smart card readers to a PC. The resulting reference implementation on linux and Mac OS X operating systems is PC/SC-lite. All windows operating systems also include out of the box smart card support, usually called PCSC.

The PCSC API is implemented in C language, and several bridges are provided to access the PCSC API from different languages such as java or visual basic. pyscard is a python framework to develop smart card PC applications on linux, Mac OS X and windows. pyscard lower layers interface to the PCSC API to access the smart cards and smart card readers.

 


Quick-start

We will see in this section some variations on how to send APDU commands to a smart card.

The reader-centric approach

A PC application interacts with a card by sending list of bytes, known as Application Protocol Data Units (APDU). The format of these APDUs is defined in the ISO7816-4 standard. To send APDUs to a card, the application needs first to connect to a card thru a smart card reader. Smart card aware applications that first select a smart card reader, then connect to the card inserted in the smart card reader use the reader-centric approach.

In the reader-centric approach, we open a connection with a card thru a smart card reader, and send APDU commands to the card using the connection:

>>> from smartcard.System import readers
>>> from smartcard.util import toHexString
>>>
>>> r=readers()
>>> print r
['SchlumbergerSema Reflex USB v.2 0', 'Utimaco CardManUSB 0']
>>> connection = r[0].createConnection()
>>> connection.connect()
>>> SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
>>> DF_TELECOM = [0x7F, 0x10]
>>> data, sw1, sw2 = connection.transmit( SELECT + DF_TELECOM )
>>> print "%x %x" % (sw1, sw2)
9f 1a
>>>

The list of available readers is retrieved with the readers() function. We create a connection with the first reader (index 0 for reader 1, 1 for reader 2, ...) with the r[0].createConnection() call and connect to the card with the connect() method of the connection. We can then send APDU commands to the card with the transmit() method.

Scripts written with the reader centric approach however have the following drawbacks:

  • the reader index or reader name is hardcoded in the scripts; the scripts must be edited to match each user configuration; for example in the previous script, we would have to edit the script and change r[0] to r[1] for using the second reader
  • there is no a-priori knowledge that the card is in the reader; to detect card insertion, we would have to execute the script and eventually catch a CardConnectionException that would indicate that there is no card in the reader.
  • there is no built-in check that the card in the reader is of the card type we expect; in the previous example, we might try to select the DF_TELECOM of an EMV card.

Most of these issues are solved with the card-centric approach, based on card type detection techniques, such as using the Answer To Reset (ATR) of the card.

to the top

The Answer To Reset (ATR)

The first answer of a smart card inserted in a smart card reader is call the ATR. The purpose of the ATR is to describe the supported communication parameters. The smart card reader, smart card reader driver, and operating system will use these parameters to establish a communication with the card. The ATR is described in the ISO7816-3 standard. The first bytes of the ATR describe the voltage convention (direct or inverse), followed by bytes describing the available communication interfaces and their respective parameters. These interface bytes are then followed by Historical Bytes which are not standardized, and are useful for transmitting proprietary informations such as the card type, the version of the embedded software, or the card state. Finally these historical bytes are eventually followd by a checksum byte.

The class smartcard.ATR is a pyscard utility class that can interpret the content of an ATR:

#! /usr/bin/env python
from smartcard.ATR import ATR
from smartcard.util import toHexString

atr = ATR([0x3B, 0x9E, 0x95, 0x80, 0x1F, 0xC3, 0x80, 0x31, 0xA0, 0x73,
0xBE, 0x21, 0x13, 0x67, 0x29, 0x02, 0x01, 0x01, 0x81,0xCD,0xB9] )
print atr
print 'historical bytes: ', toHexString( atr.getHistoricalBytes() )
print 'checksum: ', "0x%X" % atr.getChecksum()
print 'checksum OK: ', atr.checksumOK
print 'T0 supported: ', atr.isT0Supported()
print 'T1 supported: ', atr.isT1Supported()
print 'T15 supported: ', atr.isT15Supported()

Which results in the following output:

3B 9E 95 80 1F C3 80 31 A0 73 BE 21 13 67 29 02 01 01 81 CD B9
historical bytes: 80 31 A0 73 BE 21 13 67 29 02 01 01 81 CD
checksum: 0xB9
checksum OK: True
T0 supported: True
T1 supported: False
T15 supported: True

In practice, the ATR can be used to detect a particular card, either by trying to match a card with a complete ATR, or by matching a card with some data in the historical bytes. Smart card aware PC applications that detects smart cards based on the content of the ATR use the card-centric approach, independently on the smart card reader in which the card is inserted..

The card-centric approach

In the card-centric approach, we create a request for a specific type of card and wait until a card matching the request is inserted. Once a matching card is introduced, a connection to the card is automatically created and we can send APDU commands to the card using this connection.

Requesting a card by ATR

The following scripts requests a card with a known ATR:

>>> from smartcard.CardType import ATRCardType
>>> from smartcard.CardRequest import CardRequest
>>> from smartcard.util import toHexString, toBytes
>>>
>>> cardtype = ATRCardType( toBytes( "3B 16 94 20 02 01 00 00 0D" ) )
>>> cardrequest = CardRequest( timeout=1, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()
>>>
>>> cardservice.connection.connect()
>>> print toHexString( cardservice.connection.getATR() )
3B 16 94 20 02 01 00 00 0D
>>>
>>> SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
>>> DF_TELECOM = [0x7F, 0x10]
>>> data, sw1, sw2 = cardservice.connection.transmit( SELECT + DF_TELECOM )
>>> print "%x %x" % (sw1, sw2)
9f 1a
>>>

To request a card with a know ATR, you must first create an ATRCardType object with the desired ATR:

>>> cardtype = ATRCardType( toBytes( "3B 16 94 20 02 01 00 00 0D" ) )

And then create a CardRequest for this card type. In the sample, we request a time-out of 1 second.

>>> cardrequest = CardRequest( timeout=1, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()

The waitforcard() will either return with a card service or a time-out. The card service connection attribute can be used thereafter to transmit APDU commands to the card, as with the reader centric approach.

>>> cardservice.connection.connect()
>>> print toHexString( cardservice.connection.getATR() )

If necessary, the reader used for the connection can be accessed thru the CardConnection object:

>>> print cardservice.connection.getReader()
SchlumbergerSema Reflex USB v.2 0

The ATRCardType also supports masks:

>>> from smartcard.CardType import ATRCardType
>>> from smartcard.CardRequest import CardRequest
>>> from smartcard.util import toHexString, toBytes
>>>
>>> cardtype = ATRCardType( toBytes( "3B 15 94 20 02 01 00 00 0F" ), toBytes( "00 00 FF FF FF FF FF FF 00" ) )
>>> cardrequest = CardRequest( timeout=1, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()
>>>
>>> cardservice.connection.connect()
>>> print toHexString( cardservice.connection.getATR() )
3B 16 94 20 02 01 00 00 0D

Other CardTypes are available, and new CardTypes can be created, as described below.

to the top

Requesting any card

The AnyCardType is useful for requesting any card in any reader:

>>> from smartcard.CardType import AnyCardType
>>> from smartcard.CardRequest import CardRequest
>>> from smartcard.util import toHexString
>>>
>>> cardtype = AnyCardType()
>>> cardrequest = CardRequest( timeout=1, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()
>>>
>>> cardservice.connection.connect()
>>> print toHexString( cardservice.connection.getATR() )
3B 16 94 20 02 01 00 00 0D
>>> print cardservice.connection.getReader()
SchlumbergerSema Reflex USB v.2 0

to the top

Custom CardTypes

Custom CardTypes can be created, e.g. a card type that checks the ATR and the historical bytes of the card. To create a custom CardType, deriver your CardType class from the the CardType base class (or any other CardType) and override the matches() method. For exemple to create a DCCardType that will match cards with the direct convention (first byte of ATR to 0x3b):

>>> from smartcard.CardType import CardType
>>> from smartcard.CardRequest import CardRequest
>>> from smartcard.util import toHexString
>>>
>>> class DCCardType(CardType):
...      def matches( self, atr, reader=None ):
...          return atr[0]==0x3B
...
>>> cardtype = DCCardType()
>>> cardrequest = CardRequest( timeout=1, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()
>>>
>>> cardservice.connection.connect()
>>> print toHexString( cardservice.connection.getATR() )
3B 16 94 20 02 01 00 00 0D
>>> print cardservice.connection.getReader()
SchlumbergerSema Reflex USB v.2 0
>>>

Scripts written with the card-centric approach fixes the problems of the reader-centric approach:

  • there is no assumption concerning the reader index or reader name; the desired card will be located in any reader
  • the request will block or time-out if the desired card type is not inserted
  • since we request the desired card type, the script is not played on an unknown or uncompatible card

Scripts written with the card-centric approach have however the following drawbacks:

  • the script is limited to a specific card type; we have to modify the script if we want to execute the script on another card type. For exemple, we have to modify the ATR of the card if we are using the ATRCardType. This can be partially solved by having a custom CardType that matches several ATRs, though.

to the top

Selecting the card communication protocol

Communication parameters are mostly important for the protocol negociation between the smart card reader and the card. The main smartcard protocols are the T=0 protocol and the T=1 protocol, for byte or block transmission, respectively. The required protocol can be specified at card connection or card transmission.

By defaults, the connect() method of the CardConnection object.will try to connect using either the T=0 or T=1 protocol. To force a connection protocol, you can pass the required protocol to the connect() method.

>>> from smartcard.CardType import AnyCardType
>>> from smartcard.CardConnection import CardConnection
>>> from smartcard.CardRequest import CardRequest
>>> from smartcard.util import toHexString
>>>
>>> cardtype = AnyCardType()
>>> cardrequest = CardRequest( timeout=1, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()
>>>
>>> cardservice.connection.connect( CardConnection.T1_protocol )
>>> print toHexString( cardservice.connection.getATR() )
3B 16 94 20 02 01 00 00 0D
>>> print cardservice.connection.getReader()
SchlumbergerSema Reflex USB v.2 0

Alternatively, you can specify the required protocol in the CardConnection transmit() method:

>>> from smartcard.CardType import AnyCardType
>>> from smartcard.CardConnection import CardConnection
>>> from smartcard.CardRequest import CardRequest
>>> from smartcard.util import toHexString, toBytes
>>>
>>> cardtype = AnyCardType()
>>> cardrequest = CardRequest( timeout=1, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()
>>>
>>> cardservice.connection.connect()
>>>
>>> SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
>>> DF_TELECOM = [0x7F, 0x10]
>>>
>>> apdu = SELECT+DF_TELECOM
>>> print 'sending ' + toHexString(apdu)
sending A0 A4 00 00 02 7F 10
>>> response, sw1, sw2 = cardservice.connection.transmit( apdu, CardConnection.T1_protocol )
>>> print 'response: ', response, ' status words: ', "%x %x" % (sw1, sw2)
response: [] status words: 9f 1a
>>>
>>> if sw1 == 0x9F:
...     GET_RESPONSE = [0XA0, 0XC0, 00, 00 ]
...     apdu = GET_RESPONSE + [sw2]
...     print 'sending ' + toHexString(apdu)
...     response, sw1, sw2 = cardservice.connection.transmit( apdu )
...     print 'response: ', toHexString(response), ' status words: ', "%x %x" % (sw1, sw2)
...
sending A0 C0 00 00 1A
response: 00 00 00 00 7F 10 02 00 00 00 00 00 0D 13 00 0A 04 00 83 8A 83 8A 00 01 00 00 status words: 90 0
>>>

The object-centric approach

In the object-centric approach, we associate a high-level object with a set of smart cards supported by the object. For example we associate a javacard loader class with a set of javacard smart cards. We create a request for the specific object, and wait until a card supported by the object is inserted. Once a card supported by the object is inserted, we perform the required function by calling the objec methods.

To be written...


Tracing APDUs

The brute force

A straightforward way of tracing command and response APDUs is to insert print statements around the transmit() method calls:

>>> from smartcard.CardType import ATRCardType
>>> from smartcard.CardRequest import CardRequest
>>> from smartcard.util import toHexString, toBytes
>>>
>>> cardtype = ATRCardType( toBytes( "3B 16 94 20 02 01 00 00 0D" ) )
>>> cardrequest = CardRequest( timeout=1, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()
>>>
>>> cardservice.connection.connect()
>>>
>>> SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
>>> DF_TELECOM = [0x7F, 0x10]
>>>
>>> apdu = SELECT+DF_TELECOM
>>> print 'sending ' + toHexString(apdu)
sending A0 A4 00 00 02 7F 10
>>> response, sw1, sw2 = cardservice.connection.transmit( apdu )
>>> print 'response: ', response, ' status words: ', "%x %x" % (sw1, sw2)
response: [] status words: 9f 1a
>>>
>>> if sw1 == 0x9F:
...     GET_RESPONSE = [0XA0, 0XC0, 00, 00 ]
...     apdu = GET_RESPONSE + [sw2]
...     print 'sending ' + toHexString(apdu)
...     response, sw1, sw2 = cardservice.connection.transmit( apdu )
...     print 'response: ', toHexString(response), ' status words: ', "%x %x" % (sw1, sw2)
...
sending A0 C0 00 00 1A
response: 00 00 00 00 7F 10 02 00 00 00 00 00 0D 13 00 0A 04 00 83 8A 83 8A 00 01 00 00 status words: 90 0
>>>

Scripts written this way are quite difficult to read, because there are more tracing statements than actual apdu transmits..

A small improvement in visibility would be to replace the print instructions by functions, e.g.:

>>> from smartcard.CardType import ATRCardType
>>> from smartcard.CardRequest import CardRequest
>>> from smartcard.util import toHexString, toBytes
>>>
>>> cardtype = ATRCardType( toBytes( "3B 16 94 20 02 01 00 00 0D" ) )
>>> cardrequest = CardRequest( timeout=1, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()
>>>
>>> cardservice.connection.connect()
>>>
>>> SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
>>> DF_TELECOM = [0x7F, 0x10]
>>>
>>> def trace_command(apdu):
...     print 'sending ' + toHexString(apdu)
...
>>> def trace_response( response, sw1, sw2 ):
...     if None==response: response=[]
...     print 'response: ', toHexString(response), ' status words: ', "%x %x" % (sw1, sw2)
...
>>> apdu = SELECT+DF_TELECOM
>>> trace_command(apdu)
sending A0 A4 00 00 02 7F 10
>>> response, sw1, sw2 = cardservice.connection.transmit( apdu )
>>> trace_response( response, sw1, sw2 )
response: status words: 9f 1a
>>>
>>> if sw1 == 0x9F:
...    GET_RESPONSE = [0XA0, 0XC0, 00, 00 ]
...    apdu = GET_RESPONSE + [sw2]
...    trace_command(apdu)
...    response, sw1, sw2 = cardservice.connection.transmit( apdu )
...    trace_response( response, sw1, sw2 )
...
sending A0 C0 00 00 1A
response: 00 00 00 00 7F 10 02 00 00 00 00 00 0D 13 00 0A 04 00 83 8A 83 8A 00 01 00 00 status words: 90 0
>>>

to the top

Using card connection observers to trace apdu transmission

The prefered solution is to implement a card connection observer, and register the observer with the card connection. The card connection will then notify the observer when card connection events occur (e.g. connection, disconnection, apdu command or apdu response). This is illustrated in the following script:

>>> from smartcard.CardType import AnyCardType
>>> from smartcard.CardRequest import CardRequest
>>> from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver
>>>
>>> GET_RESPONSE = [0XA0, 0XC0, 00, 00 ]
>>> SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
>>> DF_TELECOM = [0x7F, 0x10]
>>>
>>>
>>> cardtype = AnyCardType()
>>> cardrequest = CardRequest( timeout=10, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()
>>>
>>> observer=ConsoleCardConnectionObserver()
>>> cardservice.connection.addObserver( observer )
>>>
>>> cardservice.connection.connect()
connecting to SchlumbergerSema Reflex USB v.2 0
>>>
>>> apdu = SELECT+DF_TELECOM
>>> response, sw1, sw2 = cardservice.connection.transmit( apdu )
> A0 A4 00 00 02 7F 10
< [] 9F 1A
>>> if sw1 == 0x9F:
...     apdu = GET_RESPONSE + [sw2]
...     response, sw1, sw2 = cardservice.connection.transmit( apdu )
... else:
...     print 'no DF_TELECOM'
...
> A0 C0 00 00 1A
< 00 00 00 00 7F 10 02 00 00 00 00 00 0D 13 00 0A 04 00 83 8A 83 8A 00 01 00 00 90 0
>>>

In this script, a ConsoleCardConnectionObserver is attached to the card service connection once the watiforcard() call returns.

>>> observer=ConsoleCardConnectionObserver()
>>> cardservice.connection.addObserver( observer )

On card connection events (connect, disconnect, transmit command apdu, receive response apdu), the card connection notifies its obersers with a CarConnectionEvent including the event type and the event data. The ConsoleCardConnectionObserver is a simple observer that will print on the console the card connection events. The class definition is the following:

class ConsoleCardConnectionObserver( CardConnectionObserver ):
    def update( self, cardconnection, ccevent ):

        if 'connect'==ccevent.type:
            print 'connecting to ' + cardconnection.getReader()

        elif 'disconnect'==ccevent.type:
            print 'disconnecting from ' + cardconnection.getReader()

        elif 'command'==ccevent.type:
            print '> ', toHexString( ccevent.args[0] )

        elif 'response'==ccevent.type:
            if []==ccevent.args[0]:
                print '< [] ', "%-2X %-2X" % tuple(ccevent.args[-2:])
            else:
        print '< ', toHexString(ccevent.args[0]), "%-2X %-2X" % tuple(ccevent.args[-2:])

The console card connection observer is thus printing the connect, disconnect, command and response apdu events:

>>> cardservice.connection.connect()
connecting to SchlumbergerSema Reflex USB v.2 0
>>>
>>> apdu = SELECT+DF_TELECOM
>>> response, sw1, sw2 = cardservice.connection.transmit( apdu )
> A0 A4 00 00 02 7F 10
< [] 9F 1A
>>> if sw1 == 0x9F:
...     apdu = GET_RESPONSE + [sw2]
...     response, sw1, sw2 = cardservice.connection.transmit( apdu )
... else:
...     print 'no DF_TELECOM'
...
> A0 C0 00 00 1A
< 00 00 00 00 7F 10 02 00 00 00 00 00 0D 13 00 0A 04 00 83 8A 83 8A 00 01 00 00 90 0

A card connection observer's update methode is called upon card connection event, with the connection and the connection event as parameters. The CardConnectionEvent class definition is the following:

class CardConnectionEvent:
    """Base class for card connection events.

   This event is notified by CardConnection objects.

   type: 'connect', 'disconnect', 'command', 'response'
   args: None for 'connect' or 'disconnect'
   command APDU byte list for 'command'
   [response data, sw1, sw2] for 'response'
   type: 'connect' args:"""
   def __init__( self, type, args=None):
       self.type=type
       self.args=args

You can write your own card connection observer, for example to perform fancy output in a wxWindows frame, or apdu interpretation. The following scripts defines a small SELECT and GET RESPONSE apdu interpreter:

>>> from smartcard.CardType import AnyCardType
>>> from smartcard.CardRequest import CardRequest
>>> from smartcard.CardConnectionObserver import CardConnectionObserver
>>> from smartcard.util import toHexString
>>>
>>> from string import replace
>>>
>>> class TracerAndSELECTInterpreter( CardConnectionObserver ):
...     def update( self, cardconnection, ccevent ):
...         if 'connect'==ccevent.type:
...             print 'connecting to ' + cardconnection.getReader()
...         elif 'disconnect'==ccevent.type:
...             print 'disconnecting from ' + cardconnection.getReader()
...         elif 'command'==ccevent.type:
...             str=toHexString(ccevent.args[0])
...             str = replace( str , "A0 A4 00 00 02", "SELECT" )
...             str = replace( str , "A0 C0 00 00", "GET RESPONSE" )
...             print '> ', str
...         elif 'response'==ccevent.type:
...             if []==ccevent.args[0]:
...                 print '< [] ', "%-2X %-2X" % tuple(ccevent.args[-2:])
...             else:
...                 print '< ', toHexString(ccevent.args[0]), "%-2X %-2X" % tuple(ccevent.args[-2:])
...
>>>
>>> GET_RESPONSE = [0XA0, 0XC0, 00, 00 ]
>>> SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
>>> DF_TELECOM = [0x7F, 0x10]
>>>
>>>
>>> cardtype = AnyCardType()
>>> cardrequest = CardRequest( timeout=10, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()
>>>
>>> observer=TracerAndSELECTInterpreter()
>>> cardservice.connection.addObserver( observer )
>>>
>>> cardservice.connection.connect()
connecting to SchlumbergerSema Reflex USB v.2 0
>>>
>>> apdu = SELECT+DF_TELECOM
>>> response, sw1, sw2 = cardservice.connection.transmit( apdu )
> SELECT 7F 10
< [] 9F 1A
>>> if sw1 == 0x9F:
...     apdu = GET_RESPONSE + [sw2]
...     response, sw1, sw2 = cardservice.connection.transmit( apdu )
... else:
...     print 'no DF_TELECOM'
...
> GET RESPONSE 1A
< 00 00 00 00 7F 10 02 00 00 00 00 00 0D 13 00 0A 04 00 83 8A 83 8A 00 01 00 00 90 0
>>>

to the top

Testing for APDU transmission errors

Upon transmission and processing of an APDU, the smart card returns a pair of status words, SW1 and SW2, to report various success or error codes following the required processing. Some of these success or error codes are standardized in ISO7816-4, ISO7816-8 or ISO7816-9, for example. Other status word codes are standardized by standardization bodies such as Open Platform (e.g. javacard), 3GPP (e.g. SIM or USIM cards), or Eurocard-Mastercard-Visa (EMV) (e.g. banking cards). Finally, any smart card application developper can defined application related proprietary codes; for example the MUSCLE applet defines a set of prioprietary codes related to the MUSCLE applet features.

Some of these status word codes are uniques, but others have a different meaning depending on the card type and its supported standards. For example, ISO7816-4 defines the error code 0x62 0x82 as "File Invalidated", whereas in Open Platform 2.1 the same error code is defined as "Card life cycle is CARD_LOCKED". As a result, the list of error codes that can be returned by a smart card and they interpretation depend on the card type. The following discussion outlines possible strategies to check and report smart card status word errors.

The brute force for testing APDU transmission errors

As for APDU tracing, a straightforward way of checking for errors in response APDUs during the execution of scripts is to insert testt statements after the transmit() method calls:

>>> from smartcard.CardType import AnyCardType
>>> from smartcard.CardRequest import CardRequest
>>> from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver
>>>
>>> GET_RESPONSE = [0XA0, 0XC0, 00, 00 ]
>>> SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
>>> DF_TELECOM = [0x7F, 0x10]
>>>
>>> cardtype = AnyCardType()
>>> cardrequest = CardRequest( timeout=10, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()
>>>
>>> observer=ConsoleCardConnectionObserver()
>>> cardservice.connection.addObserver( observer )
>>>
>>> cardservice.connection.connect()
connecting to Utimaco CardManUSB 0
>>>
>>> apdu = SELECT+DF_TELECOM
>>> response, sw1, sw2 = cardservice.connection.transmit( apdu )
> A0 A4 00 00 02 7F 10
< [] 6E 0
>>>
>>> if sw1 in range(0x61, 0x6f):
... print "Error: sw1: %x sw2: %x" % (sw1, sw2)
...
Error: sw1: 6e sw2: 0
>>> if sw1 == 0x9F:
... apdu = GET_RESPONSE + [sw2]
... response, sw1, sw2 = cardservice.connection.transmit( apdu )
...
>>> cardservice.connection.disconnect()
disconnecting from Utimaco CardManUSB 0
>>>

Scripts written this way are quite difficult to read, because there are more error detection statements than actual apdu transmits.

An improvement in visibility is to wrap the transmit instruction inside a function mytransmit, e.g.:

>>> from smartcard.CardType import AnyCardType
>>> from smartcard.CardRequest import CardRequest
>>> from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver
>>>
>>> def mytransmit( connection, apdu ):
... response, sw1, sw2 = connection.transmit( apdu )
... if sw1 in range(0x61, 0x6f):
... print "Error: sw1: %x sw2: %x" % (sw1, sw2)
... return response, sw1, sw2
...
>>>
>>> GET_RESPONSE = [0XA0, 0XC0, 00, 00 ]
>>> SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
>>> DF_TELECOM = [0x7F, 0x10]
>>>
>>>
>>> cardtype = AnyCardType()
>>> cardrequest = CardRequest( timeout=10, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()
>>>
>>> observer=ConsoleCardConnectionObserver()
>>> cardservice.connection.addObserver( observer )
>>>
>>> cardservice.connection.connect()
connecting to Utimaco CardManUSB 0
>>>
>>> apdu = SELECT+DF_TELECOM
>>> response, sw1, sw2 = mytransmit( cardservice.connection, apdu )
> A0 A4 00 00 02 7F 10
< [] 6E 0
Error: sw1: 6e sw2: 0
>>>
>>> if sw1 == 0x9F:
... apdu = GET_RESPONSE + [sw2]
... response, sw1, sw2 = mytransmit( cardservice.connection, apdu )
...
>>> cardservice.connection.disconnect()
disconnecting from Utimaco CardManUSB 0
>>>

The prefered solution is for testing errors is to use smarcard.sw.ErrorChecker, as described in the following section.

to the top

Checking APDU transmission errors with error checkers

Status word errors can occur from different sources. The ISO7816-4 standards defines status words for sw1 in the range 0x62 to 0x6F and some values of sw2, except for 0x66 which is reserved for security related issues. The ISO7816-8 standards define other status words, e.g. sw1=0x68 and sw2=0x83 or 0x84 for command chaining errors. Other standards, like Open Platform, define additional status words error, e.g. sw1=0x94 and sw2=0x84.

The prefered strategy for status word error checking is based around individual error checkers (smartcard.sw.ErrorChecker) that can be chained into an error checking chain (smartcars.sw.ErrorCheckingChain).

Error checkers

An error checker is a class deriving from ErrorChecker that checks for recognized sw1, sw2 error conditions when called, and raises an exception when finding such condition. This is illustrated in the following sample:

>>> from smartcard.sw.ISO7816_4ErrorChecker import ISO7816_4ErrorChecker
>>>
>>> errorchecker=ISO7816_4ErrorChecker()
>>> errorchecker( [], 0x90, 0x00 )
>>> errorchecker( [], 0x6A, 0x80 )
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "D:\projects\pyscard-install\factory\python\lib\site-packages\smartcard\sw\ISO7816_4ErrorChecker.py", line 137, in __call__
raise exception( data, sw1, sw2, message )
smartcard.sw.SWExceptions.CheckingErrorException: 'Status word exception: checking error - Incorrect parameters in the data field!'
>>>

The first call to error checker does not raise an exception, since 90 00 does not report any error. The second calls however raises a CheckingErrorException.

to the top

Error checking chains

Error checkers can be chained into error checking chain. Each checker in the chain is called until an error condition is met, in which case an exception is raised. This is illustrated in the following sample:

>>> from smartcard.sw.ISO7816_4ErrorChecker import ISO7816_4ErrorChecker
>>> from smartcard.sw.ISO7816_8ErrorChecker import ISO7816_8ErrorChecker
>>> from smartcard.sw.ISO7816_9ErrorChecker import ISO7816_9ErrorChecker
>>>
>>> from smartcard.sw.ErrorCheckingChain import ErrorCheckingChain
>>>
>>> errorchain = []
>>> errorchain=[ ErrorCheckingChain( errorchain, ISO7816_9ErrorChecker() ),
... ErrorCheckingChain( errorchain, ISO7816_8ErrorChecker() ),
... ErrorCheckingChain( errorchain, ISO7816_4ErrorChecker() ) ]
>>>
>>> errorchain[0]( [], 0x90, 0x00 )
>>> errorchain[0]( [], 0x6A, 0x8a )
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "D:\projects\pyscard-install\factory\python\lib\site-packages\smartcard\sw\ErrorCheckingChain.py", line 60,
in __call__
self.strategy( data, sw1, sw2 )
File "D:\projects\pyscard-install\factory\python\lib\site-packages\smartcard\sw\ISO7816_9ErrorChecker.py", line 74, in __call__
raise exception( data, sw1, sw2, message )
smartcard.sw.SWExceptions.CheckingErrorException: 'Status word exception: checking error - DF name already exists!'
>>>

In this sample, an error checking chain is created that will check first for iso 7816-9 errors, then iso7816-8 errors, and finally iso7816-4 errors.

The first call to the error chain does not raise an exception, since 90 00 does not report any error. The second calls however raises a CheckingErrorException, caused by the iso7816-9 error checker.

to the top

Filtering exceptions

You can filter undesired exceptions in a chain by adding a filtered exception to the error checking chain:

>>> from smartcard.sw.ISO7816_4ErrorChecker import ISO7816_4ErrorChecker
>>> from smartcard.sw.ISO7816_8ErrorChecker import ISO7816_8ErrorChecker
>>> from smartcard.sw.ISO7816_9ErrorChecker import ISO7816_9ErrorChecker
>>>
>>> from smartcard.sw.ErrorCheckingChain import ErrorCheckingChain
>>>
>>> errorchain = []
>>> errorchain=[ ErrorCheckingChain( errorchain, ISO7816_9ErrorChecker() ),
... ErrorCheckingChain( errorchain, ISO7816_8ErrorChecker() ),
... ErrorCheckingChain( errorchain, ISO7816_4ErrorChecker() ) ]
>>>
>>>
>>> errorchain[0]( [], 0x90, 0x00 )
>>> errorchain[0]( [], 0x62, 0x00 )
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "D:\projects\pyscard-install\factory\python\lib\site-packages\smartcard\sw\ErrorCheckingChain.py", line 72, in __call__
return self.next()( data, sw1, sw2 )
File "D:\projects\pyscard-install\factory\python\lib\site-packages\smartcard\sw\ErrorCheckingChain.py", line 72, in __call__
return self.next()( data, sw1, sw2 )
File "D:\projects\pyscard-install\factory\python\lib\site-packages\smartcard\sw\ErrorCheckingChain.py", line 60, in __call__
self.strategy( data, sw1, sw2 )
File "D:\projects\pyscard-install\factory\python\lib\site-packages\smartcard\sw\ISO7816_4ErrorChecker.py", line 137, in __call__
raise exception( data, sw1, sw2, message )
smartcard.sw.SWExceptions.WarningProcessingException: 'Status word exception: warning processing - Response padded/ More APDU commands expected!'
>>>
>>> from smartcard.sw.SWExceptions import WarningProcessingException
>>>
>>> errorchain[0].addFilterException( WarningProcessingException )
>>> errorchain[0]( [], 0x62, 0x00 )
>>>

The first call to the error chain with sw1 sw2 = 62 00 raises a WarningProcessingException.

>>> errorchain[0]( [], 0x62, 0x00 )
Traceback (most recent call last):
...

After adding a filter for WarningProcessingException, the second call to the error chain with sw1 sw2 = 62 00 does not raise any exception:

>>> from smartcard.sw.SWExceptions import WarningProcessingException
>>>
>>> errorchain[0].addFilterException( WarningProcessingException )
>>> errorchain[0]( [], 0x62, 0x00 )
>>>

to the top

Detecting response APDU errors for a card connection

To detect APDU response errors during transmission, simply set the error checking chain of the connection used for transmission:

from smartcard.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver

from smartcard.sw.ErrorCheckingChain import ErrorCheckingChain
from smartcard.sw.ISO7816_4ErrorChecker import ISO7816_4ErrorChecker
from smartcard.sw.ISO7816_8ErrorChecker import ISO7816_8ErrorChecker
from smartcard.sw.SWExceptions import SWException, WarningProcessingException

# request any card
cardtype = AnyCardType()
cardrequest = CardRequest( timeout=10, cardType=cardtype )
cardservice = cardrequest.waitforcard()

# our error checking chain
errorchain=[]
errorchain=[ ErrorCheckingChain( errorchain, ISO7816_8ErrorChecker() ),
             ErrorCheckingChain( errorchain, ISO7816_4ErrorChecker() ) ]
cardservice.connection.setErrorCheckingChain( errorchain )

# a console tracer
observer=ConsoleCardConnectionObserver()
cardservice.connection.addObserver( observer )

# send a few apdus; exceptions will occur upon errors
cardservice.connection.connect()

try:
    SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
    DF_TELECOM = [0x7F, 0x10]
    apdu = SELECT+DF_TELECOM
    response, sw1, sw2 = cardservice.connection.transmit( apdu )
    if sw1 == 0x9F:
        GET_RESPONSE = [0XA0, 0XC0, 00, 00 ]
        apdu = GET_RESPONSE + [sw2]
        response, sw1, sw2 = cardservice.connection.transmit( apdu )
except SWException, e:
    print str(e)


Executing the previous script on a SIM card will cause an output similar to:

connecting to SchlumbergerSema Reflex USB v.2 0
> A0 A4 00 00 02 7F 10
< [] 9F 1A
> A0 C0 00 00 1A
< 00 00 00 00 7F 10 02 00 00 00 00 00 0D 13 00 0A 04 00 83 8A 83 8A 00 01 00 00 90 0
disconnecting from SchlumbergerSema Reflex USB v.2 0
disconnecting from SchlumbergerSema Reflex USB v.2 0

whereas executing the script on a non-SIM card will result in:

connecting to Utimaco CardManUSB 0
> A0 A4 00 00 02 7F 10
< [] 6E 0
'Status word exception: checking error - Class (CLA) not supported!'
disconnecting from Utimaco CardManUSB 0
disconnecting from Utimaco CardManUSB 0

To implement an error checking chain, create an ErrorCheckingChain object with the desired error checking strategies, and set this chain object as the card connection error checking chain. The card connection will use the chain for error checking upon reception of a response apdu:

to the top

Writing a custom error checker

Implementing a custom error checker requires implementing a sub-class of ErrorChecker, and overriding the __call__ method. The following error checker raises a SecurityRelatedException exception when sw1=0x66 and sw2=0x00:

from smartcard.sw.ErrorChecker import ErrorChecker
from smartcard.sw.SWExceptions import SecurityRelatedException

class MyErrorChecker( ErrorChecker ):
    def __call__( self, data, sw1, sw2 ):
        if 0x66==sw1 and 0x00==sw2:
            raise SecurityRelatedException( data, sw1, sw2 )

Custom checkers can be used standalone, as in the following sample, or chained to other error checkers:

from smartcard.CardType import AnyCardType
from smartcard.CardRequest import CardRequest

from smartcard.sw.ErrorCheckingChain import ErrorCheckingChain
from smartcard.sw.ErrorChecker import ErrorChecker
from smartcard.sw.SWExceptions import SecurityRelatedException

class MyErrorChecker( ErrorChecker ):
    def __call__( self, data, sw1, sw2 ):
        if 0x66==sw1 and 0x00==sw2:
            raise SecurityRelatedException( data, sw1, sw2 )

# request any card
cardtype = AnyCardType()
cardrequest = CardRequest( timeout=10, cardType=cardtype )
cardservice = cardrequest.waitforcard()

# our error checking chain
errorchain=[]
errorchain=[ ErrorCheckingChain( [], MyErrorChecker() ) ]
cardservice.connection.setErrorCheckingChain( errorchain )

# send a few apdus; exceptions will occur upon errors
cardservice.connection.connect()

SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
DF_TELECOM = [0x7F, 0x10]
apdu = SELECT+DF_TELECOM
response, sw1, sw2 = cardservice.connection.transmit( apdu )
if sw1 == 0x9F:
    GET_RESPONSE = [0XA0, 0XC0, 00, 00 ]
    apdu = GET_RESPONSE + [sw2]
    response, sw1, sw2 = cardservice.connection.transmit( apdu )



Smartcard readers

Listing Smartcard Readers

The easiest way to retrieve the list of smartcard readers is the smartcard.System.readers() function:

>>> import smartcard.System
>>> print smartcard.System.readers()
['Schlumberger e-gate 0', 'SchlumbergerSema Reflex USB v.2 0', 'Utimaco CardManUSB 0']
>>>

to the top

Organizing Smartcard Readers into reader groups

Reader group management is only available on Windows, since PCSC-lite does not currently supports reader groups management.

Readers can be organized in reader groups. To retrieve the smartcard reader groups, use readergroups():

>>> import smartcard.System
>>> print smartcard.System.readergroups()
['SCard$DefaultReaders']
>>>

The readergroups() object has all the list attributes. To add a reader group, simply use the + operator, e.g.:

>>> from smartcard.System import readergroups
>>> g=readergroups()
>>> print g
['SCard$DefaultReaders']
>>> g+='Biometric$Readers'
>>> print g
['SCard$DefaultReaders', 'Biometric$Readers']
>>>

You can also use the append and insert methods, as well as the + operator, e.g.:

>>> from smartcard.System import readergroups
>>> g=readergroups()
>>> print g
['SCard$DefaultReaders']
>>> g=g+['Biometric$Readers','Pinpad$Readers']
>>> print g
['SCard$DefaultReaders', 'Biometric$Readers', 'Pinpad$Readers']
>>>

or

>>> from smartcard.System import readergroups
>>> g=readergroups()
>>> print g
['SCard$DefaultReaders']
>>> g.append('Biometric$Readers')
>>> g.insert(1,'Pinpad$Readers')
>>> print g
['SCard$DefaultReaders', 'Pinpad$Readers', 'Biometric$Readers']
>>>

Smartcard reader groups are not persistent until a reader as been added to the group. To add a reader to a reader group, use addreadertogroups():

>>> from smartcard.System import readergroups, addreadertogroups, readers
>>> g=readergroups()
>>> g+='USB$Readers'
>>> addreadertogroups( 'Schlumberger e-gate 0', 'USB$Readers' )
>>> readers( 'USB$Readers')
['Schlumberger e-gate 0']
>>>

To remove a reader group, all list operators are available to manage reader groups, including pop() or remove():

>>> from smartcard.System import readergroups, addreadertogroups, readers
>>> g=readergroups()
>>> g+='USB$Readers'
>>> print g
['SCard$DefaultReaders', 'USB$Readers']
>>> g.pop(1)
'USB$Readers'
>>> g
['SCard$DefaultReaders']
>>>

or

>>> from smartcard.System import readergroups, addreadertogroups, readers
>>> g=readergroups()
>>> g+='USB$Readers'
>>> print g
['SCard$DefaultReaders', 'USB$Readers']
>>> readergroups().remove('USB$Readers')
>>> readergroups()
['SCard$DefaultReaders']
>>>

to the top

Monitoring readers

You can monitor the insertion or removal of readers using the ReaderObserver interface.

To monitor reader insertion, create a ReaderObserver object that implements an update() method that will be called upon reader/insertion removal. The following sample code implements a ReaderObserver that simply prints the inserted/removed readers on the standard output:

from smartcard.ReaderMonitoring import ReaderObserver

class printobserver( ReaderObserver ):
    """A simple reader observer that is notified
    when readers are added/removed from the system and
    prints the list of readers
    """
    def update( self, observable, (addedreaders, removedreaders) ):
        print "Added readers", addedreaders
        print "Removed readers", removedreaders
  

To monitor reader insertion/removal, simply add the observer to the ReaderMonitor:

from sys import stdin, exc_info
from time import sleep

from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver

try:
    print "Add or remove a smartcard reader to the system."
    print "This program will exit in 10 seconds"
    print ""
    readermonitor = ReaderMonitor()
    readerobserver = printobserver()
    readermonitor.addObserver( readerobserver )

    sleep(10)

    # don't forget to remove observer, or the
    # monitor will poll forever...
    readermonitor.deleteObserver(readerobserver)

    print 'press Enter to continue'
    stdin.readline()

except error:
    print exc_info()[0], ': ', exc_info()[1]

to the top

Smart Cards

Monitoring Smart Cards

You can monitor the insertion or removal of cards using the CardObserver interface.

To monitor card insertion and removal, create a CardObserver object that implements an update() method that will be called upon card insertion/removal. The following sample code implements a CardObserver that simply prints the inserted/removed cards on the standard output, named printobserver. To monitor card insertion/removal, simply add the card observer to the CardMonitor: :


from smartcard.CardMonitoring import CardMonitor, CardObserver
from smartcard.util import *

# a simple card observer that prints inserted/removed cards
class printobserver( CardObserver ):
    """A simple card observer that is notified
    when cards are inserted/removed from the system and
    prints the list of cards
    """
    def update( self, observable, (addedcards, removedcards) ):
        for card in addedcards:
            print "+Inserted: ", toHexString( card.atr )
        for card in removedcards:
            print "-Removed: ", toHexString( card.atr )

try:
    print "Insert or remove a smartcard in the system."
    print "This program will exit in 10 seconds"
    print ""
    cardmonitor = CardMonitor()
    cardobserver = printobserver()
    cardmonitor.addObserver( cardobserver )

to the top

Sending APDUs to a Smart Card Obtained from Card Monitoring

The update method of the CardObserver receives two lists of Cards objects, the recently added cards and the recently removed cards. A connection can be created to each Card object of the added card list for sending APDUS.

The following sample code implements a CardObserver class named transmitobserver, that connects to inserted cards and transmit an APDU, in our case SELECT DF_TELECOM:

 


# a card observer that connects to new cards and performs a transaction, e.g. SELECT DF_TELECOM
class transmitobserver( CardObserver ):
    """A card observer that is notified when cards are inserted/removed from the system,
    connects to cards and SELECT DF_TELECOM
    """
    def __init__( self ):
        self.cards=[]

    def update( self, observable, (addedcards, removedcards) ):
        for card in addedcards:
            if card not in self.cards:
                self.cards+=[card]
                print "+Inserted: ", toHexString( card.atr )
                card.connection = card.createConnection()
                card.connection.connect()
                response, sw1, sw2 = card.connection.transmit( SELECT_DF_TELECOM )
                print "%.2x %.2x" % (sw1, sw2)

        for card in removedcards:
            print "-Removed: ", toHexString( card.atr )
            if card in self.cards:
                self.cards.remove( card )

To monitor card insertion, connect to inserted cards and send the APDU, create an instance of transmitobserver and add it to the CardMonitor: :


from time import sleep
print "Insert or remove a smartcard in the system."
print "This program will exit in 100 seconds"
print ""
cardmonitor = CardMonitor()
cardobserver = transmitobserver()
cardmonitor.addObserver( cardobserver )

sleep(100)

to the top

Connections

Connecting to a card and sending APDUs is done thru a CardConnection object. CardConnection objects are created using a CardRequest, or by the CardMonitoring.

Creating a Connection from a CardRequest

A successful CardRequest returns a CardService matching the requested card service for the card, or a PassThruCardService if no specific card service was required:

>>> from smartcard.CardType import AnyCardType
>>> from smartcard.CardRequest import CardRequest
>>> from smartcard.util import toHexString
>>>
>>> cardtype = AnyCardType()
>>> cardrequest = CardRequest( timeout=1, cardType=cardtype )
>>> cardservice = cardrequest.waitforcard()
>>>
>>> cardservice.connection.connect()
>>> print toHexString( cardservice.connection.getATR() )
3B 16 94 20 02 01 00 00 0D
>>> print cardservice.connection.getReader()
SchlumbergerSema Reflex USB v.2 0

Each CardService has a connection attribute, which is a CardConnection for the card.

to the top

Creating Connection from CardMonitoring

The update method of a CardObserver receives a tuple with a list of connected cards and a list of removed cards. To create a CardConnection from a card object, use the createConnection() method of the desired card:

 


class myobserver( CardObserver ):
    def update( self, observable, (addedcards, removedcards) ):
        for card in addedcards:
                print "+Inserted: ", toHexString( card.atr )
                card.connection = card.createConnection()
                card.connection.connect()
                response, sw1, sw2 = card.connection.transmit( SELECT_DF_TELECOM )
                print "%.2x %.2x" % (sw1, sw2)

to the top

Card Connection Decorators

APDUs are transmitted to a card using the CardConnection object. It is sometime useful to change transparently the behaviour of a smart card connection, for example to establish automatically a secure channel, or filter and modify on the fly some APDU commands or responses, or the smart card ATR. pyscard uses theDecorator design pattern to dynamically change the behaviour of a smart card connection. A CardConnectionDecorator modifies the behaviour of a CardConnection object. For example, the following CardConnectionDecorator overwrites the CardConnection getATR() method:


class FakeATRConnection( CardConnectionDecorator ):
    '''This decorator changes the fist byte of the ATR.'''
    def __init__( self, cardconnection ):
        CardConnectionDecorator.__init__( self, cardconnection )

    def getATR( self ):
        """Replace first BYTE of ATR by 3F"""
        atr = CardConnectionDecorator.getATR( self )
        return [ 0x3f ] + atr [1:]

To apply the decorator, just construct the decorator around the CardConnection instance to wrap and use the decorator in place of the card connection object:


# request any card type
cardtype = AnyCardType()
cardrequest = CardRequest( timeout=1.5, cardType=cardtype )
cardservice = cardrequest.waitforcard()

# attach the console tracer
observer=ConsoleCardConnectionObserver()
cardservice.connection.addObserver( observer )

# attach our decorator
cardservice.connection = FakeATRConnection( cardservice.connection )

# connect to the card and perform a few transmits
cardservice.connection.connect()

print 'ATR', toHexString( cardservice.connection.getATR() )

Decorators can be nested. For example to nest a FakeATRConnection with a SecureChannelConnection, use the following construction:


# attach our decorator
FakeATRConnection( SecureChannelConnection( cardservice.connection ) )

# connect to the card and perform a few transmits
cardservice.connection.connect()

print 'ATR', toHexString( cardservice.connection.getATR() )

Exclusive Card Connection Decorator

The ExclusiveConnectCardConnection object performs an exclusive connection to the card, i.e. no other thread or process will be able to connect to the card. With PCSC readers, this is done by performing a SCardConnect with the SCARD_SHARE_EXCLUSIVE attribute.


from smartcard.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.CardConnection import CardConnection
from smartcard.util import toHexString

from smartcard.ExclusiveConnectCardConnection import ExclusiveConnectCardConnection

# request any card type
cardtype = AnyCardType()
cardrequest = CardRequest( timeout=5, cardType=cardtype )
cardservice = cardrequest.waitforcard()

# attach our decorator
cardservice.connection = ExclusiveConnectCardConnection( cardservice.connection )

# connect to the card and perform a few transmits
cardservice.connection.connect()

print 'ATR', toHexString( cardservice.connection.getATR() )

to the top

Exclusive Transmit Card Connection Decorator

The ExclusiveTransmitCardConnection performs an exclusive transaction to the card, i.e. a series of transmit that cannot be interupted by other threads' transmits. To do so, include the desired transmits between an lock() and unlock() method call on the ExclusiveTransmitCardConnection:


from smartcard.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver
from smartcard.CardConnection import CardConnection
from smartcard.util import toHexString

from smartcard.ExclusiveTransmitCardConnection import ExclusiveTransmitCardConnection


# define the apdus used in this script
GET_RESPONSE = [0XA0, 0XC0, 00, 00 ]
SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
DF_TELECOM = [0x7F, 0x10]

# request any card type
cardtype = AnyCardType()
cardrequest = CardRequest( timeout=5, cardType=cardtype )
cardservice = cardrequest.waitforcard()

# attach the console tracer
observer=ConsoleCardConnectionObserver()
cardservice.connection.addObserver( observer )

# attach our decorator
cardservice.connection = ExclusiveTransmitCardConnection( cardservice.connection )

# connect to the card and perform a few transmits
cardservice.connection.connect()

print 'ATR', toHexString( cardservice.connection.getATR() )

try:
    # lock for initiating transaction
    cardservice.connection.lock()

    apdu = SELECT+DF_TELECOM
    response, sw1, sw2 = cardservice.connection.transmit( apdu )

    if sw1 == 0x9F:
        apdu = GET_RESPONSE + [sw2]
        response, sw1, sw2 = cardservice.connection.transmit( apdu )
finally:
    # unlock connection at the end of the transaction
    cardservice.connection.unlock()

to the top

Secure Channel Card Connection Decorator

Another sample of application of CardConnection decorators is to implement secure channel. The following sample is a template CardConnection decorator for secure channel, where each command APDU is cyphered and each response APDU is uncyphered:


class SecureChannelConnection( CardConnectionDecorator ):
    '''This decorator is a mockup of secure channel connection.
    It merely pretends to cypher/uncypher upon apdu transmission.'''
    def __init__( self, cardconnection ):
        CardConnectionDecorator.__init__( self, cardconnection )

    def cypher( self, bytes ):
        '''Cypher mock-up; you would include the secure channel logics here.'''
        print 'cyphering', toHexString( bytes )
        return bytes

    def uncypher( self, data ):
        '''Uncypher mock-up; you would include the secure channel logics here.'''
        print 'uncyphering', toHexString( data )
        return data

    def transmit( self, bytes, protocol=None ):
        """Cypher/uncypher APDUs before transmission"""
        cypheredbytes = self.cypher( bytes )
        data, sw1, sw2 = CardConnectionDecorator.transmit( self, cypheredbytes, protocol )
        if []!=data:
            data = self.uncypher( data )
        return data, sw1, sw2

to the top

A word on cryptography

Smart card are security devices. As a result, smart card applications usually require some kind cryptography, for example to establish a secure channel with the smart card. One of the reference cryptographic modules for python is pycrypto, the python cryptographic toolkit. This section shows briefly the basics of pycrypto to give you a quick start to include cryptography in you python smart card applications.

Bynary strings and list of bytes

pycrypto processes binary strings, i.e. python strings that contains characters such as '\01\42\70\23', whereas pyscard processes APDUs as list of bytes such as [0x01, 0x42, 0x70, 0x23]. The utility function HexListToBinString and BinStringToHexList (and their short name versions hl2bs and bs2hl) provide conversion between the two types.

from smartcard.util import HexListToBinString, BinStringToHexList
test_data = [ 0x01, 0x42, 0x70, 0x23 ]
binstring = HexListToBinString( test_data )
hexlist = BinStringToHexList( binstring )
print binstring, hexlist
?Bp# [1, 66, 112, 35]

Hashing

pycrypto supports the following hashing algorithms: SHA-1, MD2, MD4 et MD5. To hash 16 bytes of data with SHA-1:

from Crypto.Hash import SHA

from smartcard.util import toHexString, PACK

test_data = [ 0x01, 0x42, 0x70, 0x23 ]
binstring = HexListToBinString( test_data )

zhash = SHA.new( binstring )
hash_as_string = zhash.digest()[:16]
hash_as_bytes = BinStringToHexList( hash_as_string )
print hash_as_string, ',', toHexString( hash_as_bytes, PACK )

To perform MD5 hashing, just replace SHA by MD5 in the previous script.

Secret key cryptography

pycrypto supports several secret key algorithms, such as DES, triple DES, AES, blowfish, or IDEA. To perform triple DES ciphering in ECB mode:

from Crypto.Cipher import DES3

from smartcard.util import toBytes

key = "31323334353637383132333435363738"
key_as_binstring = HexListToBinString( toBytes( key ) )
zdes = DES3.new( key_as_binstring, DES3.MODE_ECB )

message = "71727374757677787172737475767778"
message_as_binstring = HexListToBinString( toBytes( message ) )

encrypted_as_string = zdes.encrypt( message_as_binstring )
decrypted_as_string = zdes.decrypt( encrypted_as_string )
print message_as_binstring, encrypted_as_string, decrypted_as_string

License

GNU LESSER GENERAL PUBLIC LICENSE

Version 2.1, February 1999

Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]

Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.

This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.

When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.

To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.

For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.

We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.

To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.

Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.

Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.

When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.

We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.

For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.

In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.

Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.

The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run.

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".

A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.

The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".)

"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.

Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.

1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.

You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.

2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:

* a) The modified work must itself be a software library.
* b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
* c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
* d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.

(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)

These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.

In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.

3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices.

Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.

This option is useful when you wish to copy part of the code of the Library into a program that is not a library.

4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.

If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.

5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License.

However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables.

When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.

If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)

Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.

6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications.

You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:

* a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
* b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.
* c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
* d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
* e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.

For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.

It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.

7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:

* a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
* b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.

8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.

10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.

11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.

If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.

This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.

12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.

13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.

14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

NO WARRANTY

15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.


pyscard-1.6.14/smartcard/sw/0000755000175000017500000000000011747777125017441 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/sw/ISO7816_8ErrorChecker.py0000644000175000017500000001214511747776676023536 0ustar rousseaurousseau00000000000000"""ISO7816-8 error checker. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.sw.ErrorChecker import ErrorChecker import smartcard.sw.SWExceptions iso7816_8SW = { 0x63: (smartcard.sw.SWExceptions.WarningProcessingException, {0x00: "Authentication failed", 0xC0: "PIN verification failed. 0 retries before blocking PIN", 0xC1: "PIN verification failed. 1 retries before blocking PIN", 0xC2: "PIN verification failed. 2 retries before blocking PIN", 0xC3: "PIN verification failed. 3 retries before blocking PIN", 0xC4: "PIN verification failed. 4 retries before blocking PIN", 0xC5: "PIN verification failed. 5 retries before blocking PIN", 0xC6: "PIN verification failed. 6 retries before blocking PIN", 0xC7: "PIN verification failed. 7 retries before blocking PIN", 0xC8: "PIN verification failed. 8 retries before blocking PIN", 0xC9: "PIN verification failed. 9 retries before blocking PIN", 0xCA: "PIN verification failed. 10 retries before blocking PIN", 0xCB: "PIN verification failed. 11 retries before blocking PIN", 0xCC: "PIN verification failed. 12 retries before blocking PIN", 0xCD: "PIN verification failed. 13 retries before blocking PIN", 0xCE: "PIN verification failed. 14 retries before blocking PIN", 0xCF: "PIN verification failed. 15 retries before blocking PIN"}), 0x65: (smartcard.sw.SWExceptions.ExecutionErrorException, {0x81: "Memory failure (unsuccessful changing)"}), 0x66: (smartcard.sw.SWExceptions.SecurityRelatedException, {0x00: "The environment cannot be set or modified", 0x87: "Expected SM data objects missing", 0x88: "SM data objects incorrect"}), 0x67: (smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Wrong length (emtpy Lc field)"}), 0x68: (smartcard.sw.SWExceptions.CheckingErrorException, {0x83: "Final command expected", 0x84: "Command chaining not supported"}), 0x69: (smartcard.sw.SWExceptions.CheckingErrorException, {0x82: "Security status not satisfied", 0x83: "Authentification method blocked", 0x84: "Referenced data invalidated", 0x85: "Conditions of use not satisfied"}), 0x6A: (smartcard.sw.SWExceptions.CheckingErrorException, {0x81: "Function not supported", 0x82: "File not found", 0x86: "Incorrect parameters P1-P2", 0x88: "Referenced data not found"}), } class ISO7816_8ErrorChecker(ErrorChecker): """ISO7816-8 error checker. This error checker raises the following exceptions: - sw1 sw2 - 63 00,c0-cf WarningProcessingException - 65 81 ExecutionErrorException - 66 00,87,88 SecurityRelatedException - 67 00 CheckingErrorException - 68 82,84 CheckingErrorException - 69 82,83,84,85 CheckingErrorException - 6A 81,82,86,88 CheckingErrorException This checker does not raise exceptions on undefined sw1 values, e.g.: - sw1 sw2 - 62 any - 6f any and on undefined sw2 values, e.g.: - sw1 sw2 - 66 81 82 - 67 any except 00 Use another checker in the error checking chain, e.g., the ISO7816_4SW1ErrorChecker or ISO7816_4ErrorChecker, to raise exceptions on these undefined values. """ def __call__(self, data, sw1, sw2): """Called to test data, sw1 and sw2 for error. @param data: apdu response data @param sw1, sw2: apdu data status words Derived classes must raise a L{smartcard.sw.SWException} upon error.""" if sw1 in iso7816_8SW: exception, sw2dir = iso7816_8SW[sw1] if type(sw2dir) == type({}): try: message = sw2dir[sw2] raise exception(data, sw1, sw2, message) except KeyError: pass if __name__ == '__main__': """Small sample illustrating the use of ISO7816_8ErrorChecker.""" ecs = ISO7816_8ErrorChecker() ecs([], 0x90, 0x00) ecs([], 0x6a, 0x83) try: ecs([], 0x66, 0x87) except smartcard.sw.SWExceptions.SecurityRelatedException, e: print e, "%x %x" % (e.sw1, e.sw2) pyscard-1.6.14/smartcard/sw/ISO7816_4_SW1ErrorChecker.py0000644000175000017500000000623611747776676024230 0ustar rousseaurousseau00000000000000"""ISO7816-4 sw1 only error checker. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.sw.ErrorChecker import ErrorChecker import smartcard.sw.SWExceptions iso7816_4SW1 = { 0x62: smartcard.sw.SWExceptions.WarningProcessingException, 0x63: smartcard.sw.SWExceptions.WarningProcessingException, 0x64: smartcard.sw.SWExceptions.ExecutionErrorException, 0x65: smartcard.sw.SWExceptions.ExecutionErrorException, 0x66: smartcard.sw.SWExceptions.SecurityRelatedException, 0x67: smartcard.sw.SWExceptions.CheckingErrorException, 0x68: smartcard.sw.SWExceptions.CheckingErrorException, 0x69: smartcard.sw.SWExceptions.CheckingErrorException, 0x6A: smartcard.sw.SWExceptions.CheckingErrorException, 0x6B: smartcard.sw.SWExceptions.CheckingErrorException, 0x6C: smartcard.sw.SWExceptions.CheckingErrorException, 0x6D: smartcard.sw.SWExceptions.CheckingErrorException, 0x6E: smartcard.sw.SWExceptions.CheckingErrorException, 0x6F: smartcard.sw.SWExceptions.CheckingErrorException, } class ISO7816_4_SW1ErrorChecker(ErrorChecker): """ISO7816-4 error checker based on status word sw1 only. This error checker raises the following exceptions: - sw1 sw2 - 62 any WarningProcessingException - 63 any WarningProcessingException - 64 any ExecutionErrorException - 65 any ExecutionErrorException - 66 any SecurityRelatedException - 67 any CheckingErrorException - 68 any CheckingErrorException - 69 any CheckingErrorException - 6a any CheckingErrorException - 6b any CheckingErrorException - 6c any CheckingErrorException - 6d any CheckingErrorException - 6e any CheckingErrorException - 6f any CheckingErrorException """ def __call__(self, data, sw1, sw2): """Called to test data, sw1 and sw2 for error. @param data: apdu response data @param sw1, sw2: apdu data status words """ if sw1 in iso7816_4SW1: exception = iso7816_4SW1[sw1] raise exception(data, sw1, sw2) if __name__ == '__main__': """Small sample illustrating the use of ISO7816_4_SW1ErrorChecker.""" ecs = ISO7816_4_SW1ErrorChecker() ecs([], 0x90, 0x00) try: ecs([], 0x66, 0x80) except smartcard.sw.SWExceptions.SecurityRelatedException, e: print e, "%x %x" % (e.sw1, e.sw2) pyscard-1.6.14/smartcard/sw/__init__.py0000644000175000017500000000162611747776676021571 0ustar rousseaurousseau00000000000000"""smartcard.sw module for status word error checking. __author__ = "gemalto http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ pyscard-1.6.14/smartcard/sw/ISO7816_4ErrorChecker.py0000644000175000017500000001470311747776676023534 0ustar rousseaurousseau00000000000000"""ISO7816-4 error checking strategy. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.sw.ErrorChecker import ErrorChecker import smartcard.sw.SWExceptions iso7816_4SW = { 0x62: (smartcard.sw.SWExceptions.WarningProcessingException, {0x00: "Response padded/ More APDU commands expected", 0x81: "Part of returned data may be corrupted", 0x82: "End of file/record reached before reading Le bytes", 0x83: "File invalidated", 0x84: "FCI not correctly formatted", 0xFF: "Correct execution, response padded"}), 0x63: (smartcard.sw.SWExceptions.WarningProcessingException, {0x00: "Authentication failed", 0x81: "File filled up by the last write", 0xC0: "PIN verification failed. 0 tries before blocking PIN", 0xC1: "PIN verification failed. 1 tries before blocking PIN", 0xC2: "PIN verification failed. 2 tries before blocking PIN", 0xC3: "PIN verification failed. 3 tries before blocking PIN", 0xC4: "PIN verification failed. 4 tries before blocking PIN", 0xC5: "PIN verification failed. 5 tries before blocking PIN", 0xC6: "PIN verification failed. 6 tries before blocking PIN", 0xC7: "PIN verification failed. 7 tries before blocking PIN", 0xC8: "PIN verification failed. 8 tries before blocking PIN", 0xC9: "PIN verification failed. 9 tries before blocking PIN", 0xCA: "PIN verification failed. 10 tries before blocking PIN", 0xCB: "PIN verification failed. 11 tries before blocking PIN", 0xCC: "PIN verification failed. 12 tries before blocking PIN", 0xCD: "PIN verification failed. 13 tries before blocking PIN", 0xCE: "PIN verification failed. 14 tries before blocking PIN", 0xCF: "PIN verification failed. 15 tries before blocking PIN"}), 0x64: (smartcard.sw.SWExceptions.ExecutionErrorException, {0x00: "Integrity error detected in EEPROM"}), 0x67: (smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Wrong length in Lc"}), 0x68: (smartcard.sw.SWExceptions.CheckingErrorException, {0x81: "Logical channel not supported", 0x82: "Secure messaging not supported"}), 0x69: (smartcard.sw.SWExceptions.CheckingErrorException, {0x81: "Command incompatible with file structure.", 0x82: "Security status not satisfied", 0x83: "Authentification method blocked", 0x84: "Referenced data invalid", 0x85: "Conditions of use not satisfied", 0x86: "Command not allowed (no current EF)", 0x87: "Secure messaging data object missing.", 0x88: "Secure messaging data object incorrect"}), 0x6A: (smartcard.sw.SWExceptions.CheckingErrorException, {0x80: "Incorrect parameters in the data field", 0x81: "Function not supported", 0x82: "File not found", 0x83: "Record not found", 0x84: "Not enough memory space in the file", 0x85: "Lc inconsistent with TLV structure", 0x86: "Incorrect parameters P1-P2", 0x87: "Lc is inconsistent with P1-P2", 0x88: "Referenced data not found"}), 0x6B: (smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Incorrect parameters P1-P2"}), 0x6D: (smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Instruction (INS) not supported"}), 0x6E: (smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Class (CLA) not supported"}), 0x6F: (smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Fatal error"}), } class ISO7816_4ErrorChecker(ErrorChecker): """ISO7816-4 error checking strategy. This strategy raises the following exceptions: - sw1 sw2 - 62 00 81 82 83 84 FF WarningProcessingException - 63 00 81 C0->CF WarningProcessingException - 64 00 ExecutionErrorException - 67 00 CheckingErrorException - 68 81 82 CheckingErrorException - 69 81->88 99? c1? CheckingErrorException - 6a 80->88 CheckingErrorException - 6b 00 CheckingErrorException - 6d 00 CheckingErrorException - 6e 00 CheckingErrorException - 6f 00 CheckingErrorException This checker does not raise exceptions on undefined sw1 values, e.g.: - sw1 sw2 - 65 any - 66 any - 6c any and on undefined sw2 values, e.g.: - sw1 sw2 - 62 80 85 - 6b any except 00 Use another checker in the error checking chain, e.g., the ISO7816_4SW1ErrorChecker, to raise exceptions on these undefined values. """ def __call__(self, data, sw1, sw2): """Called to test data, sw1 and sw2 for error. @param data: apdu response data @param sw1, sw2: apdu data status words Derived classes must raise a L{smartcard.sw.SWException} upon error.""" if sw1 in iso7816_4SW: exception, sw2dir = iso7816_4SW[sw1] if type(sw2dir) == type({}): try: message = sw2dir[sw2] raise exception(data, sw1, sw2, message) except KeyError: pass if __name__ == '__main__': """Small sample illustrating the use of ISO7816_4ErrorChecker.""" ecs = ISO7816_4ErrorChecker() ecs([], 0x90, 0x00) try: ecs([], 0x6b, 0x00) except smartcard.sw.SWExceptions.CheckingErrorException, e: print e, "%x %x" % (e.sw1, e.sw2) pyscard-1.6.14/smartcard/sw/ErrorCheckingChain.py0000644000175000017500000000613611747776676023523 0ustar rousseaurousseau00000000000000"""The error checking chain is a list of status word (sw1, sw2) error check strategies. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from sys import exc_info class ErrorCheckingChain(object): """The error checking chain is a list of response apdu status word (sw1, sw2) error check strategies. Each strategy in the chain is called until an error is detected. A L{smartcard.sw.SWException} exception is raised when an error is detected. No exception is raised if no error is detected. Implementation derived from Bruce Eckel, Thinking in Python. The L{ErrorCheckingChain} implements the Chain Of Responsibility design pattern. """ def __init__(self, chain, strategy): """constructor. Appends a strategy to the L{ErrorCheckingChain} chain.""" self.strategy = strategy self.chain = chain self.chain.append(self) self.excludes = [] def next(self): """Returns next error checking strategy.""" # Where this link is in the chain: location = self.chain.index(self) if not self.end(): return self.chain[location + 1] def addFilterException(self, exClass): """Add an exception filter to the error checking chain. @param exClass: the exception to exclude, e.g. L{smartcard.sw.SWExceptions.WarningProcessingException} A filtered exception will not be raised when the sw1,sw2 conditions that would raise the excption are met. """ self.excludes.append(exClass) if self.end(): return self.next().addFilterException(exClass) def end(self): """Returns True if this is the end of the error checking strategy chain.""" return (self.chain.index(self) + 1 >= len(self.chain)) def __call__(self, data, sw1, sw2): """Called to test data, sw1 and sw2 for error on the chain.""" try: self.strategy(data, sw1, sw2) except: # if exception is filtered, return for exception in self.excludes: if exception == exc_info()[0]: return # otherwise reraise exception raise # if not done, call next strategy if self.end(): return return self.next()(data, sw1, sw2) pyscard-1.6.14/smartcard/sw/op21_ErrorChecker.py0000644000175000017500000001033111747776676023242 0ustar rousseaurousseau00000000000000"""Open Platform 2.1 error checker. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.sw.ErrorChecker import ErrorChecker import smartcard.sw.SWExceptions op21_SW = { 0x62: (smartcard.sw.SWExceptions.WarningProcessingException, {0x83: "Card life cycle is CARD_LOCKED"}), 0x63: (smartcard.sw.SWExceptions.WarningProcessingException, {0x00: "Authentication failed"}), 0x64: (smartcard.sw.SWExceptions.ExecutionErrorException, {0x00: "Execution error"}), 0x65: (smartcard.sw.SWExceptions.ExecutionErrorException, {0x81: "Memory failure"}), 0x67: (smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Wrong length in Lc"}), 0x69: (smartcard.sw.SWExceptions.CheckingErrorException, {0x82: "Security status not satisfied", 0x85: "Conditions of use not satisfied"}), 0x6A: (smartcard.sw.SWExceptions.CheckingErrorException, {0x80: "Incorrect values in command data", 0x81: "Function not supported", 0x82: "Application not found", 0x84: "Not enough memory space", 0x86: "Incorrect parameters P1-P2", 0x88: "Referenced data not found"}), 0x6D: (smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Instruction not supported"}), 0x6E: (smartcard.sw.SWExceptions.CheckingErrorException, {0x00: "Class not supported"}), 0x94: (smartcard.sw.SWExceptions.CheckingErrorException, {0x84: "Algorithm not supported", 0x85: "Invalid key check value"}), } class op21_ErrorChecker(ErrorChecker): """Open platform 2.1 error checker. This error checker raises the following exceptions: - sw1 sw2 - 62 83 WarningProcessingException - 63 00 WarningProcessingException - 64 00 ExecutionErrorException - 65 81 ExecutionErrorException - 67 00 CheckingErrorException - 69 82 85 CheckingErrorException - 6A 80 81 82 84 86 88 CheckingErrorException - 6D 00 CheckingErrorException - 6E 00 CheckingErrorException - 94 84 85 CheckingErrorException This checker does not raise exceptions on undefined sw1 values, e.g.: - sw1 sw2 - 63 any - 6F any and on undefined sw2 values, e.g.: - sw1 sw2 - 62 81 83 - 64 any except 00 Use another checker in the error checking chain to raise exceptions on these undefined values. """ def __call__(self, data, sw1, sw2): """Called to test data, sw1 and sw2 for error. @param data: apdu response data @param sw1, sw2: apdu data status words Derived classes must raise a L{smartcard.sw.SWException} upon error.""" if sw1 in op21_SW: exception, sw2dir = op21_SW[sw1] if type(sw2dir) == type({}): try: message = sw2dir[sw2] raise exception(data, sw1, sw2, message) except KeyError: pass if __name__ == '__main__': """Small sample illustrating the use of op21_ErrorChecker.""" ecs = op21_ErrorChecker() ecs([], 0x90, 0x00) ecs([], 0x94, 0x81) try: ecs([], 0x94, 0x84) except smartcard.sw.SWExceptions.CheckingErrorException, e: print e, "%x %x" % (e.sw1, e.sw2) pyscard-1.6.14/smartcard/sw/ErrorChecker.py0000644000175000017500000000326211747776676022406 0ustar rousseaurousseau00000000000000"""Base class for status word error checkers. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ class ErrorChecker(object): """Base class for status word error checking strategies. Error checking strategies are chained into an L{ErrorCheckingChain} to implement a Chain of Responsibility. Each strategy in the chain is called until an error is detected. The strategy raises a L{smartcard.sw.SWException} exception when an error is detected. Implementation derived from Bruce Eckel, Thinking in Python. The L{ErrorCheckingChain} implements the Chain Of Responsibility design pattern. """ def __call__(data, sw1, sw2): """Called to test data, sw1 and sw2 for error. @param data: apdu response data @param sw1, sw2: apdu data status words Derived classes must raise a L{smartcard.sw.SWException} upon error.""" pass pyscard-1.6.14/smartcard/sw/SWExceptions.py0000644000175000017500000000541311747776676022423 0ustar rousseaurousseau00000000000000"""Status Word (SW) Exceptions This module defines the exceptions raised by status word errors or warnings. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ class SWException(Exception): """Base class for status word exceptions. Status word exceptions are generated when errors and warnings are detected in the sw1 and sw2 bytes of the response apdu. """ def __init__(self, data, sw1, sw2, message=""): self.message = message """response apdu data""" self.data = data """response apdu sw1""" self.sw1 = sw1 """response apdu sw2""" self.sw2 = sw2 def __str__(self): return repr('Status word exception: ' + self.message + '!') class WarningProcessingException(SWException): """Raised when a warning processing is detected from sw1, sw2. Examples of warning processing exception: sw1=62 or sw=63 (ISO7816-4).""" def __init__(self, data, sw1, sw2, message=""): SWException.__init__( self, data, sw1, sw2, "warning processing - " + message) class ExecutionErrorException(SWException): """Raised when an execution error is detected from sw1, sw2. Examples of execution error: sw1=64 or sw=65 (ISO7816-4).""" def __init__(self, data, sw1, sw2, message=""): SWException.__init__( self, data, sw1, sw2, "execution error - " + message) class SecurityRelatedException(SWException): """Raised when a security issue is detected from sw1, sw2. Examples of security issue: sw1=66 (ISO7816-4).""" def __init__(self, data, sw1, sw2, message=""): SWException.__init__( self, data, sw1, sw2, "security issue - " + message) class CheckingErrorException(SWException): """Raised when a checking error is detected from sw1, sw2. Examples of checking error: sw1=67 to 6F (ISO781604).""" def __init__(self, data, sw1, sw2, message=""): SWException.__init__( self, data, sw1, sw2, "checking error - " + message) pyscard-1.6.14/smartcard/sw/ISO7816_9ErrorChecker.py0000644000175000017500000000617111747776676023541 0ustar rousseaurousseau00000000000000"""ISO7816-9 error checker. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.sw.ErrorChecker import ErrorChecker import smartcard.sw.SWExceptions iso7816_9SW = { 0x62: (smartcard.sw.SWExceptions.WarningProcessingException, {0x82: "End of file/record reached"}), 0x64: (smartcard.sw.SWExceptions.ExecutionErrorException, {0x00: "Execution error"}), 0x69: (smartcard.sw.SWExceptions.CheckingErrorException, {0x82: "Security status not satisfied"}), 0x6A: (smartcard.sw.SWExceptions.CheckingErrorException, {0x80: "Incorrect parameters in data field", 0x84: "Not enough memory space", 0x89: "File already exists", 0x8A: "DF name already exists"}), } class ISO7816_9ErrorChecker(ErrorChecker): """ISO7816-8 error checker. This error checker raises the following exceptions: - sw1 sw2 - 62 82 WarningProcessingException - 64 00 ExecutionErrorException - 69 82 CheckingErrorException - 6A 80,84,89,8A CheckingErrorException This checker does not raise exceptions on undefined sw1 values, e.g.: - sw1 sw2 - 63 any - 6F any and on undefined sw2 values, e.g.: - sw1 sw2 - 62 81 83 - 64 any except 00 Use another checker in the error checking chain, e.g., the ISO7816_4SW1ErrorChecker or ISO7816_4ErrorChecker, to raise exceptions on these undefined values. """ def __call__(self, data, sw1, sw2): """Called to test data, sw1 and sw2 for error. @param data: apdu response data @param sw1, sw2: apdu data status words Derived classes must raise a L{smartcard.sw.SWException} upon error.""" if sw1 in iso7816_9SW: exception, sw2dir = iso7816_9SW[sw1] if type(sw2dir) == type({}): try: message = sw2dir[sw2] raise exception(data, sw1, sw2, message) except KeyError: pass if __name__ == '__main__': """Small sample illustrating the use of ISO7816_9ErrorChecker.""" ecs = ISO7816_9ErrorChecker() ecs([], 0x90, 0x00) ecs([], 0x6a, 0x81) try: ecs([], 0x6A, 0x8A) except smartcard.sw.SWExceptions.CheckingErrorException, e: print e, "%x %x" % (e.sw1, e.sw2) pyscard-1.6.14/smartcard/test/0000755000175000017500000000000011747777125017767 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/test/framework/0000755000175000017500000000000011747777125021764 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/test/framework/testcase_utils.py0000755000175000017500000001261711747776700025401 0ustar rousseaurousseau00000000000000#! /usr/bin/env python # -*- coding: iso-8859-1 -*- """Unit tests for smartcard.utils This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest from smartcard.util import * class testcase_utils(unittest.TestCase): """Test smartcard.utils.""" def testcase_asciitostring(self): """tests ASCIIToString""" self.assertEquals( toASCIIString( [0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x20, 0x31, 0x30, 0x31]), "Number 101") def testcase_bytesto338(self): """tests toGSM3_38Bytes""" self.assertEquals( toGSM3_38Bytes("@ùPascal"), [0x00, 0x06, 0x50, 0x61, 0x73, 0x63, 0x61, 0x6C]) def testcase_padd(self): """tests padd""" self.assertEquals( [0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], padd([0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3], 16)) self.assertEquals([0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3], padd([0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3], 9)) self.assertEquals([0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3], padd([0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3], 8)) self.assertEquals([0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3, 0xFF], padd([0x3B, 0x65, 0, 0, 0x9C, 0x11, 1, 1, 3], 10)) def testcase_toasciibytes(self): """tests toASCIIBytes""" self.assertEquals( [0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x20, 0x31, 0x30, 0x31], toASCIIBytes("Number 101")) self.assertEquals( toASCIIString(toASCIIBytes("Number 101")), "Number 101") def testcase_tobytestring(self): """tests toByteString""" self.assertEquals( [59, 101, 0, 0, 156, 17, 1, 1, 3], toBytes("3B 65 00 00 9C 11 01 01 03")) self.assertEquals( [59, 101, 0, 0, 156, 17, 1, 1, 3], toBytes("3B6500009C11010103")) self.assertEquals( [59, 101, 0, 0, 156, 17, 1, 1, 3], toBytes("3B65 0000 9C11 010103")) self.assertEquals( [59, 101, 0, 0, 156, 17, 1, 1, 3], toBytes("3B65 \t\t0000 \t9C11 \t0101\t03 \t\n")) def testcase_tohexstring(self): """tests toHexString""" self.assertEquals( "3B 65 00 00 9C 11 01 01 03", toHexString([59, 101, 0, 0, 156, 17, 1, 1, 3])) bytes = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03] self.assertEquals( "3B, 65, 00, 00, 9C, 11, 01, 01, 03", toHexString(bytes, COMMA)) self.assertEquals("3B6500009C11010103", toHexString(bytes, PACK)) self.assertEquals( "0x3B 0x65 0x00 0x00 0x9C 0x11 0x01 0x01 0x03", toHexString(bytes, HEX)) self.assertEquals( "0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03", toHexString(bytes, HEX | COMMA)) self.assertEquals( "0X3B 0X65 0X00 0X00 0X9C 0X11 0X01 0X01 0X03", toHexString(bytes, HEX | UPPERCASE)) self.assertEquals( "0X3B, 0X65, 0X00, 0X00, 0X9C, 0X11, 0X01, 0X01, 0X03", toHexString(bytes, HEX | UPPERCASE | COMMA)) bytes = [59, 101, 0, 0, 156, 17, 1, 1, 3] self.assertEquals( "3B, 65, 00, 00, 9C, 11, 01, 01, 03", toHexString(bytes, COMMA)) self.assertEquals( "3B6500009C11010103", toHexString(bytes, PACK)) self.assertEquals( "0x3B 0x65 0x00 0x00 0x9C 0x11 0x01 0x01 0x03", toHexString(bytes, HEX)) self.assertEquals( "0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03", toHexString(bytes, HEX | COMMA)) self.assertEquals( "0X3B 0X65 0X00 0X00 0X9C 0X11 0X01 0X01 0X03", toHexString(bytes, HEX | UPPERCASE)) self.assertEquals( "0X3B, 0X65, 0X00, 0X00, 0X9C, 0X11, 0X01, 0X01, 0X03", toHexString(bytes, HEX | UPPERCASE | COMMA)) def testcase_tohexstring_empty(self): """tests toHexString""" self.assertEquals("", toHexString()) self.assertEquals("", toHexString([])) def testcase_tohexstring_nobytes(self): """tests toHexString""" self.assertRaises(TypeError, toHexString, 'bad input') self.assertRaises(TypeError, toHexString, ['bad', 'input']) def suite(): suite1 = unittest.makeSuite(testcase_utils) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testcase_CardMonitor.py0000755000175000017500000000616011747776700026456 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.CardMonitoring. This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 threading import unittest import time # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader except: print 'execute test suite first to generate the local_config.py file' sys.exit() from smartcard.CardMonitoring import CardMonitor, CardObserver from smartcard.util import toHexString # a simple card observer that prints inserted/removed cards class printobserver(CardObserver): def __init__(self, obsindex, testcase): self.obsindex = obsindex self.testcase = testcase def update(self, observable, (addedcards, removedcards)): foundcards = {} self.testcase.assertEquals(removedcards, []) for card in addedcards: foundcards[toHexString(card.atr)] = 1 for atr in expectedATRs: if [] != atr and {} != foundcards: self.testcase.assert_(toHexString(atr) in foundcards) class testthread(threading.Thread): def __init__(self, obsindex, testcase): threading.Thread.__init__(self) self.obsindex = obsindex self.testcase = testcase self.cardmonitor = CardMonitor() self.observer = None def run(self): # create and register observer self.observer = printobserver(self.obsindex, self.testcase) self.cardmonitor.addObserver(self.observer) time.sleep(1) self.cardmonitor.deleteObserver(self.observer) class testcase_cardmonitor(unittest.TestCase): """Test smartcard framework card monitoring classes""" def testcase_cardmonitorthread(self): threads = [] for i in range(0, 4): t = testthread(i, self) threads.append(t) for t in threads: t.start() for t in threads: t.join() def suite(): suite1 = unittest.makeSuite(testcase_cardmonitorthread) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testcase_CardService.py0000755000175000017500000000471211747776700026430 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.CardService This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest import string # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader except: print 'execute test suite first to generate the local_config.py file' sys.exit() # gemalto jython from smartcard.CardService import CardService from smartcard.System import readers class testcase_CardService(unittest.TestCase): """Test case for CardService.""" def testcase_CardService(self): """Test the response to SELECT DF_TELECOM.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] for reader in readers(): if [] != expectedATRinReader[str(reader)]: cc = reader.createConnection() cs = CardService(cc) cs.connection.connect() response, sw1, sw2 = cs.connection.transmit( SELECT + DF_TELECOM) expectedSWs = {"9f 1a": 1, "6e 0": 2, "9f 20": 3, "9f 22": 4} self.assertEquals([], response) self.assert_( "%x %x" % (sw1, sw2) in expectedSWs or "9f" == "%x" % sw1) def suite(): suite1 = unittest.makeSuite(testcase_CardService) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testcase_Card.py0000755000175000017500000001055311747776700025107 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.Card This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest import string # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader except: print 'execute test suite first to generate the local_config.py file' sys.exit() from smartcard.Exceptions import NoCardException from smartcard.Card import Card from smartcard.System import readers class testcase_Card(unittest.TestCase): """Test case for smartcard.Card.""" def testcase_CardDictionary(self): """Create a dictionnary with Card keys""" mydict = {} for reader in readers(): card = Card(reader, expectedATRinReader[str(reader)]) mydict[card] = reader for card in mydict.keys(): self.assert_(str(card.reader) in expectedReaders) def testcase_Card_FromReaders(self): """Create a Card from Readers and test that the response to SELECT DF_TELECOM has two bytes.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] for reader in readers(): card = Card(reader, expectedATRinReader[str(reader)]) cc = card.createConnection() if [] != expectedATRinReader[str(reader)]: cc.connect() response, sw1, sw2 = cc.transmit(SELECT + DF_TELECOM) expectedSWs = {"9f 1a": 1, "9f 20": 2, "6e 0": 3} self.assertEquals([], response) self.assert_( "%x %x" % (sw1, sw2) in expectedSWs or "9f" == "%x" % sw1) else: self.assertRaises(NoCardException, cc.connect) def testcase_Card_FromReaderStrings(self): """Create a Card from reader strings and test that the response to SELECT DF_TELECOM has two bytes.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] for reader in readers(): card = Card(str(reader), expectedATRinReader[str(reader)]) cc = card.createConnection() if [] != expectedATRinReader[str(reader)]: cc.connect() response, sw1, sw2 = cc.transmit(SELECT + DF_TELECOM) expectedSWs = {"9f 1a": 1, "9f 20": 2, "6e 0": 3} self.assertEquals([], response) self.assert_( "%x %x" % (sw1, sw2) in expectedSWs or "9f" == "%x" % sw1) else: self.assertRaises(NoCardException, cc.connect) def testcase_Card_Eq_NotEq(self): """Test == and != for Cards.""" for reader in readers(): card = Card(str(reader), expectedATRinReader[str(reader)]) cardcopy = Card(str(reader), expectedATRinReader[str(reader)]) self.assertEquals(True, card == cardcopy) self.assertEquals(True, not card != cardcopy) for reader in readers(): card = Card(str(reader), expectedATRinReader[str(reader)]) cardcopy = Card(str(reader), [0, 0]) self.assertEquals(True, card != cardcopy) self.assertEquals(True, not card == cardcopy) def suite(): suite1 = unittest.makeSuite(testcase_CardConnection) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testcase_CardRequest.py0000755000175000017500000001221211747776700026452 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.CardRequest This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest import string # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader, expectedReaderForATR except: print 'execute test suite first to generate the local_config.py file' sys.exit() from smartcard.CardRequest import CardRequest from smartcard.CardType import ATRCardType, AnyCardType from smartcard.Exceptions import CardRequestTimeoutException from smartcard.PassThruCardService import PassThruCardService from smartcard.util import toHexString import smartcard.System class testcase_CardRequest(unittest.TestCase): """Test case for CardType.""" def testcase_CardRequestATRCardType(self): """Test smartcard.AnyCardType.""" for atr in expectedATRs: if [] != atr: ct = ATRCardType(atr) cr = CardRequest(timeout=10, cardType=ct) cs = cr.waitforcard() cs.connection.connect() self.assertEquals(atr, cs.connection.getATR()) self.assertEquals( cs.connection.getReader(), expectedReaderForATR[toHexString(atr)]) cs.connection.disconnect() def testcase_CardRequestAnyCardTypeInSelectedReader(self): """Test smartcard.AnyCardType.""" for reader in expectedReaders: atr = expectedATRinReader[reader] if [] != atr: ct = AnyCardType() cr = CardRequest(timeout=10.6, readers=[reader], cardType=ct) cs = cr.waitforcard() cs.connection.connect() self.assertEquals(atr, cs.connection.getATR()) self.assertEquals( cs.connection.getReader(), expectedReaderForATR[toHexString(atr)]) def testcase_CardRequestATRCardTypeTimeout(self): """Test smartcard.AnyCardType.""" for reader in expectedReaders: atr = expectedATRinReader[reader][:-1] ct = ATRCardType(atr) cr = CardRequest(timeout=1, readers=[reader], cardType=ct) self.assertRaises(CardRequestTimeoutException, cr.waitforcard) def testcase_CardRequestATRCardTypeTimeoutAnyReader(self): """Test smartcard.AnyCardType.""" readers = smartcard.System.readers() atr = expectedATRs[0][:-1] ct = ATRCardType(atr) cr = CardRequest(timeout=1.5, readers=readers, cardType=ct) self.assertRaises(CardRequestTimeoutException, cr.waitforcard) def testcase_CardRequestAnyCardTypeAnyReaderPassThru(self): """Test smartcard.AnyCardType.""" for reader in expectedReaders: atr = expectedATRinReader[reader] if [] != atr: ct = AnyCardType() cardservice = smartcard.PassThruCardService.PassThruCardService cr = CardRequest( timeout=10.6, readers=[reader], cardType=ct, cardServiceClass=cardservice) cs = cr.waitforcard() cs.connection.connect() self.assertEquals( cs.__class__, smartcard.PassThruCardService.PassThruCardService) self.assertEquals(atr, cs.connection.getATR()) self.assertEquals( cs.connection.getReader(), expectedReaderForATR[toHexString(atr)]) def testcase_CardRequestAnyCardTypeInSelectedReaderNewCard(self): """Test smartcard.AnyCardType.""" for reader in expectedReaders: atr = expectedATRinReader[reader] ct = AnyCardType() cr = CardRequest( newcardonly=True, timeout=1, readers=[reader], cardType=ct) self.assertRaises(CardRequestTimeoutException, cr.waitforcard) def suite(): suite1 = unittest.makeSuite(testcase_CardRequest) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testcase_readers.py0000755000175000017500000000720011747776700025656 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.readers. This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader except: print 'execute test suite first to generate the local_config.py file' sys.exit() from smartcard.System import readers, readergroups from smartcard import listReaders from smartcard.scard import resourceManager class testcase_readers(unittest.TestCase): """Test smartcard framework readers factory methods""" def testcase_enoughreaders(self): self.assert_(len(readers()) > 1) def testcase_readers(self): foundreaders = {} for reader in readers(): foundreaders[str(reader)] = 1 for reader in expectedReaders: self.assert_(reader in foundreaders) def testcase_hashreaders(self): foundreaders = {} for reader in readers(): foundreaders[reader] = 1 for reader in foundreaders.keys(): self.assert_(reader in readers()) def testcase_legacyreaders(self): foundreaders = {} for reader in listReaders(): foundreaders[reader] = 1 for reader in expectedReaders: self.assert_(reader in foundreaders) def testcase_readers_in_readergroup(self): foundreaders = {} for reader in readers(['SCard$DefaultReaders']): foundreaders[str(reader)] = 1 for reader in expectedReaders: self.assert_(reader in foundreaders) def testcase_readers_in_readergroup_empty(self): foundreaders = {} for reader in readers([]): foundreaders[str(reader)] = 1 for reader in expectedReaders: self.assert_(reader in foundreaders) if 'winscard' == resourceManager: def testcase_readers_in_readergroup_nonexistent(self): foundreaders = {} for reader in readers(['dummy$group']): foundreaders[reader] = 1 for reader in expectedReaders: self.assert_(not reader in foundreaders) self.assertEquals(0, len(foundreaders)) def testcase_readergroups(self): foundreadergroups = {} for readergroup in readergroups(): foundreadergroups[readergroup] = 1 for readergroup in expectedReaderGroups: self.assert_(readergroup in foundreadergroups) def suite(): suite1 = unittest.makeSuite(testcase_readers) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testsuite_framework.py0000755000175000017500000000353011747776700026446 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit test suite for smartcard python framework. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 sys import unittest # so that we can locate configcheck sys.path += ['..'] import configcheck def suite(): modules_to_test = ( 'testcase_ATR', 'testcase_Card', 'testcase_CardConnection', 'testcase_CardMonitor', 'testcase_CardRequest', 'testcase_CardService', 'testcase_CardType', 'testcase_CAtr', 'testcase_ErrorChecking', 'testcase_ExclusiveCardConnection', 'testcase_readers', 'testcase_readergroups', 'testcase_readermonitor', 'testcase_readermonitorstress', 'testcase_ulist', 'testcase_utils', ) testsuite_framework = unittest.TestSuite() for module in map(__import__, modules_to_test): testsuite_framework.addTest(unittest.findTestCases(module)) return testsuite_framework if __name__ == '__main__': configcheck.checklocalconfig() unittest.main(defaultTest='suite') pyscard-1.6.14/smartcard/test/framework/testcase_readermonitorstress.py0000755000175000017500000001336711747776700030362 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.ReaderMonitoring This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 random import threading import time import unittest from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver period = .1 # stats on virtual reader insertion/removal insertedreaderstats = {} removedreaderstats = {} # the virtual list of readers mutexvreaders = threading.RLock() virtualreaders = [] def getReaders(): '''Return virtual list of inserted readers. Replacement of smartcard.system.readers for testing purpose''' try: mutexvreaders.acquire() currentreaders = virtualreaders finally: mutexvreaders.release() readerEvent.set() return currentreaders # an event to signal test threads to end exitEvent = threading.Event() # an event to ensure only one insertion/removal between getReaders() calls readerEvent = threading.Event() readerEvent.clear() # test running time in seconds RUNNING_TIME = 15 # the count of registered observers OBS_COUNT = 100 class readerInsertionThread(threading.Thread): '''Simulate reader insertion every 2 to 4 periods.''' def __init__(self): threading.Thread.__init__(self) def run(self): while not exitEvent.isSet(): time.sleep(random.uniform(2 * period, 4 * period)) readerEvent.wait() newreader = random.choice('abcdefghijklmnopqrstuvwxyz') try: mutexvreaders.acquire() if newreader not in virtualreaders: virtualreaders.append(newreader) if newreader in insertedreaderstats: insertedreaderstats[newreader] += 1 else: insertedreaderstats[newreader] = 1 finally: readerEvent.clear() mutexvreaders.release() class readerRemovalThread(threading.Thread): '''Simulate reader removal every 5 to 6 periods.''' def __init__(self): threading.Thread.__init__(self) def run(self): while not exitEvent.isSet(): time.sleep(random.uniform(5 * period, 6 * period)) readerEvent.wait() try: mutexvreaders.acquire() if virtualreaders: oldreader = random.choice(virtualreaders) virtualreaders.remove(oldreader) if oldreader in removedreaderstats: removedreaderstats[oldreader] += 1 else: removedreaderstats[oldreader] = 1 finally: readerEvent.clear() mutexvreaders.release() class countobserver(ReaderObserver): '''A simple reader observer that counts added/removed readers.''' def __init__(self, obsindex): self.obsindex = obsindex self.insertedreaderstats = {} self.removedreaderstats = {} self.countnotified = 0 def update(self, observable, (addedreaders, removedreaders)): self.countnotified += 1 for newreader in addedreaders: if newreader in self.insertedreaderstats: self.insertedreaderstats[newreader] += 1 else: self.insertedreaderstats[newreader] = 1 for oldreader in removedreaders: if oldreader in self.removedreaderstats: self.removedreaderstats[oldreader] += 1 else: self.removedreaderstats[oldreader] = 1 class testcase_readermonitorstress(unittest.TestCase): '''Test smartcard framework reader monitoring''' def testcase_readermonitorthread(self): # create thread that simulates reader insertion insertionthread = readerInsertionThread() # create thread that simulates reader removal removalthread = readerRemovalThread() readermonitor = ReaderMonitor(readerProc=getReaders, period=period) observers = [] for i in range(0, OBS_COUNT): observer = countobserver(i) readermonitor.addObserver(observer) observers.append(observer) # signal threads to start insertionthread.start() removalthread.start() # let reader insertion/removal threads run for a while # then signal threads to end time.sleep(RUNNING_TIME) exitEvent.set() # wait until all threads ended removalthread.join() insertionthread.join() time.sleep(2 * period) for observer in observers: self.assertEquals( observer.insertedreaderstats, insertedreaderstats) self.assertEquals( observer.removedreaderstats, removedreaderstats) def suite(): suite1 = unittest.makeSuite(testcase_readermonitorthread) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/readme.txt0000644000175000017500000000317410633575650023757 0ustar rousseaurousseau00000000000000------------------------------------------------------------------------------- This directory contains the test suite for the pyscard framework. You will need two smart card readers and two smart cards to run the test suite. Insert the readers and the cards in the readers before executing the test suite. On the first execution of the test suite, the configcheck.py script in the parent directory will generate a localconfig.py file that will contain the current names of the readers and ATRs of the cards inserted in the readers. These data are used by the test suite. If you change the test configuration, i.e. add or remove readers or cards, or change the readers or cards, just delete localconfig.py and re-run the test suite. ------------------------------------------------------------------------------- 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 ------------------------------------------------------------------------------- pyscard-1.6.14/smartcard/test/framework/testcase_ExclusiveCardConnection.py0000755000175000017500000001033311747776700031013 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.ExclusiveTransmitCardConnection. This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 sys import random import threading import time import unittest # define the apdus used in this script GET_RESPONSE = [0XA0, 0XC0, 00, 00] SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] from smartcard.CardConnection import CardConnection from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver from smartcard.CardMonitoring import CardMonitor, CardObserver from smartcard.CardRequest import CardRequest from smartcard.CardType import AnyCardType from smartcard.ExclusiveTransmitCardConnection import \ ExclusiveTransmitCardConnection from smartcard.util import toHexString def signalEvent(evt): '''A simple callback that signals an event.''' evt.set() class testthread(threading.Thread): '''A test thread that repetitevely sends APDUs to a card within a transaction.''' def __init__(self, threadindex): '''Connect to a card with an ExclusiveTransmitCardConnection.''' threading.Thread.__init__(self) self.threadindex = threadindex # request any card type cardtype = AnyCardType() cardrequest = CardRequest(timeout=5, cardType=cardtype) cardservice = cardrequest.waitforcard() # attach our decorator cardservice.connection = ExclusiveTransmitCardConnection( cardservice.connection) # uncomment to attach the console tracer #observer=ConsoleCardConnectionObserver() #cardservice.connection.addObserver(observer) # connect to the card cardservice.connection.connect() self.cardservice = cardservice # this event will signal the end of the thread self.evtStop = threading.Event() # this timer will set the event stop event in 30s timer = threading.Timer(30, signalEvent, [self.evtStop]) timer.start() self.countTransmitted = 0 def run(self): '''Transmit APDUS with a random interval to the card.''' connection = self.cardservice.connection while not self.evtStop.isSet(): try: connection.lock() apdu = SELECT + DF_TELECOM response, sw1, sw2 = connection.transmit(apdu) if 0x90 == (sw1 & 0xF0): apdu = GET_RESPONSE + [sw2] response, sw1, sw2 = connection.transmit(apdu) finally: connection.unlock() self.countTransmitted = self.countTransmitted + 1 time.sleep(float(random.uniform(1, 3)) * 0.01) class testcase_cardmonitor(unittest.TestCase): """Test smartcard framework card monitoring classes""" def testcase_cardmonitorthread(self): threads = [] for i in range(0, 4): t = testthread(i) threads.append(t) for t in threads: t.start() for t in threads: t.join() for t in threads: if 0 == 1: print 'Thread %d: transmitted %ld apdus.' % \ (t.threadindex, t.countTransmitted) def suite(): suite1 = unittest.makeSuite(testcase_cardmonitorthread) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testcase_ulist.py0000755000175000017500000001034211747776700025372 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for ulist This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest from smartcard.ulist import ulist class C(ulist): def __onadditem__(self, item): #print '+', item pass def __onremoveitem__(self, item): #print '-', item pass class testcase_ulist(unittest.TestCase): """Test smartcard.ulist.""" def testcase_ulist_init(self): """tests constructor""" c = C([1, 2, 3, 3, 4, 5, 5]) self.assertEquals([1, 2, 3, 4, 5], c) c = C(['one', 'two', 'three', 'one']) self.assertEquals(['one', 'two', 'three'], c) def testcase_ulist_add(self): """tests l=l+other""" seed = [1, 2, 3] c = C(seed) self.assertEquals(seed, c) c = c + [] self.assertEquals(seed, c) c = c + 4 self.assertEquals(seed + [4], c) c = c + 4 self.assertEquals(seed + [4], c) c = c + 'word' self.assertEquals(seed + [4] + ['word'], c) seed = ['one', 'two', 'three'] c = C(seed) self.assertEquals(seed, c) c = c + ['four', 'five'] self.assertEquals(seed + ['four', 'five'], c) def testcase_ulist_iadd(self): """tests l+=other""" seed = [1, 2, 3] c = C(seed) self.assertEquals(seed, c) c += [] self.assertEquals(seed, c) c += 4 self.assertEquals(seed + [4], c) c += 4 self.assertEquals(seed + [4], c) c += [4, 3, 2, 1] self.assertEquals(seed + [4], c) c += 'word' self.assertEquals(seed + [4] + ['word'], c) seed = ['one', 'two', 'three'] c = C(seed) self.assertEquals(seed, c) c += ['four', 'five'] self.assertEquals(seed + ['four', 'five'], c) def testcase_ulist_radd(self): """tests l=other+l""" seed = [1, 2, 3] c = C(seed) self.assertEquals(seed, c) l = [] + c self.assertEquals(seed, l) l = [3] + c self.assertEquals(seed, c) self.assertEquals(seed, l) l = [3, 3, 4, 4] + c self.assertEquals(seed, c) self.assertEquals(seed + [4], l) l = [4] + ['word'] + c self.assertEquals(seed, c) self.assertEquals(seed + [4] + ['word'], l) def testcase_ulist_append(self): seed = [1, 2, 3] c = C(seed) c.append(4) self.assertEquals(seed + [4], c) c.append(4) self.assertEquals(seed + [4], c) c.append('word') self.assertEquals(seed + [4] + ['word'], c) def testcase_ulist_insert(self): seed = [1, 2, 3] c = C(seed) c.insert(0, 0) self.assertEquals([0] + seed, c) c.insert(1, 0) self.assertEquals([0] + seed, c) def testcase_ulist_pop(self): seed = [1, 2, 3] c = C(seed) c.pop() self.assertEquals(c, [1, 2]) c.pop(1) self.assertEquals(c, [1]) def testcase_ulist_remove(self): seed = [1, 2, 3] c = C(seed) c.remove(2) self.assertEquals(c, [1, 3]) c.remove(1) self.assertEquals(c, [3]) def suite(): suite1 = unittest.makeSuite(testcase_ulist) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testcase_CardType.py0000755000175000017500000001217311747776700025751 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.CardType This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest import string # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader except: print 'execute test suite first to generate the local_config.py file' sys.exit() from smartcard.CardType import CardType, AnyCardType, ATRCardType from smartcard.Exceptions import InvalidATRMaskLengthException from smartcard.System import readers class testcase_CardType(unittest.TestCase): """Test case for CardType.""" def testcase_AnyCardType(self): """Test smartcard.AnyCardType.""" ct = AnyCardType() for reader in readers(): if [] != expectedATRinReader[str(reader)]: connection = reader.createConnection() connection.connect() self.assertEquals(True, ct.matches(connection.getATR())) self.assertEquals( True, ct.matches(connection.getATR(), reader)) connection.disconnect() def testcase_ATRCardTypeWithoutMask(self): """Test smartcard.ATRCardType without mask.""" for reader in readers(): if [] != expectedATRinReader[str(reader)]: ct = ATRCardType(expectedATRinReader[str(reader)]) connection = reader.createConnection() connection.connect() self.assertEquals(True, ct.matches(connection.getATR())) self.assertEquals( True, ct.matches(connection.getATR(), reader)) connection.disconnect() def testcase_ATRCardTypeMisMatchWithoutMask(self): """Test smartcard.ATRCardType mismatch without mask.""" for reader in readers(): if [] != expectedATRinReader[str(reader)]: atr = list(expectedATRinReader[str(reader)]) # change the last byte of the expected atr atr[-1] = 0xFF ct = ATRCardType(atr) connection = reader.createConnection() connection.connect() self.assertEquals(False, ct.matches(connection.getATR())) self.assertEquals( False, ct.matches(connection.getATR(), reader)) connection.disconnect() def testcase_ATRCardTypeWithMask(self): """Test smartcard.ATRCardType with mask.""" for reader in readers(): if [] != expectedATRinReader[str(reader)]: mask = map(lambda x: 0xFF, expectedATRinReader[str(reader)]) # don't look to the last byte mask[-1] = 0x00 ct = ATRCardType(expectedATRinReader[str(reader)], mask) connection = reader.createConnection() connection.connect() atr = connection.getATR() connection.disconnect() # change a bit in the last byte atr[-1] = atr[-1] ^ 0xFF self.assertEquals(True, ct.matches(atr)) self.assertEquals(True, ct.matches(atr, reader)) def testcase_ATRCardTypeWithMaskMismatch(self): """Test smartcard.ATRCardType with mask and mismatch.""" for reader in readers(): if [] != expectedATRinReader[str(reader)]: mask = map(lambda x: 0xFF, expectedATRinReader[str(reader)]) # don't look to the last byte mask[0] = mask[-1] = 0x00 ct = ATRCardType(expectedATRinReader[str(reader)], mask) connection = reader.createConnection() connection.connect() atr = connection.getATR() connection.disconnect() # change a bit in the :-2 byte atr[-2] = atr[-2] ^ 0xFF self.assertEquals(False, ct.matches(atr)) self.assertEquals(False, ct.matches(atr, reader)) def suite(): suite1 = unittest.makeSuite(testcase_CardType) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testcase_CAtr.py0000755000175000017500000001124511747776700025066 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.ATR This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest import string # gemalto jython from smartcard.ATR import ATR class testcase_CAtr(unittest.TestCase): """Test APDU class and utilities""" def testcase_ATR1(self): """Usimera Classic 2.""" a = ATR([0x3B, 0x9E, 0x95, 0x80, 0x1F, 0xC3, 0x80, 0x31, 0xA0, 0x73, 0xBE, 0x21, 0x13, 0x67, 0x29, 0x02, 0x01, 0x01, 0x81, 0xCD, 0xB9]) historicalbytes = [0x80, 0x31, 0xA0, 0x73, 0xBE, 0x21, 0x13, 0x67, 0x29, 0x02, 0x01, 0x01, 0x81, 0xCD] self.assertEquals(a.getHistoricalBytes(), historicalbytes) self.assertEquals(a.getChecksum(), 0xB9) self.assert_(a.checksumOK) self.assert_(a.isT0Supported()) self.assert_(not a.isT1Supported()) self.assert_(a.isT15Supported()) def testcase_ATR2(self): """Palmera Protect V2.""" a = ATR([0x3B, 0x65, 0x00, 0x00, 0x9C, 0x02, 0x02, 0x01, 0x02]) historicalbytes = [0x9C, 0x02, 0x02, 0x01, 0x02] self.assertEquals(a.getHistoricalBytes(), historicalbytes) self.assertEquals(a.getChecksum(), None) self.assert_(a.isT0Supported()) self.assert_(not a.isT1Supported()) self.assert_(not a.isT15Supported()) def testcase_ATR3(self): """Simera 3.13.""" a = ATR([0x3B, 0x16, 0x18, 0x20, 0x02, 0x01, 0x00, 0x80, 0x0D]) historicalbytes = [0x20, 0x02, 0x01, 0x00, 0x80, 0x0D] self.assertEquals(a.getHistoricalBytes(), historicalbytes) self.assertEquals(a.getChecksum(), None) self.assert_(a.isT0Supported()) self.assert_(not a.isT1Supported()) self.assert_(not a.isT15Supported()) def testcase_ATR4(self): """SIMRock'n Tree""" a = ATR([0x3B, 0x77, 0x94, 0x00, 0x00, 0x82, 0x30, 0x00, 0x13, 0x6C, 0x9F, 0x22]) historicalbytes = [0x82, 0x30, 0x00, 0x13, 0x6C, 0x9F, 0x22] self.assertEquals(a.getHistoricalBytes(), historicalbytes) self.assertEquals(a.getChecksum(), None) self.assert_(a.isT0Supported()) self.assert_(not a.isT1Supported()) self.assert_(not a.isT15Supported()) def testcase_ATR5(self): """Demo Vitale online IGEA340""" a = ATR([0x3F, 0x65, 0x25, 0x00, 0x52, 0x09, 0x6A, 0x90, 0x00]) historicalbytes = [0x52, 0x09, 0x6A, 0x90, 0x00] self.assertEquals(a.getHistoricalBytes(), historicalbytes) self.assertEquals(a.getChecksum(), None) self.assert_(a.isT0Supported()) self.assert_(not a.isT1Supported()) self.assert_(not a.isT15Supported()) def testcase_ATR6(self): """Simagine 2002""" a = ATR([0x3B, 0x16, 0x94, 0x20, 0x02, 0x01, 0x00, 0x00, 0x0D]) historicalbytes = [0x20, 0x02, 0x01, 0x00, 0x00, 0x0D] self.assertEquals(a.getHistoricalBytes(), historicalbytes) self.assertEquals(a.getChecksum(), None) def testcase_ATR7(self): """Protect V3 T=1""" a = ATR([0x3B, 0xE5, 0x00, 0x00, 0x81, 0x21, 0x45, 0x9C, 0x10, 0x01, 0x00, 0x80, 0x0D]) historicalbytes = [0x9C, 0x10, 0x01, 0x00, 0x80] self.assertEquals(a.getHistoricalBytes(), historicalbytes) self.assertEquals(a.getChecksum(), 0x0D) self.assert_(not a.isT0Supported()) self.assert_(a.isT1Supported()) self.assert_(not a.isT15Supported()) self.assert_(a.checksumOK) self.assert_(a.getTB1() == 0x00) self.assert_(a.getTC1() == 0x00) self.assert_(a.getTD1() == 0x81) self.assert_(a.TD[2 - 1] == 0x21) # TD2 self.assert_(a.TB[3 - 1] == 0x45) # TB3 def suite(): suite1 = unittest.makeSuite(testcase_CAtr) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testcase_ErrorChecking.py0000755000175000017500000003164211747776700026765 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.sw This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest import string # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] from smartcard.sw.ErrorCheckingChain import ErrorCheckingChain from smartcard.sw.ErrorChecker import ErrorChecker from smartcard.sw.ISO7816_4ErrorChecker import ISO7816_4ErrorChecker from smartcard.sw.ISO7816_4_SW1ErrorChecker import ISO7816_4_SW1ErrorChecker from smartcard.sw.ISO7816_8ErrorChecker import ISO7816_8ErrorChecker from smartcard.sw.ISO7816_9ErrorChecker import ISO7816_9ErrorChecker from smartcard.sw.op21_ErrorChecker import op21_ErrorChecker import smartcard.sw.SWExceptions try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader except: print 'execute test suite first to generate the local_config.py file' sys.exit() class CustomSWException(smartcard.sw.SWExceptions.SWException): """Test exception raised by TestErrorChecker.""" def __init__(self, data, sw1, sw2, message=""): smartcard.sw.SWExceptions.SWException.__init__(self, data, sw1, sw2) class TestErrorChecker(ErrorChecker): """Test error checking checker. This checker raises the following exception: sw1: 56 sw2: 55 CustomSWException sw1: 63 sw2: any WarningProcessingException """ def __call__(self, data, sw1, sw2): if 0x56 == sw1 and 0x55 == sw2: raise CustomSWException(data, sw1, sw2) elif 0x63 == sw1: raise CustomSWException(data, sw1, sw2) class testcase_ErrorChecking(unittest.TestCase): """Test case for smartcard.sw.* error checking.""" def failUnlessRaises(self, excClass, callableObj, *args, **kwargs): """override of unittest.TestCase.failUnlesRaises so that we return the exception object for testing fields.""" try: callableObj(*args, **kwargs) except excClass, e: return e else: if hasattr(excClass, '__name__'): excName = excClass.__name__ else: excName = str(excClass) raise self.failureException, excName def testcase_ISO7816_4SW1ErrorChecker(self): """Test ISO7816_4_SW1ErrorChecker.""" ecs = ISO7816_4_SW1ErrorChecker() tiso7816_4SW1 = { 0x62: smartcard.sw.SWExceptions.WarningProcessingException, 0x63: smartcard.sw.SWExceptions.WarningProcessingException, 0x64: smartcard.sw.SWExceptions.ExecutionErrorException, 0x65: smartcard.sw.SWExceptions.ExecutionErrorException, 0x66: smartcard.sw.SWExceptions.SecurityRelatedException, 0x67: smartcard.sw.SWExceptions.CheckingErrorException, 0x68: smartcard.sw.SWExceptions.CheckingErrorException, 0x69: smartcard.sw.SWExceptions.CheckingErrorException, 0x6A: smartcard.sw.SWExceptions.CheckingErrorException, 0x6B: smartcard.sw.SWExceptions.CheckingErrorException, 0x6C: smartcard.sw.SWExceptions.CheckingErrorException, 0x6D: smartcard.sw.SWExceptions.CheckingErrorException, 0x6E: smartcard.sw.SWExceptions.CheckingErrorException, 0x6F: smartcard.sw.SWExceptions.CheckingErrorException, } for sw1 in range(0x00, 0xff + 1): sw2range = [] exception = None if sw1 in tiso7816_4SW1: exception = tiso7816_4SW1[sw1] for sw2 in range(0x00, 0xff + 1): if None != exception: self.assertRaises(exception, ecs, [], sw1, sw2) else: ecs([], sw1, sw2) def testcase_ISO7816_4ErrorChecker(self): """Test ISO7816_4ErrorChecker.""" ecs = ISO7816_4ErrorChecker() tiso7816_4SW = { 0x62: (smartcard.sw.SWExceptions.WarningProcessingException, [0x00, 0x81, 0x82, 0x83, 0x84, 0xff]), 0x63: (smartcard.sw.SWExceptions.WarningProcessingException, [0x00, 0x81] + range(0xc0, 0xcf + 1)), 0x64: (smartcard.sw.SWExceptions.ExecutionErrorException, [0x00]), 0x67: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x68: (smartcard.sw.SWExceptions.CheckingErrorException, [0x81, 0x82]), 0x69: (smartcard.sw.SWExceptions.CheckingErrorException, range(0x81, 0x88 + 1)), 0x6A: (smartcard.sw.SWExceptions.CheckingErrorException, range(0x80, 0x88 + 1)), 0x6B: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x6D: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x6E: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x6F: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), } for sw1 in range(0x00, 0xff + 1): sw2range = [] if sw1 in tiso7816_4SW: exception, sw2range = tiso7816_4SW[sw1] for sw2 in range(0x00, 0xff + 1): if sw2 in sw2range: self.assertRaises(exception, ecs, [], sw1, sw2) else: ecs([], sw1, sw2) def testcase_ISO7816_8ErrorChecker(self): """Test ISO7816_4ErrorChecker.""" ecs = ISO7816_8ErrorChecker() tiso7816_8SW = { 0x63: (smartcard.sw.SWExceptions.WarningProcessingException, [0x00] + range(0xc0, 0xcf + 1)), 0x65: (smartcard.sw.SWExceptions.ExecutionErrorException, [0x81]), 0x66: (smartcard.sw.SWExceptions.SecurityRelatedException, [0x00, 0x87, 0x88]), 0x67: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x68: (smartcard.sw.SWExceptions.CheckingErrorException, [0x83, 0x84]), 0x69: (smartcard.sw.SWExceptions.CheckingErrorException, range(0x82, 0x85 + 1)), 0x6A: (smartcard.sw.SWExceptions.CheckingErrorException, [0x81, 0x82, 0x86, 0x88]), } for sw1 in range(0x00, 0xff + 1): sw2range = [] if sw1 in tiso7816_8SW: exception, sw2range = tiso7816_8SW[sw1] for sw2 in range(0x00, 0xff + 1): if sw2 in sw2range: self.assertRaises(exception, ecs, [], sw1, sw2) else: ecs([], sw1, sw2) def testcase_ISO7816_9ErrorChecker(self): """Test ISO7816_4ErrorChecker.""" ecs = ISO7816_9ErrorChecker() tiso7816_9SW = { 0x62: (smartcard.sw.SWExceptions.WarningProcessingException, [0x82]), 0x64: (smartcard.sw.SWExceptions.ExecutionErrorException, [0x00]), 0x69: (smartcard.sw.SWExceptions.CheckingErrorException, [ 0x82]), 0x6A: (smartcard.sw.SWExceptions.CheckingErrorException, [0x80, 0x84, 0x89, 0x8A]), } for sw1 in range(0x00, 0xff + 1): sw2range = [] if sw1 in tiso7816_9SW: exception, sw2range = tiso7816_9SW[sw1] for sw2 in range(0x00, 0xff + 1): if sw2 in sw2range: self.assertRaises(exception, ecs, [], sw1, sw2) else: ecs([], sw1, sw2) def testcase_op21_ErrorChecker(self): """Test op21_ErrorChecker.""" ecs = op21_ErrorChecker() top21_SW = { 0x62: (smartcard.sw.SWExceptions.WarningProcessingException, [ 0x83]), 0x63: (smartcard.sw.SWExceptions.WarningProcessingException, [0x00]), 0x64: (smartcard.sw.SWExceptions.ExecutionErrorException, [ 0x00]), 0x65: (smartcard.sw.SWExceptions.ExecutionErrorException, [ 0x81]), 0x67: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x69: (smartcard.sw.SWExceptions.CheckingErrorException, [0x82, 0x85]), 0x6A: (smartcard.sw.SWExceptions.CheckingErrorException, [0x80, 0x81, 0x82, 0x84, 0x86, 0x88]), 0x6D: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x6E: (smartcard.sw.SWExceptions.CheckingErrorException, [0x00]), 0x94: (smartcard.sw.SWExceptions.CheckingErrorException, [0x84, 0x85]), } for sw1 in range(0x00, 0xff + 1): sw2range = [] if sw1 in top21_SW: exception, sw2range = top21_SW[sw1] for sw2 in range(0x00, 0xff + 1): if sw2 in sw2range: self.assertRaises(exception, ecs, [], sw1, sw2) else: ecs([], sw1, sw2) def testcase_ISO78164_Test_ErrorCheckingChain(self): """Test error chain with ISO7816-4 checker followed by Test checker.""" errorchain = [] errorchain = [ErrorCheckingChain(errorchain, ISO7816_4ErrorChecker()), ErrorCheckingChain(errorchain, TestErrorChecker())] # ISO7816-4 is answering first on the next, i.e # WarningProcessingException for sw2 in [0x00, 0x81] + range(0xc0, 0xcf + 1): self.assertRaises( smartcard.sw.SWExceptions.WarningProcessingException, errorchain[0], [], 0x63, sw2) def testcase_Test_ISO78164_ErrorCheckingChain(self): """Test error chain with Test checker followed by ISO7816-4 checker.""" errorchain = [] errorchain = [ErrorCheckingChain(errorchain, TestErrorChecker()), ErrorCheckingChain(errorchain, ISO7816_4ErrorChecker())] # TestErrorChecker is answering first, i.e. CustomSWException for sw2 in [0x00, 0x81] + range(0xc0, 0xcf + 1): self.assertRaises(CustomSWException, errorchain[0], [], 0x63, sw2) def testcase_ErrorMessage(self): """Test correct exception error message.""" ecs = ISO7816_4ErrorChecker() e = self.failUnlessRaises( smartcard.sw.SWExceptions.CheckingErrorException, ecs, [], 0x69, 0x85) self.assertEquals( str(e), "'Status word exception: checking error - " + \ "Conditions of use not satisfied!'") e = self.failUnlessRaises( smartcard.sw.SWExceptions.CheckingErrorException, ecs, [], 0x6b, 0x00) self.assertEquals( str(e), "'Status word exception: checking error - " + \ "Incorrect parameters P1-P2!'") def testcase_ISO78164_Test_ErrorCheckingChain_filtering(self): """Test error chain with ISO7816-4 checker followed by Test checker.""" errorchain = [] errorchain = [ErrorCheckingChain(errorchain, ISO7816_8ErrorChecker()), ErrorCheckingChain(errorchain, ISO7816_4ErrorChecker()), ErrorCheckingChain( errorchain, ISO7816_4_SW1ErrorChecker())] # don't care about Warning Exceptions errorchain[0].addFilterException( smartcard.sw.SWExceptions.WarningProcessingException) for sw2 in range(0x00, 0xff): # should not raise errorchain[0]([], 0x62, sw2) errorchain[0]([], 0x63, sw2) # should raise self.assertRaises( smartcard.sw.SWExceptions.ExecutionErrorException, errorchain[0], [], 0x64, sw2) def suite(): suite1 = unittest.makeSuite(testcase_ErrorChecking) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testcase_readermonitor.py0000755000175000017500000000613111747776700027105 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.ReaderMonitoring This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 threading import unittest import time # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader except: print 'execute test suite first to generate the local_config.py file' sys.exit() from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver # a simple reader observer that prints added/removed readers class printobserver(ReaderObserver): def __init__(self, obsindex, testcase): self.obsindex = obsindex self.testcase = testcase def update(self, observable, (addedreaders, removedreaders)): foundreaders = {} self.testcase.assertEquals(removedreaders, []) for reader in addedreaders: foundreaders[str(reader)] = 1 if {} != foundreaders: for reader in expectedReaders: self.testcase.assert_(reader in foundreaders) class testthread(threading.Thread): def __init__(self, obsindex, testcase): threading.Thread.__init__(self) self.obsindex = obsindex self.testcase = testcase self.readermonitor = ReaderMonitor() self.observer = None def run(self): # create and register observer self.observer = printobserver(self.obsindex, self.testcase) self.readermonitor.addObserver(self.observer) time.sleep(1) self.readermonitor.deleteObserver(self.observer) class testcase_readermonitor(unittest.TestCase): """Test smartcard framework reader monitoring methods""" def testcase_readermonitorthread(self): threads = [] for i in range(0, 4): t = testthread(i, self) threads.append(t) for t in threads: t.start() for t in threads: t.join() def suite(): suite1 = unittest.makeSuite(testcase_readermonitorthread) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testcase_readergroups.py0000755000175000017500000001310711747776700026736 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.readers.ReaderGroups This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 platform import unittest from smartcard.System import readergroups from smartcard.scard import resourceManager if 'winscard' == resourceManager and \ -1 == platform.platform().find('Windows-7'): class testcase_readergroups(unittest.TestCase): """Test smartcard framework readersgroups.""" pinpadgroup = 'Pinpad$Readers' biogroup = 'Biometric$Readers' def testcase_readergroup_add(self): """tests groups=groups+[newgroups]""" # take a snapshot of current groups groupssnapshot = list(readergroups()) groups = readergroups() # add pinpad group groups = groups + [self.pinpadgroup] self.assertEquals(groups, groupssnapshot + [self.pinpadgroup]) # add pinpad a second time and biometric once groups = groups + [self.biogroup, self.pinpadgroup] self.assertEquals( groups, groupssnapshot + [self.pinpadgroup, self.biogroup]) # clean-up groups.remove(self.biogroup) groups.remove(self.pinpadgroup) def testcase_readergroup_iadd(self): """test groups+=[newgroups]""" # take a snapshot of current groups groupssnapshot = list(readergroups()) groups = readergroups() # add pinpad group groups += [self.pinpadgroup] self.assertEquals(groups, groupssnapshot + [self.pinpadgroup]) # add pinpad a second time and biometric once groups += [self.biogroup, self.pinpadgroup] self.assertEquals( groups, groupssnapshot + [self.pinpadgroup, self.biogroup]) # clean-up groups.remove(self.biogroup) groups.remove(self.pinpadgroup) def testcase_readergroup_radd(self): """test groups=[newgroups]+groups""" # take a snapshot of current groups groupssnapshot = list(readergroups()) groups = readergroups() # add pinpad group zgroups = [self.pinpadgroup] + groups self.assertEquals(groups, groupssnapshot) self.assertEquals(zgroups, groupssnapshot + [self.pinpadgroup]) self.assert_(isinstance(zgroups, type([]))) self.assert_(isinstance(groups, type(readergroups()))) # add pinpad a tiwce and biometric once zgroups = \ [self.pinpadgroup, self.biogroup, self.pinpadgroup] + groups self.assertEquals(groups, groupssnapshot) self.assertEquals( zgroups, groupssnapshot + [self.pinpadgroup, self.biogroup]) self.assert_(isinstance(zgroups, type([]))) self.assert_(isinstance(groups, type(readergroups()))) def testcase_readergroup_append(self): """test groups.append(newgroups)""" # take a snapshot of current groups groupssnapshot = list(readergroups()) groups = readergroups() # add pinpad group groups.append(self.pinpadgroup) self.assertEquals(groups, groupssnapshot + [self.pinpadgroup]) # add pinpad a second time groups.append(self.pinpadgroup) self.assertEquals(groups, groupssnapshot + [self.pinpadgroup]) # add biometric once groups.append(self.biogroup) self.assertEquals( groups, groupssnapshot + [self.pinpadgroup, self.biogroup]) # clean-up groups.remove(self.biogroup) groups.remove(self.pinpadgroup) def testcase_readergroup_insert(self): """test groups.insert(i,newgroups)""" # take a snapshot of current groups groupssnapshot = list(readergroups()) groups = readergroups() # add pinpad group groups.insert(0, self.pinpadgroup) self.assertEquals(groups, groupssnapshot + [self.pinpadgroup]) # add pinpad a second time groups.insert(1, self.pinpadgroup) self.assertEquals(groups, groupssnapshot + [self.pinpadgroup]) # add biometric once groups.insert(1, self.biogroup) self.assertEquals( groups, groupssnapshot + [self.pinpadgroup, self.biogroup]) # clean-up groups.remove(self.biogroup) groups.remove(self.pinpadgroup) def suite(): suite1 = unittest.makeSuite(testcase_readergroups) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testcase_ATR.py0000755000175000017500000000410711747776700024662 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for testing that we have at least two cards for the test suite. This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest import string # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader except: print 'execute test suite first to generate the local_config.py file' sys.exit() # gemalto jython from smartcard import Session class testcase_ATR(unittest.TestCase): """Test ATR configuration for test suite""" def testcase_ATRconfig(self): # we have at list 2 readers (one is the simulator), e.g. # two potential ATRs self.assert_(len(expectedATRs) > 1) # we have at least two non empty ATRs count = 0 for atr in expectedATRs: if atr != []: count += 1 self.assert_(count > 1) def suite(): suite1 = unittest.makeSuite(testcase_ATR) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/framework/testcase_CardConnection.py0000755000175000017500000001636311747776700027134 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.CardConnection This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest import string # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader except: print 'execute test suite first to generate the local_config.py file' sys.exit() from smartcard.Exceptions import CardConnectionException, NoCardException from smartcard.System import readers from smartcard.CardConnection import CardConnection from smartcard.scard import resourceManagerSubType class testcase_CardConnection(unittest.TestCase): """Test case for CardConnection.""" def testcase_CardConnection(self): """Test with default protocols the response to SELECT DF_TELECOM.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] for reader in readers(): cc = reader.createConnection() if [] != expectedATRinReader[str(reader)]: cc.connect() response, sw1, sw2 = cc.transmit(SELECT + DF_TELECOM) expectedSWs = {"9f 1a": 1, "6e 0": 2, "9f 20": 3, "9f 22": 4} self.assertEquals([], response) self.assert_( "%x %x" % (sw1, sw2) in expectedSWs or "9f" == "%x" % sw1) else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def testcase_CardConnectionT0(self): """Test with T0 the response to SELECT DF_TELECOM.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] for reader in readers(): cc = reader.createConnection() if [] != expectedATRinReader[str(reader)]: cc.connect(CardConnection.T0_protocol) response, sw1, sw2 = cc.transmit(SELECT + DF_TELECOM) expectedSWs = {"9f 1a": 1, "6e 0": 2, "9f 20": 3, "9f 22": 4} self.assertEquals([], response) self.assert_( "%x %x" % (sw1, sw2) in expectedSWs or "9f" == "%x" % sw1) else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def testcase_CardConnectionT1inConnect(self): """Test that connecting with T1 on a T0 card fails.""" for reader in readers(): cc = reader.createConnection() # on Mac OS X Tiger, trying to connect # with T=1 protocol does not except if not 'pcsclite-tiger' == resourceManagerSubType: if [] != expectedATRinReader[str(reader)]: # should fail since the test card does not support T1 self.assertRaises( CardConnectionException, cc.connect, CardConnection.T1_protocol) else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def testcase_CardConnectionT1inTransmit(self): """Test that T1 in transmit for a T0 card fails.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] for reader in readers(): cc = reader.createConnection() if [] != expectedATRinReader[str(reader)]: cc.connect() self.assertRaises( CardConnectionException, cc.transmit, SELECT + DF_TELECOM, CardConnection.T1_protocol) else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def testcase_CardConnectionT0T1(self): """Test test with T0 | T1 the response to SELECT DF_TELECOM.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] for reader in readers(): cc = reader.createConnection() if [] != expectedATRinReader[str(reader)]: cc.connect( CardConnection.T0_protocol | CardConnection.T1_protocol) response, sw1, sw2 = cc.transmit(SELECT + DF_TELECOM) expectedSWs = {"9f 1a": 1, "6e 0": 2, "9f 20": 3, "9f 22": 4} self.assertEquals([], response) self.assert_( "%x %x" % (sw1, sw2) in expectedSWs or "9f" == "%x" % sw1) else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def testcase_CardConnectionT0inTransmit(self): """Test with T0 in transmit the response to SELECT DF_TELECOM.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] for reader in readers(): cc = reader.createConnection() if [] != expectedATRinReader[str(reader)]: cc.connect(CardConnection.T0_protocol) response, sw1, sw2 = cc.transmit( SELECT + DF_TELECOM, CardConnection.T0_protocol) expectedSWs = {"9f 1a": 1, "6e 0": 2, "9f 20": 3, "9f 22": 4} self.assertEquals([], response) self.assert_( "%x %x" % (sw1, sw2) in expectedSWs or "9f" == "%x" % sw1) else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def testcase_CardConnectionT0T1inTransmitMustFail(self): """Test with bad parameter in transmit the response to SELECT DF_TELECOM.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] for reader in readers(): cc = reader.createConnection() if [] != expectedATRinReader[str(reader)]: cc.connect( CardConnection.T0_protocol | CardConnection.T1_protocol) self.assertRaises( CardConnectionException, cc.transmit, SELECT + DF_TELECOM, CardConnection.T0_protocol | CardConnection.T1_protocol) else: self.assertRaises(NoCardException, cc.connect) cc.disconnect() def suite(): suite1 = unittest.makeSuite(testcase_CardConnection) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/scard/0000755000175000017500000000000011747777125021063 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/test/scard/testcase_returncodes.py0000755000175000017500000000700011404463362025646 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for return codes This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "http://www.gemalto.com" Copyright 2009 gemalto Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 unittest from smartcard.scard import * import sys class testcase_returncodes(unittest.TestCase): """Test scard API for return codes """ def test_getReturnCodes(self): errors = ( SCARD_S_SUCCESS, SCARD_F_INTERNAL_ERROR, SCARD_E_CANCELLED, SCARD_E_INVALID_HANDLE, SCARD_E_INVALID_PARAMETER, SCARD_E_INVALID_TARGET, SCARD_E_NO_MEMORY, SCARD_F_WAITED_TOO_LONG, SCARD_E_INSUFFICIENT_BUFFER, SCARD_E_UNKNOWN_READER, SCARD_E_TIMEOUT, SCARD_E_SHARING_VIOLATION, SCARD_E_NO_SMARTCARD, SCARD_E_UNKNOWN_CARD, SCARD_E_CANT_DISPOSE, SCARD_E_PROTO_MISMATCH, SCARD_E_NOT_READY, SCARD_E_INVALID_VALUE, SCARD_E_SYSTEM_CANCELLED, SCARD_F_COMM_ERROR, SCARD_F_UNKNOWN_ERROR, SCARD_E_INVALID_ATR, SCARD_E_NOT_TRANSACTED, SCARD_E_READER_UNAVAILABLE, SCARD_E_PCI_TOO_SMALL, SCARD_E_READER_UNSUPPORTED, SCARD_E_DUPLICATE_READER, SCARD_E_CARD_UNSUPPORTED, SCARD_E_NO_SERVICE, SCARD_E_SERVICE_STOPPED, SCARD_E_UNEXPECTED, SCARD_E_ICC_INSTALLATION, SCARD_E_ICC_CREATEORDER, SCARD_E_UNSUPPORTED_FEATURE, SCARD_E_DIR_NOT_FOUND, SCARD_E_FILE_NOT_FOUND, SCARD_E_NO_DIR, SCARD_E_NO_FILE, SCARD_E_NO_ACCESS, SCARD_E_WRITE_TOO_MANY, SCARD_E_BAD_SEEK, SCARD_E_INVALID_CHV, SCARD_E_UNKNOWN_RES_MNG, SCARD_E_NO_SUCH_CERTIFICATE, SCARD_E_CERTIFICATE_UNAVAILABLE, SCARD_E_NO_READERS_AVAILABLE, SCARD_E_COMM_DATA_LOST, SCARD_E_NO_KEY_CONTAINER, SCARD_E_SERVER_TOO_BUSY, SCARD_W_UNSUPPORTED_CARD, SCARD_W_UNRESPONSIVE_CARD, SCARD_W_UNPOWERED_CARD, SCARD_W_RESET_CARD, SCARD_W_REMOVED_CARD, SCARD_W_SECURITY_VIOLATION, SCARD_W_WRONG_CHV, SCARD_W_CHV_BLOCKED, SCARD_W_EOF, SCARD_W_CANCELLED_BY_USER, SCARD_W_CARD_NOT_AUTHENTICATED, ) #for e in errors: # print hex((e+0x100000000) & 0xFFFFFFFF) def suite(): suite1 = unittest.makeSuite(testcase_returncodes) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/scard/testsuite_scard.py0000755000175000017500000000310511747776677024657 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit test suite for scard python module. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 sys import unittest # so that we can locate configcheck sys.path += ['..'] import configcheck def suite(): modules_to_test = ( 'testcase_getatr', 'testcase_getattrib', 'testcase_geterrormessage', 'testcase_listcards', 'testcase_locatecards', 'testcase_readergroups', 'testcase_returncodes', 'testcase_transaction') testsuite_scard = unittest.TestSuite() for module in map(__import__, modules_to_test): testsuite_scard.addTest(unittest.findTestCases(module)) return testsuite_scard if __name__ == '__main__': configcheck.checklocalconfig() unittest.main(defaultTest='suite') pyscard-1.6.14/smartcard/test/scard/testcase_getatr.py0000755000175000017500000000601311747776677024634 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for SCardConnect/SCardStatus/SCardDisconnect This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest from smartcard.scard import * # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader except: print 'execute test suite first to generate the local_config.py file' sys.exit() class testcase_getATR(unittest.TestCase): """Test scard API for ATR retrieval""" def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEquals(hresult, 0) hresult, self.readers = SCardListReaders(self.hcontext, []) self.assertEquals(hresult, 0) def tearDown(self): hresult = SCardReleaseContext(self.hcontext) self.assertEquals(hresult, 0) def _getATR(self, r): if r < len(expectedATRs) and [] != expectedATRs[r]: hresult, hcard, dwActiveProtocol = SCardConnect( self.hcontext, self.readers[r], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) self.assertEquals(hresult, 0) try: hresult, reader, state, protocol, atr = SCardStatus(hcard) self.assertEquals(hresult, 0) self.assertEquals(reader, expectedReaders[r]) self.assertEquals(atr, expectedATRs[r]) finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) self.assertEquals(hresult, 0) def test_getATR0(self): testcase_getATR._getATR(self, 0) def test_getATR1(self): testcase_getATR._getATR(self, 1) def test_getATR2(self): testcase_getATR._getATR(self, 2) def test_getATR3(self): testcase_getATR._getATR(self, 3) def suite(): suite1 = unittest.makeSuite(testcase_getATR) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/scard/readme.txt0000644000175000017500000000324610633575650023056 0ustar rousseaurousseau00000000000000------------------------------------------------------------------------------- This directory contains the test suite for the smartcard.scard wrapper of the C language SCardXXX API. You will need two smart card readers and two smart cards to run the test suite. Insert the readers and the cards in the readers before executing the test suite. On the first execution of the test suite, the configcheck.py script in the parent directory will generate a localconfig.py file that will contain the current names of the readers and ATRs of the cards inserted in the readers. These data are used by the test suite. If you change the test configuration, i.e. add or remove readers or cards, or change the readers or cards, just delete localconfig.py and re-run the test suite. ------------------------------------------------------------------------------- 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 ------------------------------------------------------------------------------- pyscard-1.6.14/smartcard/test/scard/testcase_getattrib.py0000755000175000017500000000746111747776677025343 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for SCardConnect/SCardGetAttrib/SCardDisconnect. This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 struct import unittest from smartcard.scard import * # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader except: print 'execute test suite first to generate the local_config.py file' sys.exit() class testcase_getAttrib(unittest.TestCase): """Test scard API for SCardGetAttrib""" def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEquals(hresult, 0) hresult, self.readers = SCardListReaders(self.hcontext, []) self.assertEquals(hresult, 0) def tearDown(self): hresult = SCardReleaseContext(self.hcontext) self.assertEquals(hresult, 0) def _getAttrib(self, r): if r < len(expectedATRs) and [] != expectedATRs[r]: hresult, hcard, dwActiveProtocol = SCardConnect( self.hcontext, self.readers[r], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) self.assertEquals(hresult, 0) try: hresult, reader, state, protocol, atr = SCardStatus(hcard) self.assertEquals(hresult, 0) self.assertEquals(reader, expectedReaders[r]) self.assertEquals(atr, expectedATRs[r]) if 'SCARD_ATTR_ATR_STRING' in scard.__dict__: hresult, attrib = SCardGetAttrib( hcard, SCARD_ATTR_ATR_STRING) self.assertEquals(hresult, 0) self.assertEquals(expectedATRs[r], attrib) if 'winscard' == resourceManager: hresult, attrib = SCardGetAttrib( hcard, SCARD_ATTR_DEVICE_SYSTEM_NAME_A) self.assertEquals(hresult, 0) trimmedAttrib = attrib[:-1] self.assertEquals( expectedReaders[r], apply(struct.pack, ['<' + 'B' * len(trimmedAttrib)] + \ trimmedAttrib)) finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) self.assertEquals(hresult, 0) def test_getATR0(self): testcase_getAttrib._getAttrib(self, 0) def test_getATR1(self): testcase_getAttrib._getAttrib(self, 1) def test_getATR3(self): testcase_getAttrib._getAttrib(self, 2) def test_getATR4(self): testcase_getAttrib._getAttrib(self, 3) def suite(): suite1 = unittest.makeSuite(testcase_getAttrib) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/scard/testcase_locatecards.py0000755000175000017500000001071011747776677025631 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for SCardLocateCards. This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 platform import unittest from smartcard.scard import * # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader except: print 'execute test suite first to generate the local_config.py file' sys.exit() class testcase_locatecards(unittest.TestCase): """Test scard API for ATR retrieval with SCardLocateCards""" def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEquals(hresult, 0) def tearDown(self): hresult = SCardReleaseContext(self.hcontext) self.assertEquals(hresult, 0) def test_locateCards(self): hresult, readers = SCardListReaders(self.hcontext, []) self.assertEquals(hresult, 0) foundReaders = {} for reader in readers: foundReaders[reader] = 1 for reader in expectedReaders: self.assert_(reader in foundReaders) if 'winscard' == resourceManager: hresult, cards = SCardListCards(self.hcontext, [], []) self.assertEquals(hresult, 0) readerstates = [] for i in xrange(len(readers)): readerstates += [(readers[i], SCARD_STATE_UNAWARE)] hresult, newstates = SCardLocateCards( self.hcontext, cards, readerstates) self.assertEquals(hresult, 0) if -1 == platform.platform().find('Windows-7'): dictexpectedreaders = {} for reader in expectedReaders: dictexpectedreaders[reader] = 1 for reader, eventstate, atr in newstates: if reader in dictexpectedreaders and \ [] != expectedATRinReader[reader]: self.assertEquals(expectedATRinReader[reader], atr) self.assert_(eventstate & SCARD_STATE_PRESENT) self.assert_(eventstate & SCARD_STATE_CHANGED) # 10ms delay, so that time-out always occurs hresult, newstates = SCardGetStatusChange( self.hcontext, 10, newstates) self.assertEquals(hresult, SCARD_E_TIMEOUT) self.assertEquals( SCardGetErrorMessage(hresult), 'The user-specified timeout value has expired. ') elif 'pcsclite' == resourceManager: readerstates = [] for i in xrange(len(readers)): readerstates += [(readers[i], SCARD_STATE_UNAWARE)] hresult, newstates = SCardGetStatusChange( self.hcontext, 0, readerstates) self.assertEquals(hresult, 0) dictexpectedreaders = {} for reader in expectedReaders: dictexpectedreaders[reader] = 1 for reader, eventstate, atr in newstates: if reader in dictexpectedreaders and \ [] != expectedATRinReader[reader]: self.assertEquals(expectedATRinReader[reader], atr) self.assert_(eventstate & SCARD_STATE_PRESENT) self.assert_(eventstate & SCARD_STATE_CHANGED) def suite(): suite1 = unittest.makeSuite(testcase_locatecards) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/scard/testcase_listcards.py0000755000175000017500000002345511747776677025347 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for SCardIntroduceCardType/SCardListCards/SCardListInterfaces This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest import platform from smartcard.scard import * import smartcard.guid if 'winscard' == resourceManager: class testcase_listcards(unittest.TestCase): """Test scard API for ATR retrieval""" # setup for all unit tests: establish context and introduce # a dummy card interface def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEquals(hresult, 0) self.dummycardname = 'dummycard' self.dummycardATR = \ [0x3B, 0x75, 0x94, 0x00, 0x00, 0x62, 0x02, 0x02, 0x01, 0x01] self.dummycardMask = \ [0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] self.dummycardguid1 = \ smartcard.guid.strToGUID( '{AD4F1667-EA75-4124-84D4-641B3B197C65}') self.dummycardguid2 = \ smartcard.guid.strToGUID( '{382AE95A-7C2C-449c-A179-56C6DE6FF3BC}') testcase_listcards.__introduceinterface(self) # teardown for all unit tests: release context and forget # dummy card interface def tearDown(self): testcase_listcards.__forgetinterface(self) hresult = SCardReleaseContext(self.hcontext) self.assertEquals(hresult, 0) # introduce a dummy card interface # card ATR same as e-gate def __introduceinterface(self): hresult = SCardForgetCardType(self.hcontext, self.dummycardname) dummycardPrimaryGUID = self.dummycardguid1 dummycardGUIDS = self.dummycardguid1 + self.dummycardguid2 hresult = SCardIntroduceCardType( self.hcontext, self.dummycardname, dummycardPrimaryGUID, dummycardGUIDS, self.dummycardATR, self.dummycardMask) self.assertEquals(hresult, 0) # forget dummy card interface def __forgetinterface(self): hresult = SCardForgetCardType(self.hcontext, self.dummycardname) self.assertEquals(hresult, 0) # locate a known card # Cryptoflex 8k v2 is present in standard Windows 2000 def test_listcryptoflexbyatr(self): if -1 != platform.platform().find('Windows-7'): dmyATR = \ [0x3B, 0x75, 0x94, 0x00, 0x00, 0x62, 0x02, 0x02, 0x01, 0x01] dmyName = ['dummycard'] hresult, card = SCardListCards(self.hcontext, dmyATR, []) self.assertEquals(hresult, 0) self.assertEquals(card, dmyName) elif -1 != platform.platform().find('Windows-Vista-6.0'): axaltodotnetATR = \ [ 0x3B, 0x16, 0x96, 0x41, 0x73, 0x74, 0x72, 0x69, 0x64 ] axaltodotnetName = ['Axalto Cryptoflex .NET'] hresult, card = SCardListCards(self.hcontext, axaltodotnetATR, []) self.assertEquals(hresult, 0) self.assertEquals(card, axaltodotnetName) else: slbCryptoFlex8kv2ATR = \ [0x3B, 0x95, 0x15, 0x40, 0x00, 0x68, 0x01, 0x02, 0x00, 0x00] slbCryptoFlex8kv2Name = ['Schlumberger Cryptoflex 8K v2'] hresult, card = SCardListCards( self.hcontext, slbCryptoFlex8kv2ATR, []) self.assertEquals(hresult, 0) self.assertEquals(card, slbCryptoFlex8kv2Name) # locate dummy card by interface def test_listdummycardbyguid(self): guidstolocate = self.dummycardguid2 + self.dummycardguid1 locatedcardnames = [self.dummycardname] hresult, card = SCardListCards(self.hcontext, [], guidstolocate) self.assertEquals(hresult, 0) self.assertEquals(card, locatedcardnames) # list our dummy card interfaces and check # that they match the introduced interfaces def test_listdummycardinterfaces(self): hresult, interfaces = SCardListInterfaces( self.hcontext, self.dummycardname) self.assertEquals(hresult, 0) self.assertEquals(2, len(interfaces)) self.assertEquals(self.dummycardguid1, interfaces[0]) self.assertEquals(self.dummycardguid2, interfaces[1]) # locate all cards and interfaces in the system def test_listallcards(self): if -1 != platform.platform().find('Windows-7'): expectedCards = ['Identity Device (Microsoft Generic Profile)', 'Identity Device (NIST SP 800-73 [PIV])'] elif -1 != platform.platform().find('Windows-Vista-6.0'): expectedCards = [ 'Axalto Cryptoflex .NET', 'Infineon SICRYPT CardModule Card', 'dummycard' ] else: # dummycard has been introduced in the test setup and # will be removed in the test teardown. Other cards are # the cards present by default on Windows 2000 expectedCards = ['dummycard', 'GemSAFE Smart Card (8K)', 'Schlumberger Cryptoflex 4K', 'Schlumberger Cryptoflex 8K', 'Schlumberger Cryptoflex 8K v2'] hresult, cards = SCardListCards(self.hcontext, [], []) self.assertEquals(hresult, 0) foundCards = {} for i in xrange(len(cards)): foundCards[cards[i]] = 1 for i in expectedCards: self.assert_(i in foundCards) # dummycard has a primary provider, # other cards have no primary provider if 'Windows-7-6.1.7600' == platform.platform(): expectedPrimaryProviderResult = { 'dummycard': [0, self.dummycardguid1], 'Identity Device (Microsoft Generic Profile)': \ [2, None], 'Identity Device (NIST SP 800-73 [PIV])': \ [2, None]} else: expectedPrimaryProviderResult = { 'dummycard': [0, self.dummycardguid1], 'GemSAFE': [2, None], 'Schlumberger Cryptoflex 4k': [2, None], 'Schlumberger Cryptoflex 8k': [2, None], 'Schlumberger Cryptoflex 8k v2': [2, None]} for i in xrange(len(cards)): hresult, providername = SCardGetCardTypeProviderName( self.hcontext, cards[i], SCARD_PROVIDER_PRIMARY) if cards[i] in expectedPrimaryProviderResult: self.assertEquals( hresult, expectedPrimaryProviderResult[cards[i]][0]) if hresult == 0: self.assertEquals( providername, smartcard.guid.GUIDToStr( expectedPrimaryProviderResult[cards[i]][1])) # dummycard has no CSP, other cards have a CSP if 'Windows-7-6.1.7600' == platform.platform(): expectedProviderCSPResult = { 'dummycard': [2, None], 'Identity Device (Microsoft Generic Profile)': \ [0, 'Microsoft Base Smart Card Crypto Provider'], 'Identity Device (NIST SP 800-73 [PIV])': \ [0, 'Microsoft Base Smart Card Crypto Provider']} else: expectedProviderCSPResult = { 'dummycard': [2, None], 'GemSAFE': [0, 'Gemplus GemSAFE Card CSP v1.0'], 'Schlumberger Cryptoflex 4k': \ [0, 'Schlumberger Cryptographic Service Provider'], 'Schlumberger Cryptoflex 8k': \ [0, 'Schlumberger Cryptographic Service Provider'], 'Schlumberger Cryptoflex 8k v2': \ [0, 'Schlumberger Cryptographic Service Provider']} for i in xrange(len(cards)): hresult, providername = SCardGetCardTypeProviderName( self.hcontext, cards[i], SCARD_PROVIDER_CSP) if cards[i] in expectedProviderCSPResult: self.assertEquals( hresult, expectedProviderCSPResult[cards[i]][0]) self.assertEquals( providername, expectedProviderCSPResult[cards[i]][1]) def suite(): suite1 = unittest.makeSuite(testcase_listcards) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/scard/testcase_transaction.py0000755000175000017500000000642511747776677025702 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for SCardBeginTransaction/SCardEndTransaction. This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest from smartcard.scard import * # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders except: print 'execute test suite first to generate the local_config.py file' sys.exit() class testcase_transaction(unittest.TestCase): """Test scard API for SCardBegin/EndTransaction""" def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEquals(hresult, 0) hresult, self.readers = SCardListReaders(self.hcontext, []) self.assertEquals(hresult, 0) def tearDown(self): hresult = SCardReleaseContext(self.hcontext) self.assertEquals(hresult, 0) def _transaction(self, r): if r < len(expectedATRs) and [] != expectedATRs[r]: hresult, hcard, dwActiveProtocol = SCardConnect( self.hcontext, self.readers[r], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) self.assertEquals(hresult, 0) try: hresult = SCardBeginTransaction(hcard) self.assertEquals(hresult, 0) hresult, reader, state, protocol, atr = SCardStatus(hcard) self.assertEquals(hresult, 0) self.assertEquals(reader, expectedReaders[r]) self.assertEquals(atr, expectedATRs[r]) hresult = SCardEndTransaction(hcard, SCARD_LEAVE_CARD) self.assertEquals(hresult, 0) finally: hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD) self.assertEquals(hresult, 0) def test_transaction_reader0(self): testcase_transaction._transaction(self, 0) def test_transaction_reader1(self): testcase_transaction._transaction(self, 1) def test_transaction_reader2(self): testcase_transaction._transaction(self, 2) def test_transaction_reader3(self): testcase_transaction._transaction(self, 3) def suite(): suite1 = unittest.makeSuite(testcase_transaction) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/scard/testcase_geterrormessage.py0000755000175000017500000000443111747776677026546 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for SCardGetErrorMessage. This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest from smartcard.scard import * import sys class testcase_geterrormessage(unittest.TestCase): """Test scard API for ATR retrieval with SCardLocateCards""" def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEquals(hresult, 0) def tearDown(self): hresult = SCardReleaseContext(self.hcontext) self.assertEquals(hresult, 0) def test_getErrorMessage(self): hresult, readers = SCardListReaders(self.hcontext, []) self.assertEquals(hresult, 0) hresult = SCardReleaseContext(123L) if 'win32' == sys.platform: self.assertEquals(( SCARD_E_INVALID_HANDLE == hresult or \ ERROR_INVALID_HANDLE == hresult), True) else: self.assertEquals((SCARD_E_INVALID_HANDLE == hresult), True) self.assertEquals(( SCardGetErrorMessage(hresult).rstrip() == \ 'Invalid handle.'.rstrip() or \ SCardGetErrorMessage(hresult).rstrip() == \ 'The handle is invalid.'.rstrip()), True) def suite(): suite1 = unittest.makeSuite(testcase_geterrormessage) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/scard/testcase_readergroups.py0000755000175000017500000001075711747776677026062 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for SCardxxx readers and readergroups methods. This test case can be executed individually, or with all other test cases thru testsuite_scard.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest from smartcard.scard import * # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedReaders except: print 'execute test suite first to generate the local_config.py file' sys.exit() expectedGroups = ['SCard$DefaultReaders'] class testcase_readergroups(unittest.TestCase): """Test scard reader groups API""" def setUp(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) self.assertEquals(hresult, 0) def tearDown(self): hresult = SCardReleaseContext(self.hcontext) self.assertEquals(hresult, 0) def test_listReaders(self): # list current readers and compare with expected list hresult, readers = SCardListReaders(self.hcontext, []) self.assertEquals(hresult, 0) for i in xrange(len(expectedReaders)): self.assertEquals(readers[i], expectedReaders[i]) # list current reader groups and compare with expected list hresult, readerGroups = SCardListReaderGroups(self.hcontext) self.assertEquals(hresult, 0) for i in xrange(len(expectedGroups)): self.assertEquals(readerGroups[i], expectedGroups[i]) if 'winscard' == resourceManager: # add a new group newgroup = 'SCard$MyOwnGroup' expectedGroups.append(newgroup) hresult = SCardIntroduceReaderGroup(self.hcontext, newgroup) self.assertEquals(hresult, 0) dummyreader = readers[0] + ' alias' hresult = SCardIntroduceReader( self.hcontext, dummyreader, readers[0]) self.assertEquals(hresult, 0) hresult = SCardAddReaderToGroup( self.hcontext, dummyreader, newgroup) self.assertEquals(hresult, 0) hresult, readerGroups = SCardListReaderGroups(self.hcontext) self.assertEquals(hresult, 0) for i in xrange(len(expectedGroups)): self.assertEquals(readerGroups[i], expectedGroups[i]) # list readers in new group hresult, newreaders = SCardListReaders(self.hcontext, [newgroup]) self.assertEquals(hresult, 0) self.assertEquals(newreaders[0], dummyreader) # remove reader from new group hresult = SCardRemoveReaderFromGroup( self.hcontext, dummyreader, newgroup) self.assertEquals(hresult, 0) hresult, readerGroups = SCardListReaderGroups(self.hcontext) self.assertEquals(hresult, 0) expectedGroups.remove(newgroup) for i in xrange(len(expectedGroups)): self.assertEquals(readerGroups[i], expectedGroups[i]) hresult = SCardForgetReaderGroup(self.hcontext, newgroup) self.assertEquals(hresult, 0) hresult, readerGroups = SCardListReaderGroups(self.hcontext) self.assertEquals(hresult, 0) for i in xrange(len(expectedGroups)): self.assertEquals(readerGroups[i], expectedGroups[i]) hresult = SCardForgetReader(self.hcontext, dummyreader) self.assertEquals(hresult, 0) def suite(): suite1 = unittest.makeSuite(testcase_readergroups) return unittest.TestSuite((suite1)) if __name__ == '__main__': # When this module is executed from the command-line, run all its tests unittest.main() pyscard-1.6.14/smartcard/test/scard/local_config.py0000644000175000017500000000061011152536161024030 0ustar rousseaurousseau00000000000000from smartcard.util import toHexString expectedReaders = [] expectedATRs = [] expectedATRinReader = {} for i in xrange(len(expectedReaders)): expectedATRinReader[expectedReaders[i]]=expectedATRs[i] expectedReaderForATR = {} for i in xrange(len(expectedReaders)): expectedReaderForATR[toHexString(expectedATRs[i])]=expectedReaders[i] expectedReaderGroups = [ 'SCard$DefaultReaders' ] pyscard-1.6.14/smartcard/test/frameworkpcsc/0000755000175000017500000000000011747777125022635 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/test/frameworkpcsc/testcase_pcscreadergroups.py0000755000175000017500000001422711747776677030501 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit tests for smartcard.pcsc.readers This test case can be executed individually, or with all other test cases thru testsuite_framework.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 unittest # import local_config for reader/card configuration # configcheck.py is generating local_config.py in # the test suite. import sys sys.path += ['..'] try: from local_config import expectedATRs, expectedReaders from local_config import expectedReaderGroups, expectedATRinReader except: print 'execute test suite first to generate the local_config.py file' sys.exit() from smartcard.pcsc.PCSCReaderGroups import PCSCReaderGroups from smartcard.pcsc.PCSCReader import PCSCReader from smartcard.scard import resourceManager if 'winscard' == resourceManager: class testcase_readergroups(unittest.TestCase): """Test smartcard framework readers factory methods""" def setUp(self): groups = PCSCReaderGroups().instance try: groups.remove('Pinpad$Readers') groups.remove('Biometric$Readers') except: pass def testcase_add(self): """Test for groups=groups+newgroups""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroup = 'Pinpad$Readers' groups = groups + newgroup self.assertEquals(groups, groupssnapshot + [newgroup]) groups.remove(newgroup) def testcase_addlist(self): """Test for groups=groups+[newgroups]""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroups = ['Pinpad$Readers', 'Biometric$Readers'] groups = groups + newgroups self.assertEquals(groups, groupssnapshot + newgroups) for group in newgroups: groups.remove(group) def testcase_iadd(self): """Test for groups+=newgroup""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroup = 'Pinpad$Readers' groups += newgroup self.assertEquals(groups, groupssnapshot + [newgroup]) groups.remove(newgroup) def testcase_iaddlist(self): """Test for groups+=[newgroups]""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroups = ['Pinpad$Readers', 'Biometric$Readers'] groups += newgroups self.assertEquals(groups, groupssnapshot + newgroups) for group in newgroups: groups.remove(group) def testcase_append(self): """Test for groups.append(newgroup)""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroup = 'Pinpad$Readers' groups.append(newgroup) self.assertEquals(groups, groupssnapshot + [newgroup]) groups.remove(newgroup) def testcase_insert(self): """Test for groups.insert(newgroup)""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroup = 'Pinpad$Readers' groups.insert(0, newgroup) self.assertEquals(groups, [newgroup] + groupssnapshot) groups.remove(newgroup) def testcase_removereadergroup_pop(self): """Test for groups.pop()""" groupssnapshot = list(PCSCReaderGroups().instance) groups = PCSCReaderGroups().instance newgroup = 'Pinpad$Readers' groups.insert(0, newgroup) self.assertEquals(groups, [newgroup] + groupssnapshot) groups.pop(0) self.assertEquals(groups, groupssnapshot) def testcase_addreadertogroup(self): """Test for adding readers to group""" groups = PCSCReaderGroups().instance newgroup = 'Pinpad$Readers' groups.insert(0, newgroup) for r in PCSCReader.readers('SCard$DefaultReaders'): r.addtoreadergroup(newgroup) self.assertEquals( PCSCReader.readers( 'SCard$DefaultReaders'), PCSCReader.readers(newgroup)) groups.pop(0) self.assertEquals([], PCSCReader.readers(newgroup)) def testcase_removereaderfromgroup(self): """Test for removing readers from group""" groups = PCSCReaderGroups().instance newgroup = 'Pinpad$Readers' groups.insert(0, newgroup) for r in PCSCReader.readers('SCard$DefaultReaders'): r.addtoreadergroup(newgroup) self.assertEquals( PCSCReader.readers( 'SCard$DefaultReaders'), PCSCReader.readers(newgroup)) for r in PCSCReader.readers('SCard$DefaultReaders'): r.removefromreadergroup(newgroup) self.assertEquals([], PCSCReader.readers(newgroup)) groups.pop(0) self.assertEquals([], PCSCReader.readers(newgroup)) def suite(): suite1 = unittest.makeSuite(testcase_readergroups) return unittest.TestSuite((suite1)) if __name__ == '__main__': unittest.main() pyscard-1.6.14/smartcard/test/frameworkpcsc/readme.txt0000644000175000017500000000322210633575650024622 0ustar rousseaurousseau00000000000000------------------------------------------------------------------------------- This directory contains the test suite for the pcsc part of the pyscard framework. You will need two smart card readers and two smart cards to run the test suite. Insert the readers and the cards in the readers before executing the test suite. On the first execution of the test suite, the configcheck.py script in the parent directory will generate a localconfig.py file that will contain the current names of the readers and ATRs of the cards inserted in the readers. These data are used by the test suite. If you change the test configuration, i.e. add or remove readers or cards, or change the readers or cards, just delete localconfig.py and re-run the test suite. ------------------------------------------------------------------------------- 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 ------------------------------------------------------------------------------- pyscard-1.6.14/smartcard/test/frameworkpcsc/testsuite_frameworkpcsc.py0000755000175000017500000000262411747776677030210 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Unit test suite for smartcard python framework over pcsc. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 sys import unittest # so that we can locate configcheck sys.path += ['..'] import configcheck def suite(): modules_to_test = ( 'testcase_pcscreadergroups', ) testsuite_framework = unittest.TestSuite() for module in map(__import__, modules_to_test): testsuite_framework.addTest(unittest.findTestCases(module)) return testsuite_framework if __name__ == '__main__': configcheck.checklocalconfig() unittest.main(defaultTest='suite') pyscard-1.6.14/smartcard/test/configcheck.py0000755000175000017500000000472111747776700022611 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Generates test suite smartcard configuration from connected readers and cards. The generated configuration is store in local_config.py. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.System import readers from smartcard.Exceptions import NoCardException from smartcard.util import toHexString def getATR(reader): cc = reader.createConnection() cc.connect() atr = cc.getATR() cc.disconnect() return atr def checklocalconfig(): try: f = open('local_config.py', 'r') except IOError: print 'local_config.py not found; generating local_config.py...' # generate local configuration f = open('local_config.py', 'w+') f.write('from smartcard.util import toHexString\n') f.write('expectedReaders = ') f.write(str(readers()) + '\n') expectedATRs = [] for reader in readers(): try: expectedATRs.append(getATR(reader)) except NoCardException: expectedATRs.append([]) f.write('expectedATRs = ') #for atr in expectedATRs: print `toHexString(atr)` f.write(repr(expectedATRs) + '\n') f.write('expectedATRinReader = {}\n') f.write('for i in xrange(len(expectedReaders)):\n') f.write(' expectedATRinReader[expectedReaders[i]] = expectedATRs[i]\n') f.write('expectedReaderForATR = {}\n') f.write('for i in xrange(len(expectedReaders)):\n') f.write(' expectedReaderForATR[toHexString(expectedATRs[i])] = ' + \ 'expectedReaders[i]\n') f.write('expectedReaderGroups = [\'SCard$DefaultReaders\']\n') f.close() if __name__ == '__main__': import sys checklocalconfig() sys.exit() pyscard-1.6.14/smartcard/PassThruCardService.py0000644000175000017500000000437011747776700023250 0ustar rousseaurousseau00000000000000"""Card service abstract class. A card service is a class providings specific smart card functionality, e.g. a GSM file system or an Open Platform loader. CardService is an abstract class from which concrete card services are derived. A concrete card service is almost always smart card operating system specific __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard import CardService class PassThruCardService(CardService.CardService): """Pass-thru card service class.""" def __init__(self, connection, cardname=None): """Construct a pass-thru card service. connection: the CardConnection used to access the smart card """ CardService.CardService.__init__(self, connection, cardname) def supports(cardname): """Returns True if the cardname is supported by the card service. The PassThruCardService supports all cardnames and always returns True.""" return True supports = staticmethod(supports) if __name__ == '__main__': """Small sample illustrating the use of CardService.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] from smartcard.System import readers from smartcard.CardConnection import CardConnection cc = readers()[0].createConnection() cs = PassThruCardService(cc) cs.connection.connect() data, sw1, sw2 = cs.connection.transmit(SELECT + DF_TELECOM) print "%X %X" % (sw1, sw2) cs.connection.disconnect() pyscard-1.6.14/smartcard/CardNames.py0000644000175000017500000000635311747776700021224 0ustar rousseaurousseau00000000000000"""Card Names class __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from _bsddb import DBNotFoundError from bsddb import hashopen from os import environ from os.path import join from pickle import dumps, loads, HIGHEST_PROTOCOL from smartcard.Synchronization import Synchronization, synchronize from smartcard.util import toBytes class __CardNames__(Synchronization): """__CardNames__ inner class. Stores card names and card types into a bsddb hash database. The smartcard.CardNames.CardNames singleton manages the creation of the unique instance of this class. """ def __init__(self): Synchronization.__init__(self) carddb_dir = environ['ALLUSERSPROFILE'] carddb_file = 'cardnames.bdb' carddb_file = join(carddb_dir, carddb_file) self.db = hashopen(carddb_file, 'w') def __del__(self): self.db.sync() self.db.close() def add(self, cardname, cardtype): self.db[cardname] = dumps(cardtype, HIGHEST_PROTOCOL) self.db.sync() def delete(self, cardname): try: del self.db[cardname] except DBNotFoundError: pass def dump(self): for k, v in self.db.iteritems(): print k, repr(loads(v)) def find(self, atr, reader=None): for k, v in self.db.iteritems(): if loads(v).matches(atr, reader): return k synchronize(__CardNames__, "add delete dump find") class CardNames(object): """The CardNames organizes cards by a unique name and an associated smartcard.CardType.CardType.""" """The single instance of __CardNames__""" instance = None def __init__(self): """Constructor: create a single instance of __readergroups on first call""" if None == CardNames.instance: CardNames.instance = __CardNames__() def __getattr__(self, name): """All operators redirected to inner class.""" return getattr(self.instance, name) if __name__ == '__main__': from smartcard.CardType import ATRCardType # define a card by its ATR ct = ATRCardType([0x3B, 0x16, 0x94, 0x20, 0x02, 0x01, 0x00, 0x00, 0x0D]) # create CardName cn = CardNames() cn.add("Palmera Protect V2", ct) cn.dump() print cn.find([0x3B, 0x16, 0x94, 0x20, 0x02, 0x01, 0x00, 0x00, 0x0D]) print cn.find([0x3B, 0x16, 0x94, 0x20, 0x02, 0x01, 0x00, 0x00]) cn.delete("Palmera Protect V2") print '---------' cn.dump() pyscard-1.6.14/smartcard/CardConnectionDecorator.py0000644000175000017500000000621511747776700024120 0ustar rousseaurousseau00000000000000"""The CardConnectionDecorator is a Decorator around the CardConnection abstract class, and allows dynamic addition of features to the CardConnection, e.g. implementing a secure channel.. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardConnection import CardConnection class CardConnectionDecorator(CardConnection): """Card connection decorator class.""" def __init__(self, cardConnectionComponent): """Construct a new card connection decorator. CardConnectionComponent: CardConnection component to decorate """ self.component = cardConnectionComponent def addSWExceptionToFilter(self, exClass): """call inner component addSWExceptionToFilter""" self.component.addSWExceptionToFilter(exClass) def addObserver(self, observer): """call inner component addObserver""" self.component.addObserver(observer) def deleteObserver(self, observer): """call inner component deleteObserver""" self.component.deleteObserver(observer) def connect(self, protocol=None, mode=None, disposition=None): """call inner component connect""" self.component.connect(protocol, mode, disposition) def disconnect(self): """call inner component disconnect""" self.component.disconnect() def getATR(self): """call inner component getATR""" return self.component.getATR() def getProtocol(self): """call inner component getProtocol""" return self.component.getProtocol() def getReader(self): """call inner component getReader""" return self.component.getReader() def setErrorCheckingChain(self, errorcheckingchain): """call inner component setErrorCheckingChain""" self.component.setErrorCheckingChain(errorcheckingchain) def setProtocol(self, protocol): """call inner component setProtocol""" return self.component.setProtocol(protocol) def transmit(self, bytes, protocol=None): """call inner component transmit""" return self.component.transmit(bytes, protocol) def control(self, controlCode, bytes=[]): """call inner component control""" return self.component.control(controlCode, bytes) def getAttrib(self, attribId): """call inner component getAttrib""" return self.component.getAttrib(attribId) pyscard-1.6.14/smartcard/CardConnectionEvent.py0000644000175000017500000000263011747776700023254 0ustar rousseaurousseau00000000000000"""The CardConnectionEvent is sent to CardConnectionObserver objects when a CardConnection event occurs. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ class CardConnectionEvent(object): """Base class for card connection events. This event is notified by CardConnection objects. type: 'connect', 'disconnect', 'command', 'response' args: None for 'connect' or 'disconnect' command APDU byte list for 'command' [response data, sw1, sw2] for 'response' type: 'connect' args:""" def __init__(self, type, args=None): self.type = type self.args = args pyscard-1.6.14/smartcard/AbstractCardRequest.py0000644000175000017500000000654611747776700023301 0ustar rousseaurousseau00000000000000"""AbstractCardRequest class. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardType import AnyCardType from smartcard.PassThruCardService import PassThruCardService import smartcard.System class AbstractCardRequest(object): """The base class for xxxCardRequest classes. A CardRequest is used for waitForCard() invocations and specifies what kind of smart card an application is waited for. Known subclasses: smartcard.pcsc.PCSCCardRequest""" def __init__(self, newcardonly=False, readers=None, cardType=None, cardServiceClass=None, timeout=1): """Construct new CardRequest. newcardonly: if True, request a new card; default is False, i.e. accepts cards already inserted readers: the list of readers to consider for requesting a card; default is to consider all readers cardType: the smartcard.CardType.CardType to wait for; default is smartcard.CardType.AnyCardType, i.e. the request will succeed with any card cardServiceClass: the specific card service class to create and bind to the card;default is to create and bind a smartcard.PassThruCardService timeout: the time in seconds we are ready to wait for connecting to the requested card. default is to wait one second; to wait forever, set timeout to None """ self.newcardonly = newcardonly self.readersAsked = readers self.cardType = cardType self.cardServiceClass = cardServiceClass self.timeout = timeout # if no CardType requeted, use AnyCardType if None == self.cardType: self.cardType = AnyCardType() # if no card service requested, use pass-thru card service if None == self.cardServiceClass: self.cardServiceClass = PassThruCardService def getReaders(self): """Returns the list or readers on which to wait for cards.""" # if readers not given, use all readers if None == self.readersAsked: return smartcard.System.readers() else: return self.readersAsked def waitforcard(self): """Wait for card insertion and returns a card service.""" pass def waitforcardevent(self): """Wait for card insertion or removal.""" pass pyscard-1.6.14/smartcard/ClassLoader.py0000644000175000017500000000336111747776700021557 0ustar rousseaurousseau00000000000000"""ClassLoader allows you to load modules from packages without hard-coding their class names in code; instead, they might be specified in a configuration file, as command-line parameters, or within an interface. Source: Robert Brewer at the Python Cookbook: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/223972 License: PSF license (http://docs.python.org/license.html). """ import sys import types def get_mod(modulePath): """Import a module.""" return __import__(modulePath, globals(), locals(), ['']) def get_func(fullFuncName): """Retrieve a function object from a full dotted-package name.""" # Parse out the path, module, and function lastDot = fullFuncName.rfind(u".") funcName = fullFuncName[lastDot + 1:] modPath = fullFuncName[:lastDot] aMod = get_mod(modPath) aFunc = getattr(aMod, funcName) # Assert that the function is a *callable* attribute. assert callable(aFunc), u"%s is not callable." % fullFuncName # Return a reference to the function itself, # not the results of the function. return aFunc def get_class(fullClassName, parentClass=None): """Load a module and retrieve a class (NOT an instance). If the parentClass is supplied, className must be of parentClass or a subclass of parentClass (or None is returned). """ aClass = get_func(fullClassName) # Assert that the class is a subclass of parentClass. if parentClass is not None: if not issubclass(aClass, parentClass): raise TypeError(u"%s is not a subclass of %s" % (fullClassName, parentClass)) # Return a reference to the class itself, not an instantiated object. return aClass pyscard-1.6.14/smartcard/pcsc/0000755000175000017500000000000011747777125017740 5ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/pcsc/PCSCReaderGroups.py0000644000175000017500000000775011747776676023410 0ustar rousseaurousseau00000000000000"""PCSCReaderGroups organizes smartcard readers as groups. __author__ = "gemalto http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.scard import * from smartcard.reader.ReaderGroups import readergroups, innerreadergroups from smartcard.pcsc.PCSCExceptions import * class pcscinnerreadergroups(innerreadergroups): """Smartcard PCSC readers groups inner class. The PCSCReaderGroups singleton manages the creation of the unique instance of this class. """ def __init__(self, initlist=None): """Constructor.""" innerreadergroups.__init__(self, initlist) self.unremovablegroups = ['SCard$DefaultReaders'] def getreadergroups(self): """ Returns the list of smartcard reader groups.""" innerreadergroups.getreadergroups(self) hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != 0: raise EstablishContextException(hresult) hresult, readers = SCardListReaderGroups(hcontext) if hresult != 0: raise ListReadersException(hresult) hresult = SCardReleaseContext(hcontext) if hresult != 0: raise ReleaseContextException(hresult) return readers def addreadergroup(self, newgroup): """Add a reader group""" hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if 0 != hresult: raise error( 'Failed to establish context: ' + \ SCardGetErrorMessage(hresult)) try: hresult = SCardIntroduceReaderGroup(hcontext, newgroup) if 0 != hresult: raise error( 'Unable to introduce reader group: ' + \ SCardGetErrorMessage(hresult)) else: innerreadergroups.addreadergroup(self, newgroup) finally: hresult = SCardReleaseContext(hcontext) if 0 != hresult: raise error( 'Failed to release context: ' + \ SCardGetErrorMessage(hresult)) def removereadergroup(self, group): """Remove a reader group""" hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if 0 != hresult: raise error( 'Failed to establish context: ' + \ SCardGetErrorMessage(hresult)) try: hresult = SCardForgetReaderGroup(hcontext, group) if hresult != 0: raise error( 'Unable to forget reader group: ' + \ SCardGetErrorMessage(hresult)) else: innerreadergroups.removereadergroup(self, group) finally: hresult = SCardReleaseContext(hcontext) if 0 != hresult: raise error( 'Failed to release context: ' + \ SCardGetErrorMessage(hresult)) class PCSCReaderGroups(readergroups): """PCSC readers groups.""" def __init__(self, initlist=None): """Create a single instance of pcscinnerreadergroups on first call""" self.innerclazz = pcscinnerreadergroups readergroups.__init__(self, initlist) if __name__ == '__main__': print PCSCReaderGroups() pyscard-1.6.14/smartcard/pcsc/PCSCContext.py0000644000175000017500000000350111747776676022420 0ustar rousseaurousseau00000000000000"""PCSC context singleton. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from threading import RLock from smartcard.scard import * from smartcard.pcsc.PCSCExceptions import EstablishContextException class PCSCContext(object): """Manage a singleton pcsc context handle.""" class __PCSCContextSingleton: """The actual pcsc context class as a singleton.""" def __init__(self): hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != 0: raise EstablishContextException(hresult) def getContext(self): return self.hcontext # the singleton mutex = RLock() instance = None def __init__(self): PCSCContext.mutex.acquire() try: if not PCSCContext.instance: PCSCContext.instance = PCSCContext.__PCSCContextSingleton() finally: PCSCContext.mutex.release() def __getattr__(self, name): if self.instance: return getattr(self.instance, name) pyscard-1.6.14/smartcard/pcsc/PCSCCardConnection.py0000644000175000017500000002221611747776676023671 0ustar rousseaurousseau00000000000000"""PCSCCardConnection class manages connections thru a PCSC reader. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardConnection import CardConnection from smartcard.Exceptions import (CardConnectionException, NoCardException, SmartcardException) from smartcard.Observer import Observable from smartcard.scard import * def translateprotocolmask(protocol): """Translate CardConnection protocol mask into PCSC protocol mask.""" pcscprotocol = 0 if None != protocol: if CardConnection.T0_protocol & protocol: pcscprotocol |= SCARD_PROTOCOL_T0 if CardConnection.T1_protocol & protocol: pcscprotocol |= SCARD_PROTOCOL_T1 if CardConnection.RAW_protocol & protocol: pcscprotocol |= SCARD_PROTOCOL_RAW if CardConnection.T15_protocol & protocol: pcscprotocol |= SCARD_PROTOCOL_T15 return pcscprotocol def translateprotocolheader(protocol): """Translate protocol into PCSC protocol header.""" pcscprotocol = 0 if None != protocol: if CardConnection.T0_protocol == protocol: pcscprotocol = SCARD_PCI_T0 if CardConnection.T1_protocol == protocol: pcscprotocol = SCARD_PCI_T1 if CardConnection.RAW_protocol == protocol: pcscprotocol = SCARD_PCI_RAW return pcscprotocol dictProtocolHeader = {SCARD_PCI_T0: 'T0', SCARD_PCI_T1: 'T1', SCARD_PCI_RAW: 'RAW'} dictProtocol = {SCARD_PROTOCOL_T0: 'T0', SCARD_PROTOCOL_T1: 'T1', SCARD_PROTOCOL_RAW: 'RAW', SCARD_PROTOCOL_T15: 'T15', SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1: 'T0 or T1'} class PCSCCardConnection(CardConnection): """PCSCCard connection class. Handles connection with a card thru a PCSC reader.""" def __init__(self, reader): """Construct a new PCSC card connection. reader: the reader in which the smartcard to connect to is located. """ CardConnection.__init__(self, reader) self.hcard = None hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != 0: raise CardConnectionException( 'Failed to establish context : ' + \ SCardGetErrorMessage(hresult)) def __del__(self): """Destructor. Clean PCSC connection resources.""" # race condition: module CardConnection # can disappear before __del__ is called self.disconnect() hresult = SCardReleaseContext(self.hcontext) if hresult != 0: raise CardConnectionException( 'Failed to release context: ' + \ SCardGetErrorMessage(hresult)) CardConnection.__del__(self) def connect(self, protocol=None, mode=None, disposition=None): """Connect to the card. If protocol is not specified, connect with the default connection protocol. If mode is not specified, connect with SCARD_SHARE_SHARED.""" CardConnection.connect(self, protocol) pcscprotocol = translateprotocolmask(protocol) if 0 == pcscprotocol: pcscprotocol = self.getProtocol() if mode == None: mode = SCARD_SHARE_SHARED # store the way to dispose the card if disposition == None: disposition = SCARD_UNPOWER_CARD self.disposition = disposition hresult, self.hcard, dwActiveProtocol = SCardConnect( self.hcontext, str(self.reader), mode, pcscprotocol) if hresult != 0: self.hcard = None if SCARD_W_REMOVED_CARD == hresult: raise NoCardException( 'Unable to connect: ' + \ SCardGetErrorMessage(hresult)) else: raise CardConnectionException( 'Unable to connect with protocol: ' + \ dictProtocol[pcscprotocol] + '. ' + \ SCardGetErrorMessage(hresult)) protocol = 0 for p in dictProtocol: if p == dwActiveProtocol: protocol = eval("CardConnection.%s_protocol" % dictProtocol[p]) PCSCCardConnection.setProtocol(self, protocol) def disconnect(self): """Disconnect from the card.""" # when __del__() is invoked in response to a module being deleted, # e.g., when execution of the program is done, other globals referenced # by the __del__() method may already have been deleted. # this causes CardConnection.disconnect to except with a TypeError try: CardConnection.disconnect(self) except TypeError: pass if None != self.hcard: hresult = SCardDisconnect(self.hcard, self.disposition) if hresult != 0: raise CardConnectionException( 'Failed to disconnect: ' + \ SCardGetErrorMessage(hresult)) self.hcard = None def getATR(self): """Return card ATR""" CardConnection.getATR(self) if None == self.hcard: raise CardConnectionException('Card not connected') hresult, reader, state, protocol, atr = SCardStatus(self.hcard) if hresult != 0: raise CardConnectionException( 'Failed to get status: ' + \ SCardGetErrorMessage(hresult)) return atr def doTransmit(self, bytes, protocol=None): """Transmit an apdu to the card and return response apdu. bytes: command apdu to transmit (list of bytes) protocol: the transmission protocol, from CardConnection.T0_protocol, CardConnection.T1_protocol, or CardConnection.RAW_protocol return: a tuple (response, sw1, sw2) where sw1 is status word 1, e.g. 0x90 sw2 is status word 2, e.g. 0x1A response are the response bytes excluding status words """ if None == protocol: protocol = self.getProtocol() CardConnection.doTransmit(self, bytes, protocol) pcscprotocolheader = translateprotocolheader(protocol) if 0 == pcscprotocolheader: raise CardConnectionException( 'Invalid protocol in transmit: must be' + \ 'CardConnection.T0_protocol, ' + \ 'CardConnection.T1_protocol, or ' + \ 'CardConnection.RAW_protocol') if None == self.hcard: raise CardConnectionException('Card not connected') hresult, response = SCardTransmit( self.hcard, pcscprotocolheader, bytes) if hresult != 0: raise CardConnectionException( 'Failed to transmit with protocol ' + \ dictProtocolHeader[pcscprotocolheader] + '. ' + \ SCardGetErrorMessage(hresult)) sw1 = (response[-2] + 256) % 256 sw2 = (response[-1] + 256) % 256 data = map(lambda x: (x + 256) % 256, response[:-2]) return data, sw1, sw2 def doControl(self, controlCode, bytes=[]): """Transmit a control command to the reader and return response. controlCode: control command bytes: command data to transmit (list of bytes) return: response are the response bytes (if any) """ CardConnection.doControl(self, controlCode, bytes) hresult, response = SCardControl(self.hcard, controlCode, bytes) if hresult != 0: raise SmartcardException( 'Failed to control ' + SCardGetErrorMessage(hresult)) data = map(lambda x: (x + 256) % 256, response) return data def doGetAttrib(self, attribId): """get an attribute attribId: Identifier for the attribute to get return: response are the attribute byte array """ CardConnection.doGetAttrib(self, attribId) hresult, response = SCardGetAttrib(self.hcard, attribId) if hresult != 0: raise SmartcardException( 'Failed to getAttrib ' + SCardGetErrorMessage(hresult)) return response if __name__ == '__main__': """Small sample illustrating the use of CardConnection.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] from smartcard.pcsc.PCSCReader import readers cc = readers()[0].createConnection() cc.connect() print "%r %x %x" % cc.transmit(SELECT + DF_TELECOM) print cc.control(0, []) pyscard-1.6.14/smartcard/pcsc/__init__.py0000644000175000017500000000000011404463361022017 0ustar rousseaurousseau00000000000000pyscard-1.6.14/smartcard/pcsc/PCSCExceptions.py0000644000175000017500000000765711747776676023135 0ustar rousseaurousseau00000000000000"""Smartcard module exceptions. This module defines the exceptions raised by the smartcard.pcsc modules. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ # gemalto scard library import smartcard.scard class BaseSCardException(Exception): """Base class for scard (aka PCSC) exceptions. scard exceptions are raised by the scard module, i.e. low-level PCSC access to readers and cards. """ def __init__(self, hresult): """Constructor that stores the pcsc error status.""" self.hresult = hresult def __str__(self): """Returns a string representation of the exception.""" return repr("scard exception: " + smartcard.scard.SCardGetErrorMessage(self.hresult)) class AddReaderToGroupException(BaseSCardException): """Raised when scard fails to add a new reader to a PCSC reader group.""" def __init__(self, hresult, readername="", groupname=""): BaseSCardException.__init__(self, hresult) self.readername = readername self.groupname = groupname def __str__(self): return repr('Failure to add reader: ' + self.readername + ' to group: ' + self.groupname + ' ' + smartcard.scard.SCardGetErrorMessage(self.hresult)) class EstablishContextException(BaseSCardException): """Raised when scard failed to establish context with PCSC.""" def __str__(self): """Returns a string representation of the exception.""" return repr('Failure to establish context: ' + smartcard.scard.SCardGetErrorMessage(self.hresult)) class ListReadersException(BaseSCardException): """Raised when scard failed to list readers.""" def __str__(self): return repr('Failure to list readers: ' + smartcard.scard.SCardGetErrorMessage(self.hresult)) class IntroduceReaderException(BaseSCardException): """Raised when scard fails to introduce a new reader to PCSC.""" def __init__(self, hresult, readername=""): BaseSCardException.__init__(self, hresult) self.readername = readername def __str__(self): return repr('Failure to introduce a new reader: ' + self.readername + ' ' + smartcard.scard.SCardGetErrorMessage(self.hresult)) class ReleaseContextException(BaseSCardException): """Raised when scard failed to release PCSC context.""" def __str__(self): return repr('Failure to release context: ' + smartcard.scard.SCardGetErrorMessage(self.hresult)) class RemoveReaderFromGroupException(BaseSCardException): """Raised when scard fails to remove a reader from a PCSC reader group.""" def __init__(self, hresult, readername="", groupname=""): BaseSCardException.__init__(self, hresult) self.readername = readername self.groupname = groupname def __str__(self): return repr('Failure to remove reader: ' + self.readername + ' from group: ' + self.groupname + ' ' + smartcard.scard.SCardGetErrorMessage(self.hresult)) if __name__ == "__main__": try: raise EstablishContextException(smartcard.scard.SCARD_E_NO_MEMORY) except BaseSCardException, exc: print exc pyscard-1.6.14/smartcard/pcsc/PCSCPart10.py0000644000175000017500000002072511747776676022052 0ustar rousseaurousseau00000000000000"""PCSCPart10: PC/SC Part 10 (pinpad) __author__ = "Ludovic Rousseau" Copyright 2009-2010 Ludovic Rosseau Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr 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 """ from smartcard.scard import * # constants defined in PC/SC v2 Part 10 CM_IOCTL_GET_FEATURE_REQUEST = SCARD_CTL_CODE(3400) FEATURE_VERIFY_PIN_START = 0x01 FEATURE_VERIFY_PIN_FINISH = 0x02 FEATURE_MODIFY_PIN_START = 0x03 FEATURE_MODIFY_PIN_FINISH = 0x04 FEATURE_GET_KEY_PRESSED = 0x05 FEATURE_VERIFY_PIN_DIRECT = 0x06 FEATURE_MODIFY_PIN_DIRECT = 0x07 FEATURE_MCT_READER_DIRECT = 0x08 FEATURE_MCT_UNIVERSAL = 0x09 FEATURE_IFD_PIN_PROPERTIES = 0x0A FEATURE_ABORT = 0x0B FEATURE_SET_SPE_MESSAGE = 0x0C FEATURE_VERIFY_PIN_DIRECT_APP_ID = 0x0D FEATURE_MODIFY_PIN_DIRECT_APP_ID = 0x0E FEATURE_WRITE_DISPLAY = 0x0F FEATURE_GET_KEY = 0x10 FEATURE_IFD_DISPLAY_PROPERTIES = 0x11 FEATURE_GET_TLV_PROPERTIES = 0x12 FEATURE_CCID_ESC_COMMAND = 0x13 Features = { "FEATURE_VERIFY_PIN_START": FEATURE_VERIFY_PIN_START, "FEATURE_VERIFY_PIN_FINISH": FEATURE_VERIFY_PIN_FINISH, "FEATURE_MODIFY_PIN_START": FEATURE_MODIFY_PIN_START, "FEATURE_MODIFY_PIN_FINISH": FEATURE_MODIFY_PIN_FINISH, "FEATURE_GET_KEY_PRESSED": FEATURE_GET_KEY_PRESSED, "FEATURE_VERIFY_PIN_DIRECT": FEATURE_VERIFY_PIN_DIRECT, "FEATURE_MODIFY_PIN_DIRECT": FEATURE_MODIFY_PIN_DIRECT, "FEATURE_MCT_READER_DIRECT": FEATURE_MCT_READER_DIRECT, "FEATURE_MCT_UNIVERSAL": FEATURE_MCT_UNIVERSAL, "FEATURE_IFD_PIN_PROPERTIES": FEATURE_IFD_PIN_PROPERTIES, "FEATURE_ABORT": FEATURE_ABORT, "FEATURE_SET_SPE_MESSAGE": FEATURE_SET_SPE_MESSAGE, "FEATURE_VERIFY_PIN_DIRECT_APP_ID": FEATURE_VERIFY_PIN_DIRECT_APP_ID, "FEATURE_MODIFY_PIN_DIRECT_APP_ID": FEATURE_MODIFY_PIN_DIRECT_APP_ID, "FEATURE_WRITE_DISPLAY": FEATURE_WRITE_DISPLAY, "FEATURE_GET_KEY": FEATURE_GET_KEY, "FEATURE_IFD_DISPLAY_PROPERTIES": FEATURE_IFD_DISPLAY_PROPERTIES, "FEATURE_GET_TLV_PROPERTIES": FEATURE_GET_TLV_PROPERTIES, "FEATURE_CCID_ESC_COMMAND": FEATURE_CCID_ESC_COMMAND} # properties returned by FEATURE_GET_TLV_PROPERTIES PCSCv2_PART10_PROPERTY_wLcdLayout = 1 PCSCv2_PART10_PROPERTY_bEntryValidationCondition = 2 PCSCv2_PART10_PROPERTY_bTimeOut2 = 3 PCSCv2_PART10_PROPERTY_wLcdMaxCharacters = 4 PCSCv2_PART10_PROPERTY_wLcdMaxLines = 5 PCSCv2_PART10_PROPERTY_bMinPINSize = 6 PCSCv2_PART10_PROPERTY_bMaxPINSize = 7 PCSCv2_PART10_PROPERTY_sFirmwareID = 8 PCSCv2_PART10_PROPERTY_bPPDUSupport = 9 PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize = 10 PCSCv2_PART10_PROPERTY_wIdVendor = 11 PCSCv2_PART10_PROPERTY_wIdProduct = 12 Properties = { "PCSCv2_PART10_PROPERTY_wLcdLayout": PCSCv2_PART10_PROPERTY_wLcdLayout, "PCSCv2_PART10_PROPERTY_bEntryValidationCondition": \ PCSCv2_PART10_PROPERTY_bEntryValidationCondition, "PCSCv2_PART10_PROPERTY_bTimeOut2": PCSCv2_PART10_PROPERTY_bTimeOut2, "PCSCv2_PART10_PROPERTY_wLcdMaxCharacters": \ PCSCv2_PART10_PROPERTY_wLcdMaxCharacters, "PCSCv2_PART10_PROPERTY_wLcdMaxLines": PCSCv2_PART10_PROPERTY_wLcdMaxLines, "PCSCv2_PART10_PROPERTY_bMinPINSize": PCSCv2_PART10_PROPERTY_bMinPINSize, "PCSCv2_PART10_PROPERTY_bMaxPINSize": PCSCv2_PART10_PROPERTY_bMaxPINSize, "PCSCv2_PART10_PROPERTY_sFirmwareID": PCSCv2_PART10_PROPERTY_sFirmwareID, "PCSCv2_PART10_PROPERTY_bPPDUSupport": PCSCv2_PART10_PROPERTY_bPPDUSupport, "PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize": PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize, "PCSCv2_PART10_PROPERTY_wIdVendor": PCSCv2_PART10_PROPERTY_wIdVendor, "PCSCv2_PART10_PROPERTY_wIdProduct": PCSCv2_PART10_PROPERTY_wIdProduct} # we already have: Features['FEATURE_x'] = FEATURE_x # we will now also have: Features[FEATURE_x] = 'FEATURE_x' for k in Features.keys(): Features[Features[k]] = k for k in Properties.keys(): Properties[Properties[k]] = k def getFeatureRequest(cardConnection): """ Get the list of Part10 features supported by the reader. @param cardConnection: L{CardConnection} object @rtype: list @return: a list of list [[tag1, value1], [tag2, value2]] """ response = cardConnection.control(CM_IOCTL_GET_FEATURE_REQUEST, []) features = [] while (len(response) > 0): tag = response[0] control = (((((response[2] << 8) + \ response[3]) << 8) + \ response[4]) << 8) + \ response[5] try: features.append([Features[tag], control]) except KeyError: pass del response[:6] return features def hasFeature(featureList, feature): """ return the controlCode for a feature or None @param feature: feature to look for @param featureList: feature list as returned by L{getFeatureRequest()} @return: feature value or None """ for f in featureList: if f[0] == feature or Features[f[0]] == feature: return f[1] def getPinProperties(cardConnection, featureList=None, controlCode=None): """ return the PIN_PROPERTIES structure @param cardConnection: L{CardConnection} object @param featureList: feature list as returned by L{getFeatureRequest()} @param controlCode: control code for L{FEATURE_IFD_PIN_PROPERTIES} @rtype: dict @return: a dict """ if controlCode is None: if featureList is None: featureList = getFeatureRequest(cardConnection) controlCode = hasFeature(featureList, FEATURE_IFD_PIN_PROPERTIES) if controlCode is None: return {'raw': []} response = cardConnection.control(controlCode, []) d = { 'raw': response, 'LcdLayoutX': response[0], 'LcdLayoutY': response[1], 'EntryValidationCondition': response[2], 'TimeOut2': response[3]} return d def getTlvProperties(cardConnection, featureList=None, controlCode=None): """ return the GET_TLV_PROPERTIES structure @param cardConnection: L{CardConnection} object @param featureList: feature list as returned by L{getFeatureRequest()} @param controlCode: control code for L{FEATURE_GET_TLV_PROPERTIES} @rtype: dict @return: a dict """ if controlCode is None: if featureList is None: featureList = getFeatureRequest(cardConnection) controlCode = hasFeature(featureList, FEATURE_GET_TLV_PROPERTIES) if controlCode is None: return {'raw': []} response = cardConnection.control(controlCode, []) d = { 'raw': response, } # create a new list to consume it tmp = list(response) while tmp: tag = tmp[0] len = tmp[1] data = tmp[2:2 + len] if PCSCv2_PART10_PROPERTY_sFirmwareID == tag: # convert to a string data = "".join([chr(c) for c in data]) # we now suppose the value is an integer elif 1 == len: # byte data = data[0] elif 2 == len: # 16 bits value data = data[1] * 256 + data[0] elif 4 == len: # 32 bits value data = ((data[3] * 256 + data[2]) * 256 + data[1]) * 256 + data[0] # store the value in the dictionnary try: d[Properties[tag]] = data except KeyError: d["UNKNOWN"] = data del tmp[0:2 + len] return d if __name__ == '__main__': """Small sample illustrating the use of PCSCPart10.""" from smartcard.pcsc.PCSCReader import readers cc = readers()[0].createConnection() cc.connect(mode=SCARD_SHARE_DIRECT) #print cc.control( CM_IOCTL_GET_FEATURE_REQUEST ) features = getFeatureRequest(cc) print features print hasFeature(features, FEATURE_VERIFY_PIN_START) print hasFeature(features, FEATURE_VERIFY_PIN_DIRECT) properties = getPinProperties(cc) print "\nPinProperties:" for k in properties.keys(): print " %s: %s" % (k, properties[k]) print "\nTlvProperties:" properties = getTlvProperties(cc) for k in properties.keys(): print " %s: %s" % (k, properties[k]) pyscard-1.6.14/smartcard/pcsc/PCSCReader.py0000644000175000017500000001071111747776676022177 0ustar rousseaurousseau00000000000000"""PCSCReader: concrete reader class for PCSC Readers __author__ = "gemalto http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from smartcard.CardConnectionDecorator import CardConnectionDecorator from smartcard.reader.Reader import Reader from smartcard.pcsc.PCSCContext import PCSCContext from smartcard.pcsc.PCSCCardConnection import PCSCCardConnection from smartcard.Exceptions import * from smartcard.pcsc.PCSCExceptions import * from smartcard.scard import * def __PCSCreaders__(hcontext, groups=[]): """Returns the list of PCSC smartcard readers in PCSC group. If group is not specified, returns the list of all PCSC smartcard readers. """ # in case we have a string instead of a list if isinstance(groups, type("")): groups = [groups] hresult, readers = SCardListReaders(hcontext, groups) if hresult != 0: if hresult == SCARD_E_NO_READERS_AVAILABLE: readers = [] else: raise ListReadersException(hresult) return readers class PCSCReader(Reader): """PCSC reader class.""" def __init__(self, readername): """Constructs a new PCSC reader.""" Reader.__init__(self, readername) def addtoreadergroup(self, groupname): """Add reader to a reader group.""" hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if 0 != hresult: raise EstablishContextException(hresult) try: hresult = SCardIntroduceReader(hcontext, self.name, self.name) if 0 != hresult and SCARD_E_DUPLICATE_READER != hresult: raise IntroduceReaderException(hresult, self.name) hresult = SCardAddReaderToGroup(hcontext, self.name, groupname) if 0 != hresult: raise AddReaderToGroupException(hresult, self.name, groupname) finally: hresult = SCardReleaseContext(hcontext) if 0 != hresult: raise ReleaseContextException(hresult) def removefromreadergroup(self, groupname): """Remove a reader from a reader group""" hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if 0 != hresult: raise EstablishContextException(hresult) try: hresult = SCardRemoveReaderFromGroup(hcontext, self.name, groupname) if 0 != hresult: raise RemoveReaderFromGroupException(hresult, self.name, groupname) finally: hresult = SCardReleaseContext(hcontext) if 0 != hresult: raise ReleaseContextException(hresult) def createConnection(self): """Return a card connection thru PCSC reader.""" return CardConnectionDecorator(PCSCCardConnection(self.name)) class Factory: def create(readername): return PCSCReader(readername) create = staticmethod(create) def readers(groups=[]): creaders = [] hcontext = PCSCContext().getContext() for reader in __PCSCreaders__(hcontext, groups): creaders.append(PCSCReader.Factory.create(reader)) return creaders readers = staticmethod(readers) if __name__ == '__main__': from smartcard.util import * SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] creaders = PCSCReader.readers() for reader in creaders: try: print reader.name 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' pyscard-1.6.14/smartcard/pcsc/PCSCCardRequest.py0000644000175000017500000003236211747776676023225 0ustar rousseaurousseau00000000000000"""PCSC Smartcard request. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 threading import time from smartcard.AbstractCardRequest import AbstractCardRequest from smartcard.Exceptions import CardRequestTimeoutException from smartcard.Exceptions import CardRequestException, ListReadersException from smartcard.pcsc.PCSCReader import PCSCReader from smartcard.pcsc.PCSCContext import PCSCContext from smartcard import Card from smartcard.scard import * def signalEvent(evt, isInfinite): if not isInfinite: evt.set() class PCSCCardRequest(AbstractCardRequest): """PCSC CardRequest class.""" def __init__(self, newcardonly=False, readers=None, cardType=None, cardServiceClass=None, timeout=1): """Construct new PCSCCardRequest. @param newcardonly: if True, request a new card default is False, i.e. accepts cards already inserted @param readers: the list of readers to consider for requesting a card default is to consider all readers @param cardTypeClass: the CardType class to wait for; default is AnyCardType, i.e. the request will returns with new or already inserted cards @param cardServiceClass: the specific card service class to create and bind to the card default is to create and bind a PassThruCardService @param timeout: the time in seconds we are ready to wait for connecting to the requested card. default is to wait one second to wait forever, set timeout to None """ AbstractCardRequest.__init__( self, newcardonly, readers, cardType, cardServiceClass, timeout) # polling interval in s for SCardGetStatusChange self.pollinginterval = 0.1 # if timeout is None, translate to scard.INFINITE if None == self.timeout: self.timeout = INFINITE # otherwise, from seconds to milliseconds else: self.timeout = int(self.timeout) self.hcontext = PCSCContext().getContext() def getReaderNames(self): """Returns the list or PCSC readers on which to wait for cards.""" # get inserted readers hresult, pcscreaders = SCardListReaders(self.hcontext, []) if 0 != hresult and SCARD_E_NO_READERS_AVAILABLE != hresult: raise ListReadersException(hresult) readers = [] # if no readers asked, use all inserted readers if None == self.readersAsked: readers = pcscreaders # otherwise use only the asked readers that are inserted else: for reader in self.readersAsked: if not isinstance(reader, type("")): reader = str(reader) if reader in pcscreaders: readers = readers + [reader] return readers def waitforcard(self): """Wait for card insertion and returns a card service.""" AbstractCardRequest.waitforcard(self) cardfound = False # for non infinite timeout, a timer will signal # the end of the time-out by setting the evt event evt = threading.Event() if INFINITE == self.timeout: timertimeout = 1 else: timertimeout = self.timeout timer = threading.Timer( timertimeout, signalEvent, [evt, INFINITE == self.timeout]) # create a dictionary entry for new readers readerstates = {} readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in readerstates.keys(): if oldreader not in readernames: del readerstates[oldreader] # call SCardGetStatusChange only if we have some readers if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, readerstates.values()) else: hresult = 0 newstates = [] # we can expect normally time-outs or reader # disappearing just before the call # otherwise, raise execption on error if 0 != hresult and \ SCARD_E_TIMEOUT != hresult and \ SCARD_E_UNKNOWN_READER != hresult: raise CardRequestException( 'Failed to SCardGetStatusChange ' + \ SCardGetErrorMessage(hresult)) # in case of timeout or reader disappearing, # the content of the states is useless # in which case we clear the changed bit if SCARD_E_TIMEOUT == hresult or SCARD_E_UNKNOWN_READER == hresult: for state in newstates: state[1] = state[1] & (0xFFFFFFFF ^ SCARD_STATE_CHANGED) # update readerstate for state in newstates: readername, eventstate, atr = state readerstates[readername] = (readername, eventstate) # if a new card is not requested, just return the first available if not self.newcardonly: for state in newstates: readername, eventstate, atr = state if eventstate & SCARD_STATE_PRESENT: reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True return self.cardServiceClass( reader.createConnection()) timerstarted = False while not evt.isSet() and not cardfound: if not timerstarted: timerstarted = True timer.start() time.sleep(self.pollinginterval) # create a dictionary entry for new readers readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in readerstates.keys(): if oldreader not in readernames: del readerstates[oldreader] # wait for card insertion if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, readerstates.values()) else: hresult = SCARD_E_TIMEOUT newstates = [] # time-out if SCARD_E_TIMEOUT == hresult: if evt.isSet(): raise CardRequestTimeoutException() # reader vanished before or during the call elif SCARD_E_UNKNOWN_READER == hresult: pass # some error happened elif 0 != hresult: timer.cancel() raise CardRequestException( 'Failed to get status change ' + \ SCardGetErrorMessage(hresult)) # something changed! else: # check if we have to return a match, i.e. # if no new card in inserted and there is a card found # or if a new card is requested, and there is a change+present for state in newstates: readername, eventstate, atr = state r, oldstate = readerstates[readername] # the status can change on a card already inserted, e.g. # unpowered, in use, ... # if a new card is requested, clear the state changed bit # if the card was already inserted and is still inserted if self.newcardonly: if oldstate & SCARD_STATE_PRESENT and \ eventstate & \ (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT): eventstate = eventstate & \ (0xFFFFFFFF ^ SCARD_STATE_CHANGED) if (self.newcardonly and \ eventstate & SCARD_STATE_PRESENT and \ eventstate & SCARD_STATE_CHANGED) or \ (not self.newcardonly and \ eventstate & SCARD_STATE_PRESENT): reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True timer.cancel() return self.cardServiceClass( reader.createConnection()) # update state dictionary readerstates[readername] = (readername, eventstate) if evt.isSet(): raise CardRequestTimeoutException() def waitforcardevent(self): """Wait for card insertion or removal.""" AbstractCardRequest.waitforcardevent(self) presentcards = [] evt = threading.Event() # for non infinite timeout, a timer will signal the end of the time-out if INFINITE == self.timeout: timertimeout = 1 else: timertimeout = self.timeout timer = threading.Timer( timertimeout, signalEvent, [evt, INFINITE == self.timeout]) # get status change until time-out, e.g. evt is set readerstates = {} timerstarted = False while not evt.isSet(): if not timerstarted: timerstarted = True timer.start() time.sleep(self.pollinginterval) # reinitialize at each iteration just in case a new reader appeared readernames = self.getReaderNames() for reader in readernames: # create a dictionary entry for new readers if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in readerstates.keys(): if oldreader not in readernames: del readerstates[oldreader] # get status change if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, readerstates.values()) else: hresult = 0 newstates = [] # time-out if SCARD_E_TIMEOUT == hresult: if evt.isSet(): raise CardRequestTimeoutException() # the reader was unplugged during the loop elif SCARD_E_UNKNOWN_READER == hresult: pass # some error happened elif 0 != hresult: timer.cancel() raise CardRequestException( 'Failed to get status change ' + \ SCardGetErrorMessage(hresult)) # something changed! else: timer.cancel() for state in newstates: readername, eventstate, atr = state r, oldstate = readerstates[readername] # the status can change on a card already inserted, e.g. # unpowered, in use, ... Clear the state changed bit if # the card was already inserted and is still inserted if oldstate & SCARD_STATE_PRESENT and \ eventstate & \ (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT): eventstate = eventstate & \ (0xFFFFFFFF ^ SCARD_STATE_CHANGED) if eventstate & SCARD_STATE_PRESENT and \ eventstate & SCARD_STATE_CHANGED: presentcards.append(Card.Card(readername, atr)) return presentcards if evt.isSet(): raise CardRequestTimeoutException() if __name__ == '__main__': """Small sample illustrating the use of PCSCCardRequest.py.""" from smartcard.util import toHexString print 'Insert a new card within 10 seconds' cr = PCSCCardRequest(timeout=10, newcardonly=True) cs = cr.waitforcard() cs.connection.connect() print cs.connection.getReader(), toHexString(cs.connection.getATR()) cs.connection.disconnect() pyscard-1.6.14/smartcard/CardMonitoring.py0000644000175000017500000002052011747776700022276 0ustar rousseaurousseau00000000000000"""Smart card insertion/removal monitoring classes. CardObserver is a base class for objects that are to be notified upon smart card insertion/removal. CardMonitor is a singleton object notifying registered CardObservers upon reader insertion/removal. __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from sys import exc_info from threading import Thread, Event from time import sleep from smartcard.System import readers from smartcard.Exceptions import CardRequestTimeoutException from smartcard.Observer import Observer from smartcard.Observer import Observable from smartcard.CardType import AnyCardType from smartcard.CardRequest import CardRequest _START_ON_DEMAND_ = False # CardObserver interface class CardObserver(Observer): """ CardObserver is a base abstract class for objects that are to be notified upon smartcard reader insertion/removal. """ def __init__(self): pass def update(self, observable, (addedcards, removedcards)): """Called upon reader insertion/removal. observable: addedcards: list of added readers causing notification removedcards: list of removed readers causing notification """ pass class CardMonitor(object): """Class that monitors smart card insertion/removal. and notify observers note: a card monitoring thread will be running as long as the card monitor has observers, or CardMonitor.stop() is called. Do not forget to delete all your observers by calling deleteObserver, or your program will run forever... Uses the singleton pattern from Thinking in Python Bruce Eckel, http://mindview.net/Books/TIPython to make sure there is only one CardMonitor. """ class __CardMonitorSingleton(Observable): """The real smartcard monitor class. A single instance of this class is created by the public CardMonitor class. """ def __init__(self): Observable.__init__(self) if _START_ON_DEMAND_: self.rmthread = None else: self.rmthread = CardMonitoringThread(self) def addObserver(self, observer): """Add an observer. We only start the card monitoring thread when there are observers. """ Observable.addObserver(self, observer) if _START_ON_DEMAND_: if self.countObservers() > 0 and self.rmthread == None: self.rmthread = CardMonitoringThread(self) else: observer.update(self, (self.rmthread.cards, [])) def deleteObserver(self, observer): """Remove an observer. We delete the CardMonitoringThread reference when there are no more observers. """ Observable.deleteObserver(self, observer) if _START_ON_DEMAND_: if self.countObservers() == 0: if self.rmthread != None: self.rmthread = None def __str__(self): return 'CardMonitor' # the singleton instance = None def __init__(self): if not CardMonitor.instance: CardMonitor.instance = CardMonitor.__CardMonitorSingleton() def __getattr__(self, name): return getattr(self.instance, name) class CardMonitoringThread(object): """Card insertion thread. This thread waits for card insertion. """ class __CardMonitoringThreadSingleton(Thread): """The real card monitoring thread class. A single instance of this class is created by the public CardMonitoringThread class. """ def __init__(self, observable): Thread.__init__(self) self.observable = observable self.stopEvent = Event() self.stopEvent.clear() self.cards = [] self.setDaemon(True) # the actual monitoring thread def run(self): """Runs until stopEvent is notified, and notify observers of all card insertion/removal. """ self.cardrequest = CardRequest(timeout=0.1) while self.stopEvent.isSet() != 1: try: currentcards = self.cardrequest.waitforcardevent() addedcards = [] for card in currentcards: if not self.cards.__contains__(card): addedcards.append(card) removedcards = [] for card in self.cards: if not currentcards.__contains__(card): removedcards.append(card) if addedcards != [] or removedcards != []: self.cards = currentcards self.observable.setChanged() self.observable.notifyObservers( (addedcards, removedcards)) # when CardMonitoringThread.__del__() is invoked in # response to shutdown, e.g., when execution of the # program is done, other globals referenced by the # __del__() method may already have been deleted. # this causes ReaderMonitoringThread.run() to except # with a TypeError or AttributeError except TypeError: pass except AttributeError: pass except: try: import sys print sys.exc_info()[1] print sys.exc_info()[2] print sys.exc_info()[0] except: pass # stop the thread by signaling stopEvent def stop(self): self.stopEvent.set() # the singleton instance = None def __init__(self, observable): if not CardMonitoringThread.instance: CardMonitoringThread.instance = \ CardMonitoringThread.__CardMonitoringThreadSingleton(observable) CardMonitoringThread.instance.start() def __getattr__(self, name): if self.instance: return getattr(self.instance, name) # commented to avoid bad clean-up sequence of python where __del__ # is called when some objects it uses are already gargabe collected #def __del__(self): # if CardMonitoringThread.instance!=None: # CardMonitoringThread.instance.stop() # CardMonitoringThread.instance = None if __name__ == "__main__": from smartcard.CardMonitoring import CardMonitor print 'insert or remove cards in the next 10 seconds' # a simple card observer that prints added/removed cards class printobserver(CardObserver): def __init__(self, obsindex): self.obsindex = obsindex def update(self, observable, (addedcards, removedcards)): print "%d - added: " % self.obsindex, addedcards print "%d - removed: " % self.obsindex, removedcards class testthread(Thread): def __init__(self, obsindex): Thread.__init__(self) self.readermonitor = CardMonitor() self.obsindex = obsindex self.observer = None def run(self): # create and register observer self.observer = printobserver(self.obsindex) self.readermonitor.addObserver(self.observer) sleep(10) self.readermonitor.deleteObserver(self.observer) t1 = testthread(1) t2 = testthread(2) t1.start() t2.start() pyscard-1.6.14/LICENSE0000644000175000017500000006037310633575651016037 0ustar rousseaurousseau00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. pyscard-1.6.14/setup.py0000755000175000017500000002462211747776700016551 0ustar rousseaurousseau00000000000000#! /usr/bin/env python """Setup file for distutils __author__ = "http://www.gemalto.com" Copyright 2001-2012 gemalto Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 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 """ from distutils import core, dir_util, file_util from distutils.core import Extension from distutils.util import get_platform from distutils.command.build_ext import build_ext import glob import os import sys if sys.version[0:1] == '1': raise RuntimeError("pyscard requires Python 2.x to build.") if 'win32' == get_platform(): platform__cc_defines = [('WIN32', '100')] platform_swig_opts = ['-DWIN32'] platform_sources = ['smartcard/scard/scard.rc'] platform_libraries = ['winscard'] platform_include_dirs = [] platform_extra_compile_args = [] platform_extra_link_args = [] elif 'win-amd64' == get_platform(): platform__cc_defines = [('WIN32', '100')] platform_swig_opts = ['-DWIN32'] platform_sources = ['smartcard/scard/scard.rc'] platform_libraries = ['winscard'] platform_include_dirs = [] platform_extra_compile_args = [] platform_extra_link_args = [] # # Mac OS X Tiger has python 2.3 preinstalled # get_platform() returns a string similar to 'darwin-8.11.1-i386' with # python 2.3 # if python 2.5 is installed, get_platform() returns a string similar to # 'macosx-10.3-fat' elif 'darwin' in get_platform() \ or 'macosx-10.3' in get_platform() \ or 'macosx-10.4' in get_platform(): platform__cc_defines = [('PCSCLITE', '1'), ('__APPLE__', '1'), ('__TIGER__', '1')] platform_swig_opts = ['-DPCSCLITE', '-D__APPLE__', '-D__TIGER__'] platform_sources = [] platform_libraries = [] platform_include_dirs = [] platform_extra_compile_args = ['-v', '-framework', 'PCSC', '-arch', 'i386', '-arch', 'ppc', '-ggdb', '-O0'] platform_extra_link_args = ['-arch', 'i386', '-arch', 'ppc', '-ggdb'] # # Mac OS X Lion, python 2.7 # PowerPC is no more supported, x86_64 is new # # x86_64 and i386 # elif 'macosx-10.7' in get_platform(): platform__cc_defines = [('PCSCLITE', '1'), ('__APPLE__', '1'), ('__LION__', '1')] platform_swig_opts = ['-DPCSCLITE', '-D__APPLE__', '-D__LION__'] platform_sources = [] platform_libraries = [] platform_include_dirs = [] platform_extra_compile_args = ['-v', '-arch', 'i386', '-arch', 'x86_64', '-ggdb'] platform_extra_link_args = ['-arch', 'i386', '-arch', 'x86_64', '-ggdb'] # # Mac OS X Snow Leopard, python 2.6 # PowerPC is no more supported, x86_64 is new # elif 'macosx-10.6' in get_platform(): platform__cc_defines = [('PCSCLITE', '1'), ('__APPLE__', '1'), ('__LEOPARD__', '1')] platform_swig_opts = ['-DPCSCLITE', '-D__APPLE__', '-D__LEOPARD__'] platform_sources = [] platform_libraries = [] platform_include_dirs = [] platform_extra_compile_args = ['-v', '-arch', 'i386', '-arch', 'x86_64', '-ggdb'] platform_extra_link_args = ['-arch', 'i386', '-arch', 'x86_64', '-ggdb'] # # Mac OS X Leopard has python 2.5 preinstalled # get_platform() returns a string similar to 'macosx-10.5-i386' # elif 'macosx-10.' in get_platform(): platform__cc_defines = [('PCSCLITE', '1'), ('__APPLE__', '1'), ('__LEOPARD__', '1')] platform_swig_opts = ['-DPCSCLITE', '-D__APPLE__', '-D__LEOPARD__'] platform_sources = [] platform_libraries = [] platform_include_dirs = [] platform_extra_compile_args = ['-v', '-framework', 'PCSC', '-arch', 'i386', '-arch', 'ppc', '-ggdb', '-O0'] platform_extra_link_args = ['-arch', 'i386', '-arch', 'ppc', '-ggdb'] else: platform__cc_defines = [('PCSCLITE', '1')] platform_swig_opts = ['-DPCSCLITE'] platform_sources = [] platform_libraries = ["python%d.%d" % sys.version_info[:2]] platform_include_dirs = ['/usr/include/PCSC'] platform_extra_compile_args = [] # ['-ggdb', '-O0'] platform_extra_link_args = [] # ['-ggdb'] class _pyscardBuildExt(build_ext): '''Specialization of build_ext to enable swig_opts for python 2.3 distutils''' if sys.version_info < (2, 4): # This copy of swig_sources is from Python 2.3. # This is to add support of swig_opts for Python 2.3 distutils # (in particular for MacOS X darwin that comes with Python 2.3) def swig_sources(self, sources): """Walk the list of source files in 'sources', looking for SWIG interface (.i) files. Run SWIG on all that are found, and return a modified 'sources' list with SWIG source files replaced by the generated C (or C++) files. """ new_sources = [] swig_sources = [] swig_targets = {} # XXX this drops generated C/C++ files into the source tree, which # is fine for developers who want to distribute the generated # source -- but there should be an option to put SWIG output in # the temp dir. if self.swig_cpp: target_ext = '.cpp' else: target_ext = '.c' for source in sources: (base, ext) = os.path.splitext(source) if ext == ".i": # SWIG interface file new_sources.append(base + target_ext) swig_sources.append(source) swig_targets[source] = new_sources[-1] else: new_sources.append(source) if not swig_sources: return new_sources swig = self.find_swig() swig_cmd = [swig, "-python"] if self.swig_cpp: swig_cmd.append("-c++") swig_cmd += platform_swig_opts for source in swig_sources: target = swig_targets[source] self.announce("swigging %s to %s" % (source, target)) self.spawn(swig_cmd + ["-o", target, source]) return new_sources build_ext.swig_sources = swig_sources kw = {'name': "pyscard", 'version': "1.6.14", 'description': "Smartcard module for Python.", 'author': "Jean-Daniel Aussel", 'author_email': "aussel.jean-daniel@gemalto.com", 'url': "http://www.gemalto.com", 'long_description': 'Smartcard package for Python', 'license': 'GNU LESSER GENERAL PUBLIC LICENSE', 'platforms': ['linux', 'win32'], 'packages': ["smartcard", "smartcard/pcsc", "smartcard/reader", "smartcard/scard", "smartcard/sw", "smartcard/util", "smartcard/wx", ], 'package_dir': {"": "."}, 'package_data': { "smartcard": [ "ACKS", "ChangeLog", "LICENSE", "README", "TODO", ], "smartcard/wx": ["resources/*.ico"], }, # the _scard.pyd extension to build 'ext_modules': [Extension("smartcard.scard._scard", define_macros=platform__cc_defines, include_dirs=['smartcard/scard/'] \ + platform_include_dirs, sources=["smartcard/scard/helpers.c", "smartcard/scard/winscarddll.c", "smartcard/scard/scard.i"] \ + platform_sources, libraries=platform_libraries, extra_compile_args=platform_extra_compile_args, extra_link_args=platform_extra_link_args, swig_opts=['-outdir', 'smartcard/scard'] \ + platform_swig_opts)], 'cmdclass': {'build_ext': _pyscardBuildExt}, } # If we're running >Python 2.3, add extra information if hasattr(core, 'setup_keywords'): if 'classifiers' in core.setup_keywords: kw['classifiers'] = [ 'Development Status :: 1.6.14 - Release', 'License :: GNU LESSER GENERAL PUBLIC LICENSE', 'Intended Audience :: Developers', 'Operating System :: Unix', 'Operating System :: Microsoft :: Windows', 'Topic :: Security :: Smartcards', ] if 'download_url' in core.setup_keywords: kw['download_url'] = ('http://sourceforge.net/projects/pyscard/' '%s-%s.zip' % (kw['name'], kw['version'])) pyscard_dist = core.setup(**kw) # Python 2.3 distutils does not support package_data # copy manually package_data if sys.version_info < (2, 4): from distutils.util import convert_path from glob import glob if "install" in sys.argv: targetdir = pyscard_dist.command_obj['install'].install_purelib package_data = kw['package_data'] files = [] for directory in package_data: for pattern in package_data[directory]: filelist = glob(os.path.join(directory, convert_path(pattern))) files.extend([fn for fn in filelist if fn not in files]) for file in files: newdir = os.path.dirname(file) dir_util.mkpath(os.path.join(targetdir, newdir)) file_util.copy_file(file, os.path.join(targetdir, file)) pyscard-1.6.14/PKG-INFO0000644000175000017500000000124011747777125016122 0ustar rousseaurousseau00000000000000Metadata-Version: 1.1 Name: pyscard Version: 1.6.14 Summary: Smartcard module for Python. Home-page: http://www.gemalto.com Author: Jean-Daniel Aussel Author-email: aussel.jean-daniel@gemalto.com License: GNU LESSER GENERAL PUBLIC LICENSE Download-URL: http://sourceforge.net/projects/pyscard/pyscard-1.6.14.zip Description: Smartcard package for Python Platform: linux Platform: win32 Classifier: Development Status :: 1.6.14 - Release Classifier: License :: GNU LESSER GENERAL PUBLIC LICENSE Classifier: Intended Audience :: Developers Classifier: Operating System :: Unix Classifier: Operating System :: Microsoft :: Windows Classifier: Topic :: Security :: Smartcards