1f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt#!/usr/bin/python 2f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt# 3f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt# Example nfcpy to hostapd wrapper for WPS NFC operations 4f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt# Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi> 5f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt# 6f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt# This software may be distributed under the terms of the BSD license. 7f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt# See README for more details. 8f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 9f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtimport os 10f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtimport sys 11f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtimport time 12cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtimport argparse 13f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 14f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtimport nfc 15f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtimport nfc.ndef 16f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtimport nfc.llcp 17f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtimport nfc.handover 18f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 19f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtimport logging 20f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 21700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidtimport wpaspy 22f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 23f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtwpas_ctrl = '/var/run/hostapd' 24cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtcontinue_loop = True 2596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidtsummary_file = None 2696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidtsuccess_file = None 2796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt 2896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidtdef summary(txt): 2996be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt print txt 3096be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt if summary_file: 3196be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt with open(summary_file, 'a') as f: 3296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt f.write(txt + "\n") 3396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt 3496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidtdef success_report(txt): 3596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary(txt) 3696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt if success_file: 3796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt with open(success_file, 'a') as f: 3896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt f.write(txt + "\n") 39f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 40f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtdef wpas_connect(): 41f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt ifaces = [] 42f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if os.path.isdir(wpas_ctrl): 43f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt try: 44f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)] 45f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt except OSError, error: 46f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt print "Could not find hostapd: ", error 47f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return None 48f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 49f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if len(ifaces) < 1: 50f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt print "No hostapd control interface found" 51f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return None 52f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 53f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt for ctrl in ifaces: 54f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt try: 55700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt wpas = wpaspy.Ctrl(ctrl) 56f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return wpas 57700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt except Exception, e: 58f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt pass 59f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return None 60f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 61f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 62f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtdef wpas_tag_read(message): 63f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpas = wpas_connect() 64f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (wpas == None): 6596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt return False 66cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if "FAIL" in wpas.request("WPS_NFC_TAG_READ " + str(message).encode("hex")): 67cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return False 68cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return True 69f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 70f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 71f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtdef wpas_get_config_token(): 72f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpas = wpas_connect() 73f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (wpas == None): 74f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return None 7596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt ret = wpas.request("WPS_NFC_CONFIG_TOKEN NDEF") 7696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt if "FAIL" in ret: 7796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt return None 7896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt return ret.rstrip().decode("hex") 79f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 80f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 81f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtdef wpas_get_password_token(): 82f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpas = wpas_connect() 83f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (wpas == None): 84f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return None 8596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt ret = wpas.request("WPS_NFC_TOKEN NDEF") 8696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt if "FAIL" in ret: 8796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt return None 8896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt return ret.rstrip().decode("hex") 89f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 90f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 91f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtdef wpas_get_handover_sel(): 92f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpas = wpas_connect() 93f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (wpas == None): 94f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return None 9596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt ret = wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR") 9696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt if "FAIL" in ret: 9796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt return None 9896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt return ret.rstrip().decode("hex") 99f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 100f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 101f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtdef wpas_report_handover(req, sel): 102f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpas = wpas_connect() 103f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (wpas == None): 104f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return None 105f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return wpas.request("NFC_REPORT_HANDOVER RESP WPS " + 106f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt str(req).encode("hex") + " " + 107f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt str(sel).encode("hex")) 108f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 109f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 110f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtclass HandoverServer(nfc.handover.HandoverServer): 111cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt def __init__(self, llc): 112cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt super(HandoverServer, self).__init__(llc) 113cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt self.ho_server_processing = False 114cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt self.success = False 115f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 11696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt # override to avoid parser error in request/response.pretty() in nfcpy 11796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt # due to new WSC handover format 11896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt def _process_request(self, request): 11996be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("received handover request {}".format(request.type)) 12096be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt response = nfc.ndef.Message("\xd1\x02\x01Hs\x12") 12196be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt if not request.type == 'urn:nfc:wkt:Hr': 12296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("not a handover request") 12396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt else: 12496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt try: 12596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt request = nfc.ndef.HandoverRequestMessage(request) 12696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt except nfc.ndef.DecodeError as e: 12796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("error decoding 'Hr' message: {}".format(e)) 12896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt else: 12996be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt response = self.process_request(request) 13096be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("send handover response {}".format(response.type)) 13196be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt return response 13296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt 133f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt def process_request(self, request): 13496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("HandoverServer - request received") 135cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt try: 136cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print "Parsed handover request: " + request.pretty() 137cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt except Exception, e: 138cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print e 139cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print str(request).encode("hex") 140f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 141f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt sel = nfc.ndef.HandoverSelectMessage(version="1.2") 142f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 143f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt for carrier in request.carriers: 144f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt print "Remote carrier type: " + carrier.type 145f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if carrier.type == "application/vnd.wfa.wsc": 14696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("WPS carrier type match - add WPS carrier record") 147f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt data = wpas_get_handover_sel() 148f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if data is None: 14996be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("Could not get handover select carrier record from hostapd") 150f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt continue 151f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt print "Handover select carrier record from hostapd:" 152f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt print data.encode("hex") 15396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt if "OK" in wpas_report_handover(carrier.record, data): 15496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt success_report("Handover reported successfully") 15596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt else: 15696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("Handover report rejected") 157f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 158f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt message = nfc.ndef.Message(data); 159f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt sel.add_carrier(message[0], "active", message[1:]) 160f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 161f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt print "Handover select:" 162cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt try: 163cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print sel.pretty() 164cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt except Exception, e: 165cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print e 166f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt print str(sel).encode("hex") 167f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 16896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("Sending handover select") 169cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt self.success = True 170f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return sel 171f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 172f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 173f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtdef wps_tag_read(tag): 174cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt success = False 175f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if len(tag.ndef.message): 176cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt for record in tag.ndef.message: 177f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt print "record type " + record.type 178f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if record.type == "application/vnd.wfa.wsc": 17996be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("WPS tag - send to hostapd") 180cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt success = wpas_tag_read(tag.ndef.message) 181f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt break 182f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt else: 18396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("Empty tag") 18496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt 18596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt if success: 18696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt success_report("Tag read succeeded") 187f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 188cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return success 189f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 190f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 191cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtdef rdwr_connected_write(tag): 19296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("Tag found - writing - " + str(tag)) 193cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global write_data 194cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt tag.ndef.message = str(write_data) 19596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt success_report("Tag write succeeded") 196cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print "Done - remove tag" 197cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global only_one 198cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if only_one: 199cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global continue_loop 200cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt continue_loop = False 201cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global write_wait_remove 202cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt while write_wait_remove and tag.is_present: 203cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt time.sleep(0.1) 204cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 205cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtdef wps_write_config_tag(clf, wait_remove=True): 20696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("Write WPS config token") 207cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global write_data, write_wait_remove 208cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt write_wait_remove = wait_remove 209cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt write_data = wpas_get_config_token() 210cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if write_data == None: 21196be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("Could not get WPS config token from hostapd") 212f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return 213f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 214f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt print "Touch an NFC tag" 215cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt clf.connect(rdwr={'on-connect': rdwr_connected_write}) 216f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 217f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 218cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtdef wps_write_password_tag(clf, wait_remove=True): 21996be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("Write WPS password token") 220cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global write_data, write_wait_remove 221cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt write_wait_remove = wait_remove 222cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt write_data = wpas_get_password_token() 223cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if write_data == None: 22496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("Could not get WPS password token from hostapd") 225f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return 226f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 227f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt print "Touch an NFC tag" 228cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt clf.connect(rdwr={'on-connect': rdwr_connected_write}) 229f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 230f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 231cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtdef rdwr_connected(tag): 232cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global only_one, no_wait 23396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("Tag connected: " + str(tag)) 234cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 235cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if tag.ndef: 236cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print "NDEF tag: " + tag.type 237cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt try: 238cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print tag.ndef.message.pretty() 239cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt except Exception, e: 240cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print e 241cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt success = wps_tag_read(tag) 242cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if only_one and success: 243cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global continue_loop 244cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt continue_loop = False 245cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt else: 24696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary("Not an NDEF tag - remove tag") 24796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt return True 248f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 249cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return not no_wait 250cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 251cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 252cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtdef llcp_startup(clf, llc): 253cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print "Start LLCP server" 254cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global srv 255cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt srv = HandoverServer(llc) 256cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return llc 257cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 258cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtdef llcp_connected(llc): 259cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print "P2P LLCP connected" 260cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global wait_connection 261cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wait_connection = False 262cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global srv 263cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt srv.start() 264cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return True 265f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 266f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 267f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtdef main(): 268f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt clf = nfc.ContactlessFrontend() 269f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 270cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt parser = argparse.ArgumentParser(description='nfcpy to hostapd integration for WPS NFC operations') 271cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt parser.add_argument('-d', const=logging.DEBUG, default=logging.INFO, 272cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt action='store_const', dest='loglevel', 273cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt help='verbose debug output') 274cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt parser.add_argument('-q', const=logging.WARNING, action='store_const', 275cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dest='loglevel', help='be quiet') 276cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt parser.add_argument('--only-one', '-1', action='store_true', 277cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt help='run only one operation and exit') 278cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt parser.add_argument('--no-wait', action='store_true', 279cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt help='do not wait for tag to be removed before exiting') 28096be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt parser.add_argument('--summary', 28196be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt help='summary file for writing status updates') 28296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt parser.add_argument('--success', 28396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt help='success file for writing success update') 284cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt parser.add_argument('command', choices=['write-config', 285cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 'write-password'], 286cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt nargs='?') 287cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt args = parser.parse_args() 288cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 289cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global only_one 290cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt only_one = args.only_one 291cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 292cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global no_wait 293cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt no_wait = args.no_wait 294cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 29596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt if args.summary: 29696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt global summary_file 29796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt summary_file = args.summary 29896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt 29996be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt if args.success: 30096be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt global success_file 30196be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt success_file = args.success 30296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt 303cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt logging.basicConfig(level=args.loglevel) 304cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 305f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt try: 306cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if not clf.open("usb"): 307cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print "Could not open connection with an NFC device" 308f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt raise SystemExit 309f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 310cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if args.command == "write-config": 311cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_write_config_tag(clf, wait_remove=not args.no_wait) 312f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt raise SystemExit 313f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 314cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if args.command == "write-password": 315cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_write_password_tag(clf, wait_remove=not args.no_wait) 316cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt raise SystemExit 317f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 318cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global continue_loop 319cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt while continue_loop: 320cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print "Waiting for a tag or peer to be touched" 321cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wait_connection = True 322cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt try: 323cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if not clf.connect(rdwr={'on-connect': rdwr_connected}, 324cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt llcp={'on-startup': llcp_startup, 325cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 'on-connect': llcp_connected}): 326cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt break 327cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt except Exception, e: 328cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt print "clf.connect failed" 329cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 330cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt global srv 331cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if only_one and srv and srv.success: 332cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt raise SystemExit 333f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 334f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt except KeyboardInterrupt: 335f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt raise SystemExit 336f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt finally: 337f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt clf.close() 338f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 339f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt raise SystemExit 340f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 341f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtif __name__ == '__main__': 342f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt main() 343