1 # WPA2-Enterprise PMKSA caching tests
2 # Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi>
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
8 logger = logging.getLogger()
13 from wpasupplicant import WpaSupplicant
14 from utils import alloc_fail
15 from test_ap_eap import eap_connect
17 def test_pmksa_cache_on_roam_back(dev, apdev):
18 """PMKSA cache to skip EAP on reassociation back to same AP"""
19 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
20 hostapd.add_ap(apdev[0]['ifname'], params)
21 bssid = apdev[0]['bssid']
22 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
23 eap="GPSK", identity="gpsk user",
24 password="abcdefghijklmnop0123456789abcdef",
26 pmksa = dev[0].get_pmksa(bssid)
28 raise Exception("No PMKSA cache entry created")
29 if pmksa['opportunistic'] != '0':
30 raise Exception("Unexpected opportunistic PMKSA cache entry")
32 hostapd.add_ap(apdev[1]['ifname'], params)
33 bssid2 = apdev[1]['bssid']
36 logger.info("Roam to AP2")
37 # It can take some time for the second AP to become ready to reply to Probe
38 # Request frames especially under heavy CPU load, so allow couple of rounds
39 # of scanning to avoid reporting errors incorrectly just because of scans
40 # not having seen the target AP.
41 for i in range(0, 10):
42 dev[0].scan(freq="2412")
43 if dev[0].get_bss(bssid2) is not None:
45 logger.info("Scan again to find target AP")
46 dev[0].request("ROAM " + bssid2)
47 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
49 raise Exception("EAP success timed out")
50 dev[0].wait_connected(timeout=10, error="Roaming timed out")
51 pmksa2 = dev[0].get_pmksa(bssid2)
53 raise Exception("No PMKSA cache entry found")
54 if pmksa2['opportunistic'] != '0':
55 raise Exception("Unexpected opportunistic PMKSA cache entry")
58 logger.info("Roam back to AP1")
59 dev[0].scan(freq="2412")
60 dev[0].request("ROAM " + bssid)
61 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
62 "CTRL-EVENT-CONNECTED"], timeout=10)
64 raise Exception("Roaming with the AP timed out")
65 if "CTRL-EVENT-EAP-STARTED" in ev:
66 raise Exception("Unexpected EAP exchange")
67 pmksa1b = dev[0].get_pmksa(bssid)
69 raise Exception("No PMKSA cache entry found")
70 if pmksa['pmkid'] != pmksa1b['pmkid']:
71 raise Exception("Unexpected PMKID change for AP1")
74 if "FAIL" in dev[0].request("PMKSA_FLUSH"):
75 raise Exception("PMKSA_FLUSH failed")
76 if dev[0].get_pmksa(bssid) is not None or dev[0].get_pmksa(bssid2) is not None:
77 raise Exception("PMKSA_FLUSH did not remove PMKSA entries")
78 dev[0].wait_disconnected(timeout=5)
79 dev[0].wait_connected(timeout=15, error="Reconnection timed out")
81 def test_pmksa_cache_opportunistic_only_on_sta(dev, apdev):
82 """Opportunistic PMKSA caching enabled only on station"""
83 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
84 hostapd.add_ap(apdev[0]['ifname'], params)
85 bssid = apdev[0]['bssid']
86 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
87 eap="GPSK", identity="gpsk user",
88 password="abcdefghijklmnop0123456789abcdef", okc=True,
90 pmksa = dev[0].get_pmksa(bssid)
92 raise Exception("No PMKSA cache entry created")
93 if pmksa['opportunistic'] != '0':
94 raise Exception("Unexpected opportunistic PMKSA cache entry")
96 hostapd.add_ap(apdev[1]['ifname'], params)
97 bssid2 = apdev[1]['bssid']
100 logger.info("Roam to AP2")
101 dev[0].scan(freq="2412")
102 dev[0].request("ROAM " + bssid2)
103 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
105 raise Exception("EAP success timed out")
106 dev[0].wait_connected(timeout=10, error="Roaming timed out")
107 pmksa2 = dev[0].get_pmksa(bssid2)
109 raise Exception("No PMKSA cache entry found")
110 if pmksa2['opportunistic'] != '0':
111 raise Exception("Unexpected opportunistic PMKSA cache entry")
113 dev[0].dump_monitor()
114 logger.info("Roam back to AP1")
115 dev[0].scan(freq="2412")
116 dev[0].request("ROAM " + bssid)
117 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
118 "CTRL-EVENT-CONNECTED"], timeout=10)
120 raise Exception("Roaming with the AP timed out")
121 if "CTRL-EVENT-EAP-STARTED" in ev:
122 raise Exception("Unexpected EAP exchange")
123 pmksa1b = dev[0].get_pmksa(bssid)
125 raise Exception("No PMKSA cache entry found")
126 if pmksa['pmkid'] != pmksa1b['pmkid']:
127 raise Exception("Unexpected PMKID change for AP1")
129 def test_pmksa_cache_opportunistic(dev, apdev):
130 """Opportunistic PMKSA caching"""
131 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
133 hostapd.add_ap(apdev[0]['ifname'], params)
134 bssid = apdev[0]['bssid']
135 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
136 eap="GPSK", identity="gpsk user",
137 password="abcdefghijklmnop0123456789abcdef", okc=True,
139 pmksa = dev[0].get_pmksa(bssid)
141 raise Exception("No PMKSA cache entry created")
142 if pmksa['opportunistic'] != '0':
143 raise Exception("Unexpected opportunistic PMKSA cache entry")
145 hostapd.add_ap(apdev[1]['ifname'], params)
146 bssid2 = apdev[1]['bssid']
148 dev[0].dump_monitor()
149 logger.info("Roam to AP2")
150 dev[0].scan(freq="2412")
151 dev[0].request("ROAM " + bssid2)
152 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
153 "CTRL-EVENT-CONNECTED"], timeout=10)
155 raise Exception("Roaming with the AP timed out")
156 if "CTRL-EVENT-EAP-STARTED" in ev:
157 raise Exception("Unexpected EAP exchange")
158 pmksa2 = dev[0].get_pmksa(bssid2)
160 raise Exception("No PMKSA cache entry created")
162 dev[0].dump_monitor()
163 logger.info("Roam back to AP1")
164 dev[0].scan(freq="2412")
165 dev[0].request("ROAM " + bssid)
166 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
167 "CTRL-EVENT-CONNECTED"], timeout=10)
169 raise Exception("Roaming with the AP timed out")
170 if "CTRL-EVENT-EAP-STARTED" in ev:
171 raise Exception("Unexpected EAP exchange")
173 pmksa1b = dev[0].get_pmksa(bssid)
175 raise Exception("No PMKSA cache entry found")
176 if pmksa['pmkid'] != pmksa1b['pmkid']:
177 raise Exception("Unexpected PMKID change for AP1")
179 def test_pmksa_cache_opportunistic_connect(dev, apdev):
180 """Opportunistic PMKSA caching with connect API"""
181 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
183 hostapd.add_ap(apdev[0]['ifname'], params)
184 bssid = apdev[0]['bssid']
185 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
186 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
187 wpas.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
188 eap="GPSK", identity="gpsk user",
189 password="abcdefghijklmnop0123456789abcdef", okc=True,
191 pmksa = wpas.get_pmksa(bssid)
193 raise Exception("No PMKSA cache entry created")
194 if pmksa['opportunistic'] != '0':
195 raise Exception("Unexpected opportunistic PMKSA cache entry")
197 hostapd.add_ap(apdev[1]['ifname'], params)
198 bssid2 = apdev[1]['bssid']
201 logger.info("Roam to AP2")
202 wpas.scan_for_bss(bssid2, freq="2412")
203 wpas.request("ROAM " + bssid2)
204 ev = wpas.wait_event(["CTRL-EVENT-EAP-STARTED",
205 "CTRL-EVENT-CONNECTED"], timeout=10)
207 raise Exception("Roaming with the AP timed out")
208 if "CTRL-EVENT-EAP-STARTED" in ev:
209 raise Exception("Unexpected EAP exchange")
210 pmksa2 = wpas.get_pmksa(bssid2)
212 raise Exception("No PMKSA cache entry created")
215 logger.info("Roam back to AP1")
216 wpas.scan(freq="2412")
217 wpas.request("ROAM " + bssid)
218 ev = wpas.wait_event(["CTRL-EVENT-EAP-STARTED",
219 "CTRL-EVENT-CONNECTED"], timeout=10)
221 raise Exception("Roaming with the AP timed out")
222 if "CTRL-EVENT-EAP-STARTED" in ev:
223 raise Exception("Unexpected EAP exchange")
225 pmksa1b = wpas.get_pmksa(bssid)
227 raise Exception("No PMKSA cache entry found")
228 if pmksa['pmkid'] != pmksa1b['pmkid']:
229 raise Exception("Unexpected PMKID change for AP1")
231 def test_pmksa_cache_expiration(dev, apdev):
232 """PMKSA cache entry expiration"""
233 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
234 hostapd.add_ap(apdev[0]['ifname'], params)
235 bssid = apdev[0]['bssid']
236 dev[0].request("SET dot11RSNAConfigPMKLifetime 10")
237 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
238 eap="GPSK", identity="gpsk user",
239 password="abcdefghijklmnop0123456789abcdef",
241 pmksa = dev[0].get_pmksa(bssid)
243 raise Exception("No PMKSA cache entry created")
244 logger.info("Wait for PMKSA cache entry to expire")
245 ev = dev[0].wait_event(["WPA: Key negotiation completed",
246 "CTRL-EVENT-DISCONNECTED"], timeout=15)
248 raise Exception("No EAP reauthentication seen")
249 if "CTRL-EVENT-DISCONNECTED" in ev:
250 raise Exception("Unexpected disconnection")
251 pmksa2 = dev[0].get_pmksa(bssid)
252 if pmksa['pmkid'] == pmksa2['pmkid']:
253 raise Exception("PMKID did not change")
255 def test_pmksa_cache_expiration_disconnect(dev, apdev):
256 """PMKSA cache entry expiration (disconnect)"""
257 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
258 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
259 bssid = apdev[0]['bssid']
260 dev[0].request("SET dot11RSNAConfigPMKLifetime 2")
261 dev[0].request("SET dot11RSNAConfigPMKReauthThreshold 100")
262 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
263 eap="GPSK", identity="gpsk user",
264 password="abcdefghijklmnop0123456789abcdef",
266 pmksa = dev[0].get_pmksa(bssid)
268 raise Exception("No PMKSA cache entry created")
269 hapd.request("SET auth_server_shared_secret incorrect")
270 logger.info("Wait for PMKSA cache entry to expire")
271 ev = dev[0].wait_event(["WPA: Key negotiation completed",
272 "CTRL-EVENT-DISCONNECTED"], timeout=15)
274 raise Exception("No EAP reauthentication seen")
275 if "CTRL-EVENT-DISCONNECTED" not in ev:
276 raise Exception("Missing disconnection")
277 hapd.request("SET auth_server_shared_secret radius")
278 ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=15)
280 raise Exception("No EAP reauthentication seen")
281 pmksa2 = dev[0].get_pmksa(bssid)
282 if pmksa['pmkid'] == pmksa2['pmkid']:
283 raise Exception("PMKID did not change")
285 def test_pmksa_cache_and_cui(dev, apdev):
286 """PMKSA cache and Chargeable-User-Identity"""
287 params = hostapd.wpa2_eap_params(ssid="cui")
288 params['radius_request_cui'] = '1'
289 params['acct_server_addr'] = "127.0.0.1"
290 params['acct_server_port'] = "1813"
291 params['acct_server_shared_secret'] = "radius"
292 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
293 bssid = apdev[0]['bssid']
294 dev[0].connect("cui", proto="RSN", key_mgmt="WPA-EAP",
295 eap="GPSK", identity="gpsk-cui",
296 password="abcdefghijklmnop0123456789abcdef",
298 pmksa = dev[0].get_pmksa(bssid)
300 raise Exception("No PMKSA cache entry created")
301 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
303 raise Exception("No connection event received from hostapd")
305 dev[0].dump_monitor()
306 logger.info("Disconnect and reconnect to the same AP")
307 dev[0].request("DISCONNECT")
308 dev[0].wait_disconnected()
309 dev[0].request("RECONNECT")
310 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
311 "CTRL-EVENT-CONNECTED"], timeout=10)
313 raise Exception("Reconnect timed out")
314 if "CTRL-EVENT-EAP-STARTED" in ev:
315 raise Exception("Unexpected EAP exchange")
316 pmksa1b = dev[0].get_pmksa(bssid)
318 raise Exception("No PMKSA cache entry found")
319 if pmksa['pmkid'] != pmksa1b['pmkid']:
320 raise Exception("Unexpected PMKID change for AP1")
322 dev[0].request("REAUTHENTICATE")
323 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
325 raise Exception("EAP success timed out")
326 for i in range(0, 20):
327 state = dev[0].get_status_field("wpa_state")
328 if state == "COMPLETED":
331 if state != "COMPLETED":
332 raise Exception("Reauthentication did not complete")
334 def test_pmksa_cache_preauth(dev, apdev):
335 """RSN pre-authentication to generate PMKSA cache entry"""
337 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
338 params['bridge'] = 'ap-br0'
339 hostapd.add_ap(apdev[0]['ifname'], params)
340 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
341 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
342 eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
343 password_hex="0123456789abcdef0123456789abcdef")
345 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
346 params['bridge'] = 'ap-br0'
347 params['rsn_preauth'] = '1'
348 params['rsn_preauth_interfaces'] = 'ap-br0'
349 hostapd.add_ap(apdev[1]['ifname'], params)
350 bssid1 = apdev[1]['bssid']
351 dev[0].scan(freq="2412")
354 for i in range(0, 50):
356 status = dev[0].request("STATUS")
357 if "Pre-authentication EAPOL state machines:" in status:
360 pmksa = dev[0].get_pmksa(bssid1)
365 raise Exception("No PMKSA cache entry created from pre-authentication")
367 raise Exception("Pre-authentication EAPOL status was not available")
369 dev[0].scan(freq="2412")
370 if "[WPA2-EAP-CCMP-preauth]" not in dev[0].request("SCAN_RESULTS"):
371 raise Exception("Scan results missing RSN element info")
372 dev[0].request("ROAM " + bssid1)
373 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
374 "CTRL-EVENT-CONNECTED"], timeout=10)
376 raise Exception("Roaming with the AP timed out")
377 if "CTRL-EVENT-EAP-STARTED" in ev:
378 raise Exception("Unexpected EAP exchange")
379 pmksa2 = dev[0].get_pmksa(bssid1)
381 raise Exception("No PMKSA cache entry")
382 if pmksa['pmkid'] != pmksa2['pmkid']:
383 raise Exception("Unexpected PMKID change")
386 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
387 subprocess.call(['brctl', 'delbr', 'ap-br0'])
389 def test_pmksa_cache_preauth_vlan_enabled(dev, apdev):
390 """RSN pre-authentication to generate PMKSA cache entry (dynamic_vlan optional but station without VLAN set)"""
392 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
393 params['bridge'] = 'ap-br0'
394 params['dynamic_vlan'] = '1'
395 hostapd.add_ap(apdev[0]['ifname'], params)
396 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
397 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
398 eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
399 password_hex="0123456789abcdef0123456789abcdef")
401 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
402 params['bridge'] = 'ap-br0'
403 params['rsn_preauth'] = '1'
404 params['rsn_preauth_interfaces'] = 'ap-br0'
405 params['dynamic_vlan'] = '1'
406 hostapd.add_ap(apdev[1]['ifname'], params)
407 bssid1 = apdev[1]['bssid']
408 dev[0].scan(freq="2412")
411 for i in range(0, 50):
413 status = dev[0].request("STATUS")
414 if "Pre-authentication EAPOL state machines:" in status:
417 pmksa = dev[0].get_pmksa(bssid1)
422 raise Exception("No PMKSA cache entry created from pre-authentication")
424 raise Exception("Pre-authentication EAPOL status was not available")
426 dev[0].scan(freq="2412")
427 if "[WPA2-EAP-CCMP-preauth]" not in dev[0].request("SCAN_RESULTS"):
428 raise Exception("Scan results missing RSN element info")
429 dev[0].request("ROAM " + bssid1)
430 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
431 "CTRL-EVENT-CONNECTED"], timeout=10)
433 raise Exception("Roaming with the AP timed out")
434 if "CTRL-EVENT-EAP-STARTED" in ev:
435 raise Exception("Unexpected EAP exchange")
436 pmksa2 = dev[0].get_pmksa(bssid1)
438 raise Exception("No PMKSA cache entry")
439 if pmksa['pmkid'] != pmksa2['pmkid']:
440 raise Exception("Unexpected PMKID change")
443 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
444 subprocess.call(['brctl', 'delbr', 'ap-br0'])
446 def test_pmksa_cache_preauth_vlan_used(dev, apdev):
447 """RSN pre-authentication to generate PMKSA cache entry (station with VLAN set)"""
449 subprocess.call(['brctl', 'addbr', 'brvlan1'])
450 subprocess.call(['brctl', 'setfd', 'brvlan1', '0'])
451 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
452 params['bridge'] = 'ap-br0'
453 params['dynamic_vlan'] = '1'
454 params['vlan_file'] = 'hostapd.wlan3.vlan'
455 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
456 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
457 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
458 eap_connect(dev[0], apdev[0], "PAX", "vlan1",
459 password_hex="0123456789abcdef0123456789abcdef")
461 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
462 params['bridge'] = 'ap-br0'
463 params['rsn_preauth'] = '1'
464 params['rsn_preauth_interfaces'] = 'brvlan1'
465 params['dynamic_vlan'] = '1'
466 params['vlan_file'] = 'hostapd.wlan4.vlan'
467 hostapd.add_ap(apdev[1]['ifname'], params)
468 bssid1 = apdev[1]['bssid']
469 dev[0].scan(freq="2412")
472 for i in range(0, 50):
474 status = dev[0].request("STATUS")
475 if "Pre-authentication EAPOL state machines:" in status:
478 pmksa = dev[0].get_pmksa(bssid1)
483 raise Exception("No PMKSA cache entry created from pre-authentication")
485 raise Exception("Pre-authentication EAPOL status was not available")
487 dev[0].scan(freq="2412")
488 if "[WPA2-EAP-CCMP-preauth]" not in dev[0].request("SCAN_RESULTS"):
489 raise Exception("Scan results missing RSN element info")
490 dev[0].request("ROAM " + bssid1)
491 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
492 "CTRL-EVENT-CONNECTED"], timeout=10)
494 raise Exception("Roaming with the AP timed out")
495 if "CTRL-EVENT-EAP-STARTED" in ev:
496 raise Exception("Unexpected EAP exchange")
497 pmksa2 = dev[0].get_pmksa(bssid1)
499 raise Exception("No PMKSA cache entry")
500 if pmksa['pmkid'] != pmksa2['pmkid']:
501 raise Exception("Unexpected PMKID change")
503 # Disconnect the STA from both APs to avoid forceful ifdown by the
504 # test script on a VLAN that this has an associated STA. That used to
505 # trigger a mac80211 warning.
506 dev[0].request("DISCONNECT")
507 hapd.request("DISABLE")
510 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
511 stderr=open('/dev/null', 'w'))
512 subprocess.call(['ip', 'link', 'set', 'dev', 'brvlan1', 'down'])
513 subprocess.call(['ip', 'link', 'set', 'dev', 'wlan3.1', 'down'],
514 stderr=open('/dev/null', 'w'))
515 subprocess.call(['ip', 'link', 'set', 'dev', 'wlan4.1', 'down'],
516 stderr=open('/dev/null', 'w'))
517 subprocess.call(['brctl', 'delif', 'brvlan1', 'wlan3.1'],
518 stderr=open('/dev/null', 'w'))
519 subprocess.call(['brctl', 'delif', 'brvlan1', 'wlan4.1'],
520 stderr=open('/dev/null', 'w'))
521 subprocess.call(['brctl', 'delbr', 'ap-br0'],
522 stderr=open('/dev/null', 'w'))
523 subprocess.call(['brctl', 'delbr', 'brvlan1'])
525 def test_pmksa_cache_disabled(dev, apdev):
526 """PMKSA cache disabling on AP"""
527 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
528 params['disable_pmksa_caching'] = '1'
529 hostapd.add_ap(apdev[0]['ifname'], params)
530 bssid = apdev[0]['bssid']
531 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
532 eap="GPSK", identity="gpsk user",
533 password="abcdefghijklmnop0123456789abcdef",
536 hostapd.add_ap(apdev[1]['ifname'], params)
537 bssid2 = apdev[1]['bssid']
539 dev[0].dump_monitor()
540 logger.info("Roam to AP2")
541 dev[0].scan_for_bss(bssid2, freq="2412")
542 dev[0].request("ROAM " + bssid2)
543 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
545 raise Exception("EAP success timed out")
546 dev[0].wait_connected(timeout=10, error="Roaming timed out")
548 dev[0].dump_monitor()
549 logger.info("Roam back to AP1")
550 dev[0].scan(freq="2412")
551 dev[0].request("ROAM " + bssid)
552 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
553 "CTRL-EVENT-CONNECTED"], timeout=20)
555 raise Exception("Roaming with the AP timed out")
556 if "CTRL-EVENT-CONNECTED" in ev:
557 raise Exception("EAP exchange missing")
558 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=20)
560 raise Exception("Roaming with the AP timed out")
562 def test_pmksa_cache_ap_expiration(dev, apdev):
563 """PMKSA cache entry expiring on AP"""
564 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
565 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
566 bssid = apdev[0]['bssid']
567 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
568 eap="GPSK", identity="gpsk-user-session-timeout",
569 password="abcdefghijklmnop0123456789abcdef",
571 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
573 raise Exception("No connection event received from hostapd")
574 dev[0].request("DISCONNECT")
576 dev[0].dump_monitor()
577 dev[0].request("RECONNECT")
578 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
579 "CTRL-EVENT-CONNECTED"], timeout=20)
581 raise Exception("Roaming with the AP timed out")
582 if "CTRL-EVENT-CONNECTED" in ev:
583 raise Exception("EAP exchange missing")
584 dev[0].wait_connected(timeout=20, error="Reconnect timed out")
585 dev[0].dump_monitor()
586 dev[0].wait_disconnected(timeout=20)
587 dev[0].wait_connected(timeout=20, error="Reassociation timed out")
589 def test_pmksa_cache_multiple_sta(dev, apdev):
590 """PMKSA cache with multiple stations"""
591 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
592 hostapd.add_ap(apdev[0]['ifname'], params)
593 bssid = apdev[0]['bssid']
594 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
595 eap="GPSK", identity="gpsk-user-session-timeout",
596 password="abcdefghijklmnop0123456789abcdef",
598 dev[1].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
599 eap="GPSK", identity="gpsk user",
600 password="abcdefghijklmnop0123456789abcdef",
602 dev[2].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
603 eap="GPSK", identity="gpsk-user-session-timeout",
604 password="abcdefghijklmnop0123456789abcdef",
607 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
608 wpas.interface_add("wlan5")
609 wpas.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
610 eap="GPSK", identity="gpsk user",
611 password="abcdefghijklmnop0123456789abcdef",
614 hostapd.add_ap(apdev[1]['ifname'], params)
615 bssid2 = apdev[1]['bssid']
617 logger.info("Roam to AP2")
618 for sta in [ dev[1], dev[0], dev[2], wpas ]:
620 sta.scan_for_bss(bssid2, freq="2412")
621 sta.request("ROAM " + bssid2)
622 ev = sta.wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
624 raise Exception("EAP success timed out")
625 sta.wait_connected(timeout=10, error="Roaming timed out")
627 logger.info("Roam back to AP1")
628 for sta in [ dev[1], wpas, dev[0], dev[2] ]:
630 sta.scan(freq="2412")
632 sta.request("ROAM " + bssid)
633 sta.wait_connected(timeout=10, error="Roaming timed out")
638 logger.info("Roam back to AP2")
639 for sta in [ dev[1], wpas, dev[0], dev[2] ]:
641 sta.scan(freq="2412")
643 sta.request("ROAM " + bssid2)
644 sta.wait_connected(timeout=10, error="Roaming timed out")
647 def test_pmksa_cache_opportunistic_multiple_sta(dev, apdev):
648 """Opportunistic PMKSA caching with multiple stations"""
649 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
651 hostapd.add_ap(apdev[0]['ifname'], params)
652 bssid = apdev[0]['bssid']
653 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
654 wpas.interface_add("wlan5")
655 for sta in [ dev[0], dev[1], dev[2], wpas ]:
656 sta.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
657 eap="GPSK", identity="gpsk user",
658 password="abcdefghijklmnop0123456789abcdef", okc=True,
661 hostapd.add_ap(apdev[1]['ifname'], params)
662 bssid2 = apdev[1]['bssid']
664 logger.info("Roam to AP2")
665 for sta in [ dev[2], dev[0], wpas, dev[1] ]:
667 sta.scan_for_bss(bssid2, freq="2412")
668 if "OK" not in sta.request("ROAM " + bssid2):
669 raise Exception("ROAM command failed")
670 ev = sta.wait_event(["CTRL-EVENT-EAP-STARTED",
671 "CTRL-EVENT-CONNECTED"], timeout=10)
673 raise Exception("Roaming with the AP timed out")
674 if "CTRL-EVENT-EAP-STARTED" in ev:
675 raise Exception("Unexpected EAP exchange")
676 pmksa2 = sta.get_pmksa(bssid2)
678 raise Exception("No PMKSA cache entry created")
680 logger.info("Roam back to AP1")
681 for sta in [ dev[0], dev[1], dev[2], wpas ]:
683 sta.scan_for_bss(bssid, freq="2412")
684 sta.request("ROAM " + bssid)
685 ev = sta.wait_event(["CTRL-EVENT-EAP-STARTED",
686 "CTRL-EVENT-CONNECTED"], timeout=10)
688 raise Exception("Roaming with the AP timed out")
689 if "CTRL-EVENT-EAP-STARTED" in ev:
690 raise Exception("Unexpected EAP exchange")
692 def test_pmksa_cache_preauth_oom(dev, apdev):
693 """RSN pre-authentication to generate PMKSA cache entry and OOM"""
695 _test_pmksa_cache_preauth_oom(dev, apdev)
697 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
698 subprocess.call(['brctl', 'delbr', 'ap-br0'])
700 def _test_pmksa_cache_preauth_oom(dev, apdev):
701 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
702 params['bridge'] = 'ap-br0'
703 hostapd.add_ap(apdev[0]['ifname'], params)
704 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
705 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
706 eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
707 password_hex="0123456789abcdef0123456789abcdef",
708 bssid=apdev[0]['bssid'])
710 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
711 params['bridge'] = 'ap-br0'
712 params['rsn_preauth'] = '1'
713 params['rsn_preauth_interfaces'] = 'ap-br0'
714 hapd = hostapd.add_ap(apdev[1]['ifname'], params)
715 bssid1 = apdev[1]['bssid']
717 tests = [ (1, "rsn_preauth_receive"),
718 (2, "rsn_preauth_receive"),
719 (1, "rsn_preauth_send") ]
721 with alloc_fail(hapd, test[0], test[1]):
722 dev[0].scan_for_bss(bssid1, freq="2412")
723 if "OK" not in dev[0].request("PREAUTH " + bssid1):
724 raise Exception("PREAUTH failed")
730 pmksa = dev[0].get_pmksa(bssid1)
734 state = hapd.request('GET_ALLOC_FAIL')
735 if state.startswith('0:'):
739 logger.info("PMKSA cache success: " + str(success))
741 dev[0].request("PMKSA_FLUSH")
742 dev[0].wait_disconnected()
743 dev[0].wait_connected()
744 dev[0].dump_monitor()
746 def test_pmksa_cache_size_limit(dev, apdev):
747 """PMKSA cache size limit in wpa_supplicant"""
749 _test_pmksa_cache_size_limit(dev, apdev)
752 hapd = hostapd.HostapdGlobal()
754 hapd.remove(apdev[0]['ifname'])
757 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
758 bssid = apdev[0]['bssid']
759 params['bssid'] = bssid
760 hostapd.add_ap(apdev[0]['ifname'], params)
762 def _test_pmksa_cache_size_limit(dev, apdev):
763 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
764 id = dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
765 eap="GPSK", identity="gpsk user",
766 password="abcdefghijklmnop0123456789abcdef",
767 scan_freq="2412", only_add_network=True)
769 bssid = apdev[0]['bssid'][0:15] + "%02x" % i
770 logger.info("Iteration with BSSID " + bssid)
771 params['bssid'] = bssid
772 hostapd.add_ap(apdev[0]['ifname'], params)
773 dev[0].request("BSS_FLUSH 0")
774 dev[0].scan_for_bss(bssid, freq=2412, only_new=True)
775 dev[0].select_network(id)
776 dev[0].wait_connected()
777 dev[0].request("DISCONNECT")
778 dev[0].wait_disconnected()
779 dev[0].dump_monitor()
780 entries = len(dev[0].request("PMKSA").splitlines()) - 1
783 raise Exception("Unexpected number of PMKSA entries after expected removal of the oldest entry")
784 elif i + 1 != entries:
785 raise Exception("Unexpected number of PMKSA entries")
787 hapd = hostapd.HostapdGlobal()
789 hapd.remove(apdev[0]['ifname'])
791 def test_pmksa_cache_preauth_timeout(dev, apdev):
792 """RSN pre-authentication timing out"""
794 _test_pmksa_cache_preauth_timeout(dev, apdev)
796 dev[0].request("SET dot11RSNAConfigSATimeout 60")
798 def _test_pmksa_cache_preauth_timeout(dev, apdev):
799 dev[0].request("SET dot11RSNAConfigSATimeout 1")
800 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
801 hostapd.add_ap(apdev[0]['ifname'], params)
802 eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
803 password_hex="0123456789abcdef0123456789abcdef",
804 bssid=apdev[0]['bssid'])
805 if "OK" not in dev[0].request("PREAUTH f2:11:22:33:44:55"):
806 raise Exception("PREAUTH failed")
807 ev = dev[0].wait_event(["RSN: pre-authentication with"], timeout=5)
809 raise Exception("No timeout event seen")
810 if "timed out" not in ev:
811 raise Exception("Unexpected event: " + ev)
813 def test_pmksa_cache_preauth_wpas_oom(dev, apdev):
814 """RSN pre-authentication OOM in wpa_supplicant"""
815 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
816 hostapd.add_ap(apdev[0]['ifname'], params)
817 eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
818 password_hex="0123456789abcdef0123456789abcdef",
819 bssid=apdev[0]['bssid'])
820 for i in range(1, 11):
821 with alloc_fail(dev[0], i, "rsn_preauth_init"):
822 res = dev[0].request("PREAUTH f2:11:22:33:44:55").strip()
823 logger.info("Iteration %d - PREAUTH command results: %s" % (i, res))
825 state = dev[0].request('GET_ALLOC_FAIL')
826 if state.startswith('0:'):