tests: Report ROAM failure in pmksa_cache_opportunistic_multiple_sta
[mech_eap.git] / tests / hwsim / test_pmksa_cache.py
1 # WPA2-Enterprise PMKSA caching tests
2 # Copyright (c) 2013-2014, 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 logging
8 logger = logging.getLogger()
9 import subprocess
10 import time
11
12 import hostapd
13 from wpasupplicant import WpaSupplicant
14 from test_ap_eap import eap_connect
15
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",
24                    scan_freq="2412")
25     pmksa = dev[0].get_pmksa(bssid)
26     if pmksa is None:
27         raise Exception("No PMKSA cache entry created")
28     if pmksa['opportunistic'] != '0':
29         raise Exception("Unexpected opportunistic PMKSA cache entry")
30
31     hostapd.add_ap(apdev[1]['ifname'], params)
32     bssid2 = apdev[1]['bssid']
33
34     dev[0].dump_monitor()
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:
43             break
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)
47     if ev is None:
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)
51     if pmksa2 is None:
52         raise Exception("No PMKSA cache entry found")
53     if pmksa2['opportunistic'] != '0':
54         raise Exception("Unexpected opportunistic PMKSA cache entry")
55
56     dev[0].dump_monitor()
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)
62     if ev is None:
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)
67     if pmksa1b is None:
68         raise Exception("No PMKSA cache entry found")
69     if pmksa['pmkid'] != pmksa1b['pmkid']:
70         raise Exception("Unexpected PMKID change for AP1")
71
72     dev[0].dump_monitor()
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")
79
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,
88                    scan_freq="2412")
89     pmksa = dev[0].get_pmksa(bssid)
90     if pmksa is None:
91         raise Exception("No PMKSA cache entry created")
92     if pmksa['opportunistic'] != '0':
93         raise Exception("Unexpected opportunistic PMKSA cache entry")
94
95     hostapd.add_ap(apdev[1]['ifname'], params)
96     bssid2 = apdev[1]['bssid']
97
98     dev[0].dump_monitor()
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)
103     if ev is None:
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)
107     if pmksa2 is None:
108         raise Exception("No PMKSA cache entry found")
109     if pmksa2['opportunistic'] != '0':
110         raise Exception("Unexpected opportunistic PMKSA cache entry")
111
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)
118     if ev is None:
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)
123     if pmksa1b is None:
124         raise Exception("No PMKSA cache entry found")
125     if pmksa['pmkid'] != pmksa1b['pmkid']:
126         raise Exception("Unexpected PMKID change for AP1")
127
128 def test_pmksa_cache_opportunistic(dev, apdev):
129     """Opportunistic PMKSA caching"""
130     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
131     params['okc'] = "1"
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,
137                    scan_freq="2412")
138     pmksa = dev[0].get_pmksa(bssid)
139     if pmksa is None:
140         raise Exception("No PMKSA cache entry created")
141     if pmksa['opportunistic'] != '0':
142         raise Exception("Unexpected opportunistic PMKSA cache entry")
143
144     hostapd.add_ap(apdev[1]['ifname'], params)
145     bssid2 = apdev[1]['bssid']
146
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)
153     if ev is None:
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)
158     if pmksa2 is None:
159         raise Exception("No PMKSA cache entry created")
160
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)
167     if ev is None:
168         raise Exception("Roaming with the AP timed out")
169     if "CTRL-EVENT-EAP-STARTED" in ev:
170         raise Exception("Unexpected EAP exchange")
171
172     pmksa1b = dev[0].get_pmksa(bssid)
173     if pmksa1b is None:
174         raise Exception("No PMKSA cache entry found")
175     if pmksa['pmkid'] != pmksa1b['pmkid']:
176         raise Exception("Unexpected PMKID change for AP1")
177
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")
181     params['okc'] = "1"
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,
189                  scan_freq="2412")
190     pmksa = wpas.get_pmksa(bssid)
191     if pmksa is None:
192         raise Exception("No PMKSA cache entry created")
193     if pmksa['opportunistic'] != '0':
194         raise Exception("Unexpected opportunistic PMKSA cache entry")
195
196     hostapd.add_ap(apdev[1]['ifname'], params)
197     bssid2 = apdev[1]['bssid']
198
199     wpas.dump_monitor()
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)
205     if ev is None:
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)
210     if pmksa2 is None:
211         raise Exception("No PMKSA cache entry created")
212
213     wpas.dump_monitor()
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)
219     if ev is None:
220         raise Exception("Roaming with the AP timed out")
221     if "CTRL-EVENT-EAP-STARTED" in ev:
222         raise Exception("Unexpected EAP exchange")
223
224     pmksa1b = wpas.get_pmksa(bssid)
225     if pmksa1b is None:
226         raise Exception("No PMKSA cache entry found")
227     if pmksa['pmkid'] != pmksa1b['pmkid']:
228         raise Exception("Unexpected PMKID change for AP1")
229
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",
239                    scan_freq="2412")
240     pmksa = dev[0].get_pmksa(bssid)
241     if pmksa is None:
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)
246     if ev is None:
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")
253
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",
264                    scan_freq="2412")
265     pmksa = dev[0].get_pmksa(bssid)
266     if pmksa is None:
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)
272     if ev is None:
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)
278     if ev is None:
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")
283
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",
296                    scan_freq="2412")
297     pmksa = dev[0].get_pmksa(bssid)
298     if pmksa is None:
299         raise Exception("No PMKSA cache entry created")
300
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)
307     if ev is None:
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)
312     if pmksa1b is None:
313         raise Exception("No PMKSA cache entry found")
314     if pmksa['pmkid'] != pmksa1b['pmkid']:
315         raise Exception("Unexpected PMKID change for AP1")
316
317     dev[0].request("REAUTHENTICATE")
318     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
319     if ev is None:
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":
324             break
325         time.sleep(0.1)
326     if state != "COMPLETED":
327         raise Exception("Reauthentication did not complete")
328
329 def test_pmksa_cache_preauth(dev, apdev):
330     """RSN pre-authentication to generate PMKSA cache entry"""
331     try:
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")
339
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")
347         success = False
348         status_seen = False
349         for i in range(0, 50):
350             if not status_seen:
351                 status = dev[0].request("STATUS")
352                 if "Pre-authentication EAPOL state machines:" in status:
353                     status_seen = True
354             time.sleep(0.1)
355             pmksa = dev[0].get_pmksa(bssid1)
356             if pmksa:
357                 success = True
358                 break
359         if not success:
360             raise Exception("No PMKSA cache entry created from pre-authentication")
361         if not status_seen:
362             raise Exception("Pre-authentication EAPOL status was not available")
363
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)
370         if ev is None:
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)
375         if pmksa2 is None:
376             raise Exception("No PMKSA cache entry")
377         if pmksa['pmkid'] != pmksa2['pmkid']:
378             raise Exception("Unexpected PMKID change")
379
380     finally:
381         subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
382         subprocess.call(['sudo', 'brctl', 'delbr', 'ap-br0'])
383
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",
393                    scan_freq="2412")
394
395     hostapd.add_ap(apdev[1]['ifname'], params)
396     bssid2 = apdev[1]['bssid']
397
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)
403     if ev is None:
404         raise Exception("EAP success timed out")
405     dev[0].wait_connected(timeout=10, error="Roaming timed out")
406
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)
413     if ev is None:
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)
418     if ev is None:
419         raise Exception("Roaming with the AP timed out")
420
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",
429                    scan_freq="2412")
430     dev[0].request("DISCONNECT")
431     time.sleep(5)
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)
436     if ev is None:
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")
444
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",
453                    scan_freq="2412")
454     dev[1].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
455                    eap="GPSK", identity="gpsk user",
456                    password="abcdefghijklmnop0123456789abcdef",
457                    scan_freq="2412")
458     dev[2].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
459                    eap="GPSK", identity="gpsk-user-session-timeout",
460                    password="abcdefghijklmnop0123456789abcdef",
461                    scan_freq="2412")
462
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",
468                  scan_freq="2412")
469
470     hostapd.add_ap(apdev[1]['ifname'], params)
471     bssid2 = apdev[1]['bssid']
472
473     logger.info("Roam to AP2")
474     for sta in [ dev[1], dev[0], dev[2], wpas ]:
475         sta.dump_monitor()
476         sta.scan_for_bss(bssid2, freq="2412")
477         sta.request("ROAM " + bssid2)
478         ev = sta.wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
479         if ev is None:
480             raise Exception("EAP success timed out")
481         sta.wait_connected(timeout=10, error="Roaming timed out")
482
483     logger.info("Roam back to AP1")
484     for sta in [ dev[1], wpas, dev[0], dev[2] ]:
485         sta.dump_monitor()
486         sta.scan(freq="2412")
487         sta.dump_monitor()
488         sta.request("ROAM " + bssid)
489         sta.wait_connected(timeout=10, error="Roaming timed out")
490         sta.dump_monitor()
491
492     time.sleep(4)
493
494     logger.info("Roam back to AP2")
495     for sta in [ dev[1], wpas, dev[0], dev[2] ]:
496         sta.dump_monitor()
497         sta.scan(freq="2412")
498         sta.dump_monitor()
499         sta.request("ROAM " + bssid2)
500         sta.wait_connected(timeout=10, error="Roaming timed out")
501         sta.dump_monitor()
502
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")
506     params['okc'] = "1"
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,
515                     scan_freq="2412")
516
517     hostapd.add_ap(apdev[1]['ifname'], params)
518     bssid2 = apdev[1]['bssid']
519
520     logger.info("Roam to AP2")
521     for sta in [ dev[2], dev[0], wpas, dev[1] ]:
522         sta.dump_monitor()
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)
528         if ev is None:
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)
533         if pmksa2 is None:
534             raise Exception("No PMKSA cache entry created")
535
536     logger.info("Roam back to AP1")
537     for sta in [ dev[0], dev[1], dev[2], wpas ]:
538         sta.dump_monitor()
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)
543         if ev is None:
544             raise Exception("Roaming with the AP timed out")
545         if "CTRL-EVENT-EAP-STARTED" in ev:
546             raise Exception("Unexpected EAP exchange")