mirror of https://gerrit.osmocom.org/pysim
proactive: Send a Terminal Response automatically after a Fetch
Change-Id: I43bc994e7517b5907fb40a98d84797c54056c47d
This commit is contained in:
parent
98552ef1bd
commit
59f3b1154f
|
@ -10,7 +10,7 @@ from typing import Optional, Tuple
|
||||||
from pySim.exceptions import *
|
from pySim.exceptions import *
|
||||||
from pySim.construct import filter_dict
|
from pySim.construct import filter_dict
|
||||||
from pySim.utils import sw_match, b2h, h2b, i2h, Hexstr
|
from pySim.utils import sw_match, b2h, h2b, i2h, Hexstr
|
||||||
from pySim.cat import ProactiveCommand
|
from pySim.cat import ProactiveCommand, CommandDetails, DeviceIdentities, Result
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (C) 2009-2010 Sylvain Munaut <tnt@246tNt.com>
|
# Copyright (C) 2009-2010 Sylvain Munaut <tnt@246tNt.com>
|
||||||
|
@ -42,10 +42,7 @@ class ProactiveHandler(abc.ABC):
|
||||||
"""Abstract base class representing the interface of some code that handles
|
"""Abstract base class representing the interface of some code that handles
|
||||||
the proactive commands, as returned by the card in responses to the FETCH
|
the proactive commands, as returned by the card in responses to the FETCH
|
||||||
command."""
|
command."""
|
||||||
def receive_fetch_raw(self, payload: Hexstr):
|
def receive_fetch_raw(self, pcmd: ProactiveCommand, parsed: Hexstr):
|
||||||
# parse the proactive command
|
|
||||||
pcmd = ProactiveCommand()
|
|
||||||
parsed = pcmd.from_tlv(h2b(payload))
|
|
||||||
# try to find a generic handler like handle_SendShortMessage
|
# try to find a generic handler like handle_SendShortMessage
|
||||||
handle_name = 'handle_%s' % type(parsed).__name__
|
handle_name = 'handle_%s' % type(parsed).__name__
|
||||||
if hasattr(self, handle_name):
|
if hasattr(self, handle_name):
|
||||||
|
@ -167,11 +164,50 @@ class LinkBase(abc.ABC):
|
||||||
# need not concern the caller.
|
# need not concern the caller.
|
||||||
rv = (rv[0], '9000')
|
rv = (rv[0], '9000')
|
||||||
# proactive sim as per TS 102 221 Setion 7.4.2
|
# proactive sim as per TS 102 221 Setion 7.4.2
|
||||||
|
# TODO: Check SW manually to avoid recursing on the stack (provided this piece of code stays in this place)
|
||||||
fetch_rv = self.send_apdu_checksw('80120000' + last_sw[2:], sw)
|
fetch_rv = self.send_apdu_checksw('80120000' + last_sw[2:], sw)
|
||||||
|
# Setting this in case we later decide not to send a terminal
|
||||||
|
# response immediately unconditionally -- the card may still have
|
||||||
|
# something pending even though the last command was not processed
|
||||||
|
# yet.
|
||||||
last_sw = fetch_rv[1]
|
last_sw = fetch_rv[1]
|
||||||
print("FETCH: %s" % fetch_rv[0])
|
# parse the proactive command
|
||||||
|
pcmd = ProactiveCommand()
|
||||||
|
parsed = pcmd.from_tlv(h2b(fetch_rv[0]))
|
||||||
|
print("FETCH: %s (%s)" % (fetch_rv[0], type(parsed).__name__))
|
||||||
|
result = Result()
|
||||||
if self.proactive_handler:
|
if self.proactive_handler:
|
||||||
self.proactive_handler.receive_fetch_raw(fetch_rv[0])
|
# Extension point: If this does return a list of TLV objects,
|
||||||
|
# they could be appended after the Result; if the first is a
|
||||||
|
# Result, that cuold replace the one built here.
|
||||||
|
self.proactive_handler.receive_fetch_raw(pcmd, parsed)
|
||||||
|
result.from_dict({'general_result': 'performed_successfully', 'additional_information': ''})
|
||||||
|
else:
|
||||||
|
result.from_dict({'general_result': 'command_beyond_terminal_capability', 'additional_information': ''})
|
||||||
|
|
||||||
|
# Send response immediately, thus also flushing out any further
|
||||||
|
# proactive commands that the card already wants to send
|
||||||
|
#
|
||||||
|
# Structure as per TS 102 223 V4.4.0 Section 6.8
|
||||||
|
|
||||||
|
# The Command Details are echoed from the command that has been processed.
|
||||||
|
(command_details,) = [c for c in pcmd.decoded.children if isinstance(c, CommandDetails)]
|
||||||
|
# The Device Identities are fixed. (TS 102 223 V4.0.0 Section 6.8.2)
|
||||||
|
device_identities = DeviceIdentities()
|
||||||
|
device_identities.from_dict({'source_dev_id': 'terminal', 'dest_dev_id': 'uicc'})
|
||||||
|
|
||||||
|
# Testing hint: The value of tail does not influence the behavior
|
||||||
|
# of an SJA2 that sent ans SMS, so this is implemented only
|
||||||
|
# following TS 102 223, and not fully tested.
|
||||||
|
tail = command_details.to_tlv() + device_identities.to_tlv() + result.to_tlv()
|
||||||
|
# Testing hint: In contrast to the above, this part is positively
|
||||||
|
# essential to get the SJA2 to provide the later parts of a
|
||||||
|
# multipart SMS in response to an OTA RFM command.
|
||||||
|
terminal_response = '80140000' + b2h(len(tail).to_bytes(1, 'big') + tail)
|
||||||
|
|
||||||
|
terminal_response_rv = self.send_apdu(terminal_response)
|
||||||
|
last_sw = terminal_response_rv[1]
|
||||||
|
|
||||||
if not sw_match(rv[1], sw):
|
if not sw_match(rv[1], sw):
|
||||||
raise SwMatchError(rv[1], sw.lower(), self.sw_interpreter)
|
raise SwMatchError(rv[1], sw.lower(), self.sw_interpreter)
|
||||||
return rv
|
return rv
|
||||||
|
|
Loading…
Reference in New Issue