test_ieee8021x.py 16 KB

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