dpp-qrcode.py 4.0 KB

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