blob: b468d15cf9cde3cdf449add71371be3751fdfee3 [file] [log] [blame]
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001#!/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)]
Hai Shalom74f70d42019-02-11 14:42:39 -080027 except OSError as error:
28 print("Could not find wpa_supplicant: ", error)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070029 return None
30
31 if len(ifaces) < 1:
Hai Shalom74f70d42019-02-11 14:42:39 -080032 print("No wpa_supplicant control interface found")
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070033 return None
34
35 for ctrl in ifaces:
36 try:
37 wpas = wpaspy.Ctrl(ctrl)
38 return wpas
Hai Shalom74f70d42019-02-11 14:42:39 -080039 except Exception as e:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070040 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
Hai Shalom74f70d42019-02-11 14:42:39 -080058 print("Found DPP bootstrap info URI:")
59 print(uri)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070060 wpas = wpas_connect()
61 if not wpas:
Hai Shalom74f70d42019-02-11 14:42:39 -080062 print("Could not connect to wpa_supplicant")
63 print('')
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070064 continue
65 res = wpas.request("DPP_QR_CODE " + uri);
66 try:
67 id = int(res)
68 except ValueError:
Hai Shalom74f70d42019-02-11 14:42:39 -080069 print("QR Code URI rejected")
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070070 continue
Hai Shalom74f70d42019-02-11 14:42:39 -080071 print("QR Code URI accepted - ID=%d" % id)
72 print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070073 del wpas
74
75def dpp_display(curve):
76 wpas = wpas_connect()
77 if not wpas:
Hai Shalom74f70d42019-02-11 14:42:39 -080078 print("Could not connect to wpa_supplicant")
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070079 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:
Hai Shalom74f70d42019-02-11 14:42:39 -080096 print("Failed to generate bootstrap info URI")
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070097 return
Hai Shalom74f70d42019-02-11 14:42:39 -080098 print("Bootstrap information - ID=%d" % id)
99 print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700100 uri = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % id)
Hai Shalom74f70d42019-02-11 14:42:39 -0800101 print(uri)
102 print("ID=%d" % id)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700103 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)
Hai Shalom74f70d42019-02-11 14:42:39 -0800107 print("ID=%d" % id)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700108 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()