Esempio n. 1
0
def open_pyscard(name=None):
    """ Open PC/SC reader using PyScard
        If no reader name is given, try to open all available readers, 
        the first one that succeeds is chosen.

    Args:
        name (:obj:`str`): name of the reader as registered in the system
    
    Returns:
        :obj:`PyScardReader`: PyScard wrapper object
    
    Raises:
        RuntimeError exception if no reader can be opened
        Various PyScard exceptions
    """
    if name is not None:
        return PySCardReader(PCSCReader(name).createConnection())
    else:
        readers = smartcard.System.readers()
        for reader in readers:
            try:
                pyscardreader = PySCardReader(
                    PCSCReader(reader).createConnection())
            except:
                pass
            else:
                logger.debug("Open reader: %s", reader)
                return pyscardreader

        raise RuntimeError('No reader with card found. Available readers: ',
                           readers)
Esempio n. 2
0
 def testcase_addreadertogroup(self):
     """Test for adding readers to group"""
     groups = PCSCReaderGroups()
     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))
Esempio n. 3
0
def create_connection(reader: PCSCReader) -> CardConnectionDecorator:
    try:
        connection = reader.createConnection()
        connection.connect()
        return connection
    except NoCardException:
        return None
    except CardConnectionException:
        return False
 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.assertEqual(PCSCReader.readers('SCard$DefaultReaders'),
                      PCSCReader.readers(newgroup))
     for r in PCSCReader.readers('SCard$DefaultReaders'):
         r.removefromreadergroup(newgroup)
     self.assertEqual([], PCSCReader.readers(newgroup))
     groups.pop(0)
     self.assertEqual([], PCSCReader.readers(newgroup))
Esempio n. 5
0
 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))
Esempio n. 6
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 PCSCReader
    cc = PCSCReader.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, v in list(properties.items()):
        print(" %s: %s" % (k, v))

    print("\nTlvProperties:")
Esempio n. 7
0
    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()
        data = [(x + 256) % 256 for x in response]
        return list(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 PCSCReader
    from smartcard.pcsc.PCSCPart10 import CM_IOCTL_GET_FEATURE_REQUEST
    cc = PCSCReader.readers()[0].createConnection()
    cc.connect()
    print("%r %x %x" % cc.transmit(SELECT + DF_TELECOM))

    print(cc.control(CM_IOCTL_GET_FEATURE_REQUEST, []))
    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()
Esempio n. 10
0
    def readCard(self, dend, msr):
        """Wait for card insertion and returns a card service."""
        
        AbstractCardRequest.waitforcard(self)
        cardfound = False

        data = []
        swiped = False

        # for non infinite timeout, a timer will signal
        # the end of the time-out by setting the evt event
        evt = Event()
        if INFINITE == self.timeout:
            timertimeout = 1
        else:
            timertimeout = self.timeout
        timer = 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 list(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, list(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.cardservice(reader)
        
        while not evt.isSet() and not cardfound:
            sleep(self.pollinginterval) # PCSC refresh rate
            
            # 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 list(readerstates.keys()):
                if oldreader not in readernames:
                    del readerstates[oldreader]

            # wait for card insertion
            if {} != readerstates:
                hresult, newstates = SCardGetStatusChange(
                    self.hcontext, 0, list(readerstates.values()))
            else:
                hresult = SCARD_E_TIMEOUT
                newstates = []

            # msr-read card intermezzo
            if not self.msr_active:
                try:
                    if swiped:
                        return msr.process_data(data)
                    
                    data += msr.device.read(dend.bEndpointAddress, dend.wMaxPacketSize, 5) 
                    if len(data) >= 537:
                        swiped = True
                except usb.core.USBError as e:
                    if e.args == ('Operation timed out',):
                        print('Invalid swipe, discarding %s bytes of data', len(data))
                        data = []
                        continue


            # 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.cardservice(reader)

                    # update state dictionary
                    readerstates[readername] = (readername, eventstate)

            if evt.isSet():
                raise CardRequestTimeoutException()