Updated through tag hostap_2_5 from git://w1.fi/hostap.git
[mech_eap.git] / libeap / 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 utils import alloc_fail
15 from test_ap_eap import eap_connect
16
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",
25                    scan_freq="2412")
26     pmksa = dev[0].get_pmksa(bssid)
27     if pmksa is None:
28         raise Exception("No PMKSA cache entry created")
29     if pmksa['opportunistic'] != '0':
30         raise Exception("Unexpected opportunistic PMKSA cache entry")
31
32     hostapd.add_ap(apdev[1]['ifname'], params)
33     bssid2 = apdev[1]['bssid']
34
35     dev[0].dump_monitor()
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:
44             break
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)
48     if ev is None:
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)
52     if pmksa2 is None:
53         raise Exception("No PMKSA cache entry found")
54     if pmksa2['opportunistic'] != '0':
55         raise Exception("Unexpected opportunistic PMKSA cache entry")
56
57     dev[0].dump_monitor()
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)
63     if ev is None:
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)
68     if pmksa1b is None:
69         raise Exception("No PMKSA cache entry found")
70     if pmksa['pmkid'] != pmksa1b['pmkid']:
71         raise Exception("Unexpected PMKID change for AP1")
72
73     dev[0].dump_monitor()
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")
80
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,
89                    scan_freq="2412")
90     pmksa = dev[0].get_pmksa(bssid)
91     if pmksa is None:
92         raise Exception("No PMKSA cache entry created")
93     if pmksa['opportunistic'] != '0':
94         raise Exception("Unexpected opportunistic PMKSA cache entry")
95
96     hostapd.add_ap(apdev[1]['ifname'], params)
97     bssid2 = apdev[1]['bssid']
98
99     dev[0].dump_monitor()
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)
104     if ev is None:
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)
108     if pmksa2 is None:
109         raise Exception("No PMKSA cache entry found")
110     if pmksa2['opportunistic'] != '0':
111         raise Exception("Unexpected opportunistic PMKSA cache entry")
112
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)
119     if ev is None:
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)
124     if pmksa1b is None:
125         raise Exception("No PMKSA cache entry found")
126     if pmksa['pmkid'] != pmksa1b['pmkid']:
127         raise Exception("Unexpected PMKID change for AP1")
128
129 def test_pmksa_cache_opportunistic(dev, apdev):
130     """Opportunistic PMKSA caching"""
131     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
132     params['okc'] = "1"
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,
138                    scan_freq="2412")
139     pmksa = dev[0].get_pmksa(bssid)
140     if pmksa is None:
141         raise Exception("No PMKSA cache entry created")
142     if pmksa['opportunistic'] != '0':
143         raise Exception("Unexpected opportunistic PMKSA cache entry")
144
145     hostapd.add_ap(apdev[1]['ifname'], params)
146     bssid2 = apdev[1]['bssid']
147
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)
154     if ev is None:
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)
159     if pmksa2 is None:
160         raise Exception("No PMKSA cache entry created")
161
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)
168     if ev is None:
169         raise Exception("Roaming with the AP timed out")
170     if "CTRL-EVENT-EAP-STARTED" in ev:
171         raise Exception("Unexpected EAP exchange")
172
173     pmksa1b = dev[0].get_pmksa(bssid)
174     if pmksa1b is None:
175         raise Exception("No PMKSA cache entry found")
176     if pmksa['pmkid'] != pmksa1b['pmkid']:
177         raise Exception("Unexpected PMKID change for AP1")
178
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")
182     params['okc'] = "1"
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,
190                  scan_freq="2412")
191     pmksa = wpas.get_pmksa(bssid)
192     if pmksa is None:
193         raise Exception("No PMKSA cache entry created")
194     if pmksa['opportunistic'] != '0':
195         raise Exception("Unexpected opportunistic PMKSA cache entry")
196
197     hostapd.add_ap(apdev[1]['ifname'], params)
198     bssid2 = apdev[1]['bssid']
199
200     wpas.dump_monitor()
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)
206     if ev is None:
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)
211     if pmksa2 is None:
212         raise Exception("No PMKSA cache entry created")
213
214     wpas.dump_monitor()
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)
220     if ev is None:
221         raise Exception("Roaming with the AP timed out")
222     if "CTRL-EVENT-EAP-STARTED" in ev:
223         raise Exception("Unexpected EAP exchange")
224
225     pmksa1b = wpas.get_pmksa(bssid)
226     if pmksa1b is None:
227         raise Exception("No PMKSA cache entry found")
228     if pmksa['pmkid'] != pmksa1b['pmkid']:
229         raise Exception("Unexpected PMKID change for AP1")
230
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",
240                    scan_freq="2412")
241     pmksa = dev[0].get_pmksa(bssid)
242     if pmksa is None:
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)
247     if ev is None:
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")
254
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",
265                    scan_freq="2412")
266     pmksa = dev[0].get_pmksa(bssid)
267     if pmksa is None:
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)
273     if ev is None:
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)
279     if ev is None:
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")
284
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",
297                    scan_freq="2412")
298     pmksa = dev[0].get_pmksa(bssid)
299     if pmksa is None:
300         raise Exception("No PMKSA cache entry created")
301     ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
302     if ev is None:
303         raise Exception("No connection event received from hostapd")
304
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)
312     if ev is None:
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)
317     if pmksa1b is None:
318         raise Exception("No PMKSA cache entry found")
319     if pmksa['pmkid'] != pmksa1b['pmkid']:
320         raise Exception("Unexpected PMKID change for AP1")
321
322     dev[0].request("REAUTHENTICATE")
323     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
324     if ev is None:
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":
329             break
330         time.sleep(0.1)
331     if state != "COMPLETED":
332         raise Exception("Reauthentication did not complete")
333
334 def test_pmksa_cache_preauth(dev, apdev):
335     """RSN pre-authentication to generate PMKSA cache entry"""
336     try:
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")
344
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")
352         success = False
353         status_seen = False
354         for i in range(0, 50):
355             if not status_seen:
356                 status = dev[0].request("STATUS")
357                 if "Pre-authentication EAPOL state machines:" in status:
358                     status_seen = True
359             time.sleep(0.1)
360             pmksa = dev[0].get_pmksa(bssid1)
361             if pmksa:
362                 success = True
363                 break
364         if not success:
365             raise Exception("No PMKSA cache entry created from pre-authentication")
366         if not status_seen:
367             raise Exception("Pre-authentication EAPOL status was not available")
368
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)
375         if ev is None:
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)
380         if pmksa2 is None:
381             raise Exception("No PMKSA cache entry")
382         if pmksa['pmkid'] != pmksa2['pmkid']:
383             raise Exception("Unexpected PMKID change")
384
385     finally:
386         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
387         subprocess.call(['brctl', 'delbr', 'ap-br0'])
388
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)"""
391     try:
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")
400
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")
409         success = False
410         status_seen = False
411         for i in range(0, 50):
412             if not status_seen:
413                 status = dev[0].request("STATUS")
414                 if "Pre-authentication EAPOL state machines:" in status:
415                     status_seen = True
416             time.sleep(0.1)
417             pmksa = dev[0].get_pmksa(bssid1)
418             if pmksa:
419                 success = True
420                 break
421         if not success:
422             raise Exception("No PMKSA cache entry created from pre-authentication")
423         if not status_seen:
424             raise Exception("Pre-authentication EAPOL status was not available")
425
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)
432         if ev is None:
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)
437         if pmksa2 is None:
438             raise Exception("No PMKSA cache entry")
439         if pmksa['pmkid'] != pmksa2['pmkid']:
440             raise Exception("Unexpected PMKID change")
441
442     finally:
443         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
444         subprocess.call(['brctl', 'delbr', 'ap-br0'])
445
446 def test_pmksa_cache_preauth_vlan_used(dev, apdev):
447     """RSN pre-authentication to generate PMKSA cache entry (station with VLAN set)"""
448     try:
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")
460
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")
470         success = False
471         status_seen = False
472         for i in range(0, 50):
473             if not status_seen:
474                 status = dev[0].request("STATUS")
475                 if "Pre-authentication EAPOL state machines:" in status:
476                     status_seen = True
477             time.sleep(0.1)
478             pmksa = dev[0].get_pmksa(bssid1)
479             if pmksa:
480                 success = True
481                 break
482         if not success:
483             raise Exception("No PMKSA cache entry created from pre-authentication")
484         if not status_seen:
485             raise Exception("Pre-authentication EAPOL status was not available")
486
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)
493         if ev is None:
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)
498         if pmksa2 is None:
499             raise Exception("No PMKSA cache entry")
500         if pmksa['pmkid'] != pmksa2['pmkid']:
501             raise Exception("Unexpected PMKID change")
502
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")
508
509     finally:
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'])
524
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",
534                    scan_freq="2412")
535
536     hostapd.add_ap(apdev[1]['ifname'], params)
537     bssid2 = apdev[1]['bssid']
538
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)
544     if ev is None:
545         raise Exception("EAP success timed out")
546     dev[0].wait_connected(timeout=10, error="Roaming timed out")
547
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)
554     if ev is None:
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)
559     if ev is None:
560         raise Exception("Roaming with the AP timed out")
561
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",
570                    scan_freq="2412")
571     ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
572     if ev is None:
573         raise Exception("No connection event received from hostapd")
574     dev[0].request("DISCONNECT")
575     time.sleep(5)
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)
580     if ev is None:
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")
588
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",
597                    scan_freq="2412")
598     dev[1].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
599                    eap="GPSK", identity="gpsk user",
600                    password="abcdefghijklmnop0123456789abcdef",
601                    scan_freq="2412")
602     dev[2].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
603                    eap="GPSK", identity="gpsk-user-session-timeout",
604                    password="abcdefghijklmnop0123456789abcdef",
605                    scan_freq="2412")
606
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",
612                  scan_freq="2412")
613
614     hostapd.add_ap(apdev[1]['ifname'], params)
615     bssid2 = apdev[1]['bssid']
616
617     logger.info("Roam to AP2")
618     for sta in [ dev[1], dev[0], dev[2], wpas ]:
619         sta.dump_monitor()
620         sta.scan_for_bss(bssid2, freq="2412")
621         sta.request("ROAM " + bssid2)
622         ev = sta.wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
623         if ev is None:
624             raise Exception("EAP success timed out")
625         sta.wait_connected(timeout=10, error="Roaming timed out")
626
627     logger.info("Roam back to AP1")
628     for sta in [ dev[1], wpas, dev[0], dev[2] ]:
629         sta.dump_monitor()
630         sta.scan(freq="2412")
631         sta.dump_monitor()
632         sta.request("ROAM " + bssid)
633         sta.wait_connected(timeout=10, error="Roaming timed out")
634         sta.dump_monitor()
635
636     time.sleep(4)
637
638     logger.info("Roam back to AP2")
639     for sta in [ dev[1], wpas, dev[0], dev[2] ]:
640         sta.dump_monitor()
641         sta.scan(freq="2412")
642         sta.dump_monitor()
643         sta.request("ROAM " + bssid2)
644         sta.wait_connected(timeout=10, error="Roaming timed out")
645         sta.dump_monitor()
646
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")
650     params['okc'] = "1"
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,
659                     scan_freq="2412")
660
661     hostapd.add_ap(apdev[1]['ifname'], params)
662     bssid2 = apdev[1]['bssid']
663
664     logger.info("Roam to AP2")
665     for sta in [ dev[2], dev[0], wpas, dev[1] ]:
666         sta.dump_monitor()
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)
672         if ev is None:
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)
677         if pmksa2 is None:
678             raise Exception("No PMKSA cache entry created")
679
680     logger.info("Roam back to AP1")
681     for sta in [ dev[0], dev[1], dev[2], wpas ]:
682         sta.dump_monitor()
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)
687         if ev is None:
688             raise Exception("Roaming with the AP timed out")
689         if "CTRL-EVENT-EAP-STARTED" in ev:
690             raise Exception("Unexpected EAP exchange")
691
692 def test_pmksa_cache_preauth_oom(dev, apdev):
693     """RSN pre-authentication to generate PMKSA cache entry and OOM"""
694     try:
695         _test_pmksa_cache_preauth_oom(dev, apdev)
696     finally:
697         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
698         subprocess.call(['brctl', 'delbr', 'ap-br0'])
699
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'])
709
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']
716
717     tests = [ (1, "rsn_preauth_receive"),
718               (2, "rsn_preauth_receive"),
719               (1, "rsn_preauth_send") ]
720     for test in tests:
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")
725
726             success = False
727             count = 0
728             for i in range(50):
729                 time.sleep(0.1)
730                 pmksa = dev[0].get_pmksa(bssid1)
731                 if pmksa:
732                     success = True
733                     break
734                 state = hapd.request('GET_ALLOC_FAIL')
735                 if state.startswith('0:'):
736                     count += 1
737                     if count > 2:
738                         break
739             logger.info("PMKSA cache success: " + str(success))
740
741             dev[0].request("PMKSA_FLUSH")
742             dev[0].wait_disconnected()
743             dev[0].wait_connected()
744             dev[0].dump_monitor()
745
746 def test_pmksa_cache_size_limit(dev, apdev):
747     """PMKSA cache size limit in wpa_supplicant"""
748     try:
749         _test_pmksa_cache_size_limit(dev, apdev)
750     finally:
751         try:
752             hapd = hostapd.HostapdGlobal()
753             hapd.flush()
754             hapd.remove(apdev[0]['ifname'])
755         except:
756             pass
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)
761
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)
768     for i in range(33):
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
781         if i == 32:
782             if entries != 32:
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")
786
787         hapd = hostapd.HostapdGlobal()
788         hapd.flush()
789         hapd.remove(apdev[0]['ifname'])
790
791 def test_pmksa_cache_preauth_timeout(dev, apdev):
792     """RSN pre-authentication timing out"""
793     try:
794         _test_pmksa_cache_preauth_timeout(dev, apdev)
795     finally:
796         dev[0].request("SET dot11RSNAConfigSATimeout 60")
797
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)
808     if ev is None:
809         raise Exception("No timeout event seen")
810     if "timed out" not in ev:
811         raise Exception("Unexpected event: " + ev)
812
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))
824             for j in range(10):
825                 state = dev[0].request('GET_ALLOC_FAIL')
826                 if state.startswith('0:'):
827                     break
828                 time.sleep(0.05)