05b9d8db69620da2327645de79c033b98c0f4712
[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     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
50     if ev is None:
51         raise Exception("Roaming with the AP timed out")
52     pmksa2 = dev[0].get_pmksa(bssid2)
53     if pmksa2 is None:
54         raise Exception("No PMKSA cache entry found")
55     if pmksa2['opportunistic'] != '0':
56         raise Exception("Unexpected opportunistic PMKSA cache entry")
57
58     dev[0].dump_monitor()
59     logger.info("Roam back to AP1")
60     dev[0].scan(freq="2412")
61     dev[0].request("ROAM " + bssid)
62     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
63                             "CTRL-EVENT-CONNECTED"], timeout=10)
64     if ev is None:
65         raise Exception("Roaming with the AP timed out")
66     if "CTRL-EVENT-EAP-STARTED" in ev:
67         raise Exception("Unexpected EAP exchange")
68     pmksa1b = dev[0].get_pmksa(bssid)
69     if pmksa1b is None:
70         raise Exception("No PMKSA cache entry found")
71     if pmksa['pmkid'] != pmksa1b['pmkid']:
72         raise Exception("Unexpected PMKID change for AP1")
73
74     dev[0].dump_monitor()
75     if "FAIL" in dev[0].request("PMKSA_FLUSH"):
76         raise Exception("PMKSA_FLUSH failed")
77     if dev[0].get_pmksa(bssid) is not None or dev[0].get_pmksa(bssid2) is not None:
78         raise Exception("PMKSA_FLUSH did not remove PMKSA entries")
79     ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5)
80     if ev is None:
81         raise Exception("Disconnection event timed out")
82     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
83     if ev is None:
84         raise Exception("Reconnection timed out")
85
86 def test_pmksa_cache_opportunistic_only_on_sta(dev, apdev):
87     """Opportunistic PMKSA caching enabled only on station"""
88     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
89     hostapd.add_ap(apdev[0]['ifname'], params)
90     bssid = apdev[0]['bssid']
91     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
92                    eap="GPSK", identity="gpsk user",
93                    password="abcdefghijklmnop0123456789abcdef", okc=True,
94                    scan_freq="2412")
95     pmksa = dev[0].get_pmksa(bssid)
96     if pmksa is None:
97         raise Exception("No PMKSA cache entry created")
98     if pmksa['opportunistic'] != '0':
99         raise Exception("Unexpected opportunistic PMKSA cache entry")
100
101     hostapd.add_ap(apdev[1]['ifname'], params)
102     bssid2 = apdev[1]['bssid']
103
104     dev[0].dump_monitor()
105     logger.info("Roam to AP2")
106     dev[0].scan(freq="2412")
107     dev[0].request("ROAM " + bssid2)
108     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
109     if ev is None:
110         raise Exception("EAP success timed out")
111     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
112     if ev is None:
113         raise Exception("Roaming with the AP timed out")
114     pmksa2 = dev[0].get_pmksa(bssid2)
115     if pmksa2 is None:
116         raise Exception("No PMKSA cache entry found")
117     if pmksa2['opportunistic'] != '0':
118         raise Exception("Unexpected opportunistic PMKSA cache entry")
119
120     dev[0].dump_monitor()
121     logger.info("Roam back to AP1")
122     dev[0].scan(freq="2412")
123     dev[0].request("ROAM " + bssid)
124     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
125                             "CTRL-EVENT-CONNECTED"], timeout=10)
126     if ev is None:
127         raise Exception("Roaming with the AP timed out")
128     if "CTRL-EVENT-EAP-STARTED" in ev:
129         raise Exception("Unexpected EAP exchange")
130     pmksa1b = dev[0].get_pmksa(bssid)
131     if pmksa1b is None:
132         raise Exception("No PMKSA cache entry found")
133     if pmksa['pmkid'] != pmksa1b['pmkid']:
134         raise Exception("Unexpected PMKID change for AP1")
135
136 def test_pmksa_cache_opportunistic(dev, apdev):
137     """Opportunistic PMKSA caching"""
138     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
139     params['okc'] = "1"
140     hostapd.add_ap(apdev[0]['ifname'], params)
141     bssid = apdev[0]['bssid']
142     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
143                    eap="GPSK", identity="gpsk user",
144                    password="abcdefghijklmnop0123456789abcdef", okc=True,
145                    scan_freq="2412")
146     pmksa = dev[0].get_pmksa(bssid)
147     if pmksa is None:
148         raise Exception("No PMKSA cache entry created")
149     if pmksa['opportunistic'] != '0':
150         raise Exception("Unexpected opportunistic PMKSA cache entry")
151
152     hostapd.add_ap(apdev[1]['ifname'], params)
153     bssid2 = apdev[1]['bssid']
154
155     dev[0].dump_monitor()
156     logger.info("Roam to AP2")
157     dev[0].scan(freq="2412")
158     dev[0].request("ROAM " + bssid2)
159     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
160                             "CTRL-EVENT-CONNECTED"], timeout=10)
161     if ev is None:
162         raise Exception("Roaming with the AP timed out")
163     if "CTRL-EVENT-EAP-STARTED" in ev:
164         raise Exception("Unexpected EAP exchange")
165     pmksa2 = dev[0].get_pmksa(bssid2)
166     if pmksa2 is None:
167         raise Exception("No PMKSA cache entry created")
168
169     dev[0].dump_monitor()
170     logger.info("Roam back to AP1")
171     dev[0].scan(freq="2412")
172     dev[0].request("ROAM " + bssid)
173     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
174                             "CTRL-EVENT-CONNECTED"], timeout=10)
175     if ev is None:
176         raise Exception("Roaming with the AP timed out")
177     if "CTRL-EVENT-EAP-STARTED" in ev:
178         raise Exception("Unexpected EAP exchange")
179
180     pmksa1b = dev[0].get_pmksa(bssid)
181     if pmksa1b is None:
182         raise Exception("No PMKSA cache entry found")
183     if pmksa['pmkid'] != pmksa1b['pmkid']:
184         raise Exception("Unexpected PMKID change for AP1")
185
186 def test_pmksa_cache_opportunistic_connect(dev, apdev):
187     """Opportunistic PMKSA caching with connect API"""
188     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
189     params['okc'] = "1"
190     hostapd.add_ap(apdev[0]['ifname'], params)
191     bssid = apdev[0]['bssid']
192     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
193     wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
194     wpas.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
195                  eap="GPSK", identity="gpsk user",
196                  password="abcdefghijklmnop0123456789abcdef", okc=True,
197                  scan_freq="2412")
198     pmksa = wpas.get_pmksa(bssid)
199     if pmksa is None:
200         raise Exception("No PMKSA cache entry created")
201     if pmksa['opportunistic'] != '0':
202         raise Exception("Unexpected opportunistic PMKSA cache entry")
203
204     hostapd.add_ap(apdev[1]['ifname'], params)
205     bssid2 = apdev[1]['bssid']
206
207     wpas.dump_monitor()
208     logger.info("Roam to AP2")
209     wpas.scan(freq="2412")
210     wpas.request("ROAM " + bssid2)
211     ev = wpas.wait_event(["CTRL-EVENT-EAP-STARTED",
212                             "CTRL-EVENT-CONNECTED"], timeout=10)
213     if ev is None:
214         raise Exception("Roaming with the AP timed out")
215     if "CTRL-EVENT-EAP-STARTED" in ev:
216         raise Exception("Unexpected EAP exchange")
217     pmksa2 = wpas.get_pmksa(bssid2)
218     if pmksa2 is None:
219         raise Exception("No PMKSA cache entry created")
220
221     wpas.dump_monitor()
222     logger.info("Roam back to AP1")
223     wpas.scan(freq="2412")
224     wpas.request("ROAM " + bssid)
225     ev = wpas.wait_event(["CTRL-EVENT-EAP-STARTED",
226                             "CTRL-EVENT-CONNECTED"], timeout=10)
227     if ev is None:
228         raise Exception("Roaming with the AP timed out")
229     if "CTRL-EVENT-EAP-STARTED" in ev:
230         raise Exception("Unexpected EAP exchange")
231
232     pmksa1b = wpas.get_pmksa(bssid)
233     if pmksa1b is None:
234         raise Exception("No PMKSA cache entry found")
235     if pmksa['pmkid'] != pmksa1b['pmkid']:
236         raise Exception("Unexpected PMKID change for AP1")
237
238 def test_pmksa_cache_expiration(dev, apdev):
239     """PMKSA cache entry expiration"""
240     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
241     hostapd.add_ap(apdev[0]['ifname'], params)
242     bssid = apdev[0]['bssid']
243     dev[0].request("SET dot11RSNAConfigPMKLifetime 10")
244     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
245                    eap="GPSK", identity="gpsk user",
246                    password="abcdefghijklmnop0123456789abcdef",
247                    scan_freq="2412")
248     pmksa = dev[0].get_pmksa(bssid)
249     if pmksa is None:
250         raise Exception("No PMKSA cache entry created")
251     logger.info("Wait for PMKSA cache entry to expire")
252     ev = dev[0].wait_event(["WPA: Key negotiation completed",
253                             "CTRL-EVENT-DISCONNECTED"], timeout=15)
254     if ev is None:
255         raise Exception("No EAP reauthentication seen")
256     if "CTRL-EVENT-DISCONNECTED" in ev:
257         raise Exception("Unexpected disconnection")
258     pmksa2 = dev[0].get_pmksa(bssid)
259     if pmksa['pmkid'] == pmksa2['pmkid']:
260         raise Exception("PMKID did not change")
261
262 def test_pmksa_cache_expiration_disconnect(dev, apdev):
263     """PMKSA cache entry expiration (disconnect)"""
264     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
265     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
266     bssid = apdev[0]['bssid']
267     dev[0].request("SET dot11RSNAConfigPMKLifetime 2")
268     dev[0].request("SET dot11RSNAConfigPMKReauthThreshold 100")
269     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
270                    eap="GPSK", identity="gpsk user",
271                    password="abcdefghijklmnop0123456789abcdef",
272                    scan_freq="2412")
273     pmksa = dev[0].get_pmksa(bssid)
274     if pmksa is None:
275         raise Exception("No PMKSA cache entry created")
276     hapd.request("SET auth_server_shared_secret incorrect")
277     logger.info("Wait for PMKSA cache entry to expire")
278     ev = dev[0].wait_event(["WPA: Key negotiation completed",
279                             "CTRL-EVENT-DISCONNECTED"], timeout=15)
280     if ev is None:
281         raise Exception("No EAP reauthentication seen")
282     if "CTRL-EVENT-DISCONNECTED" not in ev:
283         raise Exception("Missing disconnection")
284     hapd.request("SET auth_server_shared_secret radius")
285     ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=15)
286     if ev is None:
287         raise Exception("No EAP reauthentication seen")
288     pmksa2 = dev[0].get_pmksa(bssid)
289     if pmksa['pmkid'] == pmksa2['pmkid']:
290         raise Exception("PMKID did not change")
291
292 def test_pmksa_cache_and_cui(dev, apdev):
293     """PMKSA cache and Chargeable-User-Identity"""
294     params = hostapd.wpa2_eap_params(ssid="cui")
295     params['radius_request_cui'] = '1'
296     params['acct_server_addr'] = "127.0.0.1"
297     params['acct_server_port'] = "1813"
298     params['acct_server_shared_secret'] = "radius"
299     hostapd.add_ap(apdev[0]['ifname'], params)
300     bssid = apdev[0]['bssid']
301     dev[0].connect("cui", proto="RSN", key_mgmt="WPA-EAP",
302                    eap="GPSK", identity="gpsk-cui",
303                    password="abcdefghijklmnop0123456789abcdef",
304                    scan_freq="2412")
305     pmksa = dev[0].get_pmksa(bssid)
306     if pmksa is None:
307         raise Exception("No PMKSA cache entry created")
308
309     dev[0].dump_monitor()
310     logger.info("Disconnect and reconnect to the same AP")
311     dev[0].request("DISCONNECT")
312     dev[0].request("RECONNECT")
313     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
314                             "CTRL-EVENT-CONNECTED"], timeout=10)
315     if ev is None:
316         raise Exception("Reconnect timed out")
317     if "CTRL-EVENT-EAP-STARTED" in ev:
318         raise Exception("Unexpected EAP exchange")
319     pmksa1b = dev[0].get_pmksa(bssid)
320     if pmksa1b is None:
321         raise Exception("No PMKSA cache entry found")
322     if pmksa['pmkid'] != pmksa1b['pmkid']:
323         raise Exception("Unexpected PMKID change for AP1")
324
325     dev[0].request("REAUTHENTICATE")
326     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
327     if ev is None:
328         raise Exception("EAP success timed out")
329     for i in range(0, 20):
330         state = dev[0].get_status_field("wpa_state")
331         if state == "COMPLETED":
332             break
333         time.sleep(0.1)
334     if state != "COMPLETED":
335         raise Exception("Reauthentication did not complete")
336
337 def test_pmksa_cache_preauth(dev, apdev):
338     """RSN pre-authentication to generate PMKSA cache entry"""
339     try:
340         params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
341         params['bridge'] = 'ap-br0'
342         hostapd.add_ap(apdev[0]['ifname'], params)
343         subprocess.call(['sudo', 'brctl', 'setfd', 'ap-br0', '0'])
344         subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
345         eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
346                     password_hex="0123456789abcdef0123456789abcdef")
347
348         params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
349         params['bridge'] = 'ap-br0'
350         params['rsn_preauth'] = '1'
351         params['rsn_preauth_interfaces'] = 'ap-br0'
352         hostapd.add_ap(apdev[1]['ifname'], params)
353         bssid1 = apdev[1]['bssid']
354         dev[0].scan(freq="2412")
355         success = False
356         status_seen = False
357         for i in range(0, 50):
358             if not status_seen:
359                 status = dev[0].request("STATUS")
360                 if "Pre-authentication EAPOL state machines:" in status:
361                     status_seen = True
362             time.sleep(0.1)
363             pmksa = dev[0].get_pmksa(bssid1)
364             if pmksa:
365                 success = True
366                 break
367         if not success:
368             raise Exception("No PMKSA cache entry created from pre-authentication")
369         if not status_seen:
370             raise Exception("Pre-authentication EAPOL status was not available")
371
372         dev[0].scan(freq="2412")
373         if "[WPA2-EAP-CCMP-preauth]" not in dev[0].request("SCAN_RESULTS"):
374             raise Exception("Scan results missing RSN element info")
375         dev[0].request("ROAM " + bssid1)
376         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
377                                 "CTRL-EVENT-CONNECTED"], timeout=10)
378         if ev is None:
379             raise Exception("Roaming with the AP timed out")
380         if "CTRL-EVENT-EAP-STARTED" in ev:
381             raise Exception("Unexpected EAP exchange")
382         pmksa2 = dev[0].get_pmksa(bssid1)
383         if pmksa2 is None:
384             raise Exception("No PMKSA cache entry")
385         if pmksa['pmkid'] != pmksa2['pmkid']:
386             raise Exception("Unexpected PMKID change")
387
388     finally:
389         subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
390         subprocess.call(['sudo', 'brctl', 'delbr', 'ap-br0'])
391
392 def test_pmksa_cache_disabled(dev, apdev):
393     """PMKSA cache disabling on AP"""
394     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
395     params['disable_pmksa_caching'] = '1'
396     hostapd.add_ap(apdev[0]['ifname'], params)
397     bssid = apdev[0]['bssid']
398     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
399                    eap="GPSK", identity="gpsk user",
400                    password="abcdefghijklmnop0123456789abcdef",
401                    scan_freq="2412")
402
403     hostapd.add_ap(apdev[1]['ifname'], params)
404     bssid2 = apdev[1]['bssid']
405
406     dev[0].dump_monitor()
407     logger.info("Roam to AP2")
408     dev[0].scan_for_bss(bssid2, freq="2412")
409     dev[0].request("ROAM " + bssid2)
410     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
411     if ev is None:
412         raise Exception("EAP success timed out")
413     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
414     if ev is None:
415         raise Exception("Roaming with the AP timed out")
416
417     dev[0].dump_monitor()
418     logger.info("Roam back to AP1")
419     dev[0].scan(freq="2412")
420     dev[0].request("ROAM " + bssid)
421     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
422                             "CTRL-EVENT-CONNECTED"], timeout=20)
423     if ev is None:
424         raise Exception("Roaming with the AP timed out")
425     if "CTRL-EVENT-CONNECTED" in ev:
426         raise Exception("EAP exchange missing")
427     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=20)
428     if ev is None:
429         raise Exception("Roaming with the AP timed out")
430
431 def test_pmksa_cache_ap_expiration(dev, apdev):
432     """PMKSA cache entry expiring on AP"""
433     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
434     hostapd.add_ap(apdev[0]['ifname'], params)
435     bssid = apdev[0]['bssid']
436     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
437                    eap="GPSK", identity="gpsk-user-session-timeout",
438                    password="abcdefghijklmnop0123456789abcdef",
439                    scan_freq="2412")
440     dev[0].request("DISCONNECT")
441     time.sleep(5)
442     dev[0].dump_monitor()
443     dev[0].request("RECONNECT")
444     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
445                             "CTRL-EVENT-CONNECTED"], timeout=20)
446     if ev is None:
447         raise Exception("Roaming with the AP timed out")
448     if "CTRL-EVENT-CONNECTED" in ev:
449         raise Exception("EAP exchange missing")
450     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=20)
451     if ev is None:
452         raise Exception("Reassociation with the AP timed out")
453     dev[0].dump_monitor()
454     ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=20)
455     if ev is None:
456         raise Exception("Disconnection event timed out")
457     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=20)
458     if ev is None:
459         raise Exception("Reassociation with the AP timed out")
460
461 def test_pmksa_cache_multiple_sta(dev, apdev):
462     """PMKSA cache with multiple stations"""
463     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
464     hostapd.add_ap(apdev[0]['ifname'], params)
465     bssid = apdev[0]['bssid']
466     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
467                    eap="GPSK", identity="gpsk-user-session-timeout",
468                    password="abcdefghijklmnop0123456789abcdef",
469                    scan_freq="2412")
470     dev[1].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
471                    eap="GPSK", identity="gpsk user",
472                    password="abcdefghijklmnop0123456789abcdef",
473                    scan_freq="2412")
474     dev[2].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
475                    eap="GPSK", identity="gpsk-user-session-timeout",
476                    password="abcdefghijklmnop0123456789abcdef",
477                    scan_freq="2412")
478
479     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
480     wpas.interface_add("wlan5")
481     wpas.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
482                  eap="GPSK", identity="gpsk user",
483                  password="abcdefghijklmnop0123456789abcdef",
484                  scan_freq="2412")
485
486     hostapd.add_ap(apdev[1]['ifname'], params)
487     bssid2 = apdev[1]['bssid']
488
489     logger.info("Roam to AP2")
490     for sta in [ dev[1], dev[0], dev[2], wpas ]:
491         sta.dump_monitor()
492         sta.scan_for_bss(bssid2, freq="2412")
493         sta.request("ROAM " + bssid2)
494         ev = sta.wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
495         if ev is None:
496             raise Exception("EAP success timed out")
497         ev = sta.wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
498         if ev is None:
499             raise Exception("Roaming with the AP timed out")
500
501     logger.info("Roam back to AP1")
502     for sta in [ dev[1], wpas, dev[0], dev[2] ]:
503         sta.dump_monitor()
504         sta.scan(freq="2412")
505         sta.dump_monitor()
506         sta.request("ROAM " + bssid)
507         ev = sta.wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
508         if ev is None:
509             raise Exception("Roaming with the AP timed out")
510         sta.dump_monitor()
511
512     time.sleep(4)
513
514     logger.info("Roam back to AP2")
515     for sta in [ dev[1], wpas, dev[0], dev[2] ]:
516         sta.dump_monitor()
517         sta.scan(freq="2412")
518         sta.dump_monitor()
519         sta.request("ROAM " + bssid2)
520         ev = sta.wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
521         if ev is None:
522             raise Exception("Roaming with the AP timed out")
523         sta.dump_monitor()
524
525 def test_pmksa_cache_opportunistic_multiple_sta(dev, apdev):
526     """Opportunistic PMKSA caching with multiple stations"""
527     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
528     params['okc'] = "1"
529     hostapd.add_ap(apdev[0]['ifname'], params)
530     bssid = apdev[0]['bssid']
531     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
532     wpas.interface_add("wlan5")
533     for sta in [ dev[0], dev[1], dev[2], wpas ]:
534         sta.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
535                     eap="GPSK", identity="gpsk user",
536                     password="abcdefghijklmnop0123456789abcdef", okc=True,
537                     scan_freq="2412")
538
539     hostapd.add_ap(apdev[1]['ifname'], params)
540     bssid2 = apdev[1]['bssid']
541
542     logger.info("Roam to AP2")
543     for sta in [ dev[2], dev[0], wpas, dev[1] ]:
544         sta.dump_monitor()
545         sta.scan_for_bss(bssid2, freq="2412")
546         sta.request("ROAM " + bssid2)
547         ev = sta.wait_event(["CTRL-EVENT-EAP-STARTED",
548                              "CTRL-EVENT-CONNECTED"], timeout=10)
549         if ev is None:
550             raise Exception("Roaming with the AP timed out")
551         if "CTRL-EVENT-EAP-STARTED" in ev:
552             raise Exception("Unexpected EAP exchange")
553         pmksa2 = sta.get_pmksa(bssid2)
554         if pmksa2 is None:
555             raise Exception("No PMKSA cache entry created")
556
557     logger.info("Roam back to AP1")
558     for sta in [ dev[0], dev[1], dev[2], wpas ]:
559         sta.dump_monitor()
560         sta.scan_for_bss(bssid, freq="2412")
561         sta.request("ROAM " + bssid)
562         ev = sta.wait_event(["CTRL-EVENT-EAP-STARTED",
563                              "CTRL-EVENT-CONNECTED"], timeout=10)
564         if ev is None:
565             raise Exception("Roaming with the AP timed out")
566         if "CTRL-EVENT-EAP-STARTED" in ev:
567             raise Exception("Unexpected EAP exchange")