tests: PMKSA caching and EAPOL reauthentication
[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 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_and_reauth(dev, apdev):
82     """PMKSA caching and EAPOL reauthentication"""
83     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
84     hapd = 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",
89                    scan_freq="2412")
90
91     hostapd.add_ap(apdev[1]['ifname'], params)
92     bssid2 = apdev[1]['bssid']
93
94     dev[0].dump_monitor()
95     logger.info("Roam to AP2")
96     # It can take some time for the second AP to become ready to reply to Probe
97     # Request frames especially under heavy CPU load, so allow couple of rounds
98     # of scanning to avoid reporting errors incorrectly just because of scans
99     # not having seen the target AP.
100     for i in range(0, 10):
101         dev[0].scan(freq="2412")
102         if dev[0].get_bss(bssid2) is not None:
103             break
104         logger.info("Scan again to find target AP")
105     dev[0].request("ROAM " + bssid2)
106     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
107     if ev is None:
108         raise Exception("EAP success timed out")
109     dev[0].wait_connected(timeout=10, error="Roaming timed out")
110
111     dev[0].dump_monitor()
112     logger.info("Roam back to AP1")
113     dev[0].scan(freq="2412")
114     dev[0].request("ROAM " + bssid)
115     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
116                             "CTRL-EVENT-CONNECTED"], timeout=10)
117     if ev is None:
118         raise Exception("Roaming with the AP timed out")
119     if "CTRL-EVENT-EAP-STARTED" in ev:
120         raise Exception("Unexpected EAP exchange")
121
122     # Verify EAPOL reauthentication after PMKSA caching
123     hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
124     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
125     if ev is None:
126         raise Exception("EAP authentication did not start")
127     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
128     if ev is None:
129         raise Exception("EAP authentication did not succeed")
130
131 def test_pmksa_cache_opportunistic_only_on_sta(dev, apdev):
132     """Opportunistic PMKSA caching enabled only on station"""
133     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
134     hostapd.add_ap(apdev[0]['ifname'], params)
135     bssid = apdev[0]['bssid']
136     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
137                    eap="GPSK", identity="gpsk user",
138                    password="abcdefghijklmnop0123456789abcdef", okc=True,
139                    scan_freq="2412")
140     pmksa = dev[0].get_pmksa(bssid)
141     if pmksa is None:
142         raise Exception("No PMKSA cache entry created")
143     if pmksa['opportunistic'] != '0':
144         raise Exception("Unexpected opportunistic PMKSA cache entry")
145
146     hostapd.add_ap(apdev[1]['ifname'], params)
147     bssid2 = apdev[1]['bssid']
148
149     dev[0].dump_monitor()
150     logger.info("Roam to AP2")
151     dev[0].scan(freq="2412")
152     dev[0].request("ROAM " + bssid2)
153     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
154     if ev is None:
155         raise Exception("EAP success timed out")
156     dev[0].wait_connected(timeout=10, error="Roaming timed out")
157     pmksa2 = dev[0].get_pmksa(bssid2)
158     if pmksa2 is None:
159         raise Exception("No PMKSA cache entry found")
160     if pmksa2['opportunistic'] != '0':
161         raise Exception("Unexpected opportunistic PMKSA cache entry")
162
163     dev[0].dump_monitor()
164     logger.info("Roam back to AP1")
165     dev[0].scan(freq="2412")
166     dev[0].request("ROAM " + bssid)
167     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
168                             "CTRL-EVENT-CONNECTED"], timeout=10)
169     if ev is None:
170         raise Exception("Roaming with the AP timed out")
171     if "CTRL-EVENT-EAP-STARTED" in ev:
172         raise Exception("Unexpected EAP exchange")
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(dev, apdev):
180     """Opportunistic PMKSA caching"""
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     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
186                    eap="GPSK", identity="gpsk user",
187                    password="abcdefghijklmnop0123456789abcdef", okc=True,
188                    scan_freq="2412")
189     pmksa = dev[0].get_pmksa(bssid)
190     if pmksa is None:
191         raise Exception("No PMKSA cache entry created")
192     if pmksa['opportunistic'] != '0':
193         raise Exception("Unexpected opportunistic PMKSA cache entry")
194
195     hostapd.add_ap(apdev[1]['ifname'], params)
196     bssid2 = apdev[1]['bssid']
197
198     dev[0].dump_monitor()
199     logger.info("Roam to AP2")
200     dev[0].scan(freq="2412")
201     dev[0].request("ROAM " + bssid2)
202     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
203                             "CTRL-EVENT-CONNECTED"], timeout=10)
204     if ev is None:
205         raise Exception("Roaming with the AP timed out")
206     if "CTRL-EVENT-EAP-STARTED" in ev:
207         raise Exception("Unexpected EAP exchange")
208     pmksa2 = dev[0].get_pmksa(bssid2)
209     if pmksa2 is None:
210         raise Exception("No PMKSA cache entry created")
211
212     dev[0].dump_monitor()
213     logger.info("Roam back to AP1")
214     dev[0].scan(freq="2412")
215     dev[0].request("ROAM " + bssid)
216     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
217                             "CTRL-EVENT-CONNECTED"], timeout=10)
218     if ev is None:
219         raise Exception("Roaming with the AP timed out")
220     if "CTRL-EVENT-EAP-STARTED" in ev:
221         raise Exception("Unexpected EAP exchange")
222
223     pmksa1b = dev[0].get_pmksa(bssid)
224     if pmksa1b is None:
225         raise Exception("No PMKSA cache entry found")
226     if pmksa['pmkid'] != pmksa1b['pmkid']:
227         raise Exception("Unexpected PMKID change for AP1")
228
229 def test_pmksa_cache_opportunistic_connect(dev, apdev):
230     """Opportunistic PMKSA caching with connect API"""
231     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
232     params['okc'] = "1"
233     hostapd.add_ap(apdev[0]['ifname'], params)
234     bssid = apdev[0]['bssid']
235     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
236     wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
237     wpas.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
238                  eap="GPSK", identity="gpsk user",
239                  password="abcdefghijklmnop0123456789abcdef", okc=True,
240                  scan_freq="2412")
241     pmksa = wpas.get_pmksa(bssid)
242     if pmksa is None:
243         raise Exception("No PMKSA cache entry created")
244     if pmksa['opportunistic'] != '0':
245         raise Exception("Unexpected opportunistic PMKSA cache entry")
246
247     hostapd.add_ap(apdev[1]['ifname'], params)
248     bssid2 = apdev[1]['bssid']
249
250     wpas.dump_monitor()
251     logger.info("Roam to AP2")
252     wpas.scan_for_bss(bssid2, freq="2412")
253     wpas.request("ROAM " + bssid2)
254     ev = wpas.wait_event(["CTRL-EVENT-EAP-STARTED",
255                             "CTRL-EVENT-CONNECTED"], timeout=10)
256     if ev is None:
257         raise Exception("Roaming with the AP timed out")
258     if "CTRL-EVENT-EAP-STARTED" in ev:
259         raise Exception("Unexpected EAP exchange")
260     pmksa2 = wpas.get_pmksa(bssid2)
261     if pmksa2 is None:
262         raise Exception("No PMKSA cache entry created")
263
264     wpas.dump_monitor()
265     logger.info("Roam back to AP1")
266     wpas.scan(freq="2412")
267     wpas.request("ROAM " + bssid)
268     ev = wpas.wait_event(["CTRL-EVENT-EAP-STARTED",
269                             "CTRL-EVENT-CONNECTED"], timeout=10)
270     if ev is None:
271         raise Exception("Roaming with the AP timed out")
272     if "CTRL-EVENT-EAP-STARTED" in ev:
273         raise Exception("Unexpected EAP exchange")
274
275     pmksa1b = wpas.get_pmksa(bssid)
276     if pmksa1b is None:
277         raise Exception("No PMKSA cache entry found")
278     if pmksa['pmkid'] != pmksa1b['pmkid']:
279         raise Exception("Unexpected PMKID change for AP1")
280
281 def test_pmksa_cache_expiration(dev, apdev):
282     """PMKSA cache entry expiration"""
283     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
284     hostapd.add_ap(apdev[0]['ifname'], params)
285     bssid = apdev[0]['bssid']
286     dev[0].request("SET dot11RSNAConfigPMKLifetime 10")
287     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
288                    eap="GPSK", identity="gpsk user",
289                    password="abcdefghijklmnop0123456789abcdef",
290                    scan_freq="2412")
291     pmksa = dev[0].get_pmksa(bssid)
292     if pmksa is None:
293         raise Exception("No PMKSA cache entry created")
294     logger.info("Wait for PMKSA cache entry to expire")
295     ev = dev[0].wait_event(["WPA: Key negotiation completed",
296                             "CTRL-EVENT-DISCONNECTED"], timeout=15)
297     if ev is None:
298         raise Exception("No EAP reauthentication seen")
299     if "CTRL-EVENT-DISCONNECTED" in ev:
300         raise Exception("Unexpected disconnection")
301     pmksa2 = dev[0].get_pmksa(bssid)
302     if pmksa['pmkid'] == pmksa2['pmkid']:
303         raise Exception("PMKID did not change")
304
305 def test_pmksa_cache_expiration_disconnect(dev, apdev):
306     """PMKSA cache entry expiration (disconnect)"""
307     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
308     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
309     bssid = apdev[0]['bssid']
310     dev[0].request("SET dot11RSNAConfigPMKLifetime 2")
311     dev[0].request("SET dot11RSNAConfigPMKReauthThreshold 100")
312     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
313                    eap="GPSK", identity="gpsk user",
314                    password="abcdefghijklmnop0123456789abcdef",
315                    scan_freq="2412")
316     pmksa = dev[0].get_pmksa(bssid)
317     if pmksa is None:
318         raise Exception("No PMKSA cache entry created")
319     hapd.request("SET auth_server_shared_secret incorrect")
320     logger.info("Wait for PMKSA cache entry to expire")
321     ev = dev[0].wait_event(["WPA: Key negotiation completed",
322                             "CTRL-EVENT-DISCONNECTED"], timeout=15)
323     if ev is None:
324         raise Exception("No EAP reauthentication seen")
325     if "CTRL-EVENT-DISCONNECTED" not in ev:
326         raise Exception("Missing disconnection")
327     hapd.request("SET auth_server_shared_secret radius")
328     ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=15)
329     if ev is None:
330         raise Exception("No EAP reauthentication seen")
331     pmksa2 = dev[0].get_pmksa(bssid)
332     if pmksa['pmkid'] == pmksa2['pmkid']:
333         raise Exception("PMKID did not change")
334
335 def test_pmksa_cache_and_cui(dev, apdev):
336     """PMKSA cache and Chargeable-User-Identity"""
337     params = hostapd.wpa2_eap_params(ssid="cui")
338     params['radius_request_cui'] = '1'
339     params['acct_server_addr'] = "127.0.0.1"
340     params['acct_server_port'] = "1813"
341     params['acct_server_shared_secret'] = "radius"
342     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
343     bssid = apdev[0]['bssid']
344     dev[0].connect("cui", proto="RSN", key_mgmt="WPA-EAP",
345                    eap="GPSK", identity="gpsk-cui",
346                    password="abcdefghijklmnop0123456789abcdef",
347                    scan_freq="2412")
348     pmksa = dev[0].get_pmksa(bssid)
349     if pmksa is None:
350         raise Exception("No PMKSA cache entry created")
351     ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
352     if ev is None:
353         raise Exception("No connection event received from hostapd")
354
355     dev[0].dump_monitor()
356     logger.info("Disconnect and reconnect to the same AP")
357     dev[0].request("DISCONNECT")
358     dev[0].wait_disconnected()
359     dev[0].request("RECONNECT")
360     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
361                             "CTRL-EVENT-CONNECTED"], timeout=10)
362     if ev is None:
363         raise Exception("Reconnect timed out")
364     if "CTRL-EVENT-EAP-STARTED" in ev:
365         raise Exception("Unexpected EAP exchange")
366     pmksa1b = dev[0].get_pmksa(bssid)
367     if pmksa1b is None:
368         raise Exception("No PMKSA cache entry found")
369     if pmksa['pmkid'] != pmksa1b['pmkid']:
370         raise Exception("Unexpected PMKID change for AP1")
371
372     dev[0].request("REAUTHENTICATE")
373     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
374     if ev is None:
375         raise Exception("EAP success timed out")
376     for i in range(0, 20):
377         state = dev[0].get_status_field("wpa_state")
378         if state == "COMPLETED":
379             break
380         time.sleep(0.1)
381     if state != "COMPLETED":
382         raise Exception("Reauthentication did not complete")
383
384 def test_pmksa_cache_preauth(dev, apdev):
385     """RSN pre-authentication to generate PMKSA cache entry"""
386     try:
387         params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
388         params['bridge'] = 'ap-br0'
389         hostapd.add_ap(apdev[0]['ifname'], params)
390         subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
391         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
392         eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
393                     password_hex="0123456789abcdef0123456789abcdef")
394
395         params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
396         params['bridge'] = 'ap-br0'
397         params['rsn_preauth'] = '1'
398         params['rsn_preauth_interfaces'] = 'ap-br0'
399         hostapd.add_ap(apdev[1]['ifname'], params)
400         bssid1 = apdev[1]['bssid']
401         dev[0].scan(freq="2412")
402         success = False
403         status_seen = False
404         for i in range(0, 50):
405             if not status_seen:
406                 status = dev[0].request("STATUS")
407                 if "Pre-authentication EAPOL state machines:" in status:
408                     status_seen = True
409             time.sleep(0.1)
410             pmksa = dev[0].get_pmksa(bssid1)
411             if pmksa:
412                 success = True
413                 break
414         if not success:
415             raise Exception("No PMKSA cache entry created from pre-authentication")
416         if not status_seen:
417             raise Exception("Pre-authentication EAPOL status was not available")
418
419         dev[0].scan(freq="2412")
420         if "[WPA2-EAP-CCMP-preauth]" not in dev[0].request("SCAN_RESULTS"):
421             raise Exception("Scan results missing RSN element info")
422         dev[0].request("ROAM " + bssid1)
423         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
424                                 "CTRL-EVENT-CONNECTED"], timeout=10)
425         if ev is None:
426             raise Exception("Roaming with the AP timed out")
427         if "CTRL-EVENT-EAP-STARTED" in ev:
428             raise Exception("Unexpected EAP exchange")
429         pmksa2 = dev[0].get_pmksa(bssid1)
430         if pmksa2 is None:
431             raise Exception("No PMKSA cache entry")
432         if pmksa['pmkid'] != pmksa2['pmkid']:
433             raise Exception("Unexpected PMKID change")
434
435     finally:
436         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
437         subprocess.call(['brctl', 'delbr', 'ap-br0'])
438
439 def test_pmksa_cache_preauth_vlan_enabled(dev, apdev):
440     """RSN pre-authentication to generate PMKSA cache entry (dynamic_vlan optional but station without VLAN set)"""
441     try:
442         params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
443         params['bridge'] = 'ap-br0'
444         params['dynamic_vlan'] = '1'
445         hostapd.add_ap(apdev[0]['ifname'], params)
446         subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
447         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
448         eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
449                     password_hex="0123456789abcdef0123456789abcdef")
450
451         params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
452         params['bridge'] = 'ap-br0'
453         params['rsn_preauth'] = '1'
454         params['rsn_preauth_interfaces'] = 'ap-br0'
455         params['dynamic_vlan'] = '1'
456         hostapd.add_ap(apdev[1]['ifname'], params)
457         bssid1 = apdev[1]['bssid']
458         dev[0].scan(freq="2412")
459         success = False
460         status_seen = False
461         for i in range(0, 50):
462             if not status_seen:
463                 status = dev[0].request("STATUS")
464                 if "Pre-authentication EAPOL state machines:" in status:
465                     status_seen = True
466             time.sleep(0.1)
467             pmksa = dev[0].get_pmksa(bssid1)
468             if pmksa:
469                 success = True
470                 break
471         if not success:
472             raise Exception("No PMKSA cache entry created from pre-authentication")
473         if not status_seen:
474             raise Exception("Pre-authentication EAPOL status was not available")
475
476         dev[0].scan(freq="2412")
477         if "[WPA2-EAP-CCMP-preauth]" not in dev[0].request("SCAN_RESULTS"):
478             raise Exception("Scan results missing RSN element info")
479         dev[0].request("ROAM " + bssid1)
480         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
481                                 "CTRL-EVENT-CONNECTED"], timeout=10)
482         if ev is None:
483             raise Exception("Roaming with the AP timed out")
484         if "CTRL-EVENT-EAP-STARTED" in ev:
485             raise Exception("Unexpected EAP exchange")
486         pmksa2 = dev[0].get_pmksa(bssid1)
487         if pmksa2 is None:
488             raise Exception("No PMKSA cache entry")
489         if pmksa['pmkid'] != pmksa2['pmkid']:
490             raise Exception("Unexpected PMKID change")
491
492     finally:
493         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
494         subprocess.call(['brctl', 'delbr', 'ap-br0'])
495
496 def test_pmksa_cache_preauth_vlan_used(dev, apdev):
497     """RSN pre-authentication to generate PMKSA cache entry (station with VLAN set)"""
498     try:
499         subprocess.call(['brctl', 'addbr', 'brvlan1'])
500         subprocess.call(['brctl', 'setfd', 'brvlan1', '0'])
501         params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
502         params['bridge'] = 'ap-br0'
503         params['dynamic_vlan'] = '1'
504         params['vlan_file'] = 'hostapd.wlan3.vlan'
505         hapd = hostapd.add_ap(apdev[0]['ifname'], params)
506         subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
507         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
508         eap_connect(dev[0], apdev[0], "PAX", "vlan1",
509                     password_hex="0123456789abcdef0123456789abcdef")
510
511         params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
512         params['bridge'] = 'ap-br0'
513         params['rsn_preauth'] = '1'
514         params['rsn_preauth_interfaces'] = 'brvlan1'
515         params['dynamic_vlan'] = '1'
516         params['vlan_file'] = 'hostapd.wlan4.vlan'
517         hostapd.add_ap(apdev[1]['ifname'], params)
518         bssid1 = apdev[1]['bssid']
519         dev[0].scan(freq="2412")
520         success = False
521         status_seen = False
522         for i in range(0, 50):
523             if not status_seen:
524                 status = dev[0].request("STATUS")
525                 if "Pre-authentication EAPOL state machines:" in status:
526                     status_seen = True
527             time.sleep(0.1)
528             pmksa = dev[0].get_pmksa(bssid1)
529             if pmksa:
530                 success = True
531                 break
532         if not success:
533             raise Exception("No PMKSA cache entry created from pre-authentication")
534         if not status_seen:
535             raise Exception("Pre-authentication EAPOL status was not available")
536
537         dev[0].scan(freq="2412")
538         if "[WPA2-EAP-CCMP-preauth]" not in dev[0].request("SCAN_RESULTS"):
539             raise Exception("Scan results missing RSN element info")
540         dev[0].request("ROAM " + bssid1)
541         ev = dev[0].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")
547         pmksa2 = dev[0].get_pmksa(bssid1)
548         if pmksa2 is None:
549             raise Exception("No PMKSA cache entry")
550         if pmksa['pmkid'] != pmksa2['pmkid']:
551             raise Exception("Unexpected PMKID change")
552
553         # Disconnect the STA from both APs to avoid forceful ifdown by the
554         # test script on a VLAN that this has an associated STA. That used to
555         # trigger a mac80211 warning.
556         dev[0].request("DISCONNECT")
557         hapd.request("DISABLE")
558
559     finally:
560         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
561                         stderr=open('/dev/null', 'w'))
562         subprocess.call(['ip', 'link', 'set', 'dev', 'brvlan1', 'down'])
563         subprocess.call(['ip', 'link', 'set', 'dev', 'wlan3.1', 'down'],
564                         stderr=open('/dev/null', 'w'))
565         subprocess.call(['ip', 'link', 'set', 'dev', 'wlan4.1', 'down'],
566                         stderr=open('/dev/null', 'w'))
567         subprocess.call(['brctl', 'delif', 'brvlan1', 'wlan3.1'],
568                         stderr=open('/dev/null', 'w'))
569         subprocess.call(['brctl', 'delif', 'brvlan1', 'wlan4.1'],
570                         stderr=open('/dev/null', 'w'))
571         subprocess.call(['brctl', 'delbr', 'ap-br0'],
572                         stderr=open('/dev/null', 'w'))
573         subprocess.call(['brctl', 'delbr', 'brvlan1'])
574
575 def test_pmksa_cache_disabled(dev, apdev):
576     """PMKSA cache disabling on AP"""
577     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
578     params['disable_pmksa_caching'] = '1'
579     hostapd.add_ap(apdev[0]['ifname'], params)
580     bssid = apdev[0]['bssid']
581     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
582                    eap="GPSK", identity="gpsk user",
583                    password="abcdefghijklmnop0123456789abcdef",
584                    scan_freq="2412")
585
586     hostapd.add_ap(apdev[1]['ifname'], params)
587     bssid2 = apdev[1]['bssid']
588
589     dev[0].dump_monitor()
590     logger.info("Roam to AP2")
591     dev[0].scan_for_bss(bssid2, freq="2412")
592     dev[0].request("ROAM " + bssid2)
593     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
594     if ev is None:
595         raise Exception("EAP success timed out")
596     dev[0].wait_connected(timeout=10, error="Roaming timed out")
597
598     dev[0].dump_monitor()
599     logger.info("Roam back to AP1")
600     dev[0].scan(freq="2412")
601     dev[0].request("ROAM " + bssid)
602     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
603                             "CTRL-EVENT-CONNECTED"], timeout=20)
604     if ev is None:
605         raise Exception("Roaming with the AP timed out")
606     if "CTRL-EVENT-CONNECTED" in ev:
607         raise Exception("EAP exchange missing")
608     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=20)
609     if ev is None:
610         raise Exception("Roaming with the AP timed out")
611
612 def test_pmksa_cache_ap_expiration(dev, apdev):
613     """PMKSA cache entry expiring on AP"""
614     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
615     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
616     bssid = apdev[0]['bssid']
617     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
618                    eap="GPSK", identity="gpsk-user-session-timeout",
619                    password="abcdefghijklmnop0123456789abcdef",
620                    scan_freq="2412")
621     ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
622     if ev is None:
623         raise Exception("No connection event received from hostapd")
624     dev[0].request("DISCONNECT")
625     time.sleep(5)
626     dev[0].dump_monitor()
627     dev[0].request("RECONNECT")
628     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
629                             "CTRL-EVENT-CONNECTED"], timeout=20)
630     if ev is None:
631         raise Exception("Roaming with the AP timed out")
632     if "CTRL-EVENT-CONNECTED" in ev:
633         raise Exception("EAP exchange missing")
634     dev[0].wait_connected(timeout=20, error="Reconnect timed out")
635     dev[0].dump_monitor()
636     dev[0].wait_disconnected(timeout=20)
637     dev[0].wait_connected(timeout=20, error="Reassociation timed out")
638
639 def test_pmksa_cache_multiple_sta(dev, apdev):
640     """PMKSA cache with multiple stations"""
641     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
642     hostapd.add_ap(apdev[0]['ifname'], params)
643     bssid = apdev[0]['bssid']
644     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
645                    eap="GPSK", identity="gpsk-user-session-timeout",
646                    password="abcdefghijklmnop0123456789abcdef",
647                    scan_freq="2412")
648     dev[1].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
649                    eap="GPSK", identity="gpsk user",
650                    password="abcdefghijklmnop0123456789abcdef",
651                    scan_freq="2412")
652     dev[2].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
653                    eap="GPSK", identity="gpsk-user-session-timeout",
654                    password="abcdefghijklmnop0123456789abcdef",
655                    scan_freq="2412")
656
657     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
658     wpas.interface_add("wlan5")
659     wpas.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
660                  eap="GPSK", identity="gpsk user",
661                  password="abcdefghijklmnop0123456789abcdef",
662                  scan_freq="2412")
663
664     hostapd.add_ap(apdev[1]['ifname'], params)
665     bssid2 = apdev[1]['bssid']
666
667     logger.info("Roam to AP2")
668     for sta in [ dev[1], dev[0], dev[2], wpas ]:
669         sta.dump_monitor()
670         sta.scan_for_bss(bssid2, freq="2412")
671         sta.request("ROAM " + bssid2)
672         ev = sta.wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
673         if ev is None:
674             raise Exception("EAP success timed out")
675         sta.wait_connected(timeout=10, error="Roaming timed out")
676
677     logger.info("Roam back to AP1")
678     for sta in [ dev[1], wpas, dev[0], dev[2] ]:
679         sta.dump_monitor()
680         sta.scan(freq="2412")
681         sta.dump_monitor()
682         sta.request("ROAM " + bssid)
683         sta.wait_connected(timeout=10, error="Roaming timed out")
684         sta.dump_monitor()
685
686     time.sleep(4)
687
688     logger.info("Roam back to AP2")
689     for sta in [ dev[1], wpas, dev[0], dev[2] ]:
690         sta.dump_monitor()
691         sta.scan(freq="2412")
692         sta.dump_monitor()
693         sta.request("ROAM " + bssid2)
694         sta.wait_connected(timeout=10, error="Roaming timed out")
695         sta.dump_monitor()
696
697 def test_pmksa_cache_opportunistic_multiple_sta(dev, apdev):
698     """Opportunistic PMKSA caching with multiple stations"""
699     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
700     params['okc'] = "1"
701     hostapd.add_ap(apdev[0]['ifname'], params)
702     bssid = apdev[0]['bssid']
703     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
704     wpas.interface_add("wlan5")
705     for sta in [ dev[0], dev[1], dev[2], wpas ]:
706         sta.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
707                     eap="GPSK", identity="gpsk user",
708                     password="abcdefghijklmnop0123456789abcdef", okc=True,
709                     scan_freq="2412")
710
711     hostapd.add_ap(apdev[1]['ifname'], params)
712     bssid2 = apdev[1]['bssid']
713
714     logger.info("Roam to AP2")
715     for sta in [ dev[2], dev[0], wpas, dev[1] ]:
716         sta.dump_monitor()
717         sta.scan_for_bss(bssid2, freq="2412")
718         if "OK" not in sta.request("ROAM " + bssid2):
719             raise Exception("ROAM command failed")
720         ev = sta.wait_event(["CTRL-EVENT-EAP-STARTED",
721                              "CTRL-EVENT-CONNECTED"], timeout=10)
722         if ev is None:
723             raise Exception("Roaming with the AP timed out")
724         if "CTRL-EVENT-EAP-STARTED" in ev:
725             raise Exception("Unexpected EAP exchange")
726         pmksa2 = sta.get_pmksa(bssid2)
727         if pmksa2 is None:
728             raise Exception("No PMKSA cache entry created")
729
730     logger.info("Roam back to AP1")
731     for sta in [ dev[0], dev[1], dev[2], wpas ]:
732         sta.dump_monitor()
733         sta.scan_for_bss(bssid, freq="2412")
734         sta.request("ROAM " + bssid)
735         ev = sta.wait_event(["CTRL-EVENT-EAP-STARTED",
736                              "CTRL-EVENT-CONNECTED"], timeout=10)
737         if ev is None:
738             raise Exception("Roaming with the AP timed out")
739         if "CTRL-EVENT-EAP-STARTED" in ev:
740             raise Exception("Unexpected EAP exchange")
741
742 def test_pmksa_cache_preauth_oom(dev, apdev):
743     """RSN pre-authentication to generate PMKSA cache entry and OOM"""
744     try:
745         _test_pmksa_cache_preauth_oom(dev, apdev)
746     finally:
747         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
748         subprocess.call(['brctl', 'delbr', 'ap-br0'])
749
750 def _test_pmksa_cache_preauth_oom(dev, apdev):
751     params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
752     params['bridge'] = 'ap-br0'
753     hostapd.add_ap(apdev[0]['ifname'], params)
754     subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
755     subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
756     eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
757                 password_hex="0123456789abcdef0123456789abcdef",
758                 bssid=apdev[0]['bssid'])
759
760     params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
761     params['bridge'] = 'ap-br0'
762     params['rsn_preauth'] = '1'
763     params['rsn_preauth_interfaces'] = 'ap-br0'
764     hapd = hostapd.add_ap(apdev[1]['ifname'], params)
765     bssid1 = apdev[1]['bssid']
766
767     tests = [ (1, "rsn_preauth_receive"),
768               (2, "rsn_preauth_receive"),
769               (1, "rsn_preauth_send") ]
770     for test in tests:
771         with alloc_fail(hapd, test[0], test[1]):
772             dev[0].scan_for_bss(bssid1, freq="2412")
773             if "OK" not in dev[0].request("PREAUTH " + bssid1):
774                 raise Exception("PREAUTH failed")
775
776             success = False
777             count = 0
778             for i in range(50):
779                 time.sleep(0.1)
780                 pmksa = dev[0].get_pmksa(bssid1)
781                 if pmksa:
782                     success = True
783                     break
784                 state = hapd.request('GET_ALLOC_FAIL')
785                 if state.startswith('0:'):
786                     count += 1
787                     if count > 2:
788                         break
789             logger.info("PMKSA cache success: " + str(success))
790
791             dev[0].request("PMKSA_FLUSH")
792             dev[0].wait_disconnected()
793             dev[0].wait_connected()
794             dev[0].dump_monitor()
795
796 def test_pmksa_cache_size_limit(dev, apdev):
797     """PMKSA cache size limit in wpa_supplicant"""
798     try:
799         _test_pmksa_cache_size_limit(dev, apdev)
800     finally:
801         try:
802             hapd = hostapd.HostapdGlobal()
803             hapd.flush()
804             hapd.remove(apdev[0]['ifname'])
805         except:
806             pass
807         params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
808         bssid = apdev[0]['bssid']
809         params['bssid'] = bssid
810         hostapd.add_ap(apdev[0]['ifname'], params)
811
812 def _test_pmksa_cache_size_limit(dev, apdev):
813     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
814     id = dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
815                         eap="GPSK", identity="gpsk user",
816                         password="abcdefghijklmnop0123456789abcdef",
817                         scan_freq="2412", only_add_network=True)
818     for i in range(33):
819         bssid = apdev[0]['bssid'][0:15] + "%02x" % i
820         logger.info("Iteration with BSSID " + bssid)
821         params['bssid'] = bssid
822         hostapd.add_ap(apdev[0]['ifname'], params)
823         dev[0].request("BSS_FLUSH 0")
824         dev[0].scan_for_bss(bssid, freq=2412, only_new=True)
825         dev[0].select_network(id)
826         dev[0].wait_connected()
827         dev[0].request("DISCONNECT")
828         dev[0].wait_disconnected()
829         dev[0].dump_monitor()
830         entries = len(dev[0].request("PMKSA").splitlines()) - 1
831         if i == 32:
832             if entries != 32:
833                 raise Exception("Unexpected number of PMKSA entries after expected removal of the oldest entry")
834         elif i + 1 != entries:
835             raise Exception("Unexpected number of PMKSA entries")
836
837         hapd = hostapd.HostapdGlobal()
838         hapd.flush()
839         hapd.remove(apdev[0]['ifname'])
840
841 def test_pmksa_cache_preauth_timeout(dev, apdev):
842     """RSN pre-authentication timing out"""
843     try:
844         _test_pmksa_cache_preauth_timeout(dev, apdev)
845     finally:
846         dev[0].request("SET dot11RSNAConfigSATimeout 60")
847
848 def _test_pmksa_cache_preauth_timeout(dev, apdev):
849     dev[0].request("SET dot11RSNAConfigSATimeout 1")
850     params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
851     hostapd.add_ap(apdev[0]['ifname'], params)
852     eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
853                 password_hex="0123456789abcdef0123456789abcdef",
854                 bssid=apdev[0]['bssid'])
855     if "OK" not in dev[0].request("PREAUTH f2:11:22:33:44:55"):
856         raise Exception("PREAUTH failed")
857     ev = dev[0].wait_event(["RSN: pre-authentication with"], timeout=5)
858     if ev is None:
859         raise Exception("No timeout event seen")
860     if "timed out" not in ev:
861         raise Exception("Unexpected event: " + ev)
862
863 def test_pmksa_cache_preauth_wpas_oom(dev, apdev):
864     """RSN pre-authentication OOM in wpa_supplicant"""
865     params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
866     hostapd.add_ap(apdev[0]['ifname'], params)
867     eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
868                 password_hex="0123456789abcdef0123456789abcdef",
869                 bssid=apdev[0]['bssid'])
870     for i in range(1, 11):
871         with alloc_fail(dev[0], i, "rsn_preauth_init"):
872             res = dev[0].request("PREAUTH f2:11:22:33:44:55").strip()
873             logger.info("Iteration %d - PREAUTH command results: %s" % (i, res))
874             for j in range(10):
875                 state = dev[0].request('GET_ALLOC_FAIL')
876                 if state.startswith('0:'):
877                     break
878                 time.sleep(0.05)