xref: /freebsd-src/contrib/wpa/wpa_supplicant/examples/dpp-qrcode.py (revision 7648bc9fee8dec6cb3c4941e0165a930fbe8dcb0)
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