Beispiel #1
0
    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
Beispiel #3
0
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})
Beispiel #4
0
    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
Beispiel #5
0
    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
Beispiel #6
0
    @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))
Beispiel #7
0
    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