eapol_test.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #!/usr/bin/env python2
  2. #
  3. # eapol_test controller
  4. # Copyright (c) 2015, Jouni Malinen <j@w1.fi>
  5. #
  6. # This software may be distributed under the terms of the BSD license.
  7. # See README for more details.
  8. import argparse
  9. import logging
  10. import os
  11. import Queue
  12. import sys
  13. import threading
  14. logger = logging.getLogger()
  15. dir = os.path.dirname(os.path.realpath(sys.modules[__name__].__file__))
  16. sys.path.append(os.path.join(dir, '..', 'wpaspy'))
  17. import wpaspy
  18. wpas_ctrl = '/tmp/eapol_test'
  19. class eapol_test:
  20. def __init__(self, ifname):
  21. self.ifname = ifname
  22. self.ctrl = wpaspy.Ctrl(os.path.join(wpas_ctrl, ifname))
  23. if "PONG" not in self.ctrl.request("PING"):
  24. raise Exception("Failed to connect to eapol_test (%s)" % ifname)
  25. self.mon = wpaspy.Ctrl(os.path.join(wpas_ctrl, ifname))
  26. self.mon.attach()
  27. def add_network(self):
  28. id = self.request("ADD_NETWORK")
  29. if "FAIL" in id:
  30. raise Exception("ADD_NETWORK failed")
  31. return int(id)
  32. def remove_network(self, id):
  33. id = self.request("REMOVE_NETWORK " + str(id))
  34. if "FAIL" in id:
  35. raise Exception("REMOVE_NETWORK failed")
  36. return None
  37. def set_network(self, id, field, value):
  38. res = self.request("SET_NETWORK " + str(id) + " " + field + " " + value)
  39. if "FAIL" in res:
  40. raise Exception("SET_NETWORK failed")
  41. return None
  42. def set_network_quoted(self, id, field, value):
  43. res = self.request("SET_NETWORK " + str(id) + " " + field + ' "' + value + '"')
  44. if "FAIL" in res:
  45. raise Exception("SET_NETWORK failed")
  46. return None
  47. def request(self, cmd, timeout=10):
  48. return self.ctrl.request(cmd, timeout=timeout)
  49. def wait_event(self, events, timeout=10):
  50. start = os.times()[4]
  51. while True:
  52. while self.mon.pending():
  53. ev = self.mon.recv()
  54. logger.debug(self.ifname + ": " + ev)
  55. for event in events:
  56. if event in ev:
  57. return ev
  58. now = os.times()[4]
  59. remaining = start + timeout - now
  60. if remaining <= 0:
  61. break
  62. if not self.mon.pending(timeout=remaining):
  63. break
  64. return None
  65. def run(ifname, count, no_fast_reauth, res):
  66. et = eapol_test(ifname)
  67. et.request("AP_SCAN 0")
  68. if no_fast_reauth:
  69. et.request("SET fast_reauth 0")
  70. else:
  71. et.request("SET fast_reauth 1")
  72. id = et.add_network()
  73. et.set_network(id, "key_mgmt", "IEEE8021X")
  74. et.set_network(id, "eapol_flags", "0")
  75. et.set_network(id, "eap", "TLS")
  76. et.set_network_quoted(id, "identity", "user")
  77. et.set_network_quoted(id, "ca_cert", 'ca.pem')
  78. et.set_network_quoted(id, "client_cert", 'client.pem')
  79. et.set_network_quoted(id, "private_key", 'client.key')
  80. et.set_network_quoted(id, "private_key_passwd", 'whatever')
  81. et.set_network(id, "disabled", "0")
  82. fail = False
  83. for i in range(count):
  84. et.request("REASSOCIATE")
  85. ev = et.wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-EAP-FAILURE"])
  86. if ev is None or "CTRL-EVENT-CONNECTED" not in ev:
  87. fail = True
  88. break
  89. et.remove_network(id)
  90. if fail:
  91. res.put("FAIL (%d OK)" % i)
  92. else:
  93. res.put("PASS %d" % (i + 1))
  94. def main():
  95. parser = argparse.ArgumentParser(description='eapol_test controller')
  96. parser.add_argument('--ctrl', help='control interface directory')
  97. parser.add_argument('--num', help='number of processes')
  98. parser.add_argument('--iter', help='number of iterations')
  99. parser.add_argument('--no-fast-reauth', action='store_true',
  100. dest='no_fast_reauth',
  101. help='disable TLS session resumption')
  102. args = parser.parse_args()
  103. num = int(args.num)
  104. iter = int(args.iter)
  105. if args.ctrl:
  106. global wpas_ctrl
  107. wpas_ctrl = args.ctrl
  108. t = {}
  109. res = {}
  110. for i in range(num):
  111. res[i] = Queue.Queue()
  112. t[i] = threading.Thread(target=run, args=(str(i), iter,
  113. args.no_fast_reauth, res[i]))
  114. for i in range(num):
  115. t[i].start()
  116. for i in range(num):
  117. t[i].join()
  118. try:
  119. results = res[i].get(False)
  120. except:
  121. results = "N/A"
  122. print "%d: %s" % (i, results)
  123. if __name__ == "__main__":
  124. main()