Exemplo n.º 1
0
    def test_SCardGetErrorMessage(self):
        res = SCardGetErrorMessage(SCARD_S_SUCCESS)

        # do not test on Windows
        # the error messages are different and localized
        if get_platform() in ('win32', 'win-amd64'):
            return

        expected = "Command successful."
        self.assertEqual(res, expected)

        res = SCardGetErrorMessage(SCARD_F_INTERNAL_ERROR)
        expected = "Internal error."
        self.assertEqual(res, expected)

        res = SCardGetErrorMessage(1)
        expected = "Unknown error: 0x00000001"
        # macOS bug not yet fixed
        if get_platform().startswith('macosx-'):
            version = get_platform()  # something like 'macosx-10.14-x86_64'
            version = version.split('-')[1]  # '10.14'
            major, minor = map(int, version.split('.'))  # (10, 14)
            if major == 10 and minor < 13:
                expected = "Unkown error: 0x00000001"

        self.assertEqual(res, expected)
    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 component.hcard is not None:
                    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
Exemplo n.º 3
0
    def __str__(self):
        text = super(SmartcardException, self).__str__()
        if self.hresult != -1:
            text += ": %s (0x%08X)" % (SCardGetErrorMessage(
                self.hresult), self.hresult)

        return text
    def updateReadersStateList(self):
        # If there is no observer remaining, there is no need to update the readers states list
        if not self.obs:
            return

        self.mutex.acquire()
        hresult, readers_list = SCardListReaders(self.hcontext, [])
        if hresult != SCARD_S_SUCCESS:
            raise CardConnectionException('Unable to list readers: ' + SCardGetErrorMessage(hresult))

        # Add the reader in the readers state list if it is not present
        for reader in readers_list:
            found = False
            for state in self.readers_state_list:
                if state[0] == reader:
                    found = True
                    break
            if not found:
                self.readers_state_list.append((reader, SCARD_STATE_UNAWARE, []))

        # Remove the reader from the readers state list if it is not present in the readers list
        for state in self.readers_state_list:
            if state[0] not in readers_list:
                self.readers_state_list.remove(state)

        # Use Pnp Notification only if supported
        if self.isPnpSupported():
            self.readers_state_list.append(('\\\\?PnP?\\Notification', SCARD_STATE_UNAWARE, []))
        self.mutex.release()
Exemplo n.º 5
0
 def send_apdu(self, cl, ins, p1, p2, data):
     apdu = [cl, ins, p1, p2, len(data)] + [byte2int(b) for b in data]
     hresult, response = SCardTransmit(self._card, self._protocol, apdu)
     if hresult != SCARD_S_SUCCESS:
         raise Exception('Failed to transmit: ' +
                         SCardGetErrorMessage(hresult))
     status = response[-2] << 8 | response[-1]
     return b''.join(int2byte(i) for i in response[:-2]), status
Exemplo n.º 6
0
    def open(self):
        if self._reader:
            try:
                hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
                if hresult != SCARD_S_SUCCESS:
                    raise Exception('Failed to establish context : ' +
                                    SCardGetErrorMessage(hresult))

                hresult, hcard, dwActiveProtocol = SCardConnect(
                    hcontext, self._reader,
                    SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
                if hresult != SCARD_S_SUCCESS:
                    raise Exception('Unable to connect: ' +
                                    SCardGetErrorMessage(hresult))
                return LLScardDevice(hcontext, hcard, dwActiveProtocol)
            except Exception:
                self._set_status(CardStatus.InUse)
Exemplo n.º 7
0
    def _list(self):
        try:
            hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
            if hresult != SCARD_S_SUCCESS:
                raise Exception('Failed to establish context : ' +
                                SCardGetErrorMessage(hresult))

            try:
                hresult, readers = SCardListReaders(hcontext, [])
                if hresult != SCARD_S_SUCCESS:
                    raise Exception('Failed to list readers: ' +
                                    SCardGetErrorMessage(hresult))
                return readers
            finally:
                hresult = SCardReleaseContext(hcontext)
                if hresult != SCARD_S_SUCCESS:
                    raise Exception('Failed to release context: ' +
                                    SCardGetErrorMessage(hresult))
        except:  # noqa: E722
            return []
Exemplo n.º 8
0
    def test_SCardGetErrorMessage(self):
        res = SCardGetErrorMessage(SCARD_S_SUCCESS)

        # do not test on Windows
        # the error messages are different and localized
        if get_platform() in ('win32', 'win-amd64'):
            return

        expected = "Command successful."
        self.assertEqual(res, expected)

        res = SCardGetErrorMessage(SCARD_F_INTERNAL_ERROR)
        expected = "Internal error."
        self.assertEqual(res, expected)

        res = SCardGetErrorMessage(1)
        expected = "Unknown error: 0x00000001"
        # macOS bug not yet fixed
        macos_bug_expected = "Unkown error: 0x00000001"
        self.assertIn(res, [expected, macos_bug_expected])
Exemplo n.º 9
0
    def __str__(self):
        text = super(SmartcardException, self).__str__()
        if self.hresult != -1:
            hresult = self.hresult
            if hresult < 0:
                # convert 0x-7FEFFFE3 into 0x8010001D
                hresult += 0x100000000
            text += ": {} (0x{:08X})".format(
                SCardGetErrorMessage(self.hresult), hresult)

        return text
Exemplo n.º 10
0
    def transceive(self, bytes):

        if not self.card_connection.hcard:
            raise PCSCNotConnected(
                "Tried to transit to non-open connection: {}".format(
                    self.card_connection))

        protocol = self.card_connection.getProtocol()
        pcscprotocolheader = translateprotocolheader(protocol)

        # http://pyscard.sourceforge.net/epydoc/smartcard.scard.scard-module.html#SCardTransmit
        hresult, response = SCardTransmit(self.card_connection.hcard,
                                          pcscprotocolheader, bytes)

        if hresult != 0:
            raise CardConnectionException('Failed to transmit with protocol ' +
                                          str(pcscprotocolheader) + '. ' +
                                          SCardGetErrorMessage(hresult))
        return response
    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
Exemplo n.º 12
0
 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
Exemplo n.º 13
0
    def update(self, observable, actions):
        addedcards, removedcards = actions

        for card in addedcards:
            connection = card.createConnection()
            connection.connect()

            # This will log raw card traffic to console
            connection.addObserver(ConsoleCardConnectionObserver())
            comp = connection.component

            if not comp.hcard:
                raise Exception(
                    "Tried to transit to non-open connection: {}".format(comp))

            protocol = comp.getProtocol()
            pcscprotocolheader = translateprotocolheader(protocol)

            # http://pyscard.sourceforge.net/epydoc/smartcard.scard.scard-module.html#SCardTransmit
            msg = [0xff, 0xca, 0x00, 0x00, 0x04]

            hresult, response = SCardTransmit(comp.hcard, pcscprotocolheader,
                                              msg)

            if hresult != 0:
                raise Exception('Failed to transmit with protocol ' +
                                str(pcscprotocolheader) + '. ' +
                                SCardGetErrorMessage(hresult))

            resp_bytes = ['{0:02x}'.format(r) for r in response]
            status = ''.join(resp_bytes[-2:])

            if status != '9000':
                return
                # raise Exception('Could not read card.')

            serial = ''.join(resp_bytes[0:4])
            self.on_card(serial)
Exemplo n.º 14
0
    def run(self):
        """Runs until stopEvent is notified, and notify observers of all card insertion/removal.
        """
        logging.debug("thread running: %d", self.observable.countObservers())
        while not self.stopEvent.isSet():
            try:
                added_cards = []
                removed_cards = []

                # Update the readers state list to add potentially new found readers and delete removed ones
                self.observable.updateReadersStateList()

                logging.debug("listening for changes...")
                hresult, new_readers_state = SCardGetStatusChange(
                    self.observable.hcontext, self.polling_timeout,
                    self.observable.getReadersStateList())
                logging.debug("changes acquired!")
                logging.debug("states: %s", new_readers_state)

                # Listen only to others result errors
                if hresult != SCARD_S_SUCCESS and hresult != SCARD_E_UNKNOWN_READER and hresult != SCARD_E_TIMEOUT:
                    if hresult == SCARD_E_CANCELLED:
                        break
                    else:
                        raise CardConnectionException(
                            'Unable to get status change: ' +
                            SCardGetErrorMessage(hresult))

                # Update observable readers state list and search for added or removed cards
                self.observable.setReadersStateList(new_readers_state)
                for state in self.observable.getReadersStateList():
                    reader, event, atr = state

                    if event & SCARD_STATE_CHANGED:
                        # Check if we have a card present and an atr (is mute + atr a thing ?)
                        if (event & SCARD_STATE_PRESENT
                                or event & SCARD_STATE_MUTE) and len(atr) != 0:
                            # If the event is telling that a card is present/mute add it to the cards list
                            card = Card(reader, atr)
                            logging.debug(
                                "card added with atr: %s on reader %s",
                                card.atr, card.reader)
                            added_cards.append(card)
                            self.observable.addCard(reader, atr)

                        # Check if we have a card empty slot and if the card is in the list (change+empty can happen after SCARD_STATE_UNAWARE fo ex.)
                        elif event & SCARD_STATE_EMPTY and reader in self.observable.getCardsList(
                        ).keys():
                            # If the event is telling that reader is empty remove it from the cards list
                            atr = self.observable.getCardsList().get(reader)
                            card = Card(reader, atr)
                            logging.debug(
                                "card removed with atr: %s on reader %s",
                                card.atr, card.reader)
                            removed_cards.append(card)
                            self.observable.removeCard(reader)
                        elif event & SCARD_STATE_UNKNOWN or event & SCARD_STATE_IGNORE or event & SCARD_STATE_UNAVAILABLE:
                            # If the event is telling that a reader is not available/existing remove the card on it from the cards list
                            if reader in self.observable.cards_list.keys():
                                logging.debug(
                                    "reader removed, card removed with atr: %s on reader %s",
                                    card.atr, card.reader)
                                removed_cards.append(card)
                                self.observable.removeCard(reader)

                # Update observers if we have added or removed cards
                if added_cards != [] or removed_cards != []:
                    self.observable.setChanged()
                    self.observable.notifyObservers(
                        (added_cards, removed_cards))

            except Exception:
                # FIXME Tighten the exceptions caught by this block
                traceback.print_exc()
                self.stopEvent.set()
Exemplo n.º 15
0
def transmit_command(command):
    hresult, response = SCardTransmit(hcard, dwActiveProtocol, command)
    if hresult != SCARD_S_SUCCESS or response[1] != 0x9F:
        raise error("Failed to select ARA: " + SCardGetErrorMessage(hresult))
    print_hex_response(response)
Exemplo n.º 16
0
    print("response: " + toHexString(response, HEX))


def transmit_command(command):
    hresult, response = SCardTransmit(hcard, dwActiveProtocol, command)
    if hresult != SCARD_S_SUCCESS or response[1] != 0x9F:
        raise error("Failed to select ARA: " + SCardGetErrorMessage(hresult))
    print_hex_response(response)


if __name__ == "__main__":
    try:
        hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
        if hresult != SCARD_S_SUCCESS:
            raise error(
                "Failed to establish context : " + SCardGetErrorMessage(hresult)
            )
        print("Context established!")

        hresult, readers = SCardListReaders(hcontext, [])
        if hresult != SCARD_S_SUCCESS:
            raise error("failed to get readers: " + SCardGetErrorMessage(hresult))
        print("readers:", readers)

        if len(readers) < 1:
            raise error("No smart card readers")

        # default to select first reader
        reader = readers[0]
        print("select reader:", reader)
Exemplo n.º 17
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()
Exemplo n.º 18
0
def check(hresult, op_des, printManualy=-1):
    if hresult != SCARD_S_SUCCESS:
        raise Exception('Failed to {0}: {1}\nhresult = {2}'.format(
            op_des, SCardGetErrorMessage(hresult), hresult))
    elif (DEBUG_PRINT and type(printManualy) == int) or printManualy:
        print('Success to ' + op_des)
Exemplo n.º 19
0
 def getReaders(self):
     if self.hcontext is None:
         self.__establishContext()
     hresult, readers_list = SCardListReaders(self.hcontext, [])
     if hresult != SCARD_S_SUCCESS:
         raise CardConnectionException('Unable to list readers: ' + SCardGetErrorMessage(hresult))
    def run(self):
        """Runs until stopEvent is notified, and notify observers of all reader insertion/removal.
        """
        logging.debug("thread running: %d", self.observable.countObservers())
        while not self.stopEvent.isSet():
            try:
                added_readers = []
                removed_readers = []

                # Update the readers state list to add potentially new found readers and delete removed ones
                self.observable.updateReadersStateList()

                logging.debug("listening for changes...")
                hresult, new_readers_state = SCardGetStatusChange(self.observable.hcontext, self.polling_timeout, self.observable.getReadersStateList())
                logging.debug("changes acquired!")
                logging.debug("states: %s", new_readers_state)

                # Listen only to others result errors
                if hresult != SCARD_S_SUCCESS and hresult != SCARD_E_UNKNOWN_READER and hresult != SCARD_E_TIMEOUT:
                    if hresult == SCARD_E_CANCELLED:
                        break
                    else:
                        raise CardConnectionException('Unable to get status change: ' + SCardGetErrorMessage(hresult))

                # Update observable readers state list and search for added or removed cards
                self.observable.setReadersStateList(new_readers_state)
                for state in self.observable.getReadersStateList():
                    reader, event, atr = state

                    if event & SCARD_STATE_CHANGED:
                        if event & SCARD_STATE_UNKNOWN or event & SCARD_STATE_IGNORE or event & SCARD_STATE_UNAVAILABLE:
                            # If the event is telling that a reader is not available/existing remove it from readers list
                            logging.debug("reader removed: %s", reader)
                            removed_readers.append(reader)
                            self.observable.removeReader(reader)
                        elif reader not in self.observable.getReadersList() and not reader == '\\\\?PnP?\\Notification':
                            # If the event is telling that there is change on a reader which is not present in the readers list, add it
                            logging.debug("reader added: %s", reader)
                            added_readers.append(reader)
                            self.observable.addReader(reader)

                # Update observers if we have added or removed cards
                if added_readers != [] or removed_readers != []:
                    self.observable.setChanged()
                    self.observable.notifyObservers((added_readers, removed_readers))

            except Exception:
                # FIXME Tighten the exceptions caught by this block
                traceback.print_exc()
                self.stopEvent.set()
Exemplo n.º 21
0
 def __establishContext(self):
     hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
     if hresult != SCARD_S_SUCCESS:
         raise CardConnectionException('Failed to establish context: ' + SCardGetErrorMessage(hresult))
Exemplo n.º 22
0
 def __releaseContext(self):
     hresult = SCardReleaseContext(self.hcontext)
     if hresult != SCARD_S_SUCCESS:
         raise CardConnectionException('Failed to release context: ' + SCardGetErrorMessage(hresult))
     self.hcontext = None