tests: RSN pre-authentication
[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 test_ap_eap import eap_connect
14
15 def test_pmksa_cache_on_roam_back(dev, apdev):
16     """PMKSA cache to skip EAP on reassociation back to same AP"""
17     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
18     hostapd.add_ap(apdev[0]['ifname'], params)
19     bssid = apdev[0]['bssid']
20     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
21                    eap="GPSK", identity="gpsk user",
22                    password="abcdefghijklmnop0123456789abcdef",
23                    scan_freq="2412")
24     pmksa = dev[0].get_pmksa(bssid)
25     if pmksa is None:
26         raise Exception("No PMKSA cache entry created")
27     if pmksa['opportunistic'] != '0':
28         raise Exception("Unexpected opportunistic PMKSA cache entry")
29
30     hostapd.add_ap(apdev[1]['ifname'], params)
31     bssid2 = apdev[1]['bssid']
32
33     dev[0].dump_monitor()
34     logger.info("Roam to AP2")
35     dev[0].scan(freq="2412")
36     dev[0].request("ROAM " + bssid2)
37     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
38     if ev is None:
39         raise Exception("EAP success timed out")
40     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
41     if ev is None:
42         raise Exception("Roaming with the AP timed out")
43     pmksa2 = dev[0].get_pmksa(bssid2)
44     if pmksa2 is None:
45         raise Exception("No PMKSA cache entry found")
46     if pmksa2['opportunistic'] != '0':
47         raise Exception("Unexpected opportunistic PMKSA cache entry")
48
49     dev[0].dump_monitor()
50     logger.info("Roam back to AP1")
51     dev[0].scan(freq="2412")
52     dev[0].request("ROAM " + bssid)
53     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
54                             "CTRL-EVENT-CONNECTED"], timeout=10)
55     if ev is None:
56         raise Exception("Roaming with the AP timed out")
57     if "CTRL-EVENT-EAP-STARTED" in ev:
58         raise Exception("Unexpected EAP exchange")
59     pmksa1b = dev[0].get_pmksa(bssid)
60     if pmksa1b is None:
61         raise Exception("No PMKSA cache entry found")
62     if pmksa['pmkid'] != pmksa1b['pmkid']:
63         raise Exception("Unexpected PMKID change for AP1")
64
65 def test_pmksa_cache_opportunistic_only_on_sta(dev, apdev):
66     """Opportunistic PMKSA caching enabled only on station"""
67     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
68     hostapd.add_ap(apdev[0]['ifname'], params)
69     bssid = apdev[0]['bssid']
70     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
71                    eap="GPSK", identity="gpsk user",
72                    password="abcdefghijklmnop0123456789abcdef", okc=True,
73                    scan_freq="2412")
74     pmksa = dev[0].get_pmksa(bssid)
75     if pmksa is None:
76         raise Exception("No PMKSA cache entry created")
77     if pmksa['opportunistic'] != '0':
78         raise Exception("Unexpected opportunistic PMKSA cache entry")
79
80     hostapd.add_ap(apdev[1]['ifname'], params)
81     bssid2 = apdev[1]['bssid']
82
83     dev[0].dump_monitor()
84     logger.info("Roam to AP2")
85     dev[0].scan(freq="2412")
86     dev[0].request("ROAM " + bssid2)
87     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
88     if ev is None:
89         raise Exception("EAP success timed out")
90     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
91     if ev is None:
92         raise Exception("Roaming with the AP timed out")
93     pmksa2 = dev[0].get_pmksa(bssid2)
94     if pmksa2 is None:
95         raise Exception("No PMKSA cache entry found")
96     if pmksa2['opportunistic'] != '0':
97         raise Exception("Unexpected opportunistic PMKSA cache entry")
98
99     dev[0].dump_monitor()
100     logger.info("Roam back to AP1")
101     dev[0].scan(freq="2412")
102     dev[0].request("ROAM " + bssid)
103     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
104                             "CTRL-EVENT-CONNECTED"], timeout=10)
105     if ev is None:
106         raise Exception("Roaming with the AP timed out")
107     if "CTRL-EVENT-EAP-STARTED" in ev:
108         raise Exception("Unexpected EAP exchange")
109     pmksa1b = dev[0].get_pmksa(bssid)
110     if pmksa1b is None:
111         raise Exception("No PMKSA cache entry found")
112     if pmksa['pmkid'] != pmksa1b['pmkid']:
113         raise Exception("Unexpected PMKID change for AP1")
114
115 def test_pmksa_cache_opportunistic(dev, apdev):
116     """Opportunistic PMKSA caching"""
117     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
118     params['okc'] = "1"
119     hostapd.add_ap(apdev[0]['ifname'], params)
120     bssid = apdev[0]['bssid']
121     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
122                    eap="GPSK", identity="gpsk user",
123                    password="abcdefghijklmnop0123456789abcdef", okc=True,
124                    scan_freq="2412")
125     pmksa = dev[0].get_pmksa(bssid)
126     if pmksa is None:
127         raise Exception("No PMKSA cache entry created")
128     if pmksa['opportunistic'] != '0':
129         raise Exception("Unexpected opportunistic PMKSA cache entry")
130
131     hostapd.add_ap(apdev[1]['ifname'], params)
132     bssid2 = apdev[1]['bssid']
133
134     dev[0].dump_monitor()
135     logger.info("Roam to AP2")
136     dev[0].scan(freq="2412")
137     dev[0].request("ROAM " + bssid2)
138     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
139                             "CTRL-EVENT-CONNECTED"], timeout=10)
140     if ev is None:
141         raise Exception("Roaming with the AP timed out")
142     if "CTRL-EVENT-EAP-STARTED" in ev:
143         raise Exception("Unexpected EAP exchange")
144     pmksa2 = dev[0].get_pmksa(bssid2)
145     if pmksa2 is None:
146         raise Exception("No PMKSA cache entry created")
147
148     dev[0].dump_monitor()
149     logger.info("Roam back to AP1")
150     dev[0].scan(freq="2412")
151     dev[0].request("ROAM " + bssid)
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
159     pmksa1b = dev[0].get_pmksa(bssid)
160     if pmksa1b is None:
161         raise Exception("No PMKSA cache entry found")
162     if pmksa['pmkid'] != pmksa1b['pmkid']:
163         raise Exception("Unexpected PMKID change for AP1")
164
165 def test_pmksa_cache_expiration(dev, apdev):
166     """PMKSA cache entry expiration"""
167     params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
168     hostapd.add_ap(apdev[0]['ifname'], params)
169     bssid = apdev[0]['bssid']
170     dev[0].request("SET dot11RSNAConfigPMKLifetime 10")
171     dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
172                    eap="GPSK", identity="gpsk user",
173                    password="abcdefghijklmnop0123456789abcdef",
174                    scan_freq="2412")
175     pmksa = dev[0].get_pmksa(bssid)
176     if pmksa is None:
177         raise Exception("No PMKSA cache entry created")
178     logger.info("Wait for PMKSA cache entry to expire")
179     ev = dev[0].wait_event(["WPA: Key negotiation completed",
180                             "CTRL-EVENT-DISCONNECTED"], timeout=15)
181     if ev is None:
182         raise Exception("No EAP reauthentication seen")
183     if "CTRL-EVENT-DISCONNECTED" in ev:
184         raise Exception("Unexpected disconnection")
185     pmksa2 = dev[0].get_pmksa(bssid)
186     if pmksa['pmkid'] == pmksa2['pmkid']:
187         raise Exception("PMKID did not change")
188
189 def test_pmksa_cache_and_cui(dev, apdev):
190     """PMKSA cache and Chargeable-User-Identity"""
191     params = hostapd.wpa2_eap_params(ssid="cui")
192     params['radius_request_cui'] = '1'
193     params['acct_server_addr'] = "127.0.0.1"
194     params['acct_server_port'] = "1813"
195     params['acct_server_shared_secret'] = "radius"
196     hostapd.add_ap(apdev[0]['ifname'], params)
197     bssid = apdev[0]['bssid']
198     dev[0].connect("cui", proto="RSN", key_mgmt="WPA-EAP",
199                    eap="GPSK", identity="gpsk-cui",
200                    password="abcdefghijklmnop0123456789abcdef",
201                    scan_freq="2412")
202     pmksa = dev[0].get_pmksa(bssid)
203     if pmksa is None:
204         raise Exception("No PMKSA cache entry created")
205
206     dev[0].dump_monitor()
207     logger.info("Disconnect and reconnect to the same AP")
208     dev[0].request("DISCONNECT")
209     dev[0].request("RECONNECT")
210     ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
211                             "CTRL-EVENT-CONNECTED"], timeout=10)
212     if ev is None:
213         raise Exception("Reconnect timed out")
214     if "CTRL-EVENT-EAP-STARTED" in ev:
215         raise Exception("Unexpected EAP exchange")
216     pmksa1b = dev[0].get_pmksa(bssid)
217     if pmksa1b is None:
218         raise Exception("No PMKSA cache entry found")
219     if pmksa['pmkid'] != pmksa1b['pmkid']:
220         raise Exception("Unexpected PMKID change for AP1")
221
222     dev[0].request("REAUTHENTICATE")
223     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
224     if ev is None:
225         raise Exception("EAP success timed out")
226     for i in range(0, 20):
227         state = dev[0].get_status_field("wpa_state")
228         if state == "COMPLETED":
229             break
230         time.sleep(0.1)
231     if state != "COMPLETED":
232         raise Exception("Reauthentication did not complete")
233
234 def test_pmksa_cache_preauth(dev, apdev):
235     """RSN pre-authentication to generate PMKSA cache entry"""
236     try:
237         params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
238         params['bridge'] = 'ap-br0'
239         hostapd.add_ap(apdev[0]['ifname'], params)
240         subprocess.call(['sudo', 'brctl', 'setfd', 'ap-br0', '0'])
241         subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
242         eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
243                     password_hex="0123456789abcdef0123456789abcdef")
244
245         params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
246         params['bridge'] = 'ap-br0'
247         params['rsn_preauth'] = '1'
248         params['rsn_preauth_interfaces'] = 'ap-br0'
249         hostapd.add_ap(apdev[1]['ifname'], params)
250         bssid1 = apdev[1]['bssid']
251         dev[0].scan(freq="2412")
252         success = False
253         for i in range(0, 50):
254             time.sleep(0.1)
255             pmksa = dev[0].get_pmksa(bssid1)
256             if pmksa:
257                 success = True
258                 break
259         if not success:
260             raise Exception("No PMKSA cache entry created from pre-authentication")
261
262         dev[0].scan(freq="2412")
263         dev[0].request("ROAM " + bssid1)
264         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
265                                 "CTRL-EVENT-CONNECTED"], timeout=10)
266         if ev is None:
267             raise Exception("Roaming with the AP timed out")
268         if "CTRL-EVENT-EAP-STARTED" in ev:
269             raise Exception("Unexpected EAP exchange")
270         pmksa2 = dev[0].get_pmksa(bssid1)
271         if pmksa2 is None:
272             raise Exception("No PMKSA cache entry")
273         if pmksa['pmkid'] != pmksa2['pmkid']:
274             raise Exception("Unexpected PMKID change")
275
276     finally:
277         subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
278         subprocess.call(['sudo', 'brctl', 'delbr', 'ap-br0'])