]> git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/test_ap_hs20.py
tests: Use only new scan results for Hotspot 2.0 test cases
[thirdparty/hostap.git] / tests / hwsim / test_ap_hs20.py
1 #!/usr/bin/python
2 #
3 # Hotspot 2.0 tests
4 # Copyright (c) 2013, Jouni Malinen <j@w1.fi>
5 #
6 # This software may be distributed under the terms of the BSD license.
7 # See README for more details.
8
9 import time
10 import subprocess
11 import logging
12 logger = logging.getLogger()
13 import os.path
14 import subprocess
15
16 import hostapd
17
18 def hs20_ap_params():
19 params = hostapd.wpa2_params(ssid="test-hs20")
20 params['wpa_key_mgmt'] = "WPA-EAP"
21 params['ieee80211w'] = "1"
22 params['ieee8021x'] = "1"
23 params['auth_server_addr'] = "127.0.0.1"
24 params['auth_server_port'] = "1812"
25 params['auth_server_shared_secret'] = "radius"
26 params['interworking'] = "1"
27 params['access_network_type'] = "14"
28 params['internet'] = "1"
29 params['asra'] = "0"
30 params['esr'] = "0"
31 params['uesa'] = "0"
32 params['venue_group'] = "7"
33 params['venue_type'] = "1"
34 params['venue_name'] = [ "eng:Example venue", "fin:Esimerkkipaikka" ]
35 params['roaming_consortium'] = [ "112233", "1020304050", "010203040506",
36 "fedcba" ]
37 params['domain_name'] = "example.com,another.example.com"
38 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
39 "0,another.example.com" ]
40 params['hs20'] = "1"
41 params['hs20_wan_metrics'] = "01:8000:1000:80:240:3000"
42 params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0" ]
43 params['hs20_operating_class'] = "5173"
44 params['anqp_3gpp_cell_net'] = "244,91"
45 return params
46
47 def interworking_select(dev, bssid, type=None, no_match=False):
48 dev.dump_monitor()
49 dev.request("INTERWORKING_SELECT")
50 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
51 timeout=15)
52 if ev is None:
53 raise Exception("Network selection timed out");
54 if no_match:
55 if "INTERWORKING-NO-MATCH" not in ev:
56 raise Exception("Unexpected network match")
57 return
58 if "INTERWORKING-NO-MATCH" in ev:
59 raise Exception("Matching network not found")
60 if bssid not in ev:
61 raise Exception("Unexpected BSSID in match")
62 if type and "type=" + type not in ev:
63 raise Exception("Network type not recognized correctly")
64
65 def check_sp_type(dev, sp_type):
66 type = dev.get_status_field("sp_type")
67 if type is None:
68 raise Exception("sp_type not available")
69 if type != sp_type:
70 raise Exception("sp_type did not indicate home network")
71
72 def hlr_auc_gw_available():
73 if not os.path.exists("/tmp/hlr_auc_gw.sock"):
74 logger.info("No hlr_auc_gw available");
75 return False
76 if not os.path.exists("../../hostapd/hlr_auc_gw"):
77 logger.info("No hlr_auc_gw available");
78 return False
79 return True
80
81 def interworking_ext_sim_connect(dev, bssid, method):
82 dev.request("INTERWORKING_CONNECT " + bssid)
83
84 ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
85 if ev is None:
86 raise Exception("Network connected timed out")
87 if "(" + method + ")" not in ev:
88 raise Exception("Unexpected EAP method selection")
89
90 ev = dev.wait_event(["CTRL-REQ-SIM"], timeout=15)
91 if ev is None:
92 raise Exception("Wait for external SIM processing request timed out")
93 p = ev.split(':', 2)
94 if p[1] != "GSM-AUTH":
95 raise Exception("Unexpected CTRL-REQ-SIM type")
96 id = p[0].split('-')[3]
97 rand = p[2].split(' ')[0]
98
99 res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
100 "-m",
101 "auth_serv/hlr_auc_gw.milenage_db",
102 "GSM-AUTH-REQ 232010000000000 " + rand])
103 if "GSM-AUTH-RESP" not in res:
104 raise Exception("Unexpected hlr_auc_gw response")
105 resp = res.split(' ')[2].rstrip()
106
107 dev.request("CTRL-RSP-SIM-" + id + ":GSM-AUTH:" + resp)
108 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
109 if ev is None:
110 raise Exception("Connection timed out")
111
112 def interworking_connect(dev, bssid, method):
113 dev.request("INTERWORKING_CONNECT " + bssid)
114
115 ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
116 if ev is None:
117 raise Exception("Network connected timed out")
118 if "(" + method + ")" not in ev:
119 raise Exception("Unexpected EAP method selection")
120
121 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
122 if ev is None:
123 raise Exception("Connection timed out")
124
125 def test_ap_hs20_select(dev, apdev):
126 """Hotspot 2.0 network selection"""
127 bssid = apdev[0]['bssid']
128 params = hs20_ap_params()
129 params['hessid'] = bssid
130 hostapd.add_ap(apdev[0]['ifname'], params)
131
132 dev[0].request("SET ignore_old_scan_res 1")
133 dev[0].hs20_enable()
134 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
135 'password': "secret",
136 'domain': "example.com" })
137 interworking_select(dev[0], bssid, "home")
138
139 dev[0].remove_cred(id)
140 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
141 'password': "secret",
142 'domain': "no.match.example.com" })
143 interworking_select(dev[0], bssid, "roaming")
144
145 dev[0].set_cred_quoted(id, "realm", "no.match.example.com");
146 interworking_select(dev[0], bssid, no_match=True)
147
148 def test_ap_hs20_ext_sim(dev, apdev):
149 """Hotspot 2.0 with external SIM processing"""
150 if not hlr_auc_gw_available():
151 return "skip"
152 bssid = apdev[0]['bssid']
153 params = hs20_ap_params()
154 params['hessid'] = bssid
155 params['anqp_3gpp_cell_net'] = "232,01"
156 params['domain_name'] = "wlan.mnc001.mcc232.3gppnetwork.org"
157 hostapd.add_ap(apdev[0]['ifname'], params)
158
159 dev[0].request("SET ignore_old_scan_res 1")
160 dev[0].hs20_enable()
161 dev[0].request("SET external_sim 1")
162 dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
163 interworking_select(dev[0], "home")
164 interworking_ext_sim_connect(dev[0], bssid, "SIM")
165 check_sp_type(dev[0], "home")
166
167 def test_ap_hs20_ext_sim_roaming(dev, apdev):
168 """Hotspot 2.0 with external SIM processing in roaming network"""
169 if not hlr_auc_gw_available():
170 return "skip"
171 bssid = apdev[0]['bssid']
172 params = hs20_ap_params()
173 params['hessid'] = bssid
174 params['anqp_3gpp_cell_net'] = "244,91;310,026;232,01;234,56"
175 params['domain_name'] = "wlan.mnc091.mcc244.3gppnetwork.org"
176 hostapd.add_ap(apdev[0]['ifname'], params)
177
178 dev[0].request("SET ignore_old_scan_res 1")
179 dev[0].hs20_enable()
180 dev[0].request("SET external_sim 1")
181 dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
182 interworking_select(dev[0], "roaming")
183 interworking_ext_sim_connect(dev[0], bssid, "SIM")
184 check_sp_type(dev[0], "roaming")
185
186 def test_ap_hs20_username(dev, apdev):
187 """Hotspot 2.0 connection in username/password credential"""
188 bssid = apdev[0]['bssid']
189 params = hs20_ap_params()
190 params['hessid'] = bssid
191 hostapd.add_ap(apdev[0]['ifname'], params)
192
193 dev[0].request("SET ignore_old_scan_res 1")
194 dev[0].hs20_enable()
195 id = dev[0].add_cred_values({ 'realm': "example.com",
196 'username': "hs20-test",
197 'password': "password",
198 'domain': "example.com" })
199 interworking_select(dev[0], bssid, "home")
200 interworking_connect(dev[0], bssid, "TTLS")
201 check_sp_type(dev[0], "home")
202
203 def test_ap_hs20_username_roaming(dev, apdev):
204 """Hotspot 2.0 connection in username/password credential (roaming)"""
205 bssid = apdev[0]['bssid']
206 params = hs20_ap_params()
207 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
208 "0,roaming.example.com,21[2:4][5:7]",
209 "0,another.example.com" ]
210 params['domain_name'] = "another.example.com"
211 params['hessid'] = bssid
212 hostapd.add_ap(apdev[0]['ifname'], params)
213
214 dev[0].request("SET ignore_old_scan_res 1")
215 dev[0].hs20_enable()
216 id = dev[0].add_cred_values({ 'realm': "roaming.example.com",
217 'username': "hs20-test",
218 'password': "password",
219 'domain': "example.com" })
220 interworking_select(dev[0], bssid, "roaming")
221 interworking_connect(dev[0], bssid, "TTLS")
222 check_sp_type(dev[0], "roaming")
223
224 def test_ap_hs20_username_unknown(dev, apdev):
225 """Hotspot 2.0 connection in username/password credential (no domain in cred)"""
226 bssid = apdev[0]['bssid']
227 params = hs20_ap_params()
228 params['hessid'] = bssid
229 hostapd.add_ap(apdev[0]['ifname'], params)
230
231 dev[0].request("SET ignore_old_scan_res 1")
232 dev[0].hs20_enable()
233 id = dev[0].add_cred_values({ 'realm': "example.com",
234 'username': "hs20-test",
235 'password': "password" })
236 interworking_select(dev[0], bssid, "unknown")
237 interworking_connect(dev[0], bssid, "TTLS")
238 check_sp_type(dev[0], "unknown")
239
240 def test_ap_hs20_username_unknown2(dev, apdev):
241 """Hotspot 2.0 connection in username/password credential (no domain advertized)"""
242 bssid = apdev[0]['bssid']
243 params = hs20_ap_params()
244 params['hessid'] = bssid
245 del params['domain_name']
246 hostapd.add_ap(apdev[0]['ifname'], params)
247
248 dev[0].request("SET ignore_old_scan_res 1")
249 dev[0].hs20_enable()
250 id = dev[0].add_cred_values({ 'realm': "example.com",
251 'username': "hs20-test",
252 'password': "password",
253 'domain': "example.com" })
254 interworking_select(dev[0], bssid, "unknown")
255 interworking_connect(dev[0], bssid, "TTLS")
256 check_sp_type(dev[0], "unknown")
257
258 def test_ap_hs20_multiple_connects(dev, apdev):
259 """Hotspot 2.0 connection through multiple network selections"""
260 bssid = apdev[0]['bssid']
261 params = hs20_ap_params()
262 params['hessid'] = bssid
263 hostapd.add_ap(apdev[0]['ifname'], params)
264
265 dev[0].request("SET ignore_old_scan_res 1")
266 dev[0].hs20_enable()
267 values = { 'realm': "example.com",
268 'username': "hs20-test",
269 'password': "password",
270 'domain': "example.com" }
271 id = dev[0].add_cred_values(values)
272
273 for i in range(0, 3):
274 logger.info("Starting Interworking network selection")
275 dev[0].request("INTERWORKING_SELECT auto")
276 while True:
277 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH",
278 "INTERWORKING-ALREADY-CONNECTED",
279 "CTRL-EVENT-CONNECTED"], timeout=15)
280 if ev is None:
281 raise Exception("Connection timed out")
282 if "INTERWORKING-NO-MATCH" in ev:
283 raise Exception("Matching AP not found")
284 if "CTRL-EVENT-CONNECTED" in ev:
285 break
286 if i == 2 and "INTERWORKING-ALREADY-CONNECTED" in ev:
287 break
288 if i == 0:
289 dev[0].request("DISCONNECT")
290 dev[0].dump_monitor()
291
292 networks = dev[0].list_networks()
293 if len(networks) > 1:
294 raise Exception("Duplicated network block detected")
295
296 def test_ap_hs20_disallow_aps(dev, apdev):
297 """Hotspot 2.0 connection and disallow_aps"""
298 bssid = apdev[0]['bssid']
299 params = hs20_ap_params()
300 params['hessid'] = bssid
301 hostapd.add_ap(apdev[0]['ifname'], params)
302
303 dev[0].request("SET ignore_old_scan_res 1")
304 dev[0].hs20_enable()
305 values = { 'realm': "example.com",
306 'username': "hs20-test",
307 'password': "password",
308 'domain': "example.com" }
309 id = dev[0].add_cred_values(values)
310
311 logger.info("Verify disallow_aps bssid")
312 dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':'))
313 dev[0].request("INTERWORKING_SELECT auto")
314 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
315 if ev is None:
316 raise Exception("Network selection timed out")
317 dev[0].dump_monitor()
318
319 logger.info("Verify disallow_aps ssid")
320 dev[0].request("SET disallow_aps ssid 746573742d68733230")
321 dev[0].request("INTERWORKING_SELECT auto")
322 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
323 if ev is None:
324 raise Exception("Network selection timed out")
325 dev[0].dump_monitor()
326
327 logger.info("Verify disallow_aps clear")
328 dev[0].request("SET disallow_aps ")
329 interworking_select(dev[0], bssid, "home")
330
331 dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':'))
332 ret = dev[0].request("INTERWORKING_CONNECT " + bssid)
333 if "FAIL" not in ret:
334 raise Exception("INTERWORKING_CONNECT to disallowed BSS not rejected")
335
336 def policy_test(dev, ap, values, only_one=True):
337 dev.dump_monitor()
338 logger.info("Verify network selection to AP " + ap['ifname'])
339 bssid = ap['bssid']
340 dev.request("SET ignore_old_scan_res 1")
341 dev.hs20_enable()
342 id = dev.add_cred_values(values)
343 dev.request("INTERWORKING_SELECT auto")
344 while True:
345 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH",
346 "CTRL-EVENT-CONNECTED"], timeout=15)
347 if ev is None:
348 raise Exception("Connection timed out")
349 if "INTERWORKING-NO-MATCH" in ev:
350 raise Exception("Matching AP not found")
351 if only_one and "INTERWORKING-AP" in ev and bssid not in ev:
352 raise Exception("Unexpected AP claimed acceptable")
353 if "CTRL-EVENT-CONNECTED" in ev:
354 if bssid not in ev:
355 raise Exception("Connected to incorrect BSS")
356 break
357
358 conn_bssid = dev.get_status_field("bssid")
359 if conn_bssid != bssid:
360 raise Exception("bssid information points to incorrect BSS")
361
362 dev.remove_cred(id)
363 dev.dump_monitor()
364
365 def default_cred():
366 return { 'realm': "example.com",
367 'username': "hs20-test",
368 'password': "password" }
369
370 def test_ap_hs20_req_roaming_consortium(dev, apdev):
371 """Hotspot 2.0 required roaming consortium"""
372 params = hs20_ap_params()
373 hostapd.add_ap(apdev[0]['ifname'], params)
374
375 params = hs20_ap_params()
376 params['ssid'] = "test-hs20-other"
377 params['roaming_consortium'] = [ "223344" ]
378 hostapd.add_ap(apdev[1]['ifname'], params)
379
380 values = default_cred()
381 values['required_roaming_consortium'] = "223344"
382 policy_test(dev[0], apdev[1], values)
383 values['required_roaming_consortium'] = "112233"
384 policy_test(dev[0], apdev[0], values)
385
386 def test_ap_hs20_excluded_ssid(dev, apdev):
387 """Hotspot 2.0 exclusion based on SSID"""
388 params = hs20_ap_params()
389 hostapd.add_ap(apdev[0]['ifname'], params)
390
391 params = hs20_ap_params()
392 params['ssid'] = "test-hs20-other"
393 params['roaming_consortium'] = [ "223344" ]
394 hostapd.add_ap(apdev[1]['ifname'], params)
395
396 values = default_cred()
397 values['excluded_ssid'] = "test-hs20"
398 policy_test(dev[0], apdev[1], values)
399 values['excluded_ssid'] = "test-hs20-other"
400 policy_test(dev[0], apdev[0], values)