tests: Verify network information in SCAN_RESULTS
[mech_eap.git] / tests / hwsim / test_pmksa_cache.py
1 # WPA2-Enterprise PMKSA caching tests
2 # Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi>
3 #
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
6
7 import logging
8 logger = logging.getLogger()
9 import subprocess
10 import time
11
12 import hostapd
13 from wpasupplicant import WpaSupplicant
14 from test_ap_eap import eap_connect
15
16 def test_pmksa_cache_on_roam_back(dev, apdev):
17     """PMKSA cache to skip EAP on reassociation back to same AP"""
18     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
19     hostapd.add_ap(apdev[0]['ifname'], params)
20     bssid = apdev[0]['bssid']
21     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
22                    eap="GPSK", identity="gpsk user",
23                    password="abcdefghijklmnop0123456789abcdef",
24                    scan_freq="2412")
25     pmksa = dev[0].get_pmksa(bssid)
26     if pmksa is None:
27         raise Exception("No PMKSA cache entry created")
28     if pmksa['opportunistic'] != '0':
29         raise Exception("Unexpected opportunistic PMKSA cache entry")
30
31     hostapd.add_ap(apdev[1]['ifname'], params)
32     bssid2 = apdev[1]['bssid']
33
34     dev[0].dump_monitor()
35     logger.info("Roam to AP2")
36     dev[0].scan(freq="2412")
37     dev[0].request("ROAM " + bssid2)
38     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
39     if ev is None:
40         raise Exception("EAP success timed out")
41     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
42     if ev is None:
43         raise Exception("Roaming with the AP timed out")
44     pmksa2 = dev[0].get_pmksa(bssid2)
45     if pmksa2 is None:
46         raise Exception("No PMKSA cache entry found")
47     if pmksa2['opportunistic'] != '0':
48         raise Exception("Unexpected opportunistic PMKSA cache entry")
49
50     dev[0].dump_monitor()
51     logger.info("Roam back to AP1")
52     dev[0].scan(freq="2412")
53     dev[0].request("ROAM " + bssid)
54     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
55                             "CTRL-EVENT-CONNECTED"], timeout=10)
56     if ev is None:
57         raise Exception("Roaming with the AP timed out")
58     if "CTRL-EVENT-EAP-STARTED" in ev:
59         raise Exception("Unexpected EAP exchange")
60     pmksa1b = dev[0].get_pmksa(bssid)
61     if pmksa1b is None:
62         raise Exception("No PMKSA cache entry found")
63     if pmksa['pmkid'] != pmksa1b['pmkid']:
64         raise Exception("Unexpected PMKID change for AP1")
65
66 def test_pmksa_cache_opportunistic_only_on_sta(dev, apdev):
67     """Opportunistic PMKSA caching enabled only on station"""
68     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
69     hostapd.add_ap(apdev[0]['ifname'], params)
70     bssid = apdev[0]['bssid']
71     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
72                    eap="GPSK", identity="gpsk user",
73                    password="abcdefghijklmnop0123456789abcdef", okc=True,
74                    scan_freq="2412")
75     pmksa = dev[0].get_pmksa(bssid)
76     if pmksa is None:
77         raise Exception("No PMKSA cache entry created")
78     if pmksa['opportunistic'] != '0':
79         raise Exception("Unexpected opportunistic PMKSA cache entry")
80
81     hostapd.add_ap(apdev[1]['ifname'], params)
82     bssid2 = apdev[1]['bssid']
83
84     dev[0].dump_monitor()
85     logger.info("Roam to AP2")
86     dev[0].scan(freq="2412")
87     dev[0].request("ROAM " + bssid2)
88     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
89     if ev is None:
90         raise Exception("EAP success timed out")
91     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
92     if ev is None:
93         raise Exception("Roaming with the AP timed out")
94     pmksa2 = dev[0].get_pmksa(bssid2)
95     if pmksa2 is None:
96         raise Exception("No PMKSA cache entry found")
97     if pmksa2['opportunistic'] != '0':
98         raise Exception("Unexpected opportunistic PMKSA cache entry")
99
100     dev[0].dump_monitor()
101     logger.info("Roam back to AP1")
102     dev[0].scan(freq="2412")
103     dev[0].request("ROAM " + bssid)
104     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
105                             "CTRL-EVENT-CONNECTED"], timeout=10)
106     if ev is None:
107         raise Exception("Roaming with the AP timed out")
108     if "CTRL-EVENT-EAP-STARTED" in ev:
109         raise Exception("Unexpected EAP exchange")
110     pmksa1b = dev[0].get_pmksa(bssid)
111     if pmksa1b is None:
112         raise Exception("No PMKSA cache entry found")
113     if pmksa['pmkid'] != pmksa1b['pmkid']:
114         raise Exception("Unexpected PMKID change for AP1")
115
116 def test_pmksa_cache_opportunistic(dev, apdev):
117     """Opportunistic PMKSA caching"""
118     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
119     params['okc'] = "1"
120     hostapd.add_ap(apdev[0]['ifname'], params)
121     bssid = apdev[0]['bssid']
122     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
123                    eap="GPSK", identity="gpsk user",
124                    password="abcdefghijklmnop0123456789abcdef", okc=True,
125                    scan_freq="2412")
126     pmksa = dev[0].get_pmksa(bssid)
127     if pmksa is None:
128         raise Exception("No PMKSA cache entry created")
129     if pmksa['opportunistic'] != '0':
130         raise Exception("Unexpected opportunistic PMKSA cache entry")
131
132     hostapd.add_ap(apdev[1]['ifname'], params)
133     bssid2 = apdev[1]['bssid']
134
135     dev[0].dump_monitor()
136     logger.info("Roam to AP2")
137     dev[0].scan(freq="2412")
138     dev[0].request("ROAM " + bssid2)
139     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
140                             "CTRL-EVENT-CONNECTED"], timeout=10)
141     if ev is None:
142         raise Exception("Roaming with the AP timed out")
143     if "CTRL-EVENT-EAP-STARTED" in ev:
144         raise Exception("Unexpected EAP exchange")
145     pmksa2 = dev[0].get_pmksa(bssid2)
146     if pmksa2 is None:
147         raise Exception("No PMKSA cache entry created")
148
149     dev[0].dump_monitor()
150     logger.info("Roam back to AP1")
151     dev[0].scan(freq="2412")
152     dev[0].request("ROAM " + bssid)
153     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
154                             "CTRL-EVENT-CONNECTED"], timeout=10)
155     if ev is None:
156         raise Exception("Roaming with the AP timed out")
157     if "CTRL-EVENT-EAP-STARTED" in ev:
158         raise Exception("Unexpected EAP exchange")
159
160     pmksa1b = dev[0].get_pmksa(bssid)
161     if pmksa1b is None:
162         raise Exception("No PMKSA cache entry found")
163     if pmksa['pmkid'] != pmksa1b['pmkid']:
164         raise Exception("Unexpected PMKID change for AP1")
165
166 def test_pmksa_cache_opportunistic_connect(dev, apdev):
167     """Opportunistic PMKSA caching with connect API"""
168     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
169     params['okc'] = "1"
170     hostapd.add_ap(apdev[0]['ifname'], params)
171     bssid = apdev[0]['bssid']
172     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
173     wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
174     wpas.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
175                  eap="GPSK", identity="gpsk user",
176                  password="abcdefghijklmnop0123456789abcdef", okc=True,
177                  scan_freq="2412")
178     pmksa = wpas.get_pmksa(bssid)
179     if pmksa is None:
180         raise Exception("No PMKSA cache entry created")
181     if pmksa['opportunistic'] != '0':
182         raise Exception("Unexpected opportunistic PMKSA cache entry")
183
184     hostapd.add_ap(apdev[1]['ifname'], params)
185     bssid2 = apdev[1]['bssid']
186
187     wpas.dump_monitor()
188     logger.info("Roam to AP2")
189     wpas.scan(freq="2412")
190     wpas.request("ROAM " + bssid2)
191     ev = wpas.wait_event(["CTRL-EVENT-EAP-STARTED",
192                             "CTRL-EVENT-CONNECTED"], timeout=10)
193     if ev is None:
194         raise Exception("Roaming with the AP timed out")
195     if "CTRL-EVENT-EAP-STARTED" in ev:
196         raise Exception("Unexpected EAP exchange")
197     pmksa2 = wpas.get_pmksa(bssid2)
198     if pmksa2 is None:
199         raise Exception("No PMKSA cache entry created")
200
201     wpas.dump_monitor()
202     logger.info("Roam back to AP1")
203     wpas.scan(freq="2412")
204     wpas.request("ROAM " + bssid)
205     ev = wpas.wait_event(["CTRL-EVENT-EAP-STARTED",
206                             "CTRL-EVENT-CONNECTED"], timeout=10)
207     if ev is None:
208         raise Exception("Roaming with the AP timed out")
209     if "CTRL-EVENT-EAP-STARTED" in ev:
210         raise Exception("Unexpected EAP exchange")
211
212     pmksa1b = wpas.get_pmksa(bssid)
213     if pmksa1b is None:
214         raise Exception("No PMKSA cache entry found")
215     if pmksa['pmkid'] != pmksa1b['pmkid']:
216         raise Exception("Unexpected PMKID change for AP1")
217
218 def test_pmksa_cache_expiration(dev, apdev):
219     """PMKSA cache entry expiration"""
220     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
221     hostapd.add_ap(apdev[0]['ifname'], params)
222     bssid = apdev[0]['bssid']
223     dev[0].request("SET dot11RSNAConfigPMKLifetime 10")
224     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
225                    eap="GPSK", identity="gpsk user",
226                    password="abcdefghijklmnop0123456789abcdef",
227                    scan_freq="2412")
228     pmksa = dev[0].get_pmksa(bssid)
229     if pmksa is None:
230         raise Exception("No PMKSA cache entry created")
231     logger.info("Wait for PMKSA cache entry to expire")
232     ev = dev[0].wait_event(["WPA: Key negotiation completed",
233                             "CTRL-EVENT-DISCONNECTED"], timeout=15)
234     if ev is None:
235         raise Exception("No EAP reauthentication seen")
236     if "CTRL-EVENT-DISCONNECTED" in ev:
237         raise Exception("Unexpected disconnection")
238     pmksa2 = dev[0].get_pmksa(bssid)
239     if pmksa['pmkid'] == pmksa2['pmkid']:
240         raise Exception("PMKID did not change")
241
242 def test_pmksa_cache_expiration_disconnect(dev, apdev):
243     """PMKSA cache entry expiration (disconnect)"""
244     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
245     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
246     bssid = apdev[0]['bssid']
247     dev[0].request("SET dot11RSNAConfigPMKLifetime 2")
248     dev[0].request("SET dot11RSNAConfigPMKReauthThreshold 100")
249     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
250                    eap="GPSK", identity="gpsk user",
251                    password="abcdefghijklmnop0123456789abcdef",
252                    scan_freq="2412")
253     pmksa = dev[0].get_pmksa(bssid)
254     if pmksa is None:
255         raise Exception("No PMKSA cache entry created")
256     hapd.request("SET auth_server_shared_secret incorrect")
257     logger.info("Wait for PMKSA cache entry to expire")
258     ev = dev[0].wait_event(["WPA: Key negotiation completed",
259                             "CTRL-EVENT-DISCONNECTED"], timeout=15)
260     if ev is None:
261         raise Exception("No EAP reauthentication seen")
262     if "CTRL-EVENT-DISCONNECTED" not in ev:
263         raise Exception("Missing disconnection")
264     hapd.request("SET auth_server_shared_secret radius")
265     ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=15)
266     if ev is None:
267         raise Exception("No EAP reauthentication seen")
268     pmksa2 = dev[0].get_pmksa(bssid)
269     if pmksa['pmkid'] == pmksa2['pmkid']:
270         raise Exception("PMKID did not change")
271
272 def test_pmksa_cache_and_cui(dev, apdev):
273     """PMKSA cache and Chargeable-User-Identity"""
274     params = hostapd.wpa2_eap_params(ssid="cui")
275     params['radius_request_cui'] = '1'
276     params['acct_server_addr'] = "127.0.0.1"
277     params['acct_server_port'] = "1813"
278     params['acct_server_shared_secret'] = "radius"
279     hostapd.add_ap(apdev[0]['ifname'], params)
280     bssid = apdev[0]['bssid']
281     dev[0].connect("cui", proto="RSN", key_mgmt="WPA-EAP",
282                    eap="GPSK", identity="gpsk-cui",
283                    password="abcdefghijklmnop0123456789abcdef",
284                    scan_freq="2412")
285     pmksa = dev[0].get_pmksa(bssid)
286     if pmksa is None:
287         raise Exception("No PMKSA cache entry created")
288
289     dev[0].dump_monitor()
290     logger.info("Disconnect and reconnect to the same AP")
291     dev[0].request("DISCONNECT")
292     dev[0].request("RECONNECT")
293     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
294                             "CTRL-EVENT-CONNECTED"], timeout=10)
295     if ev is None:
296         raise Exception("Reconnect timed out")
297     if "CTRL-EVENT-EAP-STARTED" in ev:
298         raise Exception("Unexpected EAP exchange")
299     pmksa1b = dev[0].get_pmksa(bssid)
300     if pmksa1b is None:
301         raise Exception("No PMKSA cache entry found")
302     if pmksa['pmkid'] != pmksa1b['pmkid']:
303         raise Exception("Unexpected PMKID change for AP1")
304
305     dev[0].request("REAUTHENTICATE")
306     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
307     if ev is None:
308         raise Exception("EAP success timed out")
309     for i in range(0, 20):
310         state = dev[0].get_status_field("wpa_state")
311         if state == "COMPLETED":
312             break
313         time.sleep(0.1)
314     if state != "COMPLETED":
315         raise Exception("Reauthentication did not complete")
316
317 def test_pmksa_cache_preauth(dev, apdev):
318     """RSN pre-authentication to generate PMKSA cache entry"""
319     try:
320         params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
321         params['bridge'] = 'ap-br0'
322         hostapd.add_ap(apdev[0]['ifname'], params)
323         subprocess.call(['sudo', 'brctl', 'setfd', 'ap-br0', '0'])
324         subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
325         eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
326                     password_hex="0123456789abcdef0123456789abcdef")
327
328         params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
329         params['bridge'] = 'ap-br0'
330         params['rsn_preauth'] = '1'
331         params['rsn_preauth_interfaces'] = 'ap-br0'
332         hostapd.add_ap(apdev[1]['ifname'], params)
333         bssid1 = apdev[1]['bssid']
334         dev[0].scan(freq="2412")
335         success = False
336         status_seen = False
337         for i in range(0, 50):
338             if not status_seen:
339                 status = dev[0].request("STATUS")
340                 if "Pre-authentication EAPOL state machines:" in status:
341                     status_seen = True
342             time.sleep(0.1)
343             pmksa = dev[0].get_pmksa(bssid1)
344             if pmksa:
345                 success = True
346                 break
347         if not success:
348             raise Exception("No PMKSA cache entry created from pre-authentication")
349         if not status_seen:
350             raise Exception("Pre-authentication EAPOL status was not available")
351
352         dev[0].scan(freq="2412")
353         if "[WPA2-EAP-CCMP-preauth]" not in dev[0].request("SCAN_RESULTS"):
354             raise Exception("Scan results missing RSN element info")
355         dev[0].request("ROAM " + bssid1)
356         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
357                                 "CTRL-EVENT-CONNECTED"], timeout=10)
358         if ev is None:
359             raise Exception("Roaming with the AP timed out")
360         if "CTRL-EVENT-EAP-STARTED" in ev:
361             raise Exception("Unexpected EAP exchange")
362         pmksa2 = dev[0].get_pmksa(bssid1)
363         if pmksa2 is None:
364             raise Exception("No PMKSA cache entry")
365         if pmksa['pmkid'] != pmksa2['pmkid']:
366             raise Exception("Unexpected PMKID change")
367
368     finally:
369         subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
370         subprocess.call(['sudo', 'brctl', 'delbr', 'ap-br0'])