From 8dd272fded1a0e5b10381a29c97ed6b4f0405d3b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 4 Nov 2023 11:33:15 +0200 Subject: [PATCH] tests: Avoid race condition in DPP GAS protocol testing Responder receives Authentication Request and Config Request in a sequence and it is possible for the Config Request to be received before MGMT_RX_PROCESS has been processed for Authentication Request in the cases where the test script is in the middle of RX processing. This can result in DPP-AUTH-SUCCESS being delivered only after the MGMT-RX event for Config Reques which means that wait_auth_success() would lose that MGMT-RX event. Avoid this issue by caching the "extra" MGMT-RX event within wait_auth_success() and having the caller verify if the Config Request (GAS Initial Request) has already been received before waiting to receive it. This makes dpp_gas, dpp_gas_comeback_after_failure, and dpp_gas_timeout_handling more robust. Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 37 ++++++++++++++++++++++++++---------- tests/hwsim/wpasupplicant.py | 3 +++ 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index a490f67ee..95fcf67d7 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -4858,8 +4858,9 @@ def test_dpp_keygen_configurator_error(dev, apdev): if "FAIL" not in dev[0].request("DPP_CONFIGURATOR_ADD curve=unknown"): raise Exception("Unexpected success of invalid DPP_CONFIGURATOR_ADD") -def rx_process_frame(dev): - msg = dev.mgmt_rx() +def rx_process_frame(dev, msg=None): + if msg is None: + msg = dev.mgmt_rx() if msg is None: raise Exception("No management frame RX reported") if "OK" not in dev.request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format( @@ -4873,7 +4874,12 @@ def wait_auth_success(responder, initiator, configurator=None, enrollee=None, require_configurator_failure=False, timeout=5, stop_responder=False, stop_initiator=False): res = {} - ev = responder.wait_event(["DPP-AUTH-SUCCESS", "DPP-FAIL"], timeout=timeout) + ev = responder.wait_event(["DPP-AUTH-SUCCESS", "DPP-FAIL", + "MGMT-RX"], timeout=timeout) + if ev and "MGMT-RX" in ev: + res['responder-mgmt-rx'] = ev + ev = responder.wait_event(["DPP-AUTH-SUCCESS", "DPP-FAIL"], + timeout=timeout) if ev is None or "DPP-AUTH-SUCCESS" not in ev: raise Exception("DPP authentication did not succeed (Responder)") for i in ev.split(' '): @@ -4945,10 +4951,14 @@ def test_dpp_gas_timeout_handling(dev, apdev): # DPP Authentication Confirmation rx_process_frame(dev[0]) - wait_auth_success(dev[0], dev[1]) + res = wait_auth_success(dev[0], dev[1]) + if 'responder-mgmt-rx' in res: + msg = dev[0].mgmt_rx_parse(res['responder-mgmt-rx']) + else: + msg = None # DPP Configuration Request (GAS Initial Request frame) - rx_process_frame(dev[0]) + rx_process_frame(dev[0], msg) # DPP Configuration Request (GAS Comeback Request frame) rx_process_frame(dev[0]) @@ -4970,10 +4980,14 @@ def test_dpp_gas_comeback_after_failure(dev, apdev): # DPP Authentication Confirmation rx_process_frame(dev[0]) - wait_auth_success(dev[0], dev[1]) + res = wait_auth_success(dev[0], dev[1]) + if 'responder-mgmt-rx' in res: + msg = dev[0].mgmt_rx_parse(res['responder-mgmt-rx']) + else: + msg = None # DPP Configuration Request (GAS Initial Request frame) - rx_process_frame(dev[0]) + rx_process_frame(dev[0], msg) # DPP Configuration Request (GAS Comeback Request frame) msg = dev[0].mgmt_rx() @@ -5002,14 +5016,17 @@ def test_dpp_gas(dev, apdev): # DPP Authentication Confirmation rx_process_frame(dev[0]) - wait_auth_success(dev[0], dev[1]) + res = wait_auth_success(dev[0], dev[1]) # DPP Configuration Request (GAS Initial Request frame) - msg = dev[0].mgmt_rx() + if 'responder-mgmt-rx' in res: + msg = dev[0].mgmt_rx_parse(res['responder-mgmt-rx']) + else: + msg = dev[0].mgmt_rx() # Protected Dual of GAS Initial Request frame (dropped by GAS server) if msg == None: - raise Exception("MGMT_RX_PROCESS failed. ") + raise Exception("GAS Initial Request frame not received") frame = binascii.hexlify(msg['frame']) frame = frame[0:48] + b"09" + frame[50:] frame = frame.decode() diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index d52536980..a9ca6c1b6 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1382,6 +1382,9 @@ class WpaSupplicant: ev = self.wait_event(["MGMT-RX"], timeout=timeout) if ev is None: return None + return self.mgmt_rx_parse(ev) + + def mgmt_rx_parse(self, ev): msg = {} items = ev.split(' ') field, val = items[1].split('=')