1#!/usr/bin/python 2# 3# Example Android logcat to wpa_supplicant wrapper for QR Code scans 4# Copyright (c) 2017, Qualcomm Atheros, Inc. 5# 6# This software may be distributed under the terms of the BSD license. 7# See README for more details. 8 9import os 10import sys 11import argparse 12import logging 13import qrcode 14 15scriptsdir = os.path.dirname(os.path.realpath(sys.modules[__name__].__file__)) 16sys.path.append(os.path.join(scriptsdir, '..', '..', 'wpaspy')) 17 18import wpaspy 19 20wpas_ctrl = '/var/run/wpa_supplicant' 21 22def wpas_connect(): 23 ifaces = [] 24 if os.path.isdir(wpas_ctrl): 25 try: 26 ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)] 27 except OSError as error: 28 print("Could not find wpa_supplicant: ", error) 29 return None 30 31 if len(ifaces) < 1: 32 print("No wpa_supplicant control interface found") 33 return None 34 35 for ctrl in ifaces: 36 try: 37 wpas = wpaspy.Ctrl(ctrl) 38 return wpas 39 except Exception as e: 40 pass 41 return None 42 43def dpp_logcat(): 44 for line in iter(sys.stdin.readline, ''): 45 if "ResultHandler: Launching intent: Intent" not in line: 46 continue 47 if "act=android.intent.action.VIEW" not in line: 48 continue 49 uri = None 50 for val in line.split(' '): 51 if val.startswith('dat='): 52 uri = val.split('=', 1)[1] 53 break 54 if not uri: 55 continue 56 if not uri.startswith('DPP:'): 57 continue 58 print("Found DPP bootstrap info URI:") 59 print(uri) 60 wpas = wpas_connect() 61 if not wpas: 62 print("Could not connect to wpa_supplicant") 63 print('') 64 continue 65 res = wpas.request("DPP_QR_CODE " + uri); 66 try: 67 id = int(res) 68 except ValueError: 69 print("QR Code URI rejected") 70 continue 71 print("QR Code URI accepted - ID=%d" % id) 72 print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id)) 73 del wpas 74 75def dpp_display(curve): 76 wpas = wpas_connect() 77 if not wpas: 78 print("Could not connect to wpa_supplicant") 79 return 80 res = wpas.request("STATUS") 81 addr = None 82 for line in res.splitlines(): 83 if line.startswith("address="): 84 addr = line.split('=')[1] 85 break 86 cmd = "DPP_BOOTSTRAP_GEN type=qrcode" 87 cmd += " chan=81/1" 88 if addr: 89 cmd += " mac=" + addr.replace(':','') 90 if curve: 91 cmd += " curve=" + curve 92 res = wpas.request(cmd) 93 try: 94 id = int(res) 95 except ValueError: 96 print("Failed to generate bootstrap info URI") 97 return 98 print("Bootstrap information - ID=%d" % id) 99 print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id)) 100 uri = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % id) 101 print(uri) 102 print("ID=%d" % id) 103 qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_M, 104 border=3) 105 qr.add_data(uri, optimize=5) 106 qr.print_ascii(tty=True) 107 print("ID=%d" % id) 108 del wpas 109 110def main(): 111 parser = argparse.ArgumentParser(description='Android logcat to wpa_supplicant integration for DPP QR Code operations') 112 parser.add_argument('-d', const=logging.DEBUG, default=logging.INFO, 113 action='store_const', dest='loglevel', 114 help='verbose debug output') 115 parser.add_argument('--curve', '-c', 116 help='set a specific curve (P-256, P-384, P-521, BP-256R1, BP-384R1, BP-512R1) for key generation') 117 parser.add_argument('command', choices=['logcat', 118 'display'], 119 nargs='?') 120 args = parser.parse_args() 121 122 logging.basicConfig(level=args.loglevel) 123 124 if args.command == "logcat": 125 dpp_logcat() 126 elif args.command == "display": 127 dpp_display(args.curve) 128 129if __name__ == '__main__': 130 main() 131