pySim-shell: automatic ADM pin from CSV-File
It can be hard to manage ADM pins when working with different cards at
the same time. To make this easier, add an automatic way to determine
the ADM pin for each card from a CSV file.
- add a CardData clas model that can be extended to to get the data from
various different sources. For now use CSV-Files. Also add a way how
multiple CardData classes can be registered so that one global get
function can query all registered CardData classes at once.
- automatically check for CSV-File in home directory and use it as
default CardData source unless the user specifies a CSV file via
commandline argument.
- extend the verify_adm command so that it automatically queries the
ADM pin if no argument is given. Also do not try to authenticate if
no ADM pin could be determined.
Change-Id: I51835ccb16bcbce35e7f3765e8927a4451509e77
Related: OS#4963
diff --git a/pySim-shell.py b/pySim-shell.py
index 41febd6..a8471ff 100755
--- a/pySim-shell.py
+++ b/pySim-shell.py
@@ -29,6 +29,7 @@
import os
import sys
from optparse import OptionParser
+from pathlib import Path
from pySim.ts_51_011 import EF, DF, EF_SST_map, EF_AD_mode_map
from pySim.ts_31_102 import EF_UST_map, EF_USIM_ADF_map
@@ -47,6 +48,9 @@
from pySim.ts_31_102 import ADF_USIM
from pySim.ts_31_103 import ADF_ISIM
+from pySim.card_data import CardDataCsv, card_data_register, card_data_get_field
+
+
class PysimApp(cmd2.Cmd):
CUSTOM_CATEGORY = 'pySim Commands'
def __init__(self, card, rs, script = None):
@@ -56,6 +60,8 @@
self.intro = style('Welcome to pySim-shell!', fg=fg.red)
self.default_category = 'pySim-shell built-in commands'
self.card = card
+ iccid, sw = self.card.read_iccid()
+ self.iccid = iccid
self.rs = rs
self.py_locals = { 'card': self.card, 'rs' : self.rs }
self.numeric_path = False
@@ -78,8 +84,20 @@
@cmd2.with_category(CUSTOM_CATEGORY)
def do_verify_adm(self, arg):
"""VERIFY the ADM1 PIN"""
- pin_adm = sanitize_pin_adm(arg)
- self.card.verify_adm(h2b(pin_adm))
+ if arg:
+ # use specified ADM-PIN
+ pin_adm = sanitize_pin_adm(arg)
+ else:
+ # try to find an ADM-PIN if none is specified
+ result = card_data_get_field('ADM1', key='ICCID', value=self.iccid)
+ pin_adm = sanitize_pin_adm(result)
+ if pin_adm:
+ self.poutput("found adm-pin '%s' for ICCID '%s'" % (result, self.iccid))
+
+ if pin_adm:
+ self.card.verify_adm(h2b(pin_adm))
+ else:
+ self.poutput("error: cannot authenticate, no adm-pin!")
@cmd2.with_category(CUSTOM_CATEGORY)
def do_desc(self, opts):
@@ -289,6 +307,11 @@
default=None,
)
+ parser.add_option("--csv", dest="csv", metavar="FILE",
+ help="Read card data from CSV file",
+ default=None,
+ )
+
parser.add_option("-a", "--pin-adm", dest="pin_adm",
help="ADM PIN used for provisioning (overwrites default)",
)
@@ -340,6 +363,14 @@
app = PysimApp(card, rs, opts.script)
rs.select('MF', app)
+ # Register csv-file as card data provider, either from specified CSV
+ # or from CSV file in home directory
+ csv_default = str(Path.home()) + "/.osmocom/pysim/card_data.csv"
+ if opts.csv:
+ card_data_register(CardDataCsv(opts.csv))
+ if os.path.isfile(csv_default):
+ card_data_register(CardDataCsv(csv_default))
+
# If the user supplies an ADM PIN at via commandline args authenticate
# immediatley so that the user does not have to use the shell commands
pin_adm = sanitize_pin_adm(opts.pin_adm, opts.pin_adm_hex)