1 # WPA2-Enterprise PMKSA caching tests
2 # Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi>
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
8 logger = logging.getLogger()
13 from wpasupplicant import WpaSupplicant
14 from test_ap_eap import eap_connect
16 def test_pmksa_cache_on_roam_back(dev, apdev):
17 """PMKSA cache to skip EAP on reassociation back to same AP"""
18 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
19 hostapd.add_ap(apdev[0]['ifname'], params)
20 bssid = apdev[0]['bssid']
21 dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
22 eap="GPSK", identity="gpsk user",
23 password="abcdefghijklmnop0123456789abcdef",
25 pmksa = dev[0].get_pmksa(bssid)
27 raise Exception("No PMKSA cache entry created")
28 if pmksa['opportunistic'] != '0':
29 raise Exception("Unexpected opportunistic PMKSA cache entry")
31 hostapd.add_ap(apdev[1]['ifname'], params)
32 bssid2 = apdev[1]['bssid']
35 logger.info("Roam to AP2")
36 # It can take some time for the second AP to become ready to reply to Probe
37 # Request frames especially under heavy CPU load, so allow couple of rounds
38 # of scanning to avoid reporting errors incorrectly just because of scans
39 # not having seen the target AP.
40 for i in range(0, 10):
41 dev[0].scan(freq="2412")
42 if dev[0].get_bss(bssid2) is not None:
44 logger.info("Scan again to find target AP")
45 dev[0].request("ROAM " + bssid2)
46 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
48 raise Exception("EAP success timed out")
49 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
51 raise Exception("Roaming with the AP timed out")
52 pmksa2 = dev[0].get_pmksa(bssid2)
54 raise Exception("No PMKSA cache entry found")
55 if pmksa2['opportunistic'] != '0':
56 raise Exception("Unexpected opportunistic PMKSA cache entry")
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)
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)
70 raise Exception("No PMKSA cache entry found")
71 if pmksa['pmkid'] != pmksa1b['pmkid']:
72 raise Exception("Unexpected PMKID change for AP1")
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)
81 raise Exception("Disconnection event timed out")
82 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
84 raise Exception("Reconnection timed out")
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,
95 pmksa = dev[0].get_pmksa(bssid)
97 raise Exception("No PMKSA cache entry created")
98 if pmksa['opportunistic'] != '0':
99 raise Exception("Unexpected opportunistic PMKSA cache entry")
101 hostapd.add_ap(apdev[1]['ifname'], params)
102 bssid2 = apdev[1]['bssid']
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)
110 raise Exception("EAP success timed out")
111 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
113 raise Exception("Roaming with the AP timed out")
114 pmksa2 = dev[0].get_pmksa(bssid2)
116 raise Exception("No PMKSA cache entry found")
117 if pmksa2['opportunistic'] != '0':
118 raise Exception("Unexpected opportunistic PMKSA cache entry")
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)
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)
132 raise Exception("No PMKSA cache entry found")
133 if pmksa['pmkid'] != pmksa1b['pmkid']:
134 raise Exception("Unexpected PMKID change for AP1")
136 def test_pmksa_cache_opportunistic(dev, apdev):
137 """Opportunistic PMKSA caching"""
138 params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
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,
146 pmksa = dev[0].get_pmksa(bssid)
148 raise Exception("No PMKSA cache entry created")
149 if pmksa['opportunistic'] != '0':
150 raise Exception("Unexpected opportunistic PMKSA cache entry")
152 hostapd.add_ap(apdev[1]['ifname'], params)
153 bssid2 = apdev[1]['bssid']
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)
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)
167 raise Exception("No PMKSA cache entry created")
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)
176 raise Exception("Roaming with the AP timed out")
177 if "CTRL-EVENT-EAP-STARTED" in ev:
178 raise Exception("Unexpected EAP exchange")
180 pmksa1b = dev[0].get_pmksa(bssid)
182 raise Exception("No PMKSA cache entry found")
183 if pmksa['pmkid'] != pmksa1b['pmkid']:
184 raise Exception("Unexpected PMKID change for AP1")
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")
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,
198 pmksa = wpas.get_pmksa(bssid)
200 raise Exception("No PMKSA cache entry created")
201 if pmksa['opportunistic'] != '0':
202 raise Exception("Unexpected opportunistic PMKSA cache entry")
204 hostapd.add_ap(apdev[1]['ifname'], params)
205 bssid2 = apdev[1]['bssid']
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)
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)
219 raise Exception("No PMKSA cache entry created")
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)
228 raise Exception("Roaming with the AP timed out")
229 if "CTRL-EVENT-EAP-STARTED" in ev:
230 raise Exception("Unexpected EAP exchange")
232 pmksa1b = wpas.get_pmksa(bssid)
234 raise Exception("No PMKSA cache entry found")
235 if pmksa['pmkid'] != pmksa1b['pmkid']:
236 raise Exception("Unexpected PMKID change for AP1")
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",
248 pmksa = dev[0].get_pmksa(bssid)
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)
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")
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",
273 pmksa = dev[0].get_pmksa(bssid)
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)
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)
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")
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",
305 pmksa = dev[0].get_pmksa(bssid)
307 raise Exception("No PMKSA cache entry created")
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)
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)
321 raise Exception("No PMKSA cache entry found")
322 if pmksa['pmkid'] != pmksa1b['pmkid']:
323 raise Exception("Unexpected PMKID change for AP1")
325 dev[0].request("REAUTHENTICATE")
326 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
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":
334 if state != "COMPLETED":
335 raise Exception("Reauthentication did not complete")
337 def test_pmksa_cache_preauth(dev, apdev):
338 """RSN pre-authentication to generate PMKSA cache entry"""
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")
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")
357 for i in range(0, 50):
359 status = dev[0].request("STATUS")
360 if "Pre-authentication EAPOL state machines:" in status:
363 pmksa = dev[0].get_pmksa(bssid1)
368 raise Exception("No PMKSA cache entry created from pre-authentication")
370 raise Exception("Pre-authentication EAPOL status was not available")
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)
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)
384 raise Exception("No PMKSA cache entry")
385 if pmksa['pmkid'] != pmksa2['pmkid']:
386 raise Exception("Unexpected PMKID change")
389 subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
390 subprocess.call(['sudo', 'brctl', 'delbr', 'ap-br0'])
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",
403 hostapd.add_ap(apdev[1]['ifname'], params)
404 bssid2 = apdev[1]['bssid']
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)
412 raise Exception("EAP success timed out")
413 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
415 raise Exception("Roaming with the AP timed out")
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)
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)
429 raise Exception("Roaming with the AP timed out")
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",
440 dev[0].request("DISCONNECT")
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)
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)
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)
456 raise Exception("Disconnection event timed out")
457 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=20)
459 raise Exception("Reassociation with the AP timed out")