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