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