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 test_ap_eap import eap_connect
16 def test_pmksa_cache_on_roam_back(dev, apdev):
17 """PMKSA cache to skip EAP on reassociation back to same AP"""
18 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
19 hostapd.add_ap(apdev[0]['ifname'], params)
20 bssid = apdev[0]['bssid']
21 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
22 eap="GPSK", identity="gpsk user",
23 password="abcdefghijklmnop0123456789abcdef",
25 pmksa = dev[0].get_pmksa(bssid)
27 raise Exception("No PMKSA cache entry created")
28 if pmksa['opportunistic'] != '0':
29 raise Exception("Unexpected opportunistic PMKSA cache entry")
31 hostapd.add_ap(apdev[1]['ifname'], params)
32 bssid2 = apdev[1]['bssid']
35 logger.info("Roam to AP2")
36 # It can take some time for the second AP to become ready to reply to Probe
37 # Request frames especially under heavy CPU load, so allow couple of rounds
38 # of scanning to avoid reporting errors incorrectly just because of scans
39 # not having seen the target AP.
40 for i in range(0, 10):
41 dev[0].scan(freq="2412")
42 if dev[0].get_bss(bssid2) is not None:
44 logger.info("Scan again to find target AP")
45 dev[0].request("ROAM " + bssid2)
46 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
48 raise Exception("EAP success timed out")
49 dev[0].wait_connected(timeout=10, error="Roaming timed out")
50 pmksa2 = dev[0].get_pmksa(bssid2)
52 raise Exception("No PMKSA cache entry found")
53 if pmksa2['opportunistic'] != '0':
54 raise Exception("Unexpected opportunistic PMKSA cache entry")
57 logger.info("Roam back to AP1")
58 dev[0].scan(freq="2412")
59 dev[0].request("ROAM " + bssid)
60 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
61 "CTRL-EVENT-CONNECTED"], timeout=10)
63 raise Exception("Roaming with the AP timed out")
64 if "CTRL-EVENT-EAP-STARTED" in ev:
65 raise Exception("Unexpected EAP exchange")
66 pmksa1b = dev[0].get_pmksa(bssid)
68 raise Exception("No PMKSA cache entry found")
69 if pmksa['pmkid'] != pmksa1b['pmkid']:
70 raise Exception("Unexpected PMKID change for AP1")
73 if "FAIL" in dev[0].request("PMKSA_FLUSH"):
74 raise Exception("PMKSA_FLUSH failed")
75 if dev[0].get_pmksa(bssid) is not None or dev[0].get_pmksa(bssid2) is not None:
76 raise Exception("PMKSA_FLUSH did not remove PMKSA entries")
77 dev[0].wait_disconnected(timeout=5)
78 dev[0].wait_connected(timeout=15, error="Reconnection timed out")
80 def test_pmksa_cache_opportunistic_only_on_sta(dev, apdev):
81 """Opportunistic PMKSA caching enabled only on station"""
82 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
83 hostapd.add_ap(apdev[0]['ifname'], params)
84 bssid = apdev[0]['bssid']
85 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
86 eap="GPSK", identity="gpsk user",
87 password="abcdefghijklmnop0123456789abcdef", okc=True,
89 pmksa = dev[0].get_pmksa(bssid)
91 raise Exception("No PMKSA cache entry created")
92 if pmksa['opportunistic'] != '0':
93 raise Exception("Unexpected opportunistic PMKSA cache entry")
95 hostapd.add_ap(apdev[1]['ifname'], params)
96 bssid2 = apdev[1]['bssid']
99 logger.info("Roam to AP2")
100 dev[0].scan(freq="2412")
101 dev[0].request("ROAM " + bssid2)
102 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
104 raise Exception("EAP success timed out")
105 dev[0].wait_connected(timeout=10, error="Roaming timed out")
106 pmksa2 = dev[0].get_pmksa(bssid2)
108 raise Exception("No PMKSA cache entry found")
109 if pmksa2['opportunistic'] != '0':
110 raise Exception("Unexpected opportunistic PMKSA cache entry")
112 dev[0].dump_monitor()
113 logger.info("Roam back to AP1")
114 dev[0].scan(freq="2412")
115 dev[0].request("ROAM " + bssid)
116 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
117 "CTRL-EVENT-CONNECTED"], timeout=10)
119 raise Exception("Roaming with the AP timed out")
120 if "CTRL-EVENT-EAP-STARTED" in ev:
121 raise Exception("Unexpected EAP exchange")
122 pmksa1b = dev[0].get_pmksa(bssid)
124 raise Exception("No PMKSA cache entry found")
125 if pmksa['pmkid'] != pmksa1b['pmkid']:
126 raise Exception("Unexpected PMKID change for AP1")
128 def test_pmksa_cache_opportunistic(dev, apdev):
129 """Opportunistic PMKSA caching"""
130 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
132 hostapd.add_ap(apdev[0]['ifname'], params)
133 bssid = apdev[0]['bssid']
134 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
135 eap="GPSK", identity="gpsk user",
136 password="abcdefghijklmnop0123456789abcdef", okc=True,
138 pmksa = dev[0].get_pmksa(bssid)
140 raise Exception("No PMKSA cache entry created")
141 if pmksa['opportunistic'] != '0':
142 raise Exception("Unexpected opportunistic PMKSA cache entry")
144 hostapd.add_ap(apdev[1]['ifname'], params)
145 bssid2 = apdev[1]['bssid']
147 dev[0].dump_monitor()
148 logger.info("Roam to AP2")
149 dev[0].scan(freq="2412")
150 dev[0].request("ROAM " + bssid2)
151 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
152 "CTRL-EVENT-CONNECTED"], timeout=10)
154 raise Exception("Roaming with the AP timed out")
155 if "CTRL-EVENT-EAP-STARTED" in ev:
156 raise Exception("Unexpected EAP exchange")
157 pmksa2 = dev[0].get_pmksa(bssid2)
159 raise Exception("No PMKSA cache entry created")
161 dev[0].dump_monitor()
162 logger.info("Roam back to AP1")
163 dev[0].scan(freq="2412")
164 dev[0].request("ROAM " + bssid)
165 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
166 "CTRL-EVENT-CONNECTED"], timeout=10)
168 raise Exception("Roaming with the AP timed out")
169 if "CTRL-EVENT-EAP-STARTED" in ev:
170 raise Exception("Unexpected EAP exchange")
172 pmksa1b = dev[0].get_pmksa(bssid)
174 raise Exception("No PMKSA cache entry found")
175 if pmksa['pmkid'] != pmksa1b['pmkid']:
176 raise Exception("Unexpected PMKID change for AP1")
178 def test_pmksa_cache_opportunistic_connect(dev, apdev):
179 """Opportunistic PMKSA caching with connect API"""
180 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
182 hostapd.add_ap(apdev[0]['ifname'], params)
183 bssid = apdev[0]['bssid']
184 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
185 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
186 wpas.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
187 eap="GPSK", identity="gpsk user",
188 password="abcdefghijklmnop0123456789abcdef", okc=True,
190 pmksa = wpas.get_pmksa(bssid)
192 raise Exception("No PMKSA cache entry created")
193 if pmksa['opportunistic'] != '0':
194 raise Exception("Unexpected opportunistic PMKSA cache entry")
196 hostapd.add_ap(apdev[1]['ifname'], params)
197 bssid2 = apdev[1]['bssid']
200 logger.info("Roam to AP2")
201 wpas.scan_for_bss(bssid2, freq="2412")
202 wpas.request("ROAM " + bssid2)
203 ev = wpas.wait_event(["CTRL-EVENT-EAP-STARTED",
204 "CTRL-EVENT-CONNECTED"], timeout=10)
206 raise Exception("Roaming with the AP timed out")
207 if "CTRL-EVENT-EAP-STARTED" in ev:
208 raise Exception("Unexpected EAP exchange")
209 pmksa2 = wpas.get_pmksa(bssid2)
211 raise Exception("No PMKSA cache entry created")
214 logger.info("Roam back to AP1")
215 wpas.scan(freq="2412")
216 wpas.request("ROAM " + bssid)
217 ev = wpas.wait_event(["CTRL-EVENT-EAP-STARTED",
218 "CTRL-EVENT-CONNECTED"], timeout=10)
220 raise Exception("Roaming with the AP timed out")
221 if "CTRL-EVENT-EAP-STARTED" in ev:
222 raise Exception("Unexpected EAP exchange")
224 pmksa1b = wpas.get_pmksa(bssid)
226 raise Exception("No PMKSA cache entry found")
227 if pmksa['pmkid'] != pmksa1b['pmkid']:
228 raise Exception("Unexpected PMKID change for AP1")
230 def test_pmksa_cache_expiration(dev, apdev):
231 """PMKSA cache entry expiration"""
232 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
233 hostapd.add_ap(apdev[0]['ifname'], params)
234 bssid = apdev[0]['bssid']
235 dev[0].request("SET dot11RSNAConfigPMKLifetime 10")
236 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
237 eap="GPSK", identity="gpsk user",
238 password="abcdefghijklmnop0123456789abcdef",
240 pmksa = dev[0].get_pmksa(bssid)
242 raise Exception("No PMKSA cache entry created")
243 logger.info("Wait for PMKSA cache entry to expire")
244 ev = dev[0].wait_event(["WPA: Key negotiation completed",
245 "CTRL-EVENT-DISCONNECTED"], timeout=15)
247 raise Exception("No EAP reauthentication seen")
248 if "CTRL-EVENT-DISCONNECTED" in ev:
249 raise Exception("Unexpected disconnection")
250 pmksa2 = dev[0].get_pmksa(bssid)
251 if pmksa['pmkid'] == pmksa2['pmkid']:
252 raise Exception("PMKID did not change")
254 def test_pmksa_cache_expiration_disconnect(dev, apdev):
255 """PMKSA cache entry expiration (disconnect)"""
256 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
257 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
258 bssid = apdev[0]['bssid']
259 dev[0].request("SET dot11RSNAConfigPMKLifetime 2")
260 dev[0].request("SET dot11RSNAConfigPMKReauthThreshold 100")
261 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
262 eap="GPSK", identity="gpsk user",
263 password="abcdefghijklmnop0123456789abcdef",
265 pmksa = dev[0].get_pmksa(bssid)
267 raise Exception("No PMKSA cache entry created")
268 hapd.request("SET auth_server_shared_secret incorrect")
269 logger.info("Wait for PMKSA cache entry to expire")
270 ev = dev[0].wait_event(["WPA: Key negotiation completed",
271 "CTRL-EVENT-DISCONNECTED"], timeout=15)
273 raise Exception("No EAP reauthentication seen")
274 if "CTRL-EVENT-DISCONNECTED" not in ev:
275 raise Exception("Missing disconnection")
276 hapd.request("SET auth_server_shared_secret radius")
277 ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=15)
279 raise Exception("No EAP reauthentication seen")
280 pmksa2 = dev[0].get_pmksa(bssid)
281 if pmksa['pmkid'] == pmksa2['pmkid']:
282 raise Exception("PMKID did not change")
284 def test_pmksa_cache_and_cui(dev, apdev):
285 """PMKSA cache and Chargeable-User-Identity"""
286 params = hostapd.wpa2_eap_params(ssid="cui")
287 params['radius_request_cui'] = '1'
288 params['acct_server_addr'] = "127.0.0.1"
289 params['acct_server_port'] = "1813"
290 params['acct_server_shared_secret'] = "radius"
291 hostapd.add_ap(apdev[0]['ifname'], params)
292 bssid = apdev[0]['bssid']
293 dev[0].connect("cui", proto="RSN", key_mgmt="WPA-EAP",
294 eap="GPSK", identity="gpsk-cui",
295 password="abcdefghijklmnop0123456789abcdef",
297 pmksa = dev[0].get_pmksa(bssid)
299 raise Exception("No PMKSA cache entry created")
301 dev[0].dump_monitor()
302 logger.info("Disconnect and reconnect to the same AP")
303 dev[0].request("DISCONNECT")
304 dev[0].request("RECONNECT")
305 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
306 "CTRL-EVENT-CONNECTED"], timeout=10)
308 raise Exception("Reconnect timed out")
309 if "CTRL-EVENT-EAP-STARTED" in ev:
310 raise Exception("Unexpected EAP exchange")
311 pmksa1b = dev[0].get_pmksa(bssid)
313 raise Exception("No PMKSA cache entry found")
314 if pmksa['pmkid'] != pmksa1b['pmkid']:
315 raise Exception("Unexpected PMKID change for AP1")
317 dev[0].request("REAUTHENTICATE")
318 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
320 raise Exception("EAP success timed out")
321 for i in range(0, 20):
322 state = dev[0].get_status_field("wpa_state")
323 if state == "COMPLETED":
326 if state != "COMPLETED":
327 raise Exception("Reauthentication did not complete")
329 def test_pmksa_cache_preauth(dev, apdev):
330 """RSN pre-authentication to generate PMKSA cache entry"""
332 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
333 params['bridge'] = 'ap-br0'
334 hostapd.add_ap(apdev[0]['ifname'], params)
335 subprocess.call(['sudo', 'brctl', 'setfd', 'ap-br0', '0'])
336 subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
337 eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
338 password_hex="0123456789abcdef0123456789abcdef")
340 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
341 params['bridge'] = 'ap-br0'
342 params['rsn_preauth'] = '1'
343 params['rsn_preauth_interfaces'] = 'ap-br0'
344 hostapd.add_ap(apdev[1]['ifname'], params)
345 bssid1 = apdev[1]['bssid']
346 dev[0].scan(freq="2412")
349 for i in range(0, 50):
351 status = dev[0].request("STATUS")
352 if "Pre-authentication EAPOL state machines:" in status:
355 pmksa = dev[0].get_pmksa(bssid1)
360 raise Exception("No PMKSA cache entry created from pre-authentication")
362 raise Exception("Pre-authentication EAPOL status was not available")
364 dev[0].scan(freq="2412")
365 if "[WPA2-EAP-CCMP-preauth]" not in dev[0].request("SCAN_RESULTS"):
366 raise Exception("Scan results missing RSN element info")
367 dev[0].request("ROAM " + bssid1)
368 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
369 "CTRL-EVENT-CONNECTED"], timeout=10)
371 raise Exception("Roaming with the AP timed out")
372 if "CTRL-EVENT-EAP-STARTED" in ev:
373 raise Exception("Unexpected EAP exchange")
374 pmksa2 = dev[0].get_pmksa(bssid1)
376 raise Exception("No PMKSA cache entry")
377 if pmksa['pmkid'] != pmksa2['pmkid']:
378 raise Exception("Unexpected PMKID change")
381 subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
382 subprocess.call(['sudo', 'brctl', 'delbr', 'ap-br0'])
384 def test_pmksa_cache_disabled(dev, apdev):
385 """PMKSA cache disabling on AP"""
386 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
387 params['disable_pmksa_caching'] = '1'
388 hostapd.add_ap(apdev[0]['ifname'], params)
389 bssid = apdev[0]['bssid']
390 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
391 eap="GPSK", identity="gpsk user",
392 password="abcdefghijklmnop0123456789abcdef",
395 hostapd.add_ap(apdev[1]['ifname'], params)
396 bssid2 = apdev[1]['bssid']
398 dev[0].dump_monitor()
399 logger.info("Roam to AP2")
400 dev[0].scan_for_bss(bssid2, freq="2412")
401 dev[0].request("ROAM " + bssid2)
402 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
404 raise Exception("EAP success timed out")
405 dev[0].wait_connected(timeout=10, error="Roaming timed out")
407 dev[0].dump_monitor()
408 logger.info("Roam back to AP1")
409 dev[0].scan(freq="2412")
410 dev[0].request("ROAM " + bssid)
411 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
412 "CTRL-EVENT-CONNECTED"], timeout=20)
414 raise Exception("Roaming with the AP timed out")
415 if "CTRL-EVENT-CONNECTED" in ev:
416 raise Exception("EAP exchange missing")
417 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=20)
419 raise Exception("Roaming with the AP timed out")
421 def test_pmksa_cache_ap_expiration(dev, apdev):
422 """PMKSA cache entry expiring on AP"""
423 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
424 hostapd.add_ap(apdev[0]['ifname'], params)
425 bssid = apdev[0]['bssid']
426 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
427 eap="GPSK", identity="gpsk-user-session-timeout",
428 password="abcdefghijklmnop0123456789abcdef",
430 dev[0].request("DISCONNECT")
432 dev[0].dump_monitor()
433 dev[0].request("RECONNECT")
434 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
435 "CTRL-EVENT-CONNECTED"], timeout=20)
437 raise Exception("Roaming with the AP timed out")
438 if "CTRL-EVENT-CONNECTED" in ev:
439 raise Exception("EAP exchange missing")
440 dev[0].wait_connected(timeout=20, error="Reconnect timed out")
441 dev[0].dump_monitor()
442 dev[0].wait_disconnected(timeout=20)
443 dev[0].wait_connected(timeout=20, error="Reassociation timed out")
445 def test_pmksa_cache_multiple_sta(dev, apdev):
446 """PMKSA cache with multiple stations"""
447 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
448 hostapd.add_ap(apdev[0]['ifname'], params)
449 bssid = apdev[0]['bssid']
450 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
451 eap="GPSK", identity="gpsk-user-session-timeout",
452 password="abcdefghijklmnop0123456789abcdef",
454 dev[1].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
455 eap="GPSK", identity="gpsk user",
456 password="abcdefghijklmnop0123456789abcdef",
458 dev[2].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
459 eap="GPSK", identity="gpsk-user-session-timeout",
460 password="abcdefghijklmnop0123456789abcdef",
463 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
464 wpas.interface_add("wlan5")
465 wpas.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
466 eap="GPSK", identity="gpsk user",
467 password="abcdefghijklmnop0123456789abcdef",
470 hostapd.add_ap(apdev[1]['ifname'], params)
471 bssid2 = apdev[1]['bssid']
473 logger.info("Roam to AP2")
474 for sta in [ dev[1], dev[0], dev[2], wpas ]:
476 sta.scan_for_bss(bssid2, freq="2412")
477 sta.request("ROAM " + bssid2)
478 ev = sta.wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
480 raise Exception("EAP success timed out")
481 sta.wait_connected(timeout=10, error="Roaming timed out")
483 logger.info("Roam back to AP1")
484 for sta in [ dev[1], wpas, dev[0], dev[2] ]:
486 sta.scan(freq="2412")
488 sta.request("ROAM " + bssid)
489 sta.wait_connected(timeout=10, error="Roaming timed out")
494 logger.info("Roam back to AP2")
495 for sta in [ dev[1], wpas, dev[0], dev[2] ]:
497 sta.scan(freq="2412")
499 sta.request("ROAM " + bssid2)
500 sta.wait_connected(timeout=10, error="Roaming timed out")
503 def test_pmksa_cache_opportunistic_multiple_sta(dev, apdev):
504 """Opportunistic PMKSA caching with multiple stations"""
505 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
507 hostapd.add_ap(apdev[0]['ifname'], params)
508 bssid = apdev[0]['bssid']
509 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
510 wpas.interface_add("wlan5")
511 for sta in [ dev[0], dev[1], dev[2], wpas ]:
512 sta.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
513 eap="GPSK", identity="gpsk user",
514 password="abcdefghijklmnop0123456789abcdef", okc=True,
517 hostapd.add_ap(apdev[1]['ifname'], params)
518 bssid2 = apdev[1]['bssid']
520 logger.info("Roam to AP2")
521 for sta in [ dev[2], dev[0], wpas, dev[1] ]:
523 sta.scan_for_bss(bssid2, freq="2412")
524 if "OK" not in sta.request("ROAM " + bssid2):
525 raise Exception("ROAM command failed")
526 ev = sta.wait_event(["CTRL-EVENT-EAP-STARTED",
527 "CTRL-EVENT-CONNECTED"], timeout=10)
529 raise Exception("Roaming with the AP timed out")
530 if "CTRL-EVENT-EAP-STARTED" in ev:
531 raise Exception("Unexpected EAP exchange")
532 pmksa2 = sta.get_pmksa(bssid2)
534 raise Exception("No PMKSA cache entry created")
536 logger.info("Roam back to AP1")
537 for sta in [ dev[0], dev[1], dev[2], wpas ]:
539 sta.scan_for_bss(bssid, freq="2412")
540 sta.request("ROAM " + bssid)
541 ev = sta.wait_event(["CTRL-EVENT-EAP-STARTED",
542 "CTRL-EVENT-CONNECTED"], timeout=10)
544 raise Exception("Roaming with the AP timed out")
545 if "CTRL-EVENT-EAP-STARTED" in ev:
546 raise Exception("Unexpected EAP exchange")