v3.23.2: the start-reset ordering fix (review follow-up)
A suite with start_reset and an incomplete SCP80 preset reset the card and only then refused the start: the reset block ran before _test_preset_error. The reset now runs after the preset checks - a run that cannot start must not touch the card - and stays before the ADM gate, which must see the post-reset card session (the reset bumps card_session, invalidating the ADM latch). The ICCID re-match stays with the reset block. Test: an incomplete preset refuses with 400 and _card_reset_reinit is not called. 846 frontend + 830 Python; sw cache simple-v415.
This commit is contained in:
+1
-1
@@ -1904,7 +1904,7 @@
|
||||
// ===== Version =====
|
||||
// Single source of truth for the PWA version: shown in the header and used
|
||||
// by the server version check in pysimConnect().
|
||||
const SIMPLE_VERSION = '3.23.1';
|
||||
const SIMPLE_VERSION = '3.23.2';
|
||||
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
|
||||
|
||||
// ===== view history (the browser Back/Forward buttons) =====
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
const CACHE = 'simple-v414';
|
||||
const CACHE = 'simple-v415';
|
||||
const URLS = [
|
||||
'index.html',
|
||||
'help.html',
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "pysim-simple-server"
|
||||
version = "3.23.1"
|
||||
version = "3.23.2"
|
||||
description = "HTTP REST server wrapping pysim for the SIMple PWA"
|
||||
requires-python = ">=3.8"
|
||||
# pysim is a git-only dependency installed explicitly by setup.bat/setup.sh.
|
||||
|
||||
@@ -36,7 +36,7 @@ from osmocom.tlv import BER_TLV_IE
|
||||
from osmocom.utils import rpad
|
||||
|
||||
|
||||
VERSION = '3.23.1'
|
||||
VERSION = '3.23.2'
|
||||
|
||||
MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE
|
||||
|
||||
@@ -7738,12 +7738,21 @@ class PysimHandler(BaseHTTPRequestHandler):
|
||||
self._send_json(resp, 400)
|
||||
self._log_resp(resp)
|
||||
return
|
||||
steps = [step for _entry, script in members for step in script['steps']]
|
||||
if any(s['type'] == 'action' and s['kind'] == 'scp80' for s in steps):
|
||||
err = _test_preset_error({'steps': steps}, preset)
|
||||
if err:
|
||||
resp = {'error': err}
|
||||
self._send_json(resp, 400)
|
||||
self._log_resp(resp)
|
||||
return
|
||||
reset_info = None
|
||||
if suite.get('start_reset'):
|
||||
# A suite may start with a card reset: the physical reset + the
|
||||
# full equip re-initialization, so its scripts run against a
|
||||
# freshly initialized card. This runs before the scp80 checks and
|
||||
# the ADM gate: the card session changes, so the ADM latch is
|
||||
# freshly initialized card. This runs after the preset checks - a
|
||||
# run that cannot start must not reset the card - and before the
|
||||
# ADM gate: the card session changes, so the ADM latch is
|
||||
# re-verified against the post-reset card, and the ICCID must
|
||||
# still match the run's preset (a reset can switch the active
|
||||
# profile on an eUICC).
|
||||
@@ -7777,14 +7786,6 @@ class PysimHandler(BaseHTTPRequestHandler):
|
||||
self._send_json(resp, 400)
|
||||
self._log_resp(resp)
|
||||
return
|
||||
steps = [step for _entry, script in members for step in script['steps']]
|
||||
if any(s['type'] == 'action' and s['kind'] == 'scp80' for s in steps):
|
||||
err = _test_preset_error({'steps': steps}, preset)
|
||||
if err:
|
||||
resp = {'error': err}
|
||||
self._send_json(resp, 400)
|
||||
self._log_resp(resp)
|
||||
return
|
||||
needed_adm = bool(suite.get('require_adm')) or any(
|
||||
bool(script.get('require_adm')) for _entry, script in members)
|
||||
ok, adm_info, adm_err = _ensure_adm(self.server, preset, needed_adm)
|
||||
|
||||
@@ -1702,6 +1702,21 @@ class TestScriptStoreHttpTests(unittest.TestCase):
|
||||
time.sleep(0.05)
|
||||
self.assertFalse(snap['running'], snap)
|
||||
|
||||
def test_a_bad_scp80_preset_refuses_before_the_reset(self):
|
||||
# v3.23.2: the preset checks come first - a suite that cannot start
|
||||
# must not reset the card
|
||||
self.server.app = object()
|
||||
suite = self._suite(name='reset me', start_reset=True)
|
||||
self._post('/api/test/scripts', self._script(
|
||||
suite_id=suite['id'],
|
||||
steps=[{'type': 'action', 'kind': 'scp80',
|
||||
'params': {'apdu': '80E2900000'}}]))
|
||||
with mock.patch.object(self.srv, '_card_reset_reinit') as r:
|
||||
status, resp = self._post('/api/test/run', {'suite_id': suite['id']})
|
||||
self.assertEqual(status, 400, resp)
|
||||
self.assertIn('incomplete', resp['error'])
|
||||
r.assert_not_called()
|
||||
|
||||
def test_suite_start_reset_refuses_a_mismatched_iccid(self):
|
||||
self.server.app = object()
|
||||
suite = self._suite(name='reset me', start_reset=True)
|
||||
|
||||
Reference in New Issue
Block a user