185732ac8SCy Schubert#!/usr/bin/python 285732ac8SCy Schubert# 385732ac8SCy Schubert# Example Android logcat to wpa_supplicant wrapper for QR Code scans 485732ac8SCy Schubert# Copyright (c) 2017, Qualcomm Atheros, Inc. 585732ac8SCy Schubert# 685732ac8SCy Schubert# This software may be distributed under the terms of the BSD license. 785732ac8SCy Schubert# See README for more details. 885732ac8SCy Schubert 985732ac8SCy Schubertimport os 1085732ac8SCy Schubertimport sys 1185732ac8SCy Schubertimport argparse 1285732ac8SCy Schubertimport logging 1385732ac8SCy Schubertimport qrcode 1485732ac8SCy Schubert 1585732ac8SCy Schubertscriptsdir = os.path.dirname(os.path.realpath(sys.modules[__name__].__file__)) 1685732ac8SCy Schubertsys.path.append(os.path.join(scriptsdir, '..', '..', 'wpaspy')) 1785732ac8SCy Schubert 1885732ac8SCy Schubertimport wpaspy 1985732ac8SCy Schubert 2085732ac8SCy Schubertwpas_ctrl = '/var/run/wpa_supplicant' 2185732ac8SCy Schubert 2285732ac8SCy Schubertdef wpas_connect(): 2385732ac8SCy Schubert ifaces = [] 2485732ac8SCy Schubert if os.path.isdir(wpas_ctrl): 2585732ac8SCy Schubert try: 2685732ac8SCy Schubert ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)] 27*4bc52338SCy Schubert except OSError as error: 28*4bc52338SCy Schubert print("Could not find wpa_supplicant: ", error) 2985732ac8SCy Schubert return None 3085732ac8SCy Schubert 3185732ac8SCy Schubert if len(ifaces) < 1: 32*4bc52338SCy Schubert print("No wpa_supplicant control interface found") 3385732ac8SCy Schubert return None 3485732ac8SCy Schubert 3585732ac8SCy Schubert for ctrl in ifaces: 3685732ac8SCy Schubert try: 3785732ac8SCy Schubert wpas = wpaspy.Ctrl(ctrl) 3885732ac8SCy Schubert return wpas 39*4bc52338SCy Schubert except Exception as e: 4085732ac8SCy Schubert pass 4185732ac8SCy Schubert return None 4285732ac8SCy Schubert 4385732ac8SCy Schubertdef dpp_logcat(): 4485732ac8SCy Schubert for line in iter(sys.stdin.readline, ''): 4585732ac8SCy Schubert if "ResultHandler: Launching intent: Intent" not in line: 4685732ac8SCy Schubert continue 4785732ac8SCy Schubert if "act=android.intent.action.VIEW" not in line: 4885732ac8SCy Schubert continue 4985732ac8SCy Schubert uri = None 5085732ac8SCy Schubert for val in line.split(' '): 5185732ac8SCy Schubert if val.startswith('dat='): 5285732ac8SCy Schubert uri = val.split('=', 1)[1] 5385732ac8SCy Schubert break 5485732ac8SCy Schubert if not uri: 5585732ac8SCy Schubert continue 5685732ac8SCy Schubert if not uri.startswith('DPP:'): 5785732ac8SCy Schubert continue 58*4bc52338SCy Schubert print("Found DPP bootstrap info URI:") 59*4bc52338SCy Schubert print(uri) 6085732ac8SCy Schubert wpas = wpas_connect() 6185732ac8SCy Schubert if not wpas: 62*4bc52338SCy Schubert print("Could not connect to wpa_supplicant") 63*4bc52338SCy Schubert print('') 6485732ac8SCy Schubert continue 6585732ac8SCy Schubert res = wpas.request("DPP_QR_CODE " + uri); 6685732ac8SCy Schubert try: 6785732ac8SCy Schubert id = int(res) 6885732ac8SCy Schubert except ValueError: 69*4bc52338SCy Schubert print("QR Code URI rejected") 7085732ac8SCy Schubert continue 71*4bc52338SCy Schubert print("QR Code URI accepted - ID=%d" % id) 72*4bc52338SCy Schubert print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id)) 7385732ac8SCy Schubert del wpas 7485732ac8SCy Schubert 7585732ac8SCy Schubertdef dpp_display(curve): 7685732ac8SCy Schubert wpas = wpas_connect() 7785732ac8SCy Schubert if not wpas: 78*4bc52338SCy Schubert print("Could not connect to wpa_supplicant") 7985732ac8SCy Schubert return 8085732ac8SCy Schubert res = wpas.request("STATUS") 8185732ac8SCy Schubert addr = None 8285732ac8SCy Schubert for line in res.splitlines(): 8385732ac8SCy Schubert if line.startswith("address="): 8485732ac8SCy Schubert addr = line.split('=')[1] 8585732ac8SCy Schubert break 8685732ac8SCy Schubert cmd = "DPP_BOOTSTRAP_GEN type=qrcode" 8785732ac8SCy Schubert cmd += " chan=81/1" 8885732ac8SCy Schubert if addr: 8985732ac8SCy Schubert cmd += " mac=" + addr.replace(':','') 9085732ac8SCy Schubert if curve: 9185732ac8SCy Schubert cmd += " curve=" + curve 9285732ac8SCy Schubert res = wpas.request(cmd) 9385732ac8SCy Schubert try: 9485732ac8SCy Schubert id = int(res) 9585732ac8SCy Schubert except ValueError: 96*4bc52338SCy Schubert print("Failed to generate bootstrap info URI") 9785732ac8SCy Schubert return 98*4bc52338SCy Schubert print("Bootstrap information - ID=%d" % id) 99*4bc52338SCy Schubert print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id)) 10085732ac8SCy Schubert uri = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % id) 101*4bc52338SCy Schubert print(uri) 102*4bc52338SCy Schubert print("ID=%d" % id) 10385732ac8SCy Schubert qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_M, 10485732ac8SCy Schubert border=3) 10585732ac8SCy Schubert qr.add_data(uri, optimize=5) 10685732ac8SCy Schubert qr.print_ascii(tty=True) 107*4bc52338SCy Schubert print("ID=%d" % id) 10885732ac8SCy Schubert del wpas 10985732ac8SCy Schubert 11085732ac8SCy Schubertdef main(): 11185732ac8SCy Schubert parser = argparse.ArgumentParser(description='Android logcat to wpa_supplicant integration for DPP QR Code operations') 11285732ac8SCy Schubert parser.add_argument('-d', const=logging.DEBUG, default=logging.INFO, 11385732ac8SCy Schubert action='store_const', dest='loglevel', 11485732ac8SCy Schubert help='verbose debug output') 11585732ac8SCy Schubert parser.add_argument('--curve', '-c', 11685732ac8SCy Schubert help='set a specific curve (P-256, P-384, P-521, BP-256R1, BP-384R1, BP-512R1) for key generation') 11785732ac8SCy Schubert parser.add_argument('command', choices=['logcat', 11885732ac8SCy Schubert 'display'], 11985732ac8SCy Schubert nargs='?') 12085732ac8SCy Schubert args = parser.parse_args() 12185732ac8SCy Schubert 12285732ac8SCy Schubert logging.basicConfig(level=args.loglevel) 12385732ac8SCy Schubert 12485732ac8SCy Schubert if args.command == "logcat": 12585732ac8SCy Schubert dpp_logcat() 12685732ac8SCy Schubert elif args.command == "display": 12785732ac8SCy Schubert dpp_display(args.curve) 12885732ac8SCy Schubert 12985732ac8SCy Schubertif __name__ == '__main__': 13085732ac8SCy Schubert main() 131