From 91842b471db50de2d704119cf93b79467654b971 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 11 Jan 2024 22:03:37 +0100 Subject: [PATCH] Constrain user input to hex-string in argparse We do have an is_hexstr function which we should use anywhere where we expect the user to input a string of hex digits. This way we validate the input before running in some random exception. Change-Id: I6426ea864bec82be60554dd125961a48d7751904 --- pySim/filesystem.py | 21 ++++++++------------- pySim/ts_102_222.py | 6 +++--- pySim/ts_31_102.py | 11 ++++++----- pySim/ts_51_011.py | 2 +- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/pySim/filesystem.py b/pySim/filesystem.py index c71150a9..5d1970a6 100644 --- a/pySim/filesystem.py +++ b/pySim/filesystem.py @@ -38,7 +38,7 @@ from typing import cast, Optional, Iterable, List, Dict, Tuple, Union from smartcard.util import toBytes -from pySim.utils import sw_match, h2b, b2h, i2h, is_hex, auto_int, Hexstr +from pySim.utils import sw_match, h2b, b2h, i2h, is_hex, auto_int, Hexstr, is_hexstr from pySim.construct import filter_dict, parse_construct, build_construct from pySim.exceptions import * from pySim.jsonpath import js_path_find, js_path_modify @@ -579,7 +579,7 @@ class TransparentEF(CardEF): dec_hex_parser = argparse.ArgumentParser() dec_hex_parser.add_argument('--oneline', action='store_true', help='No JSON pretty-printing, dump as a single line') - dec_hex_parser.add_argument('HEXSTR', help='Hex-string of encoded data to decode') + dec_hex_parser.add_argument('HEXSTR', type=is_hexstr, help='Hex-string of encoded data to decode') @cmd2.with_argparser(dec_hex_parser) def do_decode_hex(self, opts): @@ -612,8 +612,7 @@ class TransparentEF(CardEF): upd_bin_parser = argparse.ArgumentParser() upd_bin_parser.add_argument( '--offset', type=int, default=0, help='Byte offset for start of read') - upd_bin_parser.add_argument( - 'data', help='Data bytes (hex format) to write') + upd_bin_parser.add_argument('data', type=is_hexstr, help='Data bytes (hex format) to write') @cmd2.with_argparser(upd_bin_parser) def do_update_binary(self, opts): @@ -623,8 +622,7 @@ class TransparentEF(CardEF): self._cmd.poutput(data) upd_bin_dec_parser = argparse.ArgumentParser() - upd_bin_dec_parser.add_argument( - 'data', help='Abstract data (JSON format) to write') + upd_bin_dec_parser.add_argument('data', type=is_hexstr, help='Abstract data (JSON format) to write') upd_bin_dec_parser.add_argument('--json-path', type=str, help='JSON path to modify specific element of file only') @@ -802,7 +800,7 @@ class LinFixedEF(CardEF): dec_hex_parser = argparse.ArgumentParser() dec_hex_parser.add_argument('--oneline', action='store_true', help='No JSON pretty-printing, dump as a single line') - dec_hex_parser.add_argument('HEXSTR', help='Hex-string of encoded data to decode') + dec_hex_parser.add_argument('HEXSTR', type=is_hexstr, help='Hex-string of encoded data to decode') @cmd2.with_argparser(dec_hex_parser) def do_decode_hex(self, opts): @@ -872,8 +870,7 @@ class LinFixedEF(CardEF): upd_rec_parser = argparse.ArgumentParser() upd_rec_parser.add_argument( 'record_nr', type=int, help='Number of record to be read') - upd_rec_parser.add_argument( - 'data', help='Data bytes (hex format) to write') + upd_rec_parser.add_argument('data', type=is_hexstr, help='Data bytes (hex format) to write') @cmd2.with_argparser(upd_rec_parser) def do_update_record(self, opts): @@ -885,8 +882,7 @@ class LinFixedEF(CardEF): upd_rec_dec_parser = argparse.ArgumentParser() upd_rec_dec_parser.add_argument( 'record_nr', type=int, help='Number of record to be read') - upd_rec_dec_parser.add_argument( - 'data', help='Abstract data (JSON format) to write') + upd_rec_dec_parser.add_argument('data', type=is_hexstr, help='Abstract data (JSON format) to write') upd_rec_dec_parser.add_argument('--json-path', type=str, help='JSON path to modify specific element of record only') @@ -1248,8 +1244,7 @@ class BerTlvEF(CardEF): set_data_parser = argparse.ArgumentParser() set_data_parser.add_argument( 'tag', type=auto_int, help='BER-TLV Tag of value to set') - set_data_parser.add_argument( - 'data', help='Data bytes (hex format) to write') + set_data_parser.add_argument('data', type=is_hexstr, help='Data bytes (hex format) to write') @cmd2.with_argparser(set_data_parser) def do_set_data(self, opts): diff --git a/pySim/ts_102_222.py b/pySim/ts_102_222.py index 372d67fc..bf5e29f5 100644 --- a/pySim/ts_102_222.py +++ b/pySim/ts_102_222.py @@ -107,7 +107,7 @@ class Ts102222Commands(CommandSet): (data, sw) = self._cmd.lchan.scc.terminate_card_usage() create_parser = argparse.ArgumentParser() - create_parser.add_argument('FILE_ID', type=str, help='File Identifier as 4-character hex string') + create_parser.add_argument('FILE_ID', type=is_hexstr, help='File Identifier as 4-character hex string') create_parser._action_groups.pop() create_required = create_parser.add_argument_group('required arguments') create_optional = create_parser.add_argument_group('optional arguments') @@ -154,7 +154,7 @@ class Ts102222Commands(CommandSet): self._cmd.lchan.select_file(self._cmd.lchan.selected_file) createdf_parser = argparse.ArgumentParser() - createdf_parser.add_argument('FILE_ID', type=str, help='File Identifier as 4-character hex string') + createdf_parser.add_argument('FILE_ID', type=is_hexstr, help='File Identifier as 4-character hex string') createdf_parser._action_groups.pop() createdf_required = createdf_parser.add_argument_group('required arguments') createdf_optional = createdf_parser.add_argument_group('optional arguments') @@ -162,7 +162,7 @@ class Ts102222Commands(CommandSet): createdf_required.add_argument('--ef-arr-file-id', required=True, type=str, help='Referenced Security: File Identifier of EF.ARR') createdf_required.add_argument('--ef-arr-record-nr', required=True, type=int, help='Referenced Security: Record Number within EF.ARR') createdf_optional.add_argument('--shareable', action='store_true', help='Should the file be shareable?') - createdf_optional.add_argument('--aid', type=str, help='Application ID (creates an ADF, instead of a DF)') + createdf_optional.add_argument('--aid', type=is_hexstr, help='Application ID (creates an ADF, instead of a DF)') # mandatory by spec, but ignored by several OS, so don't force the user createdf_optional.add_argument('--total-file-size', type=int, help='Physical memory allocated for DF/ADi in octets') createdf_sja_optional.add_argument('--permit-rfm-create', action='store_true') diff --git a/pySim/ts_31_102.py b/pySim/ts_31_102.py index 4134650c..0614a0c9 100644 --- a/pySim/ts_31_102.py +++ b/pySim/ts_31_102.py @@ -39,6 +39,7 @@ from pySim.tlv import * from pySim.filesystem import * from pySim.ts_31_102_telecom import DF_PHONEBOOK, EF_UServiceTable from pySim.construct import * +from pySim.utils import is_hexstr from pySim.cat import SMS_TPDU, DeviceIdentities, SMSPPDownload from construct import Optional as COptional from construct import * @@ -1588,8 +1589,8 @@ class ADF_USIM(CardADF): super().__init__() authenticate_parser = argparse.ArgumentParser() - authenticate_parser.add_argument('rand', help='Random challenge') - authenticate_parser.add_argument('autn', help='Authentication Nonce') + authenticate_parser.add_argument('rand', type=is_hexstr, help='Random challenge') + authenticate_parser.add_argument('autn', type=is_hexstr, help='Authentication Nonce') #authenticate_parser.add_argument('--context', help='Authentication context', default='3G') @cmd2.with_argparser(authenticate_parser) @@ -1599,7 +1600,7 @@ class ADF_USIM(CardADF): self._cmd.poutput_json(data) term_prof_parser = argparse.ArgumentParser() - term_prof_parser.add_argument('PROFILE', help='Hexstring of encoded terminal profile') + term_prof_parser.add_argument('PROFILE', type=is_hexstr, help='Hexstring of encoded terminal profile') @cmd2.with_argparser(term_prof_parser) def do_terminal_profile(self, opts): @@ -1613,7 +1614,7 @@ class ADF_USIM(CardADF): self._cmd.poutput('SW: %s, data: %s' % (sw, data)) envelope_parser = argparse.ArgumentParser() - envelope_parser.add_argument('PAYLOAD', help='Hexstring of encoded payload to ENVELOPE') + envelope_parser.add_argument('PAYLOAD', type=is_hexstr, help='Hexstring of encoded payload to ENVELOPE') @cmd2.with_argparser(envelope_parser) def do_envelope(self, opts): @@ -1625,7 +1626,7 @@ class ADF_USIM(CardADF): self._cmd.poutput('SW: %s, data: %s' % (sw, data)) envelope_sms_parser = argparse.ArgumentParser() - envelope_sms_parser.add_argument('TPDU', help='Hexstring of encoded SMS TPDU') + envelope_sms_parser.add_argument('TPDU', type=is_hexstr, help='Hexstring of encoded SMS TPDU') @cmd2.with_argparser(envelope_sms_parser) def do_envelope_sms(self, opts): diff --git a/pySim/ts_51_011.py b/pySim/ts_51_011.py index 0a6f774c..9b56b0e0 100644 --- a/pySim/ts_51_011.py +++ b/pySim/ts_51_011.py @@ -1034,7 +1034,7 @@ class DF_GSM(CardDF): super().__init__() authenticate_parser = argparse.ArgumentParser() - authenticate_parser.add_argument('rand', help='Random challenge') + authenticate_parser.add_argument('rand', type=is_hexstr, help='Random challenge') @cmd2.with_argparser(authenticate_parser) def do_authenticate(self, opts):