def __get_card(self, protocol): """Get card interface""" card = None session = Session() atr_str = str(session.getATR()) session.close() if atr_str == APOLLO_CARD_ATR: CardClass = Card elif atr_str == GEMALTO_CARD_ATR: CardClass = GemaltoCard else: raise ConnectCardError('Error connecting to card: UNKNOWN CARD') # try connecting reader result, self.__hcard, self.active_protocol = scard.SCardConnect( self.context, self.name, scard.SCARD_SHARE_SHARED, self.protocol) if result != scard.SCARD_S_SUCCESS: # failed connecting reader message = scard.SCardGetErrorMessage(result) raise ConnectCardError( 'Error connecting to card: {0}'.format(message)) else: # create card class and return it card = CardClass(self.__hcard, self.active_protocol) return card
def disconnect(self): """Safely disconnect card""" result = scard.SCardDisconnect(self._handle, scard.SCARD_UNPOWER_CARD) if result != scard.SCARD_S_SUCCESS: # failed selecting path message = scard.SCardGetErrorMessage(result) raise DisconnectCardError( 'Error disconnecting card: {0}'.format(message))
def release_context(class_): """Release context""" result = scard.SCardReleaseContext(class_.context) if result != scard.SCARD_S_SUCCESS: # failed to get context message = scard.SCardGetErrorMessage(result) raise ReleaseContextError( 'Failed to release context: {0}'.format(message))
def get_context(class_): """Get default context""" result, context = scard.SCardEstablishContext(scard.SCARD_SCOPE_USER) if result != scard.SCARD_S_SUCCESS: # failed to get context message = scard.SCardGetErrorMessage(result) raise GetContextError( 'Failed to establish context: {0}'.format(message)) return context
def select_path(self, path): """Select path on card""" request = CardCommand.SELECT_PATH[:] request.append(len(path)) request.extend(path) request.append(0x01) # transmit command to card result, response = scard.SCardTransmit(self._handle, self._protocol, request) # raise error if needed if result != scard.SCARD_S_SUCCESS: # failed selecting path message = scard.SCardGetErrorMessage(result) raise SelectPathError('Error selecting path: {0}'.format(message)) return response
def get_data(self, command): """Get data from card""" data = None # get data from card result, response = scard.SCardTransmit(self._handle, self._protocol, command) # raise error if needed if result != scard.SCARD_S_SUCCESS: # failed reading data from card message = scard.SCardGetErrorMessage(result) raise GetDataError('Error reading card: {0}'.format(message)) else: data = response return data[:-2]
def get_list(class_): """Get reader list""" if class_.context is None: class_.context = class_.get_context() # get list of readers result, readers = scard.SCardListReaders(class_.get_context(), []) if result != scard.SCARD_S_SUCCESS: # failed to get reader list message = scard.SCardGetErrorMessage(result) raise GetReaderListError( 'Failed to obtain reader list: {0}'.format(message)) elif len(readers) == 0: # no readers detected on the system raise EmptyReaderListError('No smart card readers detected!') return readers
def __wait_for_reader_status(self, current_status, accepted_status): """Wait for a specific reader status""" state = current_status # wait for new status while not state[0][1] & accepted_status: result, state = scard.SCardGetStatusChange(self.context, scard.INFINITE, state) if result != scard.SCARD_S_SUCCESS: # error getting reader status message = scard.SCardGetErrorMessage(result) raise GetReaderStatusError( 'Error getting reader state: {0}'.format(message)) if state[0][1] & scard.SCARD_STATE_UNAVAILABLE: # exit loop when reader becomes unavailable break return state[0][1]
def wait_for_card(self, protocol=None, callback=None): """Wait for card to be inserted""" card = None # set protocol if specified if protocol is not None: self.protocol = protocol # get reader status current_state = [(self.name, scard.SCARD_STATE_UNAWARE)] result, state = scard.SCardGetStatusChange(self.context, 0, current_state) if result != scard.SCARD_S_SUCCESS: # error getting reader status message = scard.SCardGetErrorMessage(result) raise GetReaderStatusError( 'Error getting reader state: {0}'.format(message)) if state[0][1] & scard.SCARD_STATE_EMPTY: # reader is empty, wait for card insertion result = self.__wait_for_reader_status(state, scard.SCARD_STATE_PRESENT) # make sure reader wasn't disconnected if not result & scard.SCARD_STATE_UNAVAILABLE: card = self.__get_card(self.protocol) else: # card is already present in reader card = self.__get_card(self.protocol) # if callback is specified if callback is not None: callback(self, card) return card
def __str__(self): return sc.SCardGetErrorMessage(self.err_code)