Attention is currently required from: dexter.
laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/pysim/+/37641?usp=email )
Change subject: pySim-shell: enable export of DF and ADF files
......................................................................
Patch Set 1:
(1 comment)
File pySim-shell.py:
https://gerrit.osmocom.org/c/pysim/+/37641/comment/c77818b5_571b2542
PS1, Line 500: When walking through the file system tree the action must not
: # always restore the currently selected file
I think the code is doing the opposite of what the comment states? IF the action *must not restore* the selected file, then the code below would always be hit and always generate the RuntimeError
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/37641?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I3ee661dbae5c11fec23911775f352ac13bc2c6e5
Gerrit-Change-Number: 37641
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-CC: laforge <laforge(a)osmocom.org>
Gerrit-Attention: dexter <pmaier(a)sysmocom.de>
Gerrit-Comment-Date: Sat, 27 Jul 2024 08:24:47 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment
laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/37637?usp=email )
Change subject: pySim-shell: fix comment formatting
......................................................................
pySim-shell: fix comment formatting
Related: OS#6092
Change-Id: Icea88c061436d26a3240fc666fcc3fe1bd36d2ba
---
M pySim-shell.py
1 file changed, 16 insertions(+), 6 deletions(-)
Approvals:
laforge: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/pySim-shell.py b/pySim-shell.py
index 8f654bd..168c916 100755
--- a/pySim-shell.py
+++ b/pySim-shell.py
@@ -813,14 +813,14 @@
@cmd2.with_argparser(activate_file_parser)
def do_activate_file(self, opts):
"""Activate the specified EF by sending an ACTIVATE FILE apdu command (used to be called REHABILITATE
-in TS 11.11 for classic SIM).
+ in TS 11.11 for classic SIM).
-This command is used to (re-)activate a file that is currently in deactivated (sometimes also called
-"invalidated") state. You need to call this from the DF above the to-be-activated EF and specify the name or
-FID of the file to activate.
+ This command is used to (re-)activate a file that is currently in deactivated (sometimes also called
+ "invalidated") state. You need to call this from the DF above the to-be-activated EF and specify the name or
+ FID of the file to activate.
-Note that for *deactivation* the to-be-deactivated EF must be selected, but for *activation*, the DF
-above the to-be-activated EF must be selected!"""
+ Note that for *deactivation* the to-be-deactivated EF must be selected, but for *activation*, the DF
+ above the to-be-activated EF must be selected!"""
(data, sw) = self._cmd.lchan.activate_file(opts.NAME)
def complete_activate_file(self, text, line, begidx, endidx) -> List[str]:
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/37637?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: Icea88c061436d26a3240fc666fcc3fe1bd36d2ba
Gerrit-Change-Number: 37637
Gerrit-PatchSet: 2
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-MessageType: merged
laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/37615?usp=email )
Change subject: pySim-shell: clean up method calls in do_switch_channel
......................................................................
pySim-shell: clean up method calls in do_switch_channel
The function do_switch_channel method calls methods in RuntimeLchan
that should be private. There is also a code duplication in
RuntimeLchan that should be cleaned up.
Related: OS#6092
Change-Id: Ie5e5f45787abaaf032e1b49f51d447653cf2c996
---
M pySim-shell.py
M pySim/runtime.py
2 files changed, 29 insertions(+), 14 deletions(-)
Approvals:
laforge: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/pySim-shell.py b/pySim-shell.py
index e99c365..8f654bd 100755
--- a/pySim-shell.py
+++ b/pySim-shell.py
@@ -859,9 +859,9 @@
@cmd2.with_argparser(switch_chan_parser)
def do_switch_channel(self, opts):
"""Switch currently active logical channel."""
- self._cmd.lchan._select_pre(self._cmd)
+ self._cmd.lchan.unregister_cmds(self._cmd)
self._cmd.lchan = self._cmd.rs.lchan[opts.chan_nr]
- self._cmd.lchan._select_post(self._cmd)
+ self._cmd.lchan.register_cmds(self._cmd)
self._cmd.update_prompt()
def do_status(self, opts):
diff --git a/pySim/runtime.py b/pySim/runtime.py
index b729246..2d1f12b 100644
--- a/pySim/runtime.py
+++ b/pySim/runtime.py
@@ -262,7 +262,8 @@
raise ValueError(
"Cannot select unknown file by name %s, only hexadecimal 4 digit FID is allowed" % fid)
- self._select_pre(cmd_app)
+ # unregister commands of old file
+ self.unregister_cmds(cmd_app)
try:
# We access the card through the select_file method of the scc object.
@@ -295,12 +296,6 @@
self._select_post(cmd_app, f, data)
- def _select_pre(self, cmd_app):
- # unregister commands of old file
- if cmd_app and self.selected_file.shell_commands:
- for c in self.selected_file.shell_commands:
- cmd_app.unregister_command_set(c)
-
def _select_post(self, cmd_app, file:Optional[CardFile] = None, select_resp_data = None):
# we store some reference data (see above) about the currently selected file.
# This data must be updated after every select.
@@ -316,9 +311,7 @@
self.selected_file_fcp = None
# register commands of new file
- if cmd_app and self.selected_file.shell_commands:
- for c in self.selected_file.shell_commands:
- cmd_app.register_command_set(c)
+ self.register_cmds(cmd_app)
def select_file(self, file: CardFile, cmd_app=None):
"""Select a file (EF, DF, ADF, MF, ...).
@@ -331,7 +324,9 @@
inter_path = self.selected_file.build_select_path_to(file)
if not inter_path:
raise RuntimeError('Cannot determine path from %s to %s' % (self.selected_file, file))
- self._select_pre(cmd_app)
+
+ # unregister commands of old file
+ self.unregister_cmds(cmd_app)
# be sure the variables that we pass to _select_post contain valid values.
selected_file = self.selected_file
@@ -577,8 +572,14 @@
raise TypeError("Only works with BER-TLV EF")
return self.scc.set_data(self.selected_file.fid, tag, data_hex, conserve=self.rs.conserve_write)
+ def register_cmds(self, cmd_app=None):
+ """Register command set that is associated with the currently selected file"""
+ if cmd_app and self.selected_file.shell_commands:
+ for c in self.selected_file.shell_commands:
+ cmd_app.register_command_set(c)
+
def unregister_cmds(self, cmd_app=None):
- """Unregister all file specific commands."""
+ """Unregister command set that is associated with the currently selected file"""
if cmd_app and self.selected_file.shell_commands:
for c in self.selected_file.shell_commands:
cmd_app.unregister_command_set(c)
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/37615?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: Ie5e5f45787abaaf032e1b49f51d447653cf2c996
Gerrit-Change-Number: 37615
Gerrit-PatchSet: 4
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-MessageType: merged
laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/37614?usp=email )
Change subject: pySim-shell: fix reset command
......................................................................
pySim-shell: fix reset command
The reset command resets the card using the card object. This unfortunately
leaves the RuntimeState uninformed about the event. However, the RuntimeState
class also has a reset method that resets the card and the RuntimeState. Let's
use this reset method. Also fix this method so that it ensures that the SCP is
also no longer present.
Related: OS#6092
Change-Id: I1ad29c9e7ce7d80bebc92fa173ed7a44ee4c2998
---
M pySim-shell.py
M pySim/runtime.py
2 files changed, 21 insertions(+), 4 deletions(-)
Approvals:
laforge: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/pySim-shell.py b/pySim-shell.py
index 2eb37ea..e99c365 100755
--- a/pySim-shell.py
+++ b/pySim-shell.py
@@ -265,10 +265,8 @@
@cmd2.with_category(CUSTOM_CATEGORY)
def do_reset(self, opts):
"""Reset the Card."""
- atr = self.card.reset()
- if self.lchan and self.lchan.scc.scp:
- self.lchan.scc.scp = None
- self.poutput('Card ATR: %s' % i2h(atr))
+ atr = self.rs.reset(self)
+ self.poutput('Card ATR: %s' % atr)
self.update_prompt()
class InterceptStderr(list):
diff --git a/pySim/runtime.py b/pySim/runtime.py
index a56df4d..b729246 100644
--- a/pySim/runtime.py
+++ b/pySim/runtime.py
@@ -134,10 +134,13 @@
"""
# delete all lchan != 0 (basic lchan)
for lchan_nr in list(self.lchan.keys()):
+ self.lchan[lchan_nr].scc.scp = None
if lchan_nr == 0:
continue
del self.lchan[lchan_nr]
atr = i2h(self.card.reset())
+ if cmd_app:
+ cmd_app.lchan = self.lchan[0]
# select MF to reset internal state and to verify card really works
self.lchan[0].select('MF', cmd_app)
self.lchan[0].selected_adf = None
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/37614?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I1ad29c9e7ce7d80bebc92fa173ed7a44ee4c2998
Gerrit-Change-Number: 37614
Gerrit-PatchSet: 3
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-MessageType: merged
laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/37612?usp=email )
Change subject: pySim-shell: move export code into filesystem class model
......................................................................
pySim-shell: move export code into filesystem class model
The code that generates the filesystem export lines for the various
different file structures can be moved into the filesystem class model.
This simplifies the code since we do not need any extra logic to
distinguish between the different file structures.
Related: OS#6092
Change-Id: Icc2ee60cfc4379411744ca1033d79a1ee9cff5a6
---
M pySim-shell.py
M pySim/filesystem.py
2 files changed, 119 insertions(+), 58 deletions(-)
Approvals:
laforge: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/pySim-shell.py b/pySim-shell.py
index 0e7e63c..4f5959b 100755
--- a/pySim-shell.py
+++ b/pySim-shell.py
@@ -599,66 +599,14 @@
self._cmd.poutput("# directory: %s (%s)" % (df_path, df_path_fid))
try:
fcp_dec = self._cmd.lchan.select(filename, self._cmd)
- self._cmd.poutput("# file: %s (%s)" % (
- self._cmd.lchan.selected_file.name, self._cmd.lchan.selected_file.fid))
-
- structure = self._cmd.lchan.selected_file_structure()
- self._cmd.poutput("# structure: %s" % str(structure))
+ self._cmd.poutput("# file: %s (%s)" %
+ (self._cmd.lchan.selected_file.name, self._cmd.lchan.selected_file.fid))
+ self._cmd.poutput("# structure: %s" % self._cmd.lchan.selected_file_structure())
self._cmd.poutput("# RAW FCP Template: %s" % str(self._cmd.lchan.selected_file_fcp_hex))
self._cmd.poutput("# Decoded FCP Template: %s" % str(self._cmd.lchan.selected_file_fcp))
+ self._cmd.poutput("select " + self._cmd.lchan.selected_file.fully_qualified_path_str())
+ self._cmd.poutput(self._cmd.lchan.selected_file.export(as_json, self._cmd.lchan))
- for f in df_path_list:
- self._cmd.poutput("select " + str(f))
- self._cmd.poutput("select " + self._cmd.lchan.selected_file.name)
-
- if structure == 'transparent':
- if as_json:
- result = self._cmd.lchan.read_binary_dec()
- self._cmd.poutput("update_binary_decoded '%s'" % json.dumps(result[0], cls=JsonEncoder))
- else:
- result = self._cmd.lchan.read_binary()
- self._cmd.poutput("update_binary " + str(result[0]))
- elif structure == 'cyclic' or structure == 'linear_fixed':
- # Use number of records specified in select response
- num_of_rec = self._cmd.lchan.selected_file_num_of_rec()
- if num_of_rec:
- for r in range(1, num_of_rec + 1):
- if as_json:
- result = self._cmd.lchan.read_record_dec(r)
- self._cmd.poutput("update_record_decoded %d '%s'" % (r, json.dumps(result[0], cls=JsonEncoder)))
- else:
- result = self._cmd.lchan.read_record(r)
- self._cmd.poutput("update_record %d %s" % (r, str(result[0])))
-
- # When the select response does not return the number of records, read until we hit the
- # first record that cannot be read.
- else:
- r = 1
- while True:
- try:
- if as_json:
- result = self._cmd.lchan.read_record_dec(r)
- self._cmd.poutput("update_record_decoded %d '%s'" % (r, json.dumps(result[0], cls=JsonEncoder)))
- else:
- result = self._cmd.lchan.read_record(r)
- self._cmd.poutput("update_record %d %s" % (r, str(result[0])))
- except SwMatchError as e:
- # We are past the last valid record - stop
- if e.sw_actual == "9402":
- break
- # Some other problem occurred
- else:
- raise e
- r = r + 1
- elif structure == 'ber_tlv':
- tags = self._cmd.lchan.retrieve_tags()
- for t in tags:
- result = self._cmd.lchan.retrieve_data(t)
- (tag, l, val, remainer) = bertlv_parse_one(h2b(result[0]))
- self._cmd.poutput("set_data 0x%02x %s" % (t, b2h(val)))
- else:
- raise RuntimeError(
- 'Unsupported structure "%s" of file "%s"' % (structure, filename))
except Exception as e:
bad_file_str = df_path + "/" + str(filename) + ", " + str(e)
self._cmd.poutput("# bad file: %s" % bad_file_str)
diff --git a/pySim/filesystem.py b/pySim/filesystem.py
index 77482cc..5414fb9 100644
--- a/pySim/filesystem.py
+++ b/pySim/filesystem.py
@@ -35,10 +35,13 @@
from cmd2 import CommandSet, with_default_category
from smartcard.util import toBytes
-from pySim.utils import sw_match, h2b, b2h, is_hex, auto_int, auto_uint8, auto_uint16, is_hexstr
+from pySim.utils import sw_match, h2b, b2h, is_hex, auto_int, auto_uint8, auto_uint16, is_hexstr, JsonEncoder
+from pySim.utils import bertlv_parse_one
+
from pySim.construct import filter_dict, parse_construct, build_construct
from pySim.jsonpath import js_path_modify
from pySim.commands import SimCardCommands
+from pySim.exceptions import SwMatchError
# int: a single service is associated with this file
# list: any of the listed services requires this file
@@ -774,6 +777,25 @@
raise NotImplementedError(
"%s encoder not yet implemented. Patches welcome." % self)
+ @staticmethod
+ def export(as_json: bool, lchan):
+ """
+ Export the file contents of a TransparentEF. This method returns a shell command string (See also ShellCommand
+ definition in this class) that can be used to write the file contents back.
+ """
+
+ if lchan.selected_file_structure() != 'transparent':
+ raise ValueError("selected file has structure type '%s', expecting a file with structure 'transparent'" %
+ lchan.selected_file_structure())
+ export_str = ""
+ if as_json:
+ result = lchan.read_binary_dec()
+ export_str += ("update_binary_decoded '%s'\n" % json.dumps(result[0], cls=JsonEncoder))
+ else:
+ result = lchan.read_binary()
+ export_str += ("update_binary %s\n" % str(result[0]))
+ return export_str.strip()
+
class LinFixedEF(CardEF):
"""Linear Fixed EF (Entry File) in the smart card filesystem.
@@ -1044,6 +1066,54 @@
raise NotImplementedError(
"%s encoder not yet implemented. Patches welcome." % self)
+ @staticmethod
+ def export(as_json: bool, lchan):
+ """
+ Export the file contents of a LinFixedEF (or a CyclicEF). This method returns a shell command string (See also
+ ShellCommand definition in this class) that can be used to write the file contents back.
+ """
+
+ # A CyclicEF is a subclass of LinFixedEF.
+ if lchan.selected_file_structure() != 'linear_fixed' and lchan.selected_file_structure() != 'cyclic':
+ raise ValueError("selected file has structure type '%s', expecting a file with structure 'linear_fixed' or 'cyclic'" %
+ lchan.selected_file_structure())
+
+ export_str = ""
+
+ # Use number of records specified in select response
+ num_of_rec = lchan.selected_file_num_of_rec()
+ if num_of_rec:
+ for r in range(1, num_of_rec + 1):
+ if as_json:
+ result = lchan.read_record_dec(r)
+ export_str += ("update_record_decoded %d '%s'\n" % (r, json.dumps(result[0], cls=JsonEncoder)))
+ else:
+ result = lchan.read_record(r)
+ export_str += ("update_record %d %s\n" % (r, str(result[0])))
+
+ # In case the select response does not return the number of records, read until we hit the first record that
+ # cannot be read.
+ else:
+ r = 1
+ while True:
+ try:
+ if as_json:
+ result = lchan.read_record_dec(r)
+ export_str += ("update_record_decoded %d '%s'\n" % (r, json.dumps(result[0], cls=JsonEncoder)))
+ else:
+ result = lchan.read_record(r)
+ export_str += ("update_record %d %s\n" % (r, str(result[0])))
+ except SwMatchError as e:
+ # We are past the last valid record - stop
+ if e.sw_actual == "9402":
+ break
+ # Some other problem occurred
+ else:
+ raise e
+ r = r + 1
+
+ return export_str.strip()
+
class CyclicEF(LinFixedEF):
"""Cyclic EF (Entry File) in the smart card filesystem"""
@@ -1264,6 +1334,33 @@
self.size = size
self.shell_commands = [self.ShellCommands()]
+ @staticmethod
+ def export(as_json: bool, lchan):
+ """
+ Export the file contents of a BerTlvEF. This method returns a shell command string (See also ShellCommand
+ definition in this class) that can be used to write the file contents back.
+ """
+
+ if lchan.selected_file_structure() != 'ber_tlv':
+ raise ValueError("selected file has structure type '%s', expecting a file with structure 'ber_tlv'" %
+ lchan.selected_file_structure())
+
+ # TODO: Add JSON output as soon as we have a set_data_decoded command and a retrieve_data_dec method.
+ if as_json:
+ raise NotImplementedError("BerTlvEF encoder not yet implemented. Patches welcome.")
+
+ export_str = ""
+ tags = lchan.retrieve_tags()
+ if tags == []:
+ export_str += "# empty file, no tags"
+ else:
+ for t in tags:
+ result = lchan.retrieve_data(t)
+ (tag, l, val, remainer) = bertlv_parse_one(h2b(result[0]))
+ export_str += ("set_data 0x%02x %s\n" % (t, b2h(val)))
+ return export_str.strip()
+
+
def interpret_sw(sw_data: dict, sw: str):
"""Interpret a given status word.
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/37612?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: Icc2ee60cfc4379411744ca1033d79a1ee9cff5a6
Gerrit-Change-Number: 37612
Gerrit-PatchSet: 3
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-MessageType: merged