mirror of https://gerrit.osmocom.org/pysim
cosmetic: Switch to consistent four-spaces indent; run autopep8
We had a mixture of tab and 4space based indenting, which is a bad idea. 4space is the standard in python, so convert all our code to that. The result unfortuantely still shoed even more inconsistencies, so I've decided to run autopep8 on the entire code base. Change-Id: I4a4b1b444a2f43fab05fc5d2c8a7dd6ddecb5f07changes/41/27141/3
parent
181c7c5930
commit
c91085e744
1227
pySim-prog.py
1227
pySim-prog.py
File diff suppressed because it is too large
Load Diff
546
pySim-read.py
546
pySim-read.py
|
@ -41,312 +41,322 @@ from pySim.utils import format_xplmn_w_act, dec_st
|
|||
from pySim.utils import h2s, format_ePDGSelection
|
||||
|
||||
option_parser = argparse.ArgumentParser(prog='pySim-read',
|
||||
description='Legacy tool for reading some parts of a SIM card',
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
description='Legacy tool for reading some parts of a SIM card',
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
argparse_add_reader_args(option_parser)
|
||||
|
||||
def select_app(adf:str, card:SimCard):
|
||||
"""Select application by its AID"""
|
||||
sw = 0
|
||||
try:
|
||||
if card._scc.cla_byte == "00":
|
||||
data, sw = card.select_adf_by_aid(adf)
|
||||
except SwMatchError as e:
|
||||
if e.sw_actual == "6a82":
|
||||
# If we can't select the file because it does not exist, we just remain silent since it means
|
||||
# that this card just does not have an USIM application installed, which is not an error.
|
||||
pass
|
||||
else:
|
||||
print("ADF." + adf + ": Can't select application -- " + str(e))
|
||||
except Exception as e:
|
||||
print("ADF." + adf + ": Can't select application -- " + str(e))
|
||||
|
||||
return sw
|
||||
def select_app(adf: str, card: SimCard):
|
||||
"""Select application by its AID"""
|
||||
sw = 0
|
||||
try:
|
||||
if card._scc.cla_byte == "00":
|
||||
data, sw = card.select_adf_by_aid(adf)
|
||||
except SwMatchError as e:
|
||||
if e.sw_actual == "6a82":
|
||||
# If we can't select the file because it does not exist, we just remain silent since it means
|
||||
# that this card just does not have an USIM application installed, which is not an error.
|
||||
pass
|
||||
else:
|
||||
print("ADF." + adf + ": Can't select application -- " + str(e))
|
||||
except Exception as e:
|
||||
print("ADF." + adf + ": Can't select application -- " + str(e))
|
||||
|
||||
return sw
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
# Parse options
|
||||
opts = option_parser.parse_args()
|
||||
# Parse options
|
||||
opts = option_parser.parse_args()
|
||||
|
||||
# Init card reader driver
|
||||
sl = init_reader(opts)
|
||||
if sl is None:
|
||||
exit(1)
|
||||
# Init card reader driver
|
||||
sl = init_reader(opts)
|
||||
if sl is None:
|
||||
exit(1)
|
||||
|
||||
# Create command layer
|
||||
scc = SimCardCommands(transport=sl)
|
||||
# Create command layer
|
||||
scc = SimCardCommands(transport=sl)
|
||||
|
||||
# Wait for SIM card
|
||||
sl.wait_for_card()
|
||||
# Wait for SIM card
|
||||
sl.wait_for_card()
|
||||
|
||||
# Assuming UICC SIM
|
||||
scc.cla_byte = "00"
|
||||
scc.sel_ctrl = "0004"
|
||||
# Assuming UICC SIM
|
||||
scc.cla_byte = "00"
|
||||
scc.sel_ctrl = "0004"
|
||||
|
||||
# Testing for Classic SIM or UICC
|
||||
(res, sw) = sl.send_apdu(scc.cla_byte + "a4" + scc.sel_ctrl + "02" + "3f00")
|
||||
if sw == '6e00':
|
||||
# Just a Classic SIM
|
||||
scc.cla_byte = "a0"
|
||||
scc.sel_ctrl = "0000"
|
||||
# Testing for Classic SIM or UICC
|
||||
(res, sw) = sl.send_apdu(scc.cla_byte + "a4" + scc.sel_ctrl + "02" + "3f00")
|
||||
if sw == '6e00':
|
||||
# Just a Classic SIM
|
||||
scc.cla_byte = "a0"
|
||||
scc.sel_ctrl = "0000"
|
||||
|
||||
# Read the card
|
||||
print("Reading ...")
|
||||
# Read the card
|
||||
print("Reading ...")
|
||||
|
||||
# Initialize Card object by auto detecting the card
|
||||
card = card_detect("auto", scc) or SimCard(scc)
|
||||
# Initialize Card object by auto detecting the card
|
||||
card = card_detect("auto", scc) or SimCard(scc)
|
||||
|
||||
# Read all AIDs on the UICC
|
||||
card.read_aids()
|
||||
# Read all AIDs on the UICC
|
||||
card.read_aids()
|
||||
|
||||
# EF.ICCID
|
||||
(res, sw) = card.read_iccid()
|
||||
if sw == '9000':
|
||||
print("ICCID: %s" % (res,))
|
||||
else:
|
||||
print("ICCID: Can't read, response code = %s" % (sw,))
|
||||
# EF.ICCID
|
||||
(res, sw) = card.read_iccid()
|
||||
if sw == '9000':
|
||||
print("ICCID: %s" % (res,))
|
||||
else:
|
||||
print("ICCID: Can't read, response code = %s" % (sw,))
|
||||
|
||||
# EF.IMSI
|
||||
(res, sw) = card.read_imsi()
|
||||
if sw == '9000':
|
||||
print("IMSI: %s" % (res,))
|
||||
else:
|
||||
print("IMSI: Can't read, response code = %s" % (sw,))
|
||||
# EF.IMSI
|
||||
(res, sw) = card.read_imsi()
|
||||
if sw == '9000':
|
||||
print("IMSI: %s" % (res,))
|
||||
else:
|
||||
print("IMSI: Can't read, response code = %s" % (sw,))
|
||||
|
||||
# EF.GID1
|
||||
try:
|
||||
(res, sw) = card.read_gid1()
|
||||
if sw == '9000':
|
||||
print("GID1: %s" % (res,))
|
||||
else:
|
||||
print("GID1: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("GID1: Can't read file -- %s" % (str(e),))
|
||||
# EF.GID1
|
||||
try:
|
||||
(res, sw) = card.read_gid1()
|
||||
if sw == '9000':
|
||||
print("GID1: %s" % (res,))
|
||||
else:
|
||||
print("GID1: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("GID1: Can't read file -- %s" % (str(e),))
|
||||
|
||||
# EF.GID2
|
||||
try:
|
||||
(res, sw) = card.read_binary('GID2')
|
||||
if sw == '9000':
|
||||
print("GID2: %s" % (res,))
|
||||
else:
|
||||
print("GID2: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("GID2: Can't read file -- %s" % (str(e),))
|
||||
# EF.GID2
|
||||
try:
|
||||
(res, sw) = card.read_binary('GID2')
|
||||
if sw == '9000':
|
||||
print("GID2: %s" % (res,))
|
||||
else:
|
||||
print("GID2: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("GID2: Can't read file -- %s" % (str(e),))
|
||||
|
||||
# EF.SMSP
|
||||
(res, sw) = card.read_record('SMSP', 1)
|
||||
if sw == '9000':
|
||||
print("SMSP: %s" % (res,))
|
||||
else:
|
||||
print("SMSP: Can't read, response code = %s" % (sw,))
|
||||
# EF.SMSP
|
||||
(res, sw) = card.read_record('SMSP', 1)
|
||||
if sw == '9000':
|
||||
print("SMSP: %s" % (res,))
|
||||
else:
|
||||
print("SMSP: Can't read, response code = %s" % (sw,))
|
||||
|
||||
# EF.SPN
|
||||
try:
|
||||
(res, sw) = card.read_spn()
|
||||
if sw == '9000':
|
||||
print("SPN: %s" % (res[0] or "Not available"))
|
||||
print("Show in HPLMN: %s" % (res[1],))
|
||||
print("Hide in OPLMN: %s" % (res[2],))
|
||||
else:
|
||||
print("SPN: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("SPN: Can't read file -- %s" % (str(e),))
|
||||
# EF.SPN
|
||||
try:
|
||||
(res, sw) = card.read_spn()
|
||||
if sw == '9000':
|
||||
print("SPN: %s" % (res[0] or "Not available"))
|
||||
print("Show in HPLMN: %s" % (res[1],))
|
||||
print("Hide in OPLMN: %s" % (res[2],))
|
||||
else:
|
||||
print("SPN: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("SPN: Can't read file -- %s" % (str(e),))
|
||||
|
||||
# EF.PLMNsel
|
||||
try:
|
||||
(res, sw) = card.read_binary('PLMNsel')
|
||||
if sw == '9000':
|
||||
print("PLMNsel: %s" % (res))
|
||||
else:
|
||||
print("PLMNsel: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("PLMNsel: Can't read file -- " + str(e))
|
||||
# EF.PLMNsel
|
||||
try:
|
||||
(res, sw) = card.read_binary('PLMNsel')
|
||||
if sw == '9000':
|
||||
print("PLMNsel: %s" % (res))
|
||||
else:
|
||||
print("PLMNsel: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("PLMNsel: Can't read file -- " + str(e))
|
||||
|
||||
# EF.PLMNwAcT
|
||||
try:
|
||||
(res, sw) = card.read_plmn_act()
|
||||
if sw == '9000':
|
||||
print("PLMNwAcT:\n%s" % (res))
|
||||
else:
|
||||
print("PLMNwAcT: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("PLMNwAcT: Can't read file -- " + str(e))
|
||||
# EF.PLMNwAcT
|
||||
try:
|
||||
(res, sw) = card.read_plmn_act()
|
||||
if sw == '9000':
|
||||
print("PLMNwAcT:\n%s" % (res))
|
||||
else:
|
||||
print("PLMNwAcT: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("PLMNwAcT: Can't read file -- " + str(e))
|
||||
|
||||
# EF.OPLMNwAcT
|
||||
try:
|
||||
(res, sw) = card.read_oplmn_act()
|
||||
if sw == '9000':
|
||||
print("OPLMNwAcT:\n%s" % (res))
|
||||
else:
|
||||
print("OPLMNwAcT: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("OPLMNwAcT: Can't read file -- " + str(e))
|
||||
# EF.OPLMNwAcT
|
||||
try:
|
||||
(res, sw) = card.read_oplmn_act()
|
||||
if sw == '9000':
|
||||
print("OPLMNwAcT:\n%s" % (res))
|
||||
else:
|
||||
print("OPLMNwAcT: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("OPLMNwAcT: Can't read file -- " + str(e))
|
||||
|
||||
# EF.HPLMNAcT
|
||||
try:
|
||||
(res, sw) = card.read_hplmn_act()
|
||||
if sw == '9000':
|
||||
print("HPLMNAcT:\n%s" % (res))
|
||||
else:
|
||||
print("HPLMNAcT: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("HPLMNAcT: Can't read file -- " + str(e))
|
||||
# EF.HPLMNAcT
|
||||
try:
|
||||
(res, sw) = card.read_hplmn_act()
|
||||
if sw == '9000':
|
||||
print("HPLMNAcT:\n%s" % (res))
|
||||
else:
|
||||
print("HPLMNAcT: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("HPLMNAcT: Can't read file -- " + str(e))
|
||||
|
||||
# EF.ACC
|
||||
(res, sw) = card.read_binary('ACC')
|
||||
if sw == '9000':
|
||||
print("ACC: %s" % (res,))
|
||||
else:
|
||||
print("ACC: Can't read, response code = %s" % (sw,))
|
||||
# EF.ACC
|
||||
(res, sw) = card.read_binary('ACC')
|
||||
if sw == '9000':
|
||||
print("ACC: %s" % (res,))
|
||||
else:
|
||||
print("ACC: Can't read, response code = %s" % (sw,))
|
||||
|
||||
# EF.MSISDN
|
||||
try:
|
||||
(res, sw) = card.read_msisdn()
|
||||
if sw == '9000':
|
||||
# (npi, ton, msisdn) = res
|
||||
if res is not None:
|
||||
print("MSISDN (NPI=%d ToN=%d): %s" % res)
|
||||
else:
|
||||
print("MSISDN: Not available")
|
||||
else:
|
||||
print("MSISDN: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("MSISDN: Can't read file -- " + str(e))
|
||||
# EF.MSISDN
|
||||
try:
|
||||
(res, sw) = card.read_msisdn()
|
||||
if sw == '9000':
|
||||
# (npi, ton, msisdn) = res
|
||||
if res is not None:
|
||||
print("MSISDN (NPI=%d ToN=%d): %s" % res)
|
||||
else:
|
||||
print("MSISDN: Not available")
|
||||
else:
|
||||
print("MSISDN: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("MSISDN: Can't read file -- " + str(e))
|
||||
|
||||
# EF.AD
|
||||
(res, sw) = card.read_binary('AD')
|
||||
if sw == '9000':
|
||||
print("Administrative data: %s" % (res,))
|
||||
ad = EF_AD()
|
||||
decoded_data = ad.decode_hex(res)
|
||||
print("\tMS operation mode: %s" % decoded_data['ms_operation_mode'])
|
||||
if decoded_data['ofm']:
|
||||
print("\tCiphering Indicator: enabled")
|
||||
else:
|
||||
print("\tCiphering Indicator: disabled")
|
||||
else:
|
||||
print("AD: Can't read, response code = %s" % (sw,))
|
||||
# EF.AD
|
||||
(res, sw) = card.read_binary('AD')
|
||||
if sw == '9000':
|
||||
print("Administrative data: %s" % (res,))
|
||||
ad = EF_AD()
|
||||
decoded_data = ad.decode_hex(res)
|
||||
print("\tMS operation mode: %s" % decoded_data['ms_operation_mode'])
|
||||
if decoded_data['ofm']:
|
||||
print("\tCiphering Indicator: enabled")
|
||||
else:
|
||||
print("\tCiphering Indicator: disabled")
|
||||
else:
|
||||
print("AD: Can't read, response code = %s" % (sw,))
|
||||
|
||||
# EF.SST
|
||||
(res, sw) = card.read_binary('SST')
|
||||
if sw == '9000':
|
||||
print("SIM Service Table: %s" % res)
|
||||
# Print those which are available
|
||||
print("%s" % dec_st(res))
|
||||
else:
|
||||
print("SIM Service Table: Can't read, response code = %s" % (sw,))
|
||||
# EF.SST
|
||||
(res, sw) = card.read_binary('SST')
|
||||
if sw == '9000':
|
||||
print("SIM Service Table: %s" % res)
|
||||
# Print those which are available
|
||||
print("%s" % dec_st(res))
|
||||
else:
|
||||
print("SIM Service Table: Can't read, response code = %s" % (sw,))
|
||||
|
||||
# Check whether we have th AID of USIM, if so select it by its AID
|
||||
# EF.UST - File Id in ADF USIM : 6f38
|
||||
sw = select_app("USIM", card)
|
||||
if sw == '9000':
|
||||
# Select USIM profile
|
||||
usim_card = UsimCard(scc)
|
||||
# Check whether we have th AID of USIM, if so select it by its AID
|
||||
# EF.UST - File Id in ADF USIM : 6f38
|
||||
sw = select_app("USIM", card)
|
||||
if sw == '9000':
|
||||
# Select USIM profile
|
||||
usim_card = UsimCard(scc)
|
||||
|
||||
# EF.EHPLMN
|
||||
if usim_card.file_exists(EF_USIM_ADF_map['EHPLMN']):
|
||||
(res, sw) = usim_card.read_ehplmn()
|
||||
if sw == '9000':
|
||||
print("EHPLMN:\n%s" % (res))
|
||||
else:
|
||||
print("EHPLMN: Can't read, response code = %s" % (sw,))
|
||||
# EF.EHPLMN
|
||||
if usim_card.file_exists(EF_USIM_ADF_map['EHPLMN']):
|
||||
(res, sw) = usim_card.read_ehplmn()
|
||||
if sw == '9000':
|
||||
print("EHPLMN:\n%s" % (res))
|
||||
else:
|
||||
print("EHPLMN: Can't read, response code = %s" % (sw,))
|
||||
|
||||
# EF.UST
|
||||
try:
|
||||
if usim_card.file_exists(EF_USIM_ADF_map['UST']):
|
||||
# res[0] - EF content of UST
|
||||
# res[1] - Human readable format of services marked available in UST
|
||||
(res, sw) = usim_card.read_ust()
|
||||
if sw == '9000':
|
||||
print("USIM Service Table: %s" % res[0])
|
||||
print("%s" % res[1])
|
||||
else:
|
||||
print("USIM Service Table: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("USIM Service Table: Can't read file -- " + str(e))
|
||||
# EF.UST
|
||||
try:
|
||||
if usim_card.file_exists(EF_USIM_ADF_map['UST']):
|
||||
# res[0] - EF content of UST
|
||||
# res[1] - Human readable format of services marked available in UST
|
||||
(res, sw) = usim_card.read_ust()
|
||||
if sw == '9000':
|
||||
print("USIM Service Table: %s" % res[0])
|
||||
print("%s" % res[1])
|
||||
else:
|
||||
print("USIM Service Table: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("USIM Service Table: Can't read file -- " + str(e))
|
||||
|
||||
#EF.ePDGId - Home ePDG Identifier
|
||||
try:
|
||||
if usim_card.file_exists(EF_USIM_ADF_map['ePDGId']):
|
||||
(res, sw) = usim_card.read_epdgid()
|
||||
if sw == '9000':
|
||||
print("ePDGId:\n%s" % (len(res) and res or '\tNot available\n',))
|
||||
else:
|
||||
print("ePDGId: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("ePDGId: Can't read file -- " + str(e))
|
||||
# EF.ePDGId - Home ePDG Identifier
|
||||
try:
|
||||
if usim_card.file_exists(EF_USIM_ADF_map['ePDGId']):
|
||||
(res, sw) = usim_card.read_epdgid()
|
||||
if sw == '9000':
|
||||
print("ePDGId:\n%s" %
|
||||
(len(res) and res or '\tNot available\n',))
|
||||
else:
|
||||
print("ePDGId: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("ePDGId: Can't read file -- " + str(e))
|
||||
|
||||
#EF.ePDGSelection - ePDG Selection Information
|
||||
try:
|
||||
if usim_card.file_exists(EF_USIM_ADF_map['ePDGSelection']):
|
||||
(res, sw) = usim_card.read_ePDGSelection()
|
||||
if sw == '9000':
|
||||
print("ePDGSelection:\n%s" % (res,))
|
||||
else:
|
||||
print("ePDGSelection: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("ePDGSelection: Can't read file -- " + str(e))
|
||||
# EF.ePDGSelection - ePDG Selection Information
|
||||
try:
|
||||
if usim_card.file_exists(EF_USIM_ADF_map['ePDGSelection']):
|
||||
(res, sw) = usim_card.read_ePDGSelection()
|
||||
if sw == '9000':
|
||||
print("ePDGSelection:\n%s" % (res,))
|
||||
else:
|
||||
print("ePDGSelection: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("ePDGSelection: Can't read file -- " + str(e))
|
||||
|
||||
# Select ISIM application by its AID
|
||||
sw = select_app("ISIM", card)
|
||||
if sw == '9000':
|
||||
# Select USIM profile
|
||||
isim_card = IsimCard(scc)
|
||||
# Select ISIM application by its AID
|
||||
sw = select_app("ISIM", card)
|
||||
if sw == '9000':
|
||||
# Select USIM profile
|
||||
isim_card = IsimCard(scc)
|
||||
|
||||
#EF.P-CSCF - P-CSCF Address
|
||||
try:
|
||||
if isim_card.file_exists(EF_ISIM_ADF_map['PCSCF']):
|
||||
res = isim_card.read_pcscf()
|
||||
print("P-CSCF:\n%s" % (len(res) and res or '\tNot available\n',))
|
||||
except Exception as e:
|
||||
print("P-CSCF: Can't read file -- " + str(e))
|
||||
# EF.P-CSCF - P-CSCF Address
|
||||
try:
|
||||
if isim_card.file_exists(EF_ISIM_ADF_map['PCSCF']):
|
||||
res = isim_card.read_pcscf()
|
||||
print("P-CSCF:\n%s" %
|
||||
(len(res) and res or '\tNot available\n',))
|
||||
except Exception as e:
|
||||
print("P-CSCF: Can't read file -- " + str(e))
|
||||
|
||||
# EF.DOMAIN - Home Network Domain Name e.g. ims.mncXXX.mccXXX.3gppnetwork.org
|
||||
try:
|
||||
if isim_card.file_exists(EF_ISIM_ADF_map['DOMAIN']):
|
||||
(res, sw) = isim_card.read_domain()
|
||||
if sw == '9000':
|
||||
print("Home Network Domain Name: %s" % (len(res) and res or 'Not available',))
|
||||
else:
|
||||
print("Home Network Domain Name: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("Home Network Domain Name: Can't read file -- " + str(e))
|
||||
# EF.DOMAIN - Home Network Domain Name e.g. ims.mncXXX.mccXXX.3gppnetwork.org
|
||||
try:
|
||||
if isim_card.file_exists(EF_ISIM_ADF_map['DOMAIN']):
|
||||
(res, sw) = isim_card.read_domain()
|
||||
if sw == '9000':
|
||||
print("Home Network Domain Name: %s" %
|
||||
(len(res) and res or 'Not available',))
|
||||
else:
|
||||
print(
|
||||
"Home Network Domain Name: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("Home Network Domain Name: Can't read file -- " + str(e))
|
||||
|
||||
# EF.IMPI - IMS private user identity
|
||||
try:
|
||||
if isim_card.file_exists(EF_ISIM_ADF_map['IMPI']):
|
||||
(res, sw) = isim_card.read_impi()
|
||||
if sw == '9000':
|
||||
print("IMS private user identity: %s" % (len(res) and res or 'Not available',))
|
||||
else:
|
||||
print("IMS private user identity: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("IMS private user identity: Can't read file -- " + str(e))
|
||||
# EF.IMPI - IMS private user identity
|
||||
try:
|
||||
if isim_card.file_exists(EF_ISIM_ADF_map['IMPI']):
|
||||
(res, sw) = isim_card.read_impi()
|
||||
if sw == '9000':
|
||||
print("IMS private user identity: %s" %
|
||||
(len(res) and res or 'Not available',))
|
||||
else:
|
||||
print(
|
||||
"IMS private user identity: Can't read, response code = %s" % (sw,))
|
||||
except Exception as e:
|
||||
print("IMS private user identity: Can't read file -- " + str(e))
|
||||
|
||||
# EF.IMPU - IMS public user identity
|
||||
try:
|
||||
if isim_card.file_exists(EF_ISIM_ADF_map['IMPU']):
|
||||
res = isim_card.read_impu()
|
||||
print("IMS public user identity:\n%s" % (len(res) and res or '\tNot available\n',))
|
||||
except Exception as e:
|
||||
print("IMS public user identity: Can't read file -- " + str(e))
|
||||
# EF.IMPU - IMS public user identity
|
||||
try:
|
||||
if isim_card.file_exists(EF_ISIM_ADF_map['IMPU']):
|
||||
res = isim_card.read_impu()
|
||||
print("IMS public user identity:\n%s" %
|
||||
(len(res) and res or '\tNot available\n',))
|
||||
except Exception as e:
|
||||
print("IMS public user identity: Can't read file -- " + str(e))
|
||||
|
||||
# EF.UICCIARI - UICC IARI
|
||||
try:
|
||||
if isim_card.file_exists(EF_ISIM_ADF_map['UICCIARI']):
|
||||
res = isim_card.read_iari()
|
||||
print("UICC IARI:\n%s" % (len(res) and res or '\tNot available\n',))
|
||||
except Exception as e:
|
||||
print("UICC IARI: Can't read file -- " + str(e))
|
||||
# EF.UICCIARI - UICC IARI
|
||||
try:
|
||||
if isim_card.file_exists(EF_ISIM_ADF_map['UICCIARI']):
|
||||
res = isim_card.read_iari()
|
||||
print("UICC IARI:\n%s" %
|
||||
(len(res) and res or '\tNot available\n',))
|
||||
except Exception as e:
|
||||
print("UICC IARI: Can't read file -- " + str(e))
|
||||
|
||||
# EF.IST
|
||||
(res, sw) = card.read_binary('6f07')
|
||||
if sw == '9000':
|
||||
print("ISIM Service Table: %s" % res)
|
||||
# Print those which are available
|
||||
print("%s" % dec_st(res, table="isim"))
|
||||
else:
|
||||
print("ISIM Service Table: Can't read, response code = %s" % (sw,))
|
||||
# EF.IST
|
||||
(res, sw) = card.read_binary('6f07')
|
||||
if sw == '9000':
|
||||
print("ISIM Service Table: %s" % res)
|
||||
# Print those which are available
|
||||
print("%s" % dec_st(res, table="isim"))
|
||||
else:
|
||||
print("ISIM Service Table: Can't read, response code = %s" % (sw,))
|
||||
|
||||
# Done for this card and maybe for everything ?
|
||||
print("Done !\n")
|
||||
# Done for this card and maybe for everything ?
|
||||
print("Done !\n")
|
||||
|
|
1359
pySim-shell.py
1359
pySim-shell.py
File diff suppressed because it is too large
Load Diff
|
@ -1 +0,0 @@
|
|||
|
|
@ -34,29 +34,35 @@ from pySim.tlv import *
|
|||
|
||||
# various BER-TLV encoded Data Objects (DOs)
|
||||
|
||||
|
||||
class AidRefDO(BER_TLV_IE, tag=0x4f):
|
||||
# SEID v1.1 Table 6-3
|
||||
_construct = HexAdapter(GreedyBytes)
|
||||
|
||||
|
||||
class AidRefEmptyDO(BER_TLV_IE, tag=0xc0):
|
||||
# SEID v1.1 Table 6-3
|
||||
pass
|
||||
|
||||
|
||||
class DevAppIdRefDO(BER_TLV_IE, tag=0xc1):
|
||||
# SEID v1.1 Table 6-4
|
||||
_construct = HexAdapter(GreedyBytes)
|
||||
|
||||
|
||||
class PkgRefDO(BER_TLV_IE, tag=0xca):
|
||||
# Android UICC Carrier Privileges specific extension, see https://source.android.com/devices/tech/config/uicc
|
||||
_construct = Struct('package_name_string'/GreedyString("ascii"))
|
||||
|
||||
class RefDO(BER_TLV_IE, tag=0xe1, nested=[AidRefDO,AidRefEmptyDO,DevAppIdRefDO,PkgRefDO]):
|
||||
|
||||
class RefDO(BER_TLV_IE, tag=0xe1, nested=[AidRefDO, AidRefEmptyDO, DevAppIdRefDO, PkgRefDO]):
|
||||
# SEID v1.1 Table 6-5
|
||||
pass
|
||||
|
||||
|
||||
class ApduArDO(BER_TLV_IE, tag=0xd0):
|
||||
# SEID v1.1 Table 6-8
|
||||
def _from_bytes(self, do:bytes):
|
||||
def _from_bytes(self, do: bytes):
|
||||
if len(do) == 1:
|
||||
if do[0] == 0x00:
|
||||
self.decoded = {'generic_access_rule': 'never'}
|
||||
|
@ -76,6 +82,7 @@ class ApduArDO(BER_TLV_IE, tag=0xd0):
|
|||
'mask': b2h(do[offset+4:offset+8])}
|
||||
self.decoded = res
|
||||
return res
|
||||
|
||||
def _to_bytes(self):
|
||||
if 'generic_access_rule' in self.decoded:
|
||||
if self.decoded['generic_access_rule'] == 'never':
|
||||
|
@ -99,94 +106,118 @@ class ApduArDO(BER_TLV_IE, tag=0xd0):
|
|||
res += header_b + mask_b
|
||||
return res
|
||||
|
||||
|
||||
class NfcArDO(BER_TLV_IE, tag=0xd1):
|
||||
# SEID v1.1 Table 6-9
|
||||
_construct = Struct('nfc_event_access_rule'/Enum(Int8ub, never=0, always=1))
|
||||
_construct = Struct('nfc_event_access_rule' /
|
||||
Enum(Int8ub, never=0, always=1))
|
||||
|
||||
|
||||
class PermArDO(BER_TLV_IE, tag=0xdb):
|
||||
# Android UICC Carrier Privileges specific extension, see https://source.android.com/devices/tech/config/uicc
|
||||
_construct = Struct('permissions'/HexAdapter(Bytes(8)))
|
||||
|
||||
|
||||
class ArDO(BER_TLV_IE, tag=0xe3, nested=[ApduArDO, NfcArDO, PermArDO]):
|
||||
# SEID v1.1 Table 6-7
|
||||
pass
|
||||
|
||||
|
||||
class RefArDO(BER_TLV_IE, tag=0xe2, nested=[RefDO, ArDO]):
|
||||
# SEID v1.1 Table 6-6
|
||||
pass
|
||||
|
||||
|
||||
class ResponseAllRefArDO(BER_TLV_IE, tag=0xff40, nested=[RefArDO]):
|
||||
# SEID v1.1 Table 4-2
|
||||
pass
|
||||
|
||||
|
||||
class ResponseArDO(BER_TLV_IE, tag=0xff50, nested=[ArDO]):
|
||||
# SEID v1.1 Table 4-3
|
||||
pass
|
||||
|
||||
|
||||
class ResponseRefreshTagDO(BER_TLV_IE, tag=0xdf20):
|
||||
# SEID v1.1 Table 4-4
|
||||
_construct = Struct('refresh_tag'/HexAdapter(Bytes(8)))
|
||||
|
||||
|
||||
class DeviceInterfaceVersionDO(BER_TLV_IE, tag=0xe6):
|
||||
# SEID v1.1 Table 6-12
|
||||
_construct = Struct('major'/Int8ub, 'minor'/Int8ub, 'patch'/Int8ub)
|
||||
|
||||
|
||||
class DeviceConfigDO(BER_TLV_IE, tag=0xe4, nested=[DeviceInterfaceVersionDO]):
|
||||
# SEID v1.1 Table 6-10
|
||||
pass
|
||||
|
||||
|
||||
class ResponseDeviceConfigDO(BER_TLV_IE, tag=0xff7f, nested=[DeviceConfigDO]):
|
||||
# SEID v1.1 Table 5-14
|
||||
pass
|
||||
|
||||
|
||||
class AramConfigDO(BER_TLV_IE, tag=0xe5, nested=[DeviceInterfaceVersionDO]):
|
||||
# SEID v1.1 Table 6-11
|
||||
pass
|
||||
|
||||
|
||||
class ResponseAramConfigDO(BER_TLV_IE, tag=0xdf21, nested=[AramConfigDO]):
|
||||
# SEID v1.1 Table 4-5
|
||||
pass
|
||||
|
||||
|
||||
class CommandStoreRefArDO(BER_TLV_IE, tag=0xf0, nested=[RefArDO]):
|
||||
# SEID v1.1 Table 5-2
|
||||
pass
|
||||
|
||||
|
||||
class CommandDelete(BER_TLV_IE, tag=0xf1, nested=[AidRefDO, AidRefEmptyDO, RefDO, RefArDO]):
|
||||
# SEID v1.1 Table 5-4
|
||||
pass
|
||||
|
||||
|
||||
class CommandUpdateRefreshTagDO(BER_TLV_IE, tag=0xf2):
|
||||
# SEID V1.1 Table 5-6
|
||||
pass
|
||||
|
||||
|
||||
class CommandRegisterClientAidsDO(BER_TLV_IE, tag=0xf7, nested=[AidRefDO, AidRefEmptyDO]):
|
||||
# SEID v1.1 Table 5-7
|
||||
pass
|
||||
|
||||
|
||||
class CommandGet(BER_TLV_IE, tag=0xf3, nested=[AidRefDO, AidRefEmptyDO]):
|
||||
# SEID v1.1 Table 5-8
|
||||
pass
|
||||
|
||||
|
||||
class CommandGetAll(BER_TLV_IE, tag=0xf4):
|
||||
# SEID v1.1 Table 5-9
|
||||
pass
|
||||
|
||||
|
||||
class CommandGetClientAidsDO(BER_TLV_IE, tag=0xf6):
|
||||
# SEID v1.1 Table 5-10
|
||||
pass
|
||||
|
||||
|
||||
class CommandGetNext(BER_TLV_IE, tag=0xf5):
|
||||
# SEID v1.1 Table 5-11
|
||||
pass
|
||||
|
||||
|
||||
class CommandGetDeviceConfigDO(BER_TLV_IE, tag=0xf8):
|
||||
# SEID v1.1 Table 5-12
|
||||
pass
|
||||
|
||||
|
||||
class ResponseAracAidDO(BER_TLV_IE, tag=0xff70, nested=[AidRefDO, AidRefEmptyDO]):
|
||||
# SEID v1.1 Table 5-13
|
||||
pass
|
||||
|
||||
|
||||
class BlockDO(BER_TLV_IE, tag=0xe7):
|
||||
# SEID v1.1 Table 6-13
|
||||
_construct = Struct('offset'/Int16ub, 'length'/Int8ub)
|
||||
|
@ -197,11 +228,15 @@ class GetCommandDoCollection(TLV_IE_Collection, nested=[RefDO, DeviceConfigDO]):
|
|||
pass
|
||||
|
||||
# SEID v1.1 Table 4-2
|
||||
|
||||
|
||||
class GetResponseDoCollection(TLV_IE_Collection, nested=[ResponseAllRefArDO, ResponseArDO,
|
||||
ResponseRefreshTagDO, ResponseAramConfigDO]):
|
||||
pass
|
||||
|
||||
# SEID v1.1 Table 5-1
|
||||
|
||||
|
||||
class StoreCommandDoCollection(TLV_IE_Collection,
|
||||
nested=[BlockDO, CommandStoreRefArDO, CommandDelete,
|
||||
CommandUpdateRefreshTagDO, CommandRegisterClientAidsDO,
|
||||
|
@ -215,6 +250,7 @@ class StoreResponseDoCollection(TLV_IE_Collection,
|
|||
nested=[ResponseAllRefArDO, ResponseAracAidDO, ResponseDeviceConfigDO]):
|
||||
pass
|
||||
|
||||
|
||||
class ADF_ARAM(CardADF):
|
||||
def __init__(self, aid='a00000015141434c00', name='ADF.ARA-M', fid=None, sfid=None,
|
||||
desc='ARA-M Application'):
|
||||
|
@ -224,7 +260,7 @@ class ADF_ARAM(CardADF):
|
|||
self.add_files(files)
|
||||
|
||||
@staticmethod
|
||||
def xceive_apdu_tlv(tp, hdr:Hexstr, cmd_do, resp_cls, exp_sw='9000'):
|
||||
def xceive_apdu_tlv(tp, hdr: Hexstr, cmd_do, resp_cls, exp_sw='9000'):
|
||||
"""Transceive an APDU with the card, transparently encoding the command data from TLV
|
||||
and decoding the response data tlv."""
|
||||
if cmd_do:
|
||||
|
@ -259,7 +295,8 @@ class ADF_ARAM(CardADF):
|
|||
@staticmethod
|
||||
def get_config(tp, v_major=0, v_minor=0, v_patch=1):
|
||||
cmd_do = DeviceConfigDO()
|
||||
cmd_do.from_dict([{'DeviceInterfaceVersionDO': {'major': v_major, 'minor': v_minor, 'patch': v_patch }}])
|
||||
cmd_do.from_dict([{'DeviceInterfaceVersionDO': {
|
||||
'major': v_major, 'minor': v_minor, 'patch': v_patch}}])
|
||||
return ADF_ARAM.xceive_apdu_tlv(tp, '80cadf21', cmd_do, ResponseAramConfigDO)
|
||||
|
||||
@with_default_category('Application-Specific Commands')
|
||||
|
@ -281,20 +318,30 @@ class ADF_ARAM(CardADF):
|
|||
|
||||
store_ref_ar_do_parse = argparse.ArgumentParser()
|
||||
# REF-DO
|
||||
store_ref_ar_do_parse.add_argument('--device-app-id', required=True, help='Identifies the specific device application that the rule appplies to. Hash of Certificate of Application Provider, or UUID. (20/32 hex bytes)')
|
||||
store_ref_ar_do_parse.add_argument(
|
||||
'--device-app-id', required=True, help='Identifies the specific device application that the rule appplies to. Hash of Certificate of Application Provider, or UUID. (20/32 hex bytes)')
|
||||
aid_grp = store_ref_ar_do_parse.add_mutually_exclusive_group()
|
||||
aid_grp.add_argument('--aid', help='Identifies the specific SE application for which rules are to be stored. Can be a partial AID, containing for example only the RID. (5-16 hex bytes)')
|
||||
aid_grp.add_argument('--aid-empty', action='store_true', help='No specific SE application, applies to all applications')
|
||||
store_ref_ar_do_parse.add_argument('--pkg-ref', help='Full Android Java package name (up to 127 chars ASCII)')
|
||||
aid_grp.add_argument(
|
||||
'--aid', help='Identifies the specific SE application for which rules are to be stored. Can be a partial AID, containing for example only the RID. (5-16 hex bytes)')
|
||||
aid_grp.add_argument('--aid-empty', action='store_true',
|
||||
help='No specific SE application, applies to all applications')
|
||||
store_ref_ar_do_parse.add_argument(
|
||||
'--pkg-ref', help='Full Android Java package name (up to 127 chars ASCII)')
|
||||
# AR-DO
|
||||
apdu_grp = store_ref_ar_do_parse.add_mutually_exclusive_group()
|
||||
apdu_grp.add_argument('--apdu-never', action='store_true', help='APDU access is not allowed')
|
||||
apdu_grp.add_argument('--apdu-always', action='store_true', help='APDU access is allowed')
|
||||
apdu_grp.add_argument('--apdu-filter', help='APDU filter: 4 byte CLA/INS/P1/P2 followed by 4 byte mask (8 hex bytes)')
|
||||
apdu_grp.add_argument(
|
||||
'--apdu-never', action='store_true', help='APDU access is not allowed')
|
||||
apdu_grp.add_argument(
|
||||
'--apdu-always', action='store_true', help='APDU access is allowed')
|
||||
apdu_grp.add_argument(
|
||||
'--apdu-filter', help='APDU filter: 4 byte CLA/INS/P1/P2 followed by 4 byte mask (8 hex bytes)')
|
||||
nfc_grp = store_ref_ar_do_parse.add_mutually_exclusive_group()
|
||||
nfc_grp.add_argument('--nfc-always', action='store_true', help='NFC event access is allowed')
|
||||
nfc_grp.add_argument('--nfc-never', action='store_true', help='NFC event access is not allowed')
|
||||
store_ref_ar_do_parse.add_argument('--android-permissions', help='Android UICC Carrier Privilege Permissions (8 hex bytes)')
|
||||
nfc_grp.add_argument('--nfc-always', action='store_true',
|
||||
help='NFC event access is allowed')
|
||||
nfc_grp.add_argument('--nfc-never', action='store_true',
|
||||
help='NFC event access is not allowed')
|
||||
store_ref_ar_do_parse.add_argument(
|
||||
'--android-permissions', help='Android UICC Carrier Privilege Permissions (8 hex bytes)')
|
||||
|
||||
@cmd2.with_argparser(store_ref_ar_do_parse)
|
||||
def do_aram_store_ref_ar_do(self, opts):
|
||||
|
@ -323,7 +370,7 @@ class ADF_ARAM(CardADF):
|
|||
ar_do_content += [{'NfcArDO': {'nfc_event_access_rule': 'never'}}]
|
||||
if opts.android_permissions:
|
||||
ar_do_content += [{'PermArDO': {'permissions': opts.android_permissions}}]
|
||||
d = [{'RefArDO': [{ 'RefDO': ref_do_content}, {'ArDO': ar_do_content }]}]
|
||||
d = [{'RefArDO': [{'RefDO': ref_do_content}, {'ArDO': ar_do_content}]}]
|
||||
csrado = CommandStoreRefArDO()
|
||||
csrado.from_dict(d)
|
||||
res_do = ADF_ARAM.store_data(self._cmd.card._scc._tp, csrado)
|
||||
|
@ -359,6 +406,7 @@ sw_aram = {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
class CardApplicationARAM(CardApplication):
|
||||
def __init__(self):
|
||||
super().__init__('ARA-M', adf=ADF_ARAM(), sw=sw_aram)
|
||||
super().__init__('ARA-M', adf=ADF_ARAM(), sw=sw_aram)
|
||||
|
|
|
@ -30,116 +30,118 @@ import subprocess
|
|||
import sys
|
||||
import yaml
|
||||
|
||||
|
||||
class CardHandlerBase:
|
||||
"""Abstract base class representing a mechanism for card insertion/removal."""
|
||||
"""Abstract base class representing a mechanism for card insertion/removal."""
|
||||
|
||||
def __init__(self, sl:LinkBase):
|
||||
self.sl = sl
|
||||
def __init__(self, sl: LinkBase):
|
||||
self.sl = sl
|
||||
|
||||
def get(self, first:bool = False):
|
||||
"""Method called when pySim needs a new card to be inserted.
|
||||
def get(self, first: bool = False):
|
||||
"""Method called when pySim needs a new card to be inserted.
|
||||
|
||||
Args:
|
||||
first : set to true when the get method is called the
|
||||
first time. This is required to prevent blocking
|
||||
when a card is already inserted into the reader.
|
||||
The reader API would not recognize that card as
|
||||
"new card" until it would be removed and re-inserted
|
||||
again.
|
||||
"""
|
||||
print("Ready for Programming: ", end='')
|
||||
self._get(first)
|
||||
Args:
|
||||
first : set to true when the get method is called the
|
||||
first time. This is required to prevent blocking
|
||||
when a card is already inserted into the reader.
|
||||
The reader API would not recognize that card as
|
||||
"new card" until it would be removed and re-inserted
|
||||
again.
|
||||
"""
|
||||
print("Ready for Programming: ", end='')
|
||||
self._get(first)
|
||||
|
||||
def error(self):
|
||||
"""Method called when pySim failed to program a card. Move card to 'bad' batch."""
|
||||
print("Programming failed: ", end='')
|
||||
self._error()
|
||||
def error(self):
|
||||
"""Method called when pySim failed to program a card. Move card to 'bad' batch."""
|
||||
print("Programming failed: ", end='')
|
||||
self._error()
|
||||
|
||||
def done(self):
|
||||
"""Method called when pySim failed to program a card. Move card to 'good' batch."""
|
||||
print("Programming successful: ", end='')
|
||||
self._done()
|
||||
def done(self):
|
||||
"""Method called when pySim failed to program a card. Move card to 'good' batch."""
|
||||
print("Programming successful: ", end='')
|
||||
self._done()
|
||||
|
||||
def _get(self, first:bool = False):
|
||||
pass
|
||||
def _get(self, first: bool = False):
|
||||
pass
|
||||
|
||||
def _error(self):
|
||||
pass
|
||||
def _error(self):
|
||||
pass
|
||||
|
||||
def _done(self):
|
||||
pass
|
||||
def _done(self):
|
||||
pass
|
||||
|
||||
|
||||
class CardHandler(CardHandlerBase):
|
||||
"""Manual card handler: User is prompted to insert/remove card from the reader."""
|
||||
"""Manual card handler: User is prompted to insert/remove card from the reader."""
|
||||
|
||||
def _get(self, first:bool = False):
|
||||
print("Insert card now (or CTRL-C to cancel)")
|
||||
self.sl.wait_for_card(newcardonly=not first)
|
||||
def _get(self, first: bool = False):
|
||||
print("Insert card now (or CTRL-C to cancel)")
|
||||
self.sl.wait_for_card(newcardonly=not first)
|
||||
|
||||
def _error(self):
|
||||
print("Remove card from reader")
|
||||
print("")
|
||||
def _error(self):
|
||||
print("Remove card from reader")
|
||||
print("")
|
||||
|
||||
def _done(self):
|
||||
print("Remove card from reader")
|
||||
print("")
|
||||
def _done(self):
|
||||
print("Remove card from reader")
|
||||
print("")
|
||||
|
||||
|
||||
class CardHandlerAuto(CardHandlerBase):
|
||||
"""Automatic card handler: A machine is used to handle the cards."""
|
||||
"""Automatic card handler: A machine is used to handle the cards."""
|
||||
|
||||
verbose = True
|
||||
verbose = True
|
||||
|
||||
def __init__(self, sl:LinkBase, config_file:str):
|
||||
super().__init__(sl)
|
||||
print("Card handler Config-file: " + str(config_file))
|
||||
with open(config_file) as cfg:
|
||||
self.cmds = yaml.load(cfg, Loader=yaml.FullLoader)
|
||||
self.verbose = (self.cmds.get('verbose') == True)
|
||||
def __init__(self, sl: LinkBase, config_file: str):
|
||||
super().__init__(sl)
|
||||
print("Card handler Config-file: " + str(config_file))
|
||||
with open(config_file) as cfg:
|
||||
self.cmds = yaml.load(cfg, Loader=yaml.FullLoader)
|
||||
self.verbose = (self.cmds.get('verbose') == True)
|
||||
|
||||
def __print_outout(self, out):
|
||||
print("")
|
||||
print("Card handler output:")
|
||||
print("---------------------8<---------------------")
|
||||
stdout = out[0].strip()
|
||||
if len(stdout) > 0:
|
||||
print("stdout:")
|
||||
print(stdout)
|
||||
stderr = out[1].strip()
|
||||
if len(stderr) > 0:
|
||||
print("stderr:")
|
||||
print(stderr)
|
||||
print("---------------------8<---------------------")
|
||||
print("")
|
||||
def __print_outout(self, out):
|
||||
print("")
|
||||
print("Card handler output:")
|
||||
print("---------------------8<---------------------")
|
||||
stdout = out[0].strip()
|
||||
if len(stdout) > 0:
|
||||
print("stdout:")
|
||||
print(stdout)
|
||||
stderr = out[1].strip()
|
||||
if len(stderr) > 0:
|
||||
print("stderr:")
|
||||
print(stderr)
|
||||
print("---------------------8<---------------------")
|
||||
print("")
|
||||
|
||||
def __exec_cmd(self, command):
|
||||
print("Card handler Commandline: " + str(command))
|
||||
def __exec_cmd(self, command):
|
||||
print("Card handler Commandline: " + str(command))
|
||||
|
||||
proc = subprocess.Popen([command], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
out = proc.communicate()
|
||||
rc = proc.returncode
|
||||
proc = subprocess.Popen(
|
||||
[command], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
out = proc.communicate()
|
||||
rc = proc.returncode
|
||||
|
||||
if rc != 0 or self.verbose:
|
||||
self.__print_outout(out)
|
||||
if rc != 0 or self.verbose:
|
||||
self.__print_outout(out)
|
||||
|
||||
if rc != 0:
|
||||
print("")
|
||||
print("Error: Card handler failure! (rc=" + str(rc) + ")")
|
||||
sys.exit(rc)
|
||||
if rc != 0:
|
||||
print("")
|
||||
print("Error: Card handler failure! (rc=" + str(rc) + ")")
|
||||
sys.exit(rc)
|
||||
|
||||
def _get(self, first:bool = False):
|
||||
print("Transporting card into the reader-bay...")
|
||||
self.__exec_cmd(self.cmds['get'])
|
||||
if self.sl:
|
||||
self.sl.connect()
|
||||
def _get(self, first: bool = False):
|
||||
print("Transporting card into the reader-bay...")
|
||||
self.__exec_cmd(self.cmds['get'])
|
||||
if self.sl:
|
||||
self.sl.connect()
|
||||
|
||||
def _error(self):
|
||||
print("Transporting card to the error-bin...")
|
||||
self.__exec_cmd(self.cmds['error'])
|
||||
print("")
|
||||
def _error(self):
|
||||
print("Transporting card to the error-bin...")
|
||||
self.__exec_cmd(self.cmds['error'])
|
||||
print("")
|
||||
|
||||
def _done(self):
|
||||
print("Transporting card into the collector bin...")
|
||||
self.__exec_cmd(self.cmds['done'])
|
||||
print("")
|
||||
def _done(self):
|
||||
print("Transporting card into the collector bin...")
|
||||
self.__exec_cmd(self.cmds['done'])
|
||||
print("")
|
||||
|
|
|
@ -33,136 +33,142 @@ from typing import List, Dict, Optional
|
|||
import abc
|
||||
import csv
|
||||
|
||||
card_key_providers = [] # type: List['CardKeyProvider']
|
||||
card_key_providers = [] # type: List['CardKeyProvider']
|
||||
|
||||
|
||||
class CardKeyProvider(abc.ABC):
|
||||
"""Base class, not containing any concrete implementation."""
|
||||
"""Base class, not containing any concrete implementation."""
|
||||
|
||||
VALID_FIELD_NAMES = ['ICCID', 'ADM1', 'IMSI', 'PIN1', 'PIN2', 'PUK1', 'PUK2']
|
||||
VALID_FIELD_NAMES = ['ICCID', 'ADM1',
|
||||
'IMSI', 'PIN1', 'PIN2', 'PUK1', 'PUK2']
|
||||
|
||||
# check input parameters, but do nothing concrete yet
|
||||
def _verify_get_data(self, fields:List[str]=[], key:str='ICCID', value:str="") -> Dict[str,str]:
|
||||
"""Verify multiple fields for identified card.
|
||||
# check input parameters, but do nothing concrete yet
|
||||
def _verify_get_data(self, fields: List[str] = [], key: str = 'ICCID', value: str = "") -> Dict[str, str]:
|
||||
"""Verify multiple fields for identified card.
|
||||
|
||||
Args:
|
||||
fields : list of valid field names such as 'ADM1', 'PIN1', ... which are to be obtained
|
||||
key : look-up key to identify card data, such as 'ICCID'
|
||||
value : value for look-up key to identify card data
|
||||
Returns:
|
||||
dictionary of {field, value} strings for each requested field from 'fields'
|
||||
"""
|
||||
for f in fields:
|
||||
if (f not in self.VALID_FIELD_NAMES):
|
||||
raise ValueError("Requested field name '%s' is not a valid field name, valid field names are: %s" %
|
||||
(f, str(self.VALID_FIELD_NAMES)))
|
||||
Args:
|
||||
fields : list of valid field names such as 'ADM1', 'PIN1', ... which are to be obtained
|
||||
key : look-up key to identify card data, such as 'ICCID'
|
||||
value : value for look-up key to identify card data
|
||||
Returns:
|
||||
dictionary of {field, value} strings for each requested field from 'fields'
|
||||
"""
|
||||
for f in fields:
|
||||
if (f not in self.VALID_FIELD_NAMES):
|
||||
raise ValueError("Requested field name '%s' is not a valid field name, valid field names are: %s" %
|
||||
(f, str(self.VALID_FIELD_NAMES)))
|
||||
|
||||
if (key not in self.VALID_FIELD_NAMES):
|
||||
raise ValueError("Key field name '%s' is not a valid field name, valid field names are: %s" %
|
||||
(key, str(self.VALID_FIELD_NAMES)))
|
||||
if (key not in self.VALID_FIELD_NAMES):
|
||||
raise ValueError("Key field name '%s' is not a valid field name, valid field names are: %s" %
|
||||
(key, str(self.VALID_FIELD_NAMES)))
|
||||
|
||||
return {}
|
||||
return {}
|
||||
|
||||
def get_field(self, field:str, key:str='ICCID', value:str="") -> Optional[str]:
|
||||
"""get a single field from CSV file using a specified key/value pair"""
|
||||
fields = [field]
|
||||
result = self.get(fields, key, value)
|
||||
return result.get(field)
|
||||
def get_field(self, field: str, key: str = 'ICCID', value: str = "") -> Optional[str]:
|
||||
"""get a single field from CSV file using a specified key/value pair"""
|
||||
fields = [field]
|
||||
result = self.get(fields, key, value)
|
||||
return result.get(field)
|
||||
|
||||
@abc.abstractmethod
|
||||
def get(self, fields:List[str], key:str, value:str) -> Dict[str,str]:
|
||||
"""Get multiple card-individual fields for identified card.
|
||||
@abc.abstractmethod
|
||||
def get(self, fields: List[str], key: str, value: str) -> Dict[str, str]:
|
||||
"""Get multiple card-individual fields for identified card.
|
||||
|
||||
Args:
|
||||
fields : list of valid field names such as 'ADM1', 'PIN1', ... which are to be obtained
|
||||
key : look-up key to identify card data, such as 'ICCID'
|
||||
value : value for look-up key to identify card data
|
||||
Returns:
|
||||
dictionary of {field, value} strings for each requested field from 'fields'
|
||||
"""
|
||||
|
||||
Args:
|
||||
fields : list of valid field names such as 'ADM1', 'PIN1', ... which are to be obtained
|
||||
key : look-up key to identify card data, such as 'ICCID'
|
||||
value : value for look-up key to identify card data
|
||||
Returns:
|
||||
dictionary of {field, value} strings for each requested field from 'fields'
|
||||
"""
|
||||
|
||||
class CardKeyProviderCsv(CardKeyProvider):
|
||||
"""Card key provider implementation that allows to query against a specified CSV file"""
|
||||
csv_file = None
|
||||
filename = None
|
||||
"""Card key provider implementation that allows to query against a specified CSV file"""
|
||||
csv_file = None
|
||||
filename = None
|
||||
|
||||
def __init__(self, filename:str):
|
||||
"""
|
||||
Args:
|
||||
filename : file name (path) of CSV file containing card-individual key/data
|
||||
"""
|
||||
self.csv_file = open(filename, 'r')
|
||||
if not self.csv_file:
|
||||
raise RuntimeError("Could not open CSV file '%s'" % filename)
|
||||
self.filename = filename
|
||||
def __init__(self, filename: str):
|
||||
"""
|
||||
Args:
|
||||
filename : file name (path) of CSV file containing card-individual key/data
|
||||
"""
|
||||
self.csv_file = open(filename, 'r')
|
||||
if not self.csv_file:
|
||||
raise RuntimeError("Could not open CSV file '%s'" % filename)
|
||||
self.filename = filename
|
||||
|
||||
def get(self, fields:List[str], key:str, value:str) -> Dict[str,str]:
|
||||
super()._verify_get_data(fields, key, value)
|
||||
def get(self, fields: List[str], key: str, value: str) -> Dict[str, str]:
|
||||
super()._verify_get_data(fields, key, value)
|
||||
|
||||
self.csv_file.seek(0)
|
||||
cr = csv.DictReader(self.csv_file)
|
||||
if not cr:
|
||||
raise RuntimeError("Could not open DictReader for CSV-File '%s'" % self.filename)
|
||||
cr.fieldnames = [ field.upper() for field in cr.fieldnames ]
|
||||
self.csv_file.seek(0)
|
||||
cr = csv.DictReader(self.csv_file)
|
||||
if not cr:
|
||||
raise RuntimeError(
|
||||
"Could not open DictReader for CSV-File '%s'" % self.filename)
|
||||
cr.fieldnames = [field.upper() for field in cr.fieldnames]
|
||||
|
||||
rc = {}
|
||||
for row in cr:
|
||||
if row[key] == value:
|
||||
for f in fields:
|
||||
if f in row:
|
||||
rc.update({f : row[f]})
|
||||
else:
|
||||
raise RuntimeError("CSV-File '%s' lacks column '%s'" %
|
||||
(self.filename, f))
|
||||
return rc
|
||||
rc = {}
|
||||
for row in cr:
|
||||
if row[key] == value:
|
||||
for f in fields:
|
||||
if f in row:
|
||||
rc.update({f: row[f]})
|
||||
else:
|
||||
raise RuntimeError("CSV-File '%s' lacks column '%s'" %
|
||||
(self.filename, f))
|
||||
return rc
|
||||
|
||||
|
||||
def card_key_provider_register(provider:CardKeyProvider, provider_list=card_key_providers):
|
||||
"""Register a new card key provider.
|
||||
def card_key_provider_register(provider: CardKeyProvider, provider_list=card_key_providers):
|
||||
"""Register a new card key provider.
|
||||
|
||||
Args:
|
||||
provider : the to-be-registered provider
|
||||
provider_list : override the list of providers from the global default
|
||||
"""
|
||||
if not isinstance(provider, CardKeyProvider):
|
||||
raise ValueError("provider is not a card data provier")
|
||||
provider_list.append(provider)
|
||||
Args:
|
||||
provider : the to-be-registered provider
|
||||
provider_list : override the list of providers from the global default
|
||||
"""
|
||||
if not isinstance(provider, CardKeyProvider):
|
||||
raise ValueError("provider is not a card data provier")
|
||||
provider_list.append(provider)
|
||||
|
||||
|
||||
def card_key_provider_get(fields, key:str, value:str, provider_list=card_key_providers) -> Dict[str,str]:
|
||||
"""Query all registered card data providers for card-individual [key] data.
|
||||
def card_key_provider_get(fields, key: str, value: str, provider_list=card_key_providers) -> Dict[str, str]:
|
||||
"""Query all registered card data providers for card-individual [key] data.
|
||||
|
||||
Args:
|
||||
fields : list of valid field names such as 'ADM1', 'PIN1', ... which are to be obtained
|
||||
key : look-up key to identify card data, such as 'ICCID'
|
||||
value : value for look-up key to identify card data
|
||||
provider_list : override the list of providers from the global default
|
||||
Returns:
|
||||
dictionary of {field, value} strings for each requested field from 'fields'
|
||||
"""
|
||||
for p in provider_list:
|
||||
if not isinstance(p, CardKeyProvider):
|
||||
raise ValueError("provider list contains element which is not a card data provier")
|
||||
result = p.get(fields, key, value)
|
||||
if result:
|
||||
return result
|
||||
return {}
|
||||
Args:
|
||||
fields : list of valid field names such as 'ADM1', 'PIN1', ... which are to be obtained
|
||||
key : look-up key to identify card data, such as 'ICCID'
|
||||
value : value for look-up key to identify card data
|
||||
provider_list : override the list of providers from the global default
|
||||
Returns:
|
||||
dictionary of {field, value} strings for each requested field from 'fields'
|
||||
"""
|
||||
for p in provider_list:
|
||||
if not isinstance(p, CardKeyProvider):
|
||||
raise ValueError(
|
||||
"provider list contains element which is not a card data provier")
|
||||
result = p.get(fields, key, value)
|
||||
if result:
|
||||
return result
|
||||
return {}
|
||||
|
||||
|
||||
def card_key_provider_get_field(field:str, key:str, value:str, provider_list=card_key_providers) -> Optional[str]:
|
||||
"""Query all registered card data providers for a single field.
|
||||
def card_key_provider_get_field(field: str, key: str, value: str, provider_list=card_key_providers) -> Optional[str]:
|
||||
"""Query all registered card data providers for a single field.
|
||||
|
||||
Args:
|
||||
field : name valid field such as 'ADM1', 'PIN1', ... which is to be obtained
|
||||
key : look-up key to identify card data, such as 'ICCID'
|
||||
value : value for look-up key to identify card data
|
||||
provider_list : override the list of providers from the global default
|
||||
Returns:
|
||||
dictionary of {field, value} strings for the requested field
|
||||
"""
|
||||
for p in provider_list:
|
||||
if not isinstance(p, CardKeyProvider):
|
||||
raise ValueError("provider list contains element which is not a card data provier")
|
||||
result = p.get_field(field, key, value)
|
||||
if result:
|
||||
return result
|
||||
return None
|
||||
Args:
|
||||
field : name valid field such as 'ADM1', 'PIN1', ... which is to be obtained
|
||||
key : look-up key to identify card data, such as 'ICCID'
|
||||
value : value for look-up key to identify card data
|
||||
provider_list : override the list of providers from the global default
|
||||
Returns:
|
||||
dictionary of {field, value} strings for the requested field
|
||||
"""
|
||||
for p in provider_list:
|
||||
if not isinstance(p, CardKeyProvider):
|
||||
raise ValueError(
|
||||
"provider list contains element which is not a card data provier")
|
||||
result = p.get_field(field, key, value)
|
||||
if result:
|
||||
return result
|
||||
return None
|
||||
|
|
2574
pySim/cards.py
2574
pySim/cards.py
File diff suppressed because it is too large
Load Diff