Updated through tag hostap_2_5 from git://w1.fi/hostap.git
[mech_eap.git] / libeap / tests / hwsim / test_ieee8021x.py
1 # IEEE 802.1X tests
2 # Copyright (c) 2013-2015, Jouni Malinen <j@w1.fi>
3 #
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
6
7 import binascii
8 import hmac
9 import logging
10 import time
11
12 import hostapd
13 import hwsim_utils
14 from utils import skip_with_fips
15
16 logger = logging.getLogger()
17
18 def test_ieee8021x_wep104(dev, apdev):
19     """IEEE 802.1X connection using dynamic WEP104"""
20     skip_with_fips(dev[0])
21     params = hostapd.radius_params()
22     params["ssid"] = "ieee8021x-wep"
23     params["ieee8021x"] = "1"
24     params["wep_key_len_broadcast"] = "13"
25     params["wep_key_len_unicast"] = "13"
26     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
27
28     dev[0].connect("ieee8021x-wep", key_mgmt="IEEE8021X", eap="PSK",
29                    identity="psk.user@example.com",
30                    password_hex="0123456789abcdef0123456789abcdef",
31                    scan_freq="2412")
32     hwsim_utils.test_connectivity(dev[0], hapd)
33
34 def test_ieee8021x_wep40(dev, apdev):
35     """IEEE 802.1X connection using dynamic WEP40"""
36     skip_with_fips(dev[0])
37     params = hostapd.radius_params()
38     params["ssid"] = "ieee8021x-wep"
39     params["ieee8021x"] = "1"
40     params["wep_key_len_broadcast"] = "5"
41     params["wep_key_len_unicast"] = "5"
42     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
43
44     dev[0].connect("ieee8021x-wep", key_mgmt="IEEE8021X", eap="PSK",
45                    identity="psk.user@example.com",
46                    password_hex="0123456789abcdef0123456789abcdef",
47                    scan_freq="2412")
48     hwsim_utils.test_connectivity(dev[0], hapd)
49
50 def test_ieee8021x_open(dev, apdev):
51     """IEEE 802.1X connection using open network"""
52     params = hostapd.radius_params()
53     params["ssid"] = "ieee8021x-open"
54     params["ieee8021x"] = "1"
55     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
56
57     id = dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
58                         eap="PSK", identity="psk.user@example.com",
59                         password_hex="0123456789abcdef0123456789abcdef",
60                         scan_freq="2412")
61     hwsim_utils.test_connectivity(dev[0], hapd)
62
63     logger.info("Test EAPOL-Logoff")
64     dev[0].request("LOGOFF")
65     ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
66     if ev is None:
67         raise Exception("Did not get disconnected")
68     if "reason=23" not in ev:
69         raise Exception("Unexpected disconnection reason")
70
71     dev[0].request("LOGON")
72     dev[0].connect_network(id)
73     hwsim_utils.test_connectivity(dev[0], hapd)
74
75 def test_ieee8021x_static_wep40(dev, apdev):
76     """IEEE 802.1X connection using static WEP40"""
77     params = hostapd.radius_params()
78     params["ssid"] = "ieee8021x-wep"
79     params["ieee8021x"] = "1"
80     params["wep_key0"] = '"hello"'
81     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
82
83     dev[0].connect("ieee8021x-wep", key_mgmt="IEEE8021X", eap="PSK",
84                    identity="psk.user@example.com",
85                    password_hex="0123456789abcdef0123456789abcdef",
86                    wep_key0='"hello"', eapol_flags="0",
87                    scan_freq="2412")
88     hwsim_utils.test_connectivity(dev[0], hapd)
89
90 def test_ieee8021x_proto(dev, apdev):
91     """IEEE 802.1X and EAPOL supplicant protocol testing"""
92     params = hostapd.radius_params()
93     params["ssid"] = "ieee8021x-open"
94     params["ieee8021x"] = "1"
95     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
96     bssid = apdev[0]['bssid']
97
98     dev[1].request("SET ext_eapol_frame_io 1")
99     dev[1].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
100                    eap="PSK", identity="psk.user@example.com",
101                    password_hex="0123456789abcdef0123456789abcdef",
102                    scan_freq="2412", wait_connect=False)
103     id = dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
104                         eap="PSK", identity="psk.user@example.com",
105                         password_hex="0123456789abcdef0123456789abcdef",
106                         scan_freq="2412")
107     ev = dev[1].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
108
109     start = dev[0].get_mib()
110
111     tests = [ "11",
112               "11223344",
113               "020000050a93000501",
114               "020300050a93000501",
115               "0203002c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
116               "0203002c0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
117               "0203002c0100050000000000000000000000000000000000000000000000000000000000000000000000000000000000",
118               "02aa00050a93000501" ]
119     for frame in tests:
120         res = dev[0].request("EAPOL_RX " + bssid + " " + frame)
121         if "OK" not in res:
122             raise Exception("EAPOL_RX to wpa_supplicant failed")
123         dev[1].request("EAPOL_RX " + bssid + " " + frame)
124
125     stop = dev[0].get_mib()
126
127     logger.info("MIB before test frames: " + str(start))
128     logger.info("MIB after test frames: " + str(stop))
129
130     vals = [ 'dot1xSuppInvalidEapolFramesRx',
131              'dot1xSuppEapLengthErrorFramesRx' ]
132     for val in vals:
133         if int(stop[val]) <= int(start[val]):
134             raise Exception(val + " did not increase")
135
136 def test_ieee8021x_eapol_start(dev, apdev):
137     """IEEE 802.1X and EAPOL-Start retransmissions"""
138     params = hostapd.radius_params()
139     params["ssid"] = "ieee8021x-open"
140     params["ieee8021x"] = "1"
141     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
142     bssid = apdev[0]['bssid']
143     addr0 = dev[0].own_addr()
144
145     hapd.set("ext_eapol_frame_io", "1")
146     try:
147         dev[0].request("SET EAPOL::startPeriod 1")
148         dev[0].request("SET EAPOL::maxStart 1")
149         dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
150                        eap="PSK", identity="psk.user@example.com",
151                        password_hex="0123456789abcdef0123456789abcdef",
152                        scan_freq="2412", wait_connect=False)
153         held = False
154         for i in range(30):
155             pae = dev[0].get_status_field('Supplicant PAE state')
156             if pae == "HELD":
157                 mib = hapd.get_sta(addr0, info="eapol")
158                 if mib['auth_pae_state'] != 'AUTHENTICATING':
159                     raise Exception("Unexpected Auth PAE state: " + mib['auth_pae_state'])
160                 held = True
161                 break
162             time.sleep(0.25)
163         if not held:
164             raise Exception("PAE state HELD not reached")
165         dev[0].wait_disconnected()
166     finally:
167         dev[0].request("SET EAPOL::startPeriod 30")
168         dev[0].request("SET EAPOL::maxStart 3")
169
170 def test_ieee8021x_held(dev, apdev):
171     """IEEE 802.1X and HELD state"""
172     params = hostapd.radius_params()
173     params["ssid"] = "ieee8021x-open"
174     params["ieee8021x"] = "1"
175     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
176     bssid = apdev[0]['bssid']
177
178     hapd.set("ext_eapol_frame_io", "1")
179     try:
180         dev[0].request("SET EAPOL::startPeriod 1")
181         dev[0].request("SET EAPOL::maxStart 0")
182         dev[0].request("SET EAPOL::heldPeriod 1")
183         dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
184                        eap="PSK", identity="psk.user@example.com",
185                        password_hex="0123456789abcdef0123456789abcdef",
186                        scan_freq="2412", wait_connect=False)
187         held = False
188         for i in range(30):
189             pae = dev[0].get_status_field('Supplicant PAE state')
190             if pae == "HELD":
191                 held = True
192                 break
193             time.sleep(0.25)
194         if not held:
195             raise Exception("PAE state HELD not reached")
196
197         hapd.set("ext_eapol_frame_io", "0")
198         for i in range(30):
199             pae = dev[0].get_status_field('Supplicant PAE state')
200             if pae != "HELD":
201                 held = False
202                 break
203             time.sleep(0.25)
204         if held:
205             raise Exception("PAE state HELD not left")
206         ev = dev[0].wait_event([ "CTRL-EVENT-CONNECTED",
207                                  "CTRL-EVENT-DISCONNECTED" ], timeout=10)
208         if ev is None:
209             raise Exception("Connection timed out")
210         if "CTRL-EVENT-DISCONNECTED" in ev:
211             raise Exception("Unexpected disconnection")
212     finally:
213         dev[0].request("SET EAPOL::startPeriod 30")
214         dev[0].request("SET EAPOL::maxStart 3")
215         dev[0].request("SET EAPOL::heldPeriod 60")
216
217 def send_eapol_key(dev, bssid, signkey, frame_start, frame_end):
218     zero_sign = "00000000000000000000000000000000"
219     frame = frame_start + zero_sign + frame_end
220     hmac_obj = hmac.new(binascii.unhexlify(signkey))
221     hmac_obj.update(binascii.unhexlify(frame))
222     sign = hmac_obj.digest()
223     frame = frame_start + binascii.hexlify(sign) + frame_end
224     dev.request("EAPOL_RX " + bssid + " " + frame)
225
226 def test_ieee8021x_eapol_key(dev, apdev):
227     """IEEE 802.1X connection and EAPOL-Key protocol tests"""
228     skip_with_fips(dev[0])
229     params = hostapd.radius_params()
230     params["ssid"] = "ieee8021x-wep"
231     params["ieee8021x"] = "1"
232     params["wep_key_len_broadcast"] = "5"
233     params["wep_key_len_unicast"] = "5"
234     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
235     bssid = apdev[0]['bssid']
236
237     dev[0].connect("ieee8021x-wep", key_mgmt="IEEE8021X", eap="VENDOR-TEST",
238                    identity="vendor-test", scan_freq="2412")
239
240     # Hardcoded MSK from VENDOR-TEST
241     encrkey = "1111111111111111111111111111111111111111111111111111111111111111"
242     signkey = "2222222222222222222222222222222222222222222222222222222222222222"
243
244     # EAPOL-Key replay counter does not increase
245     send_eapol_key(dev[0], bssid, signkey,
246                    "02030031" + "010005" + "0000000000000000" + "056c22d109f29d4d9fb9b9ccbad33283" + "02",
247                    "1c636a30a4")
248
249     # EAPOL-Key too large Key Length field value
250     send_eapol_key(dev[0], bssid, signkey,
251                    "02030031" + "010021" + "ffffffffffffffff" + "056c22d109f29d4d9fb9b9ccbad33283" + "02",
252                    "1c636a30a4")
253
254     # EAPOL-Key too much key data
255     send_eapol_key(dev[0], bssid, signkey,
256                    "0203004d" + "010005" + "ffffffffffffffff" + "056c22d109f29d4d9fb9b9ccbad33283" + "02",
257                    33*"ff")
258
259     # EAPOL-Key too little key data
260     send_eapol_key(dev[0], bssid, signkey,
261                    "02030030" + "010005" + "ffffffffffffffff" + "056c22d109f29d4d9fb9b9ccbad33283" + "02",
262                    "1c636a30")
263
264     # EAPOL-Key with no key data and too long WEP key length
265     send_eapol_key(dev[0], bssid, signkey,
266                    "0203002c" + "010020" + "ffffffffffffffff" + "056c22d109f29d4d9fb9b9ccbad33283" + "02",
267                    "")
268
269 def test_ieee8021x_reauth(dev, apdev):
270     """IEEE 802.1X and EAPOL_REAUTH request"""
271     params = hostapd.radius_params()
272     params["ssid"] = "ieee8021x-open"
273     params["ieee8021x"] = "1"
274     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
275
276     dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
277                    eap="PSK", identity="psk.user@example.com",
278                    password_hex="0123456789abcdef0123456789abcdef",
279                    scan_freq="2412")
280
281     hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
282     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
283     if ev is None:
284         raise Exception("EAP authentication did not start")
285     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
286     if ev is None:
287         raise Exception("EAP authentication did not succeed")
288     time.sleep(0.1)
289     hwsim_utils.test_connectivity(dev[0], hapd)
290
291 def test_ieee8021x_set_conf(dev, apdev):
292     """IEEE 802.1X and EAPOL_SET command"""
293     params = hostapd.radius_params()
294     params["ssid"] = "ieee8021x-open"
295     params["ieee8021x"] = "1"
296     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
297
298     dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
299                    eap="PSK", identity="psk.user@example.com",
300                    password_hex="0123456789abcdef0123456789abcdef",
301                    scan_freq="2412")
302
303     addr0 = dev[0].own_addr()
304     tests = [ "EAPOL_SET 1",
305               "EAPOL_SET %sfoo bar" % addr0,
306               "EAPOL_SET %s foo" % addr0,
307               "EAPOL_SET %s foo bar" % addr0,
308               "EAPOL_SET %s AdminControlledDirections bar" % addr0,
309               "EAPOL_SET %s AdminControlledPortControl bar" % addr0,
310               "EAPOL_SET %s reAuthEnabled bar" % addr0,
311               "EAPOL_SET %s KeyTransmissionEnabled bar" % addr0,
312               "EAPOL_SET 11:22:33:44:55:66 AdminControlledDirections Both" ]
313     for t in tests:
314         if "FAIL" not in hapd.request(t):
315             raise Exception("Invalid EAPOL_SET command accepted: " + t)
316
317     tests = [ ("AdminControlledDirections", "adminControlledDirections", "In"),
318               ("AdminControlledDirections", "adminControlledDirections",
319                "Both"),
320               ("quietPeriod", "quietPeriod", "13"),
321               ("serverTimeout", "serverTimeout", "7"),
322               ("reAuthPeriod", "reAuthPeriod", "1234"),
323               ("reAuthEnabled", "reAuthEnabled", "FALSE"),
324               ("reAuthEnabled", "reAuthEnabled", "TRUE"),
325               ("KeyTransmissionEnabled", "keyTxEnabled", "TRUE"),
326               ("KeyTransmissionEnabled", "keyTxEnabled", "FALSE"),
327               ("AdminControlledPortControl", "portControl", "ForceAuthorized"),
328               ("AdminControlledPortControl", "portControl",
329                "ForceUnauthorized"),
330               ("AdminControlledPortControl", "portControl", "Auto") ]
331     for param,mibparam,val in tests:
332         if "OK" not in hapd.request("EAPOL_SET %s %s %s" % (addr0, param, val)):
333             raise Exception("Failed to set %s %s" % (param, val))
334         mib = hapd.get_sta(addr0, info="eapol")
335         if mib[mibparam] != val:
336             raise Exception("Unexpected %s value: %s (expected %s)" % (param, mib[mibparam], val))
337     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
338     if ev is None:
339         raise Exception("EAP authentication did not succeed")
340     time.sleep(0.1)
341     hwsim_utils.test_connectivity(dev[0], hapd)
342
343 def test_ieee8021x_auth_awhile(dev, apdev):
344     """IEEE 802.1X and EAPOL Authenticator aWhile handling"""
345     params = hostapd.radius_params()
346     params["ssid"] = "ieee8021x-open"
347     params["ieee8021x"] = "1"
348     params['auth_server_port'] = "18129"
349     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
350     bssid = apdev[0]['bssid']
351     addr0 = dev[0].own_addr()
352
353     params = {}
354     params['ssid'] = 'as'
355     params['beacon_int'] = '2000'
356     params['radius_server_clients'] = 'auth_serv/radius_clients.conf'
357     params['radius_server_auth_port'] = '18129'
358     params['eap_server'] = '1'
359     params['eap_user_file'] = 'auth_serv/eap_user.conf'
360     params['ca_cert'] = 'auth_serv/ca.pem'
361     params['server_cert'] = 'auth_serv/server.pem'
362     params['private_key'] = 'auth_serv/server.key'
363     hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
364
365     dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
366                    eap="PSK", identity="psk.user@example.com",
367                    password_hex="0123456789abcdef0123456789abcdef",
368                    scan_freq="2412")
369     hapd1.disable()
370     if "OK" not in hapd.request("EAPOL_SET %s serverTimeout 1" % addr0):
371         raise Exception("Failed to set serverTimeout")
372     hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
373     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
374
375     for i in range(40):
376         mib = hapd.get_sta(addr0, info="eapol")
377         val = int(mib['aWhile'])
378         if val > 0:
379             break
380         time.sleep(1)
381     if val == 0:
382         raise Exception("aWhile did not increase")
383
384     hapd.dump_monitor()
385     for i in range(40):
386         mib = hapd.get_sta(addr0, info="eapol")
387         val = int(mib['aWhile'])
388         if val < 5:
389             break
390         time.sleep(1)
391     ev = hapd.wait_event(["CTRL-EVENT-EAP-PROPOSED"], timeout=10)
392     if ev is None:
393         raise Exception("Authentication restart not seen")