def process_handover_request_message(self, records): """Process a handover request message. The *records* argument holds a list of :class:`ndef.Record` objects decoded from the received handover request message octets, where the first record type is ``urn:nfc:wkt:Hr``. The method returns a list of :class:`ndef.Record` objects with the first record typ ``urn:nfc:wkt:Hs``. This method should be overwritten by a subclass to customize it's behavior. The default implementation returns a :class:`ndef.HandoverSelectRecord` with version ``1.2`` and no alternative carriers. """ log.warning("default process_request method should be overwritten") return [ndef.HandoverSelectRecord('1.2')]
def select_carrier(self, hr_records): self.select_carrier_lock.acquire() log.info("<<< %s", '\n '.join(str(r) for r in hr_records)) hs_records = [ndef.HandoverSelectRecord('1.2')] if hr_records[0].version_info.minor == 0 and self.options.quirks: log.warning("quirks: accept handover version 1.0 as 1.1") elif hr_records[0].version_info.minor not in range(1, 3): log.warning("unsupported minor version") self.select_carrier_lock.release() return hs_records remote_carrier_records = dict( (record.name, record) for record in hr_records[1:] if record.name) for ac in hr_records[0].alternative_carriers: record = remote_carrier_records[ac.carrier_data_reference] if record.type == 'urn:nfc:wkt:Hc': remote_carrier_type = record.carrier_type else: remote_carrier_type = record.type for carrier_records in self.options.selectable: selected = len(hs_records[0].alternative_carriers) if not selected < self.options.select: break if carrier_records[0].type == 'urn:nfc:wkt:Hc': local_carrier_type = carrier_records[0].carrier_type else: local_carrier_type = carrier_records[0].type if remote_carrier_type == local_carrier_type: log.info("match for {0}".format(local_carrier_type)) cdr = carrier_records[0].name adr = [record.name for record in carrier_records] hs_records[0].add_alternative_carrier('active', cdr, *adr) hs_records.extend(carrier_records) log.info(">>> %s", '\n '.join(str(r) for r in hs_records)) self.select_carrier_lock.release() if self.options.delay: log.info("delay response for {0} ms".format(self.options.delay)) time.sleep(self.options.delay * 1e-3) return hs_records
def write_nfc_hs(clf, wait_remove=True): print("Write NFC Handover Select record on a tag") data = wpas_get_nfc_uri() if data is None: summary("Could not get NFC URI from wpa_supplicant") return global dpp_sel_wait_remove dpp_sel_wait_remove = wait_remove print("URI: %s" % data) uri = ndef.UriRecord(data) print(uri) carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) hs = ndef.HandoverSelectRecord('1.4') hs.add_alternative_carrier('active', carrier.name) print(hs) print(carrier) print("Touch an NFC tag") global dpp_tag_data dpp_tag_data = [hs, carrier] print(dpp_tag_data) clf.connect(rdwr={'on-connect': rdwr_connected_write_tag})
def process_handover_request_message(self, records): self.ho_server_processing = True clear_raw_mode() print("\nHandoverServer - request received: " + str(records)) carrier = None hs = ndef.HandoverSelectRecord('1.4') sel = [hs] found = False for carrier in records: if isinstance(carrier, ndef.HandoverRequestRecord): continue print("Remote carrier type: " + carrier.type) if carrier.type == "application/vnd.wfa.dpp": print("DPP carrier type match - add DPP carrier record") if len(carrier.data) == 0 or carrier.data[0] != 0: print("URI Identifier Code 'None' not seen") continue uri = carrier.data[1:].decode("utf-8") print("Received DPP URI: " + uri) data = wpas_get_nfc_uri(start_listen=False) print("Own URI (pre-processing): %s" % data) res = wpas_report_handover_req(uri) if res is None or "FAIL" in res: print("DPP handover request processing failed") continue found = True self.received_carrier = carrier wpas = wpas_connect() if wpas is None: continue global own_id data = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() if "FAIL" in data: continue print("Own URI (post-processing): %s" % data) uri = ndef.UriRecord(data) print("Own bootstrapping NFC URI record: " + str(uri)) info = wpas.request("DPP_BOOTSTRAP_INFO %d" % own_id) freq = None for line in info.splitlines(): if line.startswith("use_freq="): freq = int(line.split('=')[1]) if freq is None: print("No channel negotiated over NFC - use channel 1") freq = 2412 res = wpas.request("DPP_LISTEN %d" % freq) if "OK" not in res: print("Failed to start DPP listen") break carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) print("Own DPP carrier record: " + str(carrier)) hs.add_alternative_carrier('active', carrier.name) sel = [hs, carrier] break summary("Sending handover select: " + str(sel)) if found: self.success = True else: self.try_own = True return sel
def process_handover_request_message(self, records): self.ho_server_processing = True global in_raw_mode was_in_raw_mode = in_raw_mode clear_raw_mode() if was_in_raw_mode: print("\n") summary("HandoverServer - request received: " + str(records)) global my_crn, peer_crn, my_crn_ready for carrier in records: if not isinstance(carrier, ndef.HandoverRequestRecord): continue if carrier.collision_resolution_number: peer_crn = carrier.collision_resolution_number summary("peer_crn: %d" % peer_crn) if my_crn is None and my_crn_ready: summary( "Still trying to send own handover request - wait a moment to see if that succeeds before checking crn values" ) for i in range(10): if my_crn is not None: break time.sleep(0.01) if my_crn is not None: summary("my_crn: %d" % my_crn) if my_crn is not None and peer_crn is not None: if my_crn == peer_crn: summary( "Same crn used - automatic collision resolution failed") # TODO: Should generate a new Handover Request message return '' if ((my_crn & 1) == (peer_crn & 1) and my_crn > peer_crn) or \ ((my_crn & 1) != (peer_crn & 1) and my_crn < peer_crn): summary("I'm the Handover Selector Device") pass else: summary("Peer is the Handover Selector device") summary("Ignore the received request.") return '' hs = ndef.HandoverSelectRecord('1.4') sel = [hs] found = False for carrier in records: if isinstance(carrier, ndef.HandoverRequestRecord): continue summary("Remote carrier type: " + carrier.type) if carrier.type == "application/vnd.wfa.dpp": summary("DPP carrier type match - add DPP carrier record") if len(carrier.data) == 0 or carrier.data[0] != 0: summary("URI Identifier Code 'None' not seen") continue uri = carrier.data[1:].decode("utf-8") summary("Received DPP URI: " + uri) data = wpas_get_nfc_uri(start_listen=False, pick_channel=True) summary("Own URI (pre-processing): %s" % data) res = wpas_report_handover_req(uri) if res is None or "FAIL" in res: summary("DPP handover request processing failed") continue found = True wpas = wpas_connect() if wpas is None: continue global own_id data = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() if "FAIL" in data: continue summary("Own URI (post-processing): %s" % data) uri = ndef.UriRecord(data) summary("Own bootstrapping NFC URI record: " + str(uri)) info = wpas.request("DPP_BOOTSTRAP_INFO %d" % own_id) freq = None for line in info.splitlines(): if line.startswith("use_freq="): freq = int(line.split('=')[1]) if freq is None or freq == 0: summary("No channel negotiated over NFC - use channel 6") freq = 2437 else: summary("Negotiated channel: %d MHz" % freq) if get_status_field(wpas, "bssid[0]"): summary("Own AP freq: %s MHz" % str(get_status_field(wpas, "freq"))) if get_status_field(wpas, "beacon_set", extra="DRIVER") is None: summary("Enable beaconing to have radio ready for RX") wpas.request("DISABLE") wpas.request("SET start_disabled 0") wpas.request("ENABLE") cmd = "DPP_LISTEN %d" % freq global enrollee_only global configurator_only if enrollee_only: cmd += " role=enrollee" elif configurator_only: cmd += " role=configurator" summary(cmd) res = wpas.request(cmd) if "OK" not in res: summary("Failed to start DPP listen") break carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) summary("Own DPP carrier record: " + str(carrier)) hs.add_alternative_carrier('active', carrier.name) sel = [hs, carrier] break summary("Sending handover select: " + str(sel)) if found: self.success = True else: self.try_own = True global hs_sent hs_sent = True return sel
@pytest.mark.parametrize("encoded, message", handover_request_messages) def test_decode(self, encoded, message): octets = bytes(bytearray.fromhex(encoded)) print(list(ndef.message_decoder(octets))) assert list(ndef.message_decoder(octets)) == message @pytest.mark.parametrize("encoded, message", handover_request_messages) def test_encode(self, encoded, message): octets = bytes(bytearray.fromhex(encoded)) print(list(ndef.message_encoder(message))) assert b''.join(list(ndef.message_encoder(message))) == octets handover_select_messages = [ ('d102014873 13', [ndef.HandoverSelectRecord('1.3')]), ('d102094873 13 d1030265727201ff', [ndef.HandoverSelectRecord('1.3', (1, 255))]), ('91020a4873 13 d10204616301013100 5a030201612f62310001', [ndef.HandoverSelectRecord('1.3', None, (1, '1')), ndef.Record('a/b', '1', b'\x00\x01')]), ('9102124873 13 91020461630101310051030265727201ff 5a030201612f62310001', [ndef.HandoverSelectRecord('1.3', (1, 255), (1, '1')), ndef.Record('a/b', '1', b'\x00\x01')]), ] class TestHandoverSelectMessage: @pytest.mark.parametrize("encoded, message", handover_select_messages) def test_decode(self, encoded, message): octets = bytes(bytearray.fromhex(encoded))
def process_handover_request_message(self, records): handover = self.handover self.ho_server_processing = True global in_raw_mode was_in_raw_mode = in_raw_mode clear_raw_mode() if was_in_raw_mode: print("\n") summary("HandoverServer - request received: " + str(records)) for carrier in records: if not isinstance(carrier, ndef.HandoverRequestRecord): continue if carrier.collision_resolution_number: handover.peer_crn = carrier.collision_resolution_number summary("peer_crn: %d" % handover.peer_crn) if handover.my_crn is None and handover.my_crn_ready: summary("Still trying to send own handover request - wait a moment to see if that succeeds before checking crn values") for i in range(10): if handover.my_crn is not None: break time.sleep(0.01) if handover.my_crn is not None: summary("my_crn: %d" % handover.my_crn) if handover.my_crn is not None and handover.peer_crn is not None: if handover.my_crn == handover.peer_crn: summary("Same crn used - automatic collision resolution failed") # TODO: Should generate a new Handover Request message return '' if ((handover.my_crn & 1) == (handover.peer_crn & 1) and \ handover.my_crn > handover.peer_crn) or \ ((handover.my_crn & 1) != (handover.peer_crn & 1) and \ handover.my_crn < handover.peer_crn): summary("I'm the Handover Selector Device") handover.i_m_selector = True else: summary("Peer is the Handover Selector device") summary("Ignore the received request.") return '' hs = ndef.HandoverSelectRecord('1.4') sel = [hs] found = False for carrier in records: if isinstance(carrier, ndef.HandoverRequestRecord): continue summary("Remote carrier type: " + carrier.type) if carrier.type == "application/vnd.wfa.dpp": summary("DPP carrier type match - add DPP carrier record") if len(carrier.data) == 0 or carrier.data[0] != 0: summary("URI Identifier Code 'None' not seen", color=C_RED) continue uri = carrier.data[1:].decode("utf-8") summary("Received DPP URI: " + uri) global test_uri, test_alt_uri if test_uri: summary("TEST MODE: Using specified URI") data = test_sel_uri if test_sel_uri else test_uri elif handover.alt_proposal and handover.altchanlist: summary("Use alternative channel list while processing alternative proposal from peer") data = wpas_get_nfc_uri(start_listen=False, chan_override=handover.altchanlist, pick_channel=True) else: data = wpas_get_nfc_uri(start_listen=False, pick_channel=True) summary("Own URI (pre-processing): %s" % data) if test_uri: summary("TEST MODE: Fake processing") res = "OK" data += " [%s]" % uri else: res = wpas_report_handover_req(uri) if res is None or "FAIL" in res: summary("DPP handover request processing failed", color=C_RED) if handover.altchanlist: data = wpas_get_nfc_uri(start_listen=False, chan_override=handover.altchanlist) summary("Own URI (try another channel list): %s" % data) continue if test_alt_uri: summary("TEST MODE: Reject initial proposal") continue found = True if not test_uri: wpas = wpas_connect() if wpas is None: continue global own_id data = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() if "FAIL" in data: continue summary("Own URI (post-processing): %s" % data) handover.my_uri = data handover.peer_uri = uri uri = ndef.UriRecord(data) summary("Own bootstrapping NFC URI record: " + str(uri)) if not test_uri: info = wpas.request("DPP_BOOTSTRAP_INFO %d" % own_id) freq = None for line in info.splitlines(): if line.startswith("use_freq="): freq = int(line.split('=')[1]) if freq is None or freq == 0: summary("No channel negotiated over NFC - use channel 6") freq = 2437 else: summary("Negotiated channel: %d MHz" % freq) if not dpp_start_listen(wpas, freq): break carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) summary("Own DPP carrier record: " + str(carrier)) hs.add_alternative_carrier('active', carrier.name) sel = [hs, carrier] break summary("Sending handover select: " + str(sel)) if found: summary("Handover completed successfully") handover.terminate_on_hs_send_completion = True self.success = True handover.hs_sent = True handover.i_m_selector = True elif handover.no_alt_proposal: summary("Do not try alternative proposal anymore - handover failed", color=C_RED) handover.hs_sent = True else: summary("Try to initiate with alternative parameters") handover.try_own = True handover.hs_sent = False handover.no_alt_proposal = True if handover.client_thread: handover.start_client_alt = True else: handover.client_thread = threading.Thread(target=llcp_worker, args=(self.llc, True)) handover.client_thread.start() return sel